29
29
#include <stdbool.h>
30
30
#include <assert.h>
31
31
32
- #include <nuttx/queue.h>
33
-
34
32
#include "irq/irq.h"
33
+ #include "sched/queue.h"
35
34
#include "sched/sched.h"
36
35
37
36
/****************************************************************************
@@ -154,30 +153,14 @@ bool nxsched_add_readytorun(FAR struct tcb_s *btcb)
154
153
bool nxsched_add_readytorun (FAR struct tcb_s * btcb )
155
154
{
156
155
FAR struct tcb_s * rtcb ;
156
+ FAR struct tcb_s * headtcb ;
157
157
FAR dq_queue_t * tasklist ;
158
158
bool doswitch ;
159
159
int task_state ;
160
160
int cpu ;
161
161
int me ;
162
162
163
- /* Check if the blocked TCB is locked to this CPU */
164
-
165
- if ((btcb -> flags & TCB_FLAG_CPU_LOCKED ) != 0 )
166
- {
167
- /* Yes.. that is the CPU we must use */
168
-
169
- task_state = TSTATE_TASK_ASSIGNED ;
170
- cpu = btcb -> cpu ;
171
- }
172
- else
173
- {
174
- /* Otherwise, find the CPU that is executing the lowest priority task
175
- * (possibly its IDLE task).
176
- */
177
-
178
- task_state = TSTATE_TASK_READYTORUN ;
179
- cpu = nxsched_select_cpu (btcb -> affinity );
180
- }
163
+ cpu = nxsched_select_cpu (btcb -> affinity );
181
164
182
165
/* Get the task currently running on the CPU (may be the IDLE task) */
183
166
@@ -193,6 +176,10 @@ bool nxsched_add_readytorun(FAR struct tcb_s *btcb)
193
176
{
194
177
task_state = TSTATE_TASK_RUNNING ;
195
178
}
179
+ else
180
+ {
181
+ task_state = TSTATE_TASK_READYTORUN ;
182
+ }
196
183
197
184
/* If the selected state is TSTATE_TASK_RUNNING, then we would like to
198
185
* start running the task. Be we cannot do that if pre-emption is
@@ -207,8 +194,7 @@ bool nxsched_add_readytorun(FAR struct tcb_s *btcb)
207
194
* situation.
208
195
*/
209
196
210
- if ((nxsched_islocked_global ()) & &
211
- task_state != TSTATE_TASK_ASSIGNED )
197
+ if (nxsched_islocked_global ())
212
198
{
213
199
/* Add the new ready-to-run task to the g_pendingtasks task list for
214
200
* now.
@@ -233,7 +219,7 @@ bool nxsched_add_readytorun(FAR struct tcb_s *btcb)
233
219
btcb -> task_state = TSTATE_TASK_READYTORUN ;
234
220
doswitch = false;
235
221
}
236
- else /* (task_state == TSTATE_TASK_ASSIGNED || task_state == TSTATE_TASK_RUNNING) */
222
+ else /* (task_state == TSTATE_TASK_RUNNING) */
237
223
{
238
224
/* If we are modifying some assigned task list other than our own, we
239
225
* will need to stop that CPU.
@@ -245,109 +231,32 @@ bool nxsched_add_readytorun(FAR struct tcb_s *btcb)
245
231
DEBUGVERIFY (up_cpu_pause (cpu ));
246
232
}
247
233
248
- /* Add the task to the list corresponding to the selected state
249
- * and check if a context switch will occur
250
- */
234
+ tasklist = & g_assignedtasks [ cpu ];
235
+
236
+ /* Change "head" from TSTATE_TASK_RUNNING to TSTATE_TASK_ASSIGNED */
251
237
252
- tasklist = list_assignedtasks (cpu );
253
- doswitch = nxsched_add_prioritized (btcb , tasklist );
238
+ headtcb = (FAR struct tcb_s * )tasklist -> head ;
239
+ DEBUGASSERT (headtcb -> task_state = TSTATE_TASK_RUNNING );
240
+ headtcb -> task_state = TSTATE_TASK_ASSIGNED ;
254
241
255
- /* If the selected task list was the g_assignedtasks[] list and if the
256
- * new tasks is the highest priority (RUNNING) task, then a context
257
- * switch will occur.
242
+ /* Add btcb to the head of the g_assignedtasks
243
+ * task list and mark it as running
258
244
*/
259
245
260
- if (doswitch )
261
- {
262
- FAR struct tcb_s * next ;
263
-
264
- /* The new btcb was added at the head of the ready-to-run list. It
265
- * is now the new active task!
266
- */
267
-
268
- /* Assign the CPU and set the running state */
269
-
270
- DEBUGASSERT (task_state == TSTATE_TASK_RUNNING );
271
-
272
- btcb -> cpu = cpu ;
273
- btcb -> task_state = TSTATE_TASK_RUNNING ;
274
-
275
- /* Adjust global pre-emption controls. If the lockcount is
276
- * greater than zero, then this task/this CPU holds the scheduler
277
- * lock.
278
- */
279
-
280
- if (btcb -> lockcount > 0 )
281
- {
282
- g_cpu_lockset |= (1 << cpu );
283
- }
284
- else
285
- {
286
- g_cpu_lockset &= ~(1 << cpu );
287
- }
288
-
289
- /* NOTE: If the task runs on another CPU(cpu), adjusting global IRQ
290
- * controls will be done in the pause handler on the new CPU(cpu).
291
- * If the task is scheduled on this CPU(me), do nothing because
292
- * this CPU already has a critical section
293
- */
294
-
295
- /* If the following task is not locked to this CPU, then it must
296
- * be moved to the g_readytorun list. Since it cannot be at the
297
- * head of the list, we can do this without invoking any heavy
298
- * lifting machinery.
299
- */
300
-
301
- DEBUGASSERT (btcb -> flink != NULL );
302
- next = btcb -> flink ;
303
-
304
- if ((next -> flags & TCB_FLAG_CPU_LOCKED ) != 0 )
305
- {
306
- DEBUGASSERT (next -> cpu == cpu );
307
- next -> task_state = TSTATE_TASK_ASSIGNED ;
308
- }
309
- else
310
- {
311
- /* Remove the task from the assigned task list */
312
-
313
- dq_rem ((FAR dq_entry_t * )next , tasklist );
314
-
315
- /* Add the task to the g_readytorun or to the g_pendingtasks
316
- * list. NOTE: That the above operations may cause the
317
- * scheduler to become locked. It may be assigned to a
318
- * different CPU the next time that it runs.
319
- */
320
-
321
- if (nxsched_islocked_global ())
322
- {
323
- next -> task_state = TSTATE_TASK_PENDING ;
324
- tasklist = list_pendingtasks ();
325
- }
326
- else
327
- {
328
- next -> task_state = TSTATE_TASK_READYTORUN ;
329
- tasklist = list_readytorun ();
330
- }
331
-
332
- nxsched_add_prioritized (next , tasklist );
333
- }
334
- }
335
- else
246
+ dq_addfirst_nonempty ((FAR dq_entry_t * )btcb , tasklist );
247
+
248
+ DEBUGASSERT (task_state == TSTATE_TASK_RUNNING );
249
+ btcb -> cpu = cpu ;
250
+ btcb -> task_state = TSTATE_TASK_RUNNING ;
251
+
252
+ doswitch = true;
253
+
254
+ /* Resume scheduling lock */
255
+
256
+ DEBUGASSERT (g_cpu_lockset == 0 );
257
+ if (btcb -> lockcount > 0 )
336
258
{
337
- /* No context switch. Assign the CPU and set the assigned state.
338
- *
339
- * REVISIT: I have seen this assertion fire. Apparently another
340
- * CPU may add another, higher priority task to the same
341
- * g_assignedtasks[] list sometime after nxsched_select_cpu() was
342
- * called above, leaving this TCB in the wrong task list if
343
- * task_state is TSTATE_TASK_ASSIGNED).
344
- */
345
-
346
- DEBUGASSERT (task_state == TSTATE_TASK_ASSIGNED );
347
-
348
- btcb -> cpu = cpu ;
349
- btcb -> task_state = TSTATE_TASK_ASSIGNED ;
350
- doswitch = false;
259
+ g_cpu_lockset |= (1 << cpu );
351
260
}
352
261
353
262
/* All done, restart the other CPU (if it was paused). */
0 commit comments