diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-06-01 11:04:50 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-06-01 11:13:47 +0200 |
commit | f807b84ba0b7f55eead115aa66fba808ba561556 (patch) | |
tree | fc2d61c5c86c44cc3bacedf893970416d92ffbe7 /cpukit/score/include/rtems/score/threadimpl.h | |
parent | smptests/smpatomic01: New test cases (diff) | |
download | rtems-f807b84ba0b7f55eead115aa66fba808ba561556.tar.bz2 |
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.
Diffstat (limited to '')
-rw-r--r-- | cpukit/score/include/rtems/score/threadimpl.h | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index d10221234c..bd2ec5004a 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; } |