pthread mutexes: Add option to support both unsafe and robust mutexes via pthread_mutexattr_get/setrobust().

This commit is contained in:
Gregory Nutt 2017-03-26 18:37:24 -06:00
parent 8b3c554e45
commit 666208cf23
5 changed files with 87 additions and 7 deletions

View File

@ -143,12 +143,42 @@
#define PTHREAD_PRIO_INHERIT SEM_PRIO_INHERIT
#define PTHREAD_PRIO_PROTECT SEM_PRIO_PROTECT
/* Values for robust argument of pthread_mutexattr_get/setrobust
*
* PTHREAD_MUTEX_STALLED - No special actions are taken if the owner of the
* mutex is terminated while holding the mutex lock. This can lead to
* deadlocks if no other thread can unlock the mutex. This is the standard
* default value (NuttX permits you to override that default behavior
* with a configuration option).
*
* PTHREAD_MUTEX_ROBUST - If the process containing the owning thread of a
* robust mutex terminates while holding the mutex lock, the next thread
* that acquires the mutex will be notified about the termination by the
* return value EOWNERDEAD from the locking function. If the owning thread
* of a robust mutex terminates while holding the mutex lock, the next
* thread that attempts to acquire the mutex may be notified about the
* termination by the return value EOWNERDEAD. The notified thread can
* then attempt to make the state protected by the mutex consistent again,
* and if successful can mark the mutex state as consistent by calling
* pthread_mutex_consistent(). After a subsequent successful call to
* pthread_mutex_unlock(), the mutex lock will be released and can be used
* normally by other threads. If the mutex is unlocked without a call to
* pthread_mutex_consistent(), it will be in a permanently unusable state
* and all attempts to lock the mutex will fail with the error
* ENOTRECOVERABLE. The only permissible operation on such a mutex is
* pthread_mutex_destroy().
*/
#define PTHREAD_MUTEX_STALLED 0
#define PTHREAD_MUTEX_ROBUST 1
/* Values for struct pthread_mutex_s flags. These are non-standard and
* intended only for internal use within the OS.
*/
#define _PTHREAD_MFLAGS_INCONSISTENT (1 << 0) /* Mutex is in an inconsistent state */
#define _PTHREAD_MFLAGS_NOTRECOVRABLE (1 << 1) /* Inconsistent mutex has been unlocked */
#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 */
/* Definitions to map some non-standard, BSD thread management interfaces to
* the non-standard Linux-like prctl() interface. Since these are simple
@ -226,12 +256,15 @@ typedef struct pthread_cond_s pthread_cond_t;
struct pthread_mutexattr_s
{
uint8_t pshared; /* PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED */
uint8_t pshared : 1; /* PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED */
#ifdef CONFIG_PRIORITY_INHERITANCE
uint8_t proto; /* See PTHREAD_PRIO_* definitions */
uint8_t proto : 2; /* See PTHREAD_PRIO_* definitions */
#endif
#ifdef CONFIG_MUTEX_TYPES
uint8_t type; /* Type of the mutex. See PTHREAD_MUTEX_* definitions */
uint8_t type : 2; /* Type of the mutex. See PTHREAD_MUTEX_* definitions */
#endif
#ifdef CONFIG_PTHREAD_MUTEX_BOTH
uint8_t robust : 1; /* PTHREAD_MUTEX_STALLED or PTHREAD_MUTEX_ROBUST */
#endif
};
@ -432,6 +465,10 @@ int pthread_mutexattr_getprotocol(FAR const pthread_mutexattr_t *attr,
FAR int *protocol);
int pthread_mutexattr_setprotocol(FAR pthread_mutexattr_t *attr,
int protocol);
int pthread_mutexattr_getrobust(FAR const pthread_mutexattr_t *attr,
FAR int *robust);
int pthread_mutexattr_setrobust(FAR pthread_mutexattr_t *attr,
int robust);
/* The following routines create, delete, lock and unlock mutexes. */

View File

@ -49,6 +49,7 @@ CSRCS += pthread_mutexattr_init.c pthread_mutexattr_destroy.c
CSRCS += pthread_mutexattr_getpshared.c pthread_mutexattr_setpshared.c
CSRCS += pthread_mutexattr_setprotocol.c pthread_mutexattr_getprotocol.c
CSRCS += pthread_mutexattr_settype.c pthread_mutexattr_gettype.c
CSRCS += pthread_mutexattr_setrobust.c pthread_mutexattr_getrobust.c
CSRCS += pthread_setcancelstate.c pthread_setcanceltype.c
CSRCS += pthread_testcancel.c

View File

@ -76,11 +76,21 @@ int pthread_mutexattr_init(FAR pthread_mutexattr_t *attr)
else
{
attr->pshared = 0;
#ifdef CONFIG_PRIORITY_INHERITANCE
attr->proto = SEM_PRIO_INHERIT;
#endif
#ifdef CONFIG_MUTEX_TYPES
attr->type = PTHREAD_MUTEX_DEFAULT;
#endif
#ifdef CONFIG_PTHREAD_MUTEX_BOTH
#ifdef CONFIG_PTHREAD_MUTEX_DEFAULT_UNSAFE
attr->robust = PTHREAD_MUTEX_STALLED;
#else
attr->robust = PTHREAD_MUTEX_ROBUST;
#endif
#endif
}

View File

@ -549,7 +549,29 @@ choice
software you may be porting or, perhaps, if you are trying to minimize
footprint.
endchoice # thread mutex robustness
config PTHREAD_MUTEX_BOTH
bool "Both robust and unsafe mutexes"
---help---
Support both forms of NORMAL mutexes.
endchoice # pthread mutex robustness
choice
prompt "Default NORMAL mutex robustness"
default PTHREAD_MUTEX_DEFAULT_ROBUST
depends on PTHREAD_MUTEX_BOTH
config PTHREAD_MUTEX_DEFAULT_ROBUST
bool "Robust default"
---help---
The default is robust NORMAL mutexes (non-standard)
config PTHREAD_MUTEX_DEFAULT_UNSAFE
bool "Unsafe default"
---help---
The default is traditional unsafe NORMAL mutexes (standard)
endchoice # Default NORMAL mutex robustness
config NPTHREAD_KEYS
int "Maximum number of pthread keys"

View File

@ -77,6 +77,13 @@ int pthread_mutex_init(FAR pthread_mutex_t *mutex,
#endif
#ifdef CONFIG_PRIORITY_INHERITANCE
uint8_t proto = PTHREAD_PRIO_INHERIT;
#endif
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
#ifdef CONFIG_PTHREAD_MUTEX_DEFAULT_UNSAFE
uint8_t robust = PTHREAD_MUTEX_STALLED;
#else
uint8_t robust = PTHREAD_MUTEX_ROBUST;
#endif
#endif
int ret = OK;
int status;
@ -99,6 +106,9 @@ int pthread_mutex_init(FAR pthread_mutex_t *mutex,
#endif
#ifdef CONFIG_MUTEX_TYPES
type = attr->type;
#endif
#ifdef CONFIG_PTHREAD_MUTEX_BOTH
robust = attr->robust;
#endif
}
@ -128,7 +138,7 @@ int pthread_mutex_init(FAR pthread_mutex_t *mutex,
/* Initial internal fields of the mutex */
mutex->flink = NULL;
mutex->flags = 0;
mutex->flags = (robust == PTHREAD_MUTEX_ROBUST ? _PTHREAD_MFLAGS_ROBUST : 0);
#endif
#ifdef CONFIG_MUTEX_TYPES