2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
5 Desc: exec.library's internal service task. Performs memory management according
6 to task scheduler's requests.
10 #include <exec/execbase.h>
11 #include <exec/tasks.h>
12 #include <aros/libcall.h>
13 #include <proto/exec.h>
15 #include "exec_intern.h"
16 #include "exec_util.h"
17 #include "exec_debug.h"
19 void ServiceTask(struct ExecBase
*SysBase
)
21 #if defined(__AROSEXEC_SMP__)
22 struct Task
*serviceTask
;
25 struct MemList
*mb
, *mbnext
;
27 DINIT("ServiceTask: Started up");
29 #if defined(__AROSEXEC_SMP__)
30 serviceTask
= FindTask(NULL
);
31 DINIT("ServiceTask: task @ 0x%p", serviceTask
);
38 while ((task
= (struct Task
*)GetMsg(PrivExecBase(SysBase
)->ServicePort
)))
40 DREMTASK("ServiceTask: Request for Task 0x%p, State %08X\n", task
, task
->tc_State
);
44 * If we ever need to use TSS here, we'll need to explicitly check its size here.
45 * However we don't need this, because we never call so high-level libraries.
46 * So, currently we ignore this.
49 switch (task
->tc_State
)
51 #if defined(__AROSEXEC_SMP__)
53 if (!(PrivExecBase(SysBase
)->IntFlags
& EXECF_CPUAffinity
) || (GetIntETask(serviceTask
)->iet_CpuNumber
== (IPTR
)task
->tc_UserData
))
55 DREMTASK("ServiceTask: Task is running on this CPU (%03u)\n", task
->tc_UserData
);
62 DREMTASK("ServiceTask: Requeueing request for Task 0x%p <%s> (State:%08x)", task
, task
->tc_Node
.ln_Name
, task
->tc_State
);
63 InternalPutMsg(PrivExecBase(SysBase
)->ServicePort
,
64 (struct Message
*)task
, SysBase
);
68 DREMTASK("ServiceTask: Removal request for Task 0x%p <%s> (State:%08x)", task
, task
->tc_Node
.ln_Name
, task
->tc_State
);
70 // TODO: Make sure the task has terminated..
71 task
->tc_State
= TS_INVALID
;
74 * Note tc_MemEntry list is part of the task structure which
75 * usually is also placed in tc_MemEntry. MungWall_Check()
76 * will fill freed memory and destroy our list while we are
77 * iterating or the freed memory including our list could be
78 * reused by some other task. We take special care of this by
79 * resetting ln_Succ of the last node to NULL. This way we
80 * avoid getting back to our List structure.
82 task
->tc_MemEntry
.lh_TailPred
->ln_Succ
= NULL
;
84 for (mb
= (struct MemList
*)task
->tc_MemEntry
.lh_Head
; mb
; mb
= mbnext
)
86 /* Free one MemList node */
87 mbnext
= (struct MemList
*)mb
->ml_Node
.ln_Succ
;
89 DREMTASK("ServiceTask: Freeing MemList 0x%p", mb
);
95 if ((task
->tc_Node
.ln_Type
== NT_TASK
) || (task
->tc_Node
.ln_Type
== NT_PROCESS
))
97 /* FIXME: Add fault handling here. Perhaps kernel-level GURU. */
98 DREMTASK("ServiceTask: Task 0x%p <%s> not in servicable state!\n", task
, task
->tc_Node
.ln_Name
);
99 DREMTASK("ServiceTask: State = %08X\n", task
->tc_State
);
102 * Mark the task as ready to run again. Move it back to TaskReady list.
104 #if !defined(EXEC_REMTASK_NEEDSSWITCH)
105 task
->tc_State
= TS_READY
;
106 Enqueue(&SysBase
->TaskReady
, &task
->tc_Node
);
108 krnSysCallReschedTask(task
, TS_READY
);
113 DREMTASK("ServiceTask: Called with something that is not a task??\n");
119 WaitPort(PrivExecBase(SysBase
)->ServicePort
);