[rtems commit] score: _Thread_Dispatch_disable_critical()

Sebastian Huber sebh at rtems.org
Wed May 20 07:12:03 UTC 2015


Module:    rtems
Branch:    master
Commit:    d5423295988918f45b64d50cf0b9501a56b9aa36
Changeset: http://git.rtems.org/rtems/commit/?id=d5423295988918f45b64d50cf0b9501a56b9aa36

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon May 18 11:09:14 2015 +0200

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 6611a8d..981c7d2 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 b740721..a16d40e 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 ca9d61d..f57fdfc 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 5a68937..994eb48 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 82ecb07..bc9ed4b 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 f5fa6cc..a6ab283 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 89f5c0b..4ef5538 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 7145525..f73fa01 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 );




More information about the vc mailing list