RTEMS  5.0.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
priorityimpl.h
1 /*
2  * Copyright (c) 2016 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 #ifndef _RTEMS_SCORE_PRIORITYIMPL_H
16 #define _RTEMS_SCORE_PRIORITYIMPL_H
17 
18 #include <rtems/score/priority.h>
19 #include <rtems/score/scheduler.h>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif /* __cplusplus */
24 
25 RTEMS_INLINE_ROUTINE void _Priority_Actions_initialize_empty(
26  Priority_Actions *actions
27 )
28 {
29  actions->actions = NULL;
30 }
31 
32 RTEMS_INLINE_ROUTINE void _Priority_Actions_initialize_one(
33  Priority_Actions *actions,
34  Priority_Aggregation *aggregation,
35  Priority_Node *node,
37 )
38 {
39 #if defined(RTEMS_SMP)
40  aggregation->Action.next = NULL;
41 #endif
42  aggregation->Action.node = node;
43  aggregation->Action.type = type;
44 
45  actions->actions = aggregation;
46 }
47 
48 RTEMS_INLINE_ROUTINE bool _Priority_Actions_is_empty(
49  const Priority_Actions *actions
50 )
51 {
52  return actions->actions == NULL;
53 }
54 
55 RTEMS_INLINE_ROUTINE bool _Priority_Actions_is_valid(
56  const Priority_Aggregation *aggregation
57 )
58 {
59 #if defined(RTEMS_SMP)
60  return aggregation != NULL;
61 #else
62  (void) aggregation;
63  return false;
64 #endif
65 }
66 
67 RTEMS_INLINE_ROUTINE Priority_Aggregation *_Priority_Actions_move(
68  Priority_Actions *actions
69 )
70 {
71  Priority_Aggregation *aggregation;
72 
73  aggregation = actions->actions;
74  actions->actions = NULL;
75 
76  return aggregation;
77 }
78 
79 RTEMS_INLINE_ROUTINE void _Priority_Actions_add(
80  Priority_Actions *actions,
81  Priority_Aggregation *aggregation
82 )
83 {
84 #if defined(RTEMS_SMP)
85  /*
86  * Priority aggregations are only added to action lists, so do not care about
87  * the current next pointer value.
88  */
89  aggregation->Action.next = actions->actions;
90 #endif
91  actions->actions = aggregation;
92 }
93 
94 RTEMS_INLINE_ROUTINE void _Priority_Node_initialize(
95  Priority_Node *node,
96  Priority_Control priority
97 )
98 {
99  node->priority = priority;
100  _RBTree_Initialize_node( &node->Node.RBTree );
101 }
102 
103 RTEMS_INLINE_ROUTINE void _Priority_Node_set_priority(
104  Priority_Node *node,
105  Priority_Control priority
106 )
107 {
108  node->priority = priority;
109 }
110 
111 RTEMS_INLINE_ROUTINE void _Priority_Node_set_inactive(
112  Priority_Node *node
113 )
114 {
115  _RBTree_Set_off_tree( &node->Node.RBTree );
116 }
117 
118 RTEMS_INLINE_ROUTINE bool _Priority_Node_is_active(
119  const Priority_Node *node
120 )
121 {
122  return !_RBTree_Is_node_off_tree( &node->Node.RBTree );
123 }
124 
125 RTEMS_INLINE_ROUTINE void _Priority_Initialize_empty(
126  Priority_Aggregation *aggregation
127 )
128 {
129 #if defined(RTEMS_DEBUG)
130 #if defined(RTEMS_SMP)
131  aggregation->Action.next = NULL;
132 #endif
133  aggregation->Action.node = NULL;
134  aggregation->Action.type = PRIORITY_ACTION_INVALID;
135 #endif
136  _RBTree_Initialize_node( &aggregation->Node.Node.RBTree );
137  _RBTree_Initialize_empty( &aggregation->Contributors );
138 }
139 
140 RTEMS_INLINE_ROUTINE void _Priority_Initialize_one(
141  Priority_Aggregation *aggregation,
142  Priority_Node *node
143 )
144 {
145 #if defined(RTEMS_DEBUG)
146 #if defined(RTEMS_SMP)
147  aggregation->Action.next = NULL;
148 #endif
149  aggregation->Action.node = NULL;
150  aggregation->Action.type = PRIORITY_ACTION_INVALID;
151 #endif
152  _Priority_Node_initialize( &aggregation->Node, node->priority );
153  _RBTree_Initialize_one( &aggregation->Contributors, &node->Node.RBTree );
154 }
155 
156 RTEMS_INLINE_ROUTINE bool _Priority_Is_empty(
157  const Priority_Aggregation *aggregation
158 )
159 {
160  return _RBTree_Is_empty( &aggregation->Contributors );
161 }
162 
163 RTEMS_INLINE_ROUTINE Priority_Control _Priority_Get_priority(
164  const Priority_Aggregation *aggregation
165 )
166 {
167  return aggregation->Node.priority;
168 }
169 
170 RTEMS_INLINE_ROUTINE const Scheduler_Control *_Priority_Get_scheduler(
171  const Priority_Aggregation *aggregation
172 )
173 {
174 #if defined(RTEMS_SMP)
175  return aggregation->scheduler;
176 #else
177  return &_Scheduler_Table[ 0 ];
178 #endif
179 }
180 
181 RTEMS_INLINE_ROUTINE Priority_Node *_Priority_Get_minimum_node(
182  const Priority_Aggregation *aggregation
183 )
184 {
185  return (Priority_Node *) _RBTree_Minimum( &aggregation->Contributors );
186 }
187 
188 RTEMS_INLINE_ROUTINE void _Priority_Set_action_node(
189  Priority_Aggregation *aggregation,
190  Priority_Node *node
191 )
192 {
193  aggregation->Action.node = node;
194 }
195 
196 RTEMS_INLINE_ROUTINE void _Priority_Set_action_type(
197  Priority_Aggregation *aggregation,
199 )
200 {
201  aggregation->Action.type = type;
202 }
203 
204 RTEMS_INLINE_ROUTINE void _Priority_Set_action(
205  Priority_Aggregation *aggregation,
206  Priority_Node *node,
208 )
209 {
210  aggregation->Action.node = node;
211  aggregation->Action.type = type;
212 }
213 
214 RTEMS_INLINE_ROUTINE Priority_Aggregation *_Priority_Get_next_action(
215  const Priority_Aggregation *aggregation
216 )
217 {
218 #if defined(RTEMS_SMP)
219  return aggregation->Action.next;
220 #else
221  (void) aggregation;
222  return NULL;
223 #endif
224 }
225 
226 RTEMS_INLINE_ROUTINE bool _Priority_Less(
227  const void *left,
228  const RBTree_Node *right
229 )
230 {
231  const Priority_Control *the_left;
232  const Priority_Node *the_right;
233 
234  the_left = left;
235  the_right = RTEMS_CONTAINER_OF( right, Priority_Node, Node.RBTree );
236 
237  return *the_left < the_right->priority;
238 }
239 
240 RTEMS_INLINE_ROUTINE bool _Priority_Plain_insert(
241  Priority_Aggregation *aggregation,
242  Priority_Node *node,
243  Priority_Control priority
244 )
245 {
246  return _RBTree_Insert_inline(
247  &aggregation->Contributors,
248  &node->Node.RBTree,
249  &priority,
250  _Priority_Less
251  );
252 }
253 
254 RTEMS_INLINE_ROUTINE void _Priority_Plain_extract(
255  Priority_Aggregation *aggregation,
256  Priority_Node *node
257 )
258 {
259  _RBTree_Extract( &aggregation->Contributors, &node->Node.RBTree );
260 }
261 
262 RTEMS_INLINE_ROUTINE void _Priority_Plain_changed(
263  Priority_Aggregation *aggregation,
264  Priority_Node *node
265 )
266 {
267  _Priority_Plain_extract( aggregation, node );
268  _Priority_Plain_insert( aggregation, node, node->priority );
269 }
270 
271 typedef void ( *Priority_Add_handler )(
272  Priority_Aggregation *aggregation,
273  Priority_Actions *actions,
274  void *arg
275 );
276 
277 typedef void ( *Priority_Change_handler )(
278  Priority_Aggregation *aggregation,
279  bool prepend_it,
280  Priority_Actions *actions,
281  void *arg
282 );
283 
284 typedef void ( *Priority_Remove_handler )(
285  Priority_Aggregation *aggregation,
286  Priority_Actions *actions,
287  void *arg
288 );
289 
290 RTEMS_INLINE_ROUTINE void _Priority_Change_nothing(
291  Priority_Aggregation *aggregation,
292  bool prepend_it,
293  Priority_Actions *actions,
294  void *arg
295 )
296 {
297  (void) aggregation;
298  (void) prepend_it;
299  (void) actions;
300  (void) arg;
301 }
302 
303 RTEMS_INLINE_ROUTINE void _Priority_Remove_nothing(
304  Priority_Aggregation *aggregation,
305  Priority_Actions *actions,
306  void *arg
307 )
308 {
309  (void) aggregation;
310  (void) actions;
311  (void) arg;
312 }
313 
314 RTEMS_INLINE_ROUTINE void _Priority_Non_empty_insert(
315  Priority_Aggregation *aggregation,
316  Priority_Node *node,
317  Priority_Actions *actions,
318  Priority_Change_handler change,
319  void *arg
320 )
321 {
322  bool is_new_minimum;
323 
324  _Assert( !_Priority_Is_empty( aggregation ) );
325  is_new_minimum = _Priority_Plain_insert( aggregation, node, node->priority );
326 
327  if ( is_new_minimum ) {
328  aggregation->Node.priority = node->priority;
329  ( *change )( aggregation, false, actions, arg );
330  }
331 }
332 
333 RTEMS_INLINE_ROUTINE void _Priority_Insert(
334  Priority_Aggregation *aggregation,
335  Priority_Node *node,
336  Priority_Actions *actions,
337  Priority_Add_handler add,
338  Priority_Change_handler change,
339  void *arg
340 )
341 {
342  if ( _Priority_Is_empty( aggregation ) ) {
343  _Priority_Initialize_one( aggregation, node );
344  ( *add )( aggregation, actions, arg );
345  } else {
346  _Priority_Non_empty_insert( aggregation, node, actions, change, arg );
347  }
348 }
349 
350 RTEMS_INLINE_ROUTINE void _Priority_Extract(
351  Priority_Aggregation *aggregation,
352  Priority_Node *node,
353  Priority_Actions *actions,
354  Priority_Remove_handler remove,
355  Priority_Change_handler change,
356  void *arg
357 )
358 {
359  _Priority_Plain_extract( aggregation, node );
360 
361  if ( _Priority_Is_empty( aggregation ) ) {
362  ( *remove )( aggregation, actions, arg );
363  } else {
364  Priority_Node *min;
365 
366  min = _Priority_Get_minimum_node( aggregation );
367 
368  if ( node->priority < min->priority ) {
369  aggregation->Node.priority = min->priority;
370  ( *change )( aggregation, true, actions, arg );
371  }
372  }
373 }
374 
375 RTEMS_INLINE_ROUTINE void _Priority_Extract_non_empty(
376  Priority_Aggregation *aggregation,
377  Priority_Node *node,
378  Priority_Actions *actions,
379  Priority_Change_handler change,
380  void *arg
381 )
382 {
383  Priority_Node *min;
384 
385  _Priority_Plain_extract( aggregation, node );
386  _Assert( !_Priority_Is_empty( aggregation ) );
387 
388  min = _Priority_Get_minimum_node( aggregation );
389 
390  if ( node->priority < min->priority ) {
391  aggregation->Node.priority = min->priority;
392  ( *change )( aggregation, true, actions, arg );
393  }
394 }
395 
396 RTEMS_INLINE_ROUTINE void _Priority_Changed(
397  Priority_Aggregation *aggregation,
398  Priority_Node *node,
399  bool prepend_it,
400  Priority_Actions *actions,
401  Priority_Change_handler change,
402  void *arg
403 )
404 {
405  Priority_Node *min;
406 
407  _Priority_Plain_changed( aggregation, node );
408 
409  min = _Priority_Get_minimum_node( aggregation );
410 
411  if ( min->priority != aggregation->Node.priority ) {
412  aggregation->Node.priority = min->priority;
413  ( *change )( aggregation, prepend_it, actions, arg );
414  }
415 }
416 
417 RTEMS_INLINE_ROUTINE void _Priority_Replace(
418  Priority_Aggregation *aggregation,
419  Priority_Node *victim,
420  Priority_Node *replacement
421 )
422 {
423  replacement->priority = victim->priority;
425  &aggregation->Contributors,
426  &victim->Node.RBTree,
427  &replacement->Node.RBTree
428  );
429 }
430 
431 #ifdef __cplusplus
432 }
433 #endif /* __cplusplus */
434 
435 #endif /* _RTEMS_SCORE_PRIORITYIMPL_H */
RTEMS_INLINE_ROUTINE bool _RBTree_Insert_inline(RBTree_Control *the_rbtree, RBTree_Node *the_node, const void *key, bool(*less)(const void *, const RBTree_Node *))
Inserts the node into the red-black tree.
Definition: rbtree.h:483
RTEMS_INLINE_ROUTINE bool _RBTree_Is_empty(const RBTree_Control *the_rbtree)
Is the RBTree empty.
Definition: rbtree.h:353
RTEMS_INLINE_ROUTINE void _RBTree_Initialize_one(RBTree_Control *the_rbtree, RBTree_Node *the_node)
Initializes this red-black tree to contain exactly the specified node.
Definition: rbtree.h:401
The priority aggregation.
Definition: priority.h:129
union Priority_Node::@3974 Node
Node component for a chain or red-black tree.
The priority node to build up a priority aggregation.
Definition: priority.h:94
#define RTEMS_INLINE_ROUTINE
Definition: basedefs.h:65
Priority_Action_type
The priority action type.
Definition: priority.h:112
A list of priority actions.
Definition: priority.h:189
void _RBTree_Replace_node(RBTree_Control *the_rbtree, RBTree_Node *victim, RBTree_Node *replacement)
Replaces a node in the red-black tree without a rebalance.
Definition: rbtreereplace.c:29
Priority_Control priority
The priority value of this node.
Definition: priority.h:106
Red-black tree node.
Definition: rbtree.h:50
uint64_t Priority_Control
The thread priority control.
Definition: priority.h:66
RTEMS_INLINE_ROUTINE void _RBTree_Initialize_node(RBTree_Node *the_node)
Initializes a red-black tree node.
Definition: rbtree.h:125
Priority_Action_type type
The type of the action.
Definition: priority.h:178
RBTree_Control Contributors
A red-black tree to contain priority nodes contributing to the overall priority of this priority aggr...
Definition: priority.h:149
Priority Handler API.
Priority_Node Node
This priority node reflects the overall priority of the aggregation.
Definition: priority.h:143
RTEMS_INLINE_ROUTINE bool _RBTree_Is_node_off_tree(const RBTree_Node *the_node)
Returns true, if this red-black tree node is off-tree, and false otherwise.
Definition: rbtree.h:99
RTEMS_INLINE_ROUTINE void _RBTree_Set_off_tree(RBTree_Node *the_node)
Sets a red-black tree node as off-tree.
Definition: rbtree.h:83
RBTree_Node * _RBTree_Minimum(const RBTree_Control *the_rbtree)
Returns the minimum node of the red-black tree.
Definition: rbtreenext.c:36
Scheduler control.
Definition: scheduler.h:266
const Scheduler_Control _Scheduler_Table[]
Registered schedulers.
void _RBTree_Extract(RBTree_Control *the_rbtree, RBTree_Node *the_node)
Extracts (removes) the node from the red-black tree.
Definition: rbtreeextract.c:35
Priority_Node * node
The priority node of the action.
Definition: priority.h:173
#define RTEMS_CONTAINER_OF(_m, _type, _member_name)
Returns a pointer to the container of a specified member pointer.
Definition: basedefs.h:390
Constants and Structures Associated with the Scheduler.
struct Priority_Aggregation::@3975 Action
A priority action block to manage priority node additions, changes and removals.
RTEMS_INLINE_ROUTINE void _RBTree_Initialize_empty(RBTree_Control *the_rbtree)
Initialize this RBTree as empty.
Definition: rbtree.h:387
#define NULL
Requests a GPIO pin group configuration.
Definition: bestcomm_api.h:77
Priority_Aggregation * actions
The first action of a priority action list.
Definition: priority.h:193