[rtems commit] score: Avoid Giant lock for CORE rwlock

Sebastian Huber sebh at rtems.org
Fri Apr 22 07:28:44 UTC 2016


Module:    rtems
Branch:    master
Commit:    84a539885335c629100a6a12b57ead54bbbc0165
Changeset: http://git.rtems.org/rtems/commit/?id=84a539885335c629100a6a12b57ead54bbbc0165

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu Apr 21 06:32:16 2016 +0200

score: Avoid Giant lock for CORE rwlock

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..6f3088e 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
+  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..8bbb2fd 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
+  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;
 }



More information about the vc mailing list