From 2aae3a7032ea27a989b76988bba66f4d59518ce3 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 18 May 2016 13:28:52 +0200 Subject: SMP: Move lock stats to separate header file --- cpukit/score/include/rtems/score/smplock.h | 359 +++-------------------------- 1 file changed, 29 insertions(+), 330 deletions(-) (limited to 'cpukit/score/include/rtems/score/smplock.h') diff --git a/cpukit/score/include/rtems/score/smplock.h b/cpukit/score/include/rtems/score/smplock.h index 47797d3294..f4196fe1f7 100644 --- a/cpukit/score/include/rtems/score/smplock.h +++ b/cpukit/score/include/rtems/score/smplock.h @@ -22,17 +22,13 @@ #include -#if defined( RTEMS_SMP ) +#if defined(RTEMS_SMP) +#include #include #include -#if defined( RTEMS_PROFILING ) -#include -#include -#endif - -#if defined( RTEMS_PROFILING ) || defined( RTEMS_DEBUG ) +#if defined(RTEMS_PROFILING) || defined(RTEMS_DEBUG) #define RTEMS_SMP_LOCK_DO_NOT_INLINE #endif @@ -58,157 +54,6 @@ extern "C" { * @{ */ -#if defined( RTEMS_PROFILING ) - -/** - * @brief Count of lock contention counters for lock statistics. - */ -#define SMP_LOCK_STATS_CONTENTION_COUNTS 4 - -/** - * @brief SMP lock statistics. - * - * The lock acquire attempt instant is the point in time right after the - * interrupt disable action in the lock acquire sequence. - * - * The lock acquire instant is the point in time right after the lock - * acquisition. This is the begin of the critical section code execution. - * - * The lock release instant is the point in time right before the interrupt - * enable action in the lock release sequence. - * - * The lock section time is the time elapsed between the lock acquire instant - * and the lock release instant. - * - * The lock acquire time is the time elapsed between the lock acquire attempt - * instant and the lock acquire instant. - */ -typedef struct { - /** - * @brief Node for SMP lock statistics chain. - */ - Chain_Node Node; - - /** - * @brief The maximum lock acquire time in CPU counter ticks. - */ - CPU_Counter_ticks max_acquire_time; - - /** - * @brief The maximum lock section time in CPU counter ticks. - */ - CPU_Counter_ticks max_section_time; - - /** - * @brief The count of lock uses. - * - * This value may overflow. - */ - uint64_t usage_count; - - /** - * @brief Total lock acquire time in nanoseconds. - * - * The average lock acquire time is the total acquire time divided by the - * lock usage count. The ration of the total section and total acquire times - * gives a measure for the lock contention. - * - * This value may overflow. - */ - uint64_t total_acquire_time; - - /** - * @brief The counts of lock acquire operations by contention. - * - * The contention count for index N corresponds to a lock acquire attempt - * with an initial queue length of N. The last index corresponds to all - * lock acquire attempts with an initial queue length greater than or equal - * to SMP_LOCK_STATS_CONTENTION_COUNTS minus one. - * - * The values may overflow. - */ - uint64_t contention_counts[SMP_LOCK_STATS_CONTENTION_COUNTS]; - - /** - * @brief Total lock section time in CPU counter ticks. - * - * The average lock section time is the total section time divided by the - * lock usage count. - * - * This value may overflow. - */ - uint64_t total_section_time; - - /** - * @brief The lock name. - */ - const char *name; -} SMP_lock_Stats; - -/** - * @brief Local context for SMP lock statistics. - */ -typedef struct { - /** - * @brief The last lock acquire instant in CPU counter ticks. - * - * This value is used to measure the lock section time. - */ - CPU_Counter_ticks acquire_instant; - - /** - * @brief The lock stats used for the last lock acquire. - */ - SMP_lock_Stats *stats; -} SMP_lock_Stats_context; - -/** - * @brief SMP lock statistics initializer for static initialization. - */ -#define SMP_LOCK_STATS_INITIALIZER( name ) \ - { { NULL, NULL }, 0, 0, 0, 0, { 0, 0, 0, 0 }, 0, name } - -/** - * @brief Initializes an SMP lock statistics block. - * - * @param[in, out] stats The SMP lock statistics block. - * @param[in] name The name for the SMP lock statistics. This name must be - * persistent throughout the life time of this statistics block. - */ -static inline void _SMP_lock_Stats_initialize( - SMP_lock_Stats *stats, - const char *name -) -{ - SMP_lock_Stats init = SMP_LOCK_STATS_INITIALIZER( name ); - - *stats = init; -} - -/** - * @brief Destroys an SMP lock statistics block. - * - * @param[in] stats The SMP lock statistics block. - */ -static inline void _SMP_lock_Stats_destroy( SMP_lock_Stats *stats ); - -/** - * @brief Updates an SMP lock statistics block during a lock release. - * - * @param[in] stats_context The SMP lock statistics context. - */ -static inline void _SMP_lock_Stats_release_update( - const SMP_lock_Stats_context *stats_context -); - -#else /* RTEMS_PROFILING */ - -#define _SMP_lock_Stats_initialize( stats, name ) do { } while ( 0 ) - -#define _SMP_lock_Stats_destroy( stats ) do { } while ( 0 ) - -#endif /* RTEMS_PROFILING */ - /** * @brief SMP ticket lock control. */ @@ -257,7 +102,7 @@ static inline void _SMP_ticket_lock_Destroy( SMP_ticket_lock_Control *lock ) static inline void _SMP_ticket_lock_Do_acquire( SMP_ticket_lock_Control *lock -#if defined( RTEMS_PROFILING ) +#if defined(RTEMS_PROFILING) , SMP_lock_Stats *stats, SMP_lock_Stats_context *stats_context @@ -267,7 +112,7 @@ static inline void _SMP_ticket_lock_Do_acquire( unsigned int my_ticket; unsigned int now_serving; -#if defined( RTEMS_PROFILING ) +#if defined(RTEMS_PROFILING) CPU_Counter_ticks first; CPU_Counter_ticks second; CPU_Counter_ticks delta; @@ -279,7 +124,7 @@ static inline void _SMP_ticket_lock_Do_acquire( my_ticket = _Atomic_Fetch_add_uint( &lock->next_ticket, 1U, ATOMIC_ORDER_RELAXED ); -#if defined( RTEMS_PROFILING ) +#if defined(RTEMS_PROFILING) now_serving = _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_ACQUIRE ); initial_queue_length = my_ticket - now_serving; @@ -292,7 +137,7 @@ static inline void _SMP_ticket_lock_Do_acquire( _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_ACQUIRE ); } while ( now_serving != my_ticket ); -#if defined( RTEMS_PROFILING ) +#if defined(RTEMS_PROFILING) } second = _CPU_Counter_read(); @@ -327,7 +172,7 @@ static inline void _SMP_ticket_lock_Do_acquire( * @param[in] stats The SMP lock statistics. * @param[out] stats_context The SMP lock statistics context. */ -#if defined( RTEMS_PROFILING ) +#if defined(RTEMS_PROFILING) #define _SMP_ticket_lock_Acquire( lock, stats, stats_context ) \ _SMP_ticket_lock_Do_acquire( lock, stats, stats_context ) #else @@ -337,7 +182,7 @@ static inline void _SMP_ticket_lock_Do_acquire( static inline void _SMP_ticket_lock_Do_release( SMP_ticket_lock_Control *lock -#if defined( RTEMS_PROFILING ) +#if defined(RTEMS_PROFILING) , const SMP_lock_Stats_context *stats_context #endif @@ -347,7 +192,7 @@ static inline void _SMP_ticket_lock_Do_release( _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_RELAXED ); unsigned int next_ticket = current_ticket + 1U; -#if defined( RTEMS_PROFILING ) +#if defined(RTEMS_PROFILING) _SMP_lock_Stats_release_update( stats_context ); #endif @@ -360,7 +205,7 @@ static inline void _SMP_ticket_lock_Do_release( * @param[in] lock The SMP ticket lock control. * @param[in] stats_context The SMP lock statistics context. */ -#if defined( RTEMS_PROFILING ) +#if defined(RTEMS_PROFILING) #define _SMP_ticket_lock_Release( lock, stats_context ) \ _SMP_ticket_lock_Do_release( lock, stats_context ) #else @@ -373,7 +218,7 @@ static inline void _SMP_ticket_lock_Do_release( */ typedef struct { SMP_ticket_lock_Control Ticket_lock; -#if defined( RTEMS_DEBUG ) +#if defined(RTEMS_DEBUG) /** * @brief The index of the owning processor of this lock. * @@ -388,7 +233,7 @@ typedef struct { */ uint32_t owner; #endif -#if defined( RTEMS_PROFILING ) +#if defined(RTEMS_PROFILING) SMP_lock_Stats Stats; #endif } SMP_lock_Control; @@ -398,32 +243,32 @@ typedef struct { */ typedef struct { ISR_Level isr_level; -#if defined( RTEMS_DEBUG ) +#if defined(RTEMS_DEBUG) SMP_lock_Control *lock_used_for_acquire; #endif -#if defined( RTEMS_PROFILING ) +#if defined(RTEMS_PROFILING) SMP_lock_Stats_context Stats_context; #endif } SMP_lock_Context; -#if defined( RTEMS_DEBUG ) +#if defined(RTEMS_DEBUG) #define SMP_LOCK_NO_OWNER 0xffffffff #endif /** * @brief SMP lock control initializer for static initialization. */ -#if defined( RTEMS_DEBUG ) && defined( RTEMS_PROFILING ) +#if defined(RTEMS_DEBUG) && defined(RTEMS_PROFILING) #define SMP_LOCK_INITIALIZER( name ) \ { \ SMP_TICKET_LOCK_INITIALIZER, \ SMP_LOCK_NO_OWNER, \ SMP_LOCK_STATS_INITIALIZER( name ) \ } -#elif defined( RTEMS_DEBUG ) +#elif defined(RTEMS_DEBUG) #define SMP_LOCK_INITIALIZER( name ) \ { SMP_TICKET_LOCK_INITIALIZER, SMP_LOCK_NO_OWNER } -#elif defined( RTEMS_PROFILING ) +#elif defined(RTEMS_PROFILING) #define SMP_LOCK_INITIALIZER( name ) \ { SMP_TICKET_LOCK_INITIALIZER, SMP_LOCK_STATS_INITIALIZER( name ) } #else @@ -439,7 +284,7 @@ typedef struct { * @param[in] name The name for the SMP lock statistics. This name must be * persistent throughout the life time of this statistics block. */ -#if defined( RTEMS_SMP_LOCK_DO_NOT_INLINE ) +#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE) void _SMP_lock_Initialize( SMP_lock_Control *lock, const char *name @@ -454,10 +299,10 @@ static inline void _SMP_lock_Initialize( ) { _SMP_ticket_lock_Initialize( &lock->Ticket_lock ); -#if defined( RTEMS_DEBUG ) +#if defined(RTEMS_DEBUG) lock->owner = SMP_LOCK_NO_OWNER; #endif -#if defined( RTEMS_PROFILING ) +#if defined(RTEMS_PROFILING) _SMP_lock_Stats_initialize( &lock->Stats, name ); #else (void) name; @@ -471,7 +316,7 @@ static inline void _SMP_lock_Initialize( * * @param[in] lock The SMP lock control. */ -#if defined( RTEMS_SMP_LOCK_DO_NOT_INLINE ) +#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE) void _SMP_lock_Destroy( SMP_lock_Control *lock ); static inline void _SMP_lock_Destroy_body( SMP_lock_Control *lock ) @@ -494,7 +339,7 @@ static inline void _SMP_lock_Destroy( SMP_lock_Control *lock ) * @param[in] context The local SMP lock context for an acquire and release * pair. */ -#if defined( RTEMS_SMP_LOCK_DO_NOT_INLINE ) +#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE) void _SMP_lock_Acquire( SMP_lock_Control *lock, SMP_lock_Context *context @@ -523,7 +368,7 @@ static inline void _SMP_lock_Acquire( * @param[in] context The local SMP lock context for an acquire and release * pair. */ -#if defined( RTEMS_SMP_LOCK_DO_NOT_INLINE ) +#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE) void _SMP_lock_Release( SMP_lock_Control *lock, SMP_lock_Context *context @@ -551,7 +396,7 @@ static inline void _SMP_lock_Release( * @param[in] context The local SMP lock context for an acquire and release * pair. */ -#if defined( RTEMS_SMP_LOCK_DO_NOT_INLINE ) +#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE) void _SMP_lock_ISR_disable_and_acquire( SMP_lock_Control *lock, SMP_lock_Context *context @@ -576,7 +421,7 @@ static inline void _SMP_lock_ISR_disable_and_acquire( * @param[in] context The local SMP lock context for an acquire and release * pair. */ -#if defined( RTEMS_SMP_LOCK_DO_NOT_INLINE ) +#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE) void _SMP_lock_Release_and_ISR_enable( SMP_lock_Control *lock, SMP_lock_Context *context @@ -592,7 +437,7 @@ static inline void _SMP_lock_Release_and_ISR_enable( } #endif -#if defined( RTEMS_DEBUG ) +#if defined(RTEMS_DEBUG) /** * @brief Returns true, if the SMP lock is owned by the current processor, * otherwise false. @@ -602,158 +447,12 @@ static inline void _SMP_lock_Release_and_ISR_enable( bool _SMP_lock_Is_owner( const SMP_lock_Control *lock ); #endif -#if defined( RTEMS_PROFILING ) - -typedef struct { - SMP_lock_Control Lock; - Chain_Control Stats_chain; - Chain_Control Iterator_chain; -} SMP_lock_Stats_control; - -typedef struct { - Chain_Node Node; - SMP_lock_Stats *current; -} SMP_lock_Stats_iteration_context; - -extern SMP_lock_Stats_control _SMP_lock_Stats_control; - -static inline 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_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 ); -} - -static inline 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; -} - -static inline 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 ); -} - -static inline 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 ); - } -} - -static inline void _SMP_lock_Stats_release_update( - const SMP_lock_Stats_context *stats_context -) -{ - SMP_lock_Stats *stats = stats_context->stats; - CPU_Counter_ticks first = stats_context->acquire_instant; - CPU_Counter_ticks second = _CPU_Counter_read(); - CPU_Counter_ticks delta = _CPU_Counter_difference( second, first ); - - stats->total_section_time += delta; - - if ( stats->max_section_time < delta ) { - stats->max_section_time = delta; - - if ( _Chain_Is_node_off_chain( &stats->Node ) ) { - 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 ); - } - } -} - -#endif /* RTEMS_PROFILING */ - /**@}*/ #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* defined( RTEMS_SMP ) */ +#endif /* RTEMS_SMP */ #endif /* _RTEMS_SCORE_SMPLOCK_H */ -- cgit v1.2.3