summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2015-05-18 11:09:14 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-05-19 15:14:33 +0200
commitd5423295988918f45b64d50cf0b9501a56b9aa36 (patch)
treede09916f70f4f10b47cf080e7149c1cef2c47198
parentaa05cfbb3d6309ec45b69f34d0870465fe30b74c (diff)
downloadrtems-d5423295988918f45b64d50cf0b9501a56b9aa36.tar.bz2
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.
-rw-r--r--cpukit/rtems/src/eventseize.c2
-rw-r--r--cpukit/rtems/src/eventsurrender.c2
-rw-r--r--cpukit/score/include/rtems/score/coremuteximpl.h2
-rw-r--r--cpukit/score/include/rtems/score/isrlock.h23
-rw-r--r--cpukit/score/include/rtems/score/mrspimpl.h6
-rw-r--r--cpukit/score/include/rtems/score/profiling.h21
-rw-r--r--cpukit/score/include/rtems/score/threaddispatch.h26
-rw-r--r--cpukit/score/src/threadqenqueue.c4
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 <rtems/score/percpu.h>
+#include <rtems/score/isrlock.h>
#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 <rtems/score/percpu.h>
-#include <rtems/score/smplock.h>
+#include <rtems/score/isrlock.h>
#include <rtems/score/profiling.h>
#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 );