0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux Kernel(armv8-aarch64) 的原子操作的底層實(shí)現(xiàn)

冬至子 ? 來源:Arm精選 ? 作者:baron ? 2023-10-16 11:14 ? 次閱讀

通常我們代碼中的a = a + 1這樣的一行語句,翻譯成匯編后蘊(yùn)含著 3 條指令:

ldr x0, &a  
add x0,x0,#1  
str x0,&a


(1) 從內(nèi)存中讀取 a 變量到 X0 寄存器
(2)X0 寄存器加 1
(3) 將 X0 寫入到內(nèi)存 a 中

既然是 3 條指令,那么就有可能并發(fā),也就意味著返回的結(jié)果可能不說預(yù)期的。

然后在 linux kernel 的操作系統(tǒng)中,提供訪問原子變量的函數(shù),用來解決上述問題。其中部分原子操作的 API 如下:

atomic_read
atomic_add_return(i,v)
atomic_add(i,v)
atomic_inc(v)
atomic_add_unless(v,a,u)
atomic_inc_not_zero(v)
atomic_sub_return(i,v)
atomic_sub_and_test(i,v)
atomic_sub(i,v)
atomic_dec(v)
atomic_cmpxchg(v,old,new)

那么操作系統(tǒng) (僅僅是軟件而已) 是如何保證原子操作的呢?(還是得靠硬件),硬件原理是什么呢?

以上的那些 API 函數(shù),在底層調(diào)用的其實(shí)都是如下__lse_atomic_add_return##name宏的封裝,這段代碼中最核心的也就是ldadd指令了,這是 armv8.1 增加的 LSE(Large System Extension)feature。

(linux/arch/arm64/include/asm/atomic_lse.h)

static inline int __lse_atomic_add_return##name(int i, atomic_t *v)    
{                                    
    u32 tmp;                            
                                    
    asm volatile(                            
    __LSE_PREAMBLE                            
    "    ldadd" #mb "    %w[i], %w[tmp], %[v]n"            
    "    add    %w[i], %w[i], %w[tmp]"                
    : [i] "+r" (i), [v] "+Q" (v- >counter), [tmp] "=&r" (tmp)    
    : "r" (v)                            
    : cl);                                
                                    
    return i;                            
}

那么系統(tǒng)如果沒有 LSE 擴(kuò)展呢,即 armv8.0,其實(shí)現(xiàn)的原型如下所示,這段代碼中最核心的也就是ldxr、stxr指令了

(linux/arch/arm64/include/asm/atomic_ll_sc.h)

static inline void __ll_sc_atomic_##op(int i, atomic_t *v)
{                                    
    unsigned long tmp;                        
    int result;                            
                                    
    asm volatile("http:// atomic_" #op "n"                
    __LL_SC_FALLBACK(                        
"    prfm    pstl1strm, %2n"                    
"1:    ldxr    %w0, %2n"                        
"    " #asm_op "    %w0, %w0, %w3n"                
"    stxr    %w1, %w0, %2n"                        
"    cbnz    %w1, 1bn")                        
    : "=&r" (result), "=&r" (tmp), "+Q" (v- >counter)        
    : __stringify(constraint) "r" (i));                
}

那么在 armv8.0 之前呢,如 armv7 是怎樣實(shí)現(xiàn)的?如下所示, 這段代碼中最核心的也就是ldrex、strex指令了

(linux/arch/arm/include/asm/atomic.h)

static inline void atomic_##op(int i, atomic_t *v)            
{                                    
    unsigned long tmp;                        
    int result;                            
                                    
    prefetchw(&v- >counter);                        
    __asm__ __volatile__("@ atomic_" #op "n"            
"1:    ldrex    %0, [%3]n"                        
"    " #asm_op "    %0, %0, %4n"                    
"    strex    %1, %0, [%3]n"                        
"    teq    %1, #0n"                        
"    bne    1b"                            
    : "=&r" (result), "=&r" (tmp), "+Qo" (v- >counter)        
    : "r" (&v- >counter), "Ir" (i)                    
    : "cc");                            
}

總結(jié):

在很早期,使用 arm 的 exclusive 機(jī)制來實(shí)現(xiàn)的原子操作,exclusive 相關(guān)的指令也就是ldrex、strex了,但在 armv8 后,exclusive 機(jī)制的指令發(fā)生了變化變成了ldxr、stxr。

但是又由于在一個(gè)大系統(tǒng)中,處理器是非常多的,競爭也激烈,使用獨(dú)占的存儲(chǔ)和加載指令可能要多次嘗試才能成功,性能也就變得很差,在 armv8.1 為了解決該問題,增加了ldadd等相關(guān)的原子操作指令。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 處理器
    +關(guān)注

    關(guān)注

    68

    文章

    18927

    瀏覽量

    227231
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5253

    瀏覽量

    119205
  • Linux系統(tǒng)
    +關(guān)注

    關(guān)注

    4

    文章

    587

    瀏覽量

    27181
  • LSE
    LSE
    +關(guān)注

    關(guān)注

    0

    文章

    10

    瀏覽量

    10213
  • ARMv8
    +關(guān)注

    關(guān)注

    1

    文章

    35

    瀏覽量

    14105
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    ARMv8-A AArch32主要特性

    Cortex-A32產(chǎn)品介紹ARMv8-A AArch32主要特性ARMv7-M與AArch32的不同之處軟件從ARMv7-M移植到
    發(fā)表于 02-19 06:20

    編譯出的bin文件用什么方式刷入開發(fā)板

    /target-aarch64_generic_musl/linux-layerscape_armv8_64b/ls1046ardb-kernel.bin > /home/forlinx/work/OK104x-
    發(fā)表于 01-05 07:46

    ARMv8aarch64aarch32是怎樣進(jìn)行切換的

    ARMv8中,aarch64aarch32是通過異常進(jìn)行切換的。而A32和T32是通過bx指令進(jìn)行切換的。如下圖:以下A64和A32混合編程,是在EL3為
    發(fā)表于 04-01 15:09

    ARMv8架構(gòu)概述

    Armv8 OverviewARMv7與Armv8的升級(jí)示意如下:Aarch64指令集Aarch64的32個(gè)通用寄存器引用和描述如下,與Aarch
    發(fā)表于 05-13 10:31

    ARMV8-aarch64異常和中斷處理概念詳細(xì)介紹

    1、ARMV8-aarch64異常和中斷處理概念(AArch64 Exception and Interrupt Handling)異常是指需要特權(quán)軟件(an exception handler
    發(fā)表于 06-01 17:46

    請(qǐng)問Armv8-A到底是什么東西呢

    介紹了,后面的內(nèi)容都是以A為基礎(chǔ)。Armv8-A的執(zhí)行狀態(tài)有兩種,AArch64AArch32。相應(yīng)的Armv8-A支持兩種指令集:AArch64
    發(fā)表于 08-22 15:39

    Cortex-A53使用AArch32 Kernel,可以直接使用ARMv7的所支持的CPU嗎?

    CA53 run 32bit linux kernel, 發(fā)現(xiàn)arch/arm/kernel/perf_event_v7.c 只支持ARMv7 的 ca17, ca15, ca12,
    發(fā)表于 08-29 14:11

    AArch64異常模型指南

    AArch64異常模型指南介紹了Armv8-A中的異常和特權(quán)模型Armv9-A。它涵蓋了Arm體系結(jié)構(gòu)中不同類型的異常,以及處理器與異常的關(guān)系。 這些內(nèi)容面向底層代碼的開發(fā)人員,例如引
    發(fā)表于 08-02 06:03

    ARM Cortex-A系列ARMv8-A程序員指南

    。 GNU和Linux文檔(Redhat和Fedora發(fā)行版除外)有時(shí)將AArch64稱為ARM64。 因?yàn)?b class='flag-5'>ARMv8-A體系結(jié)構(gòu)的許多概念都與AR
    發(fā)表于 08-22 07:22

    ARM64與ARM32 的Linux程序區(qū)別在哪里

    我本來打算將這篇文章稱為“ARMv8 for Linux程序員的新功能?”然而,我認(rèn)為“有什么不同”更為貼切。而且,僅僅為了記錄,“ARMv8-A”是指AArch64,帶有A
    的頭像 發(fā)表于 08-09 09:51 ?2.7w次閱讀
    ARM<b class='flag-5'>64</b>與ARM32 的<b class='flag-5'>Linux</b>程序區(qū)別在哪里

    使用Linux原子操作實(shí)現(xiàn)互斥點(diǎn)燈

    Linux原子操作是指不能再進(jìn)一步分割的操作,一般原子操作用于變量或者位
    的頭像 發(fā)表于 04-13 15:07 ?768次閱讀
    使用<b class='flag-5'>Linux</b><b class='flag-5'>原子</b><b class='flag-5'>操作</b><b class='flag-5'>實(shí)現(xiàn)</b>互斥點(diǎn)燈

    SOC的多核啟動(dòng)流程和概念詳解

    本文以為armv8-aarch64、armv9為例、TF-A代碼為例,不討論其它硬件架構(gòu)和固件軟件中的設(shè)計(jì)。
    發(fā)表于 06-08 09:32 ?1911次閱讀
    SOC的多核啟動(dòng)流程和概念詳解

    最新的Linux aarch64 LSA驅(qū)動(dòng)程序

    電子發(fā)燒友網(wǎng)站提供《最新的Linux aarch64 LSA驅(qū)動(dòng)程序.zip》資料免費(fèi)下載
    發(fā)表于 08-23 15:46 ?2次下載
    最新的<b class='flag-5'>Linux</b> <b class='flag-5'>aarch64</b> LSA驅(qū)動(dòng)程序

    ARMv7-A工作模式介紹

    意思就是 64 位和 32 位,其中 AArch32 和 ARMv7基本一樣(會(huì)多一些其他操作指令)。 安全不能僅僅依靠軟件來實(shí)現(xiàn),也是需要
    的頭像 發(fā)表于 09-11 16:31 ?759次閱讀
    <b class='flag-5'>ARMv</b>7-A工作模式介紹

    ARM CORE支持中斷嵌套嗎?GIC中斷控制器支持中斷嵌套嗎?

    在默認(rèn)情況下,本文講述的都是ARMV8-aarch64架構(gòu),gicv3, linux kernel 5.14
    的頭像 發(fā)表于 08-07 09:29 ?297次閱讀
    ARM CORE支持中斷嵌套嗎?GIC中斷控制器支持中斷嵌套嗎?