diff --git a/include/pthread.h b/include/pthread.h index 30c96bab9c..53eaa0ddaa 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -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 diff --git a/sched/pthread/pthread_mutexconsistent.c b/sched/pthread/pthread_mutexconsistent.c index 3febab2d0b..86930e276c 100644 --- a/sched/pthread/pthread_mutexconsistent.c +++ b/sched/pthread/pthread_mutexconsistent.c @@ -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(). */ diff --git a/sched/pthread/pthread_mutexlock.c b/sched/pthread/pthread_mutexlock.c index ffc8eadad2..3013248842 100644 --- a/sched/pthread/pthread_mutexlock.c +++ b/sched/pthread/pthread_mutexlock.c @@ -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); diff --git a/sched/pthread/pthread_mutextrylock.c b/sched/pthread/pthread_mutextrylock.c index 6e21c74b44..50c3175de5 100644 --- a/sched/pthread/pthread_mutextrylock.c +++ b/sched/pthread/pthread_mutextrylock.c @@ -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); diff --git a/sched/pthread/pthread_mutexunlock.c b/sched/pthread/pthread_mutexunlock.c index 9efd9ed847..b27c9ecda0 100644 --- a/sched/pthread/pthread_mutexunlock.c +++ b/sched/pthread/pthread_mutexunlock.c @@ -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; }