use GET_THIS_TASK internally throughout exec - since it will result in faster/smaller...
[AROS.git] / rom / exec / remtask.c
blob9a240cbe1d94a3f241a4ffe5fbc7e6ea28e00514
1 /*
2 Copyright © 1995-2015, 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>
15 #include <aros/symbolsets.h>
17 #include "etask.h"
18 #include "exec_intern.h"
19 #include "exec_util.h"
20 #include "exec_debug.h"
22 /*****************************************************************************
24 NAME */
26 AROS_LH1(void, RemTask,
28 /* SYNOPSIS */
29 AROS_LHA(struct Task *, task, A1),
31 /* LOCATION */
32 struct ExecBase *, SysBase, 48, Exec)
34 /* FUNCTION
35 Remove a task from the task lists. All memory in the tc_MemEntry list
36 is freed and a reschedule is done. It's safe to call RemTask() outside
37 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 ******************************************************************************/
60 AROS_LIBFUNC_INIT
62 struct MemList *mb;
63 struct ETask *et;
64 #if defined(__AROSEXEC_SMP__)
65 spinlock_t *task_listlock = NULL;
66 #endif
67 struct Task *suicide = GET_THIS_TASK;
69 /* A value of NULL means current task */
70 if (task == NULL)
71 task = suicide;
73 DREMTASK("RemTask (0x%p (\"%s\"))", task, task->tc_Node.ln_Name);
75 #if !defined(__AROSEXEC_SMP__)
76 /* Don't let any other task interfere with us at the moment */
77 Forbid();
78 #endif
80 if (suicide == task)
82 DREMTASK("Removing itself");
84 else
87 * Remove() here, before freeing the MemEntry list. Because
88 * the MemEntry list might contain the task struct itself!
90 #if defined(__AROSEXEC_SMP__)
91 switch (task->tc_State)
93 case TS_SPIN:
94 task_listlock =&PrivExecBase(SysBase)->TaskSpinningLock;
95 break;
96 case TS_RUN:
97 task_listlock =&PrivExecBase(SysBase)->TaskRunningSpinLock;
98 break;
99 case TS_WAIT:
100 task_listlock = &PrivExecBase(SysBase)->TaskWaitSpinLock;
101 break;
102 default:
103 task_listlock = &PrivExecBase(SysBase)->TaskReadySpinLock;
104 break;
106 EXEC_SPINLOCK_LOCK(task_listlock, SPINLOCK_MODE_WRITE);
107 Forbid();
108 #endif
109 Remove(&task->tc_Node);
110 #if defined(__AROSEXEC_SMP__)
111 EXEC_SPINLOCK_UNLOCK(task_listlock);
112 #endif
116 * The task is being removed.
117 * This is an important signal for Alert() which will not attempt to use
118 * the context which is being deleted, for example.
120 task->tc_State = TS_REMOVED;
122 /* Delete context */
123 et = GetETask(task);
124 if (et != NULL)
125 KrnDeleteContext(et->et_RegFrame);
127 /* Uninitialize ETask structure */
128 DREMTASK("Cleaning up ETask et=%p", et);
129 CleanupETask(task);
131 /* Freeing itself? */
132 if (suicide == task)
135 * Send task to task cleaner to clean up memory. This avoids ripping
136 * memory from underneath a running Task. Message is basically a
137 * Node, so we use our task's tc_Node as a message. We use
138 * InternalPutMsg() because it won't change ln_Type. Just in case...
140 DREMTASK("Sending to garbage man");
141 InternalPutMsg(((struct IntExecBase *)SysBase)->ServicePort,
142 (struct Message *)task, SysBase);
144 /* Changing the task lists always needs a Disable(). */
145 Disable();
148 * We don't know how many levels of Forbid()
149 * are already pending, so use a default value.
151 TDNESTCOUNT_SET(-1);
154 * Force rescheduling.
155 * Note #1: We dont want to preseve the task context so use Dispatch, not Switch.
156 * Note #2: We will never return from the dispatch to "ThisTask"
159 KrnDispatch();
161 else
164 * Free all memory in the tc_MemEntry list.
165 * We do this here because it's unsafe to send it to the service task:
166 * by the time the service task processes it, the task structure may
167 * have been freed following the return of this function.
169 while((mb = (struct MemList *) RemHead(&task->tc_MemEntry)) != NULL)
170 FreeEntry(mb);
173 /* All done. */
174 Permit();
176 DREMTASK("Success");
178 AROS_LIBFUNC_EXIT