[rtems commit] sapi: SMP support for chains
Sebastian Huber
sebh at rtems.org
Fri Aug 30 09:10:58 UTC 2013
Module: rtems
Branch: master
Commit: 1215fd4d9426a59d568560e9a485628560363133
Changeset: http://git.rtems.org/rtems/commit/?id=1215fd4d9426a59d568560e9a485628560363133
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Mon Aug 26 15:14:33 2013 +0200
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.
---
c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c | 2 +-
c/src/libchip/ide/ata.c | 2 +-
cpukit/posix/src/aio_cancel.c | 18 ++--
cpukit/posix/src/aio_misc.c | 32 +++--
cpukit/sapi/Makefile.am | 1 +
cpukit/sapi/include/rtems/chain.h | 165 +++++++++++++++++++++-----
cpukit/sapi/src/chainsmp.c | 138 +++++++++++++++++++++
testsuites/libtests/block06/init.c | 4 +-
testsuites/sptests/spchain/init.c | 28 +++--
9 files changed, 326 insertions(+), 64 deletions(-)
diff --git a/c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c b/c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c
index 7b9eab4..0856ad7 100644
--- a/c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c
+++ b/c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c
@@ -275,7 +275,7 @@ void mpc55xx_edma_release_channel(edma_channel_context *ctx)
unsigned channel_index = edma_channel_index_of_tcd(ctx->edma_tcd);
mpc55xx_edma_release_channel_by_tcd(ctx->edma_tcd);
- rtems_chain_extract(&ctx->node);
+ rtems_chain_explicit_extract(&edma_channel_chain, &ctx->node);
sc = rtems_interrupt_handler_remove(
MPC55XX_IRQ_EDMA(channel_index),
diff --git a/c/src/libchip/ide/ata.c b/c/src/libchip/ide/ata.c
index 8229714..64238b7 100644
--- a/c/src/libchip/ide/ata.c
+++ b/c/src/libchip/ide/ata.c
@@ -491,7 +491,7 @@ ata_request_done(ata_req_t *areq, rtems_device_minor_number ctrl_minor,
#endif
ATA_EXEC_CALLBACK(areq, status);
- rtems_chain_extract(&areq->link);
+ rtems_chain_explicit_extract(&ata_ide_ctrls[ctrl_minor].reqs, &areq->link);
if (!rtems_chain_is_empty(&ata_ide_ctrls[ctrl_minor].reqs))
{
diff --git a/cpukit/posix/src/aio_cancel.c b/cpukit/posix/src/aio_cancel.c
index 561e2f8..aec554e 100644
--- a/cpukit/posix/src/aio_cancel.c
+++ b/cpukit/posix/src/aio_cancel.c
@@ -26,6 +26,8 @@
int aio_cancel(int fildes, struct aiocb *aiocbp)
{
+ rtems_chain_control *idle_req_chain = &aio_request_queue.idle_req;
+ rtems_chain_control *work_req_chain = &aio_request_queue.work_req;
rtems_aio_request_chain *r_chain;
int result;
@@ -40,12 +42,12 @@ int aio_cancel(int fildes, struct aiocb *aiocbp)
if (aiocbp == NULL) {
AIO_printf ("Cancel all requests\n");
- r_chain = rtems_aio_search_fd (&aio_request_queue.work_req, fildes, 0);
+ r_chain = rtems_aio_search_fd (work_req_chain, fildes, 0);
if (r_chain == NULL) {
AIO_printf ("Request chain not on [WQ]\n");
- if (!rtems_chain_is_empty (&aio_request_queue.idle_req)) {
- r_chain = rtems_aio_search_fd (&aio_request_queue.idle_req, fildes, 0);
+ if (!rtems_chain_is_empty (idle_req_chain)) {
+ r_chain = rtems_aio_search_fd (idle_req_chain, fildes, 0);
if (r_chain == NULL) {
pthread_mutex_unlock(&aio_request_queue.mutex);
return AIO_ALLDONE;
@@ -53,7 +55,7 @@ int aio_cancel(int fildes, struct aiocb *aiocbp)
AIO_printf ("Request chain on [IQ]\n");
- rtems_chain_extract (&r_chain->next_fd);
+ rtems_chain_explicit_extract (idle_req_chain, &r_chain->next_fd);
rtems_aio_remove_fd (r_chain);
pthread_mutex_destroy (&r_chain->mutex);
pthread_cond_destroy (&r_chain->mutex);
@@ -70,7 +72,7 @@ int aio_cancel(int fildes, struct aiocb *aiocbp)
AIO_printf ("Request chain on [WQ]\n");
pthread_mutex_lock (&r_chain->mutex);
- rtems_chain_extract (&r_chain->next_fd);
+ rtems_chain_explicit_extract (work_req_chain, &r_chain->next_fd);
rtems_aio_remove_fd (r_chain);
pthread_mutex_unlock (&r_chain->mutex);
pthread_mutex_unlock (&aio_request_queue.mutex);
@@ -83,10 +85,10 @@ int aio_cancel(int fildes, struct aiocb *aiocbp)
rtems_set_errno_and_return_minus_one (EINVAL);
}
- r_chain = rtems_aio_search_fd (&aio_request_queue.work_req, fildes, 0);
+ r_chain = rtems_aio_search_fd (work_req_chain, fildes, 0);
if (r_chain == NULL) {
- if (!rtems_chain_is_empty (&aio_request_queue.idle_req)) {
- r_chain = rtems_aio_search_fd (&aio_request_queue.idle_req, fildes, 0);
+ if (!rtems_chain_is_empty (idle_req_chain)) {
+ r_chain = rtems_aio_search_fd (idle_req_chain, fildes, 0);
if (r_chain == NULL) {
pthread_mutex_unlock (&aio_request_queue.mutex);
rtems_set_errno_and_return_minus_one (EINVAL);
diff --git a/cpukit/posix/src/aio_misc.c b/cpukit/posix/src/aio_misc.c
index e4c40df..656ba41 100644
--- a/cpukit/posix/src/aio_misc.c
+++ b/cpukit/posix/src/aio_misc.c
@@ -120,7 +120,9 @@ rtems_aio_search_fd (rtems_chain_control *chain, int fildes, int create)
if (rtems_chain_is_empty (chain))
rtems_chain_prepend (chain, &r_chain->next_fd);
else
- rtems_chain_insert (rtems_chain_previous (node), &r_chain->next_fd);
+ rtems_chain_explicit_insert (chain,
+ rtems_chain_previous (node),
+ &r_chain->next_fd);
r_chain->new_fd = 1;
r_chain->fildes = fildes;
@@ -144,19 +146,22 @@ rtems_aio_search_fd (rtems_chain_control *chain, int fildes, int create)
static void
rtems_aio_move_to_work (rtems_aio_request_chain *r_chain)
{
+ rtems_chain_control *work_req_chain = &aio_request_queue.work_req;
rtems_aio_request_chain *temp;
rtems_chain_node *node;
-
- node = rtems_chain_first (&aio_request_queue.work_req);
+
+ node = rtems_chain_first (work_req_chain);
temp = (rtems_aio_request_chain *) node;
- while (temp->fildes < r_chain->fildes &&
- !rtems_chain_is_tail (&aio_request_queue.work_req, node)) {
+ while (temp->fildes < r_chain->fildes &&
+ !rtems_chain_is_tail (work_req_chain, node)) {
node = rtems_chain_next (node);
temp = (rtems_aio_request_chain *) node;
}
-
- rtems_chain_insert (rtems_chain_previous (node), &r_chain->next_fd);
+
+ rtems_chain_explicit_insert (work_req_chain,
+ rtems_chain_previous (node),
+ &r_chain->next_fd);
}
@@ -195,7 +200,7 @@ rtems_aio_insert_prio (rtems_chain_control *chain, rtems_aio_request *req)
prio = ((rtems_aio_request *) node)->aiocbp->aio_reqprio;
}
- rtems_chain_insert (node->previous, &req->next_prio);
+ rtems_chain_explicit_insert (chain, node->previous, &req->next_prio);
}
}
@@ -221,7 +226,7 @@ void rtems_aio_remove_fd (rtems_aio_request_chain *r_chain)
while (!rtems_chain_is_tail (chain, node))
{
- rtems_chain_extract (node);
+ rtems_chain_explicit_extract (chain, node);
rtems_aio_request *req = (rtems_aio_request *) node;
node = rtems_chain_next (node);
req->aiocbp->error_code = ECANCELED;
@@ -265,7 +270,7 @@ int rtems_aio_remove_req (rtems_chain_control *chain, struct aiocb *aiocbp)
return AIO_NOTCANCELED;
else
{
- rtems_chain_extract (node);
+ rtems_chain_explicit_extract (chain, node);
current->aiocbp->error_code = ECANCELED;
current->aiocbp->return_value = -1;
free (current);
@@ -440,7 +445,7 @@ rtems_aio_handle (void *arg)
param.sched_priority = req->priority;
pthread_setschedparam (pthread_self(), req->policy, ¶m);
- rtems_chain_extract (node);
+ rtems_chain_explicit_extract (chain, node);
pthread_mutex_unlock (&r_chain->mutex);
@@ -506,7 +511,8 @@ rtems_aio_handle (void *arg)
/* If no requests were added to the chain we delete the fd chain from
the queue and start working with idle fd chains */
if (result == ETIMEDOUT) {
- rtems_chain_extract (&r_chain->next_fd);
+ rtems_chain_explicit_extract (&aio_request_queue.work_req,
+ &r_chain->next_fd);
pthread_mutex_destroy (&r_chain->mutex);
pthread_cond_destroy (&r_chain->cond);
free (r_chain);
@@ -542,7 +548,7 @@ rtems_aio_handle (void *arg)
++aio_request_queue.active_threads;
node = rtems_chain_first (&aio_request_queue.idle_req);
- rtems_chain_extract (node);
+ rtems_chain_explicit_extract (&aio_request_queue.idle_req, node);
r_chain = (rtems_aio_request_chain *) node;
rtems_aio_move_to_work (r_chain);
diff --git a/cpukit/sapi/Makefile.am b/cpukit/sapi/Makefile.am
index eaea591..2a88aa3 100644
--- a/cpukit/sapi/Makefile.am
+++ b/cpukit/sapi/Makefile.am
@@ -31,6 +31,7 @@ libsapi_a_SOURCES = src/debug.c src/extension.c src/extensioncreate.c \
src/chainappendnotify.c src/chaingetnotify.c src/chaingetwait.c \
src/chainprependnotify.c src/rbheap.c src/interrdesc.c \
src/fatal2.c src/fatalsrcdesc.c
+libsapi_a_SOURCES += src/chainsmp.c
libsapi_a_CPPFLAGS = $(AM_CPPFLAGS)
include $(srcdir)/preinstall.am
diff --git a/cpukit/sapi/include/rtems/chain.h b/cpukit/sapi/include/rtems/chain.h
index 7e48dc7..0927055 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 );
}
/** @} */
diff --git a/cpukit/sapi/src/chainsmp.c b/cpukit/sapi/src/chainsmp.c
new file mode 100644
index 0000000..ea8de83
--- /dev/null
+++ b/cpukit/sapi/src/chainsmp.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2013 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <rtems/chain.h>
+
+#if defined( RTEMS_SMP )
+
+void rtems_chain_explicit_extract(
+ rtems_chain_control *chain,
+ rtems_chain_node *node
+)
+{
+ ISR_Level level;
+
+ _ISR_lock_ISR_disable_and_acquire( &chain->Lock, level );
+ _Chain_Extract_unprotected( node );
+ _ISR_lock_Release_and_ISR_enable( &chain->Lock, level );
+}
+
+rtems_chain_node *rtems_chain_get( rtems_chain_control *chain )
+{
+ rtems_chain_node *node;
+ ISR_Level level;
+
+ _ISR_lock_ISR_disable_and_acquire( &chain->Lock, level );
+ node = _Chain_Get_unprotected( &chain->Chain );
+ _ISR_lock_Release_and_ISR_enable( &chain->Lock, level );
+
+ return node;
+}
+
+void rtems_chain_explicit_insert(
+ rtems_chain_control *chain,
+ rtems_chain_node *after_node,
+ rtems_chain_node *node
+)
+{
+ ISR_Level level;
+
+ _ISR_lock_ISR_disable_and_acquire( &chain->Lock, level );
+ _Chain_Insert_unprotected( after_node, node );
+ _ISR_lock_Release_and_ISR_enable( &chain->Lock, level );
+}
+
+void rtems_chain_append(
+ rtems_chain_control *chain,
+ rtems_chain_node *node
+)
+{
+ ISR_Level level;
+
+ _ISR_lock_ISR_disable_and_acquire( &chain->Lock, level );
+ _Chain_Append_unprotected( &chain->Chain, node );
+ _ISR_lock_Release_and_ISR_enable( &chain->Lock, level );
+}
+
+void rtems_chain_prepend(
+ rtems_chain_control *chain,
+ rtems_chain_node *node
+)
+{
+ ISR_Level level;
+
+ _ISR_lock_ISR_disable_and_acquire( &chain->Lock, level );
+ _Chain_Prepend_unprotected( &chain->Chain, node );
+ _ISR_lock_Release_and_ISR_enable( &chain->Lock, level );
+}
+
+bool rtems_chain_append_with_empty_check(
+ rtems_chain_control *chain,
+ rtems_chain_node *node
+)
+{
+ bool was_empty;
+ ISR_Level level;
+
+ _ISR_lock_ISR_disable_and_acquire( &chain->Lock, level );
+ was_empty = _Chain_Append_with_empty_check_unprotected(
+ &chain->Chain,
+ node
+ );
+ _ISR_lock_Release_and_ISR_enable( &chain->Lock, level );
+
+ return was_empty;
+}
+
+bool rtems_chain_prepend_with_empty_check(
+ rtems_chain_control *chain,
+ rtems_chain_node *node
+)
+{
+ bool was_empty;
+ ISR_Level level;
+
+ _ISR_lock_ISR_disable_and_acquire( &chain->Lock, level );
+ was_empty = _Chain_Prepend_with_empty_check_unprotected(
+ &chain->Chain,
+ node
+ );
+ _ISR_lock_Release_and_ISR_enable( &chain->Lock, level );
+
+ return was_empty;
+}
+
+bool rtems_chain_get_with_empty_check(
+ rtems_chain_control *chain,
+ rtems_chain_node **node
+)
+{
+ bool is_empty_now;
+ ISR_Level level;
+
+ _ISR_lock_ISR_disable_and_acquire( &chain->Lock, level );
+ is_empty_now = _Chain_Get_with_empty_check_unprotected(
+ &chain->Chain,
+ node
+ );
+ _ISR_lock_Release_and_ISR_enable( &chain->Lock, level );
+
+ return is_empty_now;
+}
+
+#endif /* defined( RTEMS_SMP ) */
diff --git a/testsuites/libtests/block06/init.c b/testsuites/libtests/block06/init.c
index 6352aba..e51bf27 100644
--- a/testsuites/libtests/block06/init.c
+++ b/testsuites/libtests/block06/init.c
@@ -1130,14 +1130,14 @@ bdbuf_tests_task_0_test_8 (bdbuf_task_control* tc)
bd = (rtems_bdbuf_buffer*) node;
pnode = node->previous;
- rtems_chain_extract (node);
+ rtems_chain_explicit_extract (&buffers, node);
node = pnode;
bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[4]: ", tc->name);
passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd), true);
bd = (rtems_bdbuf_buffer*) node;
pnode = node->previous;
- rtems_chain_extract (node);
+ rtems_chain_explicit_extract (&buffers, node);
node = pnode;
bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[3]: ", tc->name);
passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd), true);
diff --git a/testsuites/sptests/spchain/init.c b/testsuites/sptests/spchain/init.c
index 219d0f3..747f404 100644
--- a/testsuites/sptests/spchain/init.c
+++ b/testsuites/sptests/spchain/init.c
@@ -60,17 +60,29 @@ static void test_chain_control_initializer(void)
static void test_chain_control_layout(void)
{
- rtems_chain_control chain;
+ Chain_Control chain;
+
puts( "INIT - Verify rtems_chain_control layout" );
+
+ rtems_test_assert(
+ sizeof(Chain_Control)
+ == sizeof(Chain_Node) + sizeof(Chain_Node *)
+ );
rtems_test_assert(
- sizeof(rtems_chain_control)
- == sizeof(rtems_chain_node) + sizeof(rtems_chain_node *)
+ sizeof(Chain_Control)
+ == 3 * sizeof(Chain_Node *)
);
rtems_test_assert(
- sizeof(rtems_chain_control)
- == 3 * sizeof(rtems_chain_node *)
+ _Chain_Previous( _Chain_Head( &chain ) )
+ == _Chain_Next( _Chain_Tail( &chain ) )
);
- rtems_test_assert( &chain.Head.Node.previous == &chain.Tail.Node.next );
+
+#if !defined( RTEMS_SMP )
+ rtems_test_assert(
+ sizeof(Chain_Control)
+ == sizeof(rtems_chain_control)
+ );
+#endif
}
static void test_chain_get_with_wait(void)
@@ -94,7 +106,7 @@ static void test_chain_first_and_last(void)
rtems_chain_initialize_empty( &chain );
rtems_chain_append( &chain, &node1 );
- rtems_chain_insert( &node1, &node2 );
+ rtems_chain_explicit_insert( &chain, &node1, &node2 );
puts( "INIT - Verify rtems_chain_is_first" );
cnode = rtems_chain_first(&chain);
@@ -296,7 +308,7 @@ rtems_task Init(
node1.id = 1;
node2.id = 2;
rtems_chain_append( &chain1, &node1.Node );
- rtems_chain_insert( &node1.Node, &node2.Node );
+ rtems_chain_explicit_insert( &chain1, &node1.Node, &node2.Node );
for ( p = rtems_chain_first(&chain1), id = 1 ;
!rtems_chain_is_tail(&chain1, p) ;
More information about the vc
mailing list