This is an automated email from the ASF dual-hosted git repository.

jiuzhudong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 4cc384757bdfc195eaf7c20a7cf2fb36bc7de986
Author: Jukka Laitinen <jukka.laiti...@tii.ae>
AuthorDate: Fri Jul 18 00:28:28 2025 +0300

    sched: Change SMP list "g_assignedtasks" to a vector
    
    Since g_assignedtasks only holds the running task for each CPU, it can
    be just a vector. Idle tasks are already preserved in statically allocated
    structures "g_idletcb", and can be used from there.
    
    Signed-off-by: Jukka Laitinen <jukka.laiti...@tii.ae>
---
 sched/init/nx_start.c                | 49 ++++++++----------------------------
 sched/sched/sched.h                  | 31 +++++++++--------------
 sched/sched/sched_addreadytorun.c    | 16 +++---------
 sched/sched/sched_removereadytorun.c | 41 +++---------------------------
 4 files changed, 30 insertions(+), 107 deletions(-)

diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c
index 503580e3081..b52a5b52a1f 100644
--- a/sched/init/nx_start.c
+++ b/sched/init/nx_start.c
@@ -101,31 +101,19 @@ dq_queue_t g_readytorun;
  *    and
  *  - Tasks/threads that have not been assigned to a CPU.
  *
- * Otherwise, the TCB will be retained in an assigned task list,
- * g_assignedtasks.  As its name suggests, on 'g_assignedtasks queue for CPU
- * 'n' would contain only tasks/threads that are assigned to CPU 'n'.  Tasks/
+ * Otherwise, the running TCB will be retained in g_assignedtasks vector.
+ * As its name suggests, on 'g_assignedtasks vector for CPU
+ * 'n' would contain the task/thread which is assigned to CPU 'n'.  Tasks/
  * threads would be assigned a particular CPU by one of two mechanisms:
  *
  *  - (Semi-)permanently through an RTOS interfaces such as
  *    pthread_attr_setaffinity(), or
  *  - Temporarily through scheduling logic when a previously unassigned task
  *    is made to run.
- *
- * Tasks/threads that are assigned to a CPU via an interface like
- * pthread_attr_setaffinity() would never go into the g_readytorun list, but
- * would only go into the g_assignedtasks[n] list for the CPU 'n' to which
- * the thread has been assigned.  Hence, the g_readytorun list would hold
- * only unassigned tasks/threads.
- *
- * Like the g_readytorun list in in non-SMP case, each g_assignedtask[] list
- * is prioritized:  The head of the list is the currently active task on this
- * CPU.  Tasks after the active task are ready-to-run and assigned to this
- * CPU. The tail of this assigned task list, the lowest priority task, is
- * always the CPU's IDLE task.
  */
 
 #ifdef CONFIG_SMP
-dq_queue_t g_assignedtasks[CONFIG_SMP_NCPUS];
+FAR struct tcb_s *g_assignedtasks[CONFIG_SMP_NCPUS];
 enum task_deliver_e g_delivertasks[CONFIG_SMP_NCPUS];
 #endif
 
@@ -199,10 +187,6 @@ struct tasklist_s g_tasklisttable[NUM_TASK_STATES];
 
 volatile uint8_t g_nx_initstate;  /* See enum nx_initstate_e */
 
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
 /* This is an array of task control block (TCB) for the IDLE thread of each
  * CPU.  For the non-SMP case, this is a a single TCB; For the SMP case,
  * there is one TCB per CPU.  NOTE: The system boots on CPU0 into the IDLE
@@ -211,7 +195,11 @@ volatile uint8_t g_nx_initstate;  /* See enum 
nx_initstate_e */
  * bringing up the rest of the system.
  */
 
-static struct tcb_s g_idletcb[CONFIG_SMP_NCPUS];
+struct tcb_s g_idletcb[CONFIG_SMP_NCPUS];
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
 
 /* This is the name of the idle task */
 
@@ -251,19 +239,6 @@ static void tasklist_initialize(void)
   tlist[TSTATE_TASK_READYTORUN].list = list_readytorun();
   tlist[TSTATE_TASK_READYTORUN].attr = TLIST_ATTR_PRIORITIZED;
 
-  /* TSTATE_TASK_ASSIGNED */
-
-  tlist[TSTATE_TASK_ASSIGNED].list = list_assignedtasks(0);
-  tlist[TSTATE_TASK_ASSIGNED].attr = TLIST_ATTR_PRIORITIZED |
-                                     TLIST_ATTR_INDEXED |
-                                     TLIST_ATTR_RUNNABLE;
-
-  /* TSTATE_TASK_RUNNING */
-
-  tlist[TSTATE_TASK_RUNNING].list = list_assignedtasks(0);
-  tlist[TSTATE_TASK_RUNNING].attr = TLIST_ATTR_PRIORITIZED |
-                                    TLIST_ATTR_INDEXED |
-                                    TLIST_ATTR_RUNNABLE;
 #else
 
   /* TSTATE_TASK_PENDING */
@@ -346,7 +321,6 @@ static void tasklist_initialize(void)
 static void idle_task_initialize(void)
 {
   FAR struct tcb_s *tcb;
-  FAR dq_queue_t *tasklist;
   int i;
 
   memset(g_idletcb, 0, sizeof(g_idletcb));
@@ -422,11 +396,10 @@ static void idle_task_initialize(void)
        */
 
 #ifdef CONFIG_SMP
-      tasklist = TLIST_HEAD(tcb, i);
+      g_assignedtasks[i] = tcb;
 #else
-      tasklist = TLIST_HEAD(tcb);
+      dq_addfirst((FAR dq_entry_t *)tcb, TLIST_HEAD(tcb));
 #endif
-      dq_addfirst((FAR dq_entry_t *)tcb, tasklist);
 
       /* Mark the idle task as the running task */
 
diff --git a/sched/sched/sched.h b/sched/sched/sched.h
index 992edeedf77..7f1124b05bf 100644
--- a/sched/sched/sched.h
+++ b/sched/sched/sched.h
@@ -60,7 +60,6 @@
 #define list_waitingforfill()    (&g_waitingforfill)
 #define list_stoppedtasks()      (&g_stoppedtasks)
 #define list_inactivetasks()     (&g_inactivetasks)
-#define list_assignedtasks(cpu)  (&g_assignedtasks[cpu])
 
 /* 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.
@@ -68,7 +67,7 @@
  */
 
 #ifdef CONFIG_SMP
-#  define current_task(cpu)      ((FAR struct tcb_s 
*)list_assignedtasks(cpu)->head)
+#  define current_task(cpu)      (g_assignedtasks[cpu])
 #else
 #  define current_task(cpu)      ((FAR struct tcb_s *)list_readytorun()->head)
 #endif
@@ -176,36 +175,30 @@ extern dq_queue_t g_readytorun;
  *    and
  *  - Tasks/threads that have not been assigned to a CPU.
  *
- * Otherwise, the TCB will be retained in an assigned task list,
- * g_assignedtasks.  As its name suggests, on 'g_assignedtasks queue for CPU
- * 'n' would contain only tasks/threads that are assigned to CPU 'n'.  Tasks/
- * threads would be assigned a particular CPU by one of two mechanisms:
+ * Otherwise, the TCB will be retained in an assigned task vector,
+ * g_assignedtasks.  As its name suggests, on 'g_assignedtasks vector for CPU
+ * 'n' would contain only the task/thread which is running on the CPU 'n'.
+ * Tasks/threads would be assigned a particular CPU by one of two
+ * mechanisms:
  *
  *  - (Semi-)permanently through an RTOS interfaces such as
  *    pthread_attr_setaffinity(), or
  *  - Temporarily through scheduling logic when a previously unassigned task
  *    is made to run.
- *
- * Tasks/threads that are assigned to a CPU via an interface like
- * pthread_attr_setaffinity() would never go into the g_readytorun list, but
- * would only go into the g_assignedtasks[n] list for the CPU 'n' to which
- * the thread has been assigned.  Hence, the g_readytorun list would hold
- * only unassigned tasks/threads.
- *
- * Like the g_readytorun list in in non-SMP case, each g_assignedtask[] list
- * is prioritized:  The head of the list is the currently active task on this
- * CPU.  Tasks after the active task are ready-to-run and assigned to this
- * CPU. The tail of this assigned task list, the lowest priority task, is
- * always the CPU's IDLE task.
  */
 
-extern dq_queue_t g_assignedtasks[CONFIG_SMP_NCPUS];
+extern FAR struct tcb_s *g_assignedtasks[CONFIG_SMP_NCPUS];
 
 /* g_delivertasks is used to indicate that a task switch is scheduled for
  * another cpu to be processed.
  */
 
 extern enum task_deliver_e g_delivertasks[CONFIG_SMP_NCPUS];
+
+/* This is the list of idle tasks */
+
+extern FAR struct tcb_s g_idletcb[CONFIG_SMP_NCPUS];
+
 #endif
 
 /* This is the list of all tasks that are ready-to-run, but cannot be placed
diff --git a/sched/sched/sched_addreadytorun.c 
b/sched/sched/sched_addreadytorun.c
index b5d374f0b46..26e020f0498 100644
--- a/sched/sched/sched_addreadytorun.c
+++ b/sched/sched/sched_addreadytorun.c
@@ -181,33 +181,23 @@ bool nxsched_switch_running(int cpu, bool switch_equal)
       if (CPU_ISSET(cpu, &btcb->affinity) &&
           ((btcb->flags & TCB_FLAG_CPU_LOCKED) == 0 || btcb->cpu == cpu))
         {
-          FAR dq_queue_t *tasklist = list_assignedtasks(cpu);
-
           /* Found a task, remove it from ready-to-run list */
 
           dq_rem((FAR struct dq_entry_s *)btcb, list_readytorun());
 
-          /* Remove the current task from assigned tasks list and put it
-           * to the ready-to-run. But leave idle task.
-           */
-
           if (!is_idle_task(rtcb))
             {
-              dq_remfirst(tasklist);
+              /* Put currently running task back to ready-to-run list */
+
               rtcb->task_state = TSTATE_TASK_READYTORUN;
               nxsched_add_prioritized(rtcb, list_readytorun());
-
-              /* We should now have only the idle task assigned */
-
-              DEBUGASSERT(
-                is_idle_task((FAR struct tcb_s *)dq_peek(tasklist)));
             }
           else
             {
               rtcb->task_state = TSTATE_TASK_ASSIGNED;
             }
 
-          dq_addfirst((FAR dq_entry_t *)btcb, tasklist);
+          g_assignedtasks[cpu] = btcb;
           up_update_task(btcb);
 
           btcb->cpu = cpu;
diff --git a/sched/sched/sched_removereadytorun.c 
b/sched/sched/sched_removereadytorun.c
index 513d8f13cfc..0166c443fe6 100644
--- a/sched/sched/sched_removereadytorun.c
+++ b/sched/sched/sched_removereadytorun.c
@@ -137,7 +137,6 @@ void nxsched_remove_self(FAR struct tcb_s *tcb)
 #ifdef CONFIG_SMP
 static void nxsched_remove_running(FAR struct tcb_s *tcb)
 {
-  FAR dq_queue_t *tasklist;
   FAR struct tcb_s *nxttcb;
   int cpu;
 
@@ -149,40 +148,10 @@ static void nxsched_remove_running(FAR struct tcb_s *tcb)
               tcb->task_state == TSTATE_TASK_RUNNING);
 
   cpu = tcb->cpu;
-  tasklist = &g_assignedtasks[cpu];
-
-  /* Check if the TCB to be removed is at the head of a running list.
-   * 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 removing the head of that list can result in a context switch.
-   *
-   * tcb->blink == NULL will tell us if the TCB is at the head of the
-   * running list and, hence, a candidate for the new running task.
-   *
-   * If so, then the tasklist RUNNABLE attribute will inform us if the list
-   * holds the currently executing task and, hence, if a context switch
-   * should occur.
-   */
-
-  DEBUGASSERT(tcb->blink == NULL);
-  DEBUGASSERT(TLIST_ISRUNNABLE(tcb->task_state));
-
-  /* There must always be at least one task in the list (the IDLE task)
-   * after the TCB being removed.
-   */
-
-  nxttcb = tcb->flink;
-  DEBUGASSERT(nxttcb != NULL && is_idle_task(nxttcb));
 
-  /* The task is running but the CPU that it was running on has been
-   * paused.  We can now safely remove its TCB from the running
-   * task list.
-   */
+  /* Next task will be the idle task */
 
-  dq_remfirst(tasklist);
+  nxttcb = &g_idletcb[cpu];
 
   /* Since the TCB is no longer in any list, it is now invalid */
 
@@ -191,6 +160,7 @@ static void nxsched_remove_running(FAR struct tcb_s *tcb)
   /* Activate the idle task */
 
   nxttcb->task_state = TSTATE_TASK_RUNNING;
+  g_assignedtasks[cpu] = nxttcb;
   up_update_task(nxttcb);
 }
 
@@ -213,10 +183,7 @@ bool nxsched_remove_readytorun(FAR struct tcb_s *tcb)
 
       tasklist = TLIST_HEAD(tcb, tcb->cpu);
 
-      /* The task is not running.  Just remove its TCB from the task
-       * list.  In the SMP case this may be either the g_readytorun() or the
-       * g_assignedtasks[cpu] list.
-       */
+      /* The task is not running.  Just remove its TCB from the task list */
 
       dq_rem((FAR dq_entry_t *)tcb, tasklist);
 

Reply via email to