From d5423295988918f45b64d50cf0b9501a56b9aa36 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 18 May 2015 11:09:14 +0200 Subject: score: _Thread_Dispatch_disable_critical() Thread dispatching is disabled in case interrupts are disabled. To get an accurate thread dispatch disabled time it is important to use the interrupt disabled instant in case a transition from an interrupt disabled section to a thread dispatch level section happens. --- cpukit/rtems/src/eventseize.c | 2 +- cpukit/rtems/src/eventsurrender.c | 2 +- cpukit/score/include/rtems/score/coremuteximpl.h | 2 +- cpukit/score/include/rtems/score/isrlock.h | 23 ++++++++++++++++++-- cpukit/score/include/rtems/score/mrspimpl.h | 6 +++--- cpukit/score/include/rtems/score/profiling.h | 21 ++++++++++++++++++ cpukit/score/include/rtems/score/threaddispatch.h | 26 +++++++++++++++-------- cpukit/score/src/threadqenqueue.c | 4 ++-- 8 files changed, 67 insertions(+), 19 deletions(-) diff --git a/cpukit/rtems/src/eventseize.c b/cpukit/rtems/src/eventseize.c index 6611a8d6f6..981c7d281c 100644 --- a/cpukit/rtems/src/eventseize.c +++ b/cpukit/rtems/src/eventseize.c @@ -84,7 +84,7 @@ void _Event_Seize( executing->Wait.return_argument = event_out; _Thread_Wait_flags_set( executing, intend_to_block ); - cpu_self = _Thread_Dispatch_disable_critical(); + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); _Thread_Lock_release_default( executing, lock_context ); _Giant_Acquire( cpu_self ); diff --git a/cpukit/rtems/src/eventsurrender.c b/cpukit/rtems/src/eventsurrender.c index b740721e22..a16d40e7df 100644 --- a/cpukit/rtems/src/eventsurrender.c +++ b/cpukit/rtems/src/eventsurrender.c @@ -107,7 +107,7 @@ void _Event_Surrender( if ( unblock ) { Per_CPU_Control *cpu_self; - cpu_self = _Thread_Dispatch_disable_critical(); + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); _Thread_Lock_release_default( the_thread, lock_context ); _Giant_Acquire( cpu_self ); diff --git a/cpukit/score/include/rtems/score/coremuteximpl.h b/cpukit/score/include/rtems/score/coremuteximpl.h index ca9d61df4a..f57fdfcfd5 100644 --- a/cpukit/score/include/rtems/score/coremuteximpl.h +++ b/cpukit/score/include/rtems/score/coremuteximpl.h @@ -489,7 +489,7 @@ RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock_body( if ( current > ceiling ) { Per_CPU_Control *cpu_self; - cpu_self = _Thread_Dispatch_disable_critical(); + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); _Thread_queue_Release( &the_mutex->Wait_queue, lock_context ); _Thread_Raise_priority( executing, ceiling ); _Thread_Dispatch_enable( cpu_self ); diff --git a/cpukit/score/include/rtems/score/isrlock.h b/cpukit/score/include/rtems/score/isrlock.h index 5a68937b4d..994eb48ed0 100644 --- a/cpukit/score/include/rtems/score/isrlock.h +++ b/cpukit/score/include/rtems/score/isrlock.h @@ -68,6 +68,12 @@ typedef struct { #else ISR_Level isr_level; #endif +#if defined( RTEMS_PROFILING ) + /** + * @brief The last interrupt disable instant in CPU counter ticks. + */ + CPU_Counter_ticks ISR_disable_instant; +#endif } ISR_lock_Context; /** @@ -304,6 +310,13 @@ typedef struct { _ISR_Flash( ( _context )->isr_level ) #endif +#if defined( RTEMS_PROFILING ) + #define _ISR_lock_ISR_disable_profile( _context ) \ + ( _context )->ISR_disable_instant = _CPU_Counter_read(); +#else + #define _ISR_lock_ISR_disable_profile( _context ) +#endif + /** * @brief Disables interrupts and saves the previous interrupt state in the ISR * lock context. @@ -316,10 +329,16 @@ typedef struct { */ #if defined( RTEMS_SMP ) #define _ISR_lock_ISR_disable( _context ) \ - _ISR_Disable_without_giant( ( _context )->Lock_context.isr_level ) + do { \ + _ISR_Disable_without_giant( ( _context )->Lock_context.isr_level ); \ + _ISR_lock_ISR_disable_profile( _context ) \ + } while ( 0 ) #else #define _ISR_lock_ISR_disable( _context ) \ - _ISR_Disable( ( _context )->isr_level ) + do { \ + _ISR_Disable( ( _context )->isr_level ); \ + _ISR_lock_ISR_disable_profile( _context ) \ + } while ( 0 ) #endif /** diff --git a/cpukit/score/include/rtems/score/mrspimpl.h b/cpukit/score/include/rtems/score/mrspimpl.h index 82ecb07047..bc9ed4b511 100644 --- a/cpukit/score/include/rtems/score/mrspimpl.h +++ b/cpukit/score/include/rtems/score/mrspimpl.h @@ -102,7 +102,7 @@ RTEMS_INLINE_ROUTINE void _MRSP_Claim_ownership( mrsp->initial_priority_of_owner = initial_priority; _Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER ); - cpu_self = _Thread_Dispatch_disable_critical(); + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); _ISR_lock_Release_and_ISR_enable( &mrsp->Lock, lock_context ); _Thread_Raise_priority( new_owner, ceiling_priority ); @@ -230,7 +230,7 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership( _MRSP_Giant_release( &giant_lock_context ); - cpu_self = _Thread_Dispatch_disable_critical(); + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); _ISR_lock_Release_and_ISR_enable( &mrsp->Lock, lock_context ); _Thread_Raise_priority( executing, ceiling_priority ); @@ -388,7 +388,7 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Release( _MRSP_Giant_release( &giant_lock_context ); - cpu_self = _Thread_Dispatch_disable_critical(); + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); _ISR_lock_Release_and_ISR_enable( &mrsp->Lock, lock_context ); _MRSP_Restore_priority( executing, initial_priority ); diff --git a/cpukit/score/include/rtems/score/profiling.h b/cpukit/score/include/rtems/score/profiling.h index f5fa6cc241..a6ab283ae6 100644 --- a/cpukit/score/include/rtems/score/profiling.h +++ b/cpukit/score/include/rtems/score/profiling.h @@ -24,6 +24,7 @@ #define _RTEMS_SCORE_PROFILING #include +#include #ifdef __cplusplus extern "C" { @@ -55,6 +56,26 @@ static inline void _Profiling_Thread_dispatch_disable( #endif } +static inline void _Profiling_Thread_dispatch_disable_critical( + Per_CPU_Control *cpu, + uint32_t previous_thread_dispatch_disable_level, + const ISR_lock_Context *lock_context +) +{ +#if defined( RTEMS_PROFILING ) + if ( previous_thread_dispatch_disable_level == 0 ) { + Per_CPU_Stats *stats = &cpu->Stats; + + stats->thread_dispatch_disabled_instant = lock_context->ISR_disable_instant; + ++stats->thread_dispatch_disabled_count; + } +#else + (void) cpu; + (void) previous_thread_dispatch_disable_level; + (void) lock_context; +#endif +} + static inline void _Profiling_Thread_dispatch_enable( Per_CPU_Control *cpu, uint32_t new_thread_dispatch_disable_level diff --git a/cpukit/score/include/rtems/score/threaddispatch.h b/cpukit/score/include/rtems/score/threaddispatch.h index 89f5c0ba5b..4ef5538f7e 100644 --- a/cpukit/score/include/rtems/score/threaddispatch.h +++ b/cpukit/score/include/rtems/score/threaddispatch.h @@ -15,7 +15,7 @@ #define _RTEMS_SCORE_THREADDISPATCH_H #include -#include +#include #include #ifdef __cplusplus @@ -242,16 +242,25 @@ void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level ); * * This function does not acquire the Giant lock. * + * @param[in] lock_context The lock context of the corresponding + * _ISR_lock_ISR_disable() that started the critical section. + * * @return The current processor. */ -RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Dispatch_disable_critical( void ) +RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Dispatch_disable_critical( + const ISR_lock_Context *lock_context +) { Per_CPU_Control *cpu_self; uint32_t disable_level; cpu_self = _Per_CPU_Get(); disable_level = cpu_self->thread_dispatch_disable_level; - _Profiling_Thread_dispatch_disable( cpu_self, disable_level ); + _Profiling_Thread_dispatch_disable_critical( + cpu_self, + disable_level, + lock_context + ); cpu_self->thread_dispatch_disable_level = disable_level + 1; return cpu_self; @@ -266,18 +275,17 @@ RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Dispatch_disable_critical( void ) */ RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Dispatch_disable( void ) { - Per_CPU_Control *cpu_self; + Per_CPU_Control *cpu_self; + ISR_lock_Context lock_context; #if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING ) - ISR_Level level; - - _ISR_Disable_without_giant( level ); + _ISR_lock_ISR_disable( &lock_context ); #endif - cpu_self = _Thread_Dispatch_disable_critical(); + cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); #if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING ) - _ISR_Enable_without_giant( level ); + _ISR_lock_ISR_enable( &lock_context ); #endif return cpu_self; diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c index 714552509e..f73fa01173 100644 --- a/cpukit/score/src/threadqenqueue.c +++ b/cpukit/score/src/threadqenqueue.c @@ -67,7 +67,7 @@ void _Thread_queue_Enqueue_critical( ( *operations->enqueue )( the_thread_queue, the_thread ); _Thread_Wait_flags_set( the_thread, THREAD_QUEUE_INTEND_TO_BLOCK ); - cpu_self = _Thread_Dispatch_disable_critical(); + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); _Thread_queue_Release( the_thread_queue, lock_context ); #if defined(RTEMS_MULTIPROCESSING) @@ -138,7 +138,7 @@ void _Thread_queue_Unblock_critical( if ( unblock ) { Per_CPU_Control *cpu_self; - cpu_self = _Thread_Dispatch_disable_critical(); + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); _Thread_queue_Release( the_thread_queue, lock_context ); _Thread_queue_Unblock( the_thread ); -- cgit v1.2.3