02-Linux Kernel(armv8-aarch64)的原子操作的底层实现
快速鏈接:
.
👉👉👉 個(gè)人博客筆記導(dǎo)讀目錄(全部) 👈👈👈
說明:
在默認(rèn)情況下,本文講述的都是ARMV8-aarch64架構(gòu),linux kernel 5.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。
那么系統(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("// atomic_" #op "\n" \__LL_SC_FALLBACK( \ " prfm pstl1strm, %2\n" \ "1: ldxr %w0, %2\n" \ " " #asm_op " %w0, %w0, %w3\n" \ " stxr %w1, %w0, %2\n" \ " cbnz %w1, 1b\n") \: "=&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, %4\n" \ " strex %1, %0, [%3]\n" \ " teq %1, #0\n" \ " 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)的原子操作指令
總結(jié)
以上是生活随笔為你收集整理的02-Linux Kernel(armv8-aarch64)的原子操作的底层实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux Kernel中的同步机制的介
- 下一篇: Linux Kernel中local_i