mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
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 <jianglianfang@xiaomi.com>
This commit is contained in:
parent
c858f3cc44
commit
a8de4c998c
3 changed files with 19 additions and 15 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue