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.
This commit is contained in:
Sebastian Huber
2015-05-18 11:09:14 +02:00
parent aa05cfbb3d
commit d542329598
8 changed files with 67 additions and 19 deletions

View File

@@ -84,7 +84,7 @@ void _Event_Seize(
executing->Wait.return_argument = event_out; executing->Wait.return_argument = event_out;
_Thread_Wait_flags_set( executing, intend_to_block ); _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 ); _Thread_Lock_release_default( executing, lock_context );
_Giant_Acquire( cpu_self ); _Giant_Acquire( cpu_self );

View File

@@ -107,7 +107,7 @@ void _Event_Surrender(
if ( unblock ) { if ( unblock ) {
Per_CPU_Control *cpu_self; 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 ); _Thread_Lock_release_default( the_thread, lock_context );
_Giant_Acquire( cpu_self ); _Giant_Acquire( cpu_self );

View File

@@ -489,7 +489,7 @@ RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock_body(
if ( current > ceiling ) { if ( current > ceiling ) {
Per_CPU_Control *cpu_self; 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_queue_Release( &the_mutex->Wait_queue, lock_context );
_Thread_Raise_priority( executing, ceiling ); _Thread_Raise_priority( executing, ceiling );
_Thread_Dispatch_enable( cpu_self ); _Thread_Dispatch_enable( cpu_self );

View File

@@ -68,6 +68,12 @@ typedef struct {
#else #else
ISR_Level isr_level; ISR_Level isr_level;
#endif #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; } ISR_lock_Context;
/** /**
@@ -304,6 +310,13 @@ typedef struct {
_ISR_Flash( ( _context )->isr_level ) _ISR_Flash( ( _context )->isr_level )
#endif #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 * @brief Disables interrupts and saves the previous interrupt state in the ISR
* lock context. * lock context.
@@ -316,10 +329,16 @@ typedef struct {
*/ */
#if defined( RTEMS_SMP ) #if defined( RTEMS_SMP )
#define _ISR_lock_ISR_disable( _context ) \ #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 #else
#define _ISR_lock_ISR_disable( _context ) \ #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 #endif
/** /**

View File

@@ -102,7 +102,7 @@ RTEMS_INLINE_ROUTINE void _MRSP_Claim_ownership(
mrsp->initial_priority_of_owner = initial_priority; mrsp->initial_priority_of_owner = initial_priority;
_Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER ); _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 ); _ISR_lock_Release_and_ISR_enable( &mrsp->Lock, lock_context );
_Thread_Raise_priority( new_owner, ceiling_priority ); _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 ); _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 ); _ISR_lock_Release_and_ISR_enable( &mrsp->Lock, lock_context );
_Thread_Raise_priority( executing, ceiling_priority ); _Thread_Raise_priority( executing, ceiling_priority );
@@ -388,7 +388,7 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Release(
_MRSP_Giant_release( &giant_lock_context ); _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 ); _ISR_lock_Release_and_ISR_enable( &mrsp->Lock, lock_context );
_MRSP_Restore_priority( executing, initial_priority ); _MRSP_Restore_priority( executing, initial_priority );

View File

@@ -24,6 +24,7 @@
#define _RTEMS_SCORE_PROFILING #define _RTEMS_SCORE_PROFILING
#include <rtems/score/percpu.h> #include <rtems/score/percpu.h>
#include <rtems/score/isrlock.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -55,6 +56,26 @@ static inline void _Profiling_Thread_dispatch_disable(
#endif #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( static inline void _Profiling_Thread_dispatch_enable(
Per_CPU_Control *cpu, Per_CPU_Control *cpu,
uint32_t new_thread_dispatch_disable_level uint32_t new_thread_dispatch_disable_level

View File

@@ -15,7 +15,7 @@
#define _RTEMS_SCORE_THREADDISPATCH_H #define _RTEMS_SCORE_THREADDISPATCH_H
#include <rtems/score/percpu.h> #include <rtems/score/percpu.h>
#include <rtems/score/smplock.h> #include <rtems/score/isrlock.h>
#include <rtems/score/profiling.h> #include <rtems/score/profiling.h>
#ifdef __cplusplus #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. * 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. * @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; Per_CPU_Control *cpu_self;
uint32_t disable_level; uint32_t disable_level;
cpu_self = _Per_CPU_Get(); cpu_self = _Per_CPU_Get();
disable_level = cpu_self->thread_dispatch_disable_level; 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; cpu_self->thread_dispatch_disable_level = disable_level + 1;
return cpu_self; 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 ) 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 ) #if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING )
ISR_Level level; _ISR_lock_ISR_disable( &lock_context );
_ISR_Disable_without_giant( level );
#endif #endif
cpu_self = _Thread_Dispatch_disable_critical(); cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
#if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING ) #if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING )
_ISR_Enable_without_giant( level ); _ISR_lock_ISR_enable( &lock_context );
#endif #endif
return cpu_self; return cpu_self;

View File

@@ -67,7 +67,7 @@ void _Thread_queue_Enqueue_critical(
( *operations->enqueue )( the_thread_queue, the_thread ); ( *operations->enqueue )( the_thread_queue, the_thread );
_Thread_Wait_flags_set( the_thread, THREAD_QUEUE_INTEND_TO_BLOCK ); _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 ); _Thread_queue_Release( the_thread_queue, lock_context );
#if defined(RTEMS_MULTIPROCESSING) #if defined(RTEMS_MULTIPROCESSING)
@@ -138,7 +138,7 @@ void _Thread_queue_Unblock_critical(
if ( unblock ) { if ( unblock ) {
Per_CPU_Control *cpu_self; 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_Release( the_thread_queue, lock_context );
_Thread_queue_Unblock( the_thread ); _Thread_queue_Unblock( the_thread );