前言
這個(gè)是在面試的時(shí)候遇到的問(wèn)題,當(dāng)時(shí)沒(méi)有答出來(lái)?;氐郊乙院蟛榱瞬?,整理記錄下來(lái)。原問(wèn)題:什么指令集支持原子操作?其原理是什么?如果考慮到全部的指令集,問(wèn)題太大了,這里簡(jiǎn)化下。以X86和ARM為例。原子操作是不可分割的操作,在執(zhí)行完畢時(shí)它不會(huì)被任何事件中斷。在單處理器系統(tǒng)(UniProcessor,簡(jiǎn)稱 UP)中,能夠在單條指令中完成的操作都可以認(rèn)為是原子操作,因?yàn)橹袛嘀荒馨l(fā)生在指令與指令之間。比如,C語(yǔ)言代碼![d056f370-f87e-11ec-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/94/wKgaomTnBe-AIuymAAACfJskYmI567.png)
![d06173ea-f87e-11ec-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/94/wKgaomTnBe-AV06fAAAG7XQWQYQ372.png)
![d06dcb36-f87e-11ec-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/94/wKgaomTnBe-AITVgAAAPRbuYvs0936.png)
![d07f982a-f87e-11ec-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/94/wKgaomTnBe-AbNoHAAADXLIe8oE012.png)
X86架構(gòu)
Intel X86指令集提供了指令前綴lock用于鎖定前端串行總線FSB,保證了指令執(zhí)行時(shí)不會(huì)收到其他處理器的干擾。比如:![d08c24c8-f87e-11ec-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/94/wKgaomTnBfCAZbfGAAADpXDoOm0417.png)
![d0a07da6-f87e-11ec-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/94/wKgaomTnBfCAfcvtAAB-ceu9GD4132.png)
DescriptionCauses the processor’s LOCK# signal to be asserted during execution of the accompanying instruction (turns the instruction into an atomic instruction). In a multiprocessor environment, the LOCK# signal ensures that the processor has exclusive use of any shared memory while the signal is asserted.The LOCK prefix can be prepended only to the following instructions and only to those forms of the instructions where the destination operand is a memory operand: ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, and XCHG. If the LOCK prefix is used with one of these instructions and the source operand is a memory operand, an undefined opcode exception (#UD) may be generated. An undefined opcode exception will also be generated if the LOCK prefix is used with any instruction not in the above list. The XCHG instruction always asserts the LOCK# signal regardless of the presence or absence of the LOCK prefix.The LOCK prefix is typically used with the BTS instruction to perform a read-modify-write operation on a memory location in shared memory environment.The integrity of the LOCK prefix is not affected by the alignment of the memory field. Memory locking is observed for arbitrarily misaligned fields.在執(zhí)行伴隨的指令期間使處理器的LOCK#信號(hào)有效(將指令變?yōu)樵又噶睿?。在多處理器環(huán)境中,LOCK#信號(hào)確保處理器在信號(hào)有效時(shí)獨(dú)占使用任何共享存儲(chǔ)器。LOCK前綴只能附加在下面的指令之前,并且只適用于那些目標(biāo)操作數(shù)是內(nèi)存操作數(shù)的指令格式:ADD,ADC,AND,BTC,BTR,BTS,CMPXCHG,CMPXCH8B,CMPXCHG16B,DEC,INC, NEG,NOT,OR,SBB,SUB,XOR,XADD和XCHG。如果LOCK前綴與這些指令之一一起使用,并且源操作數(shù)是內(nèi)存操作數(shù),則可能會(huì)生成未定義的操作碼異常(#UD)。如果LOCK前綴與任何不在上述列表中的指令一起使用,也會(huì)產(chǎn)生未定義的操作碼異常。無(wú)論是否存在LOCK前綴,XCHG指令都始終聲明LOCK#信號(hào)。LOCK前綴通常與BTS指令一起使用,以在共享存儲(chǔ)器環(huán)境中的存儲(chǔ)器位置上執(zhí)行讀取 – 修改 – 寫(xiě)入操作。LOCK前綴的完整性不受存儲(chǔ)器字段對(duì)齊的影響。內(nèi)存鎖定是針對(duì)任意不對(duì)齊的字段。
操作系統(tǒng)中的實(shí)現(xiàn)
Linux源碼中對(duì)于原子自增一是如下定義的:![d0b19668-f87e-11ec-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/94/wKgaomTnBfCAbRMcAAAebUP_UmQ233.png)
![d0c5afc2-f87e-11ec-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/94/wKgaomTnBfCACHF5AAAmOPyw2sU514.png)
static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new)
{
return cmpxchg(&v->counter, old, new);
}
__cmpxchg(ptr, old, new, sizeof(*(ptr)))
__raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
({
__typeof__(*(ptr)) __ret;
__typeof__(*(ptr)) __old = (old);
__typeof__(*(ptr)) __new = (new);
switch (size) {
case __X86_CASE_B:
{
volatile u8 *__ptr = (volatile u8 *)(ptr);
asm volatile(lock "cmpxchgb %2,%1"
: "=a" (__ret), "+m" (*__ptr)
: "q" (__new), "0" (__old)
: "memory");
break;
}
case __X86_CASE_W:
{
volatile u16 *__ptr = (volatile u16 *)(ptr);
asm volatile(lock "cmpxchgw %2,%1"
: "=a" (__ret), "+m" (*__ptr)
: "r" (__new), "0" (__old)
: "memory");
break;
}
case __X86_CASE_L:
{
volatile u32 *__ptr = (volatile u32 *)(ptr);
asm volatile(lock "cmpxchgl %2,%1"
: "=a" (__ret), "+m" (*__ptr)
: "r" (__new), "0" (__old)
: "memory");
break;
}
case __X86_CASE_Q:
{
volatile u64 *__ptr = (volatile u64 *)(ptr);
asm volatile(lock "cmpxchgq %2,%1"
: "=a" (__ret), "+m" (*__ptr)
: "r" (__new), "0" (__old)
: "memory");
break;
}
default:
__cmpxchg_wrong_size();
}
__ret;
})
ARM架構(gòu)
在ARM架構(gòu)下,沒(méi)有LOCK#指令,其具體實(shí)現(xiàn)如下:## ARMv6之前 早期的ARM架構(gòu)是不支持SMP的,這些單核架構(gòu)的CPU實(shí)現(xiàn)原子操作的方式就是通過(guò)關(guān)閉CPU中斷來(lái)完成的。在Linux對(duì)于ARM架構(gòu)的代碼下有如下:![d0d3319c-f87e-11ec-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/94/wKgaomTnBfCAaINDAAAqG66tgE4801.png)
![d0e0a976-f87e-11ec-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/94/wKgaomTnBfCATsJMAAAhJ4DI8QI221.png)
![d0f165cc-f87e-11ec-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/94/wKgaomTnBfGAEjoiAABgXGet4Ig079.png)
原文標(biāo)題:對(duì)int變量賦值的操作是原子的嗎?為什么?
文章出處:【微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
內(nèi)存
+關(guān)注
關(guān)注
8文章
3064瀏覽量
74382 -
處理器系統(tǒng)
+關(guān)注
關(guān)注
0文章
9瀏覽量
7824 -
C語(yǔ)言代碼
+關(guān)注
關(guān)注
0文章
10瀏覽量
9181
原文標(biāo)題:對(duì)int變量賦值的操作是原子的嗎?為什么?
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
66ak2h14使用 ldrex過(guò)程中出錯(cuò)
stm32的Core_cm3.c文件
STM32F7 MPU設(shè)置跳入硬件錯(cuò)誤中
ARM平臺(tái)上特有的獨(dú)占訪問(wèn)指令LDREX和STREX該怎樣去使用呢
AHB-lite總線如何處理獨(dú)占訪問(wèn)
不能將STREX/LDREX與多核共享內(nèi)存訪問(wèn)一起使用嗎?
淺談鴻蒙內(nèi)核源碼的原子操作
![淺談鴻蒙內(nèi)核源碼的原子操作](https://file.elecfans.com/web1/M00/EC/D6/pIYBAGCFInSAHpgJAAG38gOWMDk715.png)
ARM指令集—SWP指令
![ARM指令集—SWP指令](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
Vybrid非對(duì)稱多核架構(gòu)的裸機(jī)固件
![Vybrid非對(duì)稱多核架構(gòu)的裸機(jī)固件](https://file.elecfans.com/web2/M00/4B/3D/pYYBAGKn44KAH2VaAAD-7G1PrYY786.png)
評(píng)論