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:
parent
0de9d4ba6a
commit
a367657d2d
2 changed files with 32 additions and 10 deletions
|
@ -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;
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue