Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
522 changes: 522 additions & 0 deletions include/mutex.h

Large diffs are not rendered by default.

184 changes: 116 additions & 68 deletions include/nuttx/mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,41 +25,81 @@
* Included Files
****************************************************************************/

#include <stdbool.h>
#include <nuttx/config.h>

#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <mutex.h>

#include <nuttx/semaphore.h>

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

#define NXRMUTEX_NO_HOLDER (pid_t)-1
#define NXMUTEX_INITIALIZER SEM_INITIALIZER(1)
#define NXRMUTEX_INITIALIZER {SEM_INITIALIZER(1), NXRMUTEX_NO_HOLDER, 0}

/****************************************************************************
* Public Type Definitions
****************************************************************************/

typedef sem_t mutex_t;

struct rmutex_s
{
mutex_t mutex;
pid_t holder;
uint16_t count;
};

typedef struct rmutex_s rmutex_t;
/* Initializers */

#define NXMUTEX_INITIALIZER {NXSEM_INITIALIZER(1,0),MUTEX_NO_HOLDER}
#define NXRMUTEX_INITIALIZER {NXMUTEX_INITIALIZER,0}

/* Most internal nxsem_* interfaces are not available in the user space in
* PROTECTED and KERNEL builds. In that context, the application semaphore
* interfaces must be used. The differences between the two sets of
* interfaces are: (1) the nxsem_* interfaces do not cause cancellation
* points and (2) they do not modify the errno variable.
*
* This is only important when compiling libraries (libc or libnx) that are
* used both by the OS (libkc.a and libknx.a) or by the applications
* (libc.a and libnx.a). In that case, the correct interface must be
* used for the build context.
*
* REVISIT: In the flat build, the same functions must be used both by
* the OS and by applications. We have to use the normal user functions
* in this case or we will fail to set the errno or fail to create the
* cancellation point.
*/

#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
# define _MUTEX_INIT(m) nxmutex_init(m)
# define _MUTEX_DESTROY(m) nxmutex_destroy(m)
# define _MUTEX_LOCK(m) nxmutex_lock(m)
# define _MUTEX_TRYLOCK(m) nxmutex_trylock(m)
# define _MUTEX_IS_LOCKED(m) nxmutex_is_locked(m)
# define _MUTEX_UNLOCK(m) nxmutex_unlock(m)
# define _MUTEX_ERRNO(r) (-(r))
# define _MUTEX_ERRVAL(r) (r)

# define _RMUTEX_INIT(m) nxrmutex_init(m)
# define _RMUTEX_DESTROY(m) nxrmutex_destroy(m)
# define _RMUTEX_LOCK(m) nxrmutex_lock(m)
# define _RMUTEX_TRYLOCK(m) nxrmutex_trylock(m)
# define _RMUTEX_IS_LOCKED(m) nxrmutex_is_locked(m)
# define _RMUTEX_UNLOCK(m) nxrmutex_unlock(m)
# define _RMUTEX_ERRNO(r) (-(r))
# define _RMUTEX_ERRVAL(r) (r)
#else
# define _MUTEX_INIT(m) mutex_init(m)
# define _MUTEX_DESTROY(m) mutex_destroy(m)
# define _MUTEX_LOCK(m) mutex_lock(m)
# define _MUTEX_TRYLOCK(m) mutex_trylock(m)
# define _MUTEX_IS_LOCKED(m) mutex_is_locked(m)
# define _MUTEX_UNLOCK(m) mutex_unlock(m)
# define _MUTEX_ERRNO(r) errno
# define _MUTEX_ERRVAL(r) (-errno)

# define _RMUTEX_INIT(m) rmutex_init(m)
# define _RMUTEX_DESTROY(m) rmutex_destroy(m)
# define _RMUTEX_LOCK(m) rmutex_lock(m)
# define _RMUTEX_TRYLOCK(m) rmutex_trylock(m)
# define _RMUTEX_IS_LOCKED(m) rmutex_is_locked(m)
# define _RMUTEX_UNLOCK(m) rmutex_unlock(m)
# define _RMUTEX_ERRNO(r) errno
# define _RMUTEX_ERRVAL(r) (-errno)
#endif

/****************************************************************************
* Public Function Prototypes
****************************************************************************/

#ifndef __ASSEMBLY__

#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
Expand Down Expand Up @@ -89,14 +129,10 @@ extern "C"

static inline int nxmutex_init(FAR mutex_t *mutex)
{
int ret = _SEM_INIT(mutex, 0, 1);

if (ret < 0)
{
return _SEM_ERRVAL(ret);
}
DEBUGASSERT(mutex != NULL);

return ret;
mutex->holder = MUTEX_NO_HOLDER;
return nxsem_init(&mutex->sem, 0, 1);
}

/****************************************************************************
Expand All @@ -120,14 +156,9 @@ static inline int nxmutex_init(FAR mutex_t *mutex)

static inline int nxmutex_destroy(FAR mutex_t *mutex)
{
int ret = _SEM_DESTROY(mutex);
DEBUGASSERT(mutex != NULL);

if (ret < 0)
{
return _SEM_ERRVAL(ret);
}

return ret;
return nxsem_destroy(&mutex->sem);
}

/****************************************************************************
Expand All @@ -154,21 +185,19 @@ static inline int nxmutex_lock(FAR mutex_t *mutex)
{
int ret;

for (; ; )
DEBUGASSERT(mutex != NULL);

do
{
/* Take the semaphore (perhaps waiting) */

ret = _SEM_WAIT(mutex);
if (ret >= 0)
{
break;
}
ret = nxsem_wait_uninterruptible(&mutex->sem);
}
while (ret == -ECANCELED);

ret = _SEM_ERRVAL(ret);
if (ret != -EINTR && ret != -ECANCELED)
{
break;
}
if (ret == OK)
{
mutex->holder = gettid();
}

return ret;
Expand Down Expand Up @@ -197,11 +226,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;

if (ret < 0)
DEBUGASSERT(mutex != NULL);

ret = nxsem_trywait(&mutex->sem);
if (ret == OK)
{
return _SEM_ERRVAL(ret);
mutex->holder = gettid();
}

return ret;
Expand All @@ -225,7 +257,9 @@ static inline bool nxmutex_is_locked(FAR mutex_t *mutex)
int cnt;
int ret;

ret = _SEM_GETVALUE(mutex, &cnt);
DEBUGASSERT(mutex != NULL);

ret = nxsem_get_value(&mutex->sem, &cnt);

DEBUGASSERT(ret == OK);

Expand Down Expand Up @@ -256,10 +290,16 @@ static inline int nxmutex_unlock(FAR mutex_t *mutex)
{
int ret;

ret = _SEM_POST(mutex);
if (ret < 0)
DEBUGASSERT(mutex != NULL);

if (mutex->holder == gettid())
{
mutex->holder = MUTEX_NO_HOLDER;
ret = nxsem_post(&mutex->sem);
}
else
{
return _SEM_ERRVAL(ret);
ret = -EPERM;
}

return ret;
Expand Down Expand Up @@ -287,8 +327,9 @@ static inline int nxmutex_unlock(FAR mutex_t *mutex)

static inline int nxrmutex_init(FAR rmutex_t *rmutex)
{
DEBUGASSERT(rmutex != NULL);

rmutex->count = 0;
rmutex->holder = NXRMUTEX_NO_HOLDER;
return nxmutex_init(&rmutex->mutex);
}

Expand All @@ -310,6 +351,8 @@ static inline int nxrmutex_init(FAR rmutex_t *rmutex)

static inline int nxrmutex_destroy(FAR rmutex_t *rmutex)
{
DEBUGASSERT(rmutex != NULL);

return nxmutex_destroy(&rmutex->mutex);
}

Expand All @@ -334,10 +377,11 @@ 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)
DEBUGASSERT(rmutex != NULL);

if (rmutex->mutex.holder == gettid())
{
DEBUGASSERT(rmutex->count < UINT16_MAX);
rmutex->count++;
Expand All @@ -348,7 +392,6 @@ static inline int nxrmutex_lock(FAR rmutex_t *rmutex)
ret = nxmutex_lock(&rmutex->mutex);
if (ret == OK)
{
rmutex->holder = tid;
rmutex->count = 1;
}
}
Expand Down Expand Up @@ -381,10 +424,11 @@ 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)
DEBUGASSERT(rmutex != NULL);

if (rmutex->mutex.holder == gettid())
{
DEBUGASSERT(rmutex->count < UINT16_MAX);
rmutex->count++;
Expand All @@ -395,7 +439,6 @@ static inline int nxrmutex_trylock(FAR rmutex_t *rmutex)
ret = nxmutex_trylock(&rmutex->mutex);
if (ret == OK)
{
rmutex->holder = tid;
rmutex->count = 1;
}
}
Expand All @@ -419,7 +462,9 @@ static inline int nxrmutex_trylock(FAR rmutex_t *rmutex)

static inline bool nxrmutex_is_locked(FAR rmutex_t *rmutex)
{
return rmutex->count > 0;
DEBUGASSERT(rmutex != NULL);

return nxmutex_is_locked(&rmutex->mutex);
}

/****************************************************************************
Expand All @@ -445,16 +490,16 @@ static inline bool nxrmutex_is_locked(FAR rmutex_t *rmutex)

static inline int nxrmutex_unlock(FAR rmutex_t *rmutex)
{
pid_t tid = gettid();
int ret = -EPERM;
int ret;

DEBUGASSERT(rmutex != NULL);

if (rmutex->holder == tid)
if (rmutex->mutex.holder == gettid())
{
DEBUGASSERT(rmutex->count > 0);
if (rmutex->count == 1)
{
rmutex->count = 0;
rmutex->holder = NXRMUTEX_NO_HOLDER;
ret = nxmutex_unlock(&rmutex->mutex);
}
else
Expand All @@ -463,6 +508,10 @@ static inline int nxrmutex_unlock(FAR rmutex_t *rmutex)
ret = OK;
}
}
else
{
ret = -EPERM;
}

return ret;
}
Expand All @@ -472,5 +521,4 @@ static inline int nxrmutex_unlock(FAR rmutex_t *rmutex)
}
#endif

#endif /* __ASSEMBLY__ */
#endif /* __INCLUDE_NUTTX_MUTEX_H */
2 changes: 1 addition & 1 deletion include/nuttx/serial/tioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
/* Controlling TTY */

#define TIOCSCTTY _TIOC(0x0018) /* Make controlling TTY: int */
#define TIOCNOTTY _TIOC(0x0019) /* Give up controllinog TTY: void */
#define TIOCNOTTY _TIOC(0x0019) /* Give up controlling TTY: void */

/* Exclusive mode */

Expand Down
6 changes: 3 additions & 3 deletions libs/libc/modlib/modlib_registry.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
* Private Data
****************************************************************************/

static rmutex_t g_modlock = NXRMUTEX_INITIALIZER;
static rmutex_t g_modlock = RMUTEX_INITIALIZER;

static FAR struct module_s *g_mod_registry;

Expand All @@ -68,7 +68,7 @@ static FAR struct module_s *g_mod_registry;

void modlib_registry_lock(void)
{
nxrmutex_lock(&g_modlock);
_RMUTEX_LOCK(&g_modlock);
}

/****************************************************************************
Expand All @@ -87,7 +87,7 @@ void modlib_registry_lock(void)

void modlib_registry_unlock(void)
{
nxrmutex_unlock(&g_modlock);
_RMUTEX_UNLOCK(&g_modlock);
}

/****************************************************************************
Expand Down
6 changes: 3 additions & 3 deletions libs/libc/netdb/lib_dnsinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

/* Protects DNS cache, nameserver list and notify list. */

static rmutex_t g_dns_lock = NXRMUTEX_INITIALIZER;
static rmutex_t g_dns_lock = RMUTEX_INITIALIZER;

/****************************************************************************
* Public Data
Expand Down Expand Up @@ -143,7 +143,7 @@ bool dns_initialize(void)

void dns_semtake(void)
{
nxrmutex_lock(&g_dns_lock);
_RMUTEX_LOCK(&g_dns_lock);
}

/****************************************************************************
Expand All @@ -156,5 +156,5 @@ void dns_semtake(void)

void dns_semgive(void)
{
nxrmutex_unlock(&g_dns_lock);
_RMUTEX_UNLOCK(&g_dns_lock);
}
Loading