ARM下的原子操作实现原理
ARM下的原子操作實現原理
本文的重點是學習C內嵌匯編的語法和ldrex/strex指令。
1、atomic_t類型定義
typedef struct {
?? ?int counter;
} atomic_t;
把整型原子操作定義為結構體,讓原子函數只接收atomic_t類型的參數進而確保原子操作只與這種特殊類型數據一起使用,同時也保證了該類型的數據不會被傳遞給非原子函數。
2、定義并初始化一個atomic_t變量
atomic_t v = ATOMIC_INIT(0);
#define ATOMIC_INIT(i)?? ?{ (i) }
3、基本操作
atomic_inc(v); // 原子變量自增1
atomic_dec(v); // 原子變量自減1
4、atomic_inc()函數的實現
static inline void atomic_inc(atomic_t *v)
{
atomic_add_return(1, v);
}
#define atomic_inc_return(v)?? ?atomic_add_return(1, (v))
static inline int atomic_add_return(int i, atomic_t *v)
{
?? ?unsigned long tmp;
?? ?int result;
?? ?smp_mb();
?
?? ?__asm__ __volatile__("@ atomic_add_return\n"
?? ??? ?"1:?? ?ldrex?? ?%0, [%3]\n"
?? ??? ?"?? ?add?? ?%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");
?
?? ?smp_mb();
?? ?return result;
}
4.1 C函數內嵌匯編
4.1.1 內嵌匯編語法
__asm__內嵌匯編關鍵字,告知編譯器下述語句為匯編代碼
__volatile__告知編譯器不要優化(比如重組優化)下述匯編語句
語法的格式:
__asm__ (
?? ?"asm code 1\n" // instruction list
?? ?"asm code 2\n"
?? ?"asm code n"
?? ?: Output Operands // 把匯編指令的數值輸出到C代碼的變量中
?? ?: Input ?Operands
?? ?: clobbers // 告知編譯器這條指令會修改什么值
);
變量列表中常見符號:
"+":操作數可讀可寫
"=":操作數只寫
"&":常用于輸出操作,表示輸出操作不能使用輸入操作使用過的寄存器,只能+&或=&方式使用
"r":操作數是任何可用的通用寄存器
"m":操作數是內存變量
"p":操作數是一個合法的內存地址
"I":0~31之間的立即數
"i":操作數是立即數
"Q":A memory address which uses a single base register with no offset
"o":操作數是內存變量,但其尋址方式必須是偏移量類型的,即基址尋址或基址加變址尋址
"V":操作數是內存變量,但其尋址方式非偏移量類型
4.1.2 atomic_add_return中匯編分析
__asm__ __volatile__("@ atomic_add_return\n"
?? ?"1:?? ?ldrex?? ?%0, [%3]\n"
?? ?"?? ?add?? ?%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");
%0 <-- result
%1 <-- tmp
%3 <-- v->counter的地址
%4 <-- i
注意:此時C變量的數據都已經放至寄存器中
(1) ldrex %0, [%3]
獨占式地加載(Load-Exclusive)v->counter的地址,把它的值放到result中,并更新exclusive monitor(s)
用C描述就是:
result = v->counter
(2) add %0, %0, %4
result = result + i
(3) strex %1, %0, [%3]
獨占式地保存(Store-Exclusive)數據至v->counter的地址,數據來自result,操作結果(成功/失敗)保存在tmp中
用C描述就是:
v->counter = result
(4) teq %1, #0
檢測strex的操作是否成功
(5) bne 1b
strex的操作失敗的話,向后跳轉到指定標號(jump to 1 label backward)處重新執行
(6) "cc"
"cc"是一個特殊的參數,用來標明匯編代碼會修改標志寄存器(flags register)
在某些機器平臺上,GCC通過一個特殊的硬件寄存器表征條件類型的代碼,"cc"就是這個特殊寄存器的名字
某些機器平臺沒有上述功能,"cc"會被忽略,不起作用。
附:
1、How to Use Inline Assembly Language in C Code
2、ldrex和strex簡介
LDREX and STREX
The LDREX and STREX instructions split the operation of atomically updating memory into
two separate steps. Together, they provide atomic updates in conjunction with exclusive
monitors that track exclusive memory accesses.
Load-Exclusive and Store-Exclusive must only access memory regions marked as
Normal.
LDREX
The LDREX instruction loads a word from memory, initializing the state of the exclusive
monitor(s) to track the synchronization operation. For example, LDREX R1, [R0]
performs a Load-Exclusive from the address in R0, places the value into R1 and updates
the exclusive monitor(s).
STREX
The STREX instruction performs a conditional store of a word to memory. If the exclusive
monitor(s) permit the store, the operation updates the memory location and returns the
value 0 in the destination register, indicating that the operation succeeded. If the
exclusive monitor(s) do not permit the store, the operation does not update the memory
location and returns the value 1 in the destination register. This makes it possible to
implement conditional execution paths based on the success or failure of the memory
operation. For example, STREX R2, R1, [R0] performs a Store-Exclusive operation to the
address in R0, conditionally storing the value from R1 and indicating success or failure
in R2.
詳見ARM Synchronization Primitives
————————————————
版權聲明:本文為CSDN博主「__2017__」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u013686019/article/details/78235624
總結
以上是生活随笔為你收集整理的ARM下的原子操作实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 显著增加bash交互舒适度的.input
- 下一篇: IEEE802.11e EDCA 中TX