use IntETask() instead of GetIntETask(). minor debug changes/delint.
[AROS.git] / arch / arm-native / kernel / kernel_scheduler.c
blob55bada7778a8f3a13e6471931b6eaf8701d1ac42
1 /*
2 Copyright © 2015, The AROS Development Team. All rights reserved.
3 $Id$
5 */
7 #include <exec/alerts.h>
8 #include <exec/execbase.h>
9 #include <exec/lists.h>
10 #include <proto/exec.h>
11 #include <proto/kernel.h>
13 //#include <kernel_base.h>
14 #include <kernel_debug.h>
15 #include <kernel_scheduler.h>
17 #include "kernel_cpu.h"
19 #define AROS_NO_ATOMIC_OPERATIONS
20 #include <exec_platform.h>
22 #include <aros/types/spinlock_s.h>
24 #include <etask.h>
26 #include "exec_intern.h"
28 #define DSCHED(x) x
30 /* Check if the currently running task on this cpu should be rescheduled.. */
31 BOOL core_Schedule(void)
33 #if defined(DEBUG)
34 int cpunum = GetCPUNumber();
35 #endif
36 struct Task *task = GET_THIS_TASK;
37 BOOL corereschedule = TRUE;
39 DSCHED(bug("[Kernel:%02d] core_Schedule()\n", cpunum));
41 FLAG_SCHEDSWITCH_CLEAR;
43 /* If task has pending exception, reschedule it so that the dispatcher may handle the exception */
44 if (!(task->tc_Flags & TF_EXCEPT))
46 #if defined(__AROSEXEC_SMP__)
47 KrnSpinLock(&PrivExecBase(SysBase)->TaskReadySpinLock, NULL,
48 SPINLOCK_MODE_READ);
49 #endif
50 /* Is the TaskReady empty? If yes, then the running task is the only one. Let it work */
51 if (IsListEmpty(&SysBase->TaskReady))
52 corereschedule = FALSE;
53 else
55 struct Task *nexttask;
56 #if defined(__AROSEXEC_SMP__)
57 int cpunum = GetCPUNumber();
58 uint32_t cpumask = (1 << cpunum);
59 #endif
61 If there are tasks ready for this cpu that have equal or lower priority,
62 and the current task has used its alloted time - reschedule so they can run
64 for (nexttask = (struct Task *)GetHead(&SysBase->TaskReady); nexttask != NULL; nexttask = (struct Task *)GetSucc(nexttask))
66 #if defined(__AROSEXEC_SMP__)
67 if ((GetIntETask(nexttask)->iet_CpuAffinity & cpumask) == cpumask)
69 #endif
70 if (nexttask->tc_Node.ln_Pri <= task->tc_Node.ln_Pri)
72 /* If the running task did not used it's whole quantum yet, let it work */
73 if (!FLAG_SCHEDQUANTUM_ISSET)
74 corereschedule = FALSE;
76 break;
77 #if defined(__AROSEXEC_SMP__)
79 #endif
82 #if defined(__AROSEXEC_SMP__)
83 KrnSpinUnLock(&PrivExecBase(SysBase)->TaskReadySpinLock);
84 #endif
87 DSCHED
89 if (corereschedule)
90 bug("[Kernel:%02d] '%s' @ 0x%p needs rescheduled ..\n", cpunum, task->tc_Node.ln_Name, task);
93 return corereschedule;
96 /* Switch the currently running task on this cpu to ready state */
97 void core_Switch(void)
99 #if defined(DEBUG)
100 int cpunum = GetCPUNumber();
101 #endif
102 struct Task *task = GET_THIS_TASK;
104 DSCHED(bug("[Kernel:%02d] core_Switch(%08x)\n", cpunum, task->tc_State));
106 if (task->tc_State == TS_RUN)
108 DSCHED(bug("[Kernel:%02d] Switching away from '%s' @ 0x%p\n", cpunum, task->tc_Node.ln_Name, task));
109 #if defined(__AROSEXEC_SMP__)
110 KrnSpinLock(&PrivExecBase(SysBase)->TaskRunningSpinLock, NULL,
111 SPINLOCK_MODE_WRITE);
112 #endif
113 Remove(&task->tc_Node);
114 #if defined(__AROSEXEC_SMP__)
115 KrnSpinUnLock(&PrivExecBase(SysBase)->TaskRunningSpinLock);
116 #endif
117 task->tc_State = TS_READY;
119 /* if the current task has gone out of stack bounds, suspend it to prevent further damage to the system */
120 if (task->tc_SPReg <= task->tc_SPLower || task->tc_SPReg > task->tc_SPUpper)
122 bug("[Kernel:%02d] '%s' @ 0x%p went out of stack limits\n", cpunum, task->tc_Node.ln_Name, task);
123 bug("[Kernel:%02d] - Lower 0x%p, upper 0x%p, SP 0x%p\n", cpunum, task->tc_SPLower, task->tc_SPUpper, task->tc_SPReg);
125 task->tc_SigWait = 0;
126 task->tc_State = TS_WAIT;
127 #if defined(__AROSEXEC_SMP__)
128 KrnSpinLock(&PrivExecBase(SysBase)->TaskWaitSpinLock, NULL,
129 SPINLOCK_MODE_WRITE);
130 #endif
131 Enqueue(&SysBase->TaskWait, &task->tc_Node);
132 #if defined(__AROSEXEC_SMP__)
133 KrnSpinUnLock(&PrivExecBase(SysBase)->TaskWaitSpinLock);
134 #endif
136 Alert(AN_StackProbe);
139 task->tc_IDNestCnt = IDNESTCOUNT_GET;
141 if (task->tc_Flags & TF_SWITCH)
142 AROS_UFC1NR(void, task->tc_Switch, AROS_UFCA(struct ExecBase *, SysBase, A6));
144 if (task->tc_State == TS_READY)
146 DSCHED(bug("[Kernel:%02d] Setting '%s' @ 0x%p as ready\n", cpunum, task->tc_Node.ln_Name, task));
147 #if defined(__AROSEXEC_SMP__)
148 KrnSpinLock(&PrivExecBase(SysBase)->TaskReadySpinLock, NULL,
149 SPINLOCK_MODE_WRITE);
150 #endif
151 Enqueue(&SysBase->TaskReady, &task->tc_Node);
152 #if defined(__AROSEXEC_SMP__)
153 KrnSpinUnLock(&PrivExecBase(SysBase)->TaskReadySpinLock);
154 #endif
159 /* Dispatch a "new" ready task on this cpu */
160 struct Task *core_Dispatch(void)
162 struct Task *newtask;
163 struct Task *task = GET_THIS_TASK;
164 #if defined(__AROSEXEC_SMP__) || defined(DEBUG)
165 int cpunum = GetCPUNumber();
166 #endif
167 #if defined(__AROSEXEC_SMP__)
168 uint32_t cpumask = (1 << cpunum);
169 #endif
171 DSCHED(bug("[Kernel:%02d] core_Dispatch()\n", cpunum));
173 #if defined(__AROSEXEC_SMP__)
174 KrnSpinLock(&PrivExecBase(SysBase)->TaskReadySpinLock, NULL,
175 SPINLOCK_MODE_WRITE);
176 #endif
177 for (newtask = (struct Task *)GetHead(&SysBase->TaskReady); newtask != NULL; newtask = (struct Task *)GetSucc(newtask))
179 #if defined(__AROSEXEC_SMP__)
180 if ((GetIntETask(newtask)->iet_CpuAffinity & cpumask) == cpumask)
182 #endif
183 Remove(&newtask->tc_Node);
184 break;
185 #if defined(__AROSEXEC_SMP__)
187 #endif
189 #if defined(__AROSEXEC_SMP__)
190 KrnSpinUnLock(&PrivExecBase(SysBase)->TaskReadySpinLock);
191 #endif
193 if ((!newtask) && (task) && (task->tc_State != TS_WAIT))
194 newtask = task;
196 if ((newtask) &&
197 (newtask->tc_State == TS_READY) ||
198 (newtask->tc_State == TS_RUN))
200 DSCHED(bug("[Kernel:%02d] Preparing to run '%s' @ 0x%p\n", cpunum, newtask->tc_Node.ln_Name, newtask));
202 SysBase->DispCount++;
203 IDNESTCOUNT_SET(newtask->tc_IDNestCnt);
204 SET_THIS_TASK(newtask);
205 SysBase->Elapsed = SysBase->Quantum;
206 FLAG_SCHEDQUANTUM_CLEAR;
208 /* Check the stack of the task we are about to launch. */
209 if ((newtask->tc_SPReg <= newtask->tc_SPLower) ||
210 (newtask->tc_SPReg > newtask->tc_SPUpper))
211 newtask->tc_State = TS_WAIT;
212 else
213 newtask->tc_State = TS_RUN;
216 if (newtask)
218 BOOL launchtask = TRUE;
219 #if defined(__AROSEXEC_SMP__)
220 if (newtask->tc_State == TS_SPIN)
222 /* move it to the spinning list */
223 KrnSpinLock(&PrivExecBase(SysBase)->TaskSpinningLock, NULL,
224 SPINLOCK_MODE_WRITE);
225 AddHead(&PrivExecBase(SysBase)->TaskSpinning, &newtask->tc_Node);
226 KrnSpinUnLock(&PrivExecBase(SysBase)->TaskSpinningLock);
227 launchtask = FALSE;
229 #endif
230 if (newtask->tc_State == TS_WAIT)
232 #if defined(__AROSEXEC_SMP__)
233 KrnSpinLock(&PrivExecBase(SysBase)->TaskWaitSpinLock, NULL,
234 SPINLOCK_MODE_WRITE);
235 #endif
236 Enqueue(&SysBase->TaskWait, &task->tc_Node);
237 #if defined(__AROSEXEC_SMP__)
238 KrnSpinUnLock(&PrivExecBase(SysBase)->TaskWaitSpinLock);
239 #endif
240 launchtask = FALSE;
243 if (!launchtask)
245 /* if the new task shouldnt run - force a reschedule.. */
246 DSCHED(bug("[Kernel:%02d] Skipping '%s' @ 0x%p (state %08x)\n", cpunum, newtask->tc_Node.ln_Name, newtask, newtask->tc_State));
248 core_Switch();
249 newtask = core_Dispatch();
251 else
253 DSCHED(bug("[Kernel:%02d] Launching '%s' @ 0x%p (state %08x)\n", cpunum, newtask->tc_Node.ln_Name, newtask, newtask->tc_State));
256 else
258 /* Go idle if there is nothing to do ... */
259 DSCHED(bug("[Kernel:%02d] No ready Task(s) - entering sleep mode\n", cpunum));
262 * Idle counter is incremented every time when we enter here,
263 * not only once. This is correct.
265 SysBase->IdleCount++;
266 FLAG_SCHEDSWITCH_SET;
269 return newtask;