diff --git a/libc/pthread/pthread_rwlock_rdlock.c b/libc/pthread/pthread_rwlock_rdlock.c index 9fd461a758e..29dcf7daae1 100644 --- a/libc/pthread/pthread_rwlock_rdlock.c +++ b/libc/pthread/pthread_rwlock_rdlock.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libc/pthread/pthread_rwlockread.c + * libc/pthread/pthread_rwlock_rdlock.c * * Copyright (C) 2017 Mark Schulte. All rights reserved. * Author: Mark Schulte @@ -50,6 +50,26 @@ * Private Functions ****************************************************************************/ +#ifdef CONFIG_PTHREAD_CLEANUP +static void rdlock_cleanup(FAR void *arg) +{ + FAR pthread_rwlock_t *rw_lock = (FAR pthread_rwlock_t *)arg; + +#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE + /* Check if this is a robust mutex in an inconsistent state */ + + if ((rw_lock->lock.flags & _PTHREAD_MFLAGS_INCONSISTENT) != 0) + { + (void)pthread_mutex_consistent(&rw_lock->lock); + } + else +#endif + { + (void)pthread_mutex_unlock(&rw_lock->lock); + } +} +#endif + static int tryrdlock(FAR pthread_rwlock_t *rw_lock) { int err; @@ -116,6 +136,9 @@ int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *rw_lock, return err; } +#ifdef CONFIG_PTHREAD_CLEANUP + pthread_cleanup_push(&rdlock_cleanup, rw_lock); +#endif while ((err = tryrdlock(rw_lock)) == EBUSY) { if (ts != NULL) @@ -132,6 +155,9 @@ int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *rw_lock, break; } } +#ifdef CONFIG_PTHREAD_CLEANUP + pthread_cleanup_pop(0); +#endif pthread_mutex_unlock(&rw_lock->lock); return err; diff --git a/libc/pthread/pthread_rwlock_wrlock.c b/libc/pthread/pthread_rwlock_wrlock.c index ecda4cb25be..93a6a238582 100644 --- a/libc/pthread/pthread_rwlock_wrlock.c +++ b/libc/pthread/pthread_rwlock_wrlock.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libc/pthread/pthread_rwlockwrite.c + * libc/pthread/pthread_rwlock_wrlock.c * * Copyright (C) 2017 Mark Schulte. All rights reserved. * Author: Mark Schulte @@ -46,15 +46,41 @@ #include +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_PTHREAD_CLEANUP +static void wrlock_cleanup(FAR void *arg) +{ + FAR pthread_rwlock_t *rw_lock = (FAR pthread_rwlock_t *)arg; + + rw_lock->num_writers--; + +#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE + /* Check if this is a robust mutex in an inconsistent state */ + + if ((rw_lock->lock.flags & _PTHREAD_MFLAGS_INCONSISTENT) != 0) + { + (void)pthread_mutex_consistent(&rw_lock->lock); + } + else +#endif + { + (void)pthread_mutex_unlock(&rw_lock->lock); + } +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: pthread_rwlock_rdlock + * Name: pthread_rwlock_wrlock * * Description: - * Locks a read/write lock for reading + * Locks a read/write lock for writing * * Parameters: * None @@ -106,6 +132,9 @@ int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *rw_lock, rw_lock->num_writers++; +#ifdef CONFIG_PTHREAD_CLEANUP + pthread_cleanup_push(&wrlock_cleanup, rw_lock); +#endif while (rw_lock->write_in_progress || rw_lock->num_readers > 0) { if (ts != NULL) @@ -122,12 +151,14 @@ int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *rw_lock, break; } } +#ifdef CONFIG_PTHREAD_CLEANUP + pthread_cleanup_pop(0); +#endif if (err == 0) { rw_lock->write_in_progress = true; } - else { /* In case of error, notify any blocked readers. */ diff --git a/sched/Kconfig b/sched/Kconfig index 50613fb44d3..6cefe0e121f 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -601,8 +601,6 @@ config PTHREAD_CLEANUP_STACKSIZE 8 for a CPU with 32-bit addressing and 4 for a CPU with 16-bit addressing. -endmenu # Pthread Options - config CANCELLATION_POINTS bool "Cancellation points" default n @@ -611,6 +609,8 @@ config CANCELLATION_POINTS cancellation points will also used with the () task_delete() API even if pthreads are not enabled. +endmenu # Pthread Options + menu "Performance Monitoring" config SCHED_CPULOAD diff --git a/sched/pthread/pthread_cancel.c b/sched/pthread/pthread_cancel.c index e2cad60ebbf..f68d272e03a 100644 --- a/sched/pthread/pthread_cancel.c +++ b/sched/pthread/pthread_cancel.c @@ -145,6 +145,12 @@ int pthread_cancel(pthread_t thread) pthread_exit(PTHREAD_CANCELED); } +#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE + /* Recover any mutexes still held by the canceled thread */ + + pthread_mutex_inconsistent(tcb); +#endif + #ifdef CONFIG_PTHREAD_CLEANUP /* Perform any stack pthread clean-up callbacks. * @@ -162,12 +168,6 @@ int pthread_cancel(pthread_t thread) (void)pthread_completejoin((pid_t)thread, PTHREAD_CANCELED); -#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE - /* Recover any mutexes still held by the canceled thread */ - - pthread_mutex_inconsistent(tcb); -#endif - /* Then let task_terminate do the real work */ return task_terminate((pid_t)thread, false); diff --git a/sched/pthread/pthread_exit.c b/sched/pthread/pthread_exit.c index bcc8e79c855..4929db94cb5 100644 --- a/sched/pthread/pthread_exit.c +++ b/sched/pthread/pthread_exit.c @@ -105,6 +105,12 @@ void pthread_exit(FAR void *exit_value) tcb->cpcount = 0; #endif +#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE + /* Recover any mutexes still held by the canceled thread */ + + pthread_mutex_inconsistent((FAR struct pthread_tcb_s *)tcb); +#endif + #ifdef CONFIG_PTHREAD_CLEANUP /* Perform any stack pthread clean-up callbacks */ @@ -123,12 +129,6 @@ void pthread_exit(FAR void *exit_value) exit(EXIT_FAILURE); } -#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE - /* Recover any mutexes still held by the canceled thread */ - - pthread_mutex_inconsistent((FAR struct pthread_tcb_s *)tcb); -#endif - /* Perform common task termination logic. This will get called again later * through logic kicked off by _exit(). However, we need to call it before * calling _exit() in order certain operations if this is the last thread diff --git a/sched/pthread/pthread_mutexconsistent.c b/sched/pthread/pthread_mutexconsistent.c index 77d9bede3e5..e374083021f 100644 --- a/sched/pthread/pthread_mutexconsistent.c +++ b/sched/pthread/pthread_mutexconsistent.c @@ -119,7 +119,6 @@ int pthread_mutex_consistent(FAR pthread_mutex_t *mutex) /* The thread associated with the PID no longer exists */ mutex->pid = -1; - mutex->flags &= _PTHREAD_MFLAGS_ROBUST; #ifdef CONFIG_PTHREAD_MUTEX_TYPES mutex->nlocks = 0; #endif @@ -132,6 +131,9 @@ int pthread_mutex_consistent(FAR pthread_mutex_t *mutex) } } + /* Clear the inconsistent flag in any case */ + + mutex->flags &= _PTHREAD_MFLAGS_ROBUST; sched_unlock(); ret = OK; }