1
0
Fork 0
forked from nuttx/nuttx-update

sched/semaphore: support recursive write for same process in sem_rw lock

Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu1 2024-05-17 17:52:58 +08:00 committed by Xiang Xiao
parent 0de9d4ba6a
commit a367657d2d
2 changed files with 32 additions and 10 deletions

View file

@ -28,17 +28,29 @@
#include <nuttx/semaphore.h>
#include <nuttx/spinlock.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define RWSEM_NO_HOLDER ((pid_t)-1)
#define RWSEM_INITIALIZER {SEM_INITIALIZER(0), \
RWSEM_NO_HOLDER, 0, 0, 0}
/****************************************************************************
* Public Type Definitions
****************************************************************************/
typedef struct
{
spinlock_t protected;
sem_t waiting;
int waiter;
int writer;
int reader;
sem_t waiting; /* Reader/writer Waiting queue */
pid_t holder; /* The write lock holder, this lock still can be
* locked when the holder is same as the current
* task/thread.
*/
int waiter; /* Waiter Count */
int writer; /* Writer Count */
int reader; /* Reader Count */
spinlock_t protected; /* Protecting Locks for Read/Write Locked Tables */
} rw_semaphore_t;
/****************************************************************************

View file

@ -24,8 +24,9 @@
* Included Files
****************************************************************************/
#include <nuttx/rwsem.h>
#include <nuttx/irq.h>
#include <nuttx/rwsem.h>
#include <nuttx/sched.h>
#include <assert.h>
/****************************************************************************
@ -165,8 +166,9 @@ void up_read(FAR rw_semaphore_t *rwsem)
int down_write_trylock(FAR rw_semaphore_t *rwsem)
{
irqstate_t flags = spin_lock_irqsave(&rwsem->protected);
pid_t tid = _SCHED_GETTID();
if (rwsem->writer > 0 || rwsem->reader > 0)
if (rwsem->reader > 0 || (rwsem->writer > 0 && tid != rwsem->holder))
{
spin_unlock_irqrestore(&rwsem->protected, flags);
return 0;
@ -175,6 +177,7 @@ int down_write_trylock(FAR rw_semaphore_t *rwsem)
/* The check passes, then we just need the writer reference + 1 */
rwsem->writer++;
rwsem->holder = tid;
spin_unlock_irqrestore(&rwsem->protected, flags);
@ -195,8 +198,9 @@ int down_write_trylock(FAR rw_semaphore_t *rwsem)
void down_write(FAR rw_semaphore_t *rwsem)
{
irqstate_t flags = spin_lock_irqsave(&rwsem->protected);
pid_t tid = _SCHED_GETTID();
while (rwsem->reader > 0 || rwsem->writer > 0)
while (rwsem->reader > 0 || (rwsem->writer > 0 && rwsem->holder != tid))
{
rwsem->waiter++;
spin_unlock_irqrestore(&rwsem->protected, flags);
@ -208,6 +212,7 @@ void down_write(FAR rw_semaphore_t *rwsem)
/* The check passes, then we just need the writer reference + 1 */
rwsem->writer++;
rwsem->holder = tid;
spin_unlock_irqrestore(&rwsem->protected, flags);
}
@ -228,8 +233,12 @@ void up_write(FAR rw_semaphore_t *rwsem)
irqstate_t flags = spin_lock_irqsave(&rwsem->protected);
DEBUGASSERT(rwsem->writer > 0);
DEBUGASSERT(rwsem->holder == _SCHED_GETTID());
rwsem->writer--;
if (--rwsem->writer <= 0)
{
rwsem->holder = RWSEM_NO_HOLDER;
}
up_wait(rwsem);
@ -268,6 +277,7 @@ int init_rwsem(FAR rw_semaphore_t *rwsem)
rwsem->reader = 0;
rwsem->writer = 0;
rwsem->waiter = 0;
rwsem->holder = RWSEM_NO_HOLDER;
return OK;
}
@ -289,7 +299,7 @@ void destroy_rwsem(FAR rw_semaphore_t *rwsem)
/* Need to check if there is still an unlocked or waiting state */
DEBUGASSERT(rwsem->waiter == 0 && rwsem->reader == 0 &&
rwsem->writer == 0);
rwsem->writer == 0 && rwsem->holder == RWSEM_NO_HOLDER);
nxsem_destroy(&rwsem->waiting);
}