summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src/threadhandler.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2015-02-26 10:32:08 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-03-05 11:36:19 +0100
commit222dc775838c73708054db6283723027c5deb56c (patch)
tree13ef9e9fa22774f804cef04a61d459dc7d2fd89e /cpukit/score/src/threadhandler.c
parentscore: Simplify and fix signal delivery (diff)
downloadrtems-222dc775838c73708054db6283723027c5deb56c.tar.bz2
score: Add and use _Thread_Do_dispatch()
The _Thread_Dispatch() function is quite complex and the time to set up and tear down the stack frame is significant. Split this function into two parts. The complex part is now in _Thread_Do_dispatch(). Call _Thread_Do_dispatch() in _Thread_Enable_dispatch() only if necessary. This increases the average case performance. Simplify _Thread_Handler() for SMP configurations. Update #2273.
Diffstat (limited to 'cpukit/score/src/threadhandler.c')
-rw-r--r--cpukit/score/src/threadhandler.c70
1 files changed, 31 insertions, 39 deletions
diff --git a/cpukit/score/src/threadhandler.c b/cpukit/score/src/threadhandler.c
index db7302807c..fd828a2325 100644
--- a/cpukit/score/src/threadhandler.c
+++ b/cpukit/score/src/threadhandler.c
@@ -26,9 +26,9 @@
void _Thread_Handler( void )
{
- Thread_Control *executing = _Thread_Executing;
- ISR_Level level;
-
+ Thread_Control *executing = _Thread_Executing;
+ ISR_Level level;
+ Per_CPU_Control *cpu_self;
/*
* Some CPUs need to tinker with the call frame or registers when the
@@ -37,16 +37,21 @@ void _Thread_Handler( void )
*/
_Context_Initialization_at_thread_begin();
- #if !defined(RTEMS_SMP)
- /*
- * have to put level into a register for those cpu's that use
- * inline asm here
- */
- level = executing->Start.isr_level;
- _ISR_Set_level( level );
+ #if defined(RTEMS_SMP)
+ /* On SMP we enter _Thread_Handler() with interrupts disabled */
+ _Assert( _ISR_Get_level() != 0 );
+
+ _Thread_Debug_set_real_processor( executing, _Per_CPU_Get() );
#endif
/*
+ * have to put level into a register for those cpu's that use
+ * inline asm here
+ */
+ level = executing->Start.isr_level;
+ _ISR_Set_level( level );
+
+ /*
* Initialize the floating point context because we do not come
* through _Thread_Dispatch on our first invocation. So the normal
* code path for performing the FP context switch is not hit.
@@ -61,37 +66,24 @@ void _Thread_Handler( void )
_User_extensions_Thread_begin( executing );
/*
+ * Do not use the level of the thread control block, since it has a
+ * different format.
+ */
+ _ISR_Disable_without_giant( level );
+
+ /*
* At this point, the dispatch disable level BETTER be 1.
*/
- #if defined(RTEMS_SMP)
- {
- /*
- * On SMP we enter _Thread_Handler() with interrupts disabled and
- * _Thread_Dispatch() obtained the per-CPU lock for us. We have to
- * release it here and set the desired interrupt level of the thread.
- */
- Per_CPU_Control *cpu_self = _Per_CPU_Get();
-
- _Assert( cpu_self->thread_dispatch_disable_level == 1 );
- _Assert( _ISR_Get_level() != 0 );
-
- _Thread_Debug_set_real_processor( executing, cpu_self );
-
- cpu_self->thread_dispatch_disable_level = 0;
- _Profiling_Thread_dispatch_enable( cpu_self, 0 );
-
- level = executing->Start.isr_level;
- _ISR_Set_level( level);
-
- /*
- * The thread dispatch level changed from one to zero. Make sure we lose
- * no thread dispatch necessary update.
- */
- _Thread_Dispatch();
- }
- #else
- _Thread_Enable_dispatch();
- #endif
+ cpu_self = _Per_CPU_Get();
+ _Assert( cpu_self->thread_dispatch_disable_level == 1 );
+
+ /*
+ * Make sure we lose no thread dispatch necessary update and execute the
+ * post-switch actions. As a side-effect change the thread dispatch level
+ * from one to zero. Do not use _Thread_Enable_dispatch() since there is no
+ * valid thread dispatch necessary indicator in this context.
+ */
+ _Thread_Do_dispatch( cpu_self, level );
/*
* RTEMS supports multiple APIs and each API can define a different