2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Exec utility functions.
10 #include <aros/debug.h>
11 #include <exec/lists.h>
12 #include <exec/tasks.h>
13 #include <exec/memory.h>
14 #include <exec/execbase.h>
15 #include <dos/dosextens.h>
17 #include <proto/exec.h>
20 #include "exec_intern.h"
21 #include "exec_util.h"
22 #include "taskstorage.h"
24 /*****************************************************************************
27 #include "exec_util.h"
29 struct ETask
* Exec_FindChild(
33 struct ExecBase
*SysBase
)
36 Scan through the current tasks children list searching for the task
37 whose et_UniqueID field matches.
40 id - The task ID to match.
43 Address of the ETask structure that matches, or
56 ******************************************************************************/
61 thisET
= GetETask(FindTask(NULL
));
64 ForeachNode (&thisET
->et_Children
, et
)
66 if (et
->et_UniqueID
== id
)
69 ForeachNode(&thisET
->et_TaskMsgPort
.mp_MsgList
, et
)
71 if (et
->et_UniqueID
== id
)
79 Exec_InitETask(struct Task
*task
, struct ExecBase
*SysBase
)
81 struct Task
*thistask
= FindTask(NULL
);
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 IPTR
*ts
= AllocMem(PrivExecBase(SysBase
)->TaskStorageSize
, MEMF_PUBLIC
|MEMF_CLEAR
);
88 D(bug("[TSS] Create new TS=%x for task=%x with size %d\n",
89 ts
, task
, PrivExecBase(SysBase
)->TaskStorageSize
92 /* IntETask is embedded in TaskStorage */
93 struct ETask
*et
= (struct ETask
*)ts
;
94 task
->tc_UnionETask
.tc_TaskStorage
= ts
;
97 task
->tc_Flags
|= TF_ETASK
;
99 ts
[__TS_FIRSTSLOT
] = (IPTR
)PrivExecBase(SysBase
)->TaskStorageSize
;
100 if (thistask
!= NULL
)
102 /* Clone TaskStorage */
103 CopyMem(&thistask
->tc_UnionETask
.tc_TaskStorage
[__TS_FIRSTSLOT
+1],
104 &task
->tc_UnionETask
.tc_TaskStorage
[__TS_FIRSTSLOT
+1],
105 ((ULONG
)thistask
->tc_UnionETask
.tc_TaskStorage
[__TS_FIRSTSLOT
])-(__TS_FIRSTSLOT
+1)*sizeof(IPTR
)
108 et
->et_Parent
= thistask
;
109 NEWLIST(&et
->et_Children
);
111 /* Initialise the message list */
112 InitMsgPort(&et
->et_TaskMsgPort
);
113 et
->et_TaskMsgPort
.mp_SigTask
= task
;
114 et
->et_TaskMsgPort
.mp_SigBit
= SIGB_CHILD
;
116 /* Initialise the trap fields */
117 et
->et_TrapAlloc
= SysBase
->TaskTrapAlloc
;
122 int len
= strlen(task
->tc_Node
.ln_Name
) + 1;
123 IntETask(et
)->iet_Me
= AllocVec(len
, MEMF_CLEAR
|MEMF_PUBLIC
);
124 if (IntETask(et
)->iet_Me
!= NULL
)
125 CopyMem(task
->tc_Node
.ln_Name
, IntETask(et
)->iet_Me
, len
);
129 /* Get an unique identifier for this task */
131 while(et
->et_UniqueID
== 0)
134 * Add some fuzz on wrapping. Its likely that the early numbers
135 * where taken by somebody else.
137 if(++SysBase
->ex_TaskID
== 0)
138 SysBase
->ex_TaskID
= 1024;
141 if (FindTaskByPID(SysBase
->ex_TaskID
) == NULL
)
142 et
->et_UniqueID
= SysBase
->ex_TaskID
;
147 /* Finally if the parent task is an ETask, add myself as its child */
148 if(et
->et_Parent
&& ((struct Task
*) et
->et_Parent
)->tc_Flags
& TF_ETASK
)
151 ADDHEAD(&GetETask(et
->et_Parent
)->et_Children
, et
);
157 Exec_CleanupETask(struct Task
*task
, struct ExecBase
*SysBase
)
159 struct ETask
*et
= NULL
, *child
, *nextchild
, *parent
;
160 struct Node
*tmpNode
;
163 if(task
->tc_Flags
& TF_ETASK
)
164 et
= task
->tc_UnionETask
.tc_ETask
;
168 D(bug("CleanupETask: task=%x, et=%x\n", task
, et
));
172 /* Clean up after all the children that the task didn't do itself. */
173 ForeachNodeSafe(&et
->et_TaskMsgPort
.mp_MsgList
, child
, tmpNode
)
178 /* If we have an ETask parent, tell it we have exited. */
179 if(et
->et_Parent
!= NULL
)
181 parent
= GetETask(et
->et_Parent
);
183 /* Link children to our parent. */
184 ForeachNodeSafe(&et
->et_Children
, child
, nextchild
)
186 child
->et_Parent
= et
->et_Parent
;
188 ADDTAIL(&parent
->et_Children
, child
);
192 /* Notify parent only if child was created with NP_NotifyOnDeath set
199 (((struct Task
*)task
)->tc_Node
.ln_Type
== NT_PROCESS
) &&
200 (((struct Process
*) task
)->pr_Flags
& PRF_NOTIFYONDEATH
)
203 PutMsg(&parent
->et_TaskMsgPort
, (struct Message
*)et
);
210 /* Orphan all our remaining children. */
211 ForeachNode(&et
->et_Children
, child
)
212 child
->et_Parent
= NULL
;
222 Exec_ExpungeETask(struct ETask
*et
, struct ExecBase
*SysBase
)
224 IPTR
*ts
= (IPTR
*)et
;
227 FreeVec(et
->et_Result2
);
230 FreeVec(IntETask(et
)->iet_Me
);
232 D(bug("Exec_ExpungeETask: Freeing ts=%x, size=%d\n",
233 ts
, (ULONG
)ts
[__TS_FIRSTSLOT
]
235 FreeMem(ts
, (ULONG
)ts
[__TS_FIRSTSLOT
]);
238 static inline void FixList(struct List
*from
, struct List
*to
)
241 * This sequence is incomplete. It is valid only after the whole structure has been copied.
242 * !!! DO NOT remove the second line !!!
243 * If the list is empty, the first line actually modifies from->lh_TailPred, so that
244 * to->lh_TailPred gets correct value !
246 to
->lh_Head
->ln_Pred
= (struct Node
*)&to
->lh_Head
;
247 to
->lh_TailPred
= from
->lh_TailPred
;
248 to
->lh_TailPred
->ln_Succ
= (struct Node
*)&to
->lh_Tail
;
251 BOOL
Exec_ExpandTS(struct Task
*task
, struct ExecBase
*SysBase
)
253 struct Task
*me
= FindTask(NULL
);
254 ULONG oldsize
= task
->tc_UnionETask
.tc_TaskStorage
[__TS_FIRSTSLOT
];
255 struct ETask
*et_old
= task
->tc_UnionETask
.tc_ETask
;
256 struct ETask
*et_new
;
258 D(bug("[TSS] Increasing storage (%d to %d) for task 0x%p (%s)\n", oldsize
, PrivExecBase(SysBase
)->TaskStorageSize
, task
, task
->tc_Node
.ln_Name
));
260 /* Allocate new storage */
261 et_new
= AllocMem(PrivExecBase(SysBase
)->TaskStorageSize
, MEMF_PUBLIC
|MEMF_CLEAR
);
268 * If we are updating ourselves, we need to disable task switching.
269 * Otherwise our ETask can become inconsistent (data in old ETask will
270 * be modified in the middle of copying).
275 /* This copies most of data. */
276 CopyMemQuick(et_old
, et_new
, oldsize
);
278 /* ETask includes lists, and we need to fix up pointers in them now */
279 FixList((struct List
*)&et_old
->et_Children
, (struct List
*)&et_new
->et_Children
);
280 FixList(&et_old
->et_TaskMsgPort
.mp_MsgList
, &et_new
->et_TaskMsgPort
.mp_MsgList
);
282 /* Set new TSS size, and install new ETask */
283 ((IPTR
*)et_new
)[__TS_FIRSTSLOT
] = PrivExecBase(SysBase
)->TaskStorageSize
;
284 task
->tc_UnionETask
.tc_ETask
= et_new
;
288 /* All done, enable multitask again */
292 FreeMem(et_old
, oldsize
);
296 BOOL
Exec_CheckTask(struct Task
*task
, struct ExecBase
*SysBase
)
305 if (task
== SysBase
->ThisTask
)
311 ForeachNode(&SysBase
->TaskReady
, t
)
320 ForeachNode(&SysBase
->TaskWait
, t
)