Port the SB128 code to AROS.
[AROS.git] / rom / kernel / kernel_scheduler.c
blobdd90714eee059cb74433b0ba8fd52ce8fd0b1031
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"));
79 task = (struct Task *)REMHEAD(&SysBase->TaskReady);
80 if (!task)
82 /* Is the list of ready tasks empty? Well, go idle. */
83 D(bug("[KRN] No ready tasks, entering sleep mode\n"));
85 /* Idle counter is incremented every time when we enter here,
86 not only once. This is correct. */
87 SysBase->IdleCount++;
88 SysBase->AttnResched |= ARF_AttnSwitch;
90 return NULL;
93 SysBase->DispCount++;
95 SysBase->IDNestCnt = task->tc_IDNestCnt;
96 SysBase->ThisTask = task;
97 SysBase->Elapsed = SysBase->Quantum;
98 SysBase->SysFlags &= ~SFF_QuantumOver;
99 task->tc_State = TS_RUN;
101 D(bug("[KRN] New task = %p (%s)\n", task, task->tc_Node.ln_Name));
104 * Check the stack of the task we are about to launch.
105 * Unfortunately original m68k programs can change stack manually without updating SPLower or SPUpper.
106 * For example WB3.1 C:SetPatch adds exec/OpenDevice() patch that swaps stacks manually.
107 * Result is that _all_ programs that call OpenDevice() crash if stack is checked.
109 #ifndef __mc68000
110 if (task->tc_SPReg <= task->tc_SPLower || task->tc_SPReg > task->tc_SPUpper)
112 bug("[KRN] Task %s went out of stack limits\n", task->tc_Node.ln_Name);
113 bug("[KRN] Lower %p, upper %p, SP %p\n", task->tc_SPLower, task->tc_SPUpper, task->tc_SPReg);
114 Alert(AT_DeadEnd|AN_StackProbe);
116 #endif
117 if (task->tc_Flags & TF_LAUNCH)
118 AROS_UFC1(void, task->tc_Launch, AROS_UFCA(struct ExecBase *, SysBase, A6));
120 /* Leave interrupt and jump to the new task */
121 return task;