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/nuttx.git

commit 900b1c19ddfaece35df7306ad368db72c6a32a78
Author: ouyangxiangzhen <ouyangxiangz...@xiaomi.com>
AuthorDate: Tue May 6 15:05:40 2025 +0800

    wqueue: improve the robustness of the work
    
    struct work_s
    {
      union
      {
        struct
        {
          struct dq_entry_s dq;      /* Implements a double linked list */
          clock_t qtime;             /* Time work queued */
        } s;
        struct wdog_s timer;         /* Delay expiry timer */
        struct wdog_period_s ptimer; /* Period expiry timer */
      } u;
      worker_t  worker;              /* Work callback */
      FAR void *arg;                 /* Callback argument */
      FAR struct kwork_wqueue_s *wq; /* Work queue */
    };
    
    work_cancel() should determine whether the current work is
    in the timer or has already entered the queue.
    This judgment is indispensable because the structure is a union.
    Whether it is interpreted as a timer or as a dq needs to be determined.
    
    But this judgment seriously depends on the order of struct wdog_s and
    struct dq_entry_s, once someone change the order of any, there is a bug.
    So we decide remove the union, to improve the robustness.
    
    For the work_s structure size will grow bigger, then we will provide a
    another optimization patch
    
    Signed-off-by: ligd <liguidi...@xiaomi.com>
    Signed-off-by: ouyangxiangzhen <ouyangxiangz...@xiaomi.com>
---
 include/nuttx/wdog.h              | 11 +++--------
 include/nuttx/wqueue.h            | 13 +++----------
 libs/libc/wqueue/work_cancel.c    |  2 +-
 libs/libc/wqueue/work_queue.c     | 14 +++++++-------
 libs/libc/wqueue/work_usrthread.c |  4 ++--
 5 files changed, 16 insertions(+), 28 deletions(-)

diff --git a/include/nuttx/wdog.h b/include/nuttx/wdog.h
index 90ba3fc85f..02f18b1b30 100644
--- a/include/nuttx/wdog.h
+++ b/include/nuttx/wdog.h
@@ -72,12 +72,7 @@ struct wdlist_node
   FAR struct wdlist_node *next;
 };
 
-/* This is the internal representation of the watchdog timer structure.
- * Notice !!!
- * Carefully with the struct wdog_s order, you may not directly modify
- * this. This struct will combine in struct work_s in union type, and,
- * wqueue will modify/check this struct in kwork work_qcancel().
- */
+/* Support a doubly linked list of watchdog timers */
 
 struct wdog_s
 {
@@ -87,7 +82,7 @@ struct wdog_s
 #ifdef CONFIG_PIC
   FAR void          *picbase;    /* PIC base address */
 #endif
-  clock_t            expired;    /* Timer associated with the absoulute time */
+  clock_t            expired;    /* Timer associated with the absolute time */
 };
 
 struct wdog_period_s
@@ -168,7 +163,7 @@ int wd_start(FAR struct wdog_s *wdog, sclock_t delay,
  *
  * Input Parameters:
  *   wdog     - Watchdog ID
- *   ticks    - Absoulute time in clock ticks
+ *   ticks    - Absolute time in clock ticks
  *   wdentry  - Function to call on timeout
  *   arg      - Parameter to pass to wdentry.
  *
diff --git a/include/nuttx/wqueue.h b/include/nuttx/wqueue.h
index 6155015540..f964608fbb 100644
--- a/include/nuttx/wqueue.h
+++ b/include/nuttx/wqueue.h
@@ -249,13 +249,10 @@ typedef CODE void (*worker_t)(FAR void *arg);
 
 struct work_s
 {
+  struct dq_entry_s dq;          /* Implements a double linked list */
+  clock_t qtime;                 /* Time work queued */
   union
   {
-    struct
-    {
-      struct dq_entry_s dq;      /* Implements a double linked list */
-      clock_t qtime;             /* Time work queued */
-    } s;
     struct wdog_s timer;         /* Delay expiry timer */
     struct wdog_period_s ptimer; /* Period expiry timer */
   } u;
@@ -560,11 +557,7 @@ int work_cancel_sync_wq(FAR struct kwork_wqueue_s *wqueue,
  *
  ****************************************************************************/
 
-#ifdef __KERNEL__
-#  define work_timeleft(work) wd_gettime(&((work)->u.timer))
-#else
-#  define work_timeleft(work) ((sclock_t)((work)->u.s.qtime - clock()))
-#endif
+#define work_timeleft(work) ((sclock_t)((work)->qtime - clock()))
 
 /****************************************************************************
  * Name: lpwork_boostpriority
diff --git a/libs/libc/wqueue/work_cancel.c b/libs/libc/wqueue/work_cancel.c
index 4a86335c2e..195f781a02 100644
--- a/libs/libc/wqueue/work_cancel.c
+++ b/libs/libc/wqueue/work_cancel.c
@@ -89,7 +89,7 @@ static int work_qcancel(FAR struct usr_wqueue_s *wqueue,
        */
 
       curr = wqueue->q.head;
-      while (curr && curr != &work->u.s.dq)
+      while (curr && curr != &work->dq)
         {
           prev = curr;
           curr = curr->flink;
diff --git a/libs/libc/wqueue/work_queue.c b/libs/libc/wqueue/work_queue.c
index 0a00bf6f2e..26b4acf9ff 100644
--- a/libs/libc/wqueue/work_queue.c
+++ b/libs/libc/wqueue/work_queue.c
@@ -87,9 +87,9 @@ static int work_qqueue(FAR struct usr_wqueue_s *wqueue,
 
   /* Initialize the work structure */
 
-  work->worker = worker;             /* Work callback. non-NULL means queued */
-  work->arg    = arg;                /* Callback argument */
-  work->u.s.qtime = clock() + delay; /* Delay until work performed */
+  work->worker = worker;          /* Work callback. non-NULL means queued */
+  work->arg    = arg;             /* Callback argument */
+  work->qtime  = clock() + delay; /* Delay until work performed */
 
   /* Do the easy case first -- when the work queue is empty. */
 
@@ -97,7 +97,7 @@ static int work_qqueue(FAR struct usr_wqueue_s *wqueue,
     {
       /* Add the watchdog to the head == tail of the queue. */
 
-      dq_addfirst(&work->u.s.dq, &wqueue->q);
+      dq_addfirst(&work->dq, &wqueue->q);
       nxsem_post(&wqueue->wake);
     }
 
@@ -111,7 +111,7 @@ static int work_qqueue(FAR struct usr_wqueue_s *wqueue,
 
       do
         {
-          delta = work->u.s.qtime - ((FAR struct work_s *)curr)->u.s.qtime;
+          delta = work->qtime - ((FAR struct work_s *)curr)->qtime;
           if (delta < 0)
             {
               break;
@@ -128,7 +128,7 @@ static int work_qqueue(FAR struct usr_wqueue_s *wqueue,
         {
           /* Insert the watchdog at the head of the list */
 
-          dq_addfirst(&work->u.s.dq, &wqueue->q);
+          dq_addfirst(&work->dq, &wqueue->q);
           nxsem_get_value(&wqueue->wake, &semcount);
           if (semcount < 1)
             {
@@ -139,7 +139,7 @@ static int work_qqueue(FAR struct usr_wqueue_s *wqueue,
         {
           /* Insert the watchdog in mid- or end-of-queue */
 
-          dq_addafter(prev, &work->u.s.dq, &wqueue->q);
+          dq_addafter(prev, &work->dq, &wqueue->q);
         }
     }
 
diff --git a/libs/libc/wqueue/work_usrthread.c 
b/libs/libc/wqueue/work_usrthread.c
index 8e4c679217..791cfd3e3e 100644
--- a/libs/libc/wqueue/work_usrthread.c
+++ b/libs/libc/wqueue/work_usrthread.c
@@ -125,7 +125,7 @@ static void work_process(FAR struct usr_wqueue_s *wqueue)
        * zero will always execute immediately.
        */
 
-      elapsed = clock() - work->u.s.qtime;
+      elapsed = clock() - work->qtime;
 
       /* Is this delay work ready? */
 
@@ -180,7 +180,7 @@ static void work_process(FAR struct usr_wqueue_s *wqueue)
         }
       else
         {
-          next = work->u.s.qtime - clock();
+          next = work->qtime - clock();
           break;
         }
     }

Reply via email to