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 <tjwu1217@gmail.com>
This commit is contained in:
TaiJu Wu 2024-02-26 01:45:21 +00:00 committed by Xiang Xiao
parent a7389c0057
commit 23d65cb97f
2 changed files with 28 additions and 31 deletions

View File

@ -25,7 +25,8 @@
* Included Files * Included Files
****************************************************************************/ ****************************************************************************/
#include <nuttx/mutex.h> #include <nuttx/semaphore.h>
#include <nuttx/spinlock.h>
/**************************************************************************** /****************************************************************************
* Public Type Definitions * Public Type Definitions
@ -33,11 +34,11 @@
typedef struct typedef struct
{ {
mutex_t protected; /* Protecting Locks for Read/Write Locked Tables */ spinlock_t protected;
sem_t waiting; /* Reader/writer Waiting queue */ sem_t waiting;
int waiter; /* Waiter Count */ int waiter;
int writer; /* Writer Count */ int writer;
int reader; /* Reader Count */ int reader;
} rw_semaphore_t; } rw_semaphore_t;
/**************************************************************************** /****************************************************************************

View File

@ -23,6 +23,8 @@
****************************************************************************/ ****************************************************************************/
#include <nuttx/rwsem.h> #include <nuttx/rwsem.h>
#include <nuttx/irq.h>
#include <assert.h>
/**************************************************************************** /****************************************************************************
* Private Functions * 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) 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) if (rwsem->writer > 0)
{ {
nxmutex_unlock(&rwsem->protected); spin_unlock_irqrestore(&rwsem->protected, flags);
return 0; return 0;
} }
@ -75,7 +77,7 @@ int down_read_trylock(FAR rw_semaphore_t *rwsem)
rwsem->reader++; rwsem->reader++;
nxmutex_unlock(&rwsem->protected); spin_unlock_irqrestore(&rwsem->protected, flags);
return 1; return 1;
} }
@ -97,14 +99,14 @@ void down_read(FAR rw_semaphore_t *rwsem)
* block and wait for the write-lock to be unlocked. * 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) while (rwsem->writer > 0)
{ {
rwsem->waiter++; rwsem->waiter++;
nxmutex_unlock(&rwsem->protected); spin_unlock_irqrestore(&rwsem->protected, flags);
nxsem_wait(&rwsem->waiting); nxsem_wait(&rwsem->waiting);
nxmutex_lock(&rwsem->protected); flags = spin_lock_irqsave(&rwsem->protected);
rwsem->waiter--; rwsem->waiter--;
} }
@ -114,7 +116,7 @@ void down_read(FAR rw_semaphore_t *rwsem)
rwsem->reader++; 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) void up_read(FAR rw_semaphore_t *rwsem)
{ {
nxmutex_lock(&rwsem->protected); irqstate_t flags = spin_lock_irqsave(&rwsem->protected);
DEBUGASSERT(rwsem->reader > 0); DEBUGASSERT(rwsem->reader > 0);
@ -141,7 +143,7 @@ void up_read(FAR rw_semaphore_t *rwsem)
up_wait(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) 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) if (rwsem->writer > 0 || rwsem->reader > 0)
{ {
nxmutex_unlock(&rwsem->protected); spin_unlock_irqrestore(&rwsem->protected, flags);
return 0; return 0;
} }
@ -172,7 +174,7 @@ int down_write_trylock(FAR rw_semaphore_t *rwsem)
rwsem->writer++; rwsem->writer++;
nxmutex_unlock(&rwsem->protected); spin_unlock_irqrestore(&rwsem->protected, flags);
return 1; return 1;
} }
@ -190,14 +192,14 @@ int down_write_trylock(FAR rw_semaphore_t *rwsem)
void down_write(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) while (rwsem->reader > 0 || rwsem->writer > 0)
{ {
rwsem->waiter++; rwsem->waiter++;
nxmutex_unlock(&rwsem->protected); spin_unlock_irqrestore(&rwsem->protected, flags);
nxsem_wait(&rwsem->waiting); nxsem_wait(&rwsem->waiting);
nxmutex_lock(&rwsem->protected); flags = spin_lock_irqsave(&rwsem->protected);
rwsem->waiter--; rwsem->waiter--;
} }
@ -205,7 +207,7 @@ void down_write(FAR rw_semaphore_t *rwsem)
rwsem->writer++; 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) void up_write(FAR rw_semaphore_t *rwsem)
{ {
nxmutex_lock(&rwsem->protected); irqstate_t flags = spin_lock_irqsave(&rwsem->protected);
DEBUGASSERT(rwsem->writer > 0); DEBUGASSERT(rwsem->writer > 0);
@ -229,7 +231,7 @@ void up_write(FAR rw_semaphore_t *rwsem)
up_wait(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 */ /* Initialize structure information */
ret = nxmutex_init(&rwsem->protected); spin_lock_init(&rwsem->protected);
if (ret < 0)
{
return ret;
}
ret = nxsem_init(&rwsem->waiting, 0, 0); ret = nxsem_init(&rwsem->waiting, 0, 0);
if (ret < 0) if (ret < 0)
{ {
nxmutex_destroy(&rwsem->protected);
return ret; return ret;
} }
@ -292,6 +289,5 @@ void destroy_rwsem(FAR rw_semaphore_t *rwsem)
DEBUGASSERT(rwsem->waiter == 0 && rwsem->reader == 0 && DEBUGASSERT(rwsem->waiter == 0 && rwsem->reader == 0 &&
rwsem->writer == 0); rwsem->writer == 0);
nxmutex_destroy(&rwsem->protected);
nxsem_destroy(&rwsem->waiting); nxsem_destroy(&rwsem->waiting);
} }