You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/01/18 09:41:05 UTC
[nuttx] branch master updated: add holder for mutex
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new fc176addeb add holder for mutex
fc176addeb is described below
commit fc176addeb69bfdc1f91646cadb06dc0d9e0db39
Author: lilei19 <li...@xiaomi.com>
AuthorDate: Tue Jan 17 19:15:34 2023 +0800
add holder for mutex
Signed-off-by: lilei19 <li...@xiaomi.com>
---
arch/risc-v/src/esp32c3/esp32c3_libc_stubs.c | 16 +-
drivers/modem/alt1250/alt1250.c | 38 +--
drivers/usrsock/usrsock_dev.c | 2 +-
include/nuttx/modem/alt1250.h | 13 +-
include/nuttx/mutex.h | 411 ++++++++++++++++++++-------
include/nuttx/net/net.h | 47 +++
include/nuttx/semaphore.h | 12 +-
include/semaphore.h | 20 +-
libs/libc/semaphore/sem_getprotocol.c | 5 -
libs/libc/semaphore/sem_init.c | 3 +-
libs/libc/wqueue/work_usrthread.c | 2 +-
net/usrsock/usrsock_devif.c | 4 +-
net/utils/net_lock.c | 88 ++++++
13 files changed, 506 insertions(+), 155 deletions(-)
diff --git a/arch/risc-v/src/esp32c3/esp32c3_libc_stubs.c b/arch/risc-v/src/esp32c3/esp32c3_libc_stubs.c
index 4c6a1e290e..3e03f4145f 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_libc_stubs.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_libc_stubs.c
@@ -174,13 +174,13 @@ void _raise_r(struct _reent *r)
void _lock_init(_lock_t *lock)
{
nxmutex_init(&g_nxlock_common);
- nxsem_get_value(&g_nxlock_common, lock);
+ nxsem_get_value(&g_nxlock_common.sem, lock);
}
void _lock_init_recursive(_lock_t *lock)
{
nxmutex_init(&g_nxlock_recursive);
- nxsem_get_value(&g_nxlock_recursive, lock);
+ nxsem_get_value(&g_nxlock_recursive.sem, lock);
}
void _lock_close(_lock_t *lock)
@@ -198,39 +198,39 @@ void _lock_close_recursive(_lock_t *lock)
void _lock_acquire(_lock_t *lock)
{
nxmutex_lock(&g_nxlock_common);
- nxsem_get_value(&g_nxlock_common, lock);
+ nxsem_get_value(&g_nxlock_common.sem, lock);
}
void _lock_acquire_recursive(_lock_t *lock)
{
nxmutex_lock(&g_nxlock_recursive);
- nxsem_get_value(&g_nxlock_recursive, lock);
+ nxsem_get_value(&g_nxlock_recursive.sem, lock);
}
int _lock_try_acquire(_lock_t *lock)
{
nxmutex_trylock(&g_nxlock_common);
- nxsem_get_value(&g_nxlock_common, lock);
+ nxsem_get_value(&g_nxlock_common.sem, lock);
return 0;
}
int _lock_try_acquire_recursive(_lock_t *lock)
{
nxmutex_trylock(&g_nxlock_recursive);
- nxsem_get_value(&g_nxlock_recursive, lock);
+ nxsem_get_value(&g_nxlock_recursive.sem, lock);
return 0;
}
void _lock_release(_lock_t *lock)
{
nxmutex_unlock(&g_nxlock_common);
- nxsem_get_value(&g_nxlock_common, lock);
+ nxsem_get_value(&g_nxlock_common.sem, lock);
}
void _lock_release_recursive(_lock_t *lock)
{
nxmutex_unlock(&g_nxlock_recursive);
- nxsem_get_value(&g_nxlock_recursive, lock);
+ nxsem_get_value(&g_nxlock_recursive.sem, lock);
}
struct _reent *__getreent(void)
diff --git a/drivers/modem/alt1250/alt1250.c b/drivers/modem/alt1250/alt1250.c
index b8481cdb08..73ed186539 100644
--- a/drivers/modem/alt1250/alt1250.c
+++ b/drivers/modem/alt1250/alt1250.c
@@ -1028,12 +1028,12 @@ static int alt1250_open(FAR struct file *filep)
if (ret == OK)
{
- nxsem_init(&dev->waitlist.lock, 0, 1);
- nxsem_init(&dev->replylist.lock, 0, 1);
- nxsem_init(&dev->evtmaplock, 0, 1);
- nxsem_init(&dev->pfdlock, 0, 1);
- nxsem_init(&dev->senddisablelock, 0, 1);
- nxsem_init(&dev->select_inst.stat_lock, 0, 1);
+ nxmutex_init(&dev->waitlist.lock);
+ nxmutex_init(&dev->replylist.lock);
+ nxmutex_init(&dev->evtmaplock);
+ nxmutex_init(&dev->pfdlock);
+ nxmutex_init(&dev->senddisablelock);
+ nxmutex_init(&dev->select_inst.stat_lock);
sq_init(&dev->waitlist.queue);
sq_init(&dev->replylist.queue);
@@ -1048,12 +1048,12 @@ static int alt1250_open(FAR struct file *filep)
m_err("thread create failed: %d\n", errno);
ret = -errno;
- nxsem_destroy(&dev->waitlist.lock);
- nxsem_destroy(&dev->replylist.lock);
- nxsem_destroy(&dev->evtmaplock);
- nxsem_destroy(&dev->pfdlock);
- nxsem_destroy(&dev->senddisablelock);
- nxsem_destroy(&dev->select_inst.stat_lock);
+ nxmutex_destroy(&dev->waitlist.lock);
+ nxmutex_destroy(&dev->replylist.lock);
+ nxmutex_destroy(&dev->evtmaplock);
+ nxmutex_destroy(&dev->pfdlock);
+ nxmutex_destroy(&dev->senddisablelock);
+ nxmutex_destroy(&dev->select_inst.stat_lock);
nxmutex_lock(&dev->refslock);
dev->crefs--;
@@ -1103,12 +1103,12 @@ static int alt1250_close(FAR struct file *filep)
if (ret == OK)
{
- nxsem_destroy(&dev->waitlist.lock);
- nxsem_destroy(&dev->replylist.lock);
- nxsem_destroy(&dev->evtmaplock);
- nxsem_destroy(&dev->pfdlock);
- nxsem_destroy(&dev->senddisablelock);
- nxsem_destroy(&dev->select_inst.stat_lock);
+ nxmutex_destroy(&dev->waitlist.lock);
+ nxmutex_destroy(&dev->replylist.lock);
+ nxmutex_destroy(&dev->evtmaplock);
+ nxmutex_destroy(&dev->pfdlock);
+ nxmutex_destroy(&dev->senddisablelock);
+ nxmutex_destroy(&dev->select_inst.stat_lock);
altmdm_fin();
pthread_join(dev->recvthread, NULL);
@@ -1286,7 +1286,7 @@ FAR void *alt1250_register(FAR const char *devpath,
priv->spi = dev;
priv->lower = lower;
- nxsem_init(&priv->refslock, 0, 1);
+ nxmutex_init(&priv->refslock);
ret = register_driver(devpath, &g_alt1250fops, 0666, priv);
if (ret < 0)
diff --git a/drivers/usrsock/usrsock_dev.c b/drivers/usrsock/usrsock_dev.c
index 0d45b2ff52..d14e8a8df6 100644
--- a/drivers/usrsock/usrsock_dev.c
+++ b/drivers/usrsock/usrsock_dev.c
@@ -510,7 +510,7 @@ int usrsock_request(FAR struct iovec *iov, unsigned int iovcnt)
/* Set outstanding request for daemon to handle. */
- net_sem_wait_uninterruptible(&dev->devlock);
+ net_mutex_lock(&dev->devlock);
if (usrsockdev_is_opened(dev))
{
diff --git a/include/nuttx/modem/alt1250.h b/include/nuttx/modem/alt1250.h
index 54377fdd6d..1c2643af50 100644
--- a/include/nuttx/modem/alt1250.h
+++ b/include/nuttx/modem/alt1250.h
@@ -29,6 +29,7 @@
#include <nuttx/fs/ioctl.h>
#include <nuttx/spi/spi.h>
#include <nuttx/queue.h>
+#include <nuttx/mutex.h>
#include <semaphore.h>
#include <debug.h>
#include <nuttx/irq.h>
@@ -285,7 +286,7 @@ typedef struct alt_evtbuf_inst_s
uint16_t altcid;
FAR void **outparam;
size_t outparamlen;
- sem_t stat_lock;
+ mutex_t stat_lock;
alt_evtbuf_state_t stat;
} alt_evtbuf_inst_t;
@@ -323,25 +324,25 @@ 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
{
FAR struct spi_dev_s *spi;
FAR const struct alt1250_lower_s *lower;
- sem_t refslock;
+ mutex_t refslock;
uint8_t crefs;
struct alt_queue_s waitlist;
struct alt_queue_s replylist;
uint64_t evtbitmap;
- sem_t evtmaplock;
- sem_t pfdlock;
+ mutex_t evtmaplock;
+ mutex_t pfdlock;
FAR struct pollfd *pfd;
pthread_t recvthread;
FAR struct alt_evtbuffer_s *evtbuff;
uint32_t discardcnt;
- sem_t senddisablelock;
+ mutex_t senddisablelock;
bool senddisable;
FAR alt_container_t *select_container;
struct alt_evtbuf_inst_s select_inst;
diff --git a/include/nuttx/mutex.h b/include/nuttx/mutex.h
index b790db839e..dd43011960 100644
--- a/include/nuttx/mutex.h
+++ b/include/nuttx/mutex.h
@@ -30,27 +30,33 @@
#include <assert.h>
#include <unistd.h>
+#include <nuttx/clock.h>
#include <nuttx/semaphore.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
-#define NXRMUTEX_NO_HOLDER (pid_t)-1
-#define NXMUTEX_INITIALIZER NXSEM_INITIALIZER(1, SEM_PRIO_INHERIT)
-#define NXRMUTEX_INITIALIZER {NXSEM_INITIALIZER(1, SEM_PRIO_INHERIT), \
- NXRMUTEX_NO_HOLDER, 0}
+#define NXMUTEX_NO_HOLDER (pid_t)-1
+#define NXMUTEX_INITIALIZER {NXSEM_INITIALIZER(1, SEM_PRIO_MUTEX | \
+ SEM_PRIO_INHERIT), NXMUTEX_NO_HOLDER}
+#define NXRMUTEX_INITIALIZER {NXMUTEX_INITIALIZER, 0}
/****************************************************************************
* Public Type Definitions
****************************************************************************/
-typedef sem_t mutex_t;
+struct mutex_s
+{
+ sem_t sem;
+ pid_t holder;
+};
+
+typedef struct mutex_s mutex_t;
struct rmutex_s
{
mutex_t mutex;
- pid_t holder;
unsigned int count;
};
@@ -91,14 +97,15 @@ extern "C"
static inline int nxmutex_init(FAR mutex_t *mutex)
{
- int ret = _SEM_INIT(mutex, 0, 1);
+ int ret = _SEM_INIT(&mutex->sem, 0, 1);
if (ret < 0)
{
return _SEM_ERRVAL(ret);
}
- _SEM_SETPROTOCOL(mutex, SEM_PRIO_INHERIT);
+ mutex->holder = NXMUTEX_NO_HOLDER;
+ _SEM_SETPROTOCOL(&mutex->sem, SEM_PRIO_INHERIT | SEM_PRIO_MUTEX);
return ret;
}
@@ -123,16 +130,59 @@ 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->sem);
if (ret < 0)
{
return _SEM_ERRVAL(ret);
}
+ mutex->holder = NXMUTEX_NO_HOLDER;
return ret;
}
+/****************************************************************************
+ * 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_is_locked
+ *
+ * Description:
+ * This function get the lock state the mutex referenced by 'mutex'.
+ *
+ * Parameters:
+ * mutex - mutex descriptor.
+ *
+ * Return Value:
+ *
+ ****************************************************************************/
+
+static inline bool nxmutex_is_locked(FAR mutex_t *mutex)
+{
+ int cnt;
+ int ret;
+
+ ret = _SEM_GETVALUE(&mutex->sem, &cnt);
+
+ return ret >= 0 && cnt < 1;
+}
+
/****************************************************************************
* Name: nxmutex_lock
*
@@ -157,13 +207,15 @@ static inline int nxmutex_lock(FAR mutex_t *mutex)
{
int ret;
+ DEBUGASSERT(!nxmutex_is_hold(mutex));
for (; ; )
{
/* Take the semaphore (perhaps waiting) */
- ret = _SEM_WAIT(mutex);
+ ret = _SEM_WAIT(&mutex->sem);
if (ret >= 0)
{
+ mutex->holder = gettid();
break;
}
@@ -200,38 +252,68 @@ 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;
+ DEBUGASSERT(!nxmutex_is_hold(mutex));
+ ret = _SEM_TRYWAIT(&mutex->sem);
if (ret < 0)
{
return _SEM_ERRVAL(ret);
}
+ mutex->holder = gettid();
return ret;
}
/****************************************************************************
- * Name: nxmutex_is_locked
+ * Name: nxmutex_timedlock
*
* Description:
- * This function get the lock state the mutex referenced by 'mutex'.
- *
- * Parameters:
- * mutex - mutex descriptor.
- *
- * Return Value:
+ * This function attempts to lock the mutex . If the mutex value
+ * is (<=) zero,then the calling task will not return until it
+ * successfully acquires the lock or timed out
+ *
+ * Input Parameters:
+ * mutex - Mutex object
+ * timeout - The time when mutex lock timed out
+ *
+ * Returned Value:
+ * OK The mutex successfully acquires
+ * EINVAL The mutex argument does not refer to a valid mutex. Or the
+ * thread would have blocked, and the abstime parameter specified
+ * a nanoseconds field value less than zero or greater than or
+ * equal to 1000 million.
+ * ETIMEDOUT The mutex could not be locked before the specified timeout
+ * expired.
+ * EDEADLK A deadlock condition was detected.
*
****************************************************************************/
-static inline bool nxmutex_is_locked(FAR mutex_t *mutex)
+static inline int nxmutex_timedlock(FAR mutex_t *mutex, unsigned int timeout)
{
- int cnt;
int ret;
+ struct timespec now;
+ struct timespec delay;
+ struct timespec rqtp;
+
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ clock_ticks2time(MSEC2TICK(timeout), &delay);
+ clock_timespec_add(&now, &delay, &rqtp);
- ret = _SEM_GETVALUE(mutex, &cnt);
- DEBUGASSERT(ret == OK);
+ /* Wait until we get the lock or until the timeout expires */
- return cnt < 1;
+ do
+ {
+ ret = _SEM_CLOCKWAIT(&mutex->sem, CLOCK_MONOTONIC, &rqtp);
+ }
+ while (ret == -EINTR || ret == -ECANCELED);
+
+ if (ret >= 0)
+ {
+ mutex->holder = gettid();
+ }
+
+ return ret;
}
/****************************************************************************
@@ -258,12 +340,15 @@ static inline int nxmutex_unlock(FAR mutex_t *mutex)
{
int ret;
- ret = _SEM_POST(mutex);
+ DEBUGASSERT(nxmutex_is_hold(mutex));
+
+ ret = _SEM_POST(&mutex->sem);
if (ret < 0)
{
return _SEM_ERRVAL(ret);
}
+ mutex->holder = NXMUTEX_NO_HOLDER;
return ret;
}
@@ -282,7 +367,72 @@ static inline int nxmutex_unlock(FAR mutex_t *mutex)
static inline int nxmutex_reset(FAR mutex_t *mutex)
{
- return nxsem_reset(mutex, 1);
+ int ret;
+
+ ret = nxsem_reset(&mutex->sem, 1);
+ if (ret >= 0)
+ {
+ mutex->holder = NXMUTEX_NO_HOLDER;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nxmutex_breaklock
+ *
+ * Description:
+ * This function attempts to break the mutex
+ *
+ * Parameters:
+ * mutex - Mutex descriptor.
+ * locked - Is the mutex break success
+ *
+ * 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, FAR bool *locked)
+{
+ int ret = OK;
+
+ *locked = false;
+ if (nxmutex_is_hold(mutex))
+ {
+ ret = nxmutex_unlock(mutex);
+ if (ret >= 0)
+ {
+ *locked = true;
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nxmutex_restorelock
+ *
+ * Description:
+ * This function attempts to restore the mutex.
+ *
+ * Parameters:
+ * mutex - mutex descriptor.
+ * locked - true: it's mean that the mutex is broke success
+ *
+ * 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
+ *
+ ****************************************************************************/
+
+static inline int nxmutex_restorelock(FAR mutex_t *mutex, bool locked)
+{
+ return locked ? nxmutex_lock(mutex) : OK;
}
/****************************************************************************
@@ -308,7 +458,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);
}
@@ -330,7 +479,52 @@ static inline int nxrmutex_init(FAR rmutex_t *rmutex)
static inline int nxrmutex_destroy(FAR rmutex_t *rmutex)
{
- return nxmutex_destroy(&rmutex->mutex);
+ int ret = nxmutex_destroy(&rmutex->mutex);
+
+ if (ret >= 0)
+ {
+ rmutex->count = 0;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nxrmutex_is_hold
+ *
+ * Description:
+ * This function check whether the caller hold the recursive mutex
+ * referenced by 'rmutex'.
+ *
+ * Parameters:
+ * rmutex - Recursive mutex descriptor.
+ *
+ * Return Value:
+ *
+ ****************************************************************************/
+
+static inline bool nxrmutex_is_hold(FAR rmutex_t *rmutex)
+{
+ return nxmutex_is_hold(&rmutex->mutex);
+}
+
+/****************************************************************************
+ * Name: nxrmutex_is_locked
+ *
+ * Description:
+ * This function get the lock state the recursive mutex
+ * referenced by 'rmutex'.
+ *
+ * Parameters:
+ * rmutex - Recursive mutex descriptor.
+ *
+ * Return Value:
+ *
+ ****************************************************************************/
+
+static inline bool nxrmutex_is_locked(FAR rmutex_t *rmutex)
+{
+ return nxmutex_is_locked(&rmutex->mutex);
}
/****************************************************************************
@@ -354,23 +548,17 @@ static inline int nxrmutex_destroy(FAR rmutex_t *rmutex)
static inline int nxrmutex_lock(FAR rmutex_t *rmutex)
{
- pid_t tid = gettid();
- int ret;
+ int ret = OK;
- if (rmutex->holder == tid)
+ if (!nxrmutex_is_hold(rmutex))
{
- DEBUGASSERT(rmutex->count < UINT_MAX);
- rmutex->count++;
- ret = OK;
+ ret = nxmutex_lock(&rmutex->mutex);
}
- else
+
+ if (ret >= 0)
{
- ret = nxmutex_lock(&rmutex->mutex);
- if (ret == OK)
- {
- rmutex->holder = tid;
- rmutex->count = 1;
- }
+ DEBUGASSERT(rmutex->count < UINT_MAX);
+ ++rmutex->count;
}
return ret;
@@ -401,64 +589,64 @@ static inline int nxrmutex_lock(FAR rmutex_t *rmutex)
static inline int nxrmutex_trylock(FAR rmutex_t *rmutex)
{
- pid_t tid = gettid();
- int ret;
+ int ret = OK;
- if (rmutex->holder == tid)
+ if (!nxrmutex_is_hold(rmutex))
{
- DEBUGASSERT(rmutex->count < UINT_MAX);
- rmutex->count++;
- ret = OK;
+ ret = nxmutex_trylock(&rmutex->mutex);
}
- else
+
+ if (ret >= 0)
{
- ret = nxmutex_trylock(&rmutex->mutex);
- if (ret == OK)
- {
- rmutex->holder = tid;
- rmutex->count = 1;
- }
+ DEBUGASSERT(rmutex->count < UINT_MAX);
+ ++rmutex->count;
}
return ret;
}
/****************************************************************************
- * Name: nxrmutex_is_locked
+ * Name: nxrmutex_timedlock
*
* Description:
- * This function get the lock state the recursive mutex
- * referenced by 'rmutex'.
- *
- * Parameters:
- * rmutex - Recursive mutex descriptor.
- *
- * Return Value:
+ * This function attempts to lock the mutex . If the mutex value
+ * is (<=) zero,then the calling task will not return until it
+ * successfully acquires the lock or timed out
+ *
+ * Input Parameters:
+ * rmutex - Rmutex object
+ * timeout - The time when mutex lock timed out
+ *
+ * Returned Value:
+ * OK The mutex successfully acquires
+ * EINVAL The mutex argument does not refer to a valid mutex. Or the
+ * thread would have blocked, and the abstime parameter specified
+ * a nanoseconds field value less than zero or greater than or
+ * equal to 1000 million.
+ * ETIMEDOUT The mutex could not be locked before the specified timeout
+ * expired.
+ * EDEADLK A deadlock condition was detected.
+ * ECANCELED May be returned if the thread is canceled while waiting.
*
****************************************************************************/
-static inline bool nxrmutex_is_locked(FAR rmutex_t *rmutex)
+static inline int nxrmutex_timedlock(FAR rmutex_t *rmutex,
+ unsigned int timeout)
{
- return rmutex->count > 0;
-}
+ int ret = OK;
-/****************************************************************************
- * Name: nxrmutex_is_hold
- *
- * Description:
- * This function check whether the caller hold the recursive mutex
- * referenced by 'rmutex'.
- *
- * Parameters:
- * rmutex - Recursive mutex descriptor.
- *
- * Return Value:
- *
- ****************************************************************************/
+ if (!nxrmutex_is_hold(rmutex))
+ {
+ ret = nxmutex_timedlock(&rmutex->mutex, timeout);
+ }
-static inline bool nxrmutex_is_hold(FAR rmutex_t *rmutex)
-{
- return rmutex->holder == gettid();
+ if (ret >= 0)
+ {
+ DEBUGASSERT(rmutex->count < UINT_MAX);
+ ++rmutex->count;
+ }
+
+ return ret;
}
/****************************************************************************
@@ -484,16 +672,43 @@ 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->count > 0);
- if (rmutex->count-- == 1)
+ if (--rmutex->count == 0)
{
- rmutex->holder = NXRMUTEX_NO_HOLDER;
ret = nxmutex_unlock(&rmutex->mutex);
+ if (ret < 0)
+ {
+ ++rmutex->count;
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nxrmutex_reset
+ *
+ * Description:
+ * This function reset lock state.
+ *
+ * Parameters:
+ * rmutex - rmutex descriptor.
+ *
+ * Return Value:
+ *
+ ****************************************************************************/
+
+static inline int nxrmutex_reset(FAR rmutex_t *rmutex)
+{
+ int ret;
+
+ ret = nxmutex_reset(&rmutex->mutex);
+ if (ret >= 0)
+ {
+ rmutex->count = 0;
}
return ret;
@@ -519,16 +734,18 @@ static inline int nxrmutex_unlock(FAR rmutex_t *rmutex)
static inline int nxrmutex_breaklock(FAR rmutex_t *rmutex,
FAR unsigned int *count)
{
- pid_t tid = gettid();
- int ret = -EPERM;
+ int ret = OK;
- if (rmutex->holder == tid)
+ *count = 0;
+ if (nxrmutex_is_hold(rmutex))
{
*count = rmutex->count;
rmutex->count = 0;
- rmutex->holder = NXRMUTEX_NO_HOLDER;
- nxmutex_unlock(&rmutex->mutex);
- ret = OK;
+ ret = nxmutex_unlock(&rmutex->mutex);
+ if (ret < 0)
+ {
+ rmutex->count = *count;
+ }
}
return ret;
@@ -554,15 +771,15 @@ static inline int nxrmutex_breaklock(FAR rmutex_t *rmutex,
static inline int nxrmutex_restorelock(FAR rmutex_t *rmutex,
unsigned int count)
{
- pid_t tid = gettid();
- int ret;
+ int ret = OK;
- DEBUGASSERT(rmutex->holder != tid);
- ret = nxmutex_lock(&rmutex->mutex);
- if (ret == OK)
+ if (count != 0)
{
- rmutex->holder = tid;
- rmutex->count = count;
+ ret = nxmutex_lock(&rmutex->mutex);
+ if (ret >= 0)
+ {
+ rmutex->count = count;
+ }
}
return ret;
diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h
index 504a927d55..68ffa150bf 100644
--- a/include/nuttx/net/net.h
+++ b/include/nuttx/net/net.h
@@ -35,6 +35,7 @@
#include <semaphore.h>
#include <nuttx/queue.h>
+#include <nuttx/mutex.h>
#ifdef CONFIG_MM_IOB
# include <nuttx/mm/iob.h>
#endif
@@ -392,6 +393,30 @@ void net_unlock(void);
int net_sem_timedwait(sem_t *sem, unsigned int timeout);
+/****************************************************************************
+ * Name: net_mutex_timedlock
+ *
+ * Description:
+ * Atomically wait for mutex (or a timeout) while temporarily releasing
+ * the lock on the network.
+ *
+ * Caution should be utilized. Because the network lock is relinquished
+ * during the wait, there could be changes in the network state that occur
+ * before the lock is recovered. Your design should account for this
+ * possibility.
+ *
+ * Input Parameters:
+ * mutex - A reference to the mutex to be taken.
+ * timeout - The relative time to wait until a timeout is declared.
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; a negated errno value is returned on
+ * any failure.
+ *
+ ****************************************************************************/
+
+int net_mutex_timedlock(mutex_t *mutex, unsigned int timeout);
+
/****************************************************************************
* Name: net_sem_wait
*
@@ -414,6 +439,28 @@ int net_sem_timedwait(sem_t *sem, unsigned int timeout);
int net_sem_wait(sem_t *sem);
+/****************************************************************************
+ * Name: net_mutex_lock
+ *
+ * Description:
+ * Atomically wait for mutex while temporarily releasing the network lock.
+ *
+ * Caution should be utilized. Because the network lock is relinquished
+ * during the wait, there could be changes in the network state that occur
+ * before the lock is recovered. Your design should account for this
+ * possibility.
+ *
+ * Input Parameters:
+ * mutex - A reference to the mutex to be taken.
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; a negated errno value is returned on
+ * any failure.
+ *
+ ****************************************************************************/
+
+int net_mutex_lock(mutex_t *mutex);
+
/****************************************************************************
* Name: net_sem_timedwait_uninterruptible
*
diff --git a/include/nuttx/semaphore.h b/include/nuttx/semaphore.h
index 3ad14d514e..9f59b221de 100644
--- a/include/nuttx/semaphore.h
+++ b/include/nuttx/semaphore.h
@@ -40,21 +40,21 @@
#ifdef CONFIG_PRIORITY_INHERITANCE
# if CONFIG_SEM_PREALLOCHOLDERS > 0
-/* semcount, waitlist, flags, hhead */
+/* semcount, flags, waitlist, hhead */
# define NXSEM_INITIALIZER(c, f) \
- {(c), SEM_WAITLIST_INITIALIZER, (f), NULL}
+ {(c), (f), SEM_WAITLIST_INITIALIZER, NULL}
# else
-/* semcount, waitlist, flags, holder[2] */
+/* semcount, flags, waitlist, holder[2] */
# define NXSEM_INITIALIZER(c, f) \
- {(c), SEM_WAITLIST_INITIALIZER, (f), {SEMHOLDER_INITIALIZER, SEMHOLDER_INITIALIZER}}
+ {(c), (f), SEM_WAITLIST_INITIALIZER, {SEMHOLDER_INITIALIZER, SEMHOLDER_INITIALIZER}}
# endif
#else /* CONFIG_PRIORITY_INHERITANCE */
-/* semcount, waitlist */
+/* semcount, flags, waitlist */
# define NXSEM_INITIALIZER(c, f) \
- {(c), SEM_WAITLIST_INITIALIZER}
+ {(c), (f), SEM_WAITLIST_INITIALIZER}
#endif /* CONFIG_PRIORITY_INHERITANCE */
/* Most internal nxsem_* interfaces are not available in the user space in
diff --git a/include/semaphore.h b/include/semaphore.h
index 8ba1906a44..a000397147 100644
--- a/include/semaphore.h
+++ b/include/semaphore.h
@@ -42,6 +42,7 @@
#define SEM_PRIO_INHERIT 1
#define SEM_PRIO_PROTECT 2
#define SEM_PRIO_MASK 3
+#define SEM_PRIO_MUTEX 4
/* Value returned by sem_open() in the event of a failure. */
@@ -99,14 +100,15 @@ struct sem_s
volatile int16_t semcount; /* >0 -> Num counts available */
/* <0 -> Num tasks waiting for semaphore */
- dq_queue_t waitlist;
-
/* If priority inheritance is enabled, then we have to keep track of which
* tasks hold references to the semaphore.
*/
+ uint8_t flags; /* See SEM_PRIO_* definitions */
+
+ dq_queue_t waitlist;
+
#ifdef CONFIG_PRIORITY_INHERITANCE
- uint8_t flags; /* See PRIOINHERIT_FLAGS_* definitions */
# if CONFIG_SEM_PREALLOCHOLDERS > 0
FAR struct semholder_s *hhead; /* List of holders of semaphore counts */
# else
@@ -121,21 +123,21 @@ typedef struct sem_s sem_t;
#ifdef CONFIG_PRIORITY_INHERITANCE
# if CONFIG_SEM_PREALLOCHOLDERS > 0
-/* semcount, waitlist, flags, hhead */
+/* semcount, flags, waitlist, hhead */
# define SEM_INITIALIZER(c) \
- {(c), SEM_WAITLIST_INITIALIZER, 0, NULL}
+ {(c), 0, SEM_WAITLIST_INITIALIZER, NULL}
# else
-/* semcount, waitlist, flags, holder[2] */
+/* semcount, flags, waitlist, holder[2] */
# define SEM_INITIALIZER(c) \
- {(c), SEM_WAITLIST_INITIALIZER, 0, {SEMHOLDER_INITIALIZER, SEMHOLDER_INITIALIZER}}
+ {(c), 0, SEM_WAITLIST_INITIALIZER, {SEMHOLDER_INITIALIZER, SEMHOLDER_INITIALIZER}}
# endif
#else
-/* semcount, waitlist */
+/* semcount, flags, waitlist */
# define SEM_INITIALIZER(c) \
- {(c), SEM_WAITLIST_INITIALIZER}
+ {(c), 0, SEM_WAITLIST_INITIALIZER}
#endif
# define SEM_WAITLIST(sem) (&((sem)->waitlist))
diff --git a/libs/libc/semaphore/sem_getprotocol.c b/libs/libc/semaphore/sem_getprotocol.c
index 2e1f63fbc8..38dbd172e7 100644
--- a/libs/libc/semaphore/sem_getprotocol.c
+++ b/libs/libc/semaphore/sem_getprotocol.c
@@ -54,11 +54,6 @@ int sem_getprotocol(FAR sem_t *sem, FAR int *protocol)
{
DEBUGASSERT(sem != NULL && protocol != NULL);
-#ifdef CONFIG_PRIORITY_INHERITANCE
*protocol = sem->flags;
-#else
- *protocol = SEM_PRIO_NONE;
-#endif
-
return OK;
}
diff --git a/libs/libc/semaphore/sem_init.c b/libs/libc/semaphore/sem_init.c
index fdcd8d9f5e..46400b9377 100644
--- a/libs/libc/semaphore/sem_init.c
+++ b/libs/libc/semaphore/sem_init.c
@@ -76,8 +76,9 @@ int nxsem_init(FAR sem_t *sem, int pshared, unsigned int value)
/* Initialize to support priority inheritance */
-#ifdef CONFIG_PRIORITY_INHERITANCE
sem->flags = 0;
+
+#ifdef CONFIG_PRIORITY_INHERITANCE
# if CONFIG_SEM_PREALLOCHOLDERS > 0
sem->hhead = NULL;
# else
diff --git a/libs/libc/wqueue/work_usrthread.c b/libs/libc/wqueue/work_usrthread.c
index d04be2fe94..3d57ca4ff8 100644
--- a/libs/libc/wqueue/work_usrthread.c
+++ b/libs/libc/wqueue/work_usrthread.c
@@ -191,7 +191,7 @@ static void work_process(FAR struct usr_wqueue_s *wqueue)
{
/* Wait indefinitely until work_queue has new items */
- nxmutex_lock(&wqueue->wake);
+ _SEM_WAIT(&wqueue->wake);
}
else
{
diff --git a/net/usrsock/usrsock_devif.c b/net/usrsock/usrsock_devif.c
index d061d5ee41..b3f8fdd63d 100644
--- a/net/usrsock/usrsock_devif.c
+++ b/net/usrsock/usrsock_devif.c
@@ -641,7 +641,7 @@ int usrsock_do_request(FAR struct usrsock_conn_s *conn,
/* Set outstanding request for daemon to handle. */
- net_sem_wait_uninterruptible(&req->lock);
+ net_mutex_lock(&req->lock);
if (++req->newxid == 0)
{
++req->newxid;
@@ -700,7 +700,7 @@ void usrsock_abort(void)
* requests.
*/
- ret = net_sem_timedwait(&req->lock, 10);
+ ret = net_mutex_timedlock(&req->lock, 10);
if (ret < 0)
{
if (ret != -ETIMEDOUT && ret != -EINTR)
diff --git a/net/utils/net_lock.c b/net/utils/net_lock.c
index 7f63608b65..8b499b4a84 100644
--- a/net/utils/net_lock.c
+++ b/net/utils/net_lock.c
@@ -242,6 +242,69 @@ int net_sem_timedwait(sem_t *sem, unsigned int timeout)
return _net_timedwait(sem, true, timeout);
}
+/****************************************************************************
+ * Name: net_mutex_timedlock
+ *
+ * Description:
+ * Atomically wait for mutex (or a timeout) while temporarily releasing
+ * the lock on the network.
+ *
+ * Caution should be utilized. Because the network lock is relinquished
+ * during the wait, there could be changes in the network state that occur
+ * before the lock is recovered. Your design should account for this
+ * possibility.
+ *
+ * Input Parameters:
+ * mutex - A reference to the mutex to be taken.
+ * timeout - The relative time to wait until a timeout is declared.
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; a negated errno value is returned on
+ * any failure.
+ *
+ ****************************************************************************/
+
+int net_mutex_timedlock(mutex_t *mutex, unsigned int timeout)
+{
+ unsigned int count;
+ irqstate_t flags;
+ int blresult;
+ int ret;
+
+ flags = enter_critical_section(); /* No interrupts */
+ sched_lock(); /* No context switches */
+
+ /* Release the network lock, remembering my count. net_breaklock will
+ * return a negated value if the caller does not hold the network lock.
+ */
+
+ blresult = net_breaklock(&count);
+
+ /* Now take the mutex, waiting if so requested. */
+
+ if (timeout != UINT_MAX)
+ {
+ ret = nxmutex_timedlock(mutex, timeout);
+ }
+ else
+ {
+ /* Wait as long as necessary to get the lock */
+
+ ret = nxmutex_lock(mutex);
+ }
+
+ /* Recover the network lock at the proper count (if we held it before) */
+
+ if (blresult >= 0)
+ {
+ net_restorelock(count);
+ }
+
+ sched_unlock();
+ leave_critical_section(flags);
+ return ret;
+}
+
/****************************************************************************
* Name: net_sem_wait
*
@@ -267,6 +330,31 @@ int net_sem_wait(sem_t *sem)
return net_sem_timedwait(sem, UINT_MAX);
}
+/****************************************************************************
+ * Name: net_mutex_lock
+ *
+ * Description:
+ * Atomically wait for mutex while temporarily releasing the network lock.
+ *
+ * Caution should be utilized. Because the network lock is relinquished
+ * during the wait, there could be changes in the network state that occur
+ * before the lock is recovered. Your design should account for this
+ * possibility.
+ *
+ * Input Parameters:
+ * mutex - A reference to the mutex to be taken.
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; a negated errno value is returned on
+ * any failure.
+ *
+ ****************************************************************************/
+
+int net_mutex_lock(mutex_t *mutex)
+{
+ return net_mutex_timedlock(mutex, UINT_MAX);
+}
+
/****************************************************************************
* Name: net_sem_timedwait_uninterruptible
*