Changeset fbda4a8 in rtems


Ignore:
Timestamp:
Jul 1, 2014, 8:48:28 AM (7 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, 5, master
Children:
46cd17a
Parents:
f28f5c4
git-author:
Sebastian Huber <sebastian.huber@…> (07/01/14 08:48:28)
git-committer:
Sebastian Huber <sebastian.huber@…> (07/04/14 11:17:19)
Message:

score: PR2183: Fix context switch on SMP

Fix context switch on SMP for ARM, PowerPC and SPARC.

Atomically test and set the is executing indicator of the heir context
to ensure that at most one processor uses the heir context. Break the
busy wait loop also due to heir updates.

Files:
8 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/sparc/shared/irq_asm.S

    rf28f5c4 rfbda4a8  
    77 *  COPYRIGHT (c) 1989-2011.
    88 *  On-Line Applications Research Corporation (OAR).
     9 *
     10 *  Copyright (c) 2014 embedded brains GmbH
    911 *
    1012 *  The license and distribution terms for this file may be
     
    166168#if defined(RTEMS_SMP)
    167169        ! The executing context no longer executes on this processor
    168         stb     %g0, [%o0 + SPARC_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
    169 
    170         ! Wait for heir context to stop execution
    171 1:
    172         ldub    [%o1 + SPARC_CONTEXT_CONTROL_IS_EXECUTING_OFFSET], %g1
     170        st      %g0, [%o0 + SPARC_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
     171
     172        ! Try to update the is executing indicator of the heir context
     173        mov     1, %g1
     174
     175try_update_is_executing:
     176
     177        swap    [%o1 + SPARC_CONTEXT_CONTROL_IS_EXECUTING_OFFSET], %g1
    173178        cmp     %g1, 0
    174         bne     1b
    175          mov    1, %g1
    176 
    177         ! The heir context executes now on this processor
    178         stb     %g1, [%o1 + SPARC_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
     179        bne     check_is_executing
     180
     181        ! The next load is in a delay slot, which is all right
    179182#endif
    180183
     
    203206        jmp     %o7 + 8                       ! return
    204207        nop                                   ! delay slot
     208
     209#if defined(RTEMS_SMP)
     210check_is_executing:
     211
     212        ! Check the is executing indicator of the heir context
     213        ld      [%o1 + SPARC_CONTEXT_CONTROL_IS_EXECUTING_OFFSET], %g1
     214        cmp     %g1, 0
     215        beq     try_update_is_executing
     216         mov    1, %g1
     217
     218        ! Check if a thread dispatch is necessary
     219        ldub    [%g6 + PER_CPU_DISPATCH_NEEDED], %g1
     220        cmp     %g1, 0
     221        beq     check_is_executing
     222         nop
     223
     224        ! We have a new heir
     225
     226        ! Clear the thread dispatch necessary flag
     227        stub    %g0, [%g6 + PER_CPU_DISPATCH_NEEDED]
     228
     229        ! Here we assume a strong memory order, otherwise a memory barrier must
     230        ! be inserted here
     231
     232        ! Read the executing and heir
     233        ld      [%g6 + PER_CPU_OFFSET_EXECUTING], %g1
     234        ld      [%g6 + PER_CPU_OFFSET_HEIR], %g2
     235
     236        ! Calculate the heir context pointer
     237        sub     %o1, %g1, %g1
     238        add     %g1, %g2, %o1
     239
     240        ! Update the executing
     241        st      %g2, [%g6 + PER_CPU_OFFSET_EXECUTING]
     242
     243        ba      try_update_is_executing
     244         mov    1, %g1
     245#endif
    205246
    206247/*
  • c/src/lib/libcpu/powerpc/new-exceptions/cpu_asm.S

    rf28f5c4 rfbda4a8  
    2424 *  On-Line Applications Research Corporation (OAR).
    2525 *
    26  *  Copyright (c) 2011-2013 embedded brains GmbH.
     26 *  Copyright (c) 2011-2014 embedded brains GmbH
    2727 *
    2828 *  The license and distribution terms for this file may in
     
    3333#include <rtems/asm.h>
    3434#include <rtems/powerpc/powerpc.h>
    35 #include <rtems/score/cpu.h>
     35#include <rtems/score/percpu.h>
     36#include <libcpu/powerpc-utility.h>
    3637#include <bspopts.h>
    3738
     
    258259        /* Align to a cache line */
    259260        clrrwi  r3, r3, 5
    260         clrrwi  r4, r4, 5
     261        clrrwi  r5, r4, 5
    261262
    262263        DATA_CACHE_ZERO_AND_TOUCH(r10, PPC_CONTEXT_CACHE_LINE_0)
     
    265266        /* Save context to r3 */
    266267
    267         mfmsr   r5
    268         mflr    r6
    269         mfcr    r7
     268        mfmsr   r6
     269        mflr    r7
     270        mfcr    r8
    270271
    271272        /*
    272273         * We have to clear the reservation of the executing thread.  See also
    273274         * Book E section 6.1.6.2 "Atomic Update Primitives".  Recent GCC
    274          * versions use atomic operations in the C++ library for example.
     275         * versions use atomic operations in the C++ library for example.  On
     276         * SMP configurations the reservation is cleared later during the
     277         * context switch.
    275278         */
    276279#if PPC_CONTEXT_OFFSET_GPR1 != PPC_CONTEXT_CACHE_LINE_0 \
     
    279282        li      r10, PPC_CONTEXT_OFFSET_GPR1
    280283#endif
     284#ifndef RTEMS_SMP
    281285        stwcx.  r1, r3, r10
     286#endif
    282287
    283288        stw     r1, PPC_CONTEXT_OFFSET_GPR1(r3)
    284         stw     r5, PPC_CONTEXT_OFFSET_MSR(r3)
    285         stw     r6, PPC_CONTEXT_OFFSET_LR(r3)
    286         stw     r7, PPC_CONTEXT_OFFSET_CR(r3)
     289        stw     r6, PPC_CONTEXT_OFFSET_MSR(r3)
     290        stw     r7, PPC_CONTEXT_OFFSET_LR(r3)
     291        stw     r8, PPC_CONTEXT_OFFSET_CR(r3)
    287292        PPC_GPR_STORE   r14, PPC_CONTEXT_OFFSET_GPR14(r3)
    288293        PPC_GPR_STORE   r15, PPC_CONTEXT_OFFSET_GPR15(r3)
     
    330335        /* The executing context no longer executes on this processor */
    331336        msync
    332         li      r5, 0
    333         stb     r5, PPC_CONTEXT_OFFSET_IS_EXECUTING(r3)
    334 
    335         /* Wait for heir context to stop execution */
    336 1:
    337         lbz     r5, PPC_CONTEXT_OFFSET_IS_EXECUTING(r4)
    338         cmpwi   r5, 0
    339         bne     1b
    340 
    341         /* The heir context executes now on this processor */
    342         li      r5, 1
    343         stb     r5, PPC_CONTEXT_OFFSET_IS_EXECUTING(r4)
    344         isync
    345 #endif
    346 
    347         /* Restore context from r4 */
     337        li      r6, 0
     338        stw     r6, PPC_CONTEXT_OFFSET_IS_EXECUTING(r3)
     339
     340check_is_executing:
     341
     342        /* Check the is executing indicator of the heir context */
     343        addi    r6, r5, PPC_CONTEXT_OFFSET_IS_EXECUTING
     344        lwarx   r7, r0, r6
     345        cmpwi   r7, 0
     346        bne     check_thread_dispatch_necessary
     347
     348        /* Try to update the is executing indicator of the heir context */
     349        li      r7, 1
     350        stwcx.  r7, r0, r6
     351        bne     check_thread_dispatch_necessary
     352        isync
     353#endif
     354
     355        /* Restore context from r5 */
    348356restore_context:
    349357
    350358#ifdef __ALTIVEC__
    351         mr      r14, r4
     359        mr      r14, r5
    352360        .extern _CPU_Context_switch_altivec
    353361        bl      _CPU_Context_switch_altivec
    354         mr      r4, r14
    355 #endif
    356 
    357         lwz     r1, PPC_CONTEXT_OFFSET_GPR1(r4)
    358         lwz     r5, PPC_CONTEXT_OFFSET_MSR(r4)
    359         lwz     r6, PPC_CONTEXT_OFFSET_LR(r4)
    360         lwz     r7, PPC_CONTEXT_OFFSET_CR(r4)
    361 
    362         PPC_GPR_LOAD    r14, PPC_CONTEXT_OFFSET_GPR14(r4)
    363         PPC_GPR_LOAD    r15, PPC_CONTEXT_OFFSET_GPR15(r4)
     362        mr      r5, r14
     363#endif
     364
     365        lwz     r1, PPC_CONTEXT_OFFSET_GPR1(r5)
     366        lwz     r6, PPC_CONTEXT_OFFSET_MSR(r5)
     367        lwz     r7, PPC_CONTEXT_OFFSET_LR(r5)
     368        lwz     r8, PPC_CONTEXT_OFFSET_CR(r5)
     369
     370        PPC_GPR_LOAD    r14, PPC_CONTEXT_OFFSET_GPR14(r5)
     371        PPC_GPR_LOAD    r15, PPC_CONTEXT_OFFSET_GPR15(r5)
    364372
    365373        DATA_CACHE_TOUCH(r0, r1)
    366374
    367         PPC_GPR_LOAD    r16, PPC_CONTEXT_OFFSET_GPR16(r4)
    368         PPC_GPR_LOAD    r17, PPC_CONTEXT_OFFSET_GPR17(r4)
    369         PPC_GPR_LOAD    r18, PPC_CONTEXT_OFFSET_GPR18(r4)
    370         PPC_GPR_LOAD    r19, PPC_CONTEXT_OFFSET_GPR19(r4)
    371 
    372         PPC_GPR_LOAD    r20, PPC_CONTEXT_OFFSET_GPR20(r4)
    373         PPC_GPR_LOAD    r21, PPC_CONTEXT_OFFSET_GPR21(r4)
    374         PPC_GPR_LOAD    r22, PPC_CONTEXT_OFFSET_GPR22(r4)
    375         PPC_GPR_LOAD    r23, PPC_CONTEXT_OFFSET_GPR23(r4)
    376 
    377         PPC_GPR_LOAD    r24, PPC_CONTEXT_OFFSET_GPR24(r4)
    378         PPC_GPR_LOAD    r25, PPC_CONTEXT_OFFSET_GPR25(r4)
    379         PPC_GPR_LOAD    r26, PPC_CONTEXT_OFFSET_GPR26(r4)
    380         PPC_GPR_LOAD    r27, PPC_CONTEXT_OFFSET_GPR27(r4)
    381 
    382         PPC_GPR_LOAD    r28, PPC_CONTEXT_OFFSET_GPR28(r4)
    383         PPC_GPR_LOAD    r29, PPC_CONTEXT_OFFSET_GPR29(r4)
    384         PPC_GPR_LOAD    r30, PPC_CONTEXT_OFFSET_GPR30(r4)
    385         PPC_GPR_LOAD    r31, PPC_CONTEXT_OFFSET_GPR31(r4)
    386 
    387         lwz     r2, PPC_CONTEXT_OFFSET_GPR2(r4)
    388 
    389         mtcr    r7
    390         mtlr    r6
    391         mtmsr   r5
     375        PPC_GPR_LOAD    r16, PPC_CONTEXT_OFFSET_GPR16(r5)
     376        PPC_GPR_LOAD    r17, PPC_CONTEXT_OFFSET_GPR17(r5)
     377        PPC_GPR_LOAD    r18, PPC_CONTEXT_OFFSET_GPR18(r5)
     378        PPC_GPR_LOAD    r19, PPC_CONTEXT_OFFSET_GPR19(r5)
     379
     380        PPC_GPR_LOAD    r20, PPC_CONTEXT_OFFSET_GPR20(r5)
     381        PPC_GPR_LOAD    r21, PPC_CONTEXT_OFFSET_GPR21(r5)
     382        PPC_GPR_LOAD    r22, PPC_CONTEXT_OFFSET_GPR22(r5)
     383        PPC_GPR_LOAD    r23, PPC_CONTEXT_OFFSET_GPR23(r5)
     384
     385        PPC_GPR_LOAD    r24, PPC_CONTEXT_OFFSET_GPR24(r5)
     386        PPC_GPR_LOAD    r25, PPC_CONTEXT_OFFSET_GPR25(r5)
     387        PPC_GPR_LOAD    r26, PPC_CONTEXT_OFFSET_GPR26(r5)
     388        PPC_GPR_LOAD    r27, PPC_CONTEXT_OFFSET_GPR27(r5)
     389
     390        PPC_GPR_LOAD    r28, PPC_CONTEXT_OFFSET_GPR28(r5)
     391        PPC_GPR_LOAD    r29, PPC_CONTEXT_OFFSET_GPR29(r5)
     392        PPC_GPR_LOAD    r30, PPC_CONTEXT_OFFSET_GPR30(r5)
     393        PPC_GPR_LOAD    r31, PPC_CONTEXT_OFFSET_GPR31(r5)
     394
     395        lwz     r2, PPC_CONTEXT_OFFSET_GPR2(r5)
     396
     397        mtcr    r8
     398        mtlr    r7
     399        mtmsr   r6
    392400
    393401#ifdef BSP_USE_SYNC_IN_CONTEXT_SWITCH
     
    400408PROC (_CPU_Context_restore):
    401409        /* Align to a cache line */
    402         clrrwi  r4, r3, 5
     410        clrrwi  r5, r3, 5
    403411
    404412#ifdef __ALTIVEC__
     
    407415
    408416        b       restore_context
     417
     418#ifdef RTEMS_SMP
     419check_thread_dispatch_necessary:
     420
     421        GET_SELF_CPU_CONTROL    r6
     422
     423        /* Check if a thread dispatch is necessary */
     424        lbz     r7, PER_CPU_DISPATCH_NEEDED(r6)
     425        cmpwi   r7, 0
     426        beq     check_is_executing
     427
     428        /* We have a new heir */
     429
     430        /* Clear the thread dispatch necessary flag */
     431        li      r7, 0
     432        stb     r7, PER_CPU_DISPATCH_NEEDED(r6)
     433        msync
     434
     435        /* Read the executing and heir */
     436        lwz     r7, PER_CPU_OFFSET_EXECUTING(r6)
     437        lwz     r8, PER_CPU_OFFSET_HEIR(r6)
     438
     439        /* Calculate the heir context pointer */
     440        sub     r7, r4, r7
     441        add     r4, r8, r7
     442        clrrwi  r5, r4, 5
     443
     444        /* Update the executing */
     445        stw     r8, PER_CPU_OFFSET_EXECUTING(r6)
     446
     447        b       check_is_executing
     448#endif
  • cpukit/score/cpu/arm/arm_exc_interrupt.S

    rf28f5c4 rfbda4a8  
    3232
    3333#include <rtems/asm.h>
    34 #include <rtems/score/percpu.h>
    3534
    3635#ifdef ARM_MULTILIB_ARCH_V4
     
    4948#define CONTEXT_LIST {r0, r1, r2, r3, EXCHANGE_LR, EXCHANGE_SPSR, SELF_CPU_CONTROL, r12}
    5049#define CONTEXT_SIZE 32
    51 
    52 .macro GET_SELF_CPU_CONTROL REG, TMP
    53         ldr     \REG, =_Per_CPU_Information
    54 #ifdef RTEMS_SMP
    55         /* Use ARMv7 Multiprocessor Affinity Register (MPIDR) */
    56         mrc     p15, 0, \TMP, c0, c0, 5
    57 
    58         and     \TMP, \TMP, #0xff
    59         add     \REG, \REG, \TMP, asl #PER_CPU_CONTROL_SIZE_LOG2
    60 #endif
    61 .endm
    6250
    6351.arm
  • cpukit/score/cpu/arm/cpu_asm.S

    rf28f5c4 rfbda4a8  
    2020 *  Emmanuel Raguet, mailto:raguet@crf.canon.fr
    2121 *
     22 *  Copyright (c) 2013-2014 embedded brains GmbH
     23 *
    2224 *  The license and distribution terms for this file may be
    2325 *  found in the file LICENSE in this distribution or at
     
    3133
    3234#include <rtems/asm.h>
    33 #include <rtems/score/cpu.h>
    3435
    3536#ifdef ARM_MULTILIB_ARCH_V4
     
    7475        strb    r3, [r0, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
    7576
    76         /* Wait for heir context to stop execution */
    77 1:
    78         ldrb    r3, [r1, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
    79         cmp     r3, #0
    80         bne     1b
     77.L_check_is_executing:
    8178
    82         /* The heir context executes now on this processor */
     79        /* Check the is executing indicator of the heir context */
     80        add     r3, r1, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET
     81        ldrexb  r4, [r3]
     82        cmp     r4, #0
     83        bne     .L_check_thread_dispatch_necessary
     84
     85        /* Try to update the is executing indicator of the heir context */
     86        mov     r4, #1
     87        strexb  r5, r4, [r3]
     88        cmp     r5, #0
     89        bne     .L_check_thread_dispatch_necessary
    8390        dmb
    84         mov     r3, #1
    85         strb    r3, [r1, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
    8691#endif
    8792
    8893/* Start restoring context */
    8994.L_restore:
    90 #ifdef ARM_MULTILIB_HAS_LOAD_STORE_EXCLUSIVE
     95#if !defined(RTEMS_SMP) && defined(ARM_MULTILIB_HAS_LOAD_STORE_EXCLUSIVE)
    9196        clrex
    9297#endif
     
    121126        b       .L_restore
    122127
     128#ifdef RTEMS_SMP
     129.L_check_thread_dispatch_necessary:
     130
     131        GET_SELF_CPU_CONTROL    r2, r3
     132
     133        /* Check if a thread dispatch is necessary */
     134        ldrb    r4, [r2, #PER_CPU_DISPATCH_NEEDED]
     135        cmp     r4, #0
     136        beq     .L_check_is_executing
     137
     138        /* We have a new heir */
     139
     140        /* Clear the thread dispatch necessary flag */
     141        mov     r4, #0
     142        strb    r4, [r2, #PER_CPU_DISPATCH_NEEDED]
     143        dmb
     144
     145        /* Read the executing and heir */
     146        ldr     r4, [r2, #PER_CPU_OFFSET_EXECUTING]
     147        ldr     r5, [r2, #PER_CPU_OFFSET_HEIR]
     148
     149        /* Calculate the heir context pointer */
     150        sub     r4, r1, r4
     151        add     r1, r5, r4
     152
     153        /* Update the executing */
     154        str     r5, [r2, #PER_CPU_OFFSET_EXECUTING]
     155
     156        b       .L_check_is_executing
     157#endif
     158
    123159#endif /* ARM_MULTILIB_ARCH_V4 */
  • cpukit/score/cpu/arm/rtems/asm.h

    rf28f5c4 rfbda4a8  
    4242#define ASM
    4343#endif
    44 #include <rtems/score/cpuopts.h>
    45 #include <rtems/score/arm.h>
     44#include <rtems/score/percpu.h>
    4645
    4746/**
     
    189188.endm
    190189
     190.macro GET_SELF_CPU_CONTROL REG, TMP
     191        ldr     \REG, =_Per_CPU_Information
     192#ifdef RTEMS_SMP
     193        /* Use ARMv7 Multiprocessor Affinity Register (MPIDR) */
     194        mrc     p15, 0, \TMP, c0, c0, 5
     195
     196        and     \TMP, \TMP, #0xff
     197        add     \REG, \REG, \TMP, asl #PER_CPU_CONTROL_SIZE_LOG2
     198#endif
     199.endm
     200
    191201/** @} */
    192202
  • cpukit/score/cpu/no_cpu/rtems/score/cpu.h

    rf28f5c4 rfbda4a8  
    579579    /**
    580580     * @brief On SMP configurations the thread context must contain a boolean
    581      * indicator if this context is executing on a processor.
     581     * indicator to signal if this context is executing on a processor.
    582582     *
    583583     * This field must be updated during a context switch.  The context switch
    584584     * to the heir must wait until the heir context indicates that it is no
    585      * longer executing on a processor.
     585     * longer executing on a processor.  The context switch must also check if
     586     * a thread dispatch is necessary to honor updates of the heir thread for
     587     * this processor.  This indicator must be updated using an atomic test and
     588     * set operation to ensure that at most one processor uses the heir
     589     * context at the same time.
     590     *
     591     * @code
     592     * void _CPU_Context_switch(
     593     *   Context_Control *executing,
     594     *   Context_Control *heir
     595     * )
     596     * {
     597     *   save( executing );
     598     *
     599     *   executing->is_executing = false;
     600     *   memory_barrier();
     601     *
     602     *   if ( test_and_set( &heir->is_executing ) ) {
     603     *     do {
     604     *       Per_CPU_Control *cpu_self = _Per_CPU_Get_snapshot();
     605     *
     606     *       if ( cpu_self->dispatch_necessary ) {
     607     *         heir = _Thread_Get_heir_and_make_it_executing( cpu_self );
     608     *       }
     609     *     } while ( test_and_set( &heir->is_executing ) );
     610     *   }
     611     *
     612     *   restore( heir );
     613     * }
     614     * @endcode
    586615     */
    587616    volatile bool is_executing;
  • cpukit/score/cpu/powerpc/rtems/score/cpu.h

    rf28f5c4 rfbda4a8  
    304304  uint32_t gpr2;
    305305  #ifdef RTEMS_SMP
    306     volatile bool is_executing;
     306    volatile uint32_t is_executing;
    307307  #endif
    308308  #ifdef __ALTIVEC__
  • cpukit/score/cpu/sparc/rtems/score/cpu.h

    rf28f5c4 rfbda4a8  
    476476
    477477#if defined(RTEMS_SMP)
    478   volatile bool is_executing;
     478  volatile uint32_t is_executing;
    479479#endif
    480480} Context_Control;
Note: See TracChangeset for help on using the changeset viewer.