【发布时间】:2021-06-25 12:53:27
【问题描述】:
作为本科生的一部分,我正在参加操作系统课程,我遇到了一个令人沮丧的错误,该错误仅在设置了 -O2/3 标志的情况下出现。
系统:x86
编译器:GCC
模拟器:Bochs/Qemu
我正在使用自旋锁(一种 TTAS 实现)维护关键部分。
static int
xchange(int*s)
{
int val = LOCKED;
/* Exchanging value at lock address with 1, returns the old value */
asm volatile("xchg (%%eax), %%ebx" : "=b"(val) : "0"(val), "a"(s));
return val;
}
void
TTAS(int *s)
{
/* While lock is locked, do nothing */
while(TRUE){
while(*s == LOCKED){}
/* If lock acquired */
if( xchange(s) == UNLOCKED){
return;
}
}
}
现在,当两个线程在混合了条件等待和锁定的共享变量上工作时,就会出现该错误。线程认为他们已经获得了锁,但随后的读取返回错误(旧)值。 我尝试包装锁以打印出最后一个“所有者”,但这增加的时间导致同步保持。 锁的最后和当前所有者:Thread 2 racing itself
如果我在获取锁后打印它的值。
TTAS(lock <int*>);
print(lock::val);
print(lock::val);
第一个打印'0',第二个打印'1'。
如果我将 TTAS 换成 TAS,它似乎可以工作。
void
TAS(int *s)
{
/* While lock is locked, do nothing */
While( xchange(s) != UNLOCKED){}
}
我无法确定是什么导致了这种行为,希望你们中的一些人可以帮助我推理。\
编辑: 更正了 xchange 上的错误 void return
【问题讨论】:
-
xchange不能是void- 你需要它来返回一个值。 godbolt.org/z/fY3cq43cK 有一个可编译的版本,并使用volatile int *s和一个固定的 asm 语句使其工作。 lwn.net/Articles/793253 / Multithreading program stuck in optimized mode but runs normally in -O0 / How can I indicate that the memory *pointed* to by an inline ASM argument may be used?
标签: c multithreading gcc x86 bochs