zoukankan      html  css  js  c++  java
  • Spinlock implementation in ARM architecture

    Spinlock implementation in ARM architecture

     

    SEV and WFE are the main instructions used for implementing spinlock in case of ARM architecture. Let's look briefly at those two instructions before looking into actual spinlock implementation.

    SEV

    SEV causes an event to be signaled to all cores within a multiprocessor system. If SEV is implemented, WFE must also be implemented.

    WFE

    If the Event Register is not set, WFE suspends execution until one of the following events occurs:
    • an IRQ interrupt, unless masked by the CPSR I-bit
    • an FIQ interrupt, unless masked by the CPSR F-bit
    • an Imprecise Data abort, unless masked by the CPSR A-bit
    • a Debug Entry request, if Debug is enabled
    • an Event signaled by another processor using the SEV instruction.

    In case of spin_lock_irq( )/spin_lock_irqsave( ),
    • as IRQs are disabled, the only way to to resume after WFE intruction has executed is to execute SEV instruction on some other core.

    In case of spin_lock( ),
    • If IRQs are enabled even before we had called spin_lock( ) and we executed WFE and execution got suspended,
      • Scenario 1: Interrupt occured and handled; we resume, but as the lock was still unreleased, we will loopback and execute WFE.
      • Scenario 2: Some other core executed WFE and released some other lock (but didn't release our lock); we resume; as the lock is still unreleased, we will loopback and execute WFE.
      • Scenario 3: Some other core executed WFE and released this lock; we resume; as the lock was released, we will acquire the lock.
    • If IRQs are disabled before calling spin_lock(), then the situation is same as spin_lock_irqsave().

    In case of spin_unlock( ),
    • lock is released and SEV instruction is executed.


    Check out the following code snippets for actual implementation:


    static inline void arch_spin_lock(arch_spinlock_t *lock)
    {
            unsigned long tmp;

            __asm__ __volatile__(
    "1:     ldrex   %0, [%1] "
    "       teq     %0, #0 "
            WFE("ne")
    "       strexeq %0, %2, [%1] "
    "       teqeq   %0, #0 "
    "       bne     1b"
            : "=&r" (tmp)
            : "r" (&lock->lock), "r" (1)
            : "cc");

            smp_mb();
    }



    static inline void arch_spin_unlock(arch_spinlock_t *lock)
    {
            smp_mb();

            __asm__ __volatile__(
    "       str     %1, [%0] "
            :
            : "r" (&lock->lock), "r" (0)
            : "cc");

            dsb_sev();
    }


    static inline void dsb_sev(void)
    {
    #if __LINUX_ARM_ARCH__ >= 7
            __asm__ __volatile__ (
                    "dsb "
                    SEV
            );
    #else
            __asm__ __volatile__ (
                    "mcr p15, 0, %0, c7, c10, 4 "
                    SEV
                    : : "r" (0)
            );
    #endif
    }


    For more information, check arch/arm/include/asm/spinlock.h in Linux kernel source code. The above code snippet is from 3.4 kernel.
    SRC=http://linuxkernelarticles.blogspot.com/2013/02/spinlock-implementation-in-arm.html
  • 相关阅读:
    分层图最短路(DP思想) BZOJ2662 [BeiJing wc2012]冻结
    动态规划 BZOJ1925 地精部落
    线性DP SPOJ Mobile Service
    线性DP codevs2185 最长公共上升子序列
    数位DP POJ3208 Apocalypse Someday
    线性DP POJ3666 Making the Grade
    杨氏矩阵 线性DP? POJ2279 Mr.Young's Picture Permutations
    tarjan强连通分量 洛谷P1262 间谍网络
    树链剖分 BZOJ3589 动态树
    二分图 BZOJ4554 [Tjoi2016&Heoi2016]游戏
  • 原文地址:https://www.cnblogs.com/coryxie/p/3826450.html
Copyright © 2011-2022 走看看