mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 10:58:49 +08:00
pthreads: Partial implementation of final part of robust mutexes: Keep list of all mutexes held by a thread in a list in the TCB.
This commit is contained in:
parent
2c37d369ab
commit
6e623ce06f
9 changed files with 49 additions and 23 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue