From 23d65cb97f1019c98707c5536fe790398a0c164a Mon Sep 17 00:00:00 2001 From: TaiJu Wu Date: Mon, 26 Feb 2024 01:45:21 +0000 Subject: [PATCH] shced:sem: replace mutex with spinlock The overhead of spinlok is less than mutext (mutex need to call enter_critical section.) After this patch, `down_write_trylock` and `down_read_trylock` can be use in interrupt context. The instruction is protected with mutex only one instruction so using spinlock is better. Signed-off-by: TaiJu Wu --- include/nuttx/rwsem.h | 13 ++++++------ sched/semaphore/sem_rw.c | 46 ++++++++++++++++++---------------------- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/include/nuttx/rwsem.h b/include/nuttx/rwsem.h index 69a89beb00..2999bfcd52 100644 --- a/include/nuttx/rwsem.h +++ b/include/nuttx/rwsem.h @@ -25,7 +25,8 @@ * Included Files ****************************************************************************/ -#include +#include +#include /**************************************************************************** * Public Type Definitions @@ -33,11 +34,11 @@ typedef struct { - mutex_t protected; /* Protecting Locks for Read/Write Locked Tables */ - sem_t waiting; /* Reader/writer Waiting queue */ - int waiter; /* Waiter Count */ - int writer; /* Writer Count */ - int reader; /* Reader Count */ + spinlock_t protected; + sem_t waiting; + int waiter; + int writer; + int reader; } rw_semaphore_t; /**************************************************************************** diff --git a/sched/semaphore/sem_rw.c b/sched/semaphore/sem_rw.c index 2a6f566dd1..238c071a48 100644 --- a/sched/semaphore/sem_rw.c +++ b/sched/semaphore/sem_rw.c @@ -23,6 +23,8 @@ ****************************************************************************/ #include +#include +#include /**************************************************************************** * Private Functions @@ -61,11 +63,11 @@ static inline void up_wait(FAR rw_semaphore_t *rwsem) int down_read_trylock(FAR rw_semaphore_t *rwsem) { - nxmutex_lock(&rwsem->protected); + irqstate_t flags = spin_lock_irqsave(&rwsem->protected); if (rwsem->writer > 0) { - nxmutex_unlock(&rwsem->protected); + spin_unlock_irqrestore(&rwsem->protected, flags); return 0; } @@ -75,7 +77,7 @@ int down_read_trylock(FAR rw_semaphore_t *rwsem) rwsem->reader++; - nxmutex_unlock(&rwsem->protected); + spin_unlock_irqrestore(&rwsem->protected, flags); return 1; } @@ -97,14 +99,14 @@ void down_read(FAR rw_semaphore_t *rwsem) * block and wait for the write-lock to be unlocked. */ - nxmutex_lock(&rwsem->protected); + irqstate_t flags = spin_lock_irqsave(&rwsem->protected); while (rwsem->writer > 0) { rwsem->waiter++; - nxmutex_unlock(&rwsem->protected); + spin_unlock_irqrestore(&rwsem->protected, flags); nxsem_wait(&rwsem->waiting); - nxmutex_lock(&rwsem->protected); + flags = spin_lock_irqsave(&rwsem->protected); rwsem->waiter--; } @@ -114,7 +116,7 @@ void down_read(FAR rw_semaphore_t *rwsem) rwsem->reader++; - nxmutex_unlock(&rwsem->protected); + spin_unlock_irqrestore(&rwsem->protected, flags); } /**************************************************************************** @@ -130,7 +132,7 @@ void down_read(FAR rw_semaphore_t *rwsem) void up_read(FAR rw_semaphore_t *rwsem) { - nxmutex_lock(&rwsem->protected); + irqstate_t flags = spin_lock_irqsave(&rwsem->protected); DEBUGASSERT(rwsem->reader > 0); @@ -141,7 +143,7 @@ void up_read(FAR rw_semaphore_t *rwsem) up_wait(rwsem); } - nxmutex_unlock(&rwsem->protected); + spin_unlock_irqrestore(&rwsem->protected, flags); } /**************************************************************************** @@ -160,11 +162,11 @@ void up_read(FAR rw_semaphore_t *rwsem) int down_write_trylock(FAR rw_semaphore_t *rwsem) { - nxmutex_lock(&rwsem->protected); + irqstate_t flags = spin_lock_irqsave(&rwsem->protected); if (rwsem->writer > 0 || rwsem->reader > 0) { - nxmutex_unlock(&rwsem->protected); + spin_unlock_irqrestore(&rwsem->protected, flags); return 0; } @@ -172,7 +174,7 @@ int down_write_trylock(FAR rw_semaphore_t *rwsem) rwsem->writer++; - nxmutex_unlock(&rwsem->protected); + spin_unlock_irqrestore(&rwsem->protected, flags); return 1; } @@ -190,14 +192,14 @@ int down_write_trylock(FAR rw_semaphore_t *rwsem) void down_write(FAR rw_semaphore_t *rwsem) { - nxmutex_lock(&rwsem->protected); + irqstate_t flags = spin_lock_irqsave(&rwsem->protected); while (rwsem->reader > 0 || rwsem->writer > 0) { rwsem->waiter++; - nxmutex_unlock(&rwsem->protected); + spin_unlock_irqrestore(&rwsem->protected, flags); nxsem_wait(&rwsem->waiting); - nxmutex_lock(&rwsem->protected); + flags = spin_lock_irqsave(&rwsem->protected); rwsem->waiter--; } @@ -205,7 +207,7 @@ void down_write(FAR rw_semaphore_t *rwsem) rwsem->writer++; - nxmutex_unlock(&rwsem->protected); + spin_unlock_irqrestore(&rwsem->protected, flags); } /**************************************************************************** @@ -221,7 +223,7 @@ void down_write(FAR rw_semaphore_t *rwsem) void up_write(FAR rw_semaphore_t *rwsem) { - nxmutex_lock(&rwsem->protected); + irqstate_t flags = spin_lock_irqsave(&rwsem->protected); DEBUGASSERT(rwsem->writer > 0); @@ -229,7 +231,7 @@ void up_write(FAR rw_semaphore_t *rwsem) up_wait(rwsem); - nxmutex_unlock(&rwsem->protected); + spin_unlock_irqrestore(&rwsem->protected, flags); } /**************************************************************************** @@ -253,16 +255,11 @@ int init_rwsem(FAR rw_semaphore_t *rwsem) /* Initialize structure information */ - ret = nxmutex_init(&rwsem->protected); - if (ret < 0) - { - return ret; - } + spin_lock_init(&rwsem->protected); ret = nxsem_init(&rwsem->waiting, 0, 0); if (ret < 0) { - nxmutex_destroy(&rwsem->protected); return ret; } @@ -292,6 +289,5 @@ void destroy_rwsem(FAR rw_semaphore_t *rwsem) DEBUGASSERT(rwsem->waiter == 0 && rwsem->reader == 0 && rwsem->writer == 0); - nxmutex_destroy(&rwsem->protected); nxsem_destroy(&rwsem->waiting); }