2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
8 #include <exec/alerts.h>
9 #include <exec/execbase.h>
10 #include <proto/exec.h>
12 #include <kernel_base.h>
13 #include <kernel_debug.h>
14 #include <kernel_scheduler.h>
16 #define AROS_NO_ATOMIC_OPERATIONS
17 #include "exec_platform.h"
22 * Schedule the currently running task away. Put it into the TaskReady list
23 * in some smart way. This function is subject of change and it will be probably replaced
24 * by some plugin system in the future
26 BOOL
core_Schedule(void)
28 struct Task
*task
= SysBase
->ThisTask
;
30 D(bug("[KRN] core_Schedule()\n"));
32 FLAG_SCHEDSWITCH_CLEAR
;
34 /* If task has pending exception, reschedule it so that the dispatcher may handle the exception */
35 if (!(task
->tc_Flags
& TF_EXCEPT
))
39 /* Is the TaskReady empty? If yes, then the running task is the only one. Let it work */
40 if (IsListEmpty(&SysBase
->TaskReady
))
43 /* Does the TaskReady list contains tasks with priority equal or lower than current task?
44 * If so, then check further... */
45 pri
= ((struct Task
*)GetHead(&SysBase
->TaskReady
))->tc_Node
.ln_Pri
;
46 if (pri
<= task
->tc_Node
.ln_Pri
)
48 /* If the running task did not used it's whole quantum yet, let it work */
49 if (!FLAG_SCHEDQUANTUM_ISSET
)
55 * If we got here, then the rescheduling is necessary.
56 * Put the task into the TaskReady list.
58 D(bug("[KRN] Setting task 0x%p (%s) to READY\n", task
, task
->tc_Node
.ln_Name
));
59 task
->tc_State
= TS_READY
;
60 Enqueue(&SysBase
->TaskReady
, &task
->tc_Node
);
62 /* Select new task to run */
66 /* Actually switch away from the task */
67 void core_Switch(void)
69 struct Task
*task
= SysBase
->ThisTask
;
71 D(bug("[KRN] core_Switch(): Old task = %p (%s)\n", task
, task
->tc_Node
.ln_Name
));
74 if (task
->tc_SPReg
<= task
->tc_SPLower
|| task
->tc_SPReg
> task
->tc_SPUpper
)
76 bug("[KRN] Task %s went out of stack limits\n", task
->tc_Node
.ln_Name
);
77 bug("[KRN] Lower %p, upper %p, SP %p\n", task
->tc_SPLower
, task
->tc_SPUpper
, task
->tc_SPReg
);
79 * Suspend the task to stop it from causing more harm. In some rare cases, if the task is holding
80 * lock on some global/library semaphore it will most likelly mean immenent freeze. In most cases
81 * however, user will be shown an alert.
83 Remove(&task
->tc_Node
);
85 task
->tc_State
= TS_WAIT
;
86 Enqueue(&SysBase
->TaskWait
, &task
->tc_Node
);
92 task
->tc_IDNestCnt
= IDNESTCOUNT_GET
;
94 if (task
->tc_Flags
& TF_SWITCH
)
95 AROS_UFC1NR(void, task
->tc_Switch
, AROS_UFCA(struct ExecBase
*, SysBase
, A6
));
99 * Task dispatcher. Basically it may be the same one no matter
100 * what scheduling algorithm is used (except SysBase->Elapsed reloading)
102 struct Task
*core_Dispatch(void)
106 D(bug("[KRN] core_Dispatch()\n"));
108 task
= (struct Task
*)REMHEAD(&SysBase
->TaskReady
);
111 /* Is the list of ready tasks empty? Well, go idle. */
112 D(bug("[KRN] No ready tasks, entering sleep mode\n"));
115 * Idle counter is incremented every time when we enter here,
116 * not only once. This is correct.
118 SysBase
->IdleCount
++;
119 FLAG_SCHEDSWITCH_SET
;
124 SysBase
->DispCount
++;
125 IDNESTCOUNT_SET(task
->tc_IDNestCnt
);
126 SysBase
->ThisTask
= task
;
127 SysBase
->Elapsed
= SysBase
->Quantum
;
128 FLAG_SCHEDQUANTUM_CLEAR
;
129 task
->tc_State
= TS_RUN
;
131 D(bug("[KRN] New task = %p (%s)\n", task
, task
->tc_Node
.ln_Name
));
134 * Check the stack of the task we are about to launch.
135 * Unfortunately original m68k programs can change stack manually without updating SPLower or SPUpper.
136 * For example WB3.1 C:SetPatch adds exec/OpenDevice() patch that swaps stacks manually.
137 * Result is that _all_ programs that call OpenDevice() crash if stack is checked.
140 if (task
->tc_SPReg
<= task
->tc_SPLower
|| task
->tc_SPReg
> task
->tc_SPUpper
)
142 /* Don't let the task run, switch it away (raising Alert) and dispatch another task */
144 return core_Dispatch();
148 if (task
->tc_Flags
& TF_LAUNCH
)
149 AROS_UFC1NR(void, task
->tc_Launch
, AROS_UFCA(struct ExecBase
*, SysBase
, A6
));
151 /* Leave interrupt and jump to the new task */