[PATCH 09/10] score: Avoid Giant lock for CORE rwlock
Sebastian Huber
sebastian.huber at embedded-brains.de
Thu Apr 21 07:20:13 UTC 2016
Update #2555.
---
cpukit/posix/include/rtems/posix/rwlockimpl.h | 5 +-
cpukit/posix/src/prwlockdestroy.c | 72 ++++-------
cpukit/posix/src/prwlockinit.c | 22 ++--
cpukit/posix/src/prwlockrdlock.c | 56 +++------
cpukit/posix/src/prwlocktimedrdlock.c | 88 +++++--------
cpukit/posix/src/prwlocktimedwrlock.c | 87 +++++--------
cpukit/posix/src/prwlocktryrdlock.c | 61 +++------
cpukit/posix/src/prwlocktrywrlock.c | 60 +++------
cpukit/posix/src/prwlockunlock.c | 41 ++----
cpukit/posix/src/prwlockwrlock.c | 56 +++------
cpukit/score/include/rtems/score/corerwlockimpl.h | 24 +++-
cpukit/score/src/corerwlockobtainread.c | 98 ++++++++-------
cpukit/score/src/corerwlockobtainwrite.c | 78 ++++++------
cpukit/score/src/corerwlockrelease.c | 144 +++++++++++++---------
14 files changed, 367 insertions(+), 525 deletions(-)
diff --git a/cpukit/posix/include/rtems/posix/rwlockimpl.h b/cpukit/posix/include/rtems/posix/rwlockimpl.h
index 8c94843..c024ee5 100644
--- a/cpukit/posix/include/rtems/posix/rwlockimpl.h
+++ b/cpukit/posix/include/rtems/posix/rwlockimpl.h
@@ -23,6 +23,7 @@
#include <rtems/score/corerwlockimpl.h>
#include <rtems/score/objectimpl.h>
+#include <errno.h>
#include <pthread.h>
#ifdef __cplusplus
@@ -86,8 +87,8 @@ RTEMS_INLINE_ROUTINE void _POSIX_RWLock_Free (
}
POSIX_RWLock_Control *_POSIX_RWLock_Get(
- pthread_rwlock_t *rwlock,
- Objects_Locations *location
+ const pthread_rwlock_t *rwlock,
+ ISR_lock_Context *lock_context
);
#ifdef __cplusplus
diff --git a/cpukit/posix/src/prwlockdestroy.c b/cpukit/posix/src/prwlockdestroy.c
index a675b90..6f9eec8 100644
--- a/cpukit/posix/src/prwlockdestroy.c
+++ b/cpukit/posix/src/prwlockdestroy.c
@@ -17,68 +17,42 @@
#include "config.h"
#endif
-#include <pthread.h>
-#include <errno.h>
-
#include <rtems/posix/rwlockimpl.h>
-#include <rtems/score/threadqimpl.h>
-/**
- * This directive allows a thread to delete a rwlock specified by
- * the rwlock id. The rwlock is freed back to the inactive
- * rwlock chain.
- *
- * @param[in] rwlock is the rwlock id
- *
- * @return This method returns 0 if there was not an
- * error. Otherwise, a status code is returned indicating the
- * source of the error.
- */
int pthread_rwlock_destroy(
pthread_rwlock_t *rwlock
)
{
- POSIX_RWLock_Control *the_rwlock = NULL;
- Objects_Locations location;
+ POSIX_RWLock_Control *the_rwlock;
+ ISR_lock_Context lock_context;
_Objects_Allocator_lock();
- the_rwlock = _POSIX_RWLock_Get( rwlock, &location );
- switch ( location ) {
+ the_rwlock = _POSIX_RWLock_Get( rwlock, &lock_context );
- case OBJECTS_LOCAL:
- /*
- * If there is at least one thread waiting, then do not delete it.
- */
- if (
- _Thread_queue_First(
- &the_rwlock->RWLock.Wait_queue,
- CORE_RWLOCK_TQ_OPERATIONS
- ) != NULL
- ) {
- _Objects_Put( &the_rwlock->Object );
- _Objects_Allocator_unlock();
- return EBUSY;
- }
-
- /*
- * POSIX doesn't require behavior when it is locked.
- */
+ if ( the_rwlock == NULL ) {
+ _Objects_Allocator_unlock();
+ return EINVAL;
+ }
- _Objects_Close( &_POSIX_RWLock_Information, &the_rwlock->Object );
- _Objects_Put( &the_rwlock->Object );
- _POSIX_RWLock_Free( the_rwlock );
- _Objects_Allocator_unlock();
+ _CORE_RWLock_Acquire_critical( &the_rwlock->RWLock, &lock_context );
- return 0;
+ /*
+ * If there is at least one thread waiting, then do not delete it.
+ */
-#if defined(RTEMS_MULTIPROCESSING)
- case OBJECTS_REMOTE:
-#endif
- case OBJECTS_ERROR:
- break;
+ if ( !_Thread_queue_Is_empty( &the_rwlock->RWLock.Wait_queue.Queue ) ) {
+ _CORE_RWLock_Release( &the_rwlock->RWLock, &lock_context );
+ _Objects_Allocator_unlock();
+ return EBUSY;
}
- _Objects_Allocator_unlock();
+ /*
+ * POSIX doesn't require behavior when it is locked.
+ */
- return EINVAL;
+ _Objects_Close( &_POSIX_RWLock_Information, &the_rwlock->Object );
+ _CORE_RWLock_Release( &the_rwlock->RWLock, &lock_context );
+ _POSIX_RWLock_Free( the_rwlock );
+ _Objects_Allocator_unlock();
+ return 0;
}
diff --git a/cpukit/posix/src/prwlockinit.c b/cpukit/posix/src/prwlockinit.c
index afb7056..ea6abe9 100644
--- a/cpukit/posix/src/prwlockinit.c
+++ b/cpukit/posix/src/prwlockinit.c
@@ -20,20 +20,14 @@
#include "config.h"
#endif
-#include <pthread.h>
-#include <errno.h>
-
#include <rtems/posix/rwlockimpl.h>
#include <rtems/score/apimutex.h>
static bool _POSIX_RWLock_Check_id_and_auto_init(
- pthread_mutex_t *rwlock,
- Objects_Locations *location
+ pthread_mutex_t *rwlock
)
{
if ( rwlock == NULL ) {
- *location = OBJECTS_ERROR;
-
return false;
}
@@ -51,8 +45,6 @@ static bool _POSIX_RWLock_Check_id_and_auto_init(
_Once_Unlock();
if ( eno != 0 ) {
- *location = OBJECTS_ERROR;
-
return false;
}
}
@@ -61,18 +53,18 @@ static bool _POSIX_RWLock_Check_id_and_auto_init(
}
POSIX_RWLock_Control *_POSIX_RWLock_Get(
- pthread_rwlock_t *rwlock,
- Objects_Locations *location
+ const pthread_rwlock_t *rwlock,
+ ISR_lock_Context *lock_context
)
{
- if ( !_POSIX_RWLock_Check_id_and_auto_init( rwlock, location ) ) {
+ if ( !_POSIX_RWLock_Check_id_and_auto_init( rwlock ) ) {
return NULL;
}
- return (POSIX_RWLock_Control *) _Objects_Get(
- &_POSIX_RWLock_Information,
+ return (POSIX_RWLock_Control *) _Objects_Get_local(
*rwlock,
- location
+ &_POSIX_RWLock_Information,
+ lock_context
);
}
diff --git a/cpukit/posix/src/prwlockrdlock.c b/cpukit/posix/src/prwlockrdlock.c
index 7d1bcaa..3459399 100644
--- a/cpukit/posix/src/prwlockrdlock.c
+++ b/cpukit/posix/src/prwlockrdlock.c
@@ -18,53 +18,31 @@
#include "config.h"
#endif
-#include <pthread.h>
-#include <errno.h>
-
#include <rtems/posix/rwlockimpl.h>
-#include <rtems/score/thread.h>
-
-/**
- * This directive attempts to obtain a read only lock on an rwlock instance.
- *
- * @param[in] rwlock is the pointer to rwlock id
- *
- * @retval 0 if successful
- * @retval error_code if unsuccessful
- */
int pthread_rwlock_rdlock(
pthread_rwlock_t *rwlock
)
{
- POSIX_RWLock_Control *the_rwlock;
- Objects_Locations location;
- Thread_Control *executing;
-
- the_rwlock = _POSIX_RWLock_Get( rwlock, &location );
- switch ( location ) {
-
- case OBJECTS_LOCAL:
+ POSIX_RWLock_Control *the_rwlock;
+ ISR_lock_Context lock_context;
+ Thread_Control *executing;
- executing = _Thread_Executing;
- _CORE_RWLock_Seize_for_reading(
- &the_rwlock->RWLock,
- executing,
- true, /* we are willing to wait forever */
- 0
- );
+ the_rwlock = _POSIX_RWLock_Get( rwlock, &lock_context );
- _Objects_Put( &the_rwlock->Object );
- return _POSIX_RWLock_Translate_core_RWLock_return_code(
- (CORE_RWLock_Status) executing->Wait.return_code
- );
-
-#if defined(RTEMS_MULTIPROCESSING)
- case OBJECTS_REMOTE:
-#endif
- case OBJECTS_ERROR:
- break;
+ if ( the_rwlock == NULL ) {
+ return EINVAL;
}
- return EINVAL;
+ executing = _Thread_Executing;
+ _CORE_RWLock_Seize_for_reading(
+ &the_rwlock->RWLock,
+ executing,
+ true, /* we are willing to wait forever */
+ 0,
+ &lock_context
+ );
+ return _POSIX_RWLock_Translate_core_RWLock_return_code(
+ (CORE_RWLock_Status) executing->Wait.return_code
+ );
}
diff --git a/cpukit/posix/src/prwlocktimedrdlock.c b/cpukit/posix/src/prwlocktimedrdlock.c
index 0f2878b..829e169 100644
--- a/cpukit/posix/src/prwlocktimedrdlock.c
+++ b/cpukit/posix/src/prwlocktimedrdlock.c
@@ -18,37 +18,20 @@
#include "config.h"
#endif
-#include <pthread.h>
-#include <errno.h>
-
#include <rtems/posix/rwlockimpl.h>
-#include <rtems/score/thread.h>
#include <rtems/score/todimpl.h>
-/*
- * pthread_rwlock_timedrdlock
- *
- * This directive attempts to obtain a read only lock on an rwlock instance.
- *
- * Input parameters:
- * rwlock - pointer to rwlock id
- *
- * Output parameters:
- * 0 - if successful
- * error code - if unsuccessful
- */
-
int pthread_rwlock_timedrdlock(
pthread_rwlock_t *rwlock,
const struct timespec *abstime
)
{
- POSIX_RWLock_Control *the_rwlock;
- Objects_Locations location;
- Watchdog_Interval ticks;
- bool do_wait = true;
+ POSIX_RWLock_Control *the_rwlock;
+ ISR_lock_Context lock_context;
+ Watchdog_Interval ticks;
+ bool do_wait;
TOD_Absolute_timeout_conversion_results status;
- Thread_Control *executing;
+ Thread_Control *executing;
/*
* POSIX requires that blocking calls with timeouts that take
@@ -64,43 +47,40 @@ int pthread_rwlock_timedrdlock(
* then we should not wait.
*/
status = _TOD_Absolute_timeout_to_ticks( abstime, &ticks );
- if ( status != TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE )
- do_wait = false;
-
- the_rwlock = _POSIX_RWLock_Get( rwlock, &location );
- switch ( location ) {
+ do_wait = ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE );
- case OBJECTS_LOCAL:
+ the_rwlock = _POSIX_RWLock_Get( rwlock, &lock_context );
- executing = _Thread_Executing;
- _CORE_RWLock_Seize_for_reading(
- &the_rwlock->RWLock,
- executing,
- do_wait,
- ticks
- );
+ if ( the_rwlock == NULL ) {
+ return EINVAL;
+ }
- _Objects_Put( &the_rwlock->Object );
- if ( !do_wait ) {
- if ( executing->Wait.return_code == CORE_RWLOCK_UNAVAILABLE ) {
- if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID )
- return EINVAL;
- if ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
- status == TOD_ABSOLUTE_TIMEOUT_IS_NOW )
- return ETIMEDOUT;
- }
- }
+ executing = _Thread_Executing;
+ _CORE_RWLock_Seize_for_reading(
+ &the_rwlock->RWLock,
+ executing,
+ do_wait,
+ ticks,
+ &lock_context
+ );
- return _POSIX_RWLock_Translate_core_RWLock_return_code(
- (CORE_RWLock_Status) executing->Wait.return_code
- );
+ if (
+ !do_wait
+ && ( executing->Wait.return_code == CORE_RWLOCK_UNAVAILABLE )
+ ) {
+ if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID ) {
+ return EINVAL;
+ }
-#if defined(RTEMS_MULTIPROCESSING)
- case OBJECTS_REMOTE:
-#endif
- case OBJECTS_ERROR:
- break;
+ if (
+ status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST
+ || status == TOD_ABSOLUTE_TIMEOUT_IS_NOW
+ ) {
+ return ETIMEDOUT;
+ }
}
- return EINVAL;
+ return _POSIX_RWLock_Translate_core_RWLock_return_code(
+ (CORE_RWLock_Status) executing->Wait.return_code
+ );
}
diff --git a/cpukit/posix/src/prwlocktimedwrlock.c b/cpukit/posix/src/prwlocktimedwrlock.c
index 51558de..1258c2b 100644
--- a/cpukit/posix/src/prwlocktimedwrlock.c
+++ b/cpukit/posix/src/prwlocktimedwrlock.c
@@ -20,37 +20,20 @@
#include "config.h"
#endif
-#include <pthread.h>
-#include <errno.h>
-
#include <rtems/posix/rwlockimpl.h>
-#include <rtems/score/thread.h>
#include <rtems/score/todimpl.h>
-/*
- * pthread_rwlock_timedwrlock
- *
- * This directive attempts to obtain a write only lock on an rwlock instance.
- *
- * Input parameters:
- * rwlock - pointer to rwlock id
- *
- * Output parameters:
- * 0 - if successful
- * error code - if unsuccessful
- */
-
int pthread_rwlock_timedwrlock(
pthread_rwlock_t *rwlock,
const struct timespec *abstime
)
{
- POSIX_RWLock_Control *the_rwlock;
- Objects_Locations location;
- Watchdog_Interval ticks;
- bool do_wait = true;
+ POSIX_RWLock_Control *the_rwlock;
+ ISR_lock_Context lock_context;
+ Watchdog_Interval ticks;
+ bool do_wait;
TOD_Absolute_timeout_conversion_results status;
- Thread_Control *executing;
+ Thread_Control *executing;
/*
* POSIX requires that blocking calls with timeouts that take
@@ -66,42 +49,40 @@ int pthread_rwlock_timedwrlock(
* then we should not wait.
*/
status = _TOD_Absolute_timeout_to_ticks( abstime, &ticks );
- if ( status != TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE )
- do_wait = false;
-
- the_rwlock = _POSIX_RWLock_Get( rwlock, &location );
- switch ( location ) {
+ do_wait = ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE );
- case OBJECTS_LOCAL:
+ the_rwlock = _POSIX_RWLock_Get( rwlock, &lock_context );
- executing = _Thread_Executing;
- _CORE_RWLock_Seize_for_writing(
- &the_rwlock->RWLock,
- executing,
- do_wait,
- ticks
- );
+ if ( the_rwlock == NULL ) {
+ return EINVAL;
+ }
- _Objects_Put( &the_rwlock->Object );
- if ( !do_wait &&
- (executing->Wait.return_code == CORE_RWLOCK_UNAVAILABLE) ) {
- if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID )
- return EINVAL;
- if ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
- status == TOD_ABSOLUTE_TIMEOUT_IS_NOW )
- return ETIMEDOUT;
- }
+ executing = _Thread_Executing;
+ _CORE_RWLock_Seize_for_writing(
+ &the_rwlock->RWLock,
+ executing,
+ do_wait,
+ ticks,
+ &lock_context
+ );
- return _POSIX_RWLock_Translate_core_RWLock_return_code(
- (CORE_RWLock_Status) executing->Wait.return_code
- );
+ if (
+ !do_wait
+ && ( executing->Wait.return_code == CORE_RWLOCK_UNAVAILABLE )
+ ) {
+ if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID ) {
+ return EINVAL;
+ }
-#if defined(RTEMS_MULTIPROCESSING)
- case OBJECTS_REMOTE:
-#endif
- case OBJECTS_ERROR:
- break;
+ if (
+ status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST
+ || status == TOD_ABSOLUTE_TIMEOUT_IS_NOW
+ ) {
+ return ETIMEDOUT;
+ }
}
- return EINVAL;
+ return _POSIX_RWLock_Translate_core_RWLock_return_code(
+ (CORE_RWLock_Status) executing->Wait.return_code
+ );
}
diff --git a/cpukit/posix/src/prwlocktryrdlock.c b/cpukit/posix/src/prwlocktryrdlock.c
index 642ed86..a73d122 100644
--- a/cpukit/posix/src/prwlocktryrdlock.c
+++ b/cpukit/posix/src/prwlocktryrdlock.c
@@ -18,58 +18,31 @@
#include "config.h"
#endif
-#include <pthread.h>
-#include <errno.h>
-
#include <rtems/posix/rwlockimpl.h>
-#include <rtems/score/thread.h>
-
-/*
- * pthread_rwlock_tryrdlock
- *
- * This directive attempts to obtain a read only lock on an rwlock instance.
- *
- * Input parameters:
- * rwlock - pointer to rwlock id
- *
- * Output parameters:
- * 0 - if successful
- * error code - if unsuccessful
- */
int pthread_rwlock_tryrdlock(
pthread_rwlock_t *rwlock
)
{
- POSIX_RWLock_Control *the_rwlock;
- Objects_Locations location;
- Thread_Control *executing;
-
- the_rwlock = _POSIX_RWLock_Get( rwlock, &location );
- switch ( location ) {
-
- case OBJECTS_LOCAL:
+ POSIX_RWLock_Control *the_rwlock;
+ ISR_lock_Context lock_context;
+ Thread_Control *executing;
- executing = _Thread_Executing;
- _CORE_RWLock_Seize_for_reading(
- &the_rwlock->RWLock,
- executing,
- false, /* do not wait for the rwlock */
- 0
- );
+ the_rwlock = _POSIX_RWLock_Get( rwlock, &lock_context );
-
- _Objects_Put( &the_rwlock->Object );
- return _POSIX_RWLock_Translate_core_RWLock_return_code(
- (CORE_RWLock_Status) executing->Wait.return_code
- );
-
-#if defined(RTEMS_MULTIPROCESSING)
- case OBJECTS_REMOTE:
-#endif
- case OBJECTS_ERROR:
- break;
+ if ( the_rwlock == NULL ) {
+ return EINVAL;
}
- return EINVAL;
+ executing = _Thread_Executing;
+ _CORE_RWLock_Seize_for_reading(
+ &the_rwlock->RWLock,
+ executing,
+ false, /* do not wait for the rwlock */
+ 0,
+ &lock_context
+ );
+ return _POSIX_RWLock_Translate_core_RWLock_return_code(
+ (CORE_RWLock_Status) executing->Wait.return_code
+ );
}
diff --git a/cpukit/posix/src/prwlocktrywrlock.c b/cpukit/posix/src/prwlocktrywrlock.c
index 065199b..a44a54f 100644
--- a/cpukit/posix/src/prwlocktrywrlock.c
+++ b/cpukit/posix/src/prwlocktrywrlock.c
@@ -18,57 +18,31 @@
#include "config.h"
#endif
-#include <pthread.h>
-#include <errno.h>
-
#include <rtems/posix/rwlockimpl.h>
-#include <rtems/score/thread.h>
-
-/*
- * pthread_rwlock_trywrlock
- *
- * This directive attempts to obtain a Write only lock on an rwlock instance.
- *
- * Input parameters:
- * rwlock - pointer to rwlock id
- *
- * Output parameters:
- * 0 - if successful
- * error code - if unsuccessful
- */
int pthread_rwlock_trywrlock(
pthread_rwlock_t *rwlock
)
{
- POSIX_RWLock_Control *the_rwlock;
- Objects_Locations location;
- Thread_Control *executing;
-
- the_rwlock = _POSIX_RWLock_Get( rwlock, &location );
- switch ( location ) {
-
- case OBJECTS_LOCAL:
+ POSIX_RWLock_Control *the_rwlock;
+ ISR_lock_Context lock_context;
+ Thread_Control *executing;
- executing = _Thread_Executing;
- _CORE_RWLock_Seize_for_writing(
- &the_rwlock->RWLock,
- executing,
- false, /* we are not willing to wait */
- 0
- );
+ the_rwlock = _POSIX_RWLock_Get( rwlock, &lock_context );
- _Objects_Put( &the_rwlock->Object );
- return _POSIX_RWLock_Translate_core_RWLock_return_code(
- (CORE_RWLock_Status) executing->Wait.return_code
- );
-
-#if defined(RTEMS_MULTIPROCESSING)
- case OBJECTS_REMOTE:
-#endif
- case OBJECTS_ERROR:
- break;
+ if ( the_rwlock == NULL ) {
+ return EINVAL;
}
- return EINVAL;
+ executing = _Thread_Executing;
+ _CORE_RWLock_Seize_for_writing(
+ &the_rwlock->RWLock,
+ executing,
+ false, /* we are not willing to wait */
+ 0,
+ &lock_context
+ );
+ return _POSIX_RWLock_Translate_core_RWLock_return_code(
+ (CORE_RWLock_Status) executing->Wait.return_code
+ );
}
diff --git a/cpukit/posix/src/prwlockunlock.c b/cpukit/posix/src/prwlockunlock.c
index 5dc7099..bf6b4de 100644
--- a/cpukit/posix/src/prwlockunlock.c
+++ b/cpukit/posix/src/prwlockunlock.c
@@ -20,47 +20,22 @@
#include "config.h"
#endif
-#include <pthread.h>
-#include <errno.h>
-
-#include <rtems/system.h>
#include <rtems/posix/rwlockimpl.h>
-/*
- * pthread_rwlock_unlock
- *
- * This directive attempts to release a lock on an RWLock.
- *
- * Input parameters:
- * rwlock - pointer to rwlock id
- *
- * Output parameters:
- * 0 - if successful
- * error code - if unsuccessful
- */
-
int pthread_rwlock_unlock(
pthread_rwlock_t *rwlock
)
{
- POSIX_RWLock_Control *the_rwlock;
- Objects_Locations location;
- CORE_RWLock_Status status;
+ POSIX_RWLock_Control *the_rwlock;
+ ISR_lock_Context lock_context;
+ CORE_RWLock_Status status;
- the_rwlock = _POSIX_RWLock_Get( rwlock, &location );
- switch ( location ) {
+ the_rwlock = _POSIX_RWLock_Get( rwlock, &lock_context );
- case OBJECTS_LOCAL:
- status = _CORE_RWLock_Surrender( &the_rwlock->RWLock, _Thread_Executing );
- _Objects_Put( &the_rwlock->Object );
- return _POSIX_RWLock_Translate_core_RWLock_return_code( status );
-
-#if defined(RTEMS_MULTIPROCESSING)
- case OBJECTS_REMOTE:
-#endif
- case OBJECTS_ERROR:
- break;
+ if ( the_rwlock == NULL ) {
+ return EINVAL;
}
- return EINVAL;
+ status = _CORE_RWLock_Surrender( &the_rwlock->RWLock, &lock_context );
+ return _POSIX_RWLock_Translate_core_RWLock_return_code( status );
}
diff --git a/cpukit/posix/src/prwlockwrlock.c b/cpukit/posix/src/prwlockwrlock.c
index aa35a2c..635f376 100644
--- a/cpukit/posix/src/prwlockwrlock.c
+++ b/cpukit/posix/src/prwlockwrlock.c
@@ -28,51 +28,29 @@
THREAD_WAIT_QUEUE_OBJECT_ASSERT( POSIX_RWLock_Control, RWLock.Wait_queue );
-/*
- * pthread_rwlock_wrlock
- *
- * This directive attempts to obtain a write only lock on an rwlock instance.
- *
- * Input parameters:
- * rwlock - pointer to rwlock id
- *
- * Output parameters:
- * 0 - if successful
- * error code - if unsuccessful
- */
-
int pthread_rwlock_wrlock(
pthread_rwlock_t *rwlock
)
{
- POSIX_RWLock_Control *the_rwlock;
- Objects_Locations location;
- Thread_Control *executing;
-
- the_rwlock = _POSIX_RWLock_Get( rwlock, &location );
- switch ( location ) {
-
- case OBJECTS_LOCAL:
+ POSIX_RWLock_Control *the_rwlock;
+ ISR_lock_Context lock_context;
+ Thread_Control *executing;
- executing = _Thread_Executing;
- _CORE_RWLock_Seize_for_writing(
- &the_rwlock->RWLock,
- executing,
- true, /* do not timeout -- wait forever */
- 0
- );
+ the_rwlock = _POSIX_RWLock_Get( rwlock, &lock_context );
- _Objects_Put( &the_rwlock->Object );
- return _POSIX_RWLock_Translate_core_RWLock_return_code(
- (CORE_RWLock_Status) executing->Wait.return_code
- );
-
-#if defined(RTEMS_MULTIPROCESSING)
- case OBJECTS_REMOTE:
-#endif
- case OBJECTS_ERROR:
- break;
+ if ( the_rwlock == NULL ) {
+ return EINVAL;
}
- return EINVAL;
+ executing = _Thread_Executing;
+ _CORE_RWLock_Seize_for_writing(
+ &the_rwlock->RWLock,
+ executing,
+ true, /* do not timeout -- wait forever */
+ 0,
+ &lock_context
+ );
+ return _POSIX_RWLock_Translate_core_RWLock_return_code(
+ (CORE_RWLock_Status) executing->Wait.return_code
+ );
}
diff --git a/cpukit/score/include/rtems/score/corerwlockimpl.h b/cpukit/score/include/rtems/score/corerwlockimpl.h
index e727ad6..ed59d69 100644
--- a/cpukit/score/include/rtems/score/corerwlockimpl.h
+++ b/cpukit/score/include/rtems/score/corerwlockimpl.h
@@ -86,6 +86,22 @@ RTEMS_INLINE_ROUTINE void _CORE_RWLock_Destroy(
_Thread_queue_Destroy( &the_rwlock->Wait_queue );
}
+RTEMS_INLINE_ROUTINE void _CORE_RWLock_Acquire_critical(
+ CORE_RWLock_Control *the_rwlock,
+ ISR_lock_Context *lock_context
+)
+{
+ _Thread_queue_Acquire_critical( &the_rwlock->Wait_queue, lock_context );
+}
+
+RTEMS_INLINE_ROUTINE void _CORE_RWLock_Release(
+ CORE_RWLock_Control *the_rwlock,
+ ISR_lock_Context *lock_context
+)
+{
+ _Thread_queue_Release( &the_rwlock->Wait_queue, lock_context );
+}
+
/**
* @brief Obtain RWLock for reading.
*
@@ -103,7 +119,8 @@ void _CORE_RWLock_Seize_for_reading(
CORE_RWLock_Control *the_rwlock,
Thread_Control *executing,
bool wait,
- Watchdog_Interval timeout
+ Watchdog_Interval timeout,
+ ISR_lock_Context *lock_context
);
/**
@@ -122,7 +139,8 @@ void _CORE_RWLock_Seize_for_writing(
CORE_RWLock_Control *the_rwlock,
Thread_Control *executing,
bool wait,
- Watchdog_Interval timeout
+ Watchdog_Interval timeout,
+ ISR_lock_Context *lock_context
);
/**
@@ -137,7 +155,7 @@ void _CORE_RWLock_Seize_for_writing(
*/
CORE_RWLock_Status _CORE_RWLock_Surrender(
CORE_RWLock_Control *the_rwlock,
- Thread_Control *executing
+ ISR_lock_Context *lock_context
);
/** @} */
diff --git a/cpukit/score/src/corerwlockobtainread.c b/cpukit/score/src/corerwlockobtainread.c
index 3d37571..fcbaf4a 100644
--- a/cpukit/score/src/corerwlockobtainread.c
+++ b/cpukit/score/src/corerwlockobtainread.c
@@ -27,70 +27,68 @@ void _CORE_RWLock_Seize_for_reading(
CORE_RWLock_Control *the_rwlock,
Thread_Control *executing,
bool wait,
- Watchdog_Interval timeout
+ Watchdog_Interval timeout,
+ ISR_lock_Context *lock_context
)
{
- ISR_lock_Context lock_context;
-
/*
* If unlocked, then OK to read.
* If locked for reading and no waiters, then OK to read.
* If any thread is waiting, then we wait.
*/
- _Thread_queue_Acquire( &the_rwlock->Wait_queue, &lock_context );
- switch ( the_rwlock->current_state ) {
- case CORE_RWLOCK_UNLOCKED:
- the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING;
- the_rwlock->number_of_readers += 1;
- _Thread_queue_Release( &the_rwlock->Wait_queue, &lock_context );
- executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
- return;
+ _CORE_RWLock_Acquire_critical( the_rwlock, lock_context );
+
+ switch ( the_rwlock->current_state ) {
+ case CORE_RWLOCK_UNLOCKED:
+ the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING;
+ the_rwlock->number_of_readers += 1;
+ _CORE_RWLock_Release( the_rwlock, lock_context );
+ executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
+ return;
- case CORE_RWLOCK_LOCKED_FOR_READING: {
- Thread_Control *waiter;
- waiter = _Thread_queue_First_locked(
- &the_rwlock->Wait_queue,
- CORE_RWLOCK_TQ_OPERATIONS
- );
- if ( !waiter ) {
- the_rwlock->number_of_readers += 1;
- _Thread_queue_Release( &the_rwlock->Wait_queue, &lock_context );
- executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
- return;
- }
- break;
+ case CORE_RWLOCK_LOCKED_FOR_READING: {
+ Thread_Control *waiter;
+ waiter = _Thread_queue_First_locked(
+ &the_rwlock->Wait_queue,
+ CORE_RWLOCK_TQ_OPERATIONS
+ );
+ if ( !waiter ) {
+ the_rwlock->number_of_readers += 1;
+ _CORE_RWLock_Release( the_rwlock, lock_context );
+ executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
+ return;
}
- case CORE_RWLOCK_LOCKED_FOR_WRITING:
- break;
+ break;
}
+ case CORE_RWLOCK_LOCKED_FOR_WRITING:
+ break;
+ }
- /*
- * If the thread is not willing to wait, then return immediately.
- */
-
- if ( !wait ) {
- _Thread_queue_Release( &the_rwlock->Wait_queue, &lock_context );
- executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
- return;
- }
+ /*
+ * If the thread is not willing to wait, then return immediately.
+ */
- /*
- * We need to wait to enter this critical section
- */
+ if ( !wait ) {
+ _CORE_RWLock_Release( the_rwlock, lock_context );
+ executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
+ return;
+ }
- executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_READ;
- executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
+ /*
+ * We need to wait to enter this critical section
+ */
- _Thread_queue_Enqueue_critical(
- &the_rwlock->Wait_queue.Queue,
- CORE_RWLOCK_TQ_OPERATIONS,
- executing,
- STATES_WAITING_FOR_RWLOCK,
- timeout,
- CORE_RWLOCK_TIMEOUT,
- &lock_context
- );
+ executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_READ;
+ executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
- /* return to API level so it can dispatch and we block */
+ _Thread_queue_Enqueue_critical(
+ &the_rwlock->Wait_queue.Queue,
+ CORE_RWLOCK_TQ_OPERATIONS,
+ executing,
+ STATES_WAITING_FOR_RWLOCK,
+ timeout,
+ CORE_RWLOCK_TIMEOUT,
+ lock_context
+ );
}
diff --git a/cpukit/score/src/corerwlockobtainwrite.c b/cpukit/score/src/corerwlockobtainwrite.c
index 07fe03a..e1bb1bd 100644
--- a/cpukit/score/src/corerwlockobtainwrite.c
+++ b/cpukit/score/src/corerwlockobtainwrite.c
@@ -24,14 +24,13 @@
#include <rtems/score/watchdog.h>
void _CORE_RWLock_Seize_for_writing(
- CORE_RWLock_Control *the_rwlock,
- Thread_Control *executing,
- bool wait,
- Watchdog_Interval timeout
+ CORE_RWLock_Control *the_rwlock,
+ Thread_Control *executing,
+ bool wait,
+ Watchdog_Interval timeout,
+ ISR_lock_Context *lock_context
)
{
- ISR_lock_Context lock_context;
-
/*
* If unlocked, then OK to read.
* Otherwise, we have to block.
@@ -39,45 +38,44 @@ void _CORE_RWLock_Seize_for_writing(
* If any thread is waiting, then we wait.
*/
- _Thread_queue_Acquire( &the_rwlock->Wait_queue, &lock_context );
- switch ( the_rwlock->current_state ) {
- case CORE_RWLOCK_UNLOCKED:
- the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
- _Thread_queue_Release( &the_rwlock->Wait_queue, &lock_context );
- executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
- return;
+ _CORE_RWLock_Acquire_critical( the_rwlock, lock_context );
- case CORE_RWLOCK_LOCKED_FOR_READING:
- case CORE_RWLOCK_LOCKED_FOR_WRITING:
- break;
- }
+ switch ( the_rwlock->current_state ) {
+ case CORE_RWLOCK_UNLOCKED:
+ the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
+ _CORE_RWLock_Release( the_rwlock, lock_context );
+ executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
+ return;
- /*
- * If the thread is not willing to wait, then return immediately.
- */
+ case CORE_RWLOCK_LOCKED_FOR_READING:
+ case CORE_RWLOCK_LOCKED_FOR_WRITING:
+ break;
+ }
- if ( !wait ) {
- _Thread_queue_Release( &the_rwlock->Wait_queue, &lock_context );
- executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
- return;
- }
+ /*
+ * If the thread is not willing to wait, then return immediately.
+ */
- /*
- * We need to wait to enter this critical section
- */
+ if ( !wait ) {
+ _CORE_RWLock_Release( the_rwlock, lock_context );
+ executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
+ return;
+ }
- executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_WRITE;
- executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
+ /*
+ * We need to wait to enter this critical section
+ */
- _Thread_queue_Enqueue_critical(
- &the_rwlock->Wait_queue.Queue,
- CORE_RWLOCK_TQ_OPERATIONS,
- executing,
- STATES_WAITING_FOR_RWLOCK,
- timeout,
- CORE_RWLOCK_TIMEOUT,
- &lock_context
- );
+ executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_WRITE;
+ executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
- /* return to API level so it can dispatch and we block */
+ _Thread_queue_Enqueue_critical(
+ &the_rwlock->Wait_queue.Queue,
+ CORE_RWLOCK_TQ_OPERATIONS,
+ executing,
+ STATES_WAITING_FOR_RWLOCK,
+ timeout,
+ CORE_RWLOCK_TIMEOUT,
+ lock_context
+ );
}
diff --git a/cpukit/score/src/corerwlockrelease.c b/cpukit/score/src/corerwlockrelease.c
index d8180fc..3ace00d 100644
--- a/cpukit/score/src/corerwlockrelease.c
+++ b/cpukit/score/src/corerwlockrelease.c
@@ -19,19 +19,65 @@
#include "config.h"
#endif
-#include <rtems/system.h>
#include <rtems/score/corerwlockimpl.h>
-#include <rtems/score/threadqimpl.h>
-#include <rtems/score/watchdog.h>
+#include <rtems/score/assert.h>
+
+static bool _CORE_RWLock_Is_waiting_for_reading(
+ const Thread_Control *the_thread
+)
+{
+ if ( the_thread->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_READ ) {
+ return true;
+ } else {
+ _Assert( the_thread->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_WRITE );
+ return false;
+ }
+}
+
+static Thread_Control *_CORE_RWLock_Flush_filter(
+ Thread_Control *the_thread,
+ Thread_queue_Queue *queue,
+ ISR_lock_Context *lock_context
+)
+{
+ CORE_RWLock_Control *the_rwlock;
+
+ the_rwlock = RTEMS_CONTAINER_OF(
+ queue,
+ CORE_RWLock_Control,
+ Wait_queue.Queue
+ );
+
+ switch ( the_rwlock->current_state ) {
+ case CORE_RWLOCK_LOCKED_FOR_READING:
+ if ( _CORE_RWLock_Is_waiting_for_reading( the_thread ) ) {
+ the_rwlock->number_of_readers += 1;
+ } else {
+ the_thread = NULL;
+ }
+ break;
+ case CORE_RWLOCK_LOCKED_FOR_WRITING:
+ the_thread = NULL;
+ break;
+ default:
+ _Assert( the_rwlock->current_state == CORE_RWLOCK_UNLOCKED );
+ if ( _CORE_RWLock_Is_waiting_for_reading( the_thread ) ) {
+ the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING;
+ the_rwlock->number_of_readers = 1;
+ } else {
+ the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
+ }
+ break;
+ }
+
+ return the_thread;
+}
CORE_RWLock_Status _CORE_RWLock_Surrender(
CORE_RWLock_Control *the_rwlock,
- Thread_Control *executing
+ ISR_lock_Context *lock_context
)
{
- ISR_Level level;
- Thread_Control *next;
-
/*
* If unlocked, then OK to read.
* Otherwise, we have to block.
@@ -39,67 +85,43 @@ CORE_RWLock_Status _CORE_RWLock_Surrender(
* If any thread is waiting, then we wait.
*/
- _ISR_Disable( level );
- if ( the_rwlock->current_state == CORE_RWLOCK_UNLOCKED){
- _ISR_Enable( level );
- executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
- return CORE_RWLOCK_SUCCESSFUL;
- }
- if ( the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_READING ) {
- the_rwlock->number_of_readers -= 1;
- if ( the_rwlock->number_of_readers != 0 ) {
- /* must be unlocked again */
- _ISR_Enable( level );
- return CORE_RWLOCK_SUCCESSFUL;
- }
- }
-
- /* CORE_RWLOCK_LOCKED_FOR_WRITING or READING with readers */
- executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
+ _CORE_RWLock_Acquire_critical( the_rwlock, lock_context );
- /*
- * Implicitly transition to "unlocked" and find another thread interested
- * in obtaining this rwlock.
- */
- the_rwlock->current_state = CORE_RWLOCK_UNLOCKED;
- _ISR_Enable( level );
+ if ( the_rwlock->current_state == CORE_RWLOCK_UNLOCKED){
+ /* This is an error at the caller site */
+ _CORE_RWLock_Release( the_rwlock, lock_context );
+ return CORE_RWLOCK_SUCCESSFUL;
+ }
- next = _Thread_queue_Dequeue(
- &the_rwlock->Wait_queue,
- CORE_RWLOCK_TQ_OPERATIONS,
- NULL,
- 0
- );
+ if ( the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_READING ) {
+ the_rwlock->number_of_readers -= 1;
- if ( next ) {
- if ( next->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_WRITE ) {
- the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
+ if ( the_rwlock->number_of_readers != 0 ) {
+ /* must be unlocked again */
+ _CORE_RWLock_Release( the_rwlock, lock_context );
return CORE_RWLOCK_SUCCESSFUL;
}
-
- /*
- * Must be CORE_RWLOCK_THREAD_WAITING_FOR_READING
- */
- the_rwlock->number_of_readers += 1;
- the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING;
-
- /*
- * Now see if more readers can be let go.
- */
- while ( 1 ) {
- next = _Thread_queue_First(
- &the_rwlock->Wait_queue,
- CORE_RWLOCK_TQ_OPERATIONS
- );
- if ( !next ||
- next->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_WRITE )
- return CORE_RWLOCK_SUCCESSFUL;
- the_rwlock->number_of_readers += 1;
- _Thread_queue_Extract( next );
- }
}
- /* indentation is to match _ISR_Disable at top */
+ _Assert(
+ the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_WRITING
+ || ( the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_READING
+ && the_rwlock->number_of_readers == 0 )
+ );
+
+ /*
+ * Implicitly transition to "unlocked" and find another thread interested
+ * in obtaining this rwlock.
+ */
+ the_rwlock->current_state = CORE_RWLOCK_UNLOCKED;
+ _Thread_queue_Flush_critical(
+ &the_rwlock->Wait_queue.Queue,
+ CORE_RWLOCK_TQ_OPERATIONS,
+ _CORE_RWLock_Flush_filter,
+ NULL,
+ 0,
+ lock_context
+ );
return CORE_RWLOCK_SUCCESSFUL;
}
--
1.8.4.5
More information about the devel
mailing list