sched: change pthread_mutex implementation from sem to mutex
Since pthread_mutex is implemented by sem, it is impossible to see in ps who holds the lock and causes the wait. Replace sem with mutex implementation to solve the above problems Signed-off-by: yinshengkai <yinshengkai@xiaomi.com>
This commit is contained in:
parent
2fd3981a8e
commit
d7f02a8cb6
@ -27,6 +27,7 @@
|
||||
|
||||
#include <nuttx/config.h> /* Default settings */
|
||||
#include <nuttx/compiler.h> /* Compiler settings, noreturn_function */
|
||||
#include <nuttx/mutex.h>
|
||||
|
||||
#include <sys/types.h> /* Needed for general types */
|
||||
#include <stdint.h> /* C99 fixed width integer types */
|
||||
@ -34,7 +35,6 @@
|
||||
#include <unistd.h> /* For getpid */
|
||||
#include <signal.h> /* Needed for sigset_t, includes this file */
|
||||
#include <time.h> /* Needed for struct timespec */
|
||||
#include <semaphore.h> /* For sem_t and SEM_PRIO_* defines */
|
||||
|
||||
#ifdef CONFIG_PTHREAD_SPINLOCKS
|
||||
/* The architecture specific spinlock.h header file must provide the
|
||||
@ -301,18 +301,16 @@ struct pthread_mutex_s
|
||||
/* Supports a singly linked list */
|
||||
|
||||
FAR struct pthread_mutex_s *flink;
|
||||
uint8_t flags; /* See _PTHREAD_MFLAGS_* */
|
||||
#endif
|
||||
|
||||
/* Payload */
|
||||
|
||||
sem_t sem; /* Semaphore underlying the implementation of the mutex */
|
||||
pid_t pid; /* ID of the holder of the mutex */
|
||||
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
|
||||
uint8_t flags; /* See _PTHREAD_MFLAGS_* */
|
||||
#endif
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
uint8_t type; /* Type of the mutex. See PTHREAD_MUTEX_* definitions */
|
||||
int16_t nlocks; /* The number of recursive locks held */
|
||||
rmutex_t mutex; /* Mutex underlying the implementation of the mutex */
|
||||
#else
|
||||
mutex_t mutex; /* Mutex underlying the implementation of the mutex */
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -330,24 +328,24 @@ typedef struct pthread_mutex_s pthread_mutex_t;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PTHREAD_MUTEX_TYPES) && !defined(CONFIG_PTHREAD_MUTEX_UNSAFE)
|
||||
# define PTHREAD_MUTEX_INITIALIZER {NULL, SEM_INITIALIZER(1), -1, \
|
||||
__PTHREAD_MUTEX_DEFAULT_FLAGS, \
|
||||
PTHREAD_MUTEX_DEFAULT, 0}
|
||||
# define PTHREAD_MUTEX_INITIALIZER {NULL, __PTHREAD_MUTEX_DEFAULT_FLAGS, \
|
||||
PTHREAD_MUTEX_DEFAULT, \
|
||||
NXRMUTEX_INITIALIZER}
|
||||
# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
|
||||
{NULL, SEM_INITIALIZER(1), -1, \
|
||||
__PTHREAD_MUTEX_DEFAULT_FLAGS, \
|
||||
PTHREAD_MUTEX_RECURSIVE, 0}
|
||||
{NULL, __PTHREAD_MUTEX_DEFAULT_FLAGS, \
|
||||
PTHREAD_MUTEX_RECURSIVE, \
|
||||
NXRMUTEX_INITIALIZER,}
|
||||
#elif defined(CONFIG_PTHREAD_MUTEX_TYPES)
|
||||
# define PTHREAD_MUTEX_INITIALIZER {SEM_INITIALIZER(1), -1, \
|
||||
PTHREAD_MUTEX_DEFAULT, 0}
|
||||
# define PTHREAD_MUTEX_INITIALIZER {PTHREAD_MUTEX_DEFAULT, \
|
||||
NXRMUTEX_INITIALIZER,}
|
||||
# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
|
||||
{SEM_INITIALIZER(1), -1, \
|
||||
PTHREAD_MUTEX_RECURSIVE, 0}
|
||||
{PTHREAD_MUTEX_RECURSIVE, \
|
||||
NXRMUTEX_INITIALIZER}
|
||||
#elif !defined(CONFIG_PTHREAD_MUTEX_UNSAFE)
|
||||
# define PTHREAD_MUTEX_INITIALIZER {NULL, SEM_INITIALIZER(1), -1,\
|
||||
__PTHREAD_MUTEX_DEFAULT_FLAGS}
|
||||
# define PTHREAD_MUTEX_INITIALIZER {NULL, __PTHREAD_MUTEX_DEFAULT_FLAGS,\
|
||||
NXMUTEX_INITIALIZER}
|
||||
#else
|
||||
# define PTHREAD_MUTEX_INITIALIZER {SEM_INITIALIZER(1), -1}
|
||||
# define PTHREAD_MUTEX_INITIALIZER {NXMUTEX_INITIALIZER}
|
||||
#endif
|
||||
|
||||
struct pthread_barrierattr_s
|
||||
|
@ -36,6 +36,40 @@
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/sched.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
# define mutex_init(m) nxrmutex_init(m)
|
||||
# define mutex_destroy(m) nxrmutex_destroy(m)
|
||||
# define mutex_is_hold(m) nxrmutex_is_hold(m)
|
||||
# define mutex_is_locked(m) nxrmutex_is_locked(m)
|
||||
# define mutex_is_recursive(m) nxrmutex_is_recursive(m)
|
||||
# define mutex_get_holder(m) nxrmutex_get_holder(m)
|
||||
# define mutex_reset(m) nxrmutex_reset(m)
|
||||
# define mutex_unlock(m) nxrmutex_unlock(m)
|
||||
# define mutex_lock(m) nxrmutex_lock(m)
|
||||
# define mutex_trylock(m) nxrmutex_trylock(m)
|
||||
# define mutex_breaklock(m,v) nxrmutex_breaklock(m,v)
|
||||
# define mutex_restorelock(m,v) nxrmutex_restorelock(m,v)
|
||||
# define mutex_clocklock(m,t) nxrmutex_clocklock(m,CLOCK_REALTIME,t)
|
||||
#else
|
||||
# define mutex_init(m) nxmutex_init(m)
|
||||
# define mutex_destroy(m) nxmutex_destroy(m)
|
||||
# define mutex_is_hold(m) nxmutex_is_hold(m)
|
||||
# define mutex_is_recursive(m) (false)
|
||||
# define mutex_is_locked(m) nxmutex_is_locked(m)
|
||||
# define mutex_get_holder(m) nxmutex_get_holder(m)
|
||||
# define mutex_reset(m) nxmutex_reset(m)
|
||||
# define mutex_unlock(m) nxmutex_unlock(m)
|
||||
# define mutex_lock(m) nxmutex_lock(m)
|
||||
# define mutex_trylock(m) nxmutex_trylock(m)
|
||||
# define mutex_breaklock(m,v) nxmutex_breaklock(m, v)
|
||||
# define mutex_restorelock(m,v) nxmutex_restorelock(m, v)
|
||||
# define mutex_clocklock(m,t) nxmutex_clocklock(m,CLOCK_REALTIME,t)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
@ -76,11 +110,18 @@ int pthread_mutex_take(FAR struct pthread_mutex_s *mutex,
|
||||
FAR const struct timespec *abs_timeout);
|
||||
int pthread_mutex_trytake(FAR struct pthread_mutex_s *mutex);
|
||||
int pthread_mutex_give(FAR struct pthread_mutex_s *mutex);
|
||||
int pthread_mutex_breaklock(FAR struct pthread_mutex_s *mutex,
|
||||
FAR unsigned int *breakval);
|
||||
int pthread_mutex_restorelock(FAR struct pthread_mutex_s *mutex,
|
||||
unsigned int breakval);
|
||||
void pthread_mutex_inconsistent(FAR struct tcb_s *tcb);
|
||||
#else
|
||||
# define pthread_mutex_take(m,abs_timeout) pthread_sem_take(&(m)->sem,(abs_timeout))
|
||||
# define pthread_mutex_trytake(m) pthread_sem_trytake(&(m)->sem)
|
||||
# define pthread_mutex_give(m) pthread_sem_give(&(m)->sem)
|
||||
# define pthread_mutex_take(m,abs_timeout) -mutex_clocklock(&(m)->mutex, \
|
||||
abs_timeout)
|
||||
# define pthread_mutex_trytake(m) -mutex_trylock(&(m)->mutex)
|
||||
# define pthread_mutex_give(m) -mutex_unlock(&(m)->mutex)
|
||||
# define pthread_mutex_breaklock(m,v) -mutex_breaklock(&(m)->mutex,v)
|
||||
# define pthread_mutex_restorelock(m,v) -mutex_restorelock(&(m)->mutex,v)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
|
@ -74,7 +74,6 @@ int pthread_cond_clockwait(FAR pthread_cond_t *cond,
|
||||
FAR const struct timespec *abstime)
|
||||
{
|
||||
irqstate_t flags;
|
||||
int mypid = nxsched_gettid();
|
||||
int ret = OK;
|
||||
int status;
|
||||
|
||||
@ -93,7 +92,7 @@ int pthread_cond_clockwait(FAR pthread_cond_t *cond,
|
||||
|
||||
/* Make sure that the caller holds the mutex */
|
||||
|
||||
else if (mutex->pid != mypid)
|
||||
else if (!mutex_is_hold(&mutex->mutex))
|
||||
{
|
||||
ret = EPERM;
|
||||
}
|
||||
@ -109,9 +108,7 @@ int pthread_cond_clockwait(FAR pthread_cond_t *cond,
|
||||
|
||||
else
|
||||
{
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
int16_t nlocks;
|
||||
#endif
|
||||
unsigned int nlocks;
|
||||
|
||||
sinfo("Give up mutex...\n");
|
||||
|
||||
@ -126,11 +123,7 @@ int pthread_cond_clockwait(FAR pthread_cond_t *cond,
|
||||
|
||||
/* Give up the mutex */
|
||||
|
||||
mutex->pid = INVALID_PROCESS_ID;
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
nlocks = mutex->nlocks;
|
||||
#endif
|
||||
ret = pthread_mutex_give(mutex);
|
||||
ret = pthread_mutex_breaklock(mutex, &nlocks);
|
||||
if (ret == 0)
|
||||
{
|
||||
status = nxsem_clockwait_uninterruptible(&cond->sem,
|
||||
@ -151,17 +144,10 @@ int pthread_cond_clockwait(FAR pthread_cond_t *cond,
|
||||
|
||||
sinfo("Re-locking...\n");
|
||||
|
||||
status = pthread_mutex_take(mutex, NULL);
|
||||
if (status == OK)
|
||||
status = pthread_mutex_restorelock(mutex, nlocks);
|
||||
if (ret == 0)
|
||||
{
|
||||
mutex->pid = mypid;
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
mutex->nlocks = nlocks;
|
||||
#endif
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
ret = status;
|
||||
ret = status;
|
||||
}
|
||||
|
||||
/* Re-enable pre-emption (It is expected that interrupts
|
||||
|
@ -75,15 +75,13 @@ int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex)
|
||||
|
||||
/* Make sure that the caller holds the mutex */
|
||||
|
||||
else if (mutex->pid != nxsched_gettid())
|
||||
else if (!mutex_is_hold(&mutex->mutex))
|
||||
{
|
||||
ret = EPERM;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
int16_t nlocks;
|
||||
#endif
|
||||
unsigned int nlocks;
|
||||
|
||||
/* Give up the mutex */
|
||||
|
||||
@ -91,11 +89,7 @@ int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex)
|
||||
|
||||
flags = enter_critical_section();
|
||||
sched_lock();
|
||||
mutex->pid = INVALID_PROCESS_ID;
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
nlocks = mutex->nlocks;
|
||||
#endif
|
||||
ret = pthread_mutex_give(mutex);
|
||||
ret = pthread_mutex_breaklock(mutex, &nlocks);
|
||||
|
||||
/* Take the semaphore. This may be awakened only be a signal (EINTR)
|
||||
* or if the thread is canceled (ECANCELED)
|
||||
@ -121,25 +115,13 @@ int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex)
|
||||
|
||||
sinfo("Reacquire mutex...\n");
|
||||
|
||||
status = pthread_mutex_take(mutex, NULL);
|
||||
status = pthread_mutex_restorelock(mutex, nlocks);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Report the first failure that occurs */
|
||||
|
||||
ret = status;
|
||||
}
|
||||
|
||||
/* Did we get the mutex? */
|
||||
|
||||
if (status == OK)
|
||||
{
|
||||
/* Yes.. Then initialize it properly */
|
||||
|
||||
mutex->pid = nxsched_gettid();
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
mutex->nlocks = nlocks;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
leave_cancellation_point();
|
||||
|
@ -158,13 +158,20 @@ int pthread_mutex_take(FAR struct pthread_mutex_s *mutex,
|
||||
{
|
||||
ret = EOWNERDEAD;
|
||||
}
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
else if (mutex_is_hold(&mutex->mutex) &&
|
||||
mutex->type != PTHREAD_MUTEX_RECURSIVE)
|
||||
{
|
||||
ret = EDEADLK;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* Take semaphore underlying the mutex. pthread_sem_take
|
||||
* returns zero on success and a positive errno value on failure.
|
||||
/* mutex_clocklock returns zero when successful, and the negative
|
||||
* errno value is returned when failed.
|
||||
*/
|
||||
|
||||
ret = pthread_sem_take(&mutex->sem, abs_timeout);
|
||||
ret = -mutex_clocklock(&mutex->mutex, abs_timeout);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Check if the holder of the mutex has terminated without
|
||||
@ -174,12 +181,19 @@ int pthread_mutex_take(FAR struct pthread_mutex_s *mutex,
|
||||
|
||||
if ((mutex->flags & _PTHREAD_MFLAGS_INCONSISTENT) != 0)
|
||||
{
|
||||
/* If the holder thread has terminated, we need to reset
|
||||
* the mutex and return an error.
|
||||
*/
|
||||
|
||||
mutex_reset(&mutex->mutex);
|
||||
ret = EOWNERDEAD;
|
||||
}
|
||||
|
||||
/* Add the mutex to the list of mutexes held by this task */
|
||||
/* If mutex is recursion, it is already in the linked list,
|
||||
* and we should not add it to the link list again.
|
||||
*/
|
||||
|
||||
else
|
||||
else if (!mutex_is_recursive(&mutex->mutex))
|
||||
{
|
||||
pthread_mutex_add(mutex);
|
||||
}
|
||||
@ -228,18 +242,27 @@ int pthread_mutex_trytake(FAR struct pthread_mutex_s *mutex)
|
||||
{
|
||||
ret = EOWNERDEAD;
|
||||
}
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
else if (mutex_is_hold(&mutex->mutex) &&
|
||||
mutex->type != PTHREAD_MUTEX_RECURSIVE)
|
||||
{
|
||||
ret = EBUSY;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* Try to take the semaphore underlying the mutex */
|
||||
|
||||
ret = nxsem_trywait(&mutex->sem);
|
||||
ret = mutex_trylock(&mutex->mutex);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
}
|
||||
else
|
||||
else if (!mutex_is_recursive(&mutex->mutex))
|
||||
{
|
||||
/* Add the mutex to the list of mutexes held by this task */
|
||||
/* If we successfully acquire the mutex, and we didn't get
|
||||
* it before, add the mutex to the linked list.
|
||||
*/
|
||||
|
||||
pthread_mutex_add(mutex);
|
||||
}
|
||||
@ -277,11 +300,58 @@ int pthread_mutex_give(FAR struct pthread_mutex_s *mutex)
|
||||
{
|
||||
/* Remove the mutex from the list of mutexes held by this task */
|
||||
|
||||
pthread_mutex_remove(mutex);
|
||||
if (!mutex_is_recursive(&mutex->mutex))
|
||||
{
|
||||
pthread_mutex_remove(mutex);
|
||||
}
|
||||
|
||||
/* Now release the underlying semaphore */
|
||||
/* Now release the underlying mutex */
|
||||
|
||||
ret = pthread_sem_give(&mutex->sem);
|
||||
ret = -mutex_unlock(&mutex->mutex);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pthread_mutex_breaklock(FAR struct pthread_mutex_s *mutex,
|
||||
FAR unsigned int *breakval)
|
||||
{
|
||||
int ret = EINVAL;
|
||||
|
||||
/* Verify input parameters */
|
||||
|
||||
DEBUGASSERT(mutex != NULL);
|
||||
if (mutex != NULL)
|
||||
{
|
||||
/* Remove the mutex from the list of mutexes held by this task */
|
||||
|
||||
pthread_mutex_remove(mutex);
|
||||
|
||||
/* Now release the underlying mutex */
|
||||
|
||||
ret = -mutex_breaklock(&mutex->mutex, breakval);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pthread_mutex_restorelock(FAR struct pthread_mutex_s *mutex,
|
||||
unsigned int breakval)
|
||||
{
|
||||
int ret = EINVAL;
|
||||
|
||||
/* Verify input parameters */
|
||||
|
||||
DEBUGASSERT(mutex != NULL);
|
||||
if (mutex != NULL)
|
||||
{
|
||||
ret = -mutex_restorelock(&mutex->mutex, breakval);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Add the mutex to the list of mutexes held by this task */
|
||||
|
||||
pthread_mutex_add(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -74,21 +74,24 @@
|
||||
int pthread_mutex_consistent(FAR pthread_mutex_t *mutex)
|
||||
{
|
||||
int ret = EINVAL;
|
||||
int status;
|
||||
|
||||
sinfo("mutex=%p\n", mutex);
|
||||
DEBUGASSERT(mutex != NULL);
|
||||
|
||||
if (mutex != NULL)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
/* Make sure the mutex is stable while we make the following checks. */
|
||||
|
||||
sched_lock();
|
||||
|
||||
pid = mutex_get_holder(&mutex->mutex);
|
||||
|
||||
/* Is the mutex available? */
|
||||
|
||||
DEBUGASSERT(mutex->pid != 0); /* < 0: available, >0 owned, ==0 error */
|
||||
if (mutex->pid >= 0)
|
||||
DEBUGASSERT(pid != 0); /* < 0: available, >0 owned, ==0 error */
|
||||
if (pid >= 0)
|
||||
{
|
||||
/* No.. Verify that the thread associated with the PID still
|
||||
* exists. We may be destroying the mutex after cancelling a
|
||||
@ -101,28 +104,18 @@ int pthread_mutex_consistent(FAR pthread_mutex_t *mutex)
|
||||
* nxsched_get_tcb() does.
|
||||
*/
|
||||
|
||||
if (nxsched_get_tcb(mutex->pid) == NULL)
|
||||
if (nxsched_get_tcb(pid) == NULL)
|
||||
{
|
||||
/* The thread associated with the PID no longer exists */
|
||||
|
||||
mutex->pid = INVALID_PROCESS_ID;
|
||||
mutex->flags &= _PTHREAD_MFLAGS_ROBUST;
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
mutex->nlocks = 0;
|
||||
#endif
|
||||
/* Reset the semaphore. This has the same affect as if the
|
||||
* dead task had called pthread_mutex_unlock().
|
||||
*/
|
||||
|
||||
status = nxsem_reset(&mutex->sem, 1);
|
||||
if (status < 0)
|
||||
{
|
||||
ret = -status;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = OK;
|
||||
}
|
||||
mutex_reset(&mutex->mutex);
|
||||
|
||||
/* The thread associated with the PID no longer exists */
|
||||
|
||||
mutex->flags &= _PTHREAD_MFLAGS_ROBUST;
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
/* Otherwise the mutex is held by some active thread. Let's not
|
||||
@ -136,9 +129,6 @@ int pthread_mutex_consistent(FAR pthread_mutex_t *mutex)
|
||||
*/
|
||||
|
||||
mutex->flags &= _PTHREAD_MFLAGS_ROBUST;
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
mutex->nlocks = 0;
|
||||
#endif
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
|
@ -65,20 +65,23 @@ int pthread_mutex_destroy(FAR pthread_mutex_t *mutex)
|
||||
|
||||
if (mutex != NULL)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
/* Make sure the semaphore is stable while we make the following
|
||||
* checks.
|
||||
*/
|
||||
|
||||
sched_lock();
|
||||
|
||||
pid = mutex_get_holder(&mutex->mutex);
|
||||
|
||||
/* Is the mutex available? */
|
||||
|
||||
if (mutex->pid >= 0)
|
||||
if (pid >= 0)
|
||||
{
|
||||
/* < 0: available, >0 owned, ==0 error */
|
||||
|
||||
DEBUGASSERT(mutex->pid != 0);
|
||||
|
||||
DEBUGASSERT(pid != 0);
|
||||
/* No.. Verify that the PID still exists. We may be destroying
|
||||
* the mutex after cancelling a pthread and the mutex may have
|
||||
* been in a bad state owned by the dead pthread. NOTE: The
|
||||
@ -90,28 +93,22 @@ int pthread_mutex_destroy(FAR pthread_mutex_t *mutex)
|
||||
* nxsched_get_tcb() does.
|
||||
*/
|
||||
|
||||
if (nxsched_get_tcb(mutex->pid) == NULL)
|
||||
if (nxsched_get_tcb(pid) == NULL)
|
||||
{
|
||||
/* The thread associated with the PID no longer exists */
|
||||
|
||||
mutex->pid = INVALID_PROCESS_ID;
|
||||
|
||||
/* Reset the semaphore. If threads are were on this
|
||||
* semaphore, then this will awakened them and make
|
||||
* destruction of the semaphore impossible here.
|
||||
*/
|
||||
|
||||
status = nxsem_reset(&mutex->sem, 1);
|
||||
if (status < 0)
|
||||
{
|
||||
ret = -status;
|
||||
}
|
||||
mutex_reset(&mutex->mutex);
|
||||
|
||||
/* Check if the reset caused some other thread to lock the
|
||||
* mutex.
|
||||
*/
|
||||
|
||||
else if (mutex->pid != INVALID_PROCESS_ID)
|
||||
if (mutex_is_locked(&mutex->mutex))
|
||||
{
|
||||
/* Yes.. then we cannot destroy the mutex now. */
|
||||
|
||||
@ -122,7 +119,7 @@ int pthread_mutex_destroy(FAR pthread_mutex_t *mutex)
|
||||
|
||||
else
|
||||
{
|
||||
status = nxsem_destroy(&mutex->sem);
|
||||
status = mutex_destroy(&mutex->mutex);
|
||||
ret = (status < 0) ? -status : OK;
|
||||
}
|
||||
}
|
||||
@ -139,7 +136,7 @@ int pthread_mutex_destroy(FAR pthread_mutex_t *mutex)
|
||||
* Perhaps this logic should all nxsem_reset() first?
|
||||
*/
|
||||
|
||||
status = nxsem_destroy(&mutex->sem);
|
||||
status = mutex_destroy(&mutex->mutex);
|
||||
ret = ((status < 0) ? -status : OK);
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ void pthread_mutex_inconsistent(FAR struct tcb_s *tcb)
|
||||
/* Mark the mutex as INCONSISTENT and wake up any waiting thread */
|
||||
|
||||
mutex->flags |= _PTHREAD_MFLAGS_INCONSISTENT;
|
||||
pthread_sem_give(&mutex->sem);
|
||||
mutex_unlock(&mutex->mutex);
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
|
@ -58,13 +58,6 @@ int pthread_mutex_init(FAR pthread_mutex_t *mutex,
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
uint8_t type = PTHREAD_MUTEX_DEFAULT;
|
||||
#endif
|
||||
#ifdef CONFIG_PRIORITY_INHERITANCE
|
||||
# ifdef CONFIG_PTHREAD_MUTEX_DEFAULT_PRIO_INHERIT
|
||||
uint8_t proto = PTHREAD_PRIO_INHERIT;
|
||||
# else
|
||||
uint8_t proto = PTHREAD_PRIO_NONE;
|
||||
# endif
|
||||
#endif
|
||||
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_DEFAULT_UNSAFE
|
||||
uint8_t flags = 0;
|
||||
@ -87,9 +80,6 @@ int pthread_mutex_init(FAR pthread_mutex_t *mutex,
|
||||
|
||||
if (attr)
|
||||
{
|
||||
#ifdef CONFIG_PRIORITY_INHERITANCE
|
||||
proto = attr->proto;
|
||||
#endif
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
type = attr->type;
|
||||
#endif
|
||||
@ -99,41 +89,25 @@ int pthread_mutex_init(FAR pthread_mutex_t *mutex,
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Indicate that the semaphore is not held by any thread. */
|
||||
|
||||
mutex->pid = INVALID_PROCESS_ID;
|
||||
|
||||
/* Initialize the mutex like a semaphore with initial count = 1 */
|
||||
|
||||
status = nxsem_init(&mutex->sem, 0, 1);
|
||||
if (status < 0)
|
||||
{
|
||||
ret = -ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PRIORITY_INHERITANCE
|
||||
/* Initialize the semaphore protocol */
|
||||
|
||||
status = nxsem_set_protocol(&mutex->sem, proto);
|
||||
status = mutex_init(&mutex->mutex);
|
||||
if (status < 0)
|
||||
{
|
||||
ret = -status;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
|
||||
/* Initial internal fields of the mutex */
|
||||
|
||||
mutex->flink = NULL;
|
||||
|
||||
mutex->flags = flags;
|
||||
mutex->flink = NULL;
|
||||
mutex->flags = flags;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
/* Set up attributes unique to the mutex type */
|
||||
|
||||
mutex->type = type;
|
||||
mutex->nlocks = 0;
|
||||
mutex->type = type;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,6 @@
|
||||
int pthread_mutex_timedlock(FAR pthread_mutex_t *mutex,
|
||||
FAR const struct timespec *abs_timeout)
|
||||
{
|
||||
pid_t mypid = nxsched_gettid();
|
||||
int ret = EINVAL;
|
||||
irqstate_t flags;
|
||||
|
||||
@ -87,6 +86,10 @@ int pthread_mutex_timedlock(FAR pthread_mutex_t *mutex,
|
||||
|
||||
if (mutex != NULL)
|
||||
{
|
||||
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
|
||||
pid_t pid = mutex_get_holder(&mutex->mutex);
|
||||
#endif
|
||||
|
||||
/* Make sure the semaphore is stable while we make the following
|
||||
* checks. This all needs to be one atomic action.
|
||||
*/
|
||||
@ -98,7 +101,8 @@ int pthread_mutex_timedlock(FAR pthread_mutex_t *mutex,
|
||||
* an error if the caller does not hold the mutex.
|
||||
*/
|
||||
|
||||
if (mutex->type != PTHREAD_MUTEX_NORMAL && mutex->pid == mypid)
|
||||
if (mutex->type != PTHREAD_MUTEX_NORMAL &&
|
||||
mutex_is_hold(&mutex->mutex))
|
||||
{
|
||||
/* Yes... Is this a recursive mutex? */
|
||||
|
||||
@ -108,15 +112,7 @@ int pthread_mutex_timedlock(FAR pthread_mutex_t *mutex,
|
||||
* success.
|
||||
*/
|
||||
|
||||
if (mutex->nlocks < INT16_MAX)
|
||||
{
|
||||
mutex->nlocks++;
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = EOVERFLOW;
|
||||
}
|
||||
ret = pthread_mutex_take(mutex, abs_timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -148,26 +144,26 @@ int pthread_mutex_timedlock(FAR pthread_mutex_t *mutex,
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
/* Include check if this is a NORMAL mutex and that it is robust */
|
||||
|
||||
if (mutex->pid > 0 &&
|
||||
if (pid > 0 &&
|
||||
((mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0 ||
|
||||
mutex->type != PTHREAD_MUTEX_NORMAL) &&
|
||||
nxsched_get_tcb(mutex->pid) == NULL)
|
||||
nxsched_get_tcb(pid) == NULL)
|
||||
|
||||
#else /* CONFIG_PTHREAD_MUTEX_TYPES */
|
||||
/* This can only be a NORMAL mutex. Include check if it is robust */
|
||||
|
||||
if (mutex->pid > 0 &&
|
||||
if (pid > 0 &&
|
||||
(mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0 &&
|
||||
nxsched_get_tcb(mutex->pid) == NULL)
|
||||
nxsched_get_tcb(pid) == NULL)
|
||||
|
||||
#endif /* CONFIG_PTHREAD_MUTEX_TYPES */
|
||||
#else /* CONFIG_PTHREAD_MUTEX_ROBUST */
|
||||
/* This mutex is always robust, whatever type it is. */
|
||||
|
||||
if (mutex->pid > 0 && nxsched_get_tcb(mutex->pid) == NULL)
|
||||
if (pid > 0 && nxsched_get_tcb(pid) == NULL)
|
||||
#endif
|
||||
{
|
||||
DEBUGASSERT(mutex->pid != 0); /* < 0: available, >0 owned, ==0 error */
|
||||
DEBUGASSERT(pid != 0); /* < 0: available, >0 owned, ==0 error */
|
||||
DEBUGASSERT((mutex->flags & _PTHREAD_MFLAGS_INCONSISTENT) != 0);
|
||||
|
||||
/* A thread holds the mutex, but there is no such thread. POSIX
|
||||
@ -189,18 +185,6 @@ int pthread_mutex_timedlock(FAR pthread_mutex_t *mutex,
|
||||
*/
|
||||
|
||||
ret = pthread_mutex_take(mutex, abs_timeout);
|
||||
|
||||
/* If we successfully obtained the semaphore, then indicate
|
||||
* that we own it.
|
||||
*/
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
mutex->pid = mypid;
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
mutex->nlocks = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
@ -76,7 +76,9 @@ int pthread_mutex_trylock(FAR pthread_mutex_t *mutex)
|
||||
|
||||
if (mutex != NULL)
|
||||
{
|
||||
pid_t mypid = nxsched_gettid();
|
||||
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
|
||||
pid_t pid = mutex_get_holder(&mutex->mutex);
|
||||
#endif
|
||||
|
||||
/* Make sure the semaphore is stable while we make the following
|
||||
* checks. This all needs to be one atomic action.
|
||||
@ -89,19 +91,6 @@ int pthread_mutex_trylock(FAR pthread_mutex_t *mutex)
|
||||
status = pthread_mutex_trytake(mutex);
|
||||
if (status == OK)
|
||||
{
|
||||
/* If we successfully obtained the semaphore, then indicate
|
||||
* that we own it.
|
||||
*/
|
||||
|
||||
mutex->pid = mypid;
|
||||
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
if (mutex->type == PTHREAD_MUTEX_RECURSIVE)
|
||||
{
|
||||
mutex->nlocks = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
@ -111,28 +100,6 @@ int pthread_mutex_trylock(FAR pthread_mutex_t *mutex)
|
||||
|
||||
else if (status == EAGAIN)
|
||||
{
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
/* Check if recursive mutex was locked by the calling thread. */
|
||||
|
||||
if (mutex->type == PTHREAD_MUTEX_RECURSIVE && mutex->pid == mypid)
|
||||
{
|
||||
/* Increment the number of locks held and return
|
||||
* successfully.
|
||||
*/
|
||||
|
||||
if (mutex->nlocks < INT16_MAX)
|
||||
{
|
||||
mutex->nlocks++;
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = EOVERFLOW;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
|
||||
/* The calling thread does not hold the semaphore. The correct
|
||||
* behavior for the 'robust' mutex is to verify that the holder of
|
||||
@ -144,28 +111,28 @@ int pthread_mutex_trylock(FAR pthread_mutex_t *mutex)
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
/* Check if this NORMAL mutex is robust */
|
||||
|
||||
if (mutex->pid > 0 &&
|
||||
if (pid > 0 &&
|
||||
((mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0 ||
|
||||
mutex->type != PTHREAD_MUTEX_NORMAL) &&
|
||||
nxsched_get_tcb(mutex->pid) == NULL)
|
||||
nxsched_get_tcb(pid) == NULL)
|
||||
|
||||
#else /* CONFIG_PTHREAD_MUTEX_TYPES */
|
||||
/* Check if this NORMAL mutex is robust */
|
||||
|
||||
if (mutex->pid > 0 &&
|
||||
if (pid > 0 &&
|
||||
(mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0 &&
|
||||
nxsched_get_tcb(mutex->pid) == NULL)
|
||||
nxsched_get_tcb(pid) == NULL)
|
||||
|
||||
#endif /* CONFIG_PTHREAD_MUTEX_TYPES */
|
||||
#else /* CONFIG_PTHREAD_MUTEX_ROBUST */
|
||||
/* This mutex is always robust, whatever type it is. */
|
||||
|
||||
if (mutex->pid > 0 && nxsched_get_tcb(mutex->pid) == NULL)
|
||||
if (pid > 0 && nxsched_get_tcb(pid) == NULL)
|
||||
#endif
|
||||
{
|
||||
/* < 0: available, >0 owned, ==0 error */
|
||||
|
||||
DEBUGASSERT(mutex->pid != 0);
|
||||
DEBUGASSERT(pid != 0);
|
||||
DEBUGASSERT((mutex->flags & _PTHREAD_MFLAGS_INCONSISTENT)
|
||||
!= 0);
|
||||
|
||||
|
@ -33,39 +33,6 @@
|
||||
|
||||
#include "pthread/pthread.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pthread_mutex_islocked
|
||||
*
|
||||
* Description:
|
||||
* Return true is the mutex is locked.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns true if the mutex is locked
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline bool pthread_mutex_islocked(FAR struct pthread_mutex_s *mutex)
|
||||
{
|
||||
int semcount = mutex->sem.semcount;
|
||||
|
||||
/* The underlying semaphore should have a count less than 2:
|
||||
*
|
||||
* 1 == mutex is unlocked.
|
||||
* 0 == mutex is locked with no waiters
|
||||
* -n == mutex is locked with 'n' waiters.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(semcount < 2);
|
||||
return semcount < 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -123,7 +90,7 @@ int pthread_mutex_unlock(FAR pthread_mutex_t *mutex)
|
||||
* remaining case.
|
||||
*/
|
||||
|
||||
if (pthread_mutex_islocked(mutex))
|
||||
if (mutex_is_locked(&mutex->mutex))
|
||||
{
|
||||
#if !defined(CONFIG_PTHREAD_MUTEX_UNSAFE) || defined(CONFIG_PTHREAD_MUTEX_TYPES)
|
||||
/* Does the calling thread own the semaphore? If no, should we return
|
||||
@ -143,7 +110,7 @@ int pthread_mutex_unlock(FAR pthread_mutex_t *mutex)
|
||||
* thread owns the semaphore.
|
||||
*/
|
||||
|
||||
if (mutex->pid != nxsched_gettid())
|
||||
if (!mutex_is_hold(&mutex->mutex))
|
||||
|
||||
#elif defined(CONFIG_PTHREAD_MUTEX_UNSAFE) && defined(CONFIG_PTHREAD_MUTEX_TYPES)
|
||||
/* If mutex types are not supported, then all mutexes are NORMAL (or
|
||||
@ -152,7 +119,7 @@ int pthread_mutex_unlock(FAR pthread_mutex_t *mutex)
|
||||
*/
|
||||
|
||||
if (mutex->type != PTHREAD_MUTEX_NORMAL &&
|
||||
mutex->pid != nxsched_gettid())
|
||||
!mutex_is_hold(&mutex->mutex))
|
||||
|
||||
#else /* CONFIG_PTHREAD_MUTEX_BOTH */
|
||||
/* Skip the error check if this is a non-robust NORMAL mutex */
|
||||
@ -166,7 +133,7 @@ int pthread_mutex_unlock(FAR pthread_mutex_t *mutex)
|
||||
* the EPERM error?
|
||||
*/
|
||||
|
||||
if (errcheck && mutex->pid != nxsched_gettid())
|
||||
if (errcheck && !mutex_is_hold(&mutex->mutex))
|
||||
#endif
|
||||
{
|
||||
/* No... return an EPERM error.
|
||||
@ -180,29 +147,13 @@ int pthread_mutex_unlock(FAR pthread_mutex_t *mutex)
|
||||
* the behavior is undefined.
|
||||
*/
|
||||
|
||||
serr("ERROR: Holder=%d returning EPERM\n", mutex->pid);
|
||||
serr("ERROR: Holder=%d returning EPERM\n",
|
||||
mutex_get_holder(&mutex->mutex));
|
||||
ret = EPERM;
|
||||
}
|
||||
else
|
||||
#endif /* !CONFIG_PTHREAD_MUTEX_UNSAFE || CONFIG_PTHREAD_MUTEX_TYPES */
|
||||
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
/* Yes, the caller owns the semaphore.. Is this a recursive mutex? */
|
||||
|
||||
if (mutex->type == PTHREAD_MUTEX_RECURSIVE && mutex->nlocks > 1)
|
||||
{
|
||||
/* This is a recursive mutex and we there are multiple locks held.
|
||||
* Retain the mutex lock, just decrement the count of locks held,
|
||||
* and return success.
|
||||
*/
|
||||
|
||||
mutex->nlocks--;
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
|
||||
#endif /* CONFIG_PTHREAD_MUTEX_TYPES */
|
||||
|
||||
/* This is either a non-recursive mutex or is the outermost unlock of
|
||||
* a recursive mutex.
|
||||
*
|
||||
@ -214,12 +165,6 @@ int pthread_mutex_unlock(FAR pthread_mutex_t *mutex)
|
||||
*/
|
||||
|
||||
{
|
||||
/* Nullify the pid and lock count then post the semaphore */
|
||||
|
||||
mutex->pid = INVALID_PROCESS_ID;
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
|
||||
mutex->nlocks = 0;
|
||||
#endif
|
||||
ret = pthread_mutex_give(mutex);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user