linux代码之LL/SC/LSE 及锁指令

/*
 * LL/SC
 */
    load-link与store-conditional (LL/SC)是一对用于并发同步访问内存的CPU指令。Load-link返回内存位置处的当前值,
    随后的store-conditional在该内存位置处保存新值。    这被用于实现锁算法与read-modify-write原子操作。

    LL操作返回一个内存地址上当前存储的值,后面的SC操作,会向这个内存地址写入一个新值,但是只有在这个内存地址上存储的值,
    从上个LL操作开始直到现在都没有发生改变的情况下,写入操作才能成功,否则都会失败。这个操作非常重要,是很多平台实现基本原子操作的基础。
    对于ARM平台来说,也在硬件层面上提供了对LL/SC的支持,LL操作用的是LDREX指令,SC操作用的是STREX指令。


/*
 * LSE
 */
    LSE(Large System Extensions), 大型系统扩展

    ARMv8.1指令集相对于ARMv8指令集添加了不少新的功能,其中有很大的一块功能称作LSE(Large System Extensions),
    这其中添加了很多平台原生就支持的原子操作指令。

    在这之前,如果想实现某个原子操作,必须要使用LL/SC操作,在ARMv8以前的32位系统中使用LDREX和STREX指令,从ARMv8起,它们被改名成了LDXR和STXR。

    LL/SC操作本质上是很多CPU核去抢某个内存变量的独占访问,以前ARM主要用来在低功耗设备上运行,CPU核也不会太多,不会存在太大的问题。
    但是,现在ARM已经往数据中心发展了,几十核的ARM处理器都已经出现了,如果还是大家一起抢可能会存在严重的性能问题。因此,为了支持这种大型系统,
    在ARMv8.1中特意加入了大量原生原子操作指令。

 

与spin lock 和 rwlock 相关的几个arm64指令;

/*
 * WFI、WFE、SEV、SEVL
 */
    WFI(Wait for interrupt)和WFE(Wait for event)是两个让ARM核进入low-power standby模式的指令,由ARM architecture定义,由ARM core实现。

    WFE

        等待事件(Wait For Event)指令。

        ARM架构下,有一个全局的事件寄存器(Event Register),系统中的每一个CPU核在这个寄存器上都有对应的位。

        当当前CPU执行WFE指令的时候,如果事件寄存器对应当前CPU的位没有被设置(也就是0),则当前CPU核会进入低功耗模式,会被挂起,
        不会再执行其它操作;而如果事件寄存器对应当前CPU的位被设置了(也就是1),则会将事件寄存器对应当前CPU的位清空(设置成0),
        然后立即返回,继续执行下面的指令,不会进入低功耗模式。

        如果当前CPU核通过WFE指令进入了低功耗模式,那么只有在如下情况下才可能被重新唤醒:

            发生了IRQ中断(前提是没有被屏蔽);
            发生了FIQ中断(前提是没有被屏蔽);
            发生了SError中断(前提是没有被屏蔽);
            事件寄存器对应当前CPU核的位被置位(设置成1),如果是通过这种方式唤醒的,唤醒后会立即将事件寄存器对应当前CPU核的位清0。

        注意,WFE指令到底让CPU核干什么,其实是没有具体定义的,只要不让内存丢失数据就行。所以,其可以只是一条空(NOP)指令,
              或者像绝大多数Arm核心设计的那样,可以进入低功耗状态。但是,如果实现了WFE指令将当前CPU核切换到低功耗模式,
              那就一定要实现后面说的SEV指令,否则该CPU核有可能会一直不被唤醒。

        在Arm架构下,Linux内核的自旋锁就使用到了WFE指令。


    WFI

        等待中断(Wait For Interrupt)指令。

        和前面说的WFE指令不同,执行WFI指令后,当前CPU核会立即进入低功耗状态。

        如果当前CPU核通过WFI指令进入了低功耗模式,那么只有在如下情况下才可能被重新唤醒:

            发生了IRQ中断(不管有没有被屏蔽);
            发生了FIQ中断(不管有没有被屏蔽);
            发生了SError中断(不管有没有被屏蔽)。

    SEV

        发送事件(Send Event)指令。

        这条指令将想系统中的所有CPU核发送事件。对应系统中的每个CPU核,设置事件寄存器(Event Register)相应的位。
        如果某个CPU核正在等待事件(WFE),那么该CPU核会被立即唤醒,并清除掉表示该CPU的事件寄存器相应的位。
        
    SEVL

        发送本地事件(Send Event Locally)指令。

        不同于前面说的SEV指令,这条指令只会向当前CPU核心发送。如果是多核CPU那也只向当前核心,不会向CPU内的其它核心发送。

        值得注意的是,这条指令只有在支持ARMv8指令集之后的处理器中才有效。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值