2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Exec utility functions.
8 #include <exec/lists.h>
9 #include <exec/tasks.h>
10 #include <exec/memory.h>
11 #include <exec/execbase.h>
12 #include <dos/dosextens.h>
14 #include <proto/exec.h>
17 #include "exec_util.h"
19 /*****************************************************************************
22 #include "exec_util.h"
24 APTR
Exec_AllocTaskMem (
30 struct ExecBase
*SysBase
)
33 Allocate memory which will be freed when the task is removed.
36 task - The memory will be freed when this task is removed.
37 size - How much memory.
38 req - What memory. See AllocMem() for details.
41 Adress to a memory block or NULL if no memory was available.
50 AllocMem(), FreeTaskMem()
53 The memory is allocated and queued in the tc_MemList. This
54 list is freed in RemTask().
56 ******************************************************************************/
61 ml
= AllocMem (sizeof (struct MemList
), MEMF_ANY
);
62 mem
= AllocMem (size
, req
);
67 FreeMem (ml
, sizeof (struct MemList
));
75 ml
->ml_NumEntries
= 1;
76 ml
->ml_ME
[0].me_Addr
= mem
;
77 ml
->ml_ME
[0].me_Length
= size
;
80 AddHead (&task
->tc_MemEntry
, &ml
->ml_Node
);
87 /*****************************************************************************
90 #include "exec_util.h"
92 void Exec_FreeTaskMem (
97 struct ExecBase
*SysBase
)
100 Freeate memory which will be freed when the task is removed.
103 task - The memory will be freed when this task is removed.
104 size - How much memory.
105 req - What memory. See FreeMem() for details.
108 Adress to a memory block or NULL if no memory was available.
117 FreeMem(), FreeTaskMem()
120 The memory is allocated and queued in the tc_MemList. This
121 list is freed in RemTask().
123 ******************************************************************************/
125 struct MemList
* ml
, * next
;
129 ForeachNodeSafe (&task
->tc_MemEntry
, ml
, next
)
132 Quick check: If the node was allocated by AllocTaskMem(),
133 then it has only one entry.
135 if (ml
->ml_NumEntries
== 1
136 && ml
->ml_ME
[0].me_Addr
== mem
139 Remove (&ml
->ml_Node
);
142 FreeMem (ml
->ml_ME
[0].me_Addr
, ml
->ml_ME
[0].me_Length
);
143 FreeMem (ml
, sizeof (struct MemList
));
153 /*****************************************************************************
156 #include "exec_util.h"
158 struct Task
* Exec_FindTaskByID(
162 struct ExecBase
*SysBase
)
165 Scan through the task lists searching for the task whose
166 et_UniqueID field matches.
169 id - The task ID to match.
172 Address of the Task control structure that matches, or
185 ******************************************************************************/
191 First up, check ThisTask. It could be NULL because of exec_init.c
193 if (SysBase
->ThisTask
!= NULL
)
195 et
= GetETask(SysBase
->ThisTask
);
196 if (et
!= NULL
&& et
->et_UniqueID
== id
)
197 return SysBase
->ThisTask
;
200 /* Next, go through the ready list */
201 ForeachNode(&SysBase
->TaskReady
, t
)
204 if (et
!= NULL
&& et
->et_UniqueID
== id
)
208 /* Finally, go through the wait list */
209 ForeachNode(&SysBase
->TaskWait
, t
)
212 if (et
!= NULL
&& et
->et_UniqueID
== id
)
219 /*****************************************************************************
222 #include "exec_util.h"
224 struct ETask
* Exec_FindChild(
228 struct ExecBase
*SysBase
)
231 Scan through the current tasks children list searching for the task
232 whose et_UniqueID field matches.
235 id - The task ID to match.
238 Address of the ETask structure that matches, or
251 ******************************************************************************/
254 struct ETask
*thisET
;
256 thisET
= GetETask(FindTask(NULL
));
259 ForeachNode (&thisET
->et_Children
, et
)
261 if (et
->et_UniqueID
== id
)
264 ForeachNode(&thisET
->et_TaskMsgPort
.mp_MsgList
, et
)
266 if (et
->et_UniqueID
== id
)
274 Exec_InitETask(struct Task
*task
, struct ETask
*et
, struct ExecBase
*SysBase
)
276 et
->et_Parent
= FindTask(NULL
);
277 NEWLIST(&et
->et_Children
);
279 /* Initialise the message list */
280 NEWLIST(&et
->et_TaskMsgPort
.mp_MsgList
);
281 et
->et_TaskMsgPort
.mp_Flags
= PA_SIGNAL
;
282 et
->et_TaskMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
283 et
->et_TaskMsgPort
.mp_SigTask
= task
;
284 et
->et_TaskMsgPort
.mp_SigBit
= SIGB_CHILD
;
286 /* Initialise the trap fields */
287 et
->et_TrapAlloc
= SysBase
->TaskTrapAlloc
;
292 int len
= strlen(task
->tc_Node
.ln_Name
) + 1;
293 IntETask(et
)->iet_Me
= AllocVec(len
, MEMF_CLEAR
|MEMF_PUBLIC
);
294 if (IntETask(et
)->iet_Me
!= NULL
)
295 CopyMem(task
->tc_Node
.ln_Name
, IntETask(et
)->iet_Me
, len
);
299 /* Get an unique identifier for this task */
301 while(et
->et_UniqueID
== 0)
304 * Add some fuzz on wrapping. Its likely that the early numbers
305 * where taken by somebody else.
307 if(++SysBase
->ex_TaskID
== 0)
308 SysBase
->ex_TaskID
= 1024;
311 if(Exec_FindTaskByID(SysBase
->ex_TaskID
, SysBase
) == NULL
)
312 et
->et_UniqueID
= SysBase
->ex_TaskID
;
317 /* Finally if the parent task is an ETask, add myself as its child */
318 if(et
->et_Parent
&& ((struct Task
*) et
->et_Parent
)->tc_Flags
& TF_ETASK
)
321 ADDHEAD(&GetETask(et
->et_Parent
)->et_Children
, et
);
327 Exec_CleanupETask(struct Task
*task
, struct ETask
*et
, struct ExecBase
*SysBase
)
329 struct ETask
*child
, *parent
;
330 struct Node
*tmpNode
;
334 /* Clean up after all the children that the task didn't do itself. */
335 ForeachNodeSafe(&et
->et_TaskMsgPort
.mp_MsgList
, child
, tmpNode
)
337 /* This is effectively ChildFree() */
338 if(child
->et_Result2
)
339 FreeVec(child
->et_Result2
);
341 FreeVec(child
->iet_Me
);
346 /* Orphan all our remaining children. */
347 #warning FIXME: should we link the children to our parent?
348 ForeachNode(&et
->et_Children
, child
)
349 child
->et_Parent
= NULL
;
351 /* If we have an ETask parent, tell it we have exited. */
352 if(et
->et_Parent
!= NULL
)
354 parent
= GetETask(et
->et_Parent
);
355 /* Nofity parent only if child was created with NP_NotifyOnDeath set
359 (((struct Task
*)task
)->tc_Node
.ln_Type
== NT_PROCESS
) &&
360 (((struct Process
*) task
)->pr_Flags
& PRF_NOTIFYONDEATH
)
364 PutMsg(&parent
->et_TaskMsgPort
, et
);
366 else if(parent
!= NULL
)