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

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

commit 838309313e177d207fc59c039e77050e8f6ee8ec
Author: zhangyuan21 <zhangyua...@xiaomi.com>
AuthorDate: Mon Sep 19 18:17:14 2022 +0800

    sched: semaphore wait list optimize
---
 include/nuttx/semaphore.h            | 12 +++++++++---
 include/semaphore.h                  | 19 ++++++++++++++++---
 libs/libc/semaphore/sem_init.c       |  4 ++++
 sched/init/nx_start.c                | 12 ++++--------
 sched/sched/sched.h                  | 21 ++++++++++-----------
 sched/sched/sched_addblocked.c       | 10 +++++-----
 sched/sched/sched_removeblocked.c    |  2 +-
 sched/sched/sched_removereadytorun.c |  2 +-
 sched/sched/sched_setpriority.c      |  2 +-
 sched/semaphore/sem_post.c           |  4 +---
 sched/task/task_restart.c            |  4 ++--
 sched/task/task_terminate.c          |  4 ++--
 12 files changed, 56 insertions(+), 40 deletions(-)

diff --git a/include/nuttx/semaphore.h b/include/nuttx/semaphore.h
index 736113c96e..3ad14d514e 100644
--- a/include/nuttx/semaphore.h
+++ b/include/nuttx/semaphore.h
@@ -40,15 +40,21 @@
 
 #ifdef CONFIG_PRIORITY_INHERITANCE
 # if CONFIG_SEM_PREALLOCHOLDERS > 0
+/* semcount, waitlist, flags, hhead */
+
 #  define NXSEM_INITIALIZER(c, f) \
-    {(c), (f), NULL}                    /* semcount, flags, hhead */
+    {(c), SEM_WAITLIST_INITIALIZER, (f), NULL}
 # else
+/* semcount, waitlist, flags, holder[2] */
+
 #  define NXSEM_INITIALIZER(c, f) \
-    {(c), (f), {SEMHOLDER_INITIALIZER, SEMHOLDER_INITIALIZER}}  /* semcount, 
flags, holder[2] */
+    {(c), SEM_WAITLIST_INITIALIZER, (f), {SEMHOLDER_INITIALIZER, 
SEMHOLDER_INITIALIZER}}
 # endif
 #else /* CONFIG_PRIORITY_INHERITANCE */
+/* semcount, waitlist */
+
 #  define NXSEM_INITIALIZER(c, f) \
-    {(c)}                               /* semcount, flags */
+    {(c), SEM_WAITLIST_INITIALIZER}
 #endif /* CONFIG_PRIORITY_INHERITANCE */
 
 /* Most internal nxsem_* interfaces are not available in the user space in
diff --git a/include/semaphore.h b/include/semaphore.h
index 6d377b1b87..bfc6122818 100644
--- a/include/semaphore.h
+++ b/include/semaphore.h
@@ -30,6 +30,7 @@
 #include <stdint.h>
 #include <limits.h>
 #include <time.h>
+#include <nuttx/queue.h>
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -93,6 +94,8 @@ struct semholder_s
 #endif
 #endif /* CONFIG_PRIORITY_INHERITANCE */
 
+#define SEM_WAITLIST_INITIALIZER {NULL, NULL}
+
 /* This is the generic semaphore structure. */
 
 struct sem_s
@@ -100,6 +103,8 @@ struct sem_s
   volatile int16_t semcount;     /* >0 -> Num counts available */
                                  /* <0 -> Num tasks waiting for semaphore */
 
+  dq_queue_t waitlist;
+
   /* If priority inheritance is enabled, then we have to keep track of which
    * tasks hold references to the semaphore.
    */
@@ -120,17 +125,25 @@ typedef struct sem_s sem_t;
 
 #ifdef CONFIG_PRIORITY_INHERITANCE
 # if CONFIG_SEM_PREALLOCHOLDERS > 0
+/* semcount, waitlist, flags, hhead */
+
 #  define SEM_INITIALIZER(c) \
-    {(c), 0, NULL}               /* semcount, flags, hhead */
+    {(c), SEM_WAITLIST_INITIALIZER, 0, NULL}
 # else
+/* semcount, waitlist, flags, holder[2] */
+
 #  define SEM_INITIALIZER(c) \
-    {(c), 0, {SEMHOLDER_INITIALIZER, SEMHOLDER_INITIALIZER}} /* semcount, 
flags, holder[2] */
+    {(c), SEM_WAITLIST_INITIALIZER, 0, {SEMHOLDER_INITIALIZER, 
SEMHOLDER_INITIALIZER}}
 # endif
 #else
+/* semcount, waitlist */
+
 #  define SEM_INITIALIZER(c) \
-    {(c)}                        /* semcount */
+    {(c), SEM_WAITLIST_INITIALIZER}
 #endif
 
+# define SEM_WAITLIST(sem)        (&((sem)->waitlist))
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
diff --git a/libs/libc/semaphore/sem_init.c b/libs/libc/semaphore/sem_init.c
index 785403599d..f4f276b6fa 100644
--- a/libs/libc/semaphore/sem_init.c
+++ b/libs/libc/semaphore/sem_init.c
@@ -73,6 +73,10 @@ int nxsem_init(FAR sem_t *sem, int pshared, unsigned int 
value)
 
       sem->semcount         = (int16_t)value;
 
+      /* Initialize semaphore wait list */
+
+      dq_init(&sem->waitlist);
+
       /* Initialize to support priority inheritance */
 
 #ifdef CONFIG_PRIORITY_INHERITANCE
diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c
index 52b13279d1..4be3b50750 100644
--- a/sched/init/nx_start.c
+++ b/sched/init/nx_start.c
@@ -134,10 +134,6 @@ FAR struct tcb_s *g_running_tasks[CONFIG_SMP_NCPUS];
 
 dq_queue_t g_pendingtasks;
 
-/* This is the list of all tasks that are blocked waiting for a semaphore */
-
-dq_queue_t g_waitingforsemaphore;
-
 /* This is the list of all tasks that are blocked waiting for a signal */
 
 dq_queue_t g_waitingforsignal;
@@ -237,8 +233,8 @@ const struct tasklist_s g_tasklisttable[NUM_TASK_STATES] =
     0
   },
   {                                              /* TSTATE_WAIT_SEM */
-    &g_waitingforsemaphore,
-    TLIST_ATTR_PRIORITIZED
+    (FAR void *)offsetof(sem_t, waitlist),
+    TLIST_ATTR_PRIORITIZED | TLIST_ATTR_OFFSET
   },
   {                                              /* TSTATE_WAIT_SIG */
     &g_waitingforsignal,
@@ -429,9 +425,9 @@ void nx_start(void)
        */
 
 #ifdef CONFIG_SMP
-      tasklist = TLIST_HEAD(TSTATE_TASK_RUNNING, i);
+      tasklist = TLIST_HEAD(&g_idletcb[i].cmn, i);
 #else
-      tasklist = TLIST_HEAD(TSTATE_TASK_RUNNING);
+      tasklist = TLIST_HEAD(&g_idletcb[i].cmn);
 #endif
       dq_addfirst((FAR dq_entry_t *)&g_idletcb[i], tasklist);
 
diff --git a/sched/sched/sched.h b/sched/sched/sched.h
index 976c411583..82454fae1c 100644
--- a/sched/sched/sched.h
+++ b/sched/sched/sched.h
@@ -68,22 +68,25 @@
 #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_OFFSET        (1 << 3) /* Bit 3: Pointer of task list is 
offset */
 
 #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_ISOFFSET(s)        ((__TLIST_ATTR(s) & TLIST_ATTR_OFFSET) != 0)
 
-#define __TLIST_HEAD(s)          g_tasklisttable[s].list
-#define __TLIST_HEADINDEXED(s,c) (&(__TLIST_HEAD(s))[c])
+#define __TLIST_HEAD(t) \
+  (TLIST_ISOFFSET((t)->task_state) ? (FAR dq_queue_t *)((FAR uint8_t 
*)((t)->waitobj) + \
+  (uintptr_t)g_tasklisttable[(t)->task_state].list) : 
g_tasklisttable[(t)->task_state].list)
 
 #ifdef CONFIG_SMP
-#  define TLIST_HEAD(s,c) \
-  ((TLIST_ISINDEXED(s)) ? __TLIST_HEADINDEXED(s,c) : __TLIST_HEAD(s))
-#  define TLIST_BLOCKED(s)       __TLIST_HEAD(s)
+#  define TLIST_HEAD(t,c) \
+    ((TLIST_ISINDEXED((t)->task_state)) ? (&(__TLIST_HEAD(t))[c]) : 
__TLIST_HEAD(t))
+#  define TLIST_BLOCKED(t)       __TLIST_HEAD(t)
 #else
-#  define TLIST_HEAD(s)          __TLIST_HEAD(s)
-#  define TLIST_BLOCKED(s)       __TLIST_HEAD(s)
+#  define TLIST_HEAD(t)          __TLIST_HEAD(t)
+#  define TLIST_BLOCKED(t)       __TLIST_HEAD(t)
 #endif
 
 /****************************************************************************
@@ -171,10 +174,6 @@ extern FAR struct tcb_s *g_running_tasks[CONFIG_SMP_NCPUS];
 
 extern dq_queue_t g_pendingtasks;
 
-/* This is the list of all tasks that are blocked waiting for a semaphore */
-
-extern dq_queue_t g_waitingforsemaphore;
-
 /* This is the list of all tasks that are blocked waiting for a signal */
 
 extern dq_queue_t g_waitingforsignal;
diff --git a/sched/sched/sched_addblocked.c b/sched/sched/sched_addblocked.c
index c894b5e813..d81575f699 100644
--- a/sched/sched/sched_addblocked.c
+++ b/sched/sched/sched_addblocked.c
@@ -63,9 +63,13 @@ void nxsched_add_blocked(FAR struct tcb_s *btcb, tstate_t 
task_state)
   DEBUGASSERT(task_state >= FIRST_BLOCKED_STATE &&
               task_state <= LAST_BLOCKED_STATE);
 
+  /* Make sure the TCB's state corresponds to the list */
+
+  btcb->task_state = task_state;
+
   /* Add the TCB to the blocked task list associated with this state. */
 
-  tasklist = TLIST_BLOCKED(task_state);
+  tasklist = TLIST_BLOCKED(btcb);
 
   /* Determine if the task is to be added to a prioritized task list. */
 
@@ -81,8 +85,4 @@ void nxsched_add_blocked(FAR struct tcb_s *btcb, tstate_t 
task_state)
 
       dq_addlast((FAR dq_entry_t *)btcb, tasklist);
     }
-
-  /* Make sure the TCB's state corresponds to the list */
-
-  btcb->task_state = task_state;
 }
diff --git a/sched/sched/sched_removeblocked.c 
b/sched/sched/sched_removeblocked.c
index be7e348bb5..74c597c36f 100644
--- a/sched/sched/sched_removeblocked.c
+++ b/sched/sched/sched_removeblocked.c
@@ -66,7 +66,7 @@ void nxsched_remove_blocked(FAR struct tcb_s *btcb)
    * with this state
    */
 
-  dq_rem((FAR dq_entry_t *)btcb, TLIST_BLOCKED(task_state));
+  dq_rem((FAR dq_entry_t *)btcb, TLIST_BLOCKED(btcb));
 
   /* Indicate that the wait is over. */
 
diff --git a/sched/sched/sched_removereadytorun.c 
b/sched/sched/sched_removereadytorun.c
index a3c2e06756..0b168a15fb 100644
--- a/sched/sched/sched_removereadytorun.c
+++ b/sched/sched/sched_removereadytorun.c
@@ -130,7 +130,7 @@ bool nxsched_remove_readytorun(FAR struct tcb_s *rtcb)
    */
 
   cpu      = rtcb->cpu;
-  tasklist = TLIST_HEAD(rtcb->task_state, cpu);
+  tasklist = TLIST_HEAD(rtcb, cpu);
 
   /* Check if the TCB to be removed is at the head of a ready-to-run list.
    * For the case of SMP, there are two lists involved:  (1) the
diff --git a/sched/sched/sched_setpriority.c b/sched/sched/sched_setpriority.c
index e07cbadafc..2ae5bc11e7 100644
--- a/sched/sched/sched_setpriority.c
+++ b/sched/sched/sched_setpriority.c
@@ -278,7 +278,7 @@ static inline void nxsched_blocked_setpriority(FAR struct 
tcb_s *tcb,
 
   /* CASE 3a. The task resides in a prioritized list. */
 
-  tasklist = TLIST_BLOCKED(task_state);
+  tasklist = TLIST_BLOCKED(tcb);
   if (TLIST_ISPRIORITIZED(task_state))
     {
       /* Remove the TCB from the prioritized task list */
diff --git a/sched/semaphore/sem_post.c b/sched/semaphore/sem_post.c
index 917238355a..21bb59fbbb 100644
--- a/sched/semaphore/sem_post.c
+++ b/sched/semaphore/sem_post.c
@@ -139,9 +139,7 @@ int nxsem_post(FAR sem_t *sem)
            * that we want.
            */
 
-          for (stcb = (FAR struct tcb_s *)g_waitingforsemaphore.head;
-               (stcb && stcb->waitobj != sem);
-               stcb = stcb->flink);
+          stcb = (FAR struct tcb_s *)dq_peek(SEM_WAITLIST(sem));
 
           if (stcb != NULL)
             {
diff --git a/sched/task/task_restart.c b/sched/task/task_restart.c
index 50a9d11610..0a04c1481d 100644
--- a/sched/task/task_restart.c
+++ b/sched/task/task_restart.c
@@ -133,9 +133,9 @@ int nxtask_restart(pid_t pid)
    */
 
 #ifdef CONFIG_SMP
-  tasklist = TLIST_HEAD(tcb->cmn.task_state, tcb->cmn.cpu);
+  tasklist = TLIST_HEAD(&tcb->cmn, tcb->cmn.cpu);
 #else
-  tasklist = TLIST_HEAD(tcb->cmn.task_state);
+  tasklist = TLIST_HEAD(&tcb->cmn);
 #endif
 
   dq_rem((FAR dq_entry_t *)tcb, tasklist);
diff --git a/sched/task/task_terminate.c b/sched/task/task_terminate.c
index c38709db69..b2e73aaa67 100644
--- a/sched/task/task_terminate.c
+++ b/sched/task/task_terminate.c
@@ -131,13 +131,13 @@ int nxtask_terminate(pid_t pid, bool nonblocking)
 
   /* Get the task list associated with the thread's state and CPU */
 
-  tasklist = TLIST_HEAD(dtcb->task_state, cpu);
+  tasklist = TLIST_HEAD(dtcb, cpu);
 #else
   /* In the non-SMP case, we can be assured that the task to be terminated
    * is not running.  get the task list associated with the task state.
    */
 
-  tasklist = TLIST_HEAD(dtcb->task_state);
+  tasklist = TLIST_HEAD(dtcb);
 #endif
 
   /* Remove the task from the task list */

Reply via email to