Port the SB128 code to AROS.
[AROS.git] / rom / exec / remtask.c
blob9c8efbac571ef85e86b6001cc87730e8eddaa7b8
1 /*
2 Copyright 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Remove a task
6 Lang: english
7 */
9 #include <aros/debug.h>
10 #include <exec/execbase.h>
11 #include <exec/tasks.h>
12 #include <aros/libcall.h>
13 #include <proto/exec.h>
14 #include <proto/kernel.h>
16 #include <aros/symbolsets.h>
18 #include "etask.h"
19 #include "exec_intern.h"
20 #include "exec_util.h"
21 #include "exec_debug.h"
23 /*****************************************************************************
25 NAME */
27 AROS_LH1(void, RemTask,
29 /* SYNOPSIS */
30 AROS_LHA(struct Task *, task, A1),
32 /* LOCATION */
33 struct ExecBase *, SysBase, 48, Exec)
35 /* FUNCTION
36 Remove a task from the task lists. All memory in the tc_MemEntry list
37 is freed and a rescedule is done. It's safe to call RemTask() out
38 of Forbid() or Disable().
39 This function is one way to get rid of the current task. The other way
40 is to fall through the end of the entry point.
42 INPUTS
43 task - Task to be removed. NULL means current task.
45 RESULT
47 NOTES
49 EXAMPLE
51 BUGS
53 SEE ALSO
54 AddTask()
56 INTERNALS
58 HISTORY
60 ******************************************************************************/
62 AROS_LIBFUNC_INIT
63 struct ETask *et;
65 /* A value of NULL means current task */
66 if (task==NULL)
67 task=SysBase->ThisTask;
69 DREMTASK("RemTask (0x%p (\"%s\"))", task, task->tc_Node.ln_Name);
71 if (task == SysBase->ThisTask)
72 DREMTASK("Removing itself");
74 /* Don't let any other task interfere with us at the moment
76 Forbid();
78 /* Remove() here, before freeing the MemEntry list. Because
79 the MemEntry list might contain the task struct itself! */
81 if(task != SysBase->ThisTask)
83 Remove(&task->tc_Node);
87 * The task is being removed.
88 * This is an important signal for Alert() which will not attempt to use
89 * the context which is being deleted, for example.
91 task->tc_State = TS_REMOVED;
93 /* Uninitialize ETask structure */
94 et = GetETask(task);
95 if(et != NULL)
97 KrnDeleteContext(((struct IntETask *)et)->iet_Context);
98 CleanupETask(task, et);
102 * Send task to task cleaner to clean up memory.
103 * This avoids ripping memory from underneath a running Task.
104 * Message is basically a Node, so we use our task's tc_Node as a message.
105 * We use InternalPutMsg() because it won't change ln_Type. Just in case...
107 InternalPutMsg(((struct IntExecBase *)SysBase)->RemTaskPort, (struct Message *)task, SysBase);
109 /* Freeing myself? */
110 if(task==SysBase->ThisTask)
112 /* Changing the task lists always needs a Disable(). */
113 Disable();
116 Since I don't know how many levels of Forbid()
117 are already pending I set a default value.
119 SysBase->TDNestCnt = -1;
121 /* And force a task switch. Note: Dispatch, not Switch,
122 because the state of ThisTask must not be saved
125 KrnDispatch();
126 /* Does not return. */
129 /* All done. */
130 Permit();
132 DREMTASK("Success");
134 AROS_LIBFUNC_EXIT
137 static void remtaskcleaner(void)
139 struct MemList *mb, *mbnext;
140 struct IntExecBase *IntSysBase = (struct IntExecBase *)SysBase;
142 DREMTASK("remtaskcleaner RemTaskPort created");
145 { /* forever */
146 struct List list;
147 struct Task *task;
149 WaitPort(IntSysBase->RemTaskPort);
150 task = (struct Task *)GetMsg(IntSysBase->RemTaskPort);
152 DREMTASK("remtaskcleaner for task %p", task);
154 /* Note tc_MemEntry list is part of the task structure which
155 usually is also placed in tc_MemEntry. MungWall_Check()
156 will fill freed memory and destroy our list while we are
157 iterating or the freed memory including our list could be
158 reused by some other task. We take special care of this by
159 copying the list nodes to a local list before freeing.
160 Alternatively, we could check all MemEntries for the task
161 and free it after iterating.
163 NEWLIST(&list);
164 ForeachNodeSafe(&task->tc_MemEntry, mb, mbnext)
166 Remove(&mb->ml_Node);
167 AddTail(&list, &mb->ml_Node);
169 ForeachNodeSafe(&list, mb, mbnext)
171 DREMTASK("remtaskcleaner freeing MemList 0x%p", mb);
172 /* Free one MemList node */
173 FreeEntry(mb);
175 } while(1);
178 int __RemTask_Setup(struct ExecBase *SysBase)
180 struct Task *cleaner;
182 /* taskpri is 127, we assume this task will be run before another task
183 calls RemTask()
185 cleaner = NewCreateTask(TASKTAG_NAME , "__RemTask_Cleaner__",
186 TASKTAG_PRI , 127,
187 TASKTAG_PC , remtaskcleaner,
188 TASKTAG_TASKMSGPORT, &((struct IntExecBase *)SysBase)->RemTaskPort,
189 TAG_DONE);
191 if (!cleaner)
193 DREMTASK("__RemTask_Setup task creation failed !");
194 return 0;
196 DREMTASK("__RemTask_Setup cleaner task created");
198 return 1;
201 ADD2INITLIB(__RemTask_Setup, 0);