just use FindTask directly so we don't waste storage (and also the need to call it...
[AROS.git] / rom / exec / exec_util.c
blob355a4aba3c2af4f4de26c8cd3ca5f21d8fb7c0c5
1 /*
2 Copyright © 1995-2015, 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)
83 * We don't add this to the task memory, it isn't free'd by
84 * RemTask(), rather by somebody else calling ChildFree().
85 * Alternatively, an orphaned task will free its own ETask.
87 struct ETask *et =
88 AllocMem(sizeof(struct IntETask), MEMF_PUBLIC | MEMF_CLEAR);
90 D(bug("[EXEC:ETask] Init: Allocated ETask @ 0x%p, %d bytes for Task @ %p\n",
91 et, sizeof(struct IntETask), task));
93 task->tc_UnionETask.tc_ETask = et;
94 if (!et)
95 return FALSE;
96 task->tc_Flags |= TF_ETASK;
98 #if defined(__AROSEXEC_SMP__)
99 IntETask(et)->iet_CpuAffinity = (1 << 0);
100 #endif
102 et->et_Parent = FindTask(NULL);
103 NEWLIST(&et->et_Children);
105 /* Initialise the message list */
106 InitMsgPort(&et->et_TaskMsgPort);
107 et->et_TaskMsgPort.mp_SigTask = task;
108 et->et_TaskMsgPort.mp_SigBit = SIGB_CHILD;
110 /* Initialise the trap fields */
111 et->et_TrapAlloc = SysBase->TaskTrapAlloc;
112 et->et_TrapAble = 0;
114 #ifdef DEBUG_ETASK
116 int len = strlen(task->tc_Node.ln_Name) + 1;
117 IntETask(et)->iet_Me = AllocVec(len, MEMF_CLEAR|MEMF_PUBLIC);
118 if (IntETask(et)->iet_Me != NULL)
119 CopyMem(task->tc_Node.ln_Name, IntETask(et)->iet_Me, len);
121 #endif
123 /* Get a unique identifier for this task */
124 Forbid();
125 while(et->et_UniqueID == 0)
128 * Add some fuzz on wrapping. It's likely that the early numbers
129 * where taken by somebody else.
131 if(++SysBase->ex_TaskID == 0)
132 SysBase->ex_TaskID = 1024;
134 Disable();
135 if (FindTaskByPID(SysBase->ex_TaskID) == NULL)
136 et->et_UniqueID = SysBase->ex_TaskID;
137 Enable();
139 Permit();
141 /* Finally if the parent task is an ETask, add myself as its child */
142 if(et->et_Parent && ((struct Task*) et->et_Parent)->tc_Flags & TF_ETASK)
144 Forbid();
145 ADDHEAD(&GetETask(et->et_Parent)->et_Children, et);
146 Permit();
149 return TRUE;
152 void
153 Exec_CleanupETask(struct Task *task, struct ExecBase *SysBase)
155 struct ETask *et = NULL, *child, *nextchild, *parent;
156 struct Node *tmpNode;
157 BOOL expunge = TRUE;
159 if(task->tc_Flags & TF_ETASK)
160 et = task->tc_UnionETask.tc_ETask;
161 if(!et)
162 return;
164 D(bug("[EXEC:ETask] Cleanup: Task @ 0x%p, ETask @ 0x%p\n", task, et));
166 Forbid();
168 /* Clean up after all the children that the task didn't do itself. */
169 ForeachNodeSafe(&et->et_TaskMsgPort.mp_MsgList, child, tmpNode)
171 ExpungeETask(child);
174 /* If we have an ETask parent, tell it we have exited. */
175 if(et->et_Parent != NULL)
177 parent = GetETask(et->et_Parent);
179 /* Link children to our parent. */
180 ForeachNodeSafe(&et->et_Children, child, nextchild)
182 child->et_Parent = et->et_Parent;
183 //Forbid();
184 if (parent)
185 ADDTAIL(&parent->et_Children, child);
186 //Permit();
189 /* Notify parent only if child was created with NP_NotifyOnDeath set
190 to TRUE */
191 if(parent != NULL)
193 REMOVE(et);
196 (((struct Task *)task)->tc_Node.ln_Type == NT_PROCESS) &&
197 (((struct Process*) task)->pr_Flags & PRF_NOTIFYONDEATH)
200 PutMsg(&parent->et_TaskMsgPort, (struct Message *)et);
201 expunge = FALSE;
205 else
207 /* Orphan all our remaining children. */
208 ForeachNode(&et->et_Children, child)
209 child->et_Parent = NULL;
212 if(expunge)
213 ExpungeETask(et);
215 Permit();
218 void
219 Exec_ExpungeETask(struct ETask *et, struct ExecBase *SysBase)
221 IPTR *ts = et->et_TaskStorage;
223 FreeVec(et->et_Result2);
225 #ifdef DEBUG_ETASK
226 FreeVec(IntETask(et)->iet_Me);
227 #endif
228 D(bug("[EXEC:ETask] Expunge: Freeing ETask @ 0x%p, TS @ 0x%p, size=%d\n",
229 et, ts, ts ? (ULONG)ts[__TS_FIRSTSLOT] : 0
231 FreeMem(et, sizeof(struct IntETask));
232 if (ts)
233 FreeMem(ts, ts[__TS_FIRSTSLOT] * sizeof(ts[0]));
236 BOOL Exec_CheckTask(struct Task *task, struct ExecBase *SysBase)
238 struct Task *t;
240 if (!task)
241 return FALSE;
243 #if defined(__AROSEXEC_SMP__)
244 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskRunningSpinLock, SPINLOCK_MODE_READ);
245 Disable();
246 #else
247 Forbid();
248 #endif
250 #if defined(__AROSEXEC_SMP__)
251 ForeachNode(&PrivExecBase(SysBase)->TaskRunning, t)
253 if (task == t)
255 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskRunningSpinLock);
256 Enable();
257 return TRUE;
260 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskRunningSpinLock);
261 Enable();
262 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskReadySpinLock, SPINLOCK_MODE_READ);
263 Disable();
264 #else
265 if (task == GET_THIS_TASK)
267 Permit();
268 return TRUE;
270 #endif
272 ForeachNode(&SysBase->TaskReady, t)
274 if (task == t)
276 #if defined(__AROSEXEC_SMP__)
277 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskReadySpinLock);
278 Enable();
279 #else
280 Permit();
281 #endif
282 return TRUE;
285 #if defined(__AROSEXEC_SMP__)
286 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskReadySpinLock);
287 Enable();
288 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock, SPINLOCK_MODE_READ);
289 Disable();
290 #endif
291 ForeachNode(&SysBase->TaskWait, t)
293 if (task == t)
295 #if defined(__AROSEXEC_SMP__)
296 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock);
297 Enable();
298 #else
299 Permit();
300 #endif
301 return TRUE;
304 #if defined(__AROSEXEC_SMP__)
305 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock);
306 Enable();
307 #else
308 Permit();
309 #endif
311 return FALSE;