pthread mutexes: Finish logic to support configuration mutex robustness.
This commit is contained in:
parent
d1196ddb60
commit
f2f798cb29
@ -178,7 +178,7 @@
|
||||
|
||||
#define _PTHREAD_MFLAGS_ROBUST (1 << 0) /* Robust (NORMAL) mutex */
|
||||
#define _PTHREAD_MFLAGS_INCONSISTENT (1 << 1) /* Mutex is in an inconsistent state */
|
||||
#define _PTHREAD_MFLAGS_NOTRECOVRABLE (1 << 2) /* Inconsistent mutex has been unlocked */
|
||||
#define _PTHREAD_MFLAGS_NRECOVERABLE (1 << 2) /* Inconsistent mutex has been unlocked */
|
||||
|
||||
/* Definitions to map some non-standard, BSD thread management interfaces to
|
||||
* the non-standard Linux-like prctl() interface. Since these are simple
|
||||
|
@ -118,9 +118,11 @@ int pthread_mutex_consistent(FAR pthread_mutex_t *mutex)
|
||||
{
|
||||
/* The thread associated with the PID no longer exists */
|
||||
|
||||
mutex->pid = -1;
|
||||
mutex->flags = 0;
|
||||
|
||||
mutex->pid = -1;
|
||||
mutex->flags &= _PTHREAD_MFLAGS_ROBUST;
|
||||
#ifdef CONFIG_MUTEX_TYPES
|
||||
mutex->nlocks = 0;
|
||||
#endif
|
||||
/* Reset the semaphore. This has the same affect as if the
|
||||
* dead task had called pthread_mutex_unlock().
|
||||
*/
|
||||
|
@ -171,7 +171,28 @@ int pthread_mutex_lock(FAR pthread_mutex_t *mutex)
|
||||
* where the holder of the mutex has exitted without unlocking it.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_BOTH
|
||||
#ifdef CONFIG_MUTEX_TYPES
|
||||
/* Include check if this is a NORMAL mutex and that it is robust */
|
||||
|
||||
if (mutex->pid > 0 &&
|
||||
((mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0 ||
|
||||
mutex->type != PTHREAD_MUTEX_NORMAL) &&
|
||||
sched_gettcb(mutex->pid) == NULL)
|
||||
|
||||
#else /* CONFIG_MUTEX_TYPES */
|
||||
/* This can only be a NORMAL mutex. Include check if it is robust */
|
||||
|
||||
if (mutex->pid > 0 &&
|
||||
(mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0 &&
|
||||
sched_gettcb(mutex->pid) == NULL)
|
||||
|
||||
#endif /* CONFIG_MUTEX_TYPES */
|
||||
#else /* CONFIG_PTHREAD_MUTEX_ROBUST */
|
||||
/* This mutex is always robust, whatever type it is. */
|
||||
|
||||
if (mutex->pid > 0 && sched_gettcb(mutex->pid) == NULL)
|
||||
#endif
|
||||
{
|
||||
DEBUGASSERT(mutex->pid != 0); /* < 0: available, >0 owned, ==0 error */
|
||||
DEBUGASSERT((mutex->flags & _PTHREAD_MFLAGS_INCONSISTENT) != 0);
|
||||
|
@ -156,7 +156,28 @@ int pthread_mutex_trylock(FAR pthread_mutex_t *mutex)
|
||||
* where the holder of the mutex has exitted without unlocking it.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PTHREAD_MUTEX_BOTH
|
||||
#ifdef CONFIG_MUTEX_TYPES
|
||||
/* Check if this NORMAL mutex is robust */
|
||||
|
||||
if (mutex->pid > 0 &&
|
||||
((mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0 ||
|
||||
mutex->type != PTHREAD_MUTEX_NORMAL) &&
|
||||
sched_gettcb(mutex->pid) == NULL)
|
||||
|
||||
#else /* CONFIG_MUTEX_TYPES */
|
||||
/* Check if this NORMAL mutex is robust */
|
||||
|
||||
if (mutex->pid > 0 &&
|
||||
(mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0 &&
|
||||
sched_gettcb(mutex->pid) == NULL)
|
||||
|
||||
#endif /* CONFIG_MUTEX_TYPES */
|
||||
#else /* CONFIG_PTHREAD_MUTEX_ROBUST */
|
||||
/* This mutex is always robust, whatever type it is. */
|
||||
|
||||
if (mutex->pid > 0 && sched_gettcb(mutex->pid) == NULL)
|
||||
#endif
|
||||
{
|
||||
DEBUGASSERT(mutex->pid != 0); /* < 0: available, >0 owned, ==0 error */
|
||||
DEBUGASSERT((mutex->flags & _PTHREAD_MFLAGS_INCONSISTENT) != 0);
|
||||
|
@ -85,27 +85,54 @@ int pthread_mutex_unlock(FAR pthread_mutex_t *mutex)
|
||||
sinfo("mutex=0x%p\n", mutex);
|
||||
DEBUGASSERT(mutex != NULL);
|
||||
|
||||
/* Make sure the semaphore is stable while we make the following checks.
|
||||
* This all needs to be one atomic action.
|
||||
*/
|
||||
|
||||
sched_lock();
|
||||
if (mutex != NULL)
|
||||
{
|
||||
/* Make sure the semaphore is stable while we make the following
|
||||
* checks. This all needs to be one atomic action.
|
||||
#if !defined(CONFIG_PTHREAD_MUTEX_UNSAFE) || defined(CONFIG_MUTEX_TYPES)
|
||||
/* Does the calling thread own the semaphore? If no, should we return
|
||||
* an error?
|
||||
*
|
||||
* Error checking is always performed for ERRORCHECK and RECURSIVE
|
||||
* mutex types. Error checking is only performed for NORMAL (or
|
||||
* DEFAULT) mutex type if the NORMAL mutex is robust. That is either:
|
||||
*
|
||||
* 1. CONFIG_PTHREAD_MUTEX_ROBUST is defined, or
|
||||
* 2. CONFIG_PTHREAD_MUTEX_BOTH is defined and the robust flag is set
|
||||
*/
|
||||
|
||||
sched_lock();
|
||||
|
||||
#if !defined(CONFIG_PTHREAD_MUTEX_UNSAFE) || !defined(CONFIG_MUTEX_TYPES)
|
||||
/* Does the calling thread own the semaphore? Should we report the
|
||||
* EPERM error? This applies to robust NORMAL (and DEFAULT) mutexes
|
||||
* as well as ERRORCHECK and RECURSIVE mutexes.
|
||||
#if defined(CONFIG_PTHREAD_MUTEX_ROBUST)
|
||||
/* Not that error checking is always performed if the configuration has
|
||||
* CONFIG_PTHREAD_MUTEX_ROBUST defined. Just check if the calling
|
||||
* thread owns the semaphore.
|
||||
*/
|
||||
|
||||
if (mutex->pid != (int)getpid())
|
||||
#else
|
||||
/* Does the calling thread own the semaphore? Should we report the
|
||||
* EPERM error? This applies to ERRORCHECK and RECURSIVE mutexes.
|
||||
|
||||
#elif defined(CONFIG_PTHREAD_MUTEX_UNSAFE) && defined(CONFIG_MUTEX_TYPES)
|
||||
/* If mutex types are not supported, then all mutexes are NORMAL (or
|
||||
* DEFAULT). Error checking should never be performed for the
|
||||
* non-robust NORMAL mutex type.
|
||||
*/
|
||||
|
||||
if (mutex->type != PTHREAD_MUTEX_NORMAL && mutex->pid != (int)getpid())
|
||||
|
||||
#else /* CONFIG_PTHREAD_MUTEX_BOTH */
|
||||
/* Skip the error check if this is a non-robust NORMAL mutex */
|
||||
|
||||
bool errcheck = ((mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0);
|
||||
#ifdef CONFIG_MUTEX_TYPES
|
||||
errcheck |= (mutex->type != PTHREAD_MUTEX_NORMAL);
|
||||
#endif
|
||||
|
||||
/* Does the calling thread own the semaphore? If not should we report
|
||||
* the EPERM error?
|
||||
*/
|
||||
|
||||
if (errcheck && mutex->pid != (int)getpid())
|
||||
#endif
|
||||
{
|
||||
/* No... return an EPERM error.
|
||||
@ -123,6 +150,7 @@ int pthread_mutex_unlock(FAR pthread_mutex_t *mutex)
|
||||
ret = EPERM;
|
||||
}
|
||||
else
|
||||
#endif /* !CONFIG_PTHREAD_MUTEX_UNSAFE || CONFIG_MUTEX_TYPES */
|
||||
|
||||
#ifdef CONFIG_MUTEX_TYPES
|
||||
/* Yes, the caller owns the semaphore.. Is this a recursive mutex? */
|
||||
@ -159,10 +187,9 @@ int pthread_mutex_unlock(FAR pthread_mutex_t *mutex)
|
||||
#endif
|
||||
ret = pthread_mutex_give(mutex);
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
sinfo("Returning %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user