2 Copyright © 1995-2011, 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_intern.h"
18 #include "exec_util.h"
21 * TODO: The following two functions are subject to removal.
22 * They are used only by i386-pc port for allocating CPU context.
23 * This needs to be changed.
26 /*****************************************************************************
29 #include "exec_util.h"
31 APTR
Exec_AllocTaskMem (
37 struct ExecBase
*SysBase
)
40 Allocate memory which will be freed when the task is removed.
43 task - The memory will be freed when this task is removed.
44 size - How much memory.
45 req - What memory. See AllocMem() for details.
48 Adress to a memory block or NULL if no memory was available.
57 AllocMem(), FreeTaskMem()
60 The memory is allocated and queued in the tc_MemList. This
61 list is freed in RemTask().
63 ******************************************************************************/
68 ml
= AllocMem (sizeof (struct MemList
), MEMF_ANY
);
69 mem
= AllocMem (size
, req
);
74 FreeMem (ml
, sizeof (struct MemList
));
82 ml
->ml_NumEntries
= 1;
83 ml
->ml_ME
[0].me_Addr
= mem
;
84 ml
->ml_ME
[0].me_Length
= size
;
87 AddHead (&task
->tc_MemEntry
, &ml
->ml_Node
);
94 /*****************************************************************************
97 #include "exec_util.h"
99 void Exec_FreeTaskMem (
104 struct ExecBase
*SysBase
)
107 Freeate memory which will be freed when the task is removed.
110 task - The memory will be freed when this task is removed.
111 size - How much memory.
112 req - What memory. See FreeMem() for details.
115 Adress to a memory block or NULL if no memory was available.
124 FreeMem(), FreeTaskMem()
127 The memory is allocated and queued in the tc_MemList. This
128 list is freed in RemTask().
130 ******************************************************************************/
132 struct MemList
* ml
, * next
;
136 ForeachNodeSafe (&task
->tc_MemEntry
, ml
, next
)
139 Quick check: If the node was allocated by AllocTaskMem(),
140 then it has only one entry.
142 if (ml
->ml_NumEntries
== 1
143 && ml
->ml_ME
[0].me_Addr
== mem
146 Remove (&ml
->ml_Node
);
149 FreeMem (ml
->ml_ME
[0].me_Addr
, ml
->ml_ME
[0].me_Length
);
150 FreeMem (ml
, sizeof (struct MemList
));
160 /*****************************************************************************
163 #include "exec_util.h"
165 struct ETask
* Exec_FindChild(
169 struct ExecBase
*SysBase
)
172 Scan through the current tasks children list searching for the task
173 whose et_UniqueID field matches.
176 id - The task ID to match.
179 Address of the ETask structure that matches, or
192 ******************************************************************************/
195 struct ETask
*thisET
;
197 thisET
= GetETask(FindTask(NULL
));
200 ForeachNode (&thisET
->et_Children
, et
)
202 if (et
->et_UniqueID
== id
)
205 ForeachNode(&thisET
->et_TaskMsgPort
.mp_MsgList
, et
)
207 if (et
->et_UniqueID
== id
)
215 Exec_InitETask(struct Task
*task
, struct ETask
*et
, struct ExecBase
*SysBase
)
217 et
->et_Parent
= FindTask(NULL
);
218 NEWLIST(&et
->et_Children
);
220 /* Initialise the message list */
221 InitMsgPort(&et
->et_TaskMsgPort
);
222 et
->et_TaskMsgPort
.mp_SigTask
= task
;
223 et
->et_TaskMsgPort
.mp_SigBit
= SIGB_CHILD
;
225 /* Initialise the trap fields */
226 et
->et_TrapAlloc
= SysBase
->TaskTrapAlloc
;
231 int len
= strlen(task
->tc_Node
.ln_Name
) + 1;
232 IntETask(et
)->iet_Me
= AllocVec(len
, MEMF_CLEAR
|MEMF_PUBLIC
);
233 if (IntETask(et
)->iet_Me
!= NULL
)
234 CopyMem(task
->tc_Node
.ln_Name
, IntETask(et
)->iet_Me
, len
);
238 /* Get an unique identifier for this task */
240 while(et
->et_UniqueID
== 0)
243 * Add some fuzz on wrapping. Its likely that the early numbers
244 * where taken by somebody else.
246 if(++SysBase
->ex_TaskID
== 0)
247 SysBase
->ex_TaskID
= 1024;
250 if (FindTaskByPID(SysBase
->ex_TaskID
) == NULL
)
251 et
->et_UniqueID
= SysBase
->ex_TaskID
;
256 /* Finally if the parent task is an ETask, add myself as its child */
257 if(et
->et_Parent
&& ((struct Task
*) et
->et_Parent
)->tc_Flags
& TF_ETASK
)
260 ADDHEAD(&GetETask(et
->et_Parent
)->et_Children
, et
);
266 Exec_CleanupETask(struct Task
*task
, struct ETask
*et
, struct ExecBase
*SysBase
)
268 struct ETask
*child
, *nextchild
, *parent
;
269 struct Node
*tmpNode
;
275 /* Clean up after all the children that the task didn't do itself. */
276 ForeachNodeSafe(&et
->et_TaskMsgPort
.mp_MsgList
, child
, tmpNode
)
278 /* This is effectively ChildFree() */
279 if(child
->et_Result2
)
280 FreeVec(child
->et_Result2
);
282 FreeVec(child
->iet_Me
);
287 /* If we have an ETask parent, tell it we have exited. */
288 if(et
->et_Parent
!= NULL
)
290 parent
= GetETask(et
->et_Parent
);
292 /* Link children to our parent. */
293 ForeachNodeSafe(&et
->et_Children
, child
, nextchild
)
295 child
->et_Parent
= et
->et_Parent
;
297 ADDTAIL(&parent
->et_Children
, child
);
301 /* Notify parent only if child was created with NP_NotifyOnDeath set
305 (((struct Task
*)task
)->tc_Node
.ln_Type
== NT_PROCESS
) &&
306 (((struct Process
*) task
)->pr_Flags
& PRF_NOTIFYONDEATH
)
310 PutMsg(&parent
->et_TaskMsgPort
, (struct Message
*)et
);
312 else if(parent
!= NULL
)
330 /* Orphan all our remaining children. */
331 ForeachNode(&et
->et_Children
, child
)
332 child
->et_Parent
= NULL
;
343 BOOL
Exec_CheckTask(struct Task
*task
, struct ExecBase
*SysBase
)
352 if (task
== SysBase
->ThisTask
)
358 ForeachNode(&SysBase
->TaskReady
, t
)
367 ForeachNode(&SysBase
->TaskWait
, t
)