diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 687d19dcf9b..f618ac94cea 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -697,6 +697,10 @@ struct pthread_tcb_s pthread_addr_t arg; /* Startup argument */ FAR void *joininfo; /* Detach-able info to support join */ + /* Robust mutex support *******************************************************/ + + FAR struct pthread_mutex_s *mhead; /* List of mutexes held by thread */ + /* Clean-up stack *************************************************************/ #ifdef CONFIG_PTHREAD_CLEANUP diff --git a/include/pthread.h b/include/pthread.h index 6fed93a8371..8f3c7bf37f3 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -143,6 +143,13 @@ #define PTHREAD_PRIO_INHERIT SEM_PRIO_INHERIT #define PTHREAD_PRIO_PROTECT SEM_PRIO_PROTECT +/* 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 */ + /* Definitions to map some non-standard, BSD thread management interfaces to * the non-standard Linux-like prctl() interface. Since these are simple * mappings to prctl, they will return 0 on success and -1 on failure with the @@ -221,7 +228,7 @@ struct pthread_mutexattr_s { uint8_t pshared; /* PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED */ #ifdef CONFIG_PRIORITY_INHERITANCE - uint8_t proto; /* See PTHREAD_PRIO_* definitions */ + uint8_t proto; /* See _PTHREAD_PRIO_* definitions */ #endif #ifdef CONFIG_MUTEX_TYPES uint8_t type; /* Type of the mutex. See PTHREAD_MUTEX_* definitions */ @@ -233,11 +240,18 @@ typedef struct pthread_mutexattr_s pthread_mutexattr_t; struct pthread_mutex_s { - int pid; /* ID of the holder of the mutex */ + /* Supports a singly linked list */ + + FAR struct pthread_mutex_s *flink; + + /* Payload */ + sem_t sem; /* Semaphore underlying the implementation of the mutex */ + pid_t pid; /* ID of the holder of the mutex */ + uint8_t flags; /* See PTHREAD_MFLAGS_* */ #ifdef CONFIG_MUTEX_TYPES uint8_t type; /* Type of the mutex. See PTHREAD_MUTEX_* definitions */ - int nlocks; /* The number of recursive locks held */ + int16_t nlocks; /* The number of recursive locks held */ #endif }; diff --git a/sched/pthread/Make.defs b/sched/pthread/Make.defs index 5a602d3e1fa..9f2c8c64798 100644 --- a/sched/pthread/Make.defs +++ b/sched/pthread/Make.defs @@ -37,7 +37,7 @@ ifneq ($(CONFIG_DISABLE_PTHREAD),y) CSRCS += pthread_create.c pthread_exit.c pthread_join.c pthread_detach.c CSRCS += pthread_yield.c pthread_getschedparam.c pthread_setschedparam.c -CSRCS += pthread_mutexinit.c pthread_mutexdestroy.c +CSRCS += pthread_mutexinit.c pthread_mutexdestroy.c pthread_mutex.c CSRCS += pthread_mutexlock.c pthread_mutextrylock.c pthread_mutexunlock.c CSRCS += pthread_mutexconsistent.c CSRCS += pthread_condinit.c pthread_conddestroy.c diff --git a/sched/pthread/pthread.h b/sched/pthread/pthread.h index 858e80ed079..79492d930d5 100644 --- a/sched/pthread/pthread.h +++ b/sched/pthread/pthread.h @@ -107,8 +107,10 @@ void pthread_destroyjoin(FAR struct task_group_s *group, FAR struct join_s *pthread_findjoininfo(FAR struct task_group_s *group, pid_t pid); void pthread_release(FAR struct task_group_s *group); -int pthread_givesemaphore(sem_t *sem); int pthread_takesemaphore(sem_t *sem, bool intr); +int pthread_givesemaphore(sem_t *sem); +int pthread_takemutex(FAR struct pthread_mutex_s *mutex, bool intr); +int pthread_givemutex(FAR struct pthread_mutex_s *mutex); #ifdef CONFIG_MUTEX_TYPES int pthread_mutexattr_verifytype(int type); diff --git a/sched/pthread/pthread_condtimedwait.c b/sched/pthread/pthread_condtimedwait.c index 960f46483c3..b03fc3a73fa 100644 --- a/sched/pthread/pthread_condtimedwait.c +++ b/sched/pthread/pthread_condtimedwait.c @@ -260,7 +260,7 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex, /* Give up the mutex */ mutex->pid = -1; - ret = pthread_givesemaphore((FAR sem_t *)&mutex->sem); + ret = pthread_givemutex(mutex); if (ret != 0) { /* Restore interrupts (pre-emption will be enabled when @@ -316,7 +316,7 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex, /* Reacquire the mutex (retaining the ret). */ sinfo("Re-locking...\n"); - status = pthread_takesemaphore((FAR sem_t *)&mutex->sem, false); + status = pthread_takemutex(mutex, false); if (status == OK) { mutex->pid = mypid; diff --git a/sched/pthread/pthread_condwait.c b/sched/pthread/pthread_condwait.c index a434f3032cd..88f39485aaf 100644 --- a/sched/pthread/pthread_condwait.c +++ b/sched/pthread/pthread_condwait.c @@ -101,7 +101,7 @@ int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex) sched_lock(); mutex->pid = -1; - ret = pthread_givesemaphore((FAR sem_t *)&mutex->sem); + ret = pthread_givemutex(mutex); /* Take the semaphore */ @@ -122,7 +122,7 @@ int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex) */ sinfo("Reacquire mutex...\n"); - status = pthread_takesemaphore((FAR sem_t *)&mutex->sem, false); + status = pthread_takemutex(mutex, false); if (ret == OK) { /* Report the first failure that occurs */ diff --git a/sched/pthread/pthread_mutexlock.c b/sched/pthread/pthread_mutexlock.c index 657bede3708..251f071b474 100644 --- a/sched/pthread/pthread_mutexlock.c +++ b/sched/pthread/pthread_mutexlock.c @@ -133,8 +133,15 @@ int pthread_mutex_lock(FAR pthread_mutex_t *mutex) * success. */ - mutex->nlocks++; - ret = OK; + if (mutex->nlocks < INT16_MAX) + { + mutex->nlocks++; + ret = OK; + } + else + { + ret = EOVERFLOW; + } } else #endif @@ -176,7 +183,7 @@ int pthread_mutex_lock(FAR pthread_mutex_t *mutex) { /* Take the underlying semaphore, waiting if necessary */ - ret = pthread_takesemaphore((FAR sem_t *)&mutex->sem, true); + ret = pthread_takemutex(mutex, true); /* If we successfully obtained the semaphore, then indicate * that we own it. @@ -189,14 +196,6 @@ int pthread_mutex_lock(FAR pthread_mutex_t *mutex) mutex->nlocks = 1; #endif } - - /* Check if we were awakened by a signal. This might happen if the - * tasking holding the mutex just exitted. - */ - - else if (ret == EINTR) - { - } } sched_unlock(); diff --git a/sched/pthread/pthread_mutextrylock.c b/sched/pthread/pthread_mutextrylock.c index a71e845f77d..630de9e5fd3 100644 --- a/sched/pthread/pthread_mutextrylock.c +++ b/sched/pthread/pthread_mutextrylock.c @@ -136,8 +136,15 @@ int pthread_mutex_trylock(FAR pthread_mutex_t *mutex) { /* Increment the number of locks held and return successfully. */ - mutex->nlocks++; - ret = OK; + if (mutex->nlocks < INT16_MAX) + { + mutex->nlocks++; + ret = OK; + } + else + { + ret = EOVERFLOW; + } } else #endif diff --git a/sched/pthread/pthread_mutexunlock.c b/sched/pthread/pthread_mutexunlock.c index 9493d96e6cd..05f461605fb 100644 --- a/sched/pthread/pthread_mutexunlock.c +++ b/sched/pthread/pthread_mutexunlock.c @@ -139,7 +139,7 @@ int pthread_mutex_unlock(FAR pthread_mutex_t *mutex) #ifdef CONFIG_MUTEX_TYPES mutex->nlocks = 0; #endif - ret = pthread_givesemaphore((FAR sem_t *)&mutex->sem); + ret = pthread_givemutex(mutex); } sched_unlock();