summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/arm/cpu_asm.S
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/cpu/arm/cpu_asm.S')
-rw-r--r--cpukit/score/cpu/arm/cpu_asm.S56
1 files changed, 46 insertions, 10 deletions
diff --git a/cpukit/score/cpu/arm/cpu_asm.S b/cpukit/score/cpu/arm/cpu_asm.S
index 7502923974..d4355b4e98 100644
--- a/cpukit/score/cpu/arm/cpu_asm.S
+++ b/cpukit/score/cpu/arm/cpu_asm.S
@@ -19,6 +19,8 @@
* COPYRIGHT (c) 2000 Canon Research Centre France SA.
* Emmanuel Raguet, mailto:raguet@crf.canon.fr
*
+ * Copyright (c) 2013-2014 embedded brains GmbH
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
@@ -30,7 +32,6 @@
#endif
#include <rtems/asm.h>
-#include <rtems/score/cpu.h>
#ifdef ARM_MULTILIB_ARCH_V4
@@ -73,21 +74,25 @@ DEFINE_FUNCTION_ARM(_CPU_Context_switch)
mov r3, #0
strb r3, [r0, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
- /* Wait for heir context to stop execution */
-1:
- ldrb r3, [r1, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
- cmp r3, #0
- bne 1b
+.L_check_is_executing:
+
+ /* Check the is executing indicator of the heir context */
+ add r3, r1, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET
+ ldrexb r4, [r3]
+ cmp r4, #0
+ bne .L_check_thread_dispatch_necessary
- /* The heir context executes now on this processor */
+ /* Try to update the is executing indicator of the heir context */
+ mov r4, #1
+ strexb r5, r4, [r3]
+ cmp r5, #0
+ bne .L_check_thread_dispatch_necessary
dmb
- mov r3, #1
- strb r3, [r1, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
#endif
/* Start restoring context */
.L_restore:
-#ifdef ARM_MULTILIB_HAS_LOAD_STORE_EXCLUSIVE
+#if !defined(RTEMS_SMP) && defined(ARM_MULTILIB_HAS_LOAD_STORE_EXCLUSIVE)
clrex
#endif
@@ -120,4 +125,35 @@ DEFINE_FUNCTION_ARM(_CPU_Context_restore)
mov r1, r0
b .L_restore
+#ifdef RTEMS_SMP
+.L_check_thread_dispatch_necessary:
+
+ GET_SELF_CPU_CONTROL r2, r3
+
+ /* Check if a thread dispatch is necessary */
+ ldrb r4, [r2, #PER_CPU_DISPATCH_NEEDED]
+ cmp r4, #0
+ beq .L_check_is_executing
+
+ /* We have a new heir */
+
+ /* Clear the thread dispatch necessary flag */
+ mov r4, #0
+ strb r4, [r2, #PER_CPU_DISPATCH_NEEDED]
+ dmb
+
+ /* Read the executing and heir */
+ ldr r4, [r2, #PER_CPU_OFFSET_EXECUTING]
+ ldr r5, [r2, #PER_CPU_OFFSET_HEIR]
+
+ /* Calculate the heir context pointer */
+ sub r4, r1, r4
+ add r1, r5, r4
+
+ /* Update the executing */
+ str r5, [r2, #PER_CPU_OFFSET_EXECUTING]
+
+ b .L_check_is_executing
+#endif
+
#endif /* ARM_MULTILIB_ARCH_V4 */