2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
5 Desc: Exec utility functions.
10 #include <aros/debug.h>
12 #include <exec/lists.h>
13 #include <exec/tasks.h>
14 #include <exec/memory.h>
15 #include <exec/execbase.h>
16 #include <dos/dosextens.h>
18 #include <proto/exec.h>
21 #include "exec_intern.h"
22 #include "exec_util.h"
23 #include "taskstorage.h"
25 /****************************************************************************
28 #include "exec_util.h"
30 struct ETask
* Exec_FindChild(
34 struct ExecBase
*SysBase
)
37 Scan through the current tasks children list searching for the task
38 whose et_UniqueID field matches.
41 id - The task ID to match.
44 Address of the ETask structure that matches, or
48 This is an internal exec.library function not exported from the
59 ******************************************************************************/
61 struct Task
*ThisTask
= GET_THIS_TASK
;
62 struct ETask
*et
, *retVal
= NULL
;
65 thisET
= GetETask(ThisTask
);
68 #if defined(__AROSEXEC_SMP__)
69 EXEC_SPINLOCK_LOCK(&IntETask(thisET
)->iet_TaskLock
, NULL
, SPINLOCK_MODE_READ
);
71 ForeachNode (&thisET
->et_Children
, et
)
73 if (et
->et_UniqueID
== id
)
79 #if defined(__AROSEXEC_SMP__)
80 EXEC_SPINLOCK_UNLOCK(&IntETask(thisET
)->iet_TaskLock
);
84 #if defined(__AROSEXEC_SMP__)
85 EXEC_SPINLOCK_LOCK(&thisET
->et_TaskMsgPort
.mp_SpinLock
, NULL
, SPINLOCK_MODE_READ
);
87 ForeachNode(&thisET
->et_TaskMsgPort
.mp_MsgList
, et
)
89 if (et
->et_UniqueID
== id
)
95 #if defined(__AROSEXEC_SMP__)
96 EXEC_SPINLOCK_UNLOCK(&thisET
->et_TaskMsgPort
.mp_SpinLock
);
104 Exec_InitETask(struct Task
*task
, struct Task
*parent
, struct ExecBase
*SysBase
)
107 * We don't add this to the task memory, it isn't free'd by
108 * RemTask(), rather by somebody else calling ChildFree().
109 * Alternatively, an orphaned task will free its own ETask.
111 #if defined(__AROSEXEC_SMP__)
115 AllocMem(sizeof(struct IntETask
), MEMF_PUBLIC
| MEMF_CLEAR
);
118 bug("[EXEC:ETask] Init: Allocated ETask for Task '%s' @ %p\n",
119 task
->tc_Node
.ln_Name
, task
);
120 bug("[EXEC:ETask] Init: ETask @ 0x%p, %d bytes\n",
121 et
, sizeof(struct IntETask
));
124 task
->tc_UnionETask
.tc_ETask
= et
;
127 task
->tc_Flags
|= TF_ETASK
;
129 #if defined(__AROSEXEC_SMP__)
130 cpunum
= KrnGetCPUNumber();
131 EXEC_SPINLOCK_INIT(&IntETask(et
)->iet_TaskLock
);
132 if (PrivExecBase(SysBase
)->IntFlags
& EXECF_CPUAffinity
)
134 IntETask(et
)->iet_CpuAffinity
= KrnAllocCPUMask();
135 KrnGetCPUMask(cpunum
, IntETask(et
)->iet_CpuAffinity
);
137 D(bug("[EXEC:ETask] Init: CPU #%d, mask %08x\n", cpunum
, IntETask(et
)->iet_CpuAffinity
);)
141 et
->et_Parent
= parent
;
142 NEWLIST(&et
->et_Children
);
144 D(bug("[EXEC:ETask] Init: Parent @ 0x%p\n", et
->et_Parent
);)
146 /* Initialise the message list */
147 InitMsgPort(&et
->et_TaskMsgPort
);
148 et
->et_TaskMsgPort
.mp_SigTask
= task
;
149 et
->et_TaskMsgPort
.mp_SigBit
= SIGB_CHILD
;
151 /* Initialise the trap fields */
152 et
->et_TrapAlloc
= SysBase
->TaskTrapAlloc
;
157 int len
= strlen(task
->tc_Node
.ln_Name
) + 1;
158 IntETask(et
)->iet_Me
= AllocVec(len
, MEMF_CLEAR
|MEMF_PUBLIC
);
159 if (IntETask(et
)->iet_Me
!= NULL
)
160 CopyMem(task
->tc_Node
.ln_Name
, IntETask(et
)->iet_Me
, len
);
164 D(bug("[EXEC:ETask] Init: Generating Unique ID...\n");)
166 /* Get a unique identifier for this task */
168 while(et
->et_UniqueID
== 0)
170 //TODO: Replace with UUID!
173 * Add some fuzz on wrapping. It's likely that the early numbers
174 * where taken by somebody else.
176 if(++SysBase
->ex_TaskID
== 0)
177 SysBase
->ex_TaskID
= 1024;
180 D(bug("[EXEC:ETask] Init: Checking for existing ID...\n");)
181 if (FindTaskByPID(SysBase
->ex_TaskID
) == NULL
)
182 et
->et_UniqueID
= SysBase
->ex_TaskID
;
183 D(bug("[EXEC:ETask] Init: done\n");)
187 D(bug("[EXEC:ETask] Init: Task ID : %08x\n", et
->et_UniqueID
);)
189 /* Finally if the parent task is an ETask, add myself as its child */
190 if(et
->et_Parent
&& ((struct Task
*) et
->et_Parent
)->tc_Flags
& TF_ETASK
)
192 struct ETask
* parentEtask
= GetETask(et
->et_Parent
);
193 D(bug("[EXEC:ETask] Init: Registering with Parent ETask\n");)
194 #if defined(__AROSEXEC_SMP__)
195 EXEC_SPINLOCK_LOCK(&IntETask(parentEtask
)->iet_TaskLock
, NULL
, SPINLOCK_MODE_WRITE
);
197 ADDHEAD(&parentEtask
->et_Children
, et
);
198 #if defined(__AROSEXEC_SMP__)
199 EXEC_SPINLOCK_UNLOCK(&IntETask(parentEtask
)->iet_TaskLock
);
204 D(bug("[EXEC:ETask] Init: Initialized\n");)
210 Exec_CleanupETask(struct Task
*task
, struct ExecBase
*SysBase
)
212 struct ETask
*et
, *child
, *nextchild
, *parent
;
213 struct Node
*tmpNode
;
216 if(!(task
->tc_Flags
& TF_ETASK
) ||
217 ((et
= task
->tc_UnionETask
.tc_ETask
) == NULL
))
220 D(bug("[EXEC:ETask] Cleanup: Task @ 0x%p, ETask @ 0x%p\n", task
, et
);)
224 #if defined(__AROSEXEC_SMP__)
225 if ((PrivExecBase(SysBase
)->IntFlags
& EXECF_CPUAffinity
) && (IntETask(et
)->iet_CpuAffinity
))
227 if ((IPTR
)IntETask(et
)->iet_CpuAffinity
!= TASKAFFINITY_ANY
)
228 KrnFreeCPUMask(IntETask(et
)->iet_CpuAffinity
);
232 #if defined(__AROSEXEC_SMP__)
233 EXEC_SPINLOCK_LOCK(&et
->et_TaskMsgPort
.mp_SpinLock
, NULL
, SPINLOCK_MODE_WRITE
);
235 /* Clean up after all the children that the task didn't do itself. */
236 ForeachNodeSafe(&et
->et_TaskMsgPort
.mp_MsgList
, child
, tmpNode
)
240 #if defined(__AROSEXEC_SMP__)
241 EXEC_SPINLOCK_UNLOCK(&et
->et_TaskMsgPort
.mp_SpinLock
);
243 /* If we have an ETask parent, tell it we have exited. */
244 if(et
->et_Parent
!= NULL
)
246 parent
= GetETask(et
->et_Parent
);
248 #if defined(__AROSEXEC_SMP__)
249 EXEC_SPINLOCK_LOCK(&IntETask(et
)->iet_TaskLock
, NULL
, SPINLOCK_MODE_WRITE
);
251 /* Link children to our parent. */
252 ForeachNodeSafe(&et
->et_Children
, child
, nextchild
)
254 child
->et_Parent
= et
->et_Parent
;
258 #if defined(__AROSEXEC_SMP__)
259 EXEC_SPINLOCK_LOCK(&IntETask(parent
)->iet_TaskLock
, NULL
, SPINLOCK_MODE_WRITE
);
261 ADDTAIL(&parent
->et_Children
, child
);
262 #if defined(__AROSEXEC_SMP__)
263 EXEC_SPINLOCK_UNLOCK(&IntETask(parent
)->iet_TaskLock
);
268 #if defined(__AROSEXEC_SMP__)
269 EXEC_SPINLOCK_UNLOCK(&IntETask(et
)->iet_TaskLock
);
272 /* Notify parent only if child was created with NP_NotifyOnDeath set
276 #if defined(__AROSEXEC_SMP__)
277 EXEC_SPINLOCK_LOCK(&IntETask(parent
)->iet_TaskLock
, NULL
, SPINLOCK_MODE_WRITE
);
280 #if defined(__AROSEXEC_SMP__)
281 EXEC_SPINLOCK_UNLOCK(&IntETask(parent
)->iet_TaskLock
);
284 (((struct Task
*)task
)->tc_Node
.ln_Type
== NT_PROCESS
) &&
285 (((struct Process
*) task
)->pr_Flags
& PRF_NOTIFYONDEATH
)
288 PutMsg(&parent
->et_TaskMsgPort
, (struct Message
*)et
);
295 #if defined(__AROSEXEC_SMP__)
296 EXEC_SPINLOCK_LOCK(&IntETask(et
)->iet_TaskLock
, NULL
, SPINLOCK_MODE_WRITE
);
298 /* Orphan all our remaining children. */
299 ForeachNode(&et
->et_Children
, child
)
300 child
->et_Parent
= NULL
;
301 #if defined(__AROSEXEC_SMP__)
302 EXEC_SPINLOCK_UNLOCK(&IntETask(et
)->iet_TaskLock
);
313 Exec_ExpungeETask(struct ETask
*et
, struct ExecBase
*SysBase
)
315 IPTR
*ts
= et
->et_TaskStorage
;
317 FreeVec(et
->et_Result2
);
320 FreeVec(IntETask(et
)->iet_Me
);
322 D(bug("[EXEC:ETask] Expunge: Freeing ETask @ 0x%p, TS @ 0x%p, size=%d\n",
323 et
, ts
, ts
? (ULONG
)ts
[__TS_FIRSTSLOT
] : 0
325 FreeMem(et
, sizeof(struct IntETask
));
327 FreeMem(ts
, ts
[__TS_FIRSTSLOT
] * sizeof(ts
[0]));
330 BOOL
Exec_CheckTask(struct Task
*task
, struct ExecBase
*SysBase
)
338 #if defined(__AROSEXEC_SMP__)
339 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase
)->TaskRunningSpinLock
, NULL
, SPINLOCK_MODE_READ
);
340 ForeachNode(&PrivExecBase(SysBase
)->TaskRunning
, t
)
344 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskRunningSpinLock
);
349 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskRunningSpinLock
);
352 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase
)->TaskSpinningLock
, NULL
, SPINLOCK_MODE_READ
);
353 ForeachNode(&PrivExecBase(SysBase
)->TaskSpinning
, t
)
357 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskSpinningLock
);
362 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskSpinningLock
);
365 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase
)->TaskReadySpinLock
, NULL
, SPINLOCK_MODE_READ
);
367 if (task
== GET_THIS_TASK
)
374 ForeachNode(&SysBase
->TaskReady
, t
)
378 #if defined(__AROSEXEC_SMP__)
379 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskReadySpinLock
);
385 #if defined(__AROSEXEC_SMP__)
386 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskReadySpinLock
);
389 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase
)->TaskWaitSpinLock
, NULL
, SPINLOCK_MODE_READ
);
391 ForeachNode(&SysBase
->TaskWait
, t
)
395 #if defined(__AROSEXEC_SMP__)
396 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskWaitSpinLock
);
402 #if defined(__AROSEXEC_SMP__)
403 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskWaitSpinLock
);