White space fixes, detab.
[AROS.git] / rom / kernel / kernel_scheduler.c
blob94fb989ea47c286074999b2d868eabc2868acadd
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 task->tc_IDNestCnt = SysBase->IDNestCnt;
65 if (task->tc_Flags & TF_SWITCH)
66 AROS_UFC1(void, task->tc_Switch, AROS_UFCA(struct ExecBase *, SysBase, A6));
70 * Task dispatcher. Basically it may be the same one no matter
71 * what scheduling algorithm is used (except SysBase->Elapsed reloading)
73 struct Task *core_Dispatch(void)
75 struct Task *task;
77 D(bug("[KRN] core_Dispatch()\n"));
81 task = (struct Task *)REMHEAD(&SysBase->TaskReady);
82 if (!task)
84 /* Is the list of ready tasks empty? Well, go idle. */
85 D(bug("[KRN] No ready tasks, entering sleep mode\n"));
88 * Idle counter is incremented every time when we enter here,
89 * not only once. This is correct.
91 SysBase->IdleCount++;
92 SysBase->AttnResched |= ARF_AttnSwitch;
94 return NULL;
97 * We have task. Now let's ask exec if it's okay to launch it.
98 * If exec returns FALSE, we repeat the attempt. In fact we expect
99 * that at least exec's housekeeper is READY in this case.
101 } while (!Dispatch(task));
103 SysBase->DispCount++;
104 SysBase->IDNestCnt = task->tc_IDNestCnt;
105 SysBase->ThisTask = task;
106 SysBase->Elapsed = SysBase->Quantum;
107 SysBase->SysFlags &= ~SFF_QuantumOver;
108 task->tc_State = TS_RUN;
110 D(bug("[KRN] New task = %p (%s)\n", task, task->tc_Node.ln_Name));
113 * Check the stack of the task we are about to launch.
114 * Unfortunately original m68k programs can change stack manually without updating SPLower or SPUpper.
115 * For example WB3.1 C:SetPatch adds exec/OpenDevice() patch that swaps stacks manually.
116 * Result is that _all_ programs that call OpenDevice() crash if stack is checked.
118 #ifndef __mc68000
119 if (task->tc_SPReg <= task->tc_SPLower || task->tc_SPReg > task->tc_SPUpper)
121 bug("[KRN] Task %s went out of stack limits\n", task->tc_Node.ln_Name);
122 bug("[KRN] Lower %p, upper %p, SP %p\n", task->tc_SPLower, task->tc_SPUpper, task->tc_SPReg);
123 Alert(AT_DeadEnd|AN_StackProbe);
125 #endif
127 if (task->tc_Flags & TF_LAUNCH)
128 AROS_UFC1(void, task->tc_Launch, AROS_UFCA(struct ExecBase *, SysBase, A6));
130 /* Leave interrupt and jump to the new task */
131 return task;