summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-06-01 11:04:50 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-06-01 11:13:47 +0200
commitf807b84ba0b7f55eead115aa66fba808ba561556 (patch)
treefc2d61c5c86c44cc3bacedf893970416d92ffbe7
parenta9cc6a84c50c7745155192ca8fda2ba36e43dd69 (diff)
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.
-rw-r--r--cpukit/score/include/rtems/score/threadimpl.h23
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;
}