Merge branch 'rwlock'

This commit is contained in:
Gregory Nutt 2017-04-10 08:46:02 -06:00
commit ec2a6e3721
6 changed files with 79 additions and 20 deletions

View File

@ -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 <mark@mjs.pw>
@ -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;

View File

@ -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 <mark@mjs.pw>
@ -46,15 +46,41 @@
#include <nuttx/semaphore.h>
/****************************************************************************
* 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. */

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;
}