/* * Copyright (c) 2016 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 * 82178 Puchheim * Germany * * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. */ #ifndef _RTEMS_SCORE_PRIORITYIMPL_H #define _RTEMS_SCORE_PRIORITYIMPL_H #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ RTEMS_INLINE_ROUTINE void _Priority_Actions_initialize_empty( Priority_Actions *actions ) { actions->actions = NULL; } RTEMS_INLINE_ROUTINE void _Priority_Actions_initialize_one( Priority_Actions *actions, Priority_Aggregation *aggregation, Priority_Node *node, Priority_Action_type type ) { #if defined(RTEMS_SMP) aggregation->Action.next = NULL; #endif aggregation->Action.node = node; aggregation->Action.type = type; actions->actions = aggregation; } RTEMS_INLINE_ROUTINE bool _Priority_Actions_is_empty( const Priority_Actions *actions ) { return actions->actions == NULL; } RTEMS_INLINE_ROUTINE bool _Priority_Actions_is_valid( const Priority_Aggregation *aggregation ) { #if defined(RTEMS_SMP) return aggregation != NULL; #else (void) aggregation; return false; #endif } RTEMS_INLINE_ROUTINE Priority_Aggregation *_Priority_Actions_move( Priority_Actions *actions ) { Priority_Aggregation *aggregation; aggregation = actions->actions; actions->actions = NULL; return aggregation; } RTEMS_INLINE_ROUTINE void _Priority_Actions_add( Priority_Actions *actions, Priority_Aggregation *aggregation ) { #if defined(RTEMS_SMP) /* * Priority aggregations are only added to action lists, so do not care about * the current next pointer value. */ aggregation->Action.next = actions->actions; #endif actions->actions = aggregation; } RTEMS_INLINE_ROUTINE void _Priority_Node_initialize( Priority_Node *node, Priority_Control priority ) { node->priority = priority; _RBTree_Initialize_node( &node->Node.RBTree ); } RTEMS_INLINE_ROUTINE void _Priority_Node_set_priority( Priority_Node *node, Priority_Control priority ) { node->priority = priority; } RTEMS_INLINE_ROUTINE void _Priority_Node_set_inactive( Priority_Node *node ) { _RBTree_Set_off_tree( &node->Node.RBTree ); } RTEMS_INLINE_ROUTINE bool _Priority_Node_is_active( const Priority_Node *node ) { return !_RBTree_Is_node_off_tree( &node->Node.RBTree ); } RTEMS_INLINE_ROUTINE void _Priority_Initialize_empty( Priority_Aggregation *aggregation ) { #if defined(RTEMS_DEBUG) #if defined(RTEMS_SMP) aggregation->Action.next = NULL; #endif aggregation->Action.node = NULL; aggregation->Action.type = PRIORITY_ACTION_INVALID; #endif _RBTree_Initialize_node( &aggregation->Node.Node.RBTree ); _RBTree_Initialize_empty( &aggregation->Contributors ); } RTEMS_INLINE_ROUTINE void _Priority_Initialize_one( Priority_Aggregation *aggregation, Priority_Node *node ) { #if defined(RTEMS_DEBUG) #if defined(RTEMS_SMP) aggregation->Action.next = NULL; #endif aggregation->Action.node = NULL; aggregation->Action.type = PRIORITY_ACTION_INVALID; #endif _Priority_Node_initialize( &aggregation->Node, node->priority ); _RBTree_Initialize_one( &aggregation->Contributors, &node->Node.RBTree ); } RTEMS_INLINE_ROUTINE bool _Priority_Is_empty( const Priority_Aggregation *aggregation ) { return _RBTree_Is_empty( &aggregation->Contributors ); } RTEMS_INLINE_ROUTINE Priority_Control _Priority_Get_priority( const Priority_Aggregation *aggregation ) { return aggregation->Node.priority; } RTEMS_INLINE_ROUTINE const Scheduler_Control *_Priority_Get_scheduler( const Priority_Aggregation *aggregation ) { #if defined(RTEMS_SMP) return aggregation->scheduler; #else return &_Scheduler_Table[ 0 ]; #endif } RTEMS_INLINE_ROUTINE Priority_Node *_Priority_Get_minimum_node( const Priority_Aggregation *aggregation ) { return (Priority_Node *) _RBTree_Minimum( &aggregation->Contributors ); } RTEMS_INLINE_ROUTINE void _Priority_Set_action_node( Priority_Aggregation *aggregation, Priority_Node *node ) { aggregation->Action.node = node; } RTEMS_INLINE_ROUTINE void _Priority_Set_action_type( Priority_Aggregation *aggregation, Priority_Action_type type ) { aggregation->Action.type = type; } RTEMS_INLINE_ROUTINE void _Priority_Set_action( Priority_Aggregation *aggregation, Priority_Node *node, Priority_Action_type type ) { aggregation->Action.node = node; aggregation->Action.type = type; } RTEMS_INLINE_ROUTINE Priority_Aggregation *_Priority_Get_next_action( const Priority_Aggregation *aggregation ) { #if defined(RTEMS_SMP) return aggregation->Action.next; #else (void) aggregation; return NULL; #endif } RTEMS_INLINE_ROUTINE bool _Priority_Less( const void *left, const RBTree_Node *right ) { const Priority_Control *the_left; const Priority_Node *the_right; the_left = left; the_right = RTEMS_CONTAINER_OF( right, Priority_Node, Node.RBTree ); return *the_left < the_right->priority; } RTEMS_INLINE_ROUTINE bool _Priority_Plain_insert( Priority_Aggregation *aggregation, Priority_Node *node, Priority_Control priority ) { return _RBTree_Insert_inline( &aggregation->Contributors, &node->Node.RBTree, &priority, _Priority_Less ); } RTEMS_INLINE_ROUTINE void _Priority_Plain_extract( Priority_Aggregation *aggregation, Priority_Node *node ) { _RBTree_Extract( &aggregation->Contributors, &node->Node.RBTree ); } RTEMS_INLINE_ROUTINE void _Priority_Plain_changed( Priority_Aggregation *aggregation, Priority_Node *node ) { _Priority_Plain_extract( aggregation, node ); _Priority_Plain_insert( aggregation, node, node->priority ); } typedef void ( *Priority_Add_handler )( Priority_Aggregation *aggregation, Priority_Actions *actions, void *arg ); typedef void ( *Priority_Change_handler )( Priority_Aggregation *aggregation, bool prepend_it, Priority_Actions *actions, void *arg ); typedef void ( *Priority_Remove_handler )( Priority_Aggregation *aggregation, Priority_Actions *actions, void *arg ); RTEMS_INLINE_ROUTINE void _Priority_Change_nothing( Priority_Aggregation *aggregation, bool prepend_it, Priority_Actions *actions, void *arg ) { (void) aggregation; (void) prepend_it; (void) actions; (void) arg; } RTEMS_INLINE_ROUTINE void _Priority_Remove_nothing( Priority_Aggregation *aggregation, Priority_Actions *actions, void *arg ) { (void) aggregation; (void) actions; (void) arg; } RTEMS_INLINE_ROUTINE void _Priority_Non_empty_insert( Priority_Aggregation *aggregation, Priority_Node *node, Priority_Actions *actions, Priority_Change_handler change, void *arg ) { bool is_new_minimum; _Assert( !_Priority_Is_empty( aggregation ) ); is_new_minimum = _Priority_Plain_insert( aggregation, node, node->priority ); if ( is_new_minimum ) { aggregation->Node.priority = node->priority; ( *change )( aggregation, false, actions, arg ); } } RTEMS_INLINE_ROUTINE void _Priority_Insert( Priority_Aggregation *aggregation, Priority_Node *node, Priority_Actions *actions, Priority_Add_handler add, Priority_Change_handler change, void *arg ) { if ( _Priority_Is_empty( aggregation ) ) { _Priority_Initialize_one( aggregation, node ); ( *add )( aggregation, actions, arg ); } else { _Priority_Non_empty_insert( aggregation, node, actions, change, arg ); } } RTEMS_INLINE_ROUTINE void _Priority_Extract( Priority_Aggregation *aggregation, Priority_Node *node, Priority_Actions *actions, Priority_Remove_handler remove, Priority_Change_handler change, void *arg ) { _Priority_Plain_extract( aggregation, node ); if ( _Priority_Is_empty( aggregation ) ) { ( *remove )( aggregation, actions, arg ); } else { Priority_Node *min; min = _Priority_Get_minimum_node( aggregation ); if ( node->priority < min->priority ) { aggregation->Node.priority = min->priority; ( *change )( aggregation, true, actions, arg ); } } } RTEMS_INLINE_ROUTINE void _Priority_Extract_non_empty( Priority_Aggregation *aggregation, Priority_Node *node, Priority_Actions *actions, Priority_Change_handler change, void *arg ) { Priority_Node *min; _Priority_Plain_extract( aggregation, node ); _Assert( !_Priority_Is_empty( aggregation ) ); min = _Priority_Get_minimum_node( aggregation ); if ( node->priority < min->priority ) { aggregation->Node.priority = min->priority; ( *change )( aggregation, true, actions, arg ); } } RTEMS_INLINE_ROUTINE void _Priority_Changed( Priority_Aggregation *aggregation, Priority_Node *node, bool prepend_it, Priority_Actions *actions, Priority_Change_handler change, void *arg ) { Priority_Node *min; _Priority_Plain_changed( aggregation, node ); min = _Priority_Get_minimum_node( aggregation ); if ( min->priority != aggregation->Node.priority ) { aggregation->Node.priority = min->priority; ( *change )( aggregation, prepend_it, actions, arg ); } } RTEMS_INLINE_ROUTINE void _Priority_Replace( Priority_Aggregation *aggregation, Priority_Node *victim, Priority_Node *replacement ) { replacement->priority = victim->priority; _RBTree_Replace_node( &aggregation->Contributors, &victim->Node.RBTree, &replacement->Node.RBTree ); } #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* _RTEMS_SCORE_PRIORITYIMPL_H */