Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / rom / exec / exec_util.c
blobaa61f1baa613c59f3d9c2396a02be949e1a584d2
1 /*
2 Copyright © 1995-2011, 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_intern.h"
18 #include "exec_util.h"
21 * TODO: The following two functions are subject to removal.
22 * They are used only by i386-pc port for allocating CPU context.
23 * This needs to be changed.
26 /*****************************************************************************
28 NAME */
29 #include "exec_util.h"
31 APTR Exec_AllocTaskMem (
33 /* SYNOPSIS */
34 struct Task * task,
35 ULONG size,
36 ULONG req,
37 struct ExecBase *SysBase)
39 /* FUNCTION
40 Allocate memory which will be freed when the task is removed.
42 INPUTS
43 task - The memory will be freed when this task is removed.
44 size - How much memory.
45 req - What memory. See AllocMem() for details.
47 RESULT
48 Adress to a memory block or NULL if no memory was available.
50 NOTES
52 EXAMPLE
54 BUGS
56 SEE ALSO
57 AllocMem(), FreeTaskMem()
59 INTERNALS
60 The memory is allocated and queued in the tc_MemList. This
61 list is freed in RemTask().
63 ******************************************************************************/
65 struct MemList * ml;
66 APTR mem;
68 ml = AllocMem (sizeof (struct MemList), MEMF_ANY);
69 mem = AllocMem (size, req);
71 if (!ml || !mem)
73 if (ml)
74 FreeMem (ml, sizeof (struct MemList));
76 if (mem)
77 FreeMem (mem, size);
79 return NULL;
82 ml->ml_NumEntries = 1;
83 ml->ml_ME[0].me_Addr = mem;
84 ml->ml_ME[0].me_Length = size;
86 Forbid ();
87 AddHead (&task->tc_MemEntry, &ml->ml_Node);
88 Permit ();
90 return mem;
91 } /* AllocTaskMem */
94 /*****************************************************************************
96 NAME */
97 #include "exec_util.h"
99 void Exec_FreeTaskMem (
101 /* SYNOPSIS */
102 struct Task * task,
103 APTR mem,
104 struct ExecBase *SysBase)
106 /* FUNCTION
107 Freeate memory which will be freed when the task is removed.
109 INPUTS
110 task - The memory will be freed when this task is removed.
111 size - How much memory.
112 req - What memory. See FreeMem() for details.
114 RESULT
115 Adress to a memory block or NULL if no memory was available.
117 NOTES
119 EXAMPLE
121 BUGS
123 SEE ALSO
124 FreeMem(), FreeTaskMem()
126 INTERNALS
127 The memory is allocated and queued in the tc_MemList. This
128 list is freed in RemTask().
130 ******************************************************************************/
132 struct MemList * ml, * next;
134 Forbid ();
136 ForeachNodeSafe (&task->tc_MemEntry, ml, next)
139 Quick check: If the node was allocated by AllocTaskMem(),
140 then it has only one entry.
142 if (ml->ml_NumEntries == 1
143 && ml->ml_ME[0].me_Addr == mem
146 Remove (&ml->ml_Node);
147 Permit ();
149 FreeMem (ml->ml_ME[0].me_Addr, ml->ml_ME[0].me_Length);
150 FreeMem (ml, sizeof (struct MemList));
152 return;
156 Permit ();
158 } /* FreeTaskMem */
160 /*****************************************************************************
162 NAME */
163 #include "exec_util.h"
165 struct ETask * Exec_FindChild(
167 /* SYNOPSIS */
168 ULONG id,
169 struct ExecBase *SysBase)
171 /* FUNCTION
172 Scan through the current tasks children list searching for the task
173 whose et_UniqueID field matches.
175 INPUTS
176 id - The task ID to match.
178 RESULT
179 Address of the ETask structure that matches, or
180 NULL otherwise.
182 NOTES
184 EXAMPLE
186 BUGS
188 SEE ALSO
190 INTERNALS
192 ******************************************************************************/
194 struct ETask *et;
195 struct ETask *thisET;
197 thisET = GetETask(FindTask(NULL));
198 if (thisET != NULL)
200 ForeachNode (&thisET->et_Children, et)
202 if (et->et_UniqueID == id)
203 return et;
205 ForeachNode(&thisET->et_TaskMsgPort.mp_MsgList, et)
207 if (et->et_UniqueID == id)
208 return et;
211 return NULL;
214 void
215 Exec_InitETask(struct Task *task, struct ETask *et, struct ExecBase *SysBase)
217 et->et_Parent = FindTask(NULL);
218 NEWLIST(&et->et_Children);
220 /* Initialise the message list */
221 InitMsgPort(&et->et_TaskMsgPort);
222 et->et_TaskMsgPort.mp_SigTask = task;
223 et->et_TaskMsgPort.mp_SigBit = SIGB_CHILD;
225 /* Initialise the trap fields */
226 et->et_TrapAlloc = SysBase->TaskTrapAlloc;
227 et->et_TrapAble = 0;
229 #ifdef DEBUG_ETASK
231 int len = strlen(task->tc_Node.ln_Name) + 1;
232 IntETask(et)->iet_Me = AllocVec(len, MEMF_CLEAR|MEMF_PUBLIC);
233 if (IntETask(et)->iet_Me != NULL)
234 CopyMem(task->tc_Node.ln_Name, IntETask(et)->iet_Me, len);
236 #endif
238 /* Get an unique identifier for this task */
239 Forbid();
240 while(et->et_UniqueID == 0)
243 * Add some fuzz on wrapping. Its likely that the early numbers
244 * where taken by somebody else.
246 if(++SysBase->ex_TaskID == 0)
247 SysBase->ex_TaskID = 1024;
249 Disable();
250 if (FindTaskByPID(SysBase->ex_TaskID) == NULL)
251 et->et_UniqueID = SysBase->ex_TaskID;
252 Enable();
254 Permit();
256 /* Finally if the parent task is an ETask, add myself as its child */
257 if(et->et_Parent && ((struct Task*) et->et_Parent)->tc_Flags & TF_ETASK)
259 Forbid();
260 ADDHEAD(&GetETask(et->et_Parent)->et_Children, et);
261 Permit();
265 void
266 Exec_CleanupETask(struct Task *task, struct ETask *et, struct ExecBase *SysBase)
268 struct ETask *child, *nextchild, *parent;
269 struct Node *tmpNode;
270 if(!et)
271 return;
273 Forbid();
275 /* Clean up after all the children that the task didn't do itself. */
276 ForeachNodeSafe(&et->et_TaskMsgPort.mp_MsgList, child, tmpNode)
278 /* This is effectively ChildFree() */
279 if(child->et_Result2)
280 FreeVec(child->et_Result2);
281 #ifdef DEBUG_ETASK
282 FreeVec(child->iet_Me);
283 #endif
284 FreeVec(child);
287 /* If we have an ETask parent, tell it we have exited. */
288 if(et->et_Parent != NULL)
290 parent = GetETask(et->et_Parent);
292 /* Link children to our parent. */
293 ForeachNodeSafe(&et->et_Children, child, nextchild)
295 child->et_Parent = et->et_Parent;
296 //Forbid();
297 ADDTAIL(&parent->et_Children, child);
298 //Permit();
301 /* Notify parent only if child was created with NP_NotifyOnDeath set
302 to TRUE */
304 parent != NULL &&
305 (((struct Task *)task)->tc_Node.ln_Type == NT_PROCESS) &&
306 (((struct Process*) task)->pr_Flags & PRF_NOTIFYONDEATH)
309 REMOVE(et);
310 PutMsg(&parent->et_TaskMsgPort, (struct Message *)et);
312 else if(parent != NULL)
314 #ifdef DEBUG_ETASK
315 FreeVec(et->iet_Me);
316 #endif
317 REMOVE(et);
318 FreeVec(et);
320 else
322 #ifdef DEBUG_ETASK
323 FreeVec(et->iet_Me);
324 #endif
325 FreeVec(et);
328 else
330 /* Orphan all our remaining children. */
331 ForeachNode(&et->et_Children, child)
332 child->et_Parent = NULL;
334 #ifdef DEBUG_ETASK
335 FreeVec(et->iet_Me);
336 #endif
337 FreeVec(et);
340 Permit();
343 BOOL Exec_CheckTask(struct Task *task, struct ExecBase *SysBase)
345 struct Task *t;
347 if (!task)
348 return FALSE;
350 Forbid();
352 if (task == SysBase->ThisTask)
354 Permit();
355 return TRUE;
358 ForeachNode(&SysBase->TaskReady, t)
360 if (task == t)
362 Permit();
363 return TRUE;
367 ForeachNode(&SysBase->TaskWait, t)
369 if (task == t)
371 Permit();
372 return TRUE;
376 Permit();
377 return FALSE;