summaryrefslogtreecommitdiffstats
path: root/cpukit/score
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-11-11 14:37:51 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-11-18 07:30:34 +0100
commitd5e073cde70211b2471e4366be397370e9f6ce48 (patch)
tree7ee1e3cad3dd7dfbb52475af7bacc61b216dc0e5 /cpukit/score
parentscore: Add Per_CPU_Control::Interrupt_frame (diff)
downloadrtems-d5e073cde70211b2471e4366be397370e9f6ce48.tar.bz2
score: Allow interrupts during thread dispatch
Use a processor-specific interrupt frame during context switches in case the executing thread is longer executes on the processor and the heir thread is about to start execution. During this period we must not use a thread stack for interrupt processing. Update #2809.
Diffstat (limited to 'cpukit/score')
-rw-r--r--cpukit/score/cpu/arm/cpu_asm.S10
-rw-r--r--cpukit/score/include/rtems/score/userextimpl.h13
-rw-r--r--cpukit/score/src/threaddispatch.c17
-rw-r--r--cpukit/score/src/threadhandler.c3
-rw-r--r--cpukit/score/src/threadloadenv.c16
5 files changed, 21 insertions, 38 deletions
diff --git a/cpukit/score/cpu/arm/cpu_asm.S b/cpukit/score/cpu/arm/cpu_asm.S
index cf94822eaf..1ad3a51b14 100644
--- a/cpukit/score/cpu/arm/cpu_asm.S
+++ b/cpukit/score/cpu/arm/cpu_asm.S
@@ -69,8 +69,14 @@ DEFINE_FUNCTION_ARM(_CPU_Context_switch)
#endif
#ifdef RTEMS_SMP
- /* The executing context no longer executes on this processor */
+ /*
+ * The executing thread no longer executes on this processor. Switch
+ * the stack to the temporary interrupt stack of this processor. Mark
+ * the context of the executing thread as not executing.
+ */
dmb
+ GET_SELF_CPU_CONTROL r2
+ add sp, r2, #(PER_CPU_INTERRUPT_FRAME_AREA + CPU_INTERRUPT_FRAME_SIZE)
mov r3, #0
strb r3, [r0, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
@@ -128,8 +134,6 @@ DEFINE_FUNCTION_ARM(_CPU_Context_restore)
#ifdef RTEMS_SMP
.L_get_potential_new_heir:
- GET_SELF_CPU_CONTROL r2
-
/* We may have a new heir */
/* Read the executing and heir */
diff --git a/cpukit/score/include/rtems/score/userextimpl.h b/cpukit/score/include/rtems/score/userextimpl.h
index e175c9f0a5..e6692c8749 100644
--- a/cpukit/score/include/rtems/score/userextimpl.h
+++ b/cpukit/score/include/rtems/score/userextimpl.h
@@ -261,8 +261,16 @@ static inline void _User_extensions_Thread_switch(
const Chain_Node *node = _Chain_Immutable_first( chain );
if ( node != tail ) {
- Per_CPU_Control *cpu_self = _Per_CPU_Get();
+ Per_CPU_Control *cpu_self;
+#if defined(RTEMS_SMP)
+ ISR_Level level;
+#endif
+
+ cpu_self = _Per_CPU_Get();
+#if defined(RTEMS_SMP)
+ _ISR_Local_disable( level );
+#endif
_Per_CPU_Acquire( cpu_self );
while ( node != tail ) {
@@ -275,6 +283,9 @@ static inline void _User_extensions_Thread_switch(
}
_Per_CPU_Release( cpu_self );
+#if defined(RTEMS_SMP)
+ _ISR_Local_enable( level );
+#endif
}
}
diff --git a/cpukit/score/src/threaddispatch.c b/cpukit/score/src/threaddispatch.c
index c96299cb59..f2c24905dc 100644
--- a/cpukit/score/src/threaddispatch.c
+++ b/cpukit/score/src/threaddispatch.c
@@ -174,14 +174,7 @@ void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level )
if ( heir->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE )
heir->cpu_time_budget = rtems_configuration_get_ticks_per_timeslice();
- /*
- * On SMP the complete context switch must be atomic with respect to one
- * processor. See also _Thread_Handler() since _Context_switch() may branch
- * to this function.
- */
-#if !defined( RTEMS_SMP )
_ISR_Local_enable( level );
-#endif
_User_extensions_Thread_switch( executing, heir );
_Thread_Save_fp( executing );
@@ -195,16 +188,8 @@ void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level )
*/
cpu_self = _Per_CPU_Get();
-#if !defined( RTEMS_SMP )
_ISR_Local_disable( level );
-#endif
- } while (
-#if defined( RTEMS_SMP )
- false
-#else
- cpu_self->dispatch_necessary
-#endif
- );
+ } while ( cpu_self->dispatch_necessary );
post_switch:
_Assert( cpu_self->thread_dispatch_disable_level == 1 );
diff --git a/cpukit/score/src/threadhandler.c b/cpukit/score/src/threadhandler.c
index 397e0cf95a..a8d65804af 100644
--- a/cpukit/score/src/threadhandler.c
+++ b/cpukit/score/src/threadhandler.c
@@ -38,9 +38,6 @@ void _Thread_Handler( void )
_Context_Initialization_at_thread_begin();
executing = _Thread_Executing;
- /* On SMP we enter _Thread_Handler() with interrupts disabled */
- _SMP_Assert( _ISR_Get_level() != 0 );
-
/*
* have to put level into a register for those cpu's that use
* inline asm here
diff --git a/cpukit/score/src/threadloadenv.c b/cpukit/score/src/threadloadenv.c
index 43564af878..22606ddd08 100644
--- a/cpukit/score/src/threadloadenv.c
+++ b/cpukit/score/src/threadloadenv.c
@@ -25,8 +25,6 @@ void _Thread_Load_environment(
Thread_Control *the_thread
)
{
- uint32_t isr_level;
-
#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
if ( the_thread->Start.fp_context ) {
the_thread->fp_context = the_thread->Start.fp_context;
@@ -38,25 +36,13 @@ void _Thread_Load_environment(
the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
the_thread->budget_callout = the_thread->Start.budget_callout;
-#if defined( RTEMS_SMP )
- /*
- * On SMP we have to start the threads with interrupts disabled, see also
- * _Thread_Handler() and _Thread_Dispatch(). In _Thread_Handler() the
- * _ISR_Set_level() is used to set the desired interrupt state of the thread.
- */
- isr_level = CPU_MODES_INTERRUPT_MASK;
-#else
- isr_level = the_thread->Start.isr_level;
-#endif
-
_Context_Initialize(
&the_thread->Registers,
the_thread->Start.Initial_stack.area,
the_thread->Start.Initial_stack.size,
- isr_level,
+ the_thread->Start.isr_level,
_Thread_Handler,
the_thread->is_fp,
the_thread->Start.tls_area
);
-
}