sched/sched: fix scheduler lock/unlock operation for non-SMP case

Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
This commit is contained in:
Petro Karashchenko 2023-04-14 23:41:19 +03:00 committed by Xiang Xiao
parent 770817ba2f
commit fcd6ec7809
2 changed files with 89 additions and 60 deletions

View File

@ -148,13 +148,15 @@ int sched_lock(void)
if (rtcb != NULL && !up_interrupt_context())
{
irqstate_t flags;
/* Catch attempts to increment the lockcount beyond the range of the
* integer type.
*/
DEBUGASSERT(rtcb->lockcount < MAX_LOCK_COUNT);
irqstate_t flags = enter_critical_section();
flags = enter_critical_section();
/* We must hold the lock on this CPU before we increment the lockcount
* for the first time. Holding the lock is sufficient to lockout
@ -234,12 +236,17 @@ int sched_lock(void)
if (rtcb != NULL && !up_interrupt_context())
{
FAR struct tcb_s *ptcb;
irqstate_t flags;
/* Catch attempts to increment the lockcount beyond the range of the
* integer type.
*/
DEBUGASSERT(rtcb->lockcount < MAX_LOCK_COUNT);
flags = enter_critical_section();
/* A counter is used to support locking. This allows nested lock
* operations on this thread (on any CPU)
*/
@ -262,6 +269,22 @@ int sched_lock(void)
#endif
}
#endif
/* Move any tasks in the ready-to-run list to the pending task list
* where they will not be available to run until the scheduler is
* unlocked and nxsched_merge_pending() is called. So ready-to-run
* will consist only from the currently runnig task and the idle task.
*/
for (ptcb = rtcb->flink; ptcb && ptcb->flink; ptcb = rtcb->flink)
{
dq_rem((FAR dq_entry_t *)ptcb, &g_readytorun);
nxsched_add_prioritized(ptcb, &g_pendingtasks);
ptcb->task_state = TSTATE_TASK_PENDING;
}
leave_critical_section(flags);
}
return OK;

View File

@ -82,73 +82,79 @@ bool nxsched_merge_pending(void)
rtcb = this_task();
/* Process every TCB in the g_pendingtasks list */
/* Process every TCB in the g_pendingtasks list
*
* Do nothing if pre-emption is still disabled
*/
for (ptcb = (FAR struct tcb_s *)g_pendingtasks.head;
ptcb;
ptcb = pnext)
if (rtcb->lockcount == 0)
{
pnext = ptcb->flink;
/* REVISIT: Why don't we just remove the ptcb from pending task list
* and call nxsched_add_readytorun?
*/
/* Search the ready-to-run list to find the location to insert the
* new ptcb. Each is list is maintained in ascending sched_priority
* order.
*/
for (;
(rtcb && ptcb->sched_priority <= rtcb->sched_priority);
rtcb = rtcb->flink)
for (ptcb = (FAR struct tcb_s *)g_pendingtasks.head;
ptcb;
ptcb = pnext)
{
pnext = ptcb->flink;
/* REVISIT: Why don't we just remove the ptcb from pending task
* list and call nxsched_add_readytorun?
*/
/* Search the ready-to-run list to find the location to insert the
* new ptcb. Each is list is maintained in ascending sched_priority
* order.
*/
for (;
(rtcb && ptcb->sched_priority <= rtcb->sched_priority);
rtcb = rtcb->flink)
{
}
/* Add the ptcb to the spot found in the list. Check if the
* ptcb goes at the ends of the ready-to-run list. This would be
* error condition since the idle test must always be at the end of
* the ready-to-run list!
*/
DEBUGASSERT(rtcb);
/* The ptcb goes just before rtcb */
rprev = rtcb->blink;
if (rprev == NULL)
{
/* Special case: Inserting ptcb at the head of the list */
ptcb->flink = rtcb;
ptcb->blink = NULL;
rtcb->blink = ptcb;
g_readytorun.head = (FAR dq_entry_t *)ptcb;
rtcb->task_state = TSTATE_TASK_READYTORUN;
ptcb->task_state = TSTATE_TASK_RUNNING;
ret = true;
}
else
{
/* Insert in the middle of the list */
ptcb->flink = rtcb;
ptcb->blink = rprev;
rprev->flink = ptcb;
rtcb->blink = ptcb;
ptcb->task_state = TSTATE_TASK_READYTORUN;
}
/* Set up for the next time through */
rtcb = ptcb;
}
/* Add the ptcb to the spot found in the list. Check if the
* ptcb goes at the ends of the ready-to-run list. This would be
* error condition since the idle test must always be at the end of
* the ready-to-run list!
*/
/* Mark the input list empty */
DEBUGASSERT(rtcb);
/* The ptcb goes just before rtcb */
rprev = rtcb->blink;
if (rprev == NULL)
{
/* Special case: Inserting ptcb at the head of the list */
ptcb->flink = rtcb;
ptcb->blink = NULL;
rtcb->blink = ptcb;
g_readytorun.head = (FAR dq_entry_t *)ptcb;
rtcb->task_state = TSTATE_TASK_READYTORUN;
ptcb->task_state = TSTATE_TASK_RUNNING;
ret = true;
}
else
{
/* Insert in the middle of the list */
ptcb->flink = rtcb;
ptcb->blink = rprev;
rprev->flink = ptcb;
rtcb->blink = ptcb;
ptcb->task_state = TSTATE_TASK_READYTORUN;
}
/* Set up for the next time through */
rtcb = ptcb;
g_pendingtasks.head = NULL;
g_pendingtasks.tail = NULL;
}
/* Mark the input list empty */
g_pendingtasks.head = NULL;
g_pendingtasks.tail = NULL;
return ret;
}
#endif /* !CONFIG_SMP */