source: rtems/cpukit/score/src/threadqops.c @ 8a040fe4

5
Last change on this file since 8a040fe4 was 8a040fe4, checked in by Sebastian Huber <sebastian.huber@…>, on 05/19/16 at 15:03:31

score: Use _RBTree_Insert_inline()

Use _RBTree_Insert_inline() for priority thread queues.

Update #2556.

  • Property mode set to 100644
File size: 8.2 KB
Line 
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>
20#include <rtems/score/assert.h>
21#include <rtems/score/chainimpl.h>
22#include <rtems/score/rbtreeimpl.h>
23#include <rtems/score/schedulerimpl.h>
24
25static void _Thread_queue_Do_nothing_priority_change(
26  Thread_Control     *the_thread,
27  Priority_Control    new_priority,
28  Thread_queue_Queue *queue
29)
30{
31  /* Do nothing */
32}
33
34static void _Thread_queue_Do_nothing_extract(
35  Thread_queue_Queue *queue,
36  Thread_Control    *the_thread
37)
38{
39  /* Do nothing */
40}
41
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 * )
47)
48{
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 );
65}
66
67static void _Thread_queue_Queue_extract(
68  Thread_queue_Queue *queue,
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,
99  Thread_Control     *the_thread
100)
101{
102  _Chain_Append_unprotected(
103    &heads->Heads.Fifo,
104    &the_thread->Wait.Node.Chain
105  );
106}
107
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
129static void _Thread_queue_FIFO_extract(
130  Thread_queue_Queue *queue,
131  Thread_Control     *the_thread
132)
133{
134  _Thread_queue_Queue_extract(
135    queue,
136    the_thread,
137    _Thread_queue_FIFO_do_extract
138  );
139}
140
141static Thread_Control *_Thread_queue_FIFO_first(
142  Thread_queue_Heads *heads
143)
144{
145  Chain_Control *fifo = &heads->Heads.Fifo;
146  Chain_Node    *first;
147
148  _Assert( !_Chain_Is_empty( fifo ) );
149  first = _Chain_First( fifo );
150
151  return THREAD_CHAIN_NODE_TO_THREAD( first );
152}
153
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
170static bool _Thread_queue_Priority_less(
171  const void        *left,
172  const RBTree_Node *right
173)
174{
175  const Priority_Control *the_left;
176  const Thread_Control   *the_right;
177
178  the_left = left;
179  the_right = THREAD_RBTREE_NODE_TO_THREAD( right );
180
181  return *the_left < the_right->current_priority;
182}
183
184static void _Thread_queue_Priority_priority_change(
185  Thread_Control     *the_thread,
186  Priority_Control    new_priority,
187  Thread_queue_Queue *queue
188)
189{
190  Thread_queue_Heads          *heads = queue->heads;
191  Thread_queue_Priority_queue *priority_queue;
192
193  _Assert( heads != NULL );
194
195  priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
196
197  _RBTree_Extract(
198    &priority_queue->Queue,
199    &the_thread->Wait.Node.RBTree
200  );
201  _RBTree_Insert_inline(
202    &priority_queue->Queue,
203    &the_thread->Wait.Node.RBTree,
204    &new_priority,
205    _Thread_queue_Priority_less
206  );
207}
208
209static void _Thread_queue_Priority_do_initialize(
210  Thread_queue_Heads *heads
211)
212{
213#if defined(RTEMS_SMP)
214  _Chain_Initialize_empty( &heads->Heads.Fifo );
215#else
216  _RBTree_Initialize_empty( &heads->Heads.Priority.Queue );
217#endif
218}
219
220static void _Thread_queue_Priority_do_enqueue(
221  Thread_queue_Heads *heads,
222  Thread_Control     *the_thread
223)
224{
225  Thread_queue_Priority_queue *priority_queue =
226    _Thread_queue_Priority_queue( heads, the_thread );
227  Priority_Control current_priority;
228
229#if defined(RTEMS_SMP)
230  if ( _RBTree_Is_empty( &priority_queue->Queue ) ) {
231    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
232  }
233#endif
234
235  current_priority = the_thread->current_priority;
236  _RBTree_Insert_inline(
237    &priority_queue->Queue,
238    &the_thread->Wait.Node.RBTree,
239    &current_priority,
240    _Thread_queue_Priority_less
241  );
242}
243
244static void _Thread_queue_Priority_do_extract(
245  Thread_queue_Heads *heads,
246  Thread_Control     *the_thread
247)
248{
249  Thread_queue_Priority_queue *priority_queue =
250    _Thread_queue_Priority_queue( heads, the_thread );
251
252  _RBTree_Extract(
253    &priority_queue->Queue,
254    &the_thread->Wait.Node.RBTree
255  );
256
257#if defined(RTEMS_SMP)
258  _Chain_Extract_unprotected( &priority_queue->Node );
259
260  if ( !_RBTree_Is_empty( &priority_queue->Queue ) ) {
261    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
262  }
263#endif
264}
265
266static void _Thread_queue_Priority_enqueue(
267  Thread_queue_Queue *queue,
268  Thread_Control     *the_thread
269)
270{
271  _Thread_queue_Queue_enqueue(
272    queue,
273    the_thread,
274    _Thread_queue_Priority_do_initialize,
275    _Thread_queue_Priority_do_enqueue
276  );
277}
278
279static void _Thread_queue_Priority_extract(
280  Thread_queue_Queue *queue,
281  Thread_Control     *the_thread
282)
283{
284  _Thread_queue_Queue_extract(
285    queue,
286    the_thread,
287    _Thread_queue_Priority_do_extract
288  );
289}
290
291static Thread_Control *_Thread_queue_Priority_first(
292  Thread_queue_Heads *heads
293)
294{
295  Thread_queue_Priority_queue *priority_queue;
296  RBTree_Node                 *first;
297
298#if defined(RTEMS_SMP)
299  _Assert( !_Chain_Is_empty( &heads->Heads.Fifo ) );
300  priority_queue = (Thread_queue_Priority_queue *)
301    _Chain_First( &heads->Heads.Fifo );
302#else
303  priority_queue = &heads->Heads.Priority;
304#endif
305
306  _Assert( !_RBTree_Is_empty( &priority_queue->Queue ) );
307  first = _RBTree_Minimum( &priority_queue->Queue );
308
309  return THREAD_RBTREE_NODE_TO_THREAD( first );
310}
311
312#if defined(RTEMS_SMP)
313void _Thread_queue_Boost_priority(
314  Thread_queue_Queue *queue,
315  Thread_Control     *the_thread
316)
317{
318  Thread_queue_Heads *heads = queue->heads;
319
320  if (
321    heads != NULL
322      && (
323        !_Chain_Has_only_one_node( &heads->Heads.Fifo )
324          || _RBTree_Is_empty(
325            &_Thread_queue_Priority_queue( heads, the_thread )->Queue
326          )
327      )
328  ) {
329    _Thread_Raise_priority( the_thread, PRIORITY_PSEUDO_ISR );
330  }
331}
332#endif
333
334const Thread_queue_Operations _Thread_queue_Operations_default = {
335  .priority_change = _Thread_queue_Do_nothing_priority_change,
336  .extract = _Thread_queue_Do_nothing_extract
337  /*
338   * The default operations are only used in _Thread_Change_priority() and
339   * _Thread_Timeout() and don't have a thread queue associated with them, so
340   * the enqueue and first operations are superfluous.
341   */
342};
343
344const Thread_queue_Operations _Thread_queue_Operations_FIFO = {
345  .priority_change = _Thread_queue_Do_nothing_priority_change,
346  .enqueue = _Thread_queue_FIFO_enqueue,
347  .extract = _Thread_queue_FIFO_extract,
348  .first = _Thread_queue_FIFO_first
349};
350
351const Thread_queue_Operations _Thread_queue_Operations_priority = {
352  .priority_change = _Thread_queue_Priority_priority_change,
353  .enqueue = _Thread_queue_Priority_enqueue,
354  .extract = _Thread_queue_Priority_extract,
355  .first = _Thread_queue_Priority_first
356};
Note: See TracBrowser for help on using the repository browser.