source: rtems/cpukit/include/rtems/score/priorityimpl.h @ 450c170

Last change on this file since 450c170 was 450c170, checked in by Sebastian Huber <sebastian.huber@…>, on 01/28/21 at 10:35:18

score: Add comments and asserts for clarification

This fix relates to a Coverity issue (NULL_RETURNS).

  • Property mode set to 100644
File size: 20.0 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSScorePriority
5 *
6 * @brief This header file provides interfaces of the
7 *   @ref RTEMSScorePriority which are only used by the implementation.
8 */
9
10/*
11 * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
12 *
13 *  embedded brains GmbH
14 *  Dornierstr. 4
15 *  82178 Puchheim
16 *  Germany
17 *  <rtems@embedded-brains.de>
18 *
19 * The license and distribution terms for this file may be
20 * found in the file LICENSE in this distribution or at
21 * http://www.rtems.org/license/LICENSE.
22 */
23
24#ifndef _RTEMS_SCORE_PRIORITYIMPL_H
25#define _RTEMS_SCORE_PRIORITYIMPL_H
26
27#include <rtems/score/priority.h>
28#include <rtems/score/scheduler.h>
29
30#ifdef __cplusplus
31extern "C" {
32#endif /* __cplusplus */
33
34/**
35 * @addtogroup RTEMSScorePriority
36 *
37 * @{
38 */
39
40/**
41 * @brief Initializes the priority actions empty.
42 *
43 * @param[out] actions The actions to be initialized empty.
44 */
45RTEMS_INLINE_ROUTINE void _Priority_Actions_initialize_empty(
46  Priority_Actions *actions
47)
48{
49  actions->actions = NULL;
50}
51
52/**
53 * @brief Initializes the priority actions with the given information.
54 *
55 * @param[out] actions The actions to be initialized.
56 * @param aggregation The aggregation for the @a actions to be initialized.
57 * @param node The action node for the @a actions to be initialized.
58 * @param type The action type for the @a actions to be initialized.
59 */
60RTEMS_INLINE_ROUTINE void _Priority_Actions_initialize_one(
61  Priority_Actions     *actions,
62  Priority_Aggregation *aggregation,
63  Priority_Node        *node,
64  Priority_Action_type  type
65)
66{
67#if defined(RTEMS_SMP)
68  aggregation->Action.next = NULL;
69#endif
70  aggregation->Action.node = node;
71  aggregation->Action.type = type;
72
73  actions->actions = aggregation;
74}
75
76/**
77 * @brief Checks if the priority actions is empty.
78 *
79 * @param actions The priority actions to check if it is empty.
80 *
81 * @retval true The priority actions @a actions is empty.
82 * @retval false The priority actions @a actions is empty.
83 */
84RTEMS_INLINE_ROUTINE bool _Priority_Actions_is_empty(
85  const Priority_Actions *actions
86)
87{
88  return actions->actions == NULL;
89}
90
91/**
92 * @brief Checks if the priority actions is valid.
93 *
94 * @param aggregation The aggregation of the priority action.
95 *
96 * @retval true The @a aggregation is valid.
97 * @retval false The @a aggregation is not valid.
98 */
99RTEMS_INLINE_ROUTINE bool _Priority_Actions_is_valid(
100  const Priority_Aggregation *aggregation
101)
102{
103#if defined(RTEMS_SMP)
104  return aggregation != NULL;
105#else
106  (void) aggregation;
107  return false;
108#endif
109}
110
111/**
112 * @brief Moves the priority actions' actions.
113 *
114 * @param[in, out] actions The priority actions to move the actions away from.
115 *
116 * @return The former actions of @a actions that were moved.
117 */
118RTEMS_INLINE_ROUTINE Priority_Aggregation *_Priority_Actions_move(
119  Priority_Actions *actions
120)
121{
122  Priority_Aggregation *aggregation;
123
124  aggregation = actions->actions;
125  actions->actions = NULL;
126
127  return aggregation;
128}
129
130/**
131 * @brief Adds actions to the priority actions' actions.
132 *
133 * @param[in, out] actions The priority actions to add actions to.
134 * @param[out] aggregation The actions to add to @a actions.
135 */
136RTEMS_INLINE_ROUTINE void _Priority_Actions_add(
137  Priority_Actions     *actions,
138  Priority_Aggregation *aggregation
139)
140{
141#if defined(RTEMS_SMP)
142  /*
143   * Priority aggregations are only added to action lists, so do not care about
144   * the current next pointer value.
145   */
146  aggregation->Action.next = actions->actions;
147#endif
148  actions->actions = aggregation;
149}
150
151/**
152 * @brief Initializes the priority node to the given priority.
153 *
154 * @param[out] node The priority node to be initialized.
155 * @param priority The priority to initialize @a node to.
156 */
157RTEMS_INLINE_ROUTINE void _Priority_Node_initialize(
158  Priority_Node    *node,
159  Priority_Control  priority
160)
161{
162  node->priority = priority;
163  _RBTree_Initialize_node( &node->Node.RBTree );
164}
165
166/**
167 * @brief Sets the priority of the priority node to the given priority.
168 *
169 * @param[out] node The priority node to set the priority of.
170 * @param priority The new priority for @a node.
171 */
172RTEMS_INLINE_ROUTINE void _Priority_Node_set_priority(
173  Priority_Node    *node,
174  Priority_Control  priority
175)
176{
177  node->priority = priority;
178}
179
180/**
181 * @brief Sets the priority node inactive.
182 *
183 * @param[in, out] node The priority node to set inactive.
184 */
185RTEMS_INLINE_ROUTINE void _Priority_Node_set_inactive(
186  Priority_Node *node
187)
188{
189  _RBTree_Set_off_tree( &node->Node.RBTree );
190}
191
192/**
193 * @brief Checks if the priority node is active.
194 *
195 * @param node The priority node that shall be verified if it is active.
196 *
197 * @retval true The priority node is active.
198 * @retval false The priority node is inactive.
199 */
200RTEMS_INLINE_ROUTINE bool _Priority_Node_is_active(
201  const Priority_Node *node
202)
203{
204  return !_RBTree_Is_node_off_tree( &node->Node.RBTree );
205}
206
207/**
208 * @brief Initializes the priority aggregation empty.
209 *
210 * @param[out] aggregation The priority aggregaton to initialize empty.
211 */
212RTEMS_INLINE_ROUTINE void _Priority_Initialize_empty(
213  Priority_Aggregation *aggregation
214)
215{
216#if defined(RTEMS_DEBUG)
217#if defined(RTEMS_SMP)
218  aggregation->Action.next = NULL;
219#endif
220  aggregation->Action.node = NULL;
221  aggregation->Action.type = PRIORITY_ACTION_INVALID;
222#endif
223  _RBTree_Initialize_node( &aggregation->Node.Node.RBTree );
224  _RBTree_Initialize_empty( &aggregation->Contributors );
225}
226
227/**
228 * @brief Initializes the priority aggregation with the given information.
229 *
230 * @param[out] aggregation The priority aggregaton to initialize.
231 * @param node The priority node to initialize @a aggregation with.
232 */
233RTEMS_INLINE_ROUTINE void _Priority_Initialize_one(
234  Priority_Aggregation *aggregation,
235  Priority_Node        *node
236)
237{
238#if defined(RTEMS_DEBUG)
239#if defined(RTEMS_SMP)
240  aggregation->Action.next = NULL;
241#endif
242  aggregation->Action.node = NULL;
243  aggregation->Action.type = PRIORITY_ACTION_INVALID;
244#endif
245  _Priority_Node_initialize( &aggregation->Node, node->priority );
246  _RBTree_Initialize_one( &aggregation->Contributors, &node->Node.RBTree );
247}
248
249/**
250 * @brief Checks if the priority aggregation is empty.
251 *
252 * @param aggregation The priority aggregation that shall be verified if it is empty.
253 *
254 * @retval true The priority aggregation is empty.
255 * @retval false The priority aggregation is not empty.
256 */
257RTEMS_INLINE_ROUTINE bool _Priority_Is_empty(
258  const Priority_Aggregation *aggregation
259)
260{
261  return _RBTree_Is_empty( &aggregation->Contributors );
262}
263
264/**
265 * @brief Gets the priority aggregation's priority.
266 *
267 * @param aggregation The priority aggregation to get the priority from.
268 *
269 * @return The priority of @a aggregation.
270 */
271RTEMS_INLINE_ROUTINE Priority_Control _Priority_Get_priority(
272  const Priority_Aggregation *aggregation
273)
274{
275  return aggregation->Node.priority;
276}
277
278/**
279 * @brief Gets the priority aggregation's scheduler.
280 *
281 * @param aggregation The priority aggregation to get the scheduler from.
282 *
283 * @return The scheduler of @a aggregation.
284 */
285RTEMS_INLINE_ROUTINE const Scheduler_Control *_Priority_Get_scheduler(
286  const Priority_Aggregation *aggregation
287)
288{
289#if defined(RTEMS_SMP)
290  return aggregation->scheduler;
291#else
292  return &_Scheduler_Table[ 0 ];
293#endif
294}
295
296/**
297 * @brief Gets the minimum node of the priority aggregation
298 *
299 * @param aggregation The priority aggregation to get the minimum node from.
300 *
301 * @return The minimum node of @a aggregation
302 */
303RTEMS_INLINE_ROUTINE Priority_Node *_Priority_Get_minimum_node(
304  const Priority_Aggregation *aggregation
305)
306{
307  return (Priority_Node *) _RBTree_Minimum( &aggregation->Contributors );
308}
309
310/**
311 * @brief Sets the action node of the priority aggregation.
312 *
313 * @param[out] aggregation The priority aggregation to set the action node of.
314 * @param node The new priority node for @a aggregation.
315 */
316RTEMS_INLINE_ROUTINE void _Priority_Set_action_node(
317  Priority_Aggregation *aggregation,
318  Priority_Node        *node
319)
320{
321  aggregation->Action.node = node;
322}
323
324/**
325 * @brief Sets the action type of the priority aggregation.
326 *
327 * @param[out] aggregation The priority aggregation to set the action type of.
328 * @param type The new action type for @a aggregation.
329 */
330RTEMS_INLINE_ROUTINE void _Priority_Set_action_type(
331  Priority_Aggregation *aggregation,
332  Priority_Action_type  type
333)
334{
335  aggregation->Action.type = type;
336}
337
338/**
339 * @brief Sets the action type and action node of the priority aggregation.
340 *
341 * @param[out] aggregation The priority aggregation to set the action type
342 *      and action node of.
343 * @param node The new action node for @a aggregation.
344 * @param type The new action type for @a aggregation.
345 */
346RTEMS_INLINE_ROUTINE void _Priority_Set_action(
347  Priority_Aggregation *aggregation,
348  Priority_Node        *node,
349  Priority_Action_type  type
350)
351{
352  aggregation->Action.node = node;
353  aggregation->Action.type = type;
354}
355
356/**
357 * @brief Gets the next action of the priority aggregation.
358 *
359 * @param aggregation The priority aggregation to get the next action of.
360 *
361 * @retval next_action The next action of @a aggregation if RTEMS_SMP is defined.
362 * @retval NULL RTEMS_SMP is not defined.
363 */
364RTEMS_INLINE_ROUTINE Priority_Aggregation *_Priority_Get_next_action(
365  const Priority_Aggregation *aggregation
366)
367{
368#if defined(RTEMS_SMP)
369  return aggregation->Action.next;
370#else
371  (void) aggregation;
372  return NULL;
373#endif
374}
375
376/**
377 * @brief Compares two priorities.
378 *
379 * @param left The priority control on the left hand side of the comparison.
380 * @param right THe RBTree_Node to get the priority for the comparison from.
381 *
382 * @retval true The priority on the left hand side of the comparison is smaller.
383 * @retval false The priority on the left hand side of the comparison is greater of equal.
384 */
385RTEMS_INLINE_ROUTINE bool _Priority_Less(
386  const void        *left,
387  const RBTree_Node *right
388)
389{
390  const Priority_Control *the_left;
391  const Priority_Node    *the_right;
392
393  the_left = left;
394  the_right = RTEMS_CONTAINER_OF( right, Priority_Node, Node.RBTree );
395
396  return *the_left < the_right->priority;
397}
398
399/**
400 * @brief Inserts the node with the given priority into the
401 *      priority aggregation's contributors.
402 *
403 * This method does not handle the case that @a node was the minimal node.
404 *
405 * @param[in, out] aggregation The aggregation to insert the node in its contributors.
406 * @param[in] node The node to insert in the contributors.
407 * @param priority The priority control for the inserted node.
408 *
409 * @retval true The inserted node with its priority is the minimum of the RBTree.
410 * @retval false The inserted node with its priority is not the minimum of the RBTree.
411 */
412RTEMS_INLINE_ROUTINE bool _Priority_Plain_insert(
413  Priority_Aggregation *aggregation,
414  Priority_Node        *node,
415  Priority_Control      priority
416)
417{
418  return _RBTree_Insert_inline(
419    &aggregation->Contributors,
420    &node->Node.RBTree,
421    &priority,
422    _Priority_Less
423  );
424}
425
426/**
427 * @brief Extracts the priority node from the aggregation.
428 *
429 * This method does not handle the case that @a node was the minimal node.
430 *
431 * @param[in,  out] aggregation The aggregation to extract the node from.
432 * @param node The node to be extracted.
433 */
434RTEMS_INLINE_ROUTINE void _Priority_Plain_extract(
435  Priority_Aggregation *aggregation,
436  Priority_Node        *node
437)
438{
439  _RBTree_Extract( &aggregation->Contributors, &node->Node.RBTree );
440}
441
442/**
443 * @brief Updates the priority of the node in the aggregation.
444 *
445 * It first extracts the node and inserts it again, with the new @a node priority as key.
446 *   This method does not handle the case that @a node was the minimal node.
447 *
448 * @param[in, out] aggregation The aggregation to change the node in.
449 * @param node The node that has a new priority and will be reinserted in the aggregation.
450 */
451RTEMS_INLINE_ROUTINE void _Priority_Plain_changed(
452  Priority_Aggregation *aggregation,
453  Priority_Node        *node
454)
455{
456  _Priority_Plain_extract( aggregation, node );
457  _Priority_Plain_insert( aggregation, node, node->priority );
458}
459
460typedef void ( *Priority_Add_handler )(
461  Priority_Aggregation *aggregation,
462  Priority_Actions     *actions,
463  void                 *arg
464);
465
466typedef void ( *Priority_Change_handler )(
467  Priority_Aggregation *aggregation,
468  bool                  prepend_it,
469  Priority_Actions     *actions,
470  void                 *arg
471);
472
473typedef void ( *Priority_Remove_handler )(
474  Priority_Aggregation *aggregation,
475  Priority_Actions     *actions,
476  void                 *arg
477);
478
479/**
480 * @brief Does nothing.
481 *
482 * This method does nothing.
483 *
484 * @param aggregation Is ignored by the method.
485 * @param prepend_it Is ignored by the method.
486 * @param actions Is ignored by the method.
487 * @param arg Is ignored by the method.
488 */
489RTEMS_INLINE_ROUTINE void _Priority_Change_nothing(
490  Priority_Aggregation *aggregation,
491  bool                  prepend_it,
492  Priority_Actions     *actions,
493  void                 *arg
494)
495{
496  (void) aggregation;
497  (void) prepend_it;
498  (void) actions;
499  (void) arg;
500}
501
502/**
503 * @brief Does nothing.
504 *
505 * This method does nothing.
506 *
507 * @param aggregation Is ignored by the method.
508 * @param actions Is ignored by the method.
509 * @param arg Is ignored by the method.
510 */
511RTEMS_INLINE_ROUTINE void _Priority_Remove_nothing(
512  Priority_Aggregation *aggregation,
513  Priority_Actions     *actions,
514  void                 *arg
515)
516{
517  (void) aggregation;
518  (void) actions;
519  (void) arg;
520}
521
522/**
523 * @brief Inserts the node in a nonempty aggregation and handles change if
524 *      the node is the new minimum.
525 *
526 * @param[in, out] aggregation The aggregation to insert the node into.
527 * @param node The node to be inserted.  The node's priority is used as a key.
528 * @param actions Parameter for @a change that is used if the node is the new
529 *      minimum.
530 * @param change The priority change handler that is called in the case that
531 *      the new node is the minimum of the aggregation.
532 * @param arg Arguments for @a change that is used if the node is the new
533 *      minimum.
534 */
535RTEMS_INLINE_ROUTINE void _Priority_Non_empty_insert(
536  Priority_Aggregation    *aggregation,
537  Priority_Node           *node,
538  Priority_Actions        *actions,
539  Priority_Change_handler  change,
540  void                    *arg
541)
542{
543  bool is_new_minimum;
544
545  _Assert( !_Priority_Is_empty( aggregation ) );
546  is_new_minimum = _Priority_Plain_insert( aggregation, node, node->priority );
547
548  if ( is_new_minimum ) {
549    aggregation->Node.priority = node->priority;
550    ( *change )( aggregation, false, actions, arg );
551  }
552}
553
554/**
555 * @brief
556 *
557 * @param[in, out] aggregation The aggregation to insert the node in.
558 * @param node The node to be inserted.  The node's priority is used as key.
559 * @param actions Priority actions for the case that the aggregation was empty before
560 *      the insert or the node is the new minimum.
561 * @param add Is called in the case that @a aggregation was empty before the insert.
562 * @param change Is called in the case that @a aggregation was nonempty before the
563 *      insert and @a node is the new minimum of the aggregation.
564 * @param arg The arguments for @a change.
565 */
566RTEMS_INLINE_ROUTINE void _Priority_Insert(
567  Priority_Aggregation    *aggregation,
568  Priority_Node           *node,
569  Priority_Actions        *actions,
570  Priority_Add_handler     add,
571  Priority_Change_handler  change,
572  void                    *arg
573)
574{
575  if ( _Priority_Is_empty( aggregation ) ) {
576    _Priority_Initialize_one( aggregation, node );
577    ( *add )( aggregation, actions, arg );
578  } else {
579    _Priority_Non_empty_insert( aggregation, node, actions, change, arg );
580  }
581}
582
583/**
584 * @brief Extracts the node from the aggregation.
585 *
586 * This method extracts the node from the aggregation and handles the
587 * cases that @a aggregation is empty after the extraction, or that
588 * @a node was the minimal node in @a aggregation by calling remove (if
589 * empty) or change (if @a node was the minimal node).
590 *
591 * @param[in, out] aggregation The aggregation to extract the @a node from.
592 * @param node The node to extract from @a aggregation.
593 * @param actions The actions for the cases that the aggregation is empty
594 *      after the extraction, or the minimal node was extracted.
595 * @param remove Is called in the case that the aggregation is empty after
596 *      the extraction.
597 * @param change Is called in the case that the minimal node was extracted.
598 * @param arg The arguments for @a remove and @a change.
599 */
600RTEMS_INLINE_ROUTINE void _Priority_Extract(
601  Priority_Aggregation    *aggregation,
602  Priority_Node           *node,
603  Priority_Actions        *actions,
604  Priority_Remove_handler  remove,
605  Priority_Change_handler  change,
606  void                    *arg
607)
608{
609  _Priority_Plain_extract( aggregation, node );
610
611  if ( _Priority_Is_empty( aggregation ) ) {
612    ( *remove )( aggregation, actions, arg );
613  } else {
614    Priority_Node *min;
615
616    /* The aggregation is non-empty, so the minimum node exists. */
617    min = _Priority_Get_minimum_node( aggregation );
618    _Assert( min != NULL );
619
620    if ( node->priority < min->priority ) {
621      aggregation->Node.priority = min->priority;
622      ( *change )( aggregation, true, actions, arg );
623    }
624  }
625}
626
627/**
628 * @brief Extracts the node from the aggregation.
629 *
630 * This method extracts the node from the aggregation and handles the
631 * case that @a node was the minimal node in @a aggregation by calling
632 * change (if @a node was the minimal node).
633 *
634 * @param[in, out] aggregation The aggregation to extract the @a node from.
635 * @param node The node to extract from @a aggregation.
636 * @param actions The actions for the case that the minimal node was extracted.
637 * @param change Is called in the case that the minimal node was extracted.
638 * @param arg The arguments for @a change.
639 */
640RTEMS_INLINE_ROUTINE void _Priority_Extract_non_empty(
641  Priority_Aggregation    *aggregation,
642  Priority_Node           *node,
643  Priority_Actions        *actions,
644  Priority_Change_handler  change,
645  void                    *arg
646)
647{
648  Priority_Node *min;
649
650  _Priority_Plain_extract( aggregation, node );
651  _Assert( !_Priority_Is_empty( aggregation ) );
652
653  min = _Priority_Get_minimum_node( aggregation );
654
655  if ( node->priority < min->priority ) {
656    aggregation->Node.priority = min->priority;
657    ( *change )( aggregation, true, actions, arg );
658  }
659}
660
661/**
662 * @brief Updates the priority of the node in the aggregation.
663 *
664 * This method handles the case that @a node was the minimal node in
665 * @a aggregation.
666 *
667 * @param[in, out] aggregation The aggregation to change the node in.
668 * @param node The node that has a new priority and will be reinserted in the aggregation.
669 * @param prepend_it Indicates whether @a change should prepend if the minimal priority is
670 *      incorrectly set after the change.
671 * @param actions The actions for the case that the minimal priority is incorrectly set
672 *      after the change.
673 * @param change Is called if the minimal priority is incorrectly set after the change.
674 * @param arg The arguments for @a change.
675 */
676RTEMS_INLINE_ROUTINE void _Priority_Changed(
677  Priority_Aggregation    *aggregation,
678  Priority_Node           *node,
679  bool                     prepend_it,
680  Priority_Actions        *actions,
681  Priority_Change_handler  change,
682  void                    *arg
683)
684{
685  Priority_Node *min;
686
687  _Priority_Plain_changed( aggregation, node );
688
689  /*
690   * There is at least the changed node in the aggregation, so the minimum node
691   * exists.
692   */
693  min = _Priority_Get_minimum_node( aggregation );
694  _Assert( min != NULL );
695
696  if ( min->priority != aggregation->Node.priority ) {
697    aggregation->Node.priority = min->priority;
698    ( *change )( aggregation, prepend_it, actions, arg );
699  }
700}
701
702/**
703 * @brief Replaces one node by another.
704 *
705 * The new node has the priority of the old node.
706 *
707 * @param[in, out] aggregation The aggregation to replace @a victim by @a replacement in.
708 * @param victim The node that will be replaced.
709 * @param[out] replacement The node that replaces @a victim.  It obtains its priority
710 *      from @a victim.
711 */
712RTEMS_INLINE_ROUTINE void _Priority_Replace(
713  Priority_Aggregation *aggregation,
714  Priority_Node        *victim,
715  Priority_Node        *replacement
716)
717{
718  replacement->priority = victim->priority;
719  _RBTree_Replace_node(
720    &aggregation->Contributors,
721    &victim->Node.RBTree,
722    &replacement->Node.RBTree
723  );
724}
725
726/** @} */
727
728#ifdef __cplusplus
729}
730#endif /* __cplusplus */
731
732#endif /* _RTEMS_SCORE_PRIORITYIMPL_H */
Note: See TracBrowser for help on using the repository browser.