Test initialisation of MUIA_List_AdjustWidth and MUIA_List_AdjustHeight, and
[AROS.git] / rom / exec / exec_util.c
blobe814f96bac6a72cc22c634774490b8c548def35f
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 #endif
248 Forbid();
250 #if defined(__AROSEXEC_SMP__)
251 ForeachNode(&PrivExecBase(SysBase)->TaskRunning, t)
253 if (task == t)
255 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskRunningSpinLock);
256 Permit();
257 return TRUE;
260 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskRunningSpinLock);
261 Permit();
262 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskSpinningLock, SPINLOCK_MODE_READ);
263 Forbid();
264 ForeachNode(&PrivExecBase(SysBase)->TaskSpinning, t)
266 if (task == t)
268 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskSpinningLock);
269 Permit();
270 return TRUE;
273 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskSpinningLock);
274 Permit();
275 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskReadySpinLock, SPINLOCK_MODE_READ);
276 Forbid();
277 #else
278 if (task == GET_THIS_TASK)
280 Permit();
281 return TRUE;
283 #endif
285 ForeachNode(&SysBase->TaskReady, t)
287 if (task == t)
289 #if defined(__AROSEXEC_SMP__)
290 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskReadySpinLock);
291 #endif
292 Permit();
293 return TRUE;
296 #if defined(__AROSEXEC_SMP__)
297 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskReadySpinLock);
298 Permit();
299 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock, SPINLOCK_MODE_READ);
300 Forbid();
301 #endif
302 ForeachNode(&SysBase->TaskWait, t)
304 if (task == t)
306 #if defined(__AROSEXEC_SMP__)
307 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock);
308 #endif
309 Permit();
310 return TRUE;
313 #if defined(__AROSEXEC_SMP__)
314 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock);
315 #endif
316 Permit();
318 return FALSE;