diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-02-26 10:32:08 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-03-05 11:36:19 +0100 |
commit | 222dc775838c73708054db6283723027c5deb56c (patch) | |
tree | 13ef9e9fa22774f804cef04a61d459dc7d2fd89e /cpukit/score/src/threadhandler.c | |
parent | score: Simplify and fix signal delivery (diff) | |
download | rtems-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.c | 70 |
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 |