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:
Sebastian Huber
2013-08-26 15:14:33 +02:00
parent e127c4c9ea
commit 1215fd4d94
9 changed files with 326 additions and 64 deletions

View File

@@ -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),

View File

@@ -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))
{

View File

@@ -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);

View File

@@ -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, &param);
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);

View File

@@ -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

View File

@@ -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)
{ 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)
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
View 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 ) */

View File

@@ -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);

View File

@@ -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) ;