From f807b84ba0b7f55eead115aa66fba808ba561556 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 1 Jun 2016 11:04:50 +0200 Subject: 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 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; } -- cgit v1.2.3