diff --git a/ChangeLog b/ChangeLog index c8209c9b9b..a994b05c15 100755 --- a/ChangeLog +++ b/ChangeLog @@ -11480,4 +11480,7 @@ * arch/arm/sim/up_head.c and up_simsmp.c: Add multi-CPU support to the simulation to support SMP investigation.. Currently crashes when CONFIG_SMP is enabled as expected (2016-02-10). + * sched/sched.h and other files: Replace the bool 'prioritized' in the task + list table with a uint8_t bit set so that additional attributes of a task + list can be provided without adding more booleans (2016-10-11). diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index d20a264895..a0f3d13792 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -150,6 +150,7 @@ # define TCB_FLAG_SCHED_OTHER (3 << TCB_FLAG_POLICY_SHIFT) /* Other scheding policy */ #define TCB_FLAG_CPU_ASSIGNED (1 << 6) /* Bit 6: Assigned to a CPU */ #define TCB_FLAG_EXIT_PROCESSING (1 << 7) /* Bit 7: Exitting */ + /* Bits 8-15: Available */ /* Values for struct task_group tg_flags */ @@ -157,6 +158,7 @@ #define GROUP_FLAG_ADDRENV (1 << 1) /* Bit 1: Group has an address environment */ #define GROUP_FLAG_PRIVILEGED (1 << 2) /* Bit 2: Group is privileged */ #define GROUP_FLAG_DELETED (1 << 3) /* Bit 3: Group has been deleted but not yet freed */ + /* Bits 4-7: Available */ /* Values for struct child_status_s ch_flags */ @@ -166,12 +168,14 @@ # define CHILD_FLAG_TTYPE_PTHREAD (1 << CHILD_FLAG_TTYPE_SHIFT) /* User pthread */ # define CHILD_FLAG_TTYPE_KERNEL (2 << CHILD_FLAG_TTYPE_SHIFT) /* Kernel thread */ #define CHILD_FLAG_EXITED (1 << 0) /* Bit 2: The child thread has exit'ed */ + /* Bits 3-7: Available */ /* Sporadic scheduler flags */ #define SPORADIC_FLAG_ALLOCED (1 << 0) /* Bit 0: Timer is allocated */ #define SPORADIC_FLAG_MAIN (1 << 1) /* Bit 1: The main timer */ #define SPORADIC_FLAG_REPLENISH (1 << 2) /* Bit 2: Replenishment cycle */ + /* Bits 3-7: Available */ /******************************************************************************** * Public Type Definitions @@ -191,6 +195,9 @@ enum tstate_e TSTATE_TASK_INVALID = 0, /* INVALID - The TCB is uninitialized */ TSTATE_TASK_PENDING, /* READY_TO_RUN - Pending preemption unlock */ TSTATE_TASK_READYTORUN, /* READY-TO-RUN - But not running */ +#ifdef CONFIG_SMP + TSTATE_TASK_ASSIGNED, /* READY-TO-RUN - Not running, but assigned to a CPU */ +#endif TSTATE_TASK_RUNNING, /* READY_TO_RUN - And running */ TSTATE_TASK_INACTIVE, /* BLOCKED - Initialized but not yet activated */ diff --git a/sched/init/os_start.c b/sched/init/os_start.c index 9bfcc9c7c2..95fd9526c9 100644 --- a/sched/init/os_start.c +++ b/sched/init/os_start.c @@ -203,8 +203,8 @@ volatile pid_t g_lastpid; /* The following hash table is used for two things: * - * 1. This hash table greatly speeds the determination of - * a new unique process ID for a task, and + * 1. This hash table greatly speeds the determination of a new unique + * process ID for a task, and * 2. Is used to quickly map a process ID into a TCB. * It has the side effects of using more memory and limiting * @@ -213,33 +213,74 @@ volatile pid_t g_lastpid; struct pidhash_s g_pidhash[CONFIG_MAX_TASKS]; -/* This is a table of task lists. This table is indexed by - * the task state enumeration type (tstate_t) and provides - * a pointer to the associated static task list (if there - * is one) as well as a boolean indication as to if the list - * is an ordered list or not. +/* This is a table of task lists. This table is indexed by the task stat + * enumeration type (tstate_t) and provides a pointer to the associated + * static task list (if there is one) as well as a a set of attribute flags + * indicating properities of the list, for example, if the list is an + * ordered list or not. */ const struct tasklist_s g_tasklisttable[NUM_TASK_STATES] = { - { NULL, false }, /* TSTATE_TASK_INVALID */ - { &g_pendingtasks, true }, /* TSTATE_TASK_PENDING */ - { &g_readytorun, true }, /* TSTATE_TASK_READYTORUN */ - { &g_readytorun, true }, /* TSTATE_TASK_RUNNING */ - { &g_inactivetasks, false }, /* TSTATE_TASK_INACTIVE */ - { &g_waitingforsemaphore, true } /* TSTATE_WAIT_SEM */ + { /* TSTATE_TASK_INVALID */ + NULL, + 0 + }, + { /* TSTATE_TASK_PENDING */ + &g_pendingtasks, + TLIST_ATTR_PRIORITIZED + }, + { /* TSTATE_TASK_READYTORUN */ + &g_readytorun, + TLIST_ATTR_PRIORITIZED + }, +#ifdef CONFIG_SMP + { /* TSTATE_TASK_ASSIGNED */ + g_assignedtasks, + TLIST_ATTR_PRIORITIZED | TLIST_ATTR_INDEXED + }, + { /* TSTATE_TASK_RUNNING */ + g_assignedtasks, + TLIST_ATTR_PRIORITIZED | TLIST_ATTR_INDEXED + }, +#else + { /* TSTATE_TASK_RUNNING */ + &g_readytorun, + TLIST_ATTR_PRIORITIZED + }, +#endif + { /* TSTATE_TASK_INACTIVE */ + &g_inactivetasks, + 0 + }, + { /* TSTATE_WAIT_SEM */ + &g_waitingforsemaphore, + TLIST_ATTR_PRIORITIZED + } #ifndef CONFIG_DISABLE_SIGNALS , - { &g_waitingforsignal, false } /* TSTATE_WAIT_SIG */ + { /* TSTATE_WAIT_SIG */ + &g_waitingforsignal, + 0 + } #endif #ifndef CONFIG_DISABLE_MQUEUE , - { &g_waitingformqnotempty, true }, /* TSTATE_WAIT_MQNOTEMPTY */ - { &g_waitingformqnotfull, true } /* TSTATE_WAIT_MQNOTFULL */ + { /* TSTATE_WAIT_MQNOTEMPTY */ + &g_waitingformqnotempty, + TLIST_ATTR_PRIORITIZED + }, + { /* TSTATE_WAIT_MQNOTFULL */ + &g_waitingformqnotfull, + TLIST_ATTR_PRIORITIZED + } #endif #ifdef CONFIG_PAGING , - { &g_waitingforfill, true } /* TSTATE_WAIT_PAGEFILL */ + { /* TSTATE_WAIT_PAGEFILL */ + &g_waitingforfill, + TLIST_ATTR_PRIORITIZED + } #endif }; @@ -360,7 +401,16 @@ void os_start(void) bzero((void *)&g_idletcb, sizeof(struct task_tcb_s)); g_idletcb.cmn.task_state = TSTATE_TASK_RUNNING; g_idletcb.cmn.entry.main = (main_t)os_start; + + /* Set the task flags to indicate that this is a kernel thread and, if + * configured for SMP, that this task is assigned to CPU0. + */ + +#ifdef CONFIG_SMP + g_idletcb.cmn.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_CPU_ASSIGNED); +#else g_idletcb.cmn.flags = TCB_FLAG_TTYPE_KERNEL; +#endif /* Set the IDLE task name */ diff --git a/sched/sched/sched.h b/sched/sched/sched.h index ed03755dc7..1838a559e6 100644 --- a/sched/sched/sched.h +++ b/sched/sched/sched.h @@ -62,21 +62,44 @@ * tasks built into the design). */ -#define MAX_TASKS_MASK (CONFIG_MAX_TASKS-1) -#define PIDHASH(pid) ((pid) & MAX_TASKS_MASK) +#define MAX_TASKS_MASK (CONFIG_MAX_TASKS-1) +#define PIDHASH(pid) ((pid) & MAX_TASKS_MASK) /* These are macros to access the current CPU and the current task on a CPU. * These macros are intended to support a future SMP implementation. */ #ifdef CONFIG_SMP -# define current_task(cpu) ((FAR struct tcb_s *)g_assignedtasks[cpu].head) -# define this_cpu() up_cpundx() +# define current_task(cpu) ((FAR struct tcb_s *)g_assignedtasks[cpu].head) +# define this_cpu() up_cpundx() #else -# define current_task(cpu) ((FAR struct tcb_s *)g_readytorun.head) -# define this_cpu() (0) +# define current_task(cpu) ((FAR struct tcb_s *)g_readytorun.head) +# define this_cpu() (0) +#endif +#define this_task() (current_task(this_cpu())) + +/* List attribute flags */ + +#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(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_HEAD(s) (FAR dq_queue_t *)g_tasklisttable[s].list +#define __TLIST_HEADINDEXED(s,c) (&(__TLIST_HEAD(s))[c]) + +#ifdef CONFIG_SMP +# define TLIST_HEAD(s,c) \ + ((TLIST_ISINDEXED(s)) ? __TLIST_HEADINDEXED(s,c) : __TLIST_HEAD(s)) +# define TLIST_READYTORUN(s,c) __TLIST_HEADINDEXED(s,c) +# define TLIST_BLOCKED(s) __TLIST_HEAD(s) +#else +# define TLIST_HEAD(s) __TLIST_HEAD(s) +# define TLIST_READYTORUN(s) __TLIST_HEAD(s) +# define TLIST_BLOCKED(s) __TLIST_HEAD(s) #endif -#define this_task() (current_task(this_cpu())) /**************************************************************************** * Public Type Definitions @@ -102,15 +125,14 @@ struct pidhash_s #endif }; -/* This structure defines an element of the g_tasklisttable[]. - * This table is used to map a task_state enumeration to the - * corresponding task list. +/* This structure defines an element of the g_tasklisttable[]. This table + * is used to map a task_state enumeration to the corresponding task list. */ struct tasklist_s { DSEG volatile dq_queue_t *list; /* Pointer to the task list */ - bool prioritized; /* true if the list is prioritized */ + uint8_t attr; /* List attribute flags */ }; /**************************************************************************** @@ -255,10 +277,11 @@ extern volatile pid_t g_lastpid; extern struct pidhash_s g_pidhash[CONFIG_MAX_TASKS]; -/* This is a table of task lists. This table is indexed by the task state +/* This is a table of task lists. This table is indexed by the task stat * enumeration type (tstate_t) and provides a pointer to the associated - * static task list (if there is one) as well as a boolean indication as to - * if the list is an ordered list or not. + * static task list (if there is one) as well as a a set of attribute flags + * indicating properities of the list, for example, if the list is an + * ordered list or not. */ extern const struct tasklist_s g_tasklisttable[NUM_TASK_STATES]; diff --git a/sched/sched/sched_addblocked.c b/sched/sched/sched_addblocked.c index 05a8742431..34303681c5 100644 --- a/sched/sched/sched_addblocked.c +++ b/sched/sched/sched_addblocked.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sched/sched_addblocked.c * - * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009, 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -44,26 +44,6 @@ #include "sched/sched.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Type Declarations - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -90,29 +70,30 @@ void sched_addblocked(FAR struct tcb_s *btcb, tstate_t task_state) { + FAR dq_queue_t *tasklist; + /* Make sure that we received a valid blocked state */ - ASSERT(task_state >= FIRST_BLOCKED_STATE && - task_state <= LAST_BLOCKED_STATE); + DEBUGASSERT(task_state >= FIRST_BLOCKED_STATE && + task_state <= LAST_BLOCKED_STATE); - /* Add the TCB to the blocked task list associated with this state. - * First, determine if the task is to be added to a prioritized task - * list - */ + /* Add the TCB to the blocked task list associated with this state. */ - if (g_tasklisttable[task_state].prioritized) + tasklist = TLIST_BLOCKED(task_state); + + /* Determine if the task is to be added to a prioritized task list. */ + + if (TLIST_ISPRIORITIZED(task_state)) { /* Add the task to a prioritized list */ - sched_addprioritized(btcb, - (FAR dq_queue_t *)g_tasklisttable[task_state].list); + sched_addprioritized(btcb, tasklist); } else { /* Add the task to a non-prioritized list */ - dq_addlast((FAR dq_entry_t *)btcb, - (FAR dq_queue_t *)g_tasklisttable[task_state].list); + dq_addlast((FAR dq_entry_t *)btcb, tasklist); } /* Make sure the TCB's state corresponds to the list */ diff --git a/sched/sched/sched_removeblocked.c b/sched/sched/sched_removeblocked.c index 7b6b983b04..36c92e96f0 100644 --- a/sched/sched/sched_removeblocked.c +++ b/sched/sched/sched_removeblocked.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sched/sched_removeblocked.c * - * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009, 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -44,26 +44,6 @@ #include "sched/sched.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Type Declarations - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -93,15 +73,14 @@ void sched_removeblocked(FAR struct tcb_s *btcb) /* Make sure the TCB is in a valid blocked state */ - ASSERT(task_state >= FIRST_BLOCKED_STATE && - task_state <= LAST_BLOCKED_STATE); + DEBUGASSERT(task_state >= FIRST_BLOCKED_STATE && + task_state <= LAST_BLOCKED_STATE); /* Remove the TCB from the blocked task list associated * with this state */ - dq_rem((FAR dq_entry_t *)btcb, - (FAR dq_queue_t *)g_tasklisttable[task_state].list); + dq_rem((FAR dq_entry_t *)btcb, TLIST_BLOCKED(task_state)); /* Make sure the TCB's state corresponds to not being in * any list @@ -109,4 +88,3 @@ void sched_removeblocked(FAR struct tcb_s *btcb) btcb->task_state = TSTATE_TASK_INVALID; } - diff --git a/sched/sched/sched_setpriority.c b/sched/sched/sched_setpriority.c index 3089756eec..5af005e2b7 100644 --- a/sched/sched/sched_setpriority.c +++ b/sched/sched/sched_setpriority.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sched/sched_setpriority.c * - * Copyright (C) 2009, 2013 Gregory Nutt. All rights reserved. + * Copyright (C) 2009, 2013, 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -46,30 +46,6 @@ #include "sched/sched.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Type Declarations - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -104,6 +80,7 @@ int sched_setpriority(FAR struct tcb_s *tcb, int sched_priority) { FAR struct tcb_s *rtcb = this_task(); + FAR dq_queue_t *tasklist; tstate_t task_state; irqstate_t saved_state; @@ -127,8 +104,8 @@ int sched_setpriority(FAR struct tcb_s *tcb, int sched_priority) task_state = tcb->task_state; switch (task_state) { - /* CASE 1. The task is running or ready-to-run and a context switch - * may be caused by the re-prioritization + /* CASE 1. The task is and a context switch may be caused by the + * re-prioritization */ case TSTATE_TASK_RUNNING: @@ -155,11 +132,14 @@ int sched_setpriority(FAR struct tcb_s *tcb, int sched_priority) } break; - /* CASE 2. The task is running or ready-to-run and a context switch - * may be caused by the re-prioritization + /* CASE 2. The task is ready-to-run (but not running) and a context + * switch may be caused by the re-prioritization */ case TSTATE_TASK_READYTORUN: +#ifdef CONFIG_SMP + case TSTATE_TASK_ASSIGNED: +#endif /* A context switch will occur if the new priority of the ready-to * run task is (strictly) greater than the current running task @@ -188,7 +168,7 @@ int sched_setpriority(FAR struct tcb_s *tcb, int sched_priority) /* Put it back into the ready-to-run task list */ - ASSERT(!sched_addreadytorun(tcb)); + DEBUGASSERT(!sched_addreadytorun(tcb)); } break; @@ -200,12 +180,12 @@ int sched_setpriority(FAR struct tcb_s *tcb, int sched_priority) /* CASE 3a. The task resides in a prioritized list. */ - if (g_tasklisttable[task_state].prioritized) + tasklist = TLIST_BLOCKED(task_state); + if (TLIST_ISPRIORITIZED(task_state)) { /* Remove the TCB from the prioritized task list */ - dq_rem((FAR dq_entry_t *)tcb, - (FAR dq_queue_t *)g_tasklisttable[task_state].list); + dq_rem((FAR dq_entry_t *)tcb, tasklist); /* Change the task priority */ @@ -215,8 +195,7 @@ int sched_setpriority(FAR struct tcb_s *tcb, int sched_priority) * position */ - sched_addprioritized(tcb, - (FAR dq_queue_t *)g_tasklisttable[task_state].list); + sched_addprioritized(tcb, tasklist); } /* CASE 3b. The task resides in a non-prioritized list. */ diff --git a/sched/task/task_restart.c b/sched/task/task_restart.c index 71c6f77adc..f72507756c 100644 --- a/sched/task/task_restart.c +++ b/sched/task/task_restart.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/task/task_restart.c * - * Copyright (C) 2007, 2009, 2012-2013 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009, 2012-2013, 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -80,6 +80,7 @@ int task_restart(pid_t pid) { FAR struct tcb_s *rtcb; FAR struct task_tcb_s *tcb; + FAR dq_queue_t *tasklist; irqstate_t state; int status; @@ -100,84 +101,102 @@ int task_restart(pid_t pid) return ERROR; } - /* We are restarting some other task than ourselves */ +#ifdef CONFIG_SMP + /* There is currently no capability to restart a task that is actively + * running on another CPU either. This is not the calling cast so if it + * is running, then it could only be running a a different CPU. + * + * Also, will need some interlocks to assure that no tasks are rescheduled + * on any other CPU while we do this. + */ - else +#warning Missing SMP logic + if (rtcb->task_state == TSTATE_TASK_RUNNING) { - /* Find for the TCB associated with matching pid */ + /* Not implemented */ - tcb = (FAR struct task_tcb_s *)sched_gettcb(pid); -#ifndef CONFIG_DISABLE_PTHREAD - if (!tcb || (tcb->cmn.flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD) -#else - if (!tcb) + set_errno(ENOSYS); + return ERROR; + } #endif - { - /* There is no TCB with this pid or, if there is, it is not a - * task. - */ - set_errno(ESRCH); - return ERROR; - } + /* We are restarting some other task than ourselves */ + /* Find for the TCB associated with matching pid */ - /* Try to recover from any bad states */ + tcb = (FAR struct task_tcb_s *)sched_gettcb(pid); +#ifndef CONFIG_DISABLE_PTHREAD + if (!tcb || (tcb->cmn.flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD) +#else + if (!tcb) +#endif + { + /* There is no TCB with this pid or, if there is, it is not a task. */ - task_recover((FAR struct tcb_s *)tcb); + set_errno(ESRCH); + return ERROR; + } - /* Kill any children of this thread */ + /* Try to recover from any bad states */ + + task_recover((FAR struct tcb_s *)tcb); + + /* Kill any children of this thread */ #ifdef HAVE_GROUP_MEMBERS - (void)group_killchildren(tcb); + (void)group_killchildren(tcb); #endif - /* Remove the TCB from whatever list it is in. At this point, the - * TCB should no longer be accessible to the system - */ + /* Remove the TCB from whatever list it is in. After this point, the TCB + * should no longer be accessible to the system + */ - state = irqsave(); - dq_rem((FAR dq_entry_t *)tcb, - (FAR dq_queue_t *)g_tasklisttable[tcb->cmn.task_state].list); - tcb->cmn.task_state = TSTATE_TASK_INVALID; - irqrestore(state); +#ifdef CONFIG_SMP + tasklist = TLIST_HEAD(tcb->cmn.task_state, tcb->cmn.cpu); +#else + tasklist = TLIST_HEAD(tcb->cmn.task_state); +#endif - /* Deallocate anything left in the TCB's queues */ + state = irqsave(); + dq_rem((FAR dq_entry_t *)tcb, tasklist); + tcb->cmn.task_state = TSTATE_TASK_INVALID; + irqrestore(state); - sig_cleanup((FAR struct tcb_s *)tcb); /* Deallocate Signal lists */ + /* Deallocate anything left in the TCB's queues */ - /* Reset the current task priority */ + sig_cleanup((FAR struct tcb_s *)tcb); /* Deallocate Signal lists */ - tcb->cmn.sched_priority = tcb->init_priority; + /* Reset the current task priority */ - /* Reset the base task priority and the number of pending reprioritizations */ + tcb->cmn.sched_priority = tcb->init_priority; + + /* Reset the base task priority and the number of pending reprioritizations */ #ifdef CONFIG_PRIORITY_INHERITANCE - tcb->cmn.base_priority = tcb->init_priority; + tcb->cmn.base_priority = tcb->init_priority; # if CONFIG_SEM_NNESTPRIO > 0 - tcb->cmn.npend_reprio = 0; + tcb->cmn.npend_reprio = 0; # endif #endif - /* Re-initialize the processor-specific portion of the TCB - * This will reset the entry point and the start-up parameters - */ + /* Re-initialize the processor-specific portion of the TCB. This will + * reset the entry point and the start-up parameters + */ - up_initial_state((FAR struct tcb_s *)tcb); + up_initial_state((FAR struct tcb_s *)tcb); - /* Add the task to the inactive task list */ + /* Add the task to the inactive task list */ - dq_addfirst((FAR dq_entry_t *)tcb, (FAR dq_queue_t *)&g_inactivetasks); - tcb->cmn.task_state = TSTATE_TASK_INACTIVE; + dq_addfirst((FAR dq_entry_t *)tcb, (FAR dq_queue_t *)&g_inactivetasks); + tcb->cmn.task_state = TSTATE_TASK_INACTIVE; - /* Activate the task */ + /* Activate the task */ - status = task_activate((FAR struct tcb_s *)tcb); - if (status != OK) - { - (void)task_delete(pid); - set_errno(-status); - return ERROR; - } + status = task_activate((FAR struct tcb_s *)tcb); + if (status != OK) + { + (void)task_delete(pid); + set_errno(-status); + return ERROR; } sched_unlock(); diff --git a/sched/task/task_terminate.c b/sched/task/task_terminate.c index 684c09da8d..f3abb7d825 100644 --- a/sched/task/task_terminate.c +++ b/sched/task/task_terminate.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/task/task_terminate.c * - * Copyright (C) 2007-2009, 2011-2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2011-2014, 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -53,30 +53,6 @@ #endif #include "task/task.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Type Declarations - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -124,6 +100,7 @@ int task_terminate(pid_t pid, bool nonblocking) { FAR struct tcb_s *dtcb; + FAR dq_queue_t *tasklist; irqstate_t saved_state; /* Make sure the task does not become ready-to-run while we are futzing with @@ -143,6 +120,14 @@ int task_terminate(pid_t pid, bool nonblocking) return -ESRCH; } +#ifdef CONFIG_SMP + /* We will need some interlocks to assure that no tasks are rescheduled + * on any other CPU while we do this. + */ + +# warning Missing SMP logic +#endif + /* Verify our internal sanity */ if (dtcb->task_state == TSTATE_TASK_RUNNING || @@ -165,11 +150,16 @@ int task_terminate(pid_t pid, bool nonblocking) task_exithook(dtcb, EXIT_SUCCESS, nonblocking); - /* Remove the task from the OS's tasks lists. */ + /* Remove the task from the OS's task lists. */ + +#ifdef CONFIG_SMP + tasklist = TLIST_HEAD(dtcb->task_state, dtcb->cpu); +#else + tasklist = TLIST_HEAD(dtcb->task_state); +#endif saved_state = irqsave(); - dq_rem((FAR dq_entry_t *)dtcb, - (FAR dq_queue_t *)g_tasklisttable[dtcb->task_state].list); + dq_rem((FAR dq_entry_t *)dtcb, tasklist); dtcb->task_state = TSTATE_TASK_INVALID; irqrestore(saved_state);