source: rtems/cpukit/include/rtems/score/priorityimpl.h

Last change on this file was 35a07c4, checked in by Andreas Dachsberger <andreas.dachsberger@…>, on Apr 11, 2019 at 6:17:17 AM

doxygen: score: adjust doc in priorityimpl.h to doxygen guidelines

Update #3706.

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