pack the compositor capabilities and state into the dimension info
[AROS.git] / rom / exec / exec_util.c
blobf29722b02dc191faf7289f1ef0d954d9ce848243
1 /*
2 Copyright © 1995-2011, 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)
82 struct Task *thistask = FindTask(NULL);
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);
90 D(bug("[TSS] Create new ETask=%p for task=%p with size %d\n",
91 et, task, sizeof(struct IntETask)));
93 task->tc_UnionETask.tc_ETask = et;
94 if (!et)
95 return FALSE;
96 task->tc_Flags |= TF_ETASK;
98 if (thistask != NULL)
100 /* Clone parent's TaskStorage */
101 struct ETask *thiset = GetETask(thistask);
102 if (thiset) {
103 IPTR *thists = thiset->et_TaskStorage;
105 if (thists) {
106 IPTR *ts = AllocMem(thists[__TS_FIRSTSLOT] * sizeof(thists[0]), MEMF_ANY);
107 if (!ts) {
108 FreeMem(et, sizeof(struct IntETask));
109 return FALSE;
111 CopyMem(thists, ts, thists[__TS_FIRSTSLOT] * sizeof(thists[0]));
112 et->et_TaskStorage = ts;
117 et->et_Parent = thistask;
118 NEWLIST(&et->et_Children);
120 /* Initialise the message list */
121 InitMsgPort(&et->et_TaskMsgPort);
122 et->et_TaskMsgPort.mp_SigTask = task;
123 et->et_TaskMsgPort.mp_SigBit = SIGB_CHILD;
125 /* Initialise the trap fields */
126 et->et_TrapAlloc = SysBase->TaskTrapAlloc;
127 et->et_TrapAble = 0;
129 #ifdef DEBUG_ETASK
131 int len = strlen(task->tc_Node.ln_Name) + 1;
132 IntETask(et)->iet_Me = AllocVec(len, MEMF_CLEAR|MEMF_PUBLIC);
133 if (IntETask(et)->iet_Me != NULL)
134 CopyMem(task->tc_Node.ln_Name, IntETask(et)->iet_Me, len);
136 #endif
138 /* Get a unique identifier for this task */
139 Forbid();
140 while(et->et_UniqueID == 0)
143 * Add some fuzz on wrapping. It's likely that the early numbers
144 * where taken by somebody else.
146 if(++SysBase->ex_TaskID == 0)
147 SysBase->ex_TaskID = 1024;
149 Disable();
150 if (FindTaskByPID(SysBase->ex_TaskID) == NULL)
151 et->et_UniqueID = SysBase->ex_TaskID;
152 Enable();
154 Permit();
156 /* Finally if the parent task is an ETask, add myself as its child */
157 if(et->et_Parent && ((struct Task*) et->et_Parent)->tc_Flags & TF_ETASK)
159 Forbid();
160 ADDHEAD(&GetETask(et->et_Parent)->et_Children, et);
161 Permit();
164 return TRUE;
167 void
168 Exec_CleanupETask(struct Task *task, struct ExecBase *SysBase)
170 struct ETask *et = NULL, *child, *nextchild, *parent;
171 struct Node *tmpNode;
172 BOOL expunge = TRUE;
174 if(task->tc_Flags & TF_ETASK)
175 et = task->tc_UnionETask.tc_ETask;
176 if(!et)
177 return;
179 D(bug("CleanupETask: task=%x, et=%x\n", task, et));
181 Forbid();
183 /* Clean up after all the children that the task didn't do itself. */
184 ForeachNodeSafe(&et->et_TaskMsgPort.mp_MsgList, child, tmpNode)
186 ExpungeETask(child);
189 /* If we have an ETask parent, tell it we have exited. */
190 if(et->et_Parent != NULL)
192 parent = GetETask(et->et_Parent);
194 /* Link children to our parent. */
195 ForeachNodeSafe(&et->et_Children, child, nextchild)
197 child->et_Parent = et->et_Parent;
198 //Forbid();
199 if (parent)
200 ADDTAIL(&parent->et_Children, child);
201 //Permit();
204 /* Notify parent only if child was created with NP_NotifyOnDeath set
205 to TRUE */
206 if(parent != NULL)
208 REMOVE(et);
211 (((struct Task *)task)->tc_Node.ln_Type == NT_PROCESS) &&
212 (((struct Process*) task)->pr_Flags & PRF_NOTIFYONDEATH)
215 PutMsg(&parent->et_TaskMsgPort, (struct Message *)et);
216 expunge = FALSE;
220 else
222 /* Orphan all our remaining children. */
223 ForeachNode(&et->et_Children, child)
224 child->et_Parent = NULL;
227 if(expunge)
228 ExpungeETask(et);
230 Permit();
233 void
234 Exec_ExpungeETask(struct ETask *et, struct ExecBase *SysBase)
236 IPTR *ts = et->et_TaskStorage;
238 if(et->et_Result2)
239 FreeVec(et->et_Result2);
241 #ifdef DEBUG_ETASK
242 FreeVec(IntETask(et)->iet_Me);
243 #endif
244 D(bug("Exec_ExpungeETask: Freeing et=%x, ts=%x, size=%d\n",
245 et, ts, ts ? (ULONG)ts[__TS_FIRSTSLOT] : 0
247 FreeMem(et, sizeof(struct IntETask));
248 if (ts)
249 FreeMem(ts, ts[__TS_FIRSTSLOT] * sizeof(ts[0]));
252 BOOL Exec_CheckTask(struct Task *task, struct ExecBase *SysBase)
254 struct Task *t;
256 if (!task)
257 return FALSE;
259 Forbid();
261 if (task == SysBase->ThisTask)
263 Permit();
264 return TRUE;
267 ForeachNode(&SysBase->TaskReady, t)
269 if (task == t)
271 Permit();
272 return TRUE;
276 ForeachNode(&SysBase->TaskWait, t)
278 if (task == t)
280 Permit();
281 return TRUE;
285 Permit();
286 return FALSE;