Minor fixes to comments.
[AROS.git] / rom / kernel / kernel_scheduler.c
blob72d296ffbb071b341e51a6e18b65a4f2e03a997b
1 #include <exec/alerts.h>
2 #include <exec/execbase.h>
3 #include <proto/exec.h>
5 #include <kernel_base.h>
6 #include <kernel_debug.h>
7 #include <kernel_scheduler.h>
9 #define D(x)
12 * Schedule the currently running task away. Put it into the TaskReady list
13 * in some smart way. This function is subject of change and it will be probably replaced
14 * by some plugin system in the future
16 BOOL core_Schedule(void)
18 struct Task *task = SysBase->ThisTask;
20 D(bug("[KRN] core_Schedule()\n"));
22 SysBase->AttnResched &= ~ARF_AttnSwitch;
24 /* If task has pending exception, reschedule it so that the dispatcher may handle the exception */
25 if (!(task->tc_Flags & TF_EXCEPT))
27 BYTE pri;
29 /* Is the TaskReady empty? If yes, then the running task is the only one. Let it work */
30 if (IsListEmpty(&SysBase->TaskReady))
31 return FALSE;
33 /* Does the TaskReady list contains tasks with priority equal or lower than current task?
34 * If so, then check further... */
35 pri = ((struct Task*)GetHead(&SysBase->TaskReady))->tc_Node.ln_Pri;
36 if (pri <= task->tc_Node.ln_Pri)
38 /* If the running task did not used it's whole quantum yet, let it work */
39 if (!(SysBase->SysFlags & SFF_QuantumOver))
40 return FALSE;
44 /*
45 * If we got here, then the rescheduling is necessary.
46 * Put the task into the TaskReady list.
48 D(bug("[KRN] Setting task 0x%p (%s) to READY\n", task, task->tc_Node.ln_Name));
49 task->tc_State = TS_READY;
50 Enqueue(&SysBase->TaskReady, &task->tc_Node);
52 /* Select new task to run */
53 return TRUE;
56 /* Actually switch away from the task */
57 void core_Switch(void)
59 struct Task *task = SysBase->ThisTask;
61 D(bug("[KRN] core_Switch(): Old task = %p (%s)\n", task, task->tc_Node.ln_Name));
63 #ifndef __mc68000
64 if (task->tc_SPReg <= task->tc_SPLower || task->tc_SPReg > task->tc_SPUpper)
66 bug("[KRN] Task %s went out of stack limits\n", task->tc_Node.ln_Name);
67 bug("[KRN] Lower %p, upper %p, SP %p\n", task->tc_SPLower, task->tc_SPUpper, task->tc_SPReg);
68 Alert(AT_DeadEnd|AN_StackProbe);
70 #endif
72 task->tc_IDNestCnt = SysBase->IDNestCnt;
74 if (task->tc_Flags & TF_SWITCH)
75 AROS_UFC1NR(void, task->tc_Switch, AROS_UFCA(struct ExecBase *, SysBase, A6));
79 * Task dispatcher. Basically it may be the same one no matter
80 * what scheduling algorithm is used (except SysBase->Elapsed reloading)
82 struct Task *core_Dispatch(void)
84 struct Task *task;
86 D(bug("[KRN] core_Dispatch()\n"));
88 task = (struct Task *)REMHEAD(&SysBase->TaskReady);
89 if (!task)
91 /* Is the list of ready tasks empty? Well, go idle. */
92 D(bug("[KRN] No ready tasks, entering sleep mode\n"));
95 * Idle counter is incremented every time when we enter here,
96 * not only once. This is correct.
98 SysBase->IdleCount++;
99 SysBase->AttnResched |= ARF_AttnSwitch;
101 return NULL;
104 SysBase->DispCount++;
105 SysBase->IDNestCnt = task->tc_IDNestCnt;
106 SysBase->ThisTask = task;
107 SysBase->Elapsed = SysBase->Quantum;
108 SysBase->SysFlags &= ~SFF_QuantumOver;
109 task->tc_State = TS_RUN;
111 D(bug("[KRN] New task = %p (%s)\n", task, task->tc_Node.ln_Name));
114 * Check the stack of the task we are about to launch.
115 * Unfortunately original m68k programs can change stack manually without updating SPLower or SPUpper.
116 * For example WB3.1 C:SetPatch adds exec/OpenDevice() patch that swaps stacks manually.
117 * Result is that _all_ programs that call OpenDevice() crash if stack is checked.
119 #ifndef __mc68000
120 if (task->tc_SPReg <= task->tc_SPLower || task->tc_SPReg > task->tc_SPUpper)
122 bug("[KRN] Task %s went out of stack limits\n", task->tc_Node.ln_Name);
123 bug("[KRN] Lower %p, upper %p, SP %p\n", task->tc_SPLower, task->tc_SPUpper, task->tc_SPReg);
124 Alert(AT_DeadEnd|AN_StackProbe);
126 #endif
128 if (task->tc_Flags & TF_LAUNCH)
129 AROS_UFC1NR(void, task->tc_Launch, AROS_UFCA(struct ExecBase *, SysBase, A6));
131 /* Leave interrupt and jump to the new task */
132 return task;