OS: Add a RUNNABLE attribute to the tasklists to indicate if the task list includes the currently executing task. Use this additional bit of information to determine if a context switch could really occur when removing a TCB from a task list

This commit is contained in:
Gregory Nutt 2016-02-12 08:15:16 -06:00
parent 76e88c8963
commit 7d7f4e140c
5 changed files with 34 additions and 8 deletions

2
arch

@ -1 +1 @@
Subproject commit 717113268b97f16d755a11609a63526dfe71e4cf
Subproject commit a6ad88a85c9e4c6ab633fb53f53603539206a57c

@ -1 +1 @@
Subproject commit 600d77e8b4631a67a6099b35a6959b6099b4a42b
Subproject commit f9d09bf8c091cc2d8578ae572ad8f48bb93d062a

View File

@ -230,23 +230,27 @@ const struct tasklist_s g_tasklisttable[NUM_TASK_STATES] =
&g_pendingtasks,
TLIST_ATTR_PRIORITIZED
},
#ifdef CONFIG_SMP
{ /* TSTATE_TASK_READYTORUN */
&g_readytorun,
TLIST_ATTR_PRIORITIZED
},
#ifdef CONFIG_SMP
{ /* TSTATE_TASK_ASSIGNED */
g_assignedtasks,
TLIST_ATTR_PRIORITIZED | TLIST_ATTR_INDEXED
TLIST_ATTR_PRIORITIZED | TLIST_ATTR_INDEXED | TLIST_ATTR_RUNNABLE
},
{ /* TSTATE_TASK_RUNNING */
g_assignedtasks,
TLIST_ATTR_PRIORITIZED | TLIST_ATTR_INDEXED
TLIST_ATTR_PRIORITIZED | TLIST_ATTR_INDEXED | TLIST_ATTR_RUNNABLE
},
#else
{ /* TSTATE_TASK_READYTORUN */
&g_readytorun,
TLIST_ATTR_PRIORITIZED | TLIST_ATTR_RUNNABLE
},
{ /* TSTATE_TASK_RUNNING */
&g_readytorun,
TLIST_ATTR_PRIORITIZED
TLIST_ATTR_PRIORITIZED | TLIST_ATTR_RUNNABLE
},
#endif
{ /* TSTATE_TASK_INACTIVE */

View File

@ -82,10 +82,12 @@
#define TLIST_ATTR_PRIORITIZED (1 << 0) /* Bit 0: List is prioritized */
#define TLIST_ATTR_INDEXED (1 << 1) /* Bit 1: List is indexed by CPU */
#define TLIST_ATTR_RUNNABLE (1 << 2) /* Bit 2: List includes running tasks */
#define __TLIST_ATTR(s) g_tasklisttable[s].attr
#define TLIST_ISPRIORITIZED(s) ((__TLIST_ATTR(s) & TLIST_ATTR_PRIORITIZED) != 0)
#define TLIST_ISINDEXED(s) ((__TLIST_ATTR(s) & TLIST_ATTR_INDEXED) != 0)
#define TLIST_ISRUNNABLE(s) ((__TLIST_ATTR(s) & TLIST_ATTR_RUNNABLE) != 0)
#define __TLIST_HEAD(s) (FAR dq_queue_t *)g_tasklisttable[s].list
#define __TLIST_HEADINDEXED(s,c) (&(__TLIST_HEAD(s))[c])

View File

@ -76,11 +76,31 @@ bool sched_removereadytorun(FAR struct tcb_s *rtcb)
FAR dq_queue_t *tasklist;
bool ret = false;
/* Check if the TCB to be removed is at the head of the ready to run list.
* In this case, we are removing the currently active task on this CPU.
/* Check if the TCB to be removed is at the head of a ready to run list. */
#ifdef CONFIG_SMP
/* For the case of SMP, there are two lists involved: (1) the
* g_readytorun list that holds non-running tasks that have not been
* assigned to a CPU, and (2) and the g_assignedtasks[] lists which hold
* tasks assigned a CPU, including the task that is currently running on
* that CPU. Only this latter list contains the currently active task
* only only removing the head of that list can result in a context
* switch.
*
* The tasklist RUNNABLE attribute will inform us if the list holds the
* currently executing and task and, hence, if a context switch could
* occur.
*/
if (!rtcb->blink || TLIST_ISRUNNABLE(rtcb->task_state))
#else
/* There is only one list, g_readytorun, and it always contains the
* currently running task. If we are removing the head of this list,
* then we are removing the currently active task.
*/
if (!rtcb->blink)
#endif
{
/* There must always be at least one task in the list (the idle task) */