simplerexx updated:
[AROS.git] / rom / exec / exec_util.c
blob31370c6acb1f654dee1d7e23355b5fa0833e8557
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Exec utility functions.
6 Lang: english
7 */
9 #include <aros/debug.h>
10 #include <exec/lists.h>
11 #include <exec/tasks.h>
12 #include <exec/memory.h>
13 #include <exec/execbase.h>
14 #include <dos/dosextens.h>
16 #include <proto/exec.h>
18 #include "etask.h"
19 #include "exec_intern.h"
20 #include "exec_util.h"
21 #include "taskstorage.h"
23 /*i***************************************************************************
25 NAME */
26 #include "exec_util.h"
28 struct ETask * Exec_FindChild(
30 /* SYNOPSIS */
31 ULONG id,
32 struct ExecBase *SysBase)
34 /* FUNCTION
35 Scan through the current tasks children list searching for the task
36 whose et_UniqueID field matches.
38 INPUTS
39 id - The task ID to match.
41 RESULT
42 Address of the ETask structure that matches, or
43 NULL otherwise.
45 NOTES
46 This is an internal exec.library function not exported from the
47 library.
49 EXAMPLE
51 BUGS
53 SEE ALSO
55 INTERNALS
57 ******************************************************************************/
59 struct ETask *et;
60 struct ETask *thisET;
62 thisET = GetETask(FindTask(NULL));
63 if (thisET != NULL)
65 ForeachNode (&thisET->et_Children, et)
67 if (et->et_UniqueID == id)
68 return et;
70 ForeachNode(&thisET->et_TaskMsgPort.mp_MsgList, et)
72 if (et->et_UniqueID == id)
73 return et;
76 return NULL;
79 BOOL
80 Exec_InitETask(struct Task *task, struct ExecBase *SysBase)
82 struct Task *thistask = FindTask(NULL);
84 * We don't add this to the task memory, it isn't free'd by
85 * RemTask(), rather by somebody else calling ChildFree().
86 * Alternatively, an orphaned task will free its own ETask.
88 struct ETask *et =
89 AllocMem(sizeof(struct IntETask), MEMF_PUBLIC | MEMF_CLEAR);
90 D(bug("[TSS] Create new ETask=%p for task=%p with size %d\n",
91 et, task, sizeof(struct IntETask)));
93 task->tc_UnionETask.tc_ETask = et;
94 if (!et)
95 return FALSE;
96 task->tc_Flags |= TF_ETASK;
98 et->et_Parent = thistask;
99 NEWLIST(&et->et_Children);
101 /* Initialise the message list */
102 InitMsgPort(&et->et_TaskMsgPort);
103 et->et_TaskMsgPort.mp_SigTask = task;
104 et->et_TaskMsgPort.mp_SigBit = SIGB_CHILD;
106 /* Initialise the trap fields */
107 et->et_TrapAlloc = SysBase->TaskTrapAlloc;
108 et->et_TrapAble = 0;
110 #ifdef DEBUG_ETASK
112 int len = strlen(task->tc_Node.ln_Name) + 1;
113 IntETask(et)->iet_Me = AllocVec(len, MEMF_CLEAR|MEMF_PUBLIC);
114 if (IntETask(et)->iet_Me != NULL)
115 CopyMem(task->tc_Node.ln_Name, IntETask(et)->iet_Me, len);
117 #endif
119 /* Get a unique identifier for this task */
120 Forbid();
121 while(et->et_UniqueID == 0)
124 * Add some fuzz on wrapping. It's likely that the early numbers
125 * where taken by somebody else.
127 if(++SysBase->ex_TaskID == 0)
128 SysBase->ex_TaskID = 1024;
130 Disable();
131 if (FindTaskByPID(SysBase->ex_TaskID) == NULL)
132 et->et_UniqueID = SysBase->ex_TaskID;
133 Enable();
135 Permit();
137 /* Finally if the parent task is an ETask, add myself as its child */
138 if(et->et_Parent && ((struct Task*) et->et_Parent)->tc_Flags & TF_ETASK)
140 Forbid();
141 ADDHEAD(&GetETask(et->et_Parent)->et_Children, et);
142 Permit();
145 return TRUE;
148 void
149 Exec_CleanupETask(struct Task *task, struct ExecBase *SysBase)
151 struct ETask *et = NULL, *child, *nextchild, *parent;
152 struct Node *tmpNode;
153 BOOL expunge = TRUE;
155 if(task->tc_Flags & TF_ETASK)
156 et = task->tc_UnionETask.tc_ETask;
157 if(!et)
158 return;
160 D(bug("CleanupETask: task=%x, et=%x\n", task, et));
162 Forbid();
164 /* Clean up after all the children that the task didn't do itself. */
165 ForeachNodeSafe(&et->et_TaskMsgPort.mp_MsgList, child, tmpNode)
167 ExpungeETask(child);
170 /* If we have an ETask parent, tell it we have exited. */
171 if(et->et_Parent != NULL)
173 parent = GetETask(et->et_Parent);
175 /* Link children to our parent. */
176 ForeachNodeSafe(&et->et_Children, child, nextchild)
178 child->et_Parent = et->et_Parent;
179 //Forbid();
180 if (parent)
181 ADDTAIL(&parent->et_Children, child);
182 //Permit();
185 /* Notify parent only if child was created with NP_NotifyOnDeath set
186 to TRUE */
187 if(parent != NULL)
189 REMOVE(et);
192 (((struct Task *)task)->tc_Node.ln_Type == NT_PROCESS) &&
193 (((struct Process*) task)->pr_Flags & PRF_NOTIFYONDEATH)
196 PutMsg(&parent->et_TaskMsgPort, (struct Message *)et);
197 expunge = FALSE;
201 else
203 /* Orphan all our remaining children. */
204 ForeachNode(&et->et_Children, child)
205 child->et_Parent = NULL;
208 if(expunge)
209 ExpungeETask(et);
211 Permit();
214 void
215 Exec_ExpungeETask(struct ETask *et, struct ExecBase *SysBase)
217 IPTR *ts = et->et_TaskStorage;
219 FreeVec(et->et_Result2);
221 #ifdef DEBUG_ETASK
222 FreeVec(IntETask(et)->iet_Me);
223 #endif
224 D(bug("Exec_ExpungeETask: Freeing et=%x, ts=%x, size=%d\n",
225 et, ts, ts ? (ULONG)ts[__TS_FIRSTSLOT] : 0
227 FreeMem(et, sizeof(struct IntETask));
228 if (ts)
229 FreeMem(ts, ts[__TS_FIRSTSLOT] * sizeof(ts[0]));
232 BOOL Exec_CheckTask(struct Task *task, struct ExecBase *SysBase)
234 struct Task *t;
236 if (!task)
237 return FALSE;
239 Forbid();
241 if (task == SysBase->ThisTask)
243 Permit();
244 return TRUE;
247 ForeachNode(&SysBase->TaskReady, t)
249 if (task == t)
251 Permit();
252 return TRUE;
256 ForeachNode(&SysBase->TaskWait, t)
258 if (task == t)
260 Permit();
261 return TRUE;
265 Permit();
266 return FALSE;