2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
5 Desc: Exec utility functions.
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>
19 #include "exec_intern.h"
20 #include "exec_util.h"
21 #include "taskstorage.h"
23 /*i***************************************************************************
26 #include "exec_util.h"
28 struct ETask
* Exec_FindChild(
32 struct ExecBase
*SysBase
)
35 Scan through the current tasks children list searching for the task
36 whose et_UniqueID field matches.
39 id - The task ID to match.
42 Address of the ETask structure that matches, or
46 This is an internal exec.library function not exported from the
57 ******************************************************************************/
59 struct Task
*ThisTask
= GET_THIS_TASK
;
63 thisET
= GetETask(ThisTask
);
66 ForeachNode (&thisET
->et_Children
, et
)
68 if (et
->et_UniqueID
== id
)
71 ForeachNode(&thisET
->et_TaskMsgPort
.mp_MsgList
, et
)
73 if (et
->et_UniqueID
== id
)
81 Exec_InitETask(struct Task
*task
, struct ExecBase
*SysBase
)
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.
89 AllocMem(sizeof(struct IntETask
), MEMF_PUBLIC
| MEMF_CLEAR
);
91 D(bug("[EXEC:ETask] Init: Allocated ETask @ 0x%p, %d bytes for Task @ %p\n",
92 et
, sizeof(struct IntETask
), task
);)
94 task
->tc_UnionETask
.tc_ETask
= et
;
97 task
->tc_Flags
|= TF_ETASK
;
99 #if defined(__AROSEXEC_SMP__)
100 EXEC_SPINLOCK_INIT(&IntETask(et
)->iet_TaskLock
);
101 IntETask(et
)->iet_CpuAffinity
= (1 << 0);
104 et
->et_Parent
= GET_THIS_TASK
;
105 NEWLIST(&et
->et_Children
);
107 /* Initialise the message list */
108 InitMsgPort(&et
->et_TaskMsgPort
);
109 et
->et_TaskMsgPort
.mp_SigTask
= task
;
110 et
->et_TaskMsgPort
.mp_SigBit
= SIGB_CHILD
;
112 /* Initialise the trap fields */
113 et
->et_TrapAlloc
= SysBase
->TaskTrapAlloc
;
118 int len
= strlen(task
->tc_Node
.ln_Name
) + 1;
119 IntETask(et
)->iet_Me
= AllocVec(len
, MEMF_CLEAR
|MEMF_PUBLIC
);
120 if (IntETask(et
)->iet_Me
!= NULL
)
121 CopyMem(task
->tc_Node
.ln_Name
, IntETask(et
)->iet_Me
, len
);
125 /* Get a unique identifier for this task */
127 while(et
->et_UniqueID
== 0)
130 * Add some fuzz on wrapping. It's likely that the early numbers
131 * where taken by somebody else.
133 if(++SysBase
->ex_TaskID
== 0)
134 SysBase
->ex_TaskID
= 1024;
137 if (FindTaskByPID(SysBase
->ex_TaskID
) == NULL
)
138 et
->et_UniqueID
= SysBase
->ex_TaskID
;
143 /* Finally if the parent task is an ETask, add myself as its child */
144 if(et
->et_Parent
&& ((struct Task
*) et
->et_Parent
)->tc_Flags
& TF_ETASK
)
147 ADDHEAD(&GetETask(et
->et_Parent
)->et_Children
, et
);
155 Exec_CleanupETask(struct Task
*task
, struct ExecBase
*SysBase
)
157 struct ETask
*et
= NULL
, *child
, *nextchild
, *parent
;
158 struct Node
*tmpNode
;
161 if(task
->tc_Flags
& TF_ETASK
)
162 et
= task
->tc_UnionETask
.tc_ETask
;
166 D(bug("[EXEC:ETask] Cleanup: Task @ 0x%p, ETask @ 0x%p\n", task
, et
);)
170 /* Clean up after all the children that the task didn't do itself. */
171 ForeachNodeSafe(&et
->et_TaskMsgPort
.mp_MsgList
, child
, tmpNode
)
176 /* If we have an ETask parent, tell it we have exited. */
177 if(et
->et_Parent
!= NULL
)
179 parent
= GetETask(et
->et_Parent
);
181 /* Link children to our parent. */
182 ForeachNodeSafe(&et
->et_Children
, child
, nextchild
)
184 child
->et_Parent
= et
->et_Parent
;
187 ADDTAIL(&parent
->et_Children
, child
);
191 /* Notify parent only if child was created with NP_NotifyOnDeath set
198 (((struct Task
*)task
)->tc_Node
.ln_Type
== NT_PROCESS
) &&
199 (((struct Process
*) task
)->pr_Flags
& PRF_NOTIFYONDEATH
)
202 PutMsg(&parent
->et_TaskMsgPort
, (struct Message
*)et
);
209 /* Orphan all our remaining children. */
210 ForeachNode(&et
->et_Children
, child
)
211 child
->et_Parent
= NULL
;
221 Exec_ExpungeETask(struct ETask
*et
, struct ExecBase
*SysBase
)
223 IPTR
*ts
= et
->et_TaskStorage
;
225 FreeVec(et
->et_Result2
);
228 FreeVec(IntETask(et
)->iet_Me
);
230 D(bug("[EXEC:ETask] Expunge: Freeing ETask @ 0x%p, TS @ 0x%p, size=%d\n",
231 et
, ts
, ts
? (ULONG
)ts
[__TS_FIRSTSLOT
] : 0
233 FreeMem(et
, sizeof(struct IntETask
));
235 FreeMem(ts
, ts
[__TS_FIRSTSLOT
] * sizeof(ts
[0]));
238 BOOL
Exec_CheckTask(struct Task
*task
, struct ExecBase
*SysBase
)
245 #if defined(__AROSEXEC_SMP__)
246 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase
)->TaskRunningSpinLock
, SPINLOCK_MODE_READ
);
250 #if defined(__AROSEXEC_SMP__)
251 ForeachNode(&PrivExecBase(SysBase
)->TaskRunning
, t
)
255 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskRunningSpinLock
);
260 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskRunningSpinLock
);
262 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase
)->TaskSpinningLock
, SPINLOCK_MODE_READ
);
264 ForeachNode(&PrivExecBase(SysBase
)->TaskSpinning
, t
)
268 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskSpinningLock
);
273 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskSpinningLock
);
275 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase
)->TaskReadySpinLock
, SPINLOCK_MODE_READ
);
278 if (task
== GET_THIS_TASK
)
285 ForeachNode(&SysBase
->TaskReady
, t
)
289 #if defined(__AROSEXEC_SMP__)
290 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskReadySpinLock
);
296 #if defined(__AROSEXEC_SMP__)
297 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskReadySpinLock
);
299 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase
)->TaskWaitSpinLock
, SPINLOCK_MODE_READ
);
302 ForeachNode(&SysBase
->TaskWait
, t
)
306 #if defined(__AROSEXEC_SMP__)
307 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskWaitSpinLock
);
313 #if defined(__AROSEXEC_SMP__)
314 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskWaitSpinLock
);