Cancel redefinition of DOSBase for the 'cdrom' test utility. Now the
[AROS.git] / rom / exec / exec_util.c
blob576a11ce5bad89f856924f962d133be7bd51624c
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 if (thistask != NULL)
100 /* Clone parent's TaskStorage */
101 struct ETask *thiset = GetETask(thistask);
102 if (thiset) {
103 IPTR *thists = thiset->et_TaskStorage;
105 if (thists) {
106 IPTR *ts = AllocMem(thists[__TS_FIRSTSLOT] * sizeof(thists[0]), MEMF_ANY);
107 if (!ts) {
108 FreeMem(et, sizeof(struct IntETask));
109 return FALSE;
111 CopyMem(thists, ts, thists[__TS_FIRSTSLOT] * sizeof(thists[0]));
112 et->et_TaskStorage = ts;
117 et->et_Parent = thistask;
118 NEWLIST(&et->et_Children);
120 /* Initialise the message list */
121 InitMsgPort(&et->et_TaskMsgPort);
122 et->et_TaskMsgPort.mp_SigTask = task;
123 et->et_TaskMsgPort.mp_SigBit = SIGB_CHILD;
125 /* Initialise the trap fields */
126 et->et_TrapAlloc = SysBase->TaskTrapAlloc;
127 et->et_TrapAble = 0;
129 #ifdef DEBUG_ETASK
131 int len = strlen(task->tc_Node.ln_Name) + 1;
132 IntETask(et)->iet_Me = AllocVec(len, MEMF_CLEAR|MEMF_PUBLIC);
133 if (IntETask(et)->iet_Me != NULL)
134 CopyMem(task->tc_Node.ln_Name, IntETask(et)->iet_Me, len);
136 #endif
138 /* Get a unique identifier for this task */
139 Forbid();
140 while(et->et_UniqueID == 0)
143 * Add some fuzz on wrapping. It's likely that the early numbers
144 * where taken by somebody else.
146 if(++SysBase->ex_TaskID == 0)
147 SysBase->ex_TaskID = 1024;
149 Disable();
150 if (FindTaskByPID(SysBase->ex_TaskID) == NULL)
151 et->et_UniqueID = SysBase->ex_TaskID;
152 Enable();
154 Permit();
156 /* Finally if the parent task is an ETask, add myself as its child */
157 if(et->et_Parent && ((struct Task*) et->et_Parent)->tc_Flags & TF_ETASK)
159 Forbid();
160 ADDHEAD(&GetETask(et->et_Parent)->et_Children, et);
161 Permit();
164 return TRUE;
167 void
168 Exec_CleanupETask(struct Task *task, struct ExecBase *SysBase)
170 struct ETask *et = NULL, *child, *nextchild, *parent;
171 struct Node *tmpNode;
172 BOOL expunge = TRUE;
174 if(task->tc_Flags & TF_ETASK)
175 et = task->tc_UnionETask.tc_ETask;
176 if(!et)
177 return;
179 D(bug("CleanupETask: task=%x, et=%x\n", task, et));
181 Forbid();
183 /* Clean up after all the children that the task didn't do itself. */
184 ForeachNodeSafe(&et->et_TaskMsgPort.mp_MsgList, child, tmpNode)
186 ExpungeETask(child);
189 /* If we have an ETask parent, tell it we have exited. */
190 if(et->et_Parent != NULL)
192 parent = GetETask(et->et_Parent);
194 /* Link children to our parent. */
195 ForeachNodeSafe(&et->et_Children, child, nextchild)
197 child->et_Parent = et->et_Parent;
198 //Forbid();
199 if (parent)
200 ADDTAIL(&parent->et_Children, child);
201 //Permit();
204 /* Notify parent only if child was created with NP_NotifyOnDeath set
205 to TRUE */
206 if(parent != NULL)
208 REMOVE(et);
211 (((struct Task *)task)->tc_Node.ln_Type == NT_PROCESS) &&
212 (((struct Process*) task)->pr_Flags & PRF_NOTIFYONDEATH)
215 PutMsg(&parent->et_TaskMsgPort, (struct Message *)et);
216 expunge = FALSE;
220 else
222 /* Orphan all our remaining children. */
223 ForeachNode(&et->et_Children, child)
224 child->et_Parent = NULL;
227 if(expunge)
228 ExpungeETask(et);
230 Permit();
233 void
234 Exec_ExpungeETask(struct ETask *et, struct ExecBase *SysBase)
236 IPTR *ts = et->et_TaskStorage;
238 FreeVec(et->et_Result2);
240 #ifdef DEBUG_ETASK
241 FreeVec(IntETask(et)->iet_Me);
242 #endif
243 D(bug("Exec_ExpungeETask: Freeing et=%x, ts=%x, size=%d\n",
244 et, ts, ts ? (ULONG)ts[__TS_FIRSTSLOT] : 0
246 FreeMem(et, sizeof(struct IntETask));
247 if (ts)
248 FreeMem(ts, ts[__TS_FIRSTSLOT] * sizeof(ts[0]));
251 BOOL Exec_CheckTask(struct Task *task, struct ExecBase *SysBase)
253 struct Task *t;
255 if (!task)
256 return FALSE;
258 Forbid();
260 if (task == SysBase->ThisTask)
262 Permit();
263 return TRUE;
266 ForeachNode(&SysBase->TaskReady, t)
268 if (task == t)
270 Permit();
271 return TRUE;
275 ForeachNode(&SysBase->TaskWait, t)
277 if (task == t)
279 Permit();
280 return TRUE;
284 Permit();
285 return FALSE;