summaryrefslogtreecommitdiffstats
path: root/cpukit/sapi/include/rtems/chain.h
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-08-26 15:14:33 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-08-30 11:16:28 +0200
commit1215fd4d9426a59d568560e9a485628560363133 (patch)
tree1fa51c2c86080bdbf80d20386732f34f08e708be /cpukit/sapi/include/rtems/chain.h
parentsmptests/smpatomic08: Fix race conditions (diff)
downloadrtems-1215fd4d9426a59d568560e9a485628560363133.tar.bz2
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.
Diffstat (limited to 'cpukit/sapi/include/rtems/chain.h')
-rw-r--r--cpukit/sapi/include/rtems/chain.h165
1 files changed, 134 insertions, 31 deletions
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 <rtems/score/chainimpl.h>
+#include <rtems/score/isrlock.h>
#include <rtems/rtems/event.h>
#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 );
}
/** @} */