[rtems commit] score: Fix _Thread_Lock_acquire()

Sebastian Huber sebh at rtems.org
Wed Jun 1 09:27:10 UTC 2016


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Jun  1 11:04:50 2016 +0200

score: Fix _Thread_Lock_acquire()

A read-modify-write operation is necessary to read the last value
written.

See for example C11 standard or Power ISA 2.07, Book II: Power ISA
Virtual Environment Architecture, Section 1.6.3 Memory Coherence
Required [Category: Memory Coherence] and Section 1.7.3 Atomic Update.

---

 cpukit/score/include/rtems/score/threadimpl.h | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index d102212..bd2ec50 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -1128,16 +1128,16 @@ RTEMS_INLINE_ROUTINE void *_Thread_Lock_acquire(
   SMP_ticket_lock_Control *lock;
 
   while ( true ) {
-    unsigned int first_generation;
-    unsigned int second_generation;
+    unsigned int my_generation;
+    bool         success;
 
     _ISR_lock_ISR_disable( lock_context );
 
     /*
-     * Ensure that we read our first lock generation before we obtain our
+     * Ensure that we read our lock generation before we obtain our
      * current lock.  See _Thread_Lock_set_unprotected().
      */
-    first_generation = _Atomic_Load_uint(
+    my_generation = _Atomic_Load_uint(
       &the_thread->Lock.generation,
       ATOMIC_ORDER_ACQUIRE
     );
@@ -1150,17 +1150,18 @@ RTEMS_INLINE_ROUTINE void *_Thread_Lock_acquire(
     );
 
     /*
-     * The C11 memory model doesn't guarantee that we read the latest
-     * generation here.  For this a read-modify-write operation would be
-     * necessary.  We read at least the new generation set up by the owner of
-     * our current thread lock, and so on.
+     * We must use a read-modify-write operation to observe the last value
+     * written.
      */
-    second_generation = _Atomic_Load_uint(
+    success = _Atomic_Compare_exchange_uint(
       &the_thread->Lock.generation,
-      ATOMIC_ORDER_ACQUIRE
+      &my_generation,
+      my_generation,
+      ATOMIC_ORDER_RELAXED,
+      ATOMIC_ORDER_RELAXED
     );
 
-    if ( first_generation == second_generation ) {
+    if ( success ) {
       return lock;
     }
 



More information about the vc mailing list