From 059529e685e059d366ee56aa6117ee0d4e899e66 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 21 Jul 2016 10:15:02 +0200 Subject: score: Add debug support to chains 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 | 2 + 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, 116 insertions(+), 11 deletions(-) diff --git a/cpukit/libcsupport/src/malloc_deferred.c b/cpukit/libcsupport/src/malloc_deferred.c index 962ae3e81f..f37b852cba 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 20c900fe8d..02468208ad 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 f358f32bb1..bae623bff3 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 ddda4d15eb..2b8126ee8b 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 d12f9c48d5..d9886f4c01 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 bdcd0d38d8..5a281a94f5 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, ¶m); + 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 3d8a860f20..25f02c9ba8 100644 --- a/cpukit/sapi/include/rtems/chain.h +++ b/cpukit/sapi/include/rtems/chain.h @@ -187,6 +187,21 @@ RTEMS_INLINE_ROUTINE void rtems_chain_set_off_chain( _Chain_Set_off_chain( node ); } +/** + * @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. * diff --git a/cpukit/sapi/include/rtems/rbheap.h b/cpukit/sapi/include/rtems/rbheap.h index c008721b23..735aa6c8fd 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 6fc2aef218..3a6983781e 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 f78f2d60bb..b50f4ff910 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 69e9a3c5f8..4739bdadba 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 e33866e59b..38f9f5b53a 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 73d4de2032..986edc3482 100644 --- a/cpukit/score/include/rtems/score/threadqimpl.h +++ b/cpukit/score/include/rtems/score/threadqimpl.h @@ -122,11 +122,13 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Heads_initialize( size_t i; for ( i = 0; i < _Scheduler_Count; ++i ) { + _Chain_Initialize_node( &heads->Priority[ i ].Node ); _RBTree_Initialize_empty( &heads->Priority[ i ].Queue ); } #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 301e9b28b0..68786b1d7a 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 2a76114096..cd78a72af5 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 c3221b94b6..5a00ee6fe1 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 dd46d6877b..eb5ea4e7df 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( ® ); _Chain_Iterator_initialize( &chain, ®, &fit, CHAIN_ITERATOR_FORWARD ); _Chain_Iterator_initialize( &chain, ®, &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" ); -- cgit v1.2.3