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

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


The following commit(s) were added to refs/heads/master by this push:
     new a8de4c998cb drivers/video: use spinlock to replace critical section 
for goldfish_fb and vnc
a8de4c998cb is described below

commit a8de4c998cbcebd73d81ede31c4f758d793d7e12
Author: jianglianfang <[email protected]>
AuthorDate: Thu Apr 17 15:06:16 2025 +0800

    drivers/video: use spinlock to replace critical section for goldfish_fb and 
vnc
    
    Critical sections only disable interrupts on the local CPU, which
    is insufficient for SMP. Replace with per-device spinlocks to
    ensure proper mutual exclusion across all cores.
    
    Signed-off-by: jianglianfang <[email protected]>
---
 drivers/video/goldfish_fb.c     |  6 ++++--
 drivers/video/vnc/vnc_server.h  |  3 +++
 drivers/video/vnc/vnc_updater.c | 25 ++++++++++++-------------
 3 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/video/goldfish_fb.c b/drivers/video/goldfish_fb.c
index a2b60005e64..b030a3bc853 100644
--- a/drivers/video/goldfish_fb.c
+++ b/drivers/video/goldfish_fb.c
@@ -29,6 +29,7 @@
 #include <nuttx/video/fb.h>
 #include <nuttx/irq.h>
 #include <nuttx/kmalloc.h>
+#include <nuttx/spinlock.h>
 
 /****************************************************************************
  * Pre-processor definitions
@@ -82,6 +83,7 @@ struct goldfish_fb_s
   struct fb_videoinfo_s videoinfo;
   FAR void *base;
   int irq;
+  spinlock_t lock;                  /* Lock for this framebuffer */
 };
 
 /****************************************************************************
@@ -166,7 +168,7 @@ static int goldfish_fb_interrupt(int irq, FAR void *dev_id, 
FAR void *arg)
   irqstate_t flags;
   uint32_t status;
 
-  flags = enter_critical_section();
+  flags = spin_lock_irqsave(&fb->lock);
   status = getreg32(fb->base + GOLDFISH_FB_INT_STATUS);
   if (status & GOLDFISH_FB_INT_VSYNC)
     {
@@ -178,7 +180,7 @@ static int goldfish_fb_interrupt(int irq, FAR void *dev_id, 
FAR void *arg)
       goldfish_fb_framedone_irq(fb);
     }
 
-  leave_critical_section(flags);
+  spin_unlock_irqrestore(&fb->lock, flags);
   return OK;
 }
 
diff --git a/drivers/video/vnc/vnc_server.h b/drivers/video/vnc/vnc_server.h
index c5d90205bce..ac4a5c4f025 100644
--- a/drivers/video/vnc/vnc_server.h
+++ b/drivers/video/vnc/vnc_server.h
@@ -41,6 +41,7 @@
 #include <nuttx/input/keyboard.h>
 #include <nuttx/net/net.h>
 #include <nuttx/semaphore.h>
+#include <nuttx/spinlock.h>
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -211,6 +212,8 @@ struct vnc_session_s
   volatile bool rre;           /* True: Remote supports RRE encoding */
   FAR uint8_t *fb;             /* Allocated local frame buffer */
 
+  spinlock_t lock;             /* Lock for vnc updating */
+
   /* VNC client input support */
 
   vnc_kbdout_t kbdout;         /* Callout when keyboard input is received */
diff --git a/drivers/video/vnc/vnc_updater.c b/drivers/video/vnc/vnc_updater.c
index 6caeba4828f..33e5f815687 100644
--- a/drivers/video/vnc/vnc_updater.c
+++ b/drivers/video/vnc/vnc_updater.c
@@ -192,15 +192,16 @@ vnc_alloc_update(FAR struct vnc_session_s *session)
    */
 
   vnc_sem_debug(session, "Before alloc", 0);
-  flags = enter_critical_section();
 
   nxsem_wait_uninterruptible(&session->freesem);
 
+  flags = spin_lock_irqsave(&session->lock);
+
   /* It is reserved.. go get it */
 
   update = (FAR struct vnc_fbupdate_s *)sq_remfirst(&session->updfree);
 
-  leave_critical_section(flags);
+  spin_unlock_irqrestore(&session->lock, flags);
   vnc_sem_debug(session, "After alloc", 1);
 
   DEBUGASSERT(update != NULL);
@@ -232,7 +233,7 @@ static void vnc_free_update(FAR struct vnc_session_s 
*session,
    */
 
   vnc_sem_debug(session, "Before free", 1);
-  flags = enter_critical_section();
+  flags = spin_lock_irqsave_nopreempt(&session->lock);
 
   /* Put the entry into the free list */
 
@@ -242,7 +243,7 @@ static void vnc_free_update(FAR struct vnc_session_s 
*session,
 
   nxsem_post(&session->freesem);
 
-  leave_critical_section(flags);
+  spin_unlock_irqrestore_nopreempt(&session->lock, flags);
   vnc_sem_debug(session, "After free", 0);
 
   DEBUGASSERT(nxsem_get_value(&session->freesem, &sval) == 0 &&
@@ -278,10 +279,11 @@ vnc_remove_queue(FAR struct vnc_session_s *session)
    */
 
   vnc_sem_debug(session, "Before remove", 0);
-  flags = enter_critical_section();
 
   nxsem_wait_uninterruptible(&session->queuesem);
 
+  flags = spin_lock_irqsave(&session->lock);
+
   /* It is reserved.. go get it */
 
   rect = (FAR struct vnc_fbupdate_s *)sq_remfirst(&session->updqueue);
@@ -302,7 +304,7 @@ vnc_remove_queue(FAR struct vnc_session_s *session)
     }
 
 errout:
-  leave_critical_section(flags);
+  spin_unlock_irqrestore(&session->lock, flags);
   return rect;
 }
 
@@ -332,7 +334,7 @@ static void vnc_add_queue(FAR struct vnc_session_s *session,
    */
 
   vnc_sem_debug(session, "Before add", 1);
-  flags = enter_critical_section();
+  flags = spin_lock_irqsave_nopreempt(&session->lock);
 
   /* Put the entry into the list of queued rectangles. */
 
@@ -344,7 +346,7 @@ static void vnc_add_queue(FAR struct vnc_session_s *session,
 
   nxsem_post(&session->queuesem);
 
-  leave_critical_section(flags);
+  spin_unlock_irqrestore_nopreempt(&session->lock, flags);
   vnc_sem_debug(session, "After add", 0);
 
   DEBUGASSERT(nxsem_get_value(&session->queuesem, &sval) == 0 &&
@@ -611,12 +613,10 @@ int vnc_update_rectangle(FAR struct vnc_session_s 
*session,
        * the framebuffer since the last whole screen update.
        */
 
-      flags = enter_critical_section();
       if (!change && !session->change)
         {
           /* No.. ignore the client update.  We have nothing new to report. */
 
-          leave_critical_section(flags);
           return OK;
         }
 
@@ -636,9 +636,10 @@ int vnc_update_rectangle(FAR struct vnc_session_s *session,
               FAR struct vnc_fbupdate_s *next;
 
               updinfo("New whole screen update...\n");
-
+              flags = spin_lock_irqsave(&session->lock);
               curr = (FAR struct vnc_fbupdate_s *)session->updqueue.head;
               sq_init(&session->updqueue);
+              spin_unlock_irqrestore(&session->lock, flags);
               nxsem_reset(&session->queuesem, 0);
 
               for (; curr != NULL; curr = next)
@@ -681,8 +682,6 @@ int vnc_update_rectangle(FAR struct vnc_session_s *session,
                   intersection.x, intersection.y,
                   intersection.w, intersection.h);
         }
-
-      leave_critical_section(flags);
     }
 
   /* Since we ignore bad rectangles and wait for update structures, there is

Reply via email to