From 1215fd4d9426a59d568560e9a485628560363133 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 26 Aug 2013 15:14:33 +0200 Subject: sapi: SMP support for chains Add ISR lock to chain control for proper SMP protection. Replace rtems_chain_extract() with rtems_chain_explicit_extract() and rtems_chain_insert() with rtems_chain_explicit_insert() on SMP configurations. Use rtems_chain_explicit_extract() and rtems_chain_explicit_insert() to provide SMP support. --- cpukit/sapi/include/rtems/chain.h | 165 +++++++++++++++++++++++++++++++------- 1 file changed, 134 insertions(+), 31 deletions(-) (limited to 'cpukit/sapi/include/rtems/chain.h') diff --git a/cpukit/sapi/include/rtems/chain.h b/cpukit/sapi/include/rtems/chain.h index 7e48dc7470..09270558d8 100644 --- a/cpukit/sapi/include/rtems/chain.h +++ b/cpukit/sapi/include/rtems/chain.h @@ -19,6 +19,7 @@ #define _RTEMS_CHAIN_H #include +#include #include #ifdef __cplusplus @@ -36,13 +37,16 @@ extern "C" { typedef Chain_Node rtems_chain_node; -typedef Chain_Control rtems_chain_control; +typedef struct { + Chain_Control Chain; + ISR_lock_Control Lock; +} rtems_chain_control; /** * @brief Chain initializer for an empty chain with designator @a name. */ -#define RTEMS_CHAIN_INITIALIZER_EMPTY(name) \ - CHAIN_INITIALIZER_EMPTY(name) +#define RTEMS_CHAIN_INITIALIZER_EMPTY( name ) \ + { CHAIN_INITIALIZER_EMPTY( name.Chain ), ISR_LOCK_INITIALIZER } /** * @brief Chain initializer for a chain with one @a node. @@ -50,7 +54,7 @@ typedef Chain_Control rtems_chain_control; * @see RTEMS_CHAIN_NODE_INITIALIZER_ONE_NODE_CHAIN(). */ #define RTEMS_CHAIN_INITIALIZER_ONE_NODE( node ) \ - CHAIN_INITIALIZER_ONE_NODE( node ) + { CHAIN_INITIALIZER_ONE_NODE( node ), ISR_LOCK_INITIALIZER } /** * @brief Chain node initializer for a @a chain containing exactly this node. @@ -58,13 +62,13 @@ typedef Chain_Control rtems_chain_control; * @see RTEMS_CHAIN_INITIALIZER_ONE_NODE(). */ #define RTEMS_CHAIN_NODE_INITIALIZER_ONE_NODE_CHAIN( chain ) \ - CHAIN_NODE_INITIALIZER_ONE_NODE_CHAIN( chain ) + CHAIN_NODE_INITIALIZER_ONE_NODE_CHAIN( &( chain )->Chain ) /** * @brief Chain definition for an empty chain with designator @a name. */ -#define RTEMS_CHAIN_DEFINE_EMPTY(name) \ - CHAIN_DEFINE_EMPTY(name) +#define RTEMS_CHAIN_DEFINE_EMPTY( name ) \ + rtems_chain_control name = RTEMS_CHAIN_INITIALIZER_EMPTY( name ) /** * @brief Appends the @a node to the @a chain and sends the @a events to the @@ -150,7 +154,13 @@ RTEMS_INLINE_ROUTINE void rtems_chain_initialize( size_t node_size ) { - _Chain_Initialize( the_chain, starting_address, number_nodes, node_size ); + _ISR_lock_Initialize( &the_chain->Lock ); + _Chain_Initialize( + &the_chain->Chain, + starting_address, + number_nodes, + node_size + ); } /** @@ -164,7 +174,8 @@ RTEMS_INLINE_ROUTINE void rtems_chain_initialize_empty( rtems_chain_control *the_chain ) { - _Chain_Initialize_empty( the_chain ); + _ISR_lock_Initialize( &the_chain->Lock ); + _Chain_Initialize_empty( &the_chain->Chain ); } /** @@ -230,7 +241,7 @@ RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_head( rtems_chain_control *the_chain ) { - return _Chain_Head( the_chain ); + return _Chain_Head( &the_chain->Chain ); } /** @@ -246,7 +257,7 @@ RTEMS_INLINE_ROUTINE const rtems_chain_node *rtems_chain_immutable_head( const rtems_chain_control *the_chain ) { - return _Chain_Immutable_head( the_chain ); + return _Chain_Immutable_head( &the_chain->Chain ); } /** @@ -262,7 +273,7 @@ RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_tail( rtems_chain_control *the_chain ) { - return _Chain_Tail( the_chain ); + return _Chain_Tail( &the_chain->Chain ); } /** @@ -278,7 +289,7 @@ RTEMS_INLINE_ROUTINE const rtems_chain_node *rtems_chain_immutable_tail( const rtems_chain_control *the_chain ) { - return _Chain_Immutable_tail( the_chain ); + return _Chain_Immutable_tail( &the_chain->Chain ); } /** @@ -295,7 +306,7 @@ RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_first( rtems_chain_control *the_chain ) { - return _Chain_First( the_chain ); + return _Chain_First( &the_chain->Chain ); } /** @@ -312,7 +323,7 @@ RTEMS_INLINE_ROUTINE const rtems_chain_node *rtems_chain_immutable_first( const rtems_chain_control *the_chain ) { - return _Chain_Immutable_first( the_chain ); + return _Chain_Immutable_first( &the_chain->Chain ); } /** @@ -329,7 +340,7 @@ RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_last( rtems_chain_control *the_chain ) { - return _Chain_Last( the_chain ); + return _Chain_Last( &the_chain->Chain ); } /** @@ -346,7 +357,7 @@ RTEMS_INLINE_ROUTINE const rtems_chain_node *rtems_chain_immutable_last( const rtems_chain_control *the_chain ) { - return _Chain_Immutable_last( the_chain ); + return _Chain_Immutable_last( &the_chain->Chain ); } /** @@ -448,7 +459,7 @@ RTEMS_INLINE_ROUTINE bool rtems_chain_is_empty( const rtems_chain_control *the_chain ) { - return _Chain_Is_empty( the_chain ); + return _Chain_Is_empty( &the_chain->Chain ); } /** @@ -503,7 +514,7 @@ RTEMS_INLINE_ROUTINE bool rtems_chain_has_only_one_node( const rtems_chain_control *the_chain ) { - return _Chain_Has_only_one_node( the_chain ); + return _Chain_Has_only_one_node( &the_chain->Chain ); } /** @@ -523,7 +534,7 @@ RTEMS_INLINE_ROUTINE bool rtems_chain_is_head( const rtems_chain_node *the_node ) { - return _Chain_Is_head( the_chain, the_node ); + return _Chain_Is_head( &the_chain->Chain, the_node ); } /** @@ -543,9 +554,10 @@ RTEMS_INLINE_ROUTINE bool rtems_chain_is_tail( const rtems_chain_node *the_node ) { - return _Chain_Is_tail( the_chain, the_node ); + return _Chain_Is_tail( &the_chain->Chain, the_node ); } +#if !defined( RTEMS_SMP ) /** * @brief Extract the specified node from a chain. * @@ -561,6 +573,29 @@ RTEMS_INLINE_ROUTINE void rtems_chain_extract( { _Chain_Extract( the_node ); } +#endif + +#if defined( RTEMS_SMP ) +/** + * @brief Extract the specified node from a chain. + * + * @param[in,out] chain The chain containing the node. + * @param[in,out] node The node to extract. + */ +void rtems_chain_explicit_extract( + rtems_chain_control *chain, + rtems_chain_node *node +); +#else +RTEMS_INLINE_ROUTINE void rtems_chain_explicit_extract( + rtems_chain_control *chain, + rtems_chain_node *node +) +{ + ( void ) chain; + rtems_chain_extract( node ); +} +#endif /** * @brief Extract the specified node from a chain (unprotected). @@ -589,12 +624,18 @@ RTEMS_INLINE_ROUTINE void rtems_chain_extract_unprotected( * * NOTE: It disables interrupts to ensure the atomicity of the get operation. */ +#if defined( RTEMS_SMP ) +rtems_chain_node *rtems_chain_get( + rtems_chain_control *the_chain +); +#else RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_get( rtems_chain_control *the_chain ) { - return _Chain_Get( the_chain ); + return _Chain_Get( &the_chain->Chain ); } +#endif /** * @brief See _Chain_Get_unprotected(). @@ -603,9 +644,10 @@ RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_get_unprotected( rtems_chain_control *the_chain ) { - return _Chain_Get_unprotected( the_chain ); + return _Chain_Get_unprotected( &the_chain->Chain ); } +#if !defined( RTEMS_SMP ) /** * @brief Insert a node on a chain * @@ -622,6 +664,32 @@ RTEMS_INLINE_ROUTINE void rtems_chain_insert( { _Chain_Insert( after_node, the_node ); } +#endif + +/** + * @brief Insert a node on a chain + * + * @param[in,out] chain The chain containing the after node. + * @param[in,out] after_node Insert the node after this node. + * @param[in,out] node The node to insert. + */ +#if defined( RTEMS_SMP ) +void rtems_chain_explicit_insert( + rtems_chain_control *chain, + rtems_chain_node *after_node, + rtems_chain_node *node +); +#else +RTEMS_INLINE_ROUTINE void rtems_chain_explicit_insert( + rtems_chain_control *chain, + rtems_chain_node *after_node, + rtems_chain_node *node +) +{ + ( void ) chain; + rtems_chain_insert( after_node, node ); +} +#endif /** * @brief See _Chain_Insert_unprotected(). @@ -642,13 +710,20 @@ RTEMS_INLINE_ROUTINE void rtems_chain_insert_unprotected( * NOTE: It disables interrupts to ensure the atomicity of the * append operation. */ +#if defined( RTEMS_SMP ) +void rtems_chain_append( + rtems_chain_control *the_chain, + rtems_chain_node *the_node +); +#else RTEMS_INLINE_ROUTINE void rtems_chain_append( rtems_chain_control *the_chain, rtems_chain_node *the_node ) { - _Chain_Append( the_chain, the_node ); + _Chain_Append( &the_chain->Chain, the_node ); } +#endif /** * @brief Append a node on the end of a chain (unprotected). @@ -663,7 +738,7 @@ RTEMS_INLINE_ROUTINE void rtems_chain_append_unprotected( rtems_chain_node *the_node ) { - _Chain_Append_unprotected( the_chain, the_node ); + _Chain_Append_unprotected( &the_chain->Chain, the_node ); } /** @@ -677,13 +752,20 @@ RTEMS_INLINE_ROUTINE void rtems_chain_append_unprotected( * NOTE: It disables interrupts to ensure the atomicity of the * prepend operation. */ +#if defined( RTEMS_SMP ) +void rtems_chain_prepend( + rtems_chain_control *the_chain, + rtems_chain_node *the_node +); +#else RTEMS_INLINE_ROUTINE void rtems_chain_prepend( rtems_chain_control *the_chain, rtems_chain_node *the_node ) { - _Chain_Prepend( the_chain, the_node ); + _Chain_Prepend( &the_chain->Chain, the_node ); } +#endif /** * @brief Prepend a node (unprotected). @@ -701,7 +783,7 @@ RTEMS_INLINE_ROUTINE void rtems_chain_prepend_unprotected( rtems_chain_node *the_node ) { - _Chain_Prepend_unprotected( the_chain, the_node ); + _Chain_Prepend_unprotected( &the_chain->Chain, the_node ); } /** @@ -712,13 +794,20 @@ RTEMS_INLINE_ROUTINE void rtems_chain_prepend_unprotected( * @retval true The chain was empty before the append. * @retval false The chain contained at least one node before the append. */ +#if defined( RTEMS_SMP ) +bool rtems_chain_append_with_empty_check( + rtems_chain_control *chain, + rtems_chain_node *node +); +#else RTEMS_INLINE_ROUTINE bool rtems_chain_append_with_empty_check( rtems_chain_control *chain, rtems_chain_node *node ) { - return _Chain_Append_with_empty_check( chain, node ); + return _Chain_Append_with_empty_check( &chain->Chain, node ); } +#endif /** * @brief Checks if the @a chain is empty and prepends the @a node. @@ -728,13 +817,20 @@ RTEMS_INLINE_ROUTINE bool rtems_chain_append_with_empty_check( * @retval true The chain was empty before the prepend. * @retval false The chain contained at least one node before the prepend. */ +#if defined( RTEMS_SMP ) +bool rtems_chain_prepend_with_empty_check( + rtems_chain_control *chain, + rtems_chain_node *node +); +#else RTEMS_INLINE_ROUTINE bool rtems_chain_prepend_with_empty_check( rtems_chain_control *chain, rtems_chain_node *node ) { - return _Chain_Prepend_with_empty_check( chain, node ); + return _Chain_Prepend_with_empty_check( &chain->Chain, node ); } +#endif /** * @brief Tries to get the first @a node and check if the @a chain is empty @@ -748,13 +844,20 @@ RTEMS_INLINE_ROUTINE bool rtems_chain_prepend_with_empty_check( * @retval true The chain is empty after the node removal. * @retval false The chain contained at least one node after the node removal. */ +#if defined( RTEMS_SMP ) +bool rtems_chain_get_with_empty_check( + rtems_chain_control *chain, + rtems_chain_node **node +); +#else RTEMS_INLINE_ROUTINE bool rtems_chain_get_with_empty_check( rtems_chain_control *chain, rtems_chain_node **node ) { - return _Chain_Get_with_empty_check( chain, node ); + return _Chain_Get_with_empty_check( &chain->Chain, node ); } +#endif /** * @brief Returns the node count of the chain. @@ -770,7 +873,7 @@ RTEMS_INLINE_ROUTINE size_t rtems_chain_node_count_unprotected( const rtems_chain_control *chain ) { - return _Chain_Node_count_unprotected( chain ); + return _Chain_Node_count_unprotected( &chain->Chain ); } /** @} */ -- cgit v1.2.3