source: rtems/cpukit/score/src/threadqops.c @ dafa5d88

5
Last change on this file since dafa5d88 was dafa5d88, checked in by Sebastian Huber <sebastian.huber@…>, on 09/03/15 at 08:27:16

score: Implement priority boosting

  • Property mode set to 100644
File size: 7.7 KB
RevLine 
[568af83]1/*
2 * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#if HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include <rtems/score/threadimpl.h>
[d7665823]20#include <rtems/score/assert.h>
[383cf42]21#include <rtems/score/chainimpl.h>
[568af83]22#include <rtems/score/rbtreeimpl.h>
[3995e6d]23#include <rtems/score/schedulerimpl.h>
[568af83]24
25static void _Thread_queue_Do_nothing_priority_change(
[e2735012]26  Thread_Control     *the_thread,
27  Priority_Control    new_priority,
28  Thread_queue_Queue *queue
[568af83]29)
30{
31  /* Do nothing */
32}
33
[383cf42]34static void _Thread_queue_Do_nothing_extract(
[e2735012]35  Thread_queue_Queue *queue,
36  Thread_Control    *the_thread
[383cf42]37)
38{
39  /* Do nothing */
40}
41
[d7665823]42static void _Thread_queue_Queue_enqueue(
43  Thread_queue_Queue *queue,
44  Thread_Control     *the_thread,
45  void             ( *initialize )( Thread_queue_Heads * ),
46  void             ( *enqueue )( Thread_queue_Heads *, Thread_Control * )
[383cf42]47)
48{
[d7665823]49  Thread_queue_Heads *heads = queue->heads;
50  Thread_queue_Heads *spare_heads = the_thread->Wait.spare_heads;
51
52  the_thread->Wait.spare_heads = NULL;
53
54  if ( heads == NULL ) {
55    _Assert( spare_heads != NULL );
56    _Assert( _Chain_Is_empty( &spare_heads->Free_chain ) );
57    heads = spare_heads;
58    queue->heads = heads;
59    ( *initialize )( heads );
60  }
61
62  _Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node );
63
64  ( *enqueue )( heads, the_thread );
[383cf42]65}
66
[d7665823]67static void _Thread_queue_Queue_extract(
[e2735012]68  Thread_queue_Queue *queue,
[d7665823]69  Thread_Control     *the_thread,
70  void             ( *extract )( Thread_queue_Heads *, Thread_Control * )
71)
72{
73  Thread_queue_Heads *heads = queue->heads;
74
75  _Assert( heads != NULL );
76
77  the_thread->Wait.spare_heads = RTEMS_CONTAINER_OF(
78    _Chain_Get_first_unprotected( &heads->Free_chain ),
79    Thread_queue_Heads,
80    Free_node
81  );
82
83  if ( _Chain_Is_empty( &heads->Free_chain ) ) {
84    queue->heads = NULL;
85  }
86
87  ( *extract )( heads, the_thread );
88}
89
90static void _Thread_queue_FIFO_do_initialize(
91  Thread_queue_Heads *heads
92)
93{
94  _Chain_Initialize_empty( &heads->Heads.Fifo );
95}
96
97static void _Thread_queue_FIFO_do_enqueue(
98  Thread_queue_Heads *heads,
[e2735012]99  Thread_Control     *the_thread
[383cf42]100)
101{
102  _Chain_Append_unprotected(
[d7665823]103    &heads->Heads.Fifo,
[383cf42]104    &the_thread->Wait.Node.Chain
105  );
106}
107
[d7665823]108static void _Thread_queue_FIFO_do_extract(
109  Thread_queue_Heads *heads,
110  Thread_Control     *the_thread
111)
112{
113  _Chain_Extract_unprotected( &the_thread->Wait.Node.Chain );
114}
115
116static void _Thread_queue_FIFO_enqueue(
117  Thread_queue_Queue *queue,
118  Thread_Control     *the_thread
119)
120{
121  _Thread_queue_Queue_enqueue(
122    queue,
123    the_thread,
124    _Thread_queue_FIFO_do_initialize,
125    _Thread_queue_FIFO_do_enqueue
126  );
127}
128
[383cf42]129static void _Thread_queue_FIFO_extract(
[e2735012]130  Thread_queue_Queue *queue,
131  Thread_Control     *the_thread
[383cf42]132)
133{
[d7665823]134  _Thread_queue_Queue_extract(
135    queue,
136    the_thread,
137    _Thread_queue_FIFO_do_extract
138  );
[383cf42]139}
140
141static Thread_Control *_Thread_queue_FIFO_first(
[d7665823]142  Thread_queue_Heads *heads
[383cf42]143)
144{
[d7665823]145  Chain_Control *fifo = &heads->Heads.Fifo;
[8c25e04]146  Chain_Node    *first;
[383cf42]147
[8c25e04]148  _Assert( !_Chain_Is_empty( fifo ) );
149  first = _Chain_First( fifo );
150
151  return THREAD_CHAIN_NODE_TO_THREAD( first );
[383cf42]152}
153
[3995e6d]154static Thread_queue_Priority_queue *_Thread_queue_Priority_queue(
155  Thread_queue_Heads   *heads,
156  const Thread_Control *the_thread
157)
158{
159#if defined(RTEMS_SMP)
160  return &heads->Priority[
161    _Scheduler_Get_index( _Scheduler_Get_own( the_thread ) )
162  ];
163#else
164  (void) the_thread;
165
166  return &heads->Heads.Priority;
167#endif
168}
169
[568af83]170static void _Thread_queue_Priority_priority_change(
[e2735012]171  Thread_Control     *the_thread,
172  Priority_Control    new_priority,
173  Thread_queue_Queue *queue
[383cf42]174)
175{
[3995e6d]176  Thread_queue_Heads          *heads = queue->heads;
177  Thread_queue_Priority_queue *priority_queue;
[d7665823]178
179  _Assert( heads != NULL );
180
[3995e6d]181  priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
182
[383cf42]183  _RBTree_Extract(
[3995e6d]184    &priority_queue->Queue,
[383cf42]185    &the_thread->Wait.Node.RBTree
186  );
187  _RBTree_Insert(
[3995e6d]188    &priority_queue->Queue,
[383cf42]189    &the_thread->Wait.Node.RBTree,
190    _Thread_queue_Compare_priority,
191    false
192  );
193}
194
[d7665823]195static void _Thread_queue_Priority_do_initialize(
196  Thread_queue_Heads *heads
[383cf42]197)
198{
[3995e6d]199#if defined(RTEMS_SMP)
200  _Chain_Initialize_empty( &heads->Heads.Fifo );
201#else
[d7665823]202  _RBTree_Initialize_empty( &heads->Heads.Priority );
[3995e6d]203#endif
[383cf42]204}
205
[d7665823]206static void _Thread_queue_Priority_do_enqueue(
207  Thread_queue_Heads *heads,
[e2735012]208  Thread_Control     *the_thread
[568af83]209)
210{
[3995e6d]211  Thread_queue_Priority_queue *priority_queue =
212    _Thread_queue_Priority_queue( heads, the_thread );
213
214#if defined(RTEMS_SMP)
215  if ( _RBTree_Is_empty( &priority_queue->Queue ) ) {
216    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
217  }
218#endif
219
[568af83]220  _RBTree_Insert(
[3995e6d]221    &priority_queue->Queue,
[383cf42]222    &the_thread->Wait.Node.RBTree,
[568af83]223    _Thread_queue_Compare_priority,
224    false
225  );
226}
227
[d7665823]228static void _Thread_queue_Priority_do_extract(
229  Thread_queue_Heads *heads,
[e2735012]230  Thread_Control     *the_thread
[383cf42]231)
232{
[3995e6d]233  Thread_queue_Priority_queue *priority_queue =
234    _Thread_queue_Priority_queue( heads, the_thread );
235
[383cf42]236  _RBTree_Extract(
[3995e6d]237    &priority_queue->Queue,
[383cf42]238    &the_thread->Wait.Node.RBTree
239  );
[3995e6d]240
241#if defined(RTEMS_SMP)
242  _Chain_Extract_unprotected( &priority_queue->Node );
243
244  if ( !_RBTree_Is_empty( &priority_queue->Queue ) ) {
245    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
246  }
247#endif
[383cf42]248}
249
[d7665823]250static void _Thread_queue_Priority_enqueue(
251  Thread_queue_Queue *queue,
252  Thread_Control     *the_thread
253)
254{
255  _Thread_queue_Queue_enqueue(
256    queue,
257    the_thread,
258    _Thread_queue_Priority_do_initialize,
259    _Thread_queue_Priority_do_enqueue
260  );
261}
262
263static void _Thread_queue_Priority_extract(
264  Thread_queue_Queue *queue,
265  Thread_Control     *the_thread
266)
267{
268  _Thread_queue_Queue_extract(
269    queue,
270    the_thread,
271    _Thread_queue_Priority_do_extract
272  );
273}
274
[383cf42]275static Thread_Control *_Thread_queue_Priority_first(
[d7665823]276  Thread_queue_Heads *heads
[383cf42]277)
278{
[3995e6d]279  Thread_queue_Priority_queue *priority_queue;
280  RBTree_Node                 *first;
281
282#if defined(RTEMS_SMP)
283  _Assert( !_Chain_Is_empty( &heads->Heads.Fifo ) );
284  priority_queue = (Thread_queue_Priority_queue *)
285    _Chain_First( &heads->Heads.Fifo );
286#else
287  priority_queue = &heads->Heads.Priority;
288#endif
[383cf42]289
[3995e6d]290  _Assert( !_RBTree_Is_empty( &priority_queue->Queue ) );
291  first = _RBTree_Minimum( &priority_queue->Queue );
[383cf42]292
[8c25e04]293  return THREAD_RBTREE_NODE_TO_THREAD( first );
[383cf42]294}
295
[dafa5d88]296#if defined(RTEMS_SMP)
297void _Thread_queue_Boost_priority(
298  Thread_queue_Queue *queue,
299  Thread_Control     *the_thread
300)
301{
302  Thread_queue_Heads *heads = queue->heads;
303
304  if (
305    heads != NULL
306      && (
307        !_Chain_Has_only_one_node( &heads->Heads.Fifo )
308          || _RBTree_Is_empty(
309            &_Thread_queue_Priority_queue( heads, the_thread )->Queue
310          )
311      )
312  ) {
313    _Thread_Raise_priority( the_thread, PRIORITY_PSEUDO_ISR );
314  }
315}
316#endif
317
[568af83]318const Thread_queue_Operations _Thread_queue_Operations_default = {
[383cf42]319  .priority_change = _Thread_queue_Do_nothing_priority_change,
320  .extract = _Thread_queue_Do_nothing_extract
321  /*
322   * The default operations are only used in _Thread_Change_priority() and
323   * _Thread_Timeout() and don't have a thread queue associated with them, so
324   * the enqueue and first operations are superfluous.
325   */
[568af83]326};
327
328const Thread_queue_Operations _Thread_queue_Operations_FIFO = {
[383cf42]329  .priority_change = _Thread_queue_Do_nothing_priority_change,
330  .enqueue = _Thread_queue_FIFO_enqueue,
331  .extract = _Thread_queue_FIFO_extract,
332  .first = _Thread_queue_FIFO_first
[568af83]333};
334
335const Thread_queue_Operations _Thread_queue_Operations_priority = {
[383cf42]336  .priority_change = _Thread_queue_Priority_priority_change,
337  .enqueue = _Thread_queue_Priority_enqueue,
338  .extract = _Thread_queue_Priority_extract,
339  .first = _Thread_queue_Priority_first
[568af83]340};
Note: See TracBrowser for help on using the repository browser.