diff --git a/include/nuttx/modem/alt1250.h b/include/nuttx/modem/alt1250.h index 54377fdd6d191..99727460bd718 100644 --- a/include/nuttx/modem/alt1250.h +++ b/include/nuttx/modem/alt1250.h @@ -323,7 +323,7 @@ typedef struct altcom_fd_set_s altcom_fd_set; struct alt_queue_s { sq_queue_t queue; - sem_t lock; + mutex_t lock; }; struct alt1250_dev_s diff --git a/include/nuttx/mutex.h b/include/nuttx/mutex.h index 814da6adcd92a..70a013ea8c20a 100644 --- a/include/nuttx/mutex.h +++ b/include/nuttx/mutex.h @@ -36,21 +36,31 @@ * Pre-processor Definitions ****************************************************************************/ +#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) +# define _MUTEX_WAIT(s) _nxsem_wait(s, true) +#else +# define _MUTEX_WAIT(s) _sem_wait(s, true) +#endif + #define NXRMUTEX_NO_HOLDER (pid_t)-1 -#define NXMUTEX_INITIALIZER NXSEM_INITIALIZER(1, 0) -#define NXRMUTEX_INITIALIZER {NXSEM_INITIALIZER(1, 0), \ - NXRMUTEX_NO_HOLDER, 0} +#define NXMUTEX_INITIALIZER {NXSEM_INITIALIZER(1, 0), NXRMUTEX_NO_HOLDER} +#define NXRMUTEX_INITIALIZER {NXSEM_INITIALIZER(1, 0), 0} /**************************************************************************** * Public Type Definitions ****************************************************************************/ -typedef sem_t mutex_t; +struct mutex_s +{ + sem_t mutex; + pid_t holder; +}; + +typedef struct mutex_s mutex_t; struct rmutex_s { mutex_t mutex; - pid_t holder; unsigned int count; }; @@ -91,14 +101,15 @@ extern "C" static inline int nxmutex_init(FAR mutex_t *mutex) { - int ret = _SEM_INIT(mutex, 0, 1); + int ret = _SEM_INIT(&mutex->mutex, 0, 1); if (ret < 0) { return _SEM_ERRVAL(ret); } - _SEM_SETPROTOCOL(mutex, SEM_PRIO_INHERIT); + mutex->holder = NXRMUTEX_NO_HOLDER; + _SEM_SETPROTOCOL(&mutex->mutex, SEM_PRIO_INHERIT); return ret; } @@ -123,7 +134,7 @@ static inline int nxmutex_init(FAR mutex_t *mutex) static inline int nxmutex_destroy(FAR mutex_t *mutex) { - int ret = _SEM_DESTROY(mutex); + int ret = _SEM_DESTROY(&mutex->mutex); if (ret < 0) { @@ -161,9 +172,10 @@ static inline int nxmutex_lock(FAR mutex_t *mutex) { /* Take the semaphore (perhaps waiting) */ - ret = _SEM_WAIT(mutex); + ret = _MUTEX_WAIT(&mutex->mutex); if (ret >= 0) { + mutex->holder = gettid(); break; } @@ -200,13 +212,14 @@ static inline int nxmutex_lock(FAR mutex_t *mutex) static inline int nxmutex_trylock(FAR mutex_t *mutex) { - int ret = _SEM_TRYWAIT(mutex); + int ret = _SEM_TRYWAIT(&mutex->mutex); if (ret < 0) { return _SEM_ERRVAL(ret); } + mutex->holder = gettid(); return ret; } @@ -228,12 +241,31 @@ static inline bool nxmutex_is_locked(FAR mutex_t *mutex) int cnt; int ret; - ret = _SEM_GETVALUE(mutex, &cnt); + ret = _SEM_GETVALUE(&mutex->mutex, &cnt); DEBUGASSERT(ret == OK); return cnt < 1; } +/**************************************************************************** + * Name: nxmutex_is_hold + * + * Description: + * This function check whether the caller hold the mutex + * referenced by 'mutex'. + * + * Parameters: + * mutex - mutex descriptor. + * + * Return Value: + * + ****************************************************************************/ + +static inline bool nxmutex_is_hold(FAR mutex_t *mutex) +{ + return mutex->holder == gettid(); +} + /**************************************************************************** * Name: nxmutex_unlock * @@ -258,15 +290,70 @@ static inline int nxmutex_unlock(FAR mutex_t *mutex) { int ret; - ret = _SEM_POST(mutex); + DEBUGASSERT(mutex->holder == gettid()); + + ret = _SEM_POST(&mutex->mutex); if (ret < 0) { return _SEM_ERRVAL(ret); } + mutex->holder = NXRMUTEX_NO_HOLDER; return ret; } +/**************************************************************************** + * Name: nxmutex_breaklock + * + * Description: + * This function attempts to break the mutex + * + * Parameters: + * mutex - mutex descriptor. + * + * Return Value: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * Possible returned errors: + * + ****************************************************************************/ + +static inline int nxmutex_breaklock(FAR mutex_t *mutex) +{ + if (mutex->holder == gettid()) + { + return nxmutex_unlock(mutex); + } + else + { + return -EPERM; + } +} + +/**************************************************************************** + * Name: nxmutex_restorelock + * + * Description: + * This function attempts to restore the mutex. + * + * Parameters: + * mutex - mutex descriptor. + * + * Return Value: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * Possible returned errors: + * + ****************************************************************************/ + +static inline int nxmutex_restorelock(FAR mutex_t *mutex) +{ + DEBUGASSERT(mutex->holder != gettid()); + return nxmutex_lock(mutex); +} + /**************************************************************************** * Name: nxmutex_reset * @@ -282,7 +369,7 @@ static inline int nxmutex_unlock(FAR mutex_t *mutex) static inline int nxmutex_reset(FAR mutex_t *mutex) { - return nxsem_reset(mutex, 1); + return nxsem_reset(&mutex->mutex, 1); } /**************************************************************************** @@ -308,7 +395,6 @@ static inline int nxmutex_reset(FAR mutex_t *mutex) static inline int nxrmutex_init(FAR rmutex_t *rmutex) { rmutex->count = 0; - rmutex->holder = NXRMUTEX_NO_HOLDER; return nxmutex_init(&rmutex->mutex); } @@ -354,10 +440,9 @@ static inline int nxrmutex_destroy(FAR rmutex_t *rmutex) static inline int nxrmutex_lock(FAR rmutex_t *rmutex) { - pid_t tid = gettid(); int ret; - if (rmutex->holder == tid) + if (rmutex->mutex.holder == gettid()) { DEBUGASSERT(rmutex->count < UINT_MAX); rmutex->count++; @@ -368,7 +453,6 @@ static inline int nxrmutex_lock(FAR rmutex_t *rmutex) ret = nxmutex_lock(&rmutex->mutex); if (ret == OK) { - rmutex->holder = tid; rmutex->count = 1; } } @@ -401,10 +485,9 @@ static inline int nxrmutex_lock(FAR rmutex_t *rmutex) static inline int nxrmutex_trylock(FAR rmutex_t *rmutex) { - pid_t tid = gettid(); int ret; - if (rmutex->holder == tid) + if (rmutex->mutex.holder == gettid()) { DEBUGASSERT(rmutex->count < UINT_MAX); rmutex->count++; @@ -415,7 +498,6 @@ static inline int nxrmutex_trylock(FAR rmutex_t *rmutex) ret = nxmutex_trylock(&rmutex->mutex); if (ret == OK) { - rmutex->holder = tid; rmutex->count = 1; } } @@ -458,7 +540,7 @@ static inline bool nxrmutex_is_locked(FAR rmutex_t *rmutex) static inline bool nxrmutex_is_hold(FAR rmutex_t *rmutex) { - return rmutex->holder == gettid(); + return rmutex->mutex.holder == gettid(); } /**************************************************************************** @@ -484,15 +566,13 @@ static inline bool nxrmutex_is_hold(FAR rmutex_t *rmutex) static inline int nxrmutex_unlock(FAR rmutex_t *rmutex) { - pid_t tid = gettid(); int ret = OK; - DEBUGASSERT(rmutex->holder == tid); + DEBUGASSERT(rmutex->mutex.holder == gettid()); DEBUGASSERT(rmutex->count > 0); if (rmutex->count-- == 1) { - rmutex->holder = NXRMUTEX_NO_HOLDER; ret = nxmutex_unlock(&rmutex->mutex); } @@ -522,11 +602,10 @@ static inline int nxrmutex_breaklock(FAR rmutex_t *rmutex, pid_t tid = gettid(); int ret = -EPERM; - if (rmutex->holder == tid) + if (rmutex->mutex.holder == tid) { *count = rmutex->count; rmutex->count = 0; - rmutex->holder = NXRMUTEX_NO_HOLDER; nxmutex_unlock(&rmutex->mutex); ret = 0; } @@ -557,11 +636,10 @@ static inline int nxrmutex_restorelock(FAR rmutex_t *rmutex, pid_t tid = gettid(); int ret; - DEBUGASSERT(rmutex->holder != tid); + DEBUGASSERT(rmutex->mutex.holder != tid); ret = nxmutex_lock(&rmutex->mutex); if (ret == OK) { - rmutex->holder = tid; rmutex->count = count; } diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index f1bacbf7f9feb..d2aee100fc800 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -204,6 +204,7 @@ enum tstate_e TSTATE_TASK_INACTIVE, /* BLOCKED - Initialized but not yet activated */ TSTATE_WAIT_SEM, /* BLOCKED - Waiting for a semaphore */ + TSTATE_WAIT_MUTEX, /* BLOCKED - Waiting for a mutex */ TSTATE_WAIT_SIG, /* BLOCKED - Waiting for a signal */ #if !defined(CONFIG_DISABLE_MQUEUE) && !defined(CONFIG_DISABLE_MQUEUE_SYSV) TSTATE_WAIT_MQNOTEMPTY, /* BLOCKED - Waiting for a MQ to become not empty. */ @@ -453,7 +454,7 @@ struct task_group_s /* Pthread join Info: */ - sem_t tg_joinlock; /* Mutually exclusive access to join data */ + mutex_t tg_joinlock; /* Mutually exclusive access to join data */ FAR struct join_s *tg_joinhead; /* Head of a list of join data */ FAR struct join_s *tg_jointail; /* Tail of a list of join data */ #endif diff --git a/include/nuttx/semaphore.h b/include/nuttx/semaphore.h index 3ad14d514e7fe..29771d4330baf 100644 --- a/include/nuttx/semaphore.h +++ b/include/nuttx/semaphore.h @@ -29,6 +29,7 @@ #include #include +#include #include @@ -142,6 +143,63 @@ extern "C" * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: _nxsem_wait + * + * Description: + * This function attempts to lock the semaphore referenced by 'sem'. If + * the semaphore value is (<=) zero, then the calling task will not return + * until it successfully acquires the lock. + * + * This is an internal OS interface. It is functionally equivalent to + * sem_wait except that: + * + * - It is not a cancellation point, and + * - It does not modify the errno value. + * + * Input Parameters: + * sem - Semaphore descriptor. + * is_mutex - true if mutex. + * + * Returned Value: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * Possible returned errors: + * + * - EINVAL: Invalid attempt to get the semaphore + * - EINTR: The wait was interrupted by the receipt of a signal. + * + ****************************************************************************/ + +int _nxsem_wait(FAR sem_t *sem, bool is_mutex); + +/**************************************************************************** + * Name: _sem_wait + * + * Description: + * This function attempts to lock the semaphore referenced by 'sem'. If + * the semaphore value is (<=) zero, then the calling task will not return + * until it successfully acquires the lock. + * + * This is an internal OS interface. + * + * Input Parameters: + * sem - Semaphore descriptor. + * is_mutex - true if mutex. + * + * Returned Value: + * This function is a standard, POSIX application interface. It returns + * zero (OK) if successful. Otherwise, -1 (ERROR) is returned and + * the errno value is set appropriately. Possible errno values include: + * + * - EINVAL: Invalid attempt to get the semaphore + * - EINTR: The wait was interrupted by the receipt of a signal. + * + ****************************************************************************/ + +int _sem_wait(FAR sem_t *sem, bool is_mutex); + /**************************************************************************** * Name: nxsem_init * diff --git a/mm/mm_heap/mm.h b/mm/mm_heap/mm.h index a53b63aa60ebc..615ebae7b2f3f 100644 --- a/mm/mm_heap/mm.h +++ b/mm/mm_heap/mm.h @@ -220,7 +220,7 @@ struct mm_heap_s * the following un-named mutex. */ - sem_t mm_lock; + mutex_t mm_lock; /* This is the size of the heap provided to mm */ diff --git a/net/usrsock/usrsock_devif.c b/net/usrsock/usrsock_devif.c index 7f40a29f83f60..6c849b011d298 100644 --- a/net/usrsock/usrsock_devif.c +++ b/net/usrsock/usrsock_devif.c @@ -36,7 +36,6 @@ #include #include -#include #include #include #include @@ -49,7 +48,7 @@ struct usrsock_req_s { - mutex_t lock; /* Request mutex (only one outstanding + sem_t sem; /* Request semaphore (only one outstanding * request) */ sem_t acksem; /* Request acknowledgment notification */ uint32_t newxid; /* New transcation Id */ @@ -73,7 +72,7 @@ struct usrsock_req_s static struct usrsock_req_s g_usrsock_req = { - NXMUTEX_INITIALIZER, + NXSEM_INITIALIZER(1, PRIOINHERIT_FLAGS_DISABLE), SEM_INITIALIZER(0), 0, 0, @@ -641,7 +640,7 @@ int usrsock_do_request(FAR struct usrsock_conn_s *conn, /* Set outstanding request for daemon to handle. */ - net_lockedwait_uninterruptible(&req->lock); + net_lockedwait_uninterruptible(&req->sem); if (++req->newxid == 0) { ++req->newxid; @@ -668,7 +667,7 @@ int usrsock_do_request(FAR struct usrsock_conn_s *conn, /* Free request line for next command. */ - nxmutex_unlock(&req->lock); + nxsem_post(&req->sem); return ret; } @@ -700,7 +699,7 @@ void usrsock_abort(void) * requests. */ - ret = net_timedwait(&req->lock, 10); + ret = net_timedwait(&req->sem, 10); if (ret < 0) { if (ret != -ETIMEDOUT && ret != -EINTR) @@ -711,7 +710,7 @@ void usrsock_abort(void) } else { - nxmutex_unlock(&req->lock); + nxsem_post(&req->sem); } /* Wake-up pending requests. */ diff --git a/sched/semaphore/sem_recover.c b/sched/semaphore/sem_recover.c index 5293ab0c2b276..05958fe97ac2c 100644 --- a/sched/semaphore/sem_recover.c +++ b/sched/semaphore/sem_recover.c @@ -80,7 +80,8 @@ void nxsem_recover(FAR struct tcb_s *tcb) */ flags = enter_critical_section(); - if (tcb->task_state == TSTATE_WAIT_SEM) + if (tcb->task_state == TSTATE_WAIT_SEM || + tcb->task_state == TSTATE_WAIT_MUTEX) { FAR sem_t *sem = tcb->waitobj; DEBUGASSERT(sem != NULL && sem->semcount < 0); diff --git a/sched/semaphore/sem_wait.c b/sched/semaphore/sem_wait.c index 67d6af70f4cec..d6b4c5ac800bc 100644 --- a/sched/semaphore/sem_wait.c +++ b/sched/semaphore/sem_wait.c @@ -41,7 +41,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: nxsem_wait + * Name: _nxsem_wait * * Description: * This function attempts to lock the semaphore referenced by 'sem'. If @@ -55,7 +55,8 @@ * - It does not modify the errno value. * * Input Parameters: - * sem - Semaphore descriptor. + * sem - Semaphore descriptor. + * is_mutex - true if mutex. * * Returned Value: * This is an internal OS interface and should not be used by applications. @@ -68,7 +69,7 @@ * ****************************************************************************/ -int nxsem_wait(FAR sem_t *sem) +int _nxsem_wait(FAR sem_t *sem, bool is_mutex) { FAR struct tcb_s *rtcb = this_task(); irqstate_t flags; @@ -152,7 +153,8 @@ int nxsem_wait(FAR sem_t *sem) */ DEBUGASSERT(NULL != rtcb->flink); - up_block_task(rtcb, TSTATE_WAIT_SEM); + up_block_task(rtcb, + is_mutex ? TSTATE_WAIT_MUTEX : TSTATE_WAIT_SEM); /* When we resume at this point, either (1) the semaphore has been * assigned to this thread of execution, or (2) the semaphore wait @@ -196,6 +198,39 @@ int nxsem_wait(FAR sem_t *sem) return ret; } +/**************************************************************************** + * Name: nxsem_wait + * + * Description: + * This function attempts to lock the semaphore referenced by 'sem'. If + * the semaphore value is (<=) zero, then the calling task will not return + * until it successfully acquires the lock. + * + * This is an internal OS interface. It is functionally equivalent to + * sem_wait except that: + * + * - It is not a cancellation point, and + * - It does not modify the errno value. + * + * Input Parameters: + * sem - Semaphore descriptor. + * + * Returned Value: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * Possible returned errors: + * + * - EINVAL: Invalid attempt to get the semaphore + * - EINTR: The wait was interrupted by the receipt of a signal. + * + ****************************************************************************/ + +int nxsem_wait(FAR sem_t *sem) +{ + return _nxsem_wait(sem, false); +} + /**************************************************************************** * Name: nxsem_wait_uninterruptible * @@ -229,15 +264,18 @@ int nxsem_wait_uninterruptible(FAR sem_t *sem) } /**************************************************************************** - * Name: sem_wait + * Name: _sem_wait * * Description: * This function attempts to lock the semaphore referenced by 'sem'. If * the semaphore value is (<=) zero, then the calling task will not return * until it successfully acquires the lock. * + * This is an internal OS interface. + * * Input Parameters: * sem - Semaphore descriptor. + * is_mutex - true if mutex. * * Returned Value: * This function is a standard, POSIX application interface. It returns @@ -249,7 +287,7 @@ int nxsem_wait_uninterruptible(FAR sem_t *sem) * ****************************************************************************/ -int sem_wait(FAR sem_t *sem) +int _sem_wait(FAR sem_t *sem, bool is_mutex) { int errcode; int ret; @@ -270,7 +308,7 @@ int sem_wait(FAR sem_t *sem) /* Let nxsem_wait() do the real work */ - ret = nxsem_wait(sem); + ret = _nxsem_wait(sem, is_mutex); if (ret < 0) { errcode = -ret; @@ -285,3 +323,29 @@ int sem_wait(FAR sem_t *sem) leave_cancellation_point(); return ERROR; } + +/**************************************************************************** + * Name: sem_wait + * + * Description: + * This function attempts to lock the semaphore referenced by 'sem'. If + * the semaphore value is (<=) zero, then the calling task will not return + * until it successfully acquires the lock. + * + * Input Parameters: + * sem - Semaphore descriptor. + * + * Returned Value: + * This function is a standard, POSIX application interface. It returns + * zero (OK) if successful. Otherwise, -1 (ERROR) is returned and + * the errno value is set appropriately. Possible errno values include: + * + * - EINVAL: Invalid attempt to get the semaphore + * - EINTR: The wait was interrupted by the receipt of a signal. + * + ****************************************************************************/ + +int sem_wait(FAR sem_t *sem) +{ + return _sem_wait(sem, false); +} diff --git a/sched/semaphore/sem_waitirq.c b/sched/semaphore/sem_waitirq.c index 2a296ca16670e..39c673712c267 100644 --- a/sched/semaphore/sem_waitirq.c +++ b/sched/semaphore/sem_waitirq.c @@ -78,7 +78,8 @@ void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode) * and already changed the task's state. */ - if (wtcb->task_state == TSTATE_WAIT_SEM) + if (wtcb->task_state == TSTATE_WAIT_SEM || + wtcb->task_state == TSTATE_WAIT_MUTEX) { FAR sem_t *sem = wtcb->waitobj; DEBUGASSERT(sem != NULL && sem->semcount < 0); diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c index b54e5960a074e..03b759b9dcae9 100644 --- a/sched/signal/sig_dispatch.c +++ b/sched/signal/sig_dispatch.c @@ -434,7 +434,8 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info) * be unblocked when a signal is received. */ - if (stcb->task_state == TSTATE_WAIT_SEM) + if (stcb->task_state == TSTATE_WAIT_SEM || + stcb->task_state == TSTATE_WAIT_MUTEX) { nxsem_wait_irq(stcb, EINTR); } diff --git a/sched/task/task_cancelpt.c b/sched/task/task_cancelpt.c index 2335235d2b203..2f521a1301009 100644 --- a/sched/task/task_cancelpt.c +++ b/sched/task/task_cancelpt.c @@ -378,7 +378,8 @@ bool nxnotify_cancellation(FAR struct tcb_s *tcb) * thread must be unblocked to handle the cancellation. */ - if (tcb->task_state == TSTATE_WAIT_SEM) + if (tcb->task_state == TSTATE_WAIT_SEM || + tcb->task_state == TSTATE_WAIT_MUTEX) { nxsem_wait_irq(tcb, ECANCELED); }