forked from Imagelibrary/rtems
score: Add debug support to red-black trees
This helps to detect double insert and extract errors.
This commit is contained in:
@@ -117,6 +117,7 @@ static inline void rb_link_node(
|
|||||||
struct rb_node **link
|
struct rb_node **link
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
_RBTree_Initialize_node( (RBTree_Node *) node );
|
||||||
_RBTree_Add_child(
|
_RBTree_Add_child(
|
||||||
(RBTree_Node *) node,
|
(RBTree_Node *) node,
|
||||||
(RBTree_Node *) parent,
|
(RBTree_Node *) parent,
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ static int _POSIX_Keys_Create_value(
|
|||||||
key_value_pair->thread = executing;
|
key_value_pair->thread = executing;
|
||||||
key_value_pair->value = RTEMS_DECONST( void *, value );
|
key_value_pair->value = RTEMS_DECONST( void *, value );
|
||||||
|
|
||||||
|
_RBTree_Initialize_node( &key_value_pair->Lookup_node );
|
||||||
|
|
||||||
_Chain_Initialize_node( &key_value_pair->Key_node );
|
_Chain_Initialize_node( &key_value_pair->Key_node );
|
||||||
_Chain_Append_unprotected(
|
_Chain_Append_unprotected(
|
||||||
&the_key->Key_value_pairs,
|
&the_key->Key_value_pairs,
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ rtems_rbtree_node *rtems_rbtree_insert(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_RBTree_Initialize_node( the_node );
|
||||||
_RBTree_Add_child( the_node, parent, which );
|
_RBTree_Add_child( the_node, parent, which );
|
||||||
_RBTree_Insert_color( the_rbtree, the_node );
|
_RBTree_Insert_color( the_rbtree, the_node );
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <sys/tree.h>
|
#include <sys/tree.h>
|
||||||
#include <rtems/score/basedefs.h>
|
#include <rtems/score/basedefs.h>
|
||||||
|
#include <rtems/score/assert.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -68,6 +69,38 @@ typedef RB_HEAD(RBTree_Control, RBTree_Node) RBTree_Control;
|
|||||||
#define RBTREE_DEFINE_EMPTY( name ) \
|
#define RBTREE_DEFINE_EMPTY( name ) \
|
||||||
RBTree_Control name = RBTREE_INITIALIZER_EMPTY( name )
|
RBTree_Control name = RBTREE_INITIALIZER_EMPTY( name )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets a red-black tree node as off-tree.
|
||||||
|
*
|
||||||
|
* Do not use this function on nodes which are a part of a tree.
|
||||||
|
*
|
||||||
|
* @param[in] the_node The node to set off-tree.
|
||||||
|
*
|
||||||
|
* @see _RBTree_Is_node_off_tree().
|
||||||
|
*/
|
||||||
|
RTEMS_INLINE_ROUTINE void _RBTree_Set_off_tree( RBTree_Node *the_node )
|
||||||
|
{
|
||||||
|
RB_COLOR( the_node, Node ) = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true, if this red-black tree node is off-tree, and false
|
||||||
|
* otherwise.
|
||||||
|
*
|
||||||
|
* @param[in] the_node The node to test.
|
||||||
|
*
|
||||||
|
* @retval true The node is not a part of a tree (off-tree).
|
||||||
|
* @retval false Otherwise.
|
||||||
|
*
|
||||||
|
* @see _RBTree_Set_off_tree().
|
||||||
|
*/
|
||||||
|
RTEMS_INLINE_ROUTINE bool _RBTree_Is_node_off_tree(
|
||||||
|
const RBTree_Node *the_node
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return RB_COLOR( the_node, Node ) == -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Rebalances the red-black tree after insertion of the node.
|
* @brief Rebalances the red-black tree after insertion of the node.
|
||||||
*
|
*
|
||||||
@@ -79,6 +112,21 @@ void _RBTree_Insert_color(
|
|||||||
RBTree_Node *the_node
|
RBTree_Node *the_node
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes a red-black tree node.
|
||||||
|
*
|
||||||
|
* In debug configurations, the node is set off tree. In all other
|
||||||
|
* configurations, this function does nothing.
|
||||||
|
*
|
||||||
|
* @param[in] the_node The red-black tree node to initialize.
|
||||||
|
*/
|
||||||
|
RTEMS_INLINE_ROUTINE void _RBTree_Initialize_node( RBTree_Node *the_node )
|
||||||
|
{
|
||||||
|
#if defined(RTEMS_DEBUG)
|
||||||
|
_RBTree_Set_off_tree( the_node );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds a child node to a parent node.
|
* @brief Adds a child node to a parent node.
|
||||||
*
|
*
|
||||||
@@ -92,6 +140,7 @@ RTEMS_INLINE_ROUTINE void _RBTree_Add_child(
|
|||||||
RBTree_Node **link
|
RBTree_Node **link
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
_Assert( _RBTree_Is_node_off_tree( child ) );
|
||||||
RB_SET( child, parent, Node );
|
RB_SET( child, parent, Node );
|
||||||
*link = child;
|
*link = child;
|
||||||
}
|
}
|
||||||
@@ -174,38 +223,6 @@ void _RBTree_Extract(
|
|||||||
RBTree_Node *the_node
|
RBTree_Node *the_node
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets a red-black tree node as off-tree.
|
|
||||||
*
|
|
||||||
* Do not use this function on nodes which are a part of a tree.
|
|
||||||
*
|
|
||||||
* @param[in] the_node The node to set off-tree.
|
|
||||||
*
|
|
||||||
* @see _RBTree_Is_node_off_tree().
|
|
||||||
*/
|
|
||||||
RTEMS_INLINE_ROUTINE void _RBTree_Set_off_tree( RBTree_Node *the_node )
|
|
||||||
{
|
|
||||||
RB_COLOR( the_node, Node ) = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns true, if this red-black tree node is off-tree, and false
|
|
||||||
* otherwise.
|
|
||||||
*
|
|
||||||
* @param[in] the_node The node to test.
|
|
||||||
*
|
|
||||||
* @retval true The node is not a part of a tree (off-tree).
|
|
||||||
* @retval false Otherwise.
|
|
||||||
*
|
|
||||||
* @see _RBTree_Set_off_tree().
|
|
||||||
*/
|
|
||||||
RTEMS_INLINE_ROUTINE bool _RBTree_Is_node_off_tree(
|
|
||||||
const RBTree_Node *the_node
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return RB_COLOR( the_node, Node ) == -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a pointer to root node of the red-black tree.
|
* @brief Returns a pointer to root node of the red-black tree.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -22,4 +22,7 @@ void _RBTree_Extract(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
RB_REMOVE( RBTree_Control, the_rbtree, the_node );
|
RB_REMOVE( RBTree_Control, the_rbtree, the_node );
|
||||||
|
#if defined(RTEMS_DEBUG)
|
||||||
|
_RBTree_Set_off_tree( the_node );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,4 +35,5 @@ void _Scheduler_EDF_Node_initialize(
|
|||||||
|
|
||||||
the_node = _Scheduler_EDF_Node_downcast( node );
|
the_node = _Scheduler_EDF_Node_downcast( node );
|
||||||
the_node->thread = the_thread;
|
the_node->thread = the_thread;
|
||||||
|
_RBTree_Initialize_node( &the_node->Node );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ bool _Thread_Initialize(
|
|||||||
"Thread Wait Default Lock"
|
"Thread Wait Default Lock"
|
||||||
);
|
);
|
||||||
_Thread_queue_Gate_open( &the_thread->Wait.Lock.Tranquilizer );
|
_Thread_queue_Gate_open( &the_thread->Wait.Lock.Tranquilizer );
|
||||||
|
_RBTree_Initialize_node( &the_thread->Wait.Link.Registry_node );
|
||||||
_SMP_lock_Stats_initialize( &the_thread->Potpourri_stats, "Thread Potpourri" );
|
_SMP_lock_Stats_initialize( &the_thread->Potpourri_stats, "Thread Potpourri" );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ void _Thread_MP_Handler_initialization (
|
|||||||
proxy = (Thread_Proxy_control *) ( proxies + i * proxy_size );
|
proxy = (Thread_Proxy_control *) ( proxies + i * proxy_size );
|
||||||
|
|
||||||
_Thread_Timer_initialize( &proxy->Timer, _Per_CPU_Get_by_index( 0 ) );
|
_Thread_Timer_initialize( &proxy->Timer, _Per_CPU_Get_by_index( 0 ) );
|
||||||
|
_RBTree_Initialize_node( &proxy->Active );
|
||||||
|
|
||||||
proxy->Wait.spare_heads = &proxy->Thread_queue_heads[ 0 ];
|
proxy->Wait.spare_heads = &proxy->Thread_queue_heads[ 0 ];
|
||||||
_Thread_queue_Heads_initialize( proxy->Wait.spare_heads );
|
_Thread_queue_Heads_initialize( proxy->Wait.spare_heads );
|
||||||
|
|||||||
@@ -251,6 +251,7 @@ static bool _Thread_queue_Path_acquire(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_RBTree_Initialize_node( &path->Start.Registry_node );
|
||||||
_Chain_Initialize_node( &path->Start.Path_node );
|
_Chain_Initialize_node( &path->Start.Path_node );
|
||||||
_Thread_queue_Context_initialize( &path->Start.Queue_context );
|
_Thread_queue_Context_initialize( &path->Start.Queue_context );
|
||||||
link = &path->Start;
|
link = &path->Start;
|
||||||
|
|||||||
@@ -242,6 +242,7 @@ static void _Thread_queue_Priority_do_enqueue(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
current_priority = the_thread->current_priority;
|
current_priority = the_thread->current_priority;
|
||||||
|
_RBTree_Initialize_node( &the_thread->Wait.Node.RBTree );
|
||||||
_RBTree_Insert_inline(
|
_RBTree_Insert_inline(
|
||||||
&priority_queue->Queue,
|
&priority_queue->Queue,
|
||||||
&the_thread->Wait.Node.RBTree,
|
&the_thread->Wait.Node.RBTree,
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ void _Watchdog_Insert(
|
|||||||
}
|
}
|
||||||
|
|
||||||
header->first = new_first;
|
header->first = new_first;
|
||||||
|
_RBTree_Initialize_node( &the_watchdog->Node.RBTree );
|
||||||
_RBTree_Add_child( &the_watchdog->Node.RBTree, parent, link );
|
_RBTree_Add_child( &the_watchdog->Node.RBTree, parent, link );
|
||||||
_RBTree_Insert_color( &header->Watchdogs, &the_watchdog->Node.RBTree );
|
_RBTree_Insert_color( &header->Watchdogs, &the_watchdog->Node.RBTree );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1801,7 +1801,6 @@ rtems_task Init( rtems_task_argument ignored )
|
|||||||
puts( "INIT - rtems_rbtree_extract failed");
|
puts( "INIT - rtems_rbtree_extract failed");
|
||||||
rtems_test_exit(0);
|
rtems_test_exit(0);
|
||||||
}
|
}
|
||||||
rtems_test_assert( !rtems_rbtree_is_node_off_tree( p ) );
|
|
||||||
rb_insert_unique(&rbtree1, p);
|
rb_insert_unique(&rbtree1, p);
|
||||||
|
|
||||||
for ( p = rtems_rbtree_get_min(&rbtree1), id = 1 ; p ;
|
for ( p = rtems_rbtree_get_min(&rbtree1), id = 1 ; p ;
|
||||||
|
|||||||
Reference in New Issue
Block a user