Check if volumes are bootable by checking whether C/Shell is compatible with
[cake.git] / rom / exec / exec_util.c
blobb1c03e8aa9bb5543714b60c7d166ff5afded5afd
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Exec utility functions.
6 Lang: english
7 */
8 #include <exec/lists.h>
9 #include <exec/tasks.h>
10 #include <exec/memory.h>
11 #include <exec/execbase.h>
12 #include <dos/dosextens.h>
14 #include <proto/exec.h>
16 #include "etask.h"
17 #include "exec_util.h"
19 /*****************************************************************************
21 NAME */
22 #include "exec_util.h"
24 APTR Exec_AllocTaskMem (
26 /* SYNOPSIS */
27 struct Task * task,
28 ULONG size,
29 ULONG req,
30 struct ExecBase *SysBase)
32 /* FUNCTION
33 Allocate memory which will be freed when the task is removed.
35 INPUTS
36 task - The memory will be freed when this task is removed.
37 size - How much memory.
38 req - What memory. See AllocMem() for details.
40 RESULT
41 Adress to a memory block or NULL if no memory was available.
43 NOTES
45 EXAMPLE
47 BUGS
49 SEE ALSO
50 AllocMem(), FreeTaskMem()
52 INTERNALS
53 The memory is allocated and queued in the tc_MemList. This
54 list is freed in RemTask().
56 ******************************************************************************/
58 struct MemList * ml;
59 APTR mem;
61 ml = AllocMem (sizeof (struct MemList), MEMF_ANY);
62 mem = AllocMem (size, req);
64 if (!ml || !mem)
66 if (ml)
67 FreeMem (ml, sizeof (struct MemList));
69 if (mem)
70 FreeMem (mem, size);
72 return NULL;
75 ml->ml_NumEntries = 1;
76 ml->ml_ME[0].me_Addr = mem;
77 ml->ml_ME[0].me_Length = size;
79 Forbid ();
80 AddHead (&task->tc_MemEntry, &ml->ml_Node);
81 Permit ();
83 return mem;
84 } /* AllocTaskMem */
87 /*****************************************************************************
89 NAME */
90 #include "exec_util.h"
92 void Exec_FreeTaskMem (
94 /* SYNOPSIS */
95 struct Task * task,
96 APTR mem,
97 struct ExecBase *SysBase)
99 /* FUNCTION
100 Freeate memory which will be freed when the task is removed.
102 INPUTS
103 task - The memory will be freed when this task is removed.
104 size - How much memory.
105 req - What memory. See FreeMem() for details.
107 RESULT
108 Adress to a memory block or NULL if no memory was available.
110 NOTES
112 EXAMPLE
114 BUGS
116 SEE ALSO
117 FreeMem(), FreeTaskMem()
119 INTERNALS
120 The memory is allocated and queued in the tc_MemList. This
121 list is freed in RemTask().
123 ******************************************************************************/
125 struct MemList * ml, * next;
127 Forbid ();
129 ForeachNodeSafe (&task->tc_MemEntry, ml, next)
132 Quick check: If the node was allocated by AllocTaskMem(),
133 then it has only one entry.
135 if (ml->ml_NumEntries == 1
136 && ml->ml_ME[0].me_Addr == mem
139 Remove (&ml->ml_Node);
140 Permit ();
142 FreeMem (ml->ml_ME[0].me_Addr, ml->ml_ME[0].me_Length);
143 FreeMem (ml, sizeof (struct MemList));
145 return;
149 Permit ();
151 } /* FreeTaskMem */
153 /*****************************************************************************
155 NAME */
156 #include "exec_util.h"
158 struct Task * Exec_FindTaskByID(
160 /* SYNOPSIS */
161 ULONG id,
162 struct ExecBase *SysBase)
164 /* FUNCTION
165 Scan through the task lists searching for the task whose
166 et_UniqueID field matches.
168 INPUTS
169 id - The task ID to match.
171 RESULT
172 Address of the Task control structure that matches, or
173 NULL otherwise.
175 NOTES
177 EXAMPLE
179 BUGS
181 SEE ALSO
183 INTERNALS
185 ******************************************************************************/
187 struct Task *t;
188 struct ETask *et;
191 First up, check ThisTask. It could be NULL because of exec_init.c
193 if (SysBase->ThisTask != NULL)
195 et = GetETask(SysBase->ThisTask);
196 if (et != NULL && et->et_UniqueID == id)
197 return SysBase->ThisTask;
200 /* Next, go through the ready list */
201 ForeachNode(&SysBase->TaskReady, t)
203 et = GetETask(t);
204 if (et != NULL && et->et_UniqueID == id)
205 return t;
208 /* Finally, go through the wait list */
209 ForeachNode(&SysBase->TaskWait, t)
211 et = GetETask(t);
212 if (et != NULL && et->et_UniqueID == id)
213 return t;
216 return NULL;
219 /*****************************************************************************
221 NAME */
222 #include "exec_util.h"
224 struct ETask * Exec_FindChild(
226 /* SYNOPSIS */
227 ULONG id,
228 struct ExecBase *SysBase)
230 /* FUNCTION
231 Scan through the current tasks children list searching for the task
232 whose et_UniqueID field matches.
234 INPUTS
235 id - The task ID to match.
237 RESULT
238 Address of the ETask structure that matches, or
239 NULL otherwise.
241 NOTES
243 EXAMPLE
245 BUGS
247 SEE ALSO
249 INTERNALS
251 ******************************************************************************/
253 struct ETask *et;
254 struct ETask *thisET;
256 thisET = GetETask(FindTask(NULL));
257 if (thisET != NULL)
259 ForeachNode (&thisET->et_Children, et)
261 if (et->et_UniqueID == id)
262 return et;
264 ForeachNode(&thisET->et_TaskMsgPort.mp_MsgList, et)
266 if (et->et_UniqueID == id)
267 return et;
270 return NULL;
273 void
274 Exec_InitETask(struct Task *task, struct ETask *et, struct ExecBase *SysBase)
276 et->et_Parent = FindTask(NULL);
277 NEWLIST(&et->et_Children);
279 /* Initialise the message list */
280 NEWLIST(&et->et_TaskMsgPort.mp_MsgList);
281 et->et_TaskMsgPort.mp_Flags = PA_SIGNAL;
282 et->et_TaskMsgPort.mp_Node.ln_Type = NT_MSGPORT;
283 et->et_TaskMsgPort.mp_SigTask = task;
284 et->et_TaskMsgPort.mp_SigBit = SIGB_CHILD;
286 /* Initialise the trap fields */
287 et->et_TrapAlloc = SysBase->TaskTrapAlloc;
288 et->et_TrapAble = 0;
290 #ifdef DEBUG_ETASK
292 int len = strlen(task->tc_Node.ln_Name) + 1;
293 IntETask(et)->iet_Me = AllocVec(len, MEMF_CLEAR|MEMF_PUBLIC);
294 if (IntETask(et)->iet_Me != NULL)
295 CopyMem(task->tc_Node.ln_Name, IntETask(et)->iet_Me, len);
297 #endif
299 /* Get an unique identifier for this task */
300 Forbid();
301 while(et->et_UniqueID == 0)
304 * Add some fuzz on wrapping. Its likely that the early numbers
305 * where taken by somebody else.
307 if(++SysBase->ex_TaskID == 0)
308 SysBase->ex_TaskID = 1024;
310 Disable();
311 if(Exec_FindTaskByID(SysBase->ex_TaskID, SysBase) == NULL)
312 et->et_UniqueID = SysBase->ex_TaskID;
313 Enable();
315 Permit();
317 /* Finally if the parent task is an ETask, add myself as its child */
318 if(et->et_Parent && ((struct Task*) et->et_Parent)->tc_Flags & TF_ETASK)
320 Forbid();
321 ADDHEAD(&GetETask(et->et_Parent)->et_Children, et);
322 Permit();
326 void
327 Exec_CleanupETask(struct Task *task, struct ETask *et, struct ExecBase *SysBase)
329 struct ETask *child, *parent;
330 struct Node *tmpNode;
331 if(!et)
332 return;
334 /* Clean up after all the children that the task didn't do itself. */
335 ForeachNodeSafe(&et->et_TaskMsgPort.mp_MsgList, child, tmpNode)
337 /* This is effectively ChildFree() */
338 if(child->et_Result2)
339 FreeVec(child->et_Result2);
340 #ifdef DEBUG_ETASK
341 FreeVec(child->iet_Me);
342 #endif
343 FreeVec(child);
346 /* Orphan all our remaining children. */
347 #warning FIXME: should we link the children to our parent?
348 ForeachNode(&et->et_Children, child)
349 child->et_Parent = NULL;
351 /* If we have an ETask parent, tell it we have exited. */
352 if(et->et_Parent != NULL)
354 parent = GetETask(et->et_Parent);
355 /* Nofity parent only if child was created with NP_NotifyOnDeath set
356 to TRUE */
358 parent != NULL &&
359 (((struct Task *)task)->tc_Node.ln_Type == NT_PROCESS) &&
360 (((struct Process*) task)->pr_Flags & PRF_NOTIFYONDEATH)
363 REMOVE(et);
364 PutMsg(&parent->et_TaskMsgPort, et);
366 else if(parent != NULL)
368 #ifdef DEBUG_ETASK
369 FreeVec(et->iet_Me);
370 #endif
371 REMOVE(et);
372 FreeVec(et);
374 else
376 #ifdef DEBUG_ETASK
377 FreeVec(et->iet_Me);
378 #endif
379 FreeVec(et);
382 else
384 #ifdef DEBUG_ETASK
385 FreeVec(et->iet_Me);
386 #endif
387 FreeVec(et);