[已解决]使用__sync_fetch_and_or
而不是__sync_or_and_fetch
! 双重amoor
指令可能仍然是一个错误。
[免责声明] 这可能是 GCC 中的一个错误,但可以肯定的是,我对 RISC-V 汇编还不熟悉!
我正在尝试使用混合 C 语言以及 GCC v14.2.0 和 GCC 15.1.0 的交叉编译,在 RISC-V (64 位,仅供参考) 中实现一个“快速asm()
”自旋锁功能。以下代码(非常精简):
#define LOCK_BIT ((unsigned long)(1ul<<(8*sizeof(long)-1)))
void lock_hold(long* lock) {
while(__sync_or_and_fetch(lock,LOCK_BIT) < 0);
__sync_synchronize();
}
两个版本均使用-O3
和-O2
来呈现为:
lock_hold:
li a5,-1
slli a5,a5,63
.L2:
amoor.d.aqrl a4,a5,0(a0)
amoor.d.aqrl a4,a5,0(a0)
j .L2
这似乎是一个具有两个连续相同amoor
指令的无限循环。
首先,我并不期望那里出现无限循环!
如果我切换到-O1
,我会得到以下代码:
lock_hold:
li a4,-1
slli a4,a4,63
.L2:
amoor.d.aqrl a5,a4,0(a0)
or a5,a5,a4. #USELESS?
blt a5,zero,.L2
fence rw,rw
ret
它看起来更像我期望的,同时-Os
生成以下代码:
lock_hold:
li a5,-1
slli a5,a5,63
.L2:
amoor.d.aqrl a4,a5,0(a0)
j .L2
再次陷入无限循环。
最后,使用-O0
我得到的结果与使用的结果基本相同,但-O1
有一些额外的说明。
我是不是遇到了 bug,或者遗漏了什么?万一我遗漏了什么呢?
除此之外,我还想得到“比我懂得多得多的人”的回答。
在生成的代码中,-O1
我将一条or
指令标记为#USELESS?
。我是否真的需要对 执行某些操作a5
才能在一条amoor
写入a5
自身的指令之后设置“符号标志”?
万一,这样的事还不够吗or a5,zero,a5
?