[PATCH] score: Add debug support to chains

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Jul 21 13:31:32 UTC 2016


This helps to detect

 * double insert, append, prepend errors, and
 * get from empty chain errors.
---
 cpukit/libcsupport/src/malloc_deferred.c           |  6 ++-
 cpukit/libcsupport/src/mount-mgr.c                 |  1 +
 cpukit/libcsupport/src/printertask.c               |  1 +
 cpukit/libcsupport/src/sup_fs_location.c           |  1 +
 cpukit/libcsupport/src/termios.c                   |  1 +
 cpukit/posix/src/aio_misc.c                        |  4 +-
 cpukit/sapi/include/rtems/chain.h                  | 15 +++++++
 cpukit/sapi/include/rtems/rbheap.h                 |  1 +
 cpukit/sapi/src/rbheap.c                           |  1 +
 cpukit/score/include/rtems/score/chainimpl.h       | 52 +++++++++++++++++++---
 cpukit/score/include/rtems/score/resourceimpl.h    |  2 +
 .../include/rtems/score/schedulerpriorityimpl.h    |  1 +
 cpukit/score/include/rtems/score/threadqimpl.h     |  1 +
 cpukit/score/src/freechain.c                       |  1 +
 cpukit/score/src/objectextendinformation.c         |  1 +
 cpukit/score/src/threadqops.c                      |  1 +
 testsuites/sptests/spchain/init.c                  | 36 +++++++++++++--
 17 files changed, 115 insertions(+), 11 deletions(-)

diff --git a/cpukit/libcsupport/src/malloc_deferred.c b/cpukit/libcsupport/src/malloc_deferred.c
index 962ae3e..f37b852 100644
--- a/cpukit/libcsupport/src/malloc_deferred.c
+++ b/cpukit/libcsupport/src/malloc_deferred.c
@@ -127,9 +127,13 @@ void *rtems_heap_allocate_aligned_with_boundary(
 void _Malloc_Deferred_free( void *p )
 {
   rtems_interrupt_lock_context lock_context;
+  rtems_chain_node *node;
+
+  node = (rtems_chain_node *) p;
 
   rtems_interrupt_lock_acquire( &_Malloc_GC_lock, &lock_context );
-  rtems_chain_append_unprotected( &_Malloc_GC_list, (rtems_chain_node *) p );
+  rtems_chain_initialize_node( node );
+  rtems_chain_append_unprotected( &_Malloc_GC_list, node );
   rtems_interrupt_lock_release( &_Malloc_GC_lock, &lock_context );
 }
 #endif
diff --git a/cpukit/libcsupport/src/mount-mgr.c b/cpukit/libcsupport/src/mount-mgr.c
index 20c900f..0246820 100644
--- a/cpukit/libcsupport/src/mount-mgr.c
+++ b/cpukit/libcsupport/src/mount-mgr.c
@@ -124,6 +124,7 @@ rtems_filesystem_register(
 
   rtems_libio_lock();
   if ( rtems_filesystem_get_mount_handler( type ) == NULL ) {
+    rtems_chain_initialize_node( &fsn->node );
     rtems_chain_append_unprotected( chain, &fsn->node );
   } else {
     rtems_libio_unlock();
diff --git a/cpukit/libcsupport/src/printertask.c b/cpukit/libcsupport/src/printertask.c
index f358f32..bae623b 100644
--- a/cpukit/libcsupport/src/printertask.c
+++ b/cpukit/libcsupport/src/printertask.c
@@ -194,6 +194,7 @@ void rtems_printer_task_drain( rtems_printer_task_context *ctx )
 {
   printer_task_buffer buffer;
 
+  rtems_chain_initialize_node( &buffer.node );
   buffer.action_kind = ACTION_DRAIN;
   buffer.action_data.task = rtems_task_self();
 
diff --git a/cpukit/libcsupport/src/sup_fs_location.c b/cpukit/libcsupport/src/sup_fs_location.c
index ddda4d1..2b8126e 100644
--- a/cpukit/libcsupport/src/sup_fs_location.c
+++ b/cpukit/libcsupport/src/sup_fs_location.c
@@ -48,6 +48,7 @@ rtems_filesystem_location_info_t *rtems_filesystem_location_copy(
   dst->node_access_2 = src->node_access_2;
   dst->handlers = src->handlers;
   dst->mt_entry = src->mt_entry;
+  rtems_chain_initialize_node(&dst->mt_entry_node);
   rtems_filesystem_location_add_to_mt_entry(dst);
 
   return dst;
diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c
index d12f9c4..d9886f4 100644
--- a/cpukit/libcsupport/src/termios.c
+++ b/cpukit/libcsupport/src/termios.c
@@ -149,6 +149,7 @@ rtems_status_code rtems_termios_device_install(
     return RTEMS_NO_MEMORY;
   }
 
+  rtems_chain_initialize_node(&new_device_node->node);
   new_device_node->major = major;
   new_device_node->minor = minor;
   new_device_node->handler = handler;
diff --git a/cpukit/posix/src/aio_misc.c b/cpukit/posix/src/aio_misc.c
index bdcd0d3..5a281a9 100644
--- a/cpukit/posix/src/aio_misc.c
+++ b/cpukit/posix/src/aio_misc.c
@@ -116,6 +116,7 @@ rtems_aio_search_fd (rtems_chain_control *chain, int fildes, int create)
     else {
       r_chain = malloc (sizeof (rtems_aio_request_chain));
       rtems_chain_initialize_empty (&r_chain->perfd);
+      rtems_chain_initialize_node (&r_chain->next_fd);
 
       if (rtems_chain_is_empty (chain))
         rtems_chain_prepend (chain, &r_chain->next_fd);
@@ -222,9 +223,9 @@ void rtems_aio_remove_fd (rtems_aio_request_chain *r_chain)
   
   while (!rtems_chain_is_tail (chain, node))
     {
-      rtems_chain_extract (node);
       rtems_aio_request *req = (rtems_aio_request *) node;
       node = rtems_chain_next (node);
+      rtems_chain_extract (&req->next_prio);
       req->aiocbp->error_code = ECANCELED;
       req->aiocbp->return_value = -1;
       free (req);
@@ -311,6 +312,7 @@ rtems_aio_enqueue (rtems_aio_request *req)
      we can use aio_reqprio to lower the priority of the request */
   pthread_getschedparam (pthread_self(), &policy, &param);
 
+  rtems_chain_initialize_node (&req->next_prio);
   req->caller_thread = pthread_self ();
   req->priority = param.sched_priority - req->aiocbp->aio_reqprio;
   req->policy = policy;
diff --git a/cpukit/sapi/include/rtems/chain.h b/cpukit/sapi/include/rtems/chain.h
index 3d8a860..25f02c9 100644
--- a/cpukit/sapi/include/rtems/chain.h
+++ b/cpukit/sapi/include/rtems/chain.h
@@ -188,6 +188,21 @@ RTEMS_INLINE_ROUTINE void rtems_chain_set_off_chain(
 }
 
 /**
+ * @brief Initializes a chain node.
+ *
+ * In debug configurations, the node is set off chain.  In all other
+ * configurations, this function does nothing.
+ *
+ * @param[in] the_node The chain node to initialize.
+ */
+RTEMS_INLINE_ROUTINE void rtems_chain_initialize_node(
+  rtems_chain_node *node
+)
+{
+  _Chain_Initialize_node( node );
+}
+
+/**
  * @brief Is the node off chain.
  *
  * This function returns true if the @a node is not on a chain. A @a node is
diff --git a/cpukit/sapi/include/rtems/rbheap.h b/cpukit/sapi/include/rtems/rbheap.h
index c008721..735aa6c 100644
--- a/cpukit/sapi/include/rtems/rbheap.h
+++ b/cpukit/sapi/include/rtems/rbheap.h
@@ -210,6 +210,7 @@ static inline void rtems_rbheap_add_to_spare_descriptor_chain(
   rtems_chain_control *chain =
     rtems_rbheap_get_spare_descriptor_chain(control);
 
+  rtems_chain_initialize_node(&chunk->chain_node);
   rtems_chain_prepend_unprotected(chain, &chunk->chain_node);
 }
 
diff --git a/cpukit/sapi/src/rbheap.c b/cpukit/sapi/src/rbheap.c
index 6fc2aef..3a69837 100644
--- a/cpukit/sapi/src/rbheap.c
+++ b/cpukit/sapi/src/rbheap.c
@@ -76,6 +76,7 @@ static void add_to_chain(
   rtems_rbheap_chunk *chunk
 )
 {
+  rtems_chain_initialize_node(&chunk->chain_node);
   rtems_chain_prepend_unprotected(chain, &chunk->chain_node);
 }
 
diff --git a/cpukit/score/include/rtems/score/chainimpl.h b/cpukit/score/include/rtems/score/chainimpl.h
index f78f2d6..b50f4ff 100644
--- a/cpukit/score/include/rtems/score/chainimpl.h
+++ b/cpukit/score/include/rtems/score/chainimpl.h
@@ -104,6 +104,26 @@ RTEMS_INLINE_ROUTINE void _Chain_Set_off_chain(
 )
 {
   node->next = NULL;
+#if defined(RTEMS_DEBUG)
+  node->previous = NULL;
+#endif
+}
+
+/**
+ * @brief Initializes a chain node.
+ *
+ * In debug configurations, the node is set off chain.  In all other
+ * configurations, this function does nothing.
+ *
+ * @param[in] the_node The chain node to initialize.
+ */
+RTEMS_INLINE_ROUTINE void _Chain_Initialize_node( Chain_Node *the_node )
+{
+#if defined(RTEMS_DEBUG)
+  _Chain_Set_off_chain( the_node );
+#else
+  (void) the_node;
+#endif
 }
 
 /**
@@ -519,6 +539,10 @@ RTEMS_INLINE_ROUTINE void _Chain_Extract_unprotected(
   previous       = the_node->previous;
   next->previous = previous;
   previous->next = next;
+
+#if defined(RTEMS_DEBUG)
+  _Chain_Set_off_chain( the_node );
+#endif
 }
 
 /**
@@ -540,13 +564,23 @@ RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Get_first_unprotected(
   Chain_Control *the_chain
 )
 {
-  Chain_Node *head = _Chain_Head( the_chain );
-  Chain_Node *old_first = head->next;
-  Chain_Node *new_first = old_first->next;
+  Chain_Node *head;
+  Chain_Node *old_first;
+  Chain_Node *new_first;
+
+  _Assert( !_Chain_Is_empty( the_chain ) );
+
+  head = _Chain_Head( the_chain );
+  old_first = head->next;
+  new_first = old_first->next;
 
   head->next = new_first;
   new_first->previous = head;
 
+#if defined(RTEMS_DEBUG)
+  _Chain_Set_off_chain( old_first );
+#endif
+
   return old_first;
 }
 
@@ -594,6 +628,8 @@ RTEMS_INLINE_ROUTINE void _Chain_Insert_unprotected(
 {
   Chain_Node *before_node;
 
+  _Assert( _Chain_Is_node_off_chain( the_node ) );
+
   the_node->previous    = after_node;
   before_node           = after_node->next;
   after_node->next      = the_node;
@@ -617,8 +653,13 @@ RTEMS_INLINE_ROUTINE void _Chain_Append_unprotected(
   Chain_Node    *the_node
 )
 {
-  Chain_Node *tail = _Chain_Tail( the_chain );
-  Chain_Node *old_last = tail->previous;
+  Chain_Node *tail;
+  Chain_Node *old_last;
+
+  _Assert( _Chain_Is_node_off_chain( the_node ) );
+
+  tail = _Chain_Tail( the_chain );
+  old_last = tail->previous;
 
   the_node->next = tail;
   tail->previous = the_node;
@@ -978,6 +1019,7 @@ RTEMS_INLINE_ROUTINE void _Chain_Iterator_initialize(
   Chain_Iterator_direction  direction
 )
 {
+  _Chain_Initialize_node( &the_iterator->Registry_node );
   _Chain_Append_unprotected(
     &the_registry->Iterators,
     &the_iterator->Registry_node
diff --git a/cpukit/score/include/rtems/score/resourceimpl.h b/cpukit/score/include/rtems/score/resourceimpl.h
index 69e9a3c..4739bda 100644
--- a/cpukit/score/include/rtems/score/resourceimpl.h
+++ b/cpukit/score/include/rtems/score/resourceimpl.h
@@ -59,6 +59,7 @@ RTEMS_INLINE_ROUTINE void _Resource_Node_initialize( Resource_Node *node )
 {
   node->dependency = NULL;
   node->root = node;
+  _Chain_Initialize_node( &node->Node );
   _Chain_Initialize_empty( &node->Resources );
 }
 
@@ -106,6 +107,7 @@ RTEMS_INLINE_ROUTINE void _Resource_Node_extract( Resource_Node *node )
 RTEMS_INLINE_ROUTINE void _Resource_Initialize( Resource_Control *resource )
 {
   resource->owner = NULL;
+  _Chain_Initialize_node( &resource->Node );
   _Chain_Initialize_empty( &resource->Rivals );
 }
 
diff --git a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
index e33866e..38f9f5b 100644
--- a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
@@ -131,6 +131,7 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_extract(
 
   if ( _Chain_Has_only_one_node( ready_chain ) ) {
     _Chain_Initialize_empty( ready_chain );
+    _Chain_Initialize_node( node );
     _Priority_bit_map_Remove( bit_map, &ready_queue->Priority_map );
   } else {
     _Chain_Extract_unprotected( node );
diff --git a/cpukit/score/include/rtems/score/threadqimpl.h b/cpukit/score/include/rtems/score/threadqimpl.h
index 73d4de2..df0c3e0 100644
--- a/cpukit/score/include/rtems/score/threadqimpl.h
+++ b/cpukit/score/include/rtems/score/threadqimpl.h
@@ -127,6 +127,7 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Heads_initialize(
 #endif
 
   _Chain_Initialize_empty( &heads->Free_chain );
+  _Chain_Initialize_node( &heads->Free_node );
 }
 
 RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_initialize(
diff --git a/cpukit/score/src/freechain.c b/cpukit/score/src/freechain.c
index 301e9b2..68786b1 100644
--- a/cpukit/score/src/freechain.c
+++ b/cpukit/score/src/freechain.c
@@ -75,6 +75,7 @@ void *_Freechain_Get(
 void _Freechain_Put( Freechain_Control *freechain, void *node )
 {
   if ( node != NULL ) {
+    _Chain_Initialize_node( node );
     _Chain_Prepend_unprotected( &freechain->Free, node );
   }
 }
diff --git a/cpukit/score/src/objectextendinformation.c b/cpukit/score/src/objectextendinformation.c
index 2a76114..cd78a72 100644
--- a/cpukit/score/src/objectextendinformation.c
+++ b/cpukit/score/src/objectextendinformation.c
@@ -265,6 +265,7 @@ void _Objects_Extend_information(
       index
     );
 
+    _Chain_Initialize_node( &the_object->Node );
     _Chain_Append_unprotected( &information->Inactive, &the_object->Node );
 
     the_object = (Objects_Control *)
diff --git a/cpukit/score/src/threadqops.c b/cpukit/score/src/threadqops.c
index c3221b9..5a00ee6 100644
--- a/cpukit/score/src/threadqops.c
+++ b/cpukit/score/src/threadqops.c
@@ -99,6 +99,7 @@ static void _Thread_queue_FIFO_do_enqueue(
   Thread_Control     *the_thread
 )
 {
+  _Chain_Initialize_node( &the_thread->Wait.Node.Chain );
   _Chain_Append_unprotected(
     &heads->Heads.Fifo,
     &the_thread->Wait.Node.Chain
diff --git a/testsuites/sptests/spchain/init.c b/testsuites/sptests/spchain/init.c
index dd46d68..eb5ea4e 100644
--- a/testsuites/sptests/spchain/init.c
+++ b/testsuites/sptests/spchain/init.c
@@ -43,6 +43,9 @@ static void test_chain_iterator( void )
   rtems_test_assert( _Chain_Is_empty( &static_reg.Iterators ));
 
   _Chain_Initialize_empty( &chain );
+  _Chain_Initialize_node( &a );
+  _Chain_Initialize_node( &b );
+  _Chain_Initialize_node( &c );
   _Chain_Iterator_registry_initialize( &reg );
   _Chain_Iterator_initialize( &chain, &reg, &fit, CHAIN_ITERATOR_FORWARD );
   _Chain_Iterator_initialize( &chain, &reg, &bit, CHAIN_ITERATOR_BACKWARD );
@@ -225,6 +228,8 @@ static void test_chain_first_and_last(void)
   rtems_chain_node     *cnode;
 
   rtems_chain_initialize_empty( &chain );
+  rtems_chain_initialize_node( &node1 );
+  rtems_chain_initialize_node( &node2 );
   rtems_chain_append( &chain, &node1 );
   rtems_chain_insert( &node1, &node2 );
 
@@ -255,6 +260,7 @@ static void test_chain_with_notification(void)
 
   puts( "INIT - Verify rtems_chain_append_with_notification" );
   rtems_chain_initialize_empty( &chain );
+  rtems_chain_initialize_node( &a );
   sc = rtems_chain_append_with_notification(
     &chain,
     &a,
@@ -267,6 +273,8 @@ static void test_chain_with_notification(void)
   rtems_test_assert( p == &a );
 
   rtems_chain_initialize_empty( &chain );
+  rtems_chain_initialize_node( &a );
+  rtems_chain_initialize_node( &b );
 
   rtems_chain_append( &chain, &b );
   sc = rtems_chain_append_with_notification(
@@ -280,6 +288,8 @@ static void test_chain_with_notification(void)
 
   puts( "INIT - Verify rtems_chain_prepend_with_notification" );
   rtems_chain_initialize_empty( &chain );
+  rtems_chain_initialize_node( &a );
+  rtems_chain_initialize_node( &b );
   sc = rtems_chain_prepend_with_notification(
     &chain,
     &a,
@@ -303,6 +313,8 @@ static void test_chain_with_notification(void)
 
   puts( "INIT - Verify rtems_chain_get_with_notification" );
   rtems_chain_initialize_empty( &chain );
+  rtems_chain_initialize_node( &a );
+  rtems_chain_initialize_node( &b );
 
   rtems_chain_append( &chain, &b );
   rtems_chain_append( &chain, &a );
@@ -329,27 +341,35 @@ static void test_chain_with_empty_check(void)
   rtems_chain_control chain;
   rtems_chain_node a;
   rtems_chain_node b;
+  rtems_chain_node c;
   rtems_chain_node *p;
   bool empty;
 
   puts( "INIT - Verify rtems_chain_append_with_empty_check" );
   rtems_chain_initialize_empty( &chain );
+  rtems_chain_initialize_node( &a );
+  rtems_chain_initialize_node( &b );
   empty = rtems_chain_append_with_empty_check( &chain, &a );
   rtems_test_assert( empty );
-  empty = rtems_chain_append_with_empty_check( &chain, &a );
+  empty = rtems_chain_append_with_empty_check( &chain, &b );
   rtems_test_assert( !empty );
 
   puts( "INIT - Verify rtems_chain_prepend_with_empty_check" );
   rtems_chain_initialize_empty( &chain );
+  rtems_chain_initialize_node( &a );
+  rtems_chain_initialize_node( &b );
+  rtems_chain_initialize_node( &c );
   empty = rtems_chain_prepend_with_empty_check( &chain, &a );
   rtems_test_assert( empty );
-  empty = rtems_chain_prepend_with_empty_check( &chain, &a );
-  rtems_test_assert( !empty );
   empty = rtems_chain_prepend_with_empty_check( &chain, &b );
   rtems_test_assert( !empty );
+  empty = rtems_chain_prepend_with_empty_check( &chain, &c );
+  rtems_test_assert( !empty );
 
   puts( "INIT - Verify rtems_chain_get_with_empty_check" );
   rtems_chain_initialize_empty( &chain );
+  rtems_chain_initialize_node( &a );
+  rtems_chain_initialize_node( &b );
   empty = rtems_chain_get_with_empty_check( &chain, &p );
   rtems_test_assert( empty );
 
@@ -377,6 +397,7 @@ static void test_chain_node_count(void)
   rtems_test_assert( count == 0 );
 
   for (i = 0; i < RTEMS_ARRAY_SIZE( nodes ); ++i) {
+    rtems_chain_initialize_node( &nodes[ i ] );
     rtems_chain_append_unprotected( &chain, &nodes[i] );
     count = rtems_chain_node_count_unprotected( &chain );
     rtems_test_assert( count == i + 1 );
@@ -395,10 +416,14 @@ static void test_chain_insert_ordered( void )
   const Chain_Node *tail;
   const Chain_Node *node;
   size_t n = RTEMS_ARRAY_SIZE( nodes );
-  size_t i = 0;
+  size_t i;
 
   puts( "INIT - Verify _Chain_Insert_ordered_unprotected" );
 
+  for ( i = 0; i < n; ++i ) {
+    _Chain_Initialize_node( &nodes[ i ] );
+  }
+
   _Chain_Insert_ordered_unprotected( &chain, &nodes[4], test_order );
   _Chain_Insert_ordered_unprotected( &chain, &nodes[2], test_order );
   _Chain_Insert_ordered_unprotected( &chain, &nodes[0], test_order );
@@ -407,6 +432,7 @@ static void test_chain_insert_ordered( void )
 
   tail = _Chain_Immutable_tail( &chain );
   node = _Chain_Immutable_first( &chain );
+  i = 0;
   while ( node != tail && i < n ) {
     rtems_test_assert( node == &nodes[ i ] );
     ++i;
@@ -429,6 +455,8 @@ rtems_task Init(
 
   puts( "Init - Initialize chain empty" );
   rtems_chain_initialize_empty( &chain1 );
+  rtems_chain_initialize_node( &node1.Node );
+  rtems_chain_initialize_node( &node2.Node );
 
   /* verify that the chain append and insert work */
   puts( "INIT - Verify rtems_chain_insert" );
-- 
1.8.4.5



More information about the devel mailing list