source: rtems/cpukit/score/src/threadtimeout.c @ b84a51c

Last change on this file since b84a51c was b84a51c, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 10, 2015 at 4:23:12 PM

score: Fix race condition on SMP

We must ensure that the Thread_Control::Wait information update is
visible to the target thread before we update its wait flags, otherwise
we may return out of date events or a wrong status.

  • Property mode set to 100644
File size: 2.3 KB
Line 
1/**
2 * @file
3 *
4 * @brief Thread Wait Timeout
5 *
6 * @ingroup ScoreThread
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2008.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#if HAVE_CONFIG_H
19  #include "config.h"
20#endif
21
22#include <rtems/score/threadimpl.h>
23
24static void _Thread_Do_timeout( Thread_Control *the_thread )
25{
26  the_thread->Wait.return_code = the_thread->Wait.timeout_code;
27  ( *the_thread->Wait.operations->extract )(
28    the_thread->Wait.queue,
29    the_thread
30  );
31  _Thread_Wait_set_queue( the_thread, NULL );
32  _Thread_Wait_restore_default_operations( the_thread );
33  _Thread_Lock_restore_default( the_thread );
34}
35
36void _Thread_Timeout( Objects_Id id, void *arg )
37{
38  Thread_Control    *the_thread;
39  void              *thread_lock;
40  ISR_lock_Context   lock_context;
41  Thread_Wait_flags  wait_flags;
42  bool               unblock;
43
44  the_thread = arg;
45  thread_lock = _Thread_Lock_acquire( the_thread, &lock_context );
46
47  wait_flags = _Thread_Wait_flags_get( the_thread );
48
49  if ( ( wait_flags & THREAD_WAIT_STATE_READY_AGAIN ) == 0 ) {
50    Thread_Wait_flags wait_class;
51    Thread_Wait_flags ready_again;
52    bool              success;
53
54    _Thread_Do_timeout( the_thread );
55
56    /*
57     * This fence is only necessary for the events, see _Event_Seize().  The
58     * thread queues use the thread lock for synchronization.
59     */
60    _Atomic_Fence( ATOMIC_ORDER_RELEASE );
61
62    wait_class = wait_flags & THREAD_WAIT_CLASS_MASK;
63    ready_again = wait_class | THREAD_WAIT_STATE_READY_AGAIN;
64    success = _Thread_Wait_flags_try_change_critical(
65      the_thread,
66      wait_class | THREAD_WAIT_STATE_INTEND_TO_BLOCK,
67      ready_again
68    );
69
70    if ( success ) {
71      unblock = false;
72    } else {
73      _Assert(
74        _Thread_Wait_flags_get( the_thread )
75          == wait_class | THREAD_WAIT_STATE_BLOCKED
76      );
77      _Thread_Wait_flags_set( the_thread, ready_again );
78      unblock = true;
79    }
80  } else {
81    unblock = false;
82  }
83
84  _Thread_Lock_release( thread_lock, &lock_context );
85
86  if ( unblock ) {
87    _Thread_Unblock( the_thread );
88
89#if defined(RTEMS_MULTIPROCESSING)
90    if ( !_Objects_Is_local_id( the_thread->Object.id ) ) {
91      _Thread_MP_Free_proxy( the_thread );
92    }
93#endif
94  }
95}
Note: See TracBrowser for help on using the repository browser.