use GET_THIS_TASK internally throughout exec - since it will result in faster/smaller...
[AROS.git] / rom / exec / exec_util.c
bloba1809f59491d012013d728ec09cdc3d8a5f59bea
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 Task *ThisTask = GET_THIS_TASK;
60 struct ETask *et;
61 struct ETask *thisET;
63 thisET = GetETask(ThisTask);
64 if (thisET != NULL)
66 ForeachNode (&thisET->et_Children, et)
68 if (et->et_UniqueID == id)
69 return et;
71 ForeachNode(&thisET->et_TaskMsgPort.mp_MsgList, et)
73 if (et->et_UniqueID == id)
74 return et;
77 return NULL;
80 BOOL
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.
88 struct ETask *et =
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;
95 if (!et)
96 return FALSE;
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);
102 #endif
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;
114 et->et_TrapAble = 0;
116 #ifdef DEBUG_ETASK
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);
123 #endif
125 /* Get a unique identifier for this task */
126 Forbid();
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;
136 Disable();
137 if (FindTaskByPID(SysBase->ex_TaskID) == NULL)
138 et->et_UniqueID = SysBase->ex_TaskID;
139 Enable();
141 Permit();
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)
146 Forbid();
147 ADDHEAD(&GetETask(et->et_Parent)->et_Children, et);
148 Permit();
151 return TRUE;
154 void
155 Exec_CleanupETask(struct Task *task, struct ExecBase *SysBase)
157 struct ETask *et = NULL, *child, *nextchild, *parent;
158 struct Node *tmpNode;
159 BOOL expunge = TRUE;
161 if(task->tc_Flags & TF_ETASK)
162 et = task->tc_UnionETask.tc_ETask;
163 if(!et)
164 return;
166 D(bug("[EXEC:ETask] Cleanup: Task @ 0x%p, ETask @ 0x%p\n", task, et));
168 Forbid();
170 /* Clean up after all the children that the task didn't do itself. */
171 ForeachNodeSafe(&et->et_TaskMsgPort.mp_MsgList, child, tmpNode)
173 ExpungeETask(child);
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;
185 //Forbid();
186 if (parent)
187 ADDTAIL(&parent->et_Children, child);
188 //Permit();
191 /* Notify parent only if child was created with NP_NotifyOnDeath set
192 to TRUE */
193 if(parent != NULL)
195 REMOVE(et);
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);
203 expunge = FALSE;
207 else
209 /* Orphan all our remaining children. */
210 ForeachNode(&et->et_Children, child)
211 child->et_Parent = NULL;
214 if(expunge)
215 ExpungeETask(et);
217 Permit();
220 void
221 Exec_ExpungeETask(struct ETask *et, struct ExecBase *SysBase)
223 IPTR *ts = et->et_TaskStorage;
225 FreeVec(et->et_Result2);
227 #ifdef DEBUG_ETASK
228 FreeVec(IntETask(et)->iet_Me);
229 #endif
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));
234 if (ts)
235 FreeMem(ts, ts[__TS_FIRSTSLOT] * sizeof(ts[0]));
238 BOOL Exec_CheckTask(struct Task *task, struct ExecBase *SysBase)
240 struct Task *t;
242 if (!task)
243 return FALSE;
245 #if defined(__AROSEXEC_SMP__)
246 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskRunningSpinLock, SPINLOCK_MODE_READ);
247 Disable();
248 #else
249 Forbid();
250 #endif
252 #if defined(__AROSEXEC_SMP__)
253 ForeachNode(&PrivExecBase(SysBase)->TaskRunning, t)
255 if (task == t)
257 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskRunningSpinLock);
258 Enable();
259 return TRUE;
262 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskRunningSpinLock);
263 Enable();
264 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskReadySpinLock, SPINLOCK_MODE_READ);
265 Disable();
266 #else
267 if (task == GET_THIS_TASK)
269 Permit();
270 return TRUE;
272 #endif
274 ForeachNode(&SysBase->TaskReady, t)
276 if (task == t)
278 #if defined(__AROSEXEC_SMP__)
279 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskReadySpinLock);
280 Enable();
281 #else
282 Permit();
283 #endif
284 return TRUE;
287 #if defined(__AROSEXEC_SMP__)
288 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskReadySpinLock);
289 Enable();
290 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock, SPINLOCK_MODE_READ);
291 Disable();
292 #endif
293 ForeachNode(&SysBase->TaskWait, t)
295 if (task == t)
297 #if defined(__AROSEXEC_SMP__)
298 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock);
299 Enable();
300 #else
301 Permit();
302 #endif
303 return TRUE;
306 #if defined(__AROSEXEC_SMP__)
307 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock);
308 Enable();
309 #else
310 Permit();
311 #endif
313 return FALSE;