- Fixed potential memory leaks and use of freed memory.
[AROS.git] / rom / exec / remtask.c
blobe3fa71fbe95e265810a9052b6cce2a76d0b98e98
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 BOOL suicide;
65 #if defined(__AROSEXEC_SMP__)
66 spinlock_t *task_listlock = NULL;
67 #endif
69 /* A value of NULL means current task */
70 if (task==NULL)
71 task=GET_THIS_TASK;
73 DREMTASK("RemTask (0x%p (\"%s\"))", task, task->tc_Node.ln_Name);
75 /* Don't let any other task interfere with us at the moment
77 #if !defined(__AROSEXEC_SMP__)
78 Forbid();
79 #endif
81 suicide = (task == GET_THIS_TASK);
82 if (suicide)
83 DREMTASK("Removing itself");
85 /* Remove() here, before freeing the MemEntry list. Because
86 the MemEntry list might contain the task struct itself! */
88 if (!suicide)
90 #if defined(__AROSEXEC_SMP__)
91 switch (task->tc_State)
93 case TS_RUN:
94 task_listlock =&PrivExecBase(SysBase)->TaskRunningSpinLock;
95 break;
96 case TS_WAIT:
97 task_listlock = &PrivExecBase(SysBase)->TaskWaitSpinLock;
98 break;
99 default:
100 task_listlock = &PrivExecBase(SysBase)->TaskReadySpinLock;
101 break;
103 EXEC_SPINLOCK_LOCK(task_listlock, SPINLOCK_MODE_WRITE);
104 Disable();
105 #endif
106 Remove(&task->tc_Node);
107 #if defined(__AROSEXEC_SMP__)
108 EXEC_SPINLOCK_UNLOCK(task_listlock);
109 #endif
113 * The task is being removed.
114 * This is an important signal for Alert() which will not attempt to use
115 * the context which is being deleted, for example.
117 task->tc_State = TS_REMOVED;
119 /* Delete context */
120 et = GetETask(task);
121 if (et != NULL)
122 KrnDeleteContext(et->et_RegFrame);
124 /* Uninitialize ETask structure */
125 DREMTASK("Cleaning up ETask et=%p", et);
126 CleanupETask(task);
128 /* Freeing myself? */
129 if (suicide)
132 * Send task to task cleaner to clean up memory. This avoids ripping
133 * memory from underneath a running Task. Message is basically a
134 * Node, so we use our task's tc_Node as a message. We use
135 * InternalPutMsg() because it won't change ln_Type. Just in case...
137 DREMTASK("Sending to garbage man");
138 InternalPutMsg(((struct IntExecBase *)SysBase)->ServicePort,
139 (struct Message *)task, SysBase);
141 #if !defined(__AROSEXEC_SMP__)
142 /* Changing the task lists always needs a Disable(). */
143 Disable();
144 #endif
147 Since I don't know how many levels of Forbid()
148 are already pending I set a default value.
150 TDNESTCOUNT_SET(-1);
152 /* And force a task switch. Note: Dispatch, not Switch,
153 because the state of ThisTask must not be saved
156 KrnDispatch();
157 /* Does not return. */
159 else
162 * Free all memory in the tc_MemEntry list.
163 * We do this here because it's unsafe to send it to the service task:
164 * by the time the service task processes it, the task structure may
165 * have been freed following the return of this function.
167 while((mb = (struct MemList *) RemHead(&task->tc_MemEntry)) != NULL)
168 FreeEntry(mb);
171 /* All done. */
172 #if defined(__AROSEXEC_SMP__)
173 if (task_listlock)
174 Enable();
175 #else
176 Permit();
177 #endif
179 DREMTASK("Success");
181 AROS_LIBFUNC_EXIT