Changeset c6556e2 in rtems


Ignore:
Timestamp:
Jun 1, 2016, 12:38:05 PM (3 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
23213135
Parents:
f807b84
git-author:
Sebastian Huber <sebastian.huber@…> (06/01/16 12:38:05)
git-committer:
Sebastian Huber <sebastian.huber@…> (06/02/16 05:43:15)
Message:

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).

Location:
cpukit/score/include/rtems/score
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • cpukit/score/include/rtems/score/thread.h

    rf807b84 rc6556e2  
    692692  SMP_lock_Stats Stats;
    693693#endif
    694 
    695   /**
    696    * @brief Generation number to invalidate stale locks.
    697    */
    698   Atomic_Uint generation;
    699694} Thread_Lock_control;
    700695#endif
  • cpukit/score/include/rtems/score/threadimpl.h

    rf807b84 rc6556e2  
    11291129
    11301130  while ( true ) {
    1131     unsigned int my_generation;
    1132     bool         success;
    1133 
    11341131    _ISR_lock_ISR_disable( lock_context );
    11351132
    11361133    /*
    1137      * Ensure that we read our lock generation before we obtain our
    1138      * current lock.  See _Thread_Lock_set_unprotected().
     1134     * We assume that a normal load of pointer is identical to a relaxed atomic
     1135     * load.  Here, we may read an out-of-date lock.  However, only the owner
     1136     * of this out-of-date lock is allowed to set a new one.  Thus, we read at
     1137     * least this new lock ...
    11391138     */
    1140     my_generation = _Atomic_Load_uint(
    1141       &the_thread->Lock.generation,
    1142       ATOMIC_ORDER_ACQUIRE
    1143     );
    1144 
    11451139    lock = the_thread->Lock.current;
     1140
    11461141    _SMP_ticket_lock_Acquire(
    11471142      lock,
     
    11511146
    11521147    /*
    1153      * We must use a read-modify-write operation to observe the last value
    1154      * written.
     1148     * ... here, and so on.
    11551149     */
    1156     success = _Atomic_Compare_exchange_uint(
    1157       &the_thread->Lock.generation,
    1158       &my_generation,
    1159       my_generation,
    1160       ATOMIC_ORDER_RELAXED,
    1161       ATOMIC_ORDER_RELAXED
    1162     );
    1163 
    1164     if ( success ) {
     1150    if ( lock == the_thread->Lock.current ) {
    11651151      return lock;
    11661152    }
     
    11861172{
    11871173  the_thread->Lock.current = new_lock;
    1188 
    1189   /*
    1190    * The generation release corresponds to the generation acquire in
    1191    * _Thread_Lock_acquire() and ensures that the new lock and other fields are
    1192    * visible to the next thread lock owner.  Otherwise someone would be able to
    1193    * read an up to date generation number and an old lock.  See
    1194    * _Thread_Wait_set_queue() and _Thread_Wait_restore_default_operations().
    1195    *
    1196    * Since we set a new lock right before, this increment is not protected by a
    1197    * lock and thus must be an atomic operation.
    1198    */
    1199   _Atomic_Fetch_add_uint(
    1200     &the_thread->Lock.generation,
    1201     1,
    1202     ATOMIC_ORDER_RELEASE
    1203   );
    12041174}
    12051175#endif
Note: See TracChangeset for help on using the changeset viewer.