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