forked from Imagelibrary/rtems
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.
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
!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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
138
cpukit/sapi/src/chainsmp.c
Normal file
138
cpukit/sapi/src/chainsmp.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2013 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Dornierstr. 4
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@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 ) */
|
||||
@@ -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);
|
||||
|
||||
@@ -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(rtems_chain_control)
|
||||
== sizeof(rtems_chain_node) + sizeof(rtems_chain_node *)
|
||||
sizeof(Chain_Control)
|
||||
== sizeof(Chain_Node) + sizeof(Chain_Node *)
|
||||
);
|
||||
rtems_test_assert(
|
||||
sizeof(rtems_chain_control)
|
||||
== 3 * sizeof(rtems_chain_node *)
|
||||
sizeof(Chain_Control)
|
||||
== 3 * sizeof(Chain_Node *)
|
||||
);
|
||||
rtems_test_assert( &chain.Head.Node.previous == &chain.Tail.Node.next );
|
||||
rtems_test_assert(
|
||||
_Chain_Previous( _Chain_Head( &chain ) )
|
||||
== _Chain_Next( _Chain_Tail( &chain ) )
|
||||
);
|
||||
|
||||
#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) ;
|
||||
|
||||
Reference in New Issue
Block a user