/* * Copyright (c) 2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 * 82178 Puchheim * Germany * * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #if defined(RTEMS_SMP) && defined(RTEMS_PROFILING) typedef struct { SMP_lock_Control Lock; Chain_Control Stats_chain; Chain_Control Iterator_chain; } SMP_lock_Stats_control; static SMP_lock_Stats_control _SMP_lock_Stats_control = { .Lock = { .Ticket_lock = { .next_ticket = ATOMIC_INITIALIZER_UINT( 0U ), .now_serving = ATOMIC_INITIALIZER_UINT( 0U ) }, .Stats = { .Node = CHAIN_NODE_INITIALIZER_ONE_NODE_CHAIN( &_SMP_lock_Stats_control.Stats_chain ), .name = "SMP Lock Stats" } }, .Stats_chain = CHAIN_INITIALIZER_ONE_NODE( &_SMP_lock_Stats_control.Lock.Stats.Node ), .Iterator_chain = CHAIN_INITIALIZER_EMPTY( _SMP_lock_Stats_control.Iterator_chain ) }; void _SMP_lock_Stats_destroy( SMP_lock_Stats *stats ) { if ( !_Chain_Is_node_off_chain( &stats->Node ) ) { SMP_lock_Stats_control *control = &_SMP_lock_Stats_control; SMP_lock_Context lock_context; SMP_lock_Stats_iteration_context *iteration_context; SMP_lock_Stats_iteration_context *iteration_context_tail; SMP_lock_Stats *next_stats; _SMP_lock_ISR_disable_and_acquire( &control->Lock, &lock_context ); next_stats = (SMP_lock_Stats *) _Chain_Next( &stats->Node ); _Chain_Extract_unprotected( &stats->Node ); iteration_context = (SMP_lock_Stats_iteration_context *) _Chain_First( &control->Iterator_chain ); iteration_context_tail = (SMP_lock_Stats_iteration_context *) _Chain_Tail( &control->Iterator_chain ); while ( iteration_context != iteration_context_tail ) { if ( iteration_context->current == stats ) { iteration_context->current = next_stats; } iteration_context = (SMP_lock_Stats_iteration_context *) _Chain_Next( &iteration_context->Node ); } _SMP_lock_Release_and_ISR_enable( &control->Lock, &lock_context ); } } void _SMP_lock_Stats_register( SMP_lock_Stats *stats ) { SMP_lock_Stats_control *control = &_SMP_lock_Stats_control; SMP_lock_Context lock_context; _SMP_lock_ISR_disable_and_acquire( &control->Lock, &lock_context ); _Chain_Append_unprotected( &control->Stats_chain, &stats->Node ); _SMP_lock_Release_and_ISR_enable( &control->Lock, &lock_context ); } void _SMP_lock_Stats_iteration_start( SMP_lock_Stats_iteration_context *iteration_context ) { SMP_lock_Stats_control *control = &_SMP_lock_Stats_control; SMP_lock_Context lock_context; _SMP_lock_ISR_disable_and_acquire( &control->Lock, &lock_context ); _Chain_Initialize_node( &iteration_context->Node ); _Chain_Append_unprotected( &control->Iterator_chain, &iteration_context->Node ); iteration_context->current = (SMP_lock_Stats *) _Chain_First( &control->Stats_chain ); _SMP_lock_Release_and_ISR_enable( &control->Lock, &lock_context ); } bool _SMP_lock_Stats_iteration_next( SMP_lock_Stats_iteration_context *iteration_context, SMP_lock_Stats *snapshot, char *name, size_t name_size ) { SMP_lock_Stats_control *control = &_SMP_lock_Stats_control; SMP_lock_Context lock_context; SMP_lock_Stats *current; bool valid; _SMP_lock_ISR_disable_and_acquire( &control->Lock, &lock_context ); current = iteration_context->current; if ( !_Chain_Is_tail( &control->Stats_chain, ¤t->Node ) ) { size_t name_len = current->name != NULL ? strlen(current->name) : 0; valid = true; iteration_context->current = (SMP_lock_Stats *) _Chain_Next( ¤t->Node ); *snapshot = *current; snapshot->name = name; if ( name_len >= name_size ) { name_len = name_size - 1; } name[name_len] = '\0'; memcpy(name, current->name, name_len); } else { valid = false; } _SMP_lock_Release_and_ISR_enable( &control->Lock, &lock_context ); return valid; } void _SMP_lock_Stats_iteration_stop( SMP_lock_Stats_iteration_context *iteration_context ) { SMP_lock_Stats_control *control = &_SMP_lock_Stats_control; SMP_lock_Context lock_context; _SMP_lock_ISR_disable_and_acquire( &control->Lock, &lock_context ); _Chain_Extract_unprotected( &iteration_context->Node ); _SMP_lock_Release_and_ISR_enable( &control->Lock, &lock_context ); } #endif /* RTEMS_SMP && RTEMS_PROFILING */