diff options
Diffstat (limited to 'cpukit/score/cpu/arm/cpu_asm.S')
-rw-r--r-- | cpukit/score/cpu/arm/cpu_asm.S | 56 |
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 */ |