[rtems commit] score: Maybe fix _Thread_Lock_acquire()
Sebastian Huber
sebh at rtems.org
Thu Jun 2 05:45:14 UTC 2016
Module: rtems
Branch: master
Commit: c6556e2ecc6b80f981bb210d541544f24b7f59df
Changeset: http://git.rtems.org/rtems/commit/?id=c6556e2ecc6b80f981bb210d541544f24b7f59df
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Wed Jun 1 14:38:05 2016 +0200
score: Maybe fix _Thread_Lock_acquire()
The approach with the generation number was broken. The load/store of
the current lock, the thread queue and the thread queue operations were not
properly synchronized. Under certain conditions on a PowerPC T4240 old
thread queue operations operated on a new thread queue (NULL pointer).
---
cpukit/score/include/rtems/score/thread.h | 5 ---
cpukit/score/include/rtems/score/threadimpl.h | 44 +++++----------------------
2 files changed, 7 insertions(+), 42 deletions(-)
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index 4618a40..7491e8f 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -691,11 +691,6 @@ typedef struct {
*/
SMP_lock_Stats Stats;
#endif
-
- /**
- * @brief Generation number to invalidate stale locks.
- */
- Atomic_Uint generation;
} Thread_Lock_control;
#endif
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index bd2ec50..164773a 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -1128,21 +1128,16 @@ RTEMS_INLINE_ROUTINE void *_Thread_Lock_acquire(
SMP_ticket_lock_Control *lock;
while ( true ) {
- unsigned int my_generation;
- bool success;
-
_ISR_lock_ISR_disable( lock_context );
/*
- * Ensure that we read our lock generation before we obtain our
- * current lock. See _Thread_Lock_set_unprotected().
+ * We assume that a normal load of pointer is identical to a relaxed atomic
+ * load. Here, we may read an out-of-date lock. However, only the owner
+ * of this out-of-date lock is allowed to set a new one. Thus, we read at
+ * least this new lock ...
*/
- my_generation = _Atomic_Load_uint(
- &the_thread->Lock.generation,
- ATOMIC_ORDER_ACQUIRE
- );
-
lock = the_thread->Lock.current;
+
_SMP_ticket_lock_Acquire(
lock,
&_Thread_Executing->Lock.Stats,
@@ -1150,18 +1145,9 @@ RTEMS_INLINE_ROUTINE void *_Thread_Lock_acquire(
);
/*
- * We must use a read-modify-write operation to observe the last value
- * written.
+ * ... here, and so on.
*/
- success = _Atomic_Compare_exchange_uint(
- &the_thread->Lock.generation,
- &my_generation,
- my_generation,
- ATOMIC_ORDER_RELAXED,
- ATOMIC_ORDER_RELAXED
- );
-
- if ( success ) {
+ if ( lock == the_thread->Lock.current ) {
return lock;
}
@@ -1185,22 +1171,6 @@ RTEMS_INLINE_ROUTINE void _Thread_Lock_set_unprotected(
)
{
the_thread->Lock.current = new_lock;
-
- /*
- * The generation release corresponds to the generation acquire in
- * _Thread_Lock_acquire() and ensures that the new lock and other fields are
- * visible to the next thread lock owner. Otherwise someone would be able to
- * read an up to date generation number and an old lock. See
- * _Thread_Wait_set_queue() and _Thread_Wait_restore_default_operations().
- *
- * Since we set a new lock right before, this increment is not protected by a
- * lock and thus must be an atomic operation.
- */
- _Atomic_Fetch_add_uint(
- &the_thread->Lock.generation,
- 1,
- ATOMIC_ORDER_RELEASE
- );
}
#endif
More information about the vc
mailing list