source: rtems/cpukit/score/src/threadchangepriority.c @ 99fc1d1d

5
Last change on this file since 99fc1d1d was bd12dda, checked in by Sebastian Huber <sebastian.huber@…>, on 05/11/16 at 09:54:49

score: Use thread state lock for current state

In addition protect scheduler of thread by thread state lock. Enables
use of scheduler per-instance locks.

Update #2555.

  • Property mode set to 100644
File size: 3.9 KB
Line 
1/**
2 * @file
3 *
4 * @brief Changes the Priority of a Thread
5 *
6 * @ingroup ScoreThread
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2014.
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#include <rtems/score/schedulerimpl.h>
24
25void _Thread_Change_priority(
26  Thread_Control                *the_thread,
27  Priority_Control               new_priority,
28  void                          *arg,
29  Thread_Change_priority_filter  filter,
30  bool                           prepend_it
31)
32{
33  ISR_lock_Context  lock_context;
34  ISR_lock_Control *lock;
35
36  lock = _Thread_Lock_acquire( the_thread, &lock_context );
37
38  /*
39   * For simplicity set the priority restore hint unconditionally since this is
40   * an average case optimization.  Otherwise complicated atomic operations
41   * would be necessary.  Synchronize with a potential read of the resource
42   * count in the filter function.  See also _CORE_mutex_Surrender(),
43   * _Thread_Set_priority_filter() and _Thread_Restore_priority_filter().
44   */
45  the_thread->priority_restore_hint = true;
46  _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
47
48  /*
49   *  Do not bother recomputing all the priority related information if
50   *  we are not REALLY changing priority.
51   */
52  if ( ( *filter )( the_thread, &new_priority, arg ) ) {
53    uint32_t my_generation;
54
55    my_generation = the_thread->priority_generation + 1;
56    the_thread->current_priority = new_priority;
57    the_thread->priority_generation = my_generation;
58
59    ( *the_thread->Wait.operations->priority_change )(
60      the_thread,
61      new_priority,
62      the_thread->Wait.queue
63    );
64
65    _Thread_Lock_release( lock, &lock_context );
66
67    _Thread_State_acquire( the_thread, &lock_context );
68
69    if ( the_thread->priority_generation == my_generation ) {
70      if ( _States_Is_ready( the_thread->current_state ) ) {
71        _Scheduler_Change_priority(
72          the_thread,
73          new_priority,
74          prepend_it
75        );
76      } else {
77        _Scheduler_Update_priority( the_thread, new_priority );
78      }
79    }
80
81    _Thread_State_release( the_thread, &lock_context );
82  } else {
83    _Thread_Lock_release( lock, &lock_context );
84  }
85}
86
87static bool _Thread_Raise_priority_filter(
88  Thread_Control   *the_thread,
89  Priority_Control *new_priority,
90  void             *arg
91)
92{
93  return _Thread_Priority_less_than(
94    the_thread->current_priority,
95    *new_priority
96  );
97}
98
99void _Thread_Raise_priority(
100  Thread_Control   *the_thread,
101  Priority_Control  new_priority
102)
103{
104  _Thread_Change_priority(
105    the_thread,
106    new_priority,
107    NULL,
108    _Thread_Raise_priority_filter,
109    false
110  );
111}
112
113#if defined(RTEMS_SMP)
114static bool _Thread_Inherit_priority_filter(
115  Thread_Control   *inheritor,
116  Priority_Control *new_priority,
117  void             *arg
118)
119{
120  Thread_Control *ancestor = arg;
121
122  if ( _Scheduler_Get_own( inheritor ) == _Scheduler_Get_own( ancestor ) ) {
123    *new_priority = ancestor->current_priority;
124  }
125
126  return _Thread_Priority_less_than(
127    inheritor->current_priority,
128    *new_priority
129  );
130}
131
132void _Thread_Inherit_priority(
133  Thread_Control *inheritor,
134  Thread_Control *ancestor
135)
136{
137  _Thread_Change_priority(
138    inheritor,
139    PRIORITY_PSEUDO_ISR,
140    ancestor,
141    _Thread_Inherit_priority_filter,
142    false
143  );
144}
145#endif
146
147static bool _Thread_Restore_priority_filter(
148  Thread_Control   *the_thread,
149  Priority_Control *new_priority,
150  void             *arg
151)
152{
153  *new_priority = the_thread->real_priority;
154
155  the_thread->priority_restore_hint = false;
156
157  return *new_priority != the_thread->current_priority;
158}
159
160void _Thread_Restore_priority( Thread_Control *the_thread )
161{
162  _Thread_Change_priority(
163    the_thread,
164    0,
165    NULL,
166    _Thread_Restore_priority_filter,
167    true
168  );
169}
Note: See TracBrowser for help on using the repository browser.