尝试通过 "lock xchg" 程序集实现自旋锁
Trying to implement a spin-lock via "lock xchg" assembly
基本上,我试图在两个线程中 运行 void spinlock_counter(int) 并且计数应该是 2000(参数不执行任何操作我只是太懒了)。然而,我在关键区域做了一个断点,即“count++”并打印了“flag”,标志是“GO”(如果一切正常,标志应该是“BLOCK”)。
不明白为什么这不起作用。
感谢您的回答!
代码:
int xchg(volatile int *addr, int newval){
int result;
asm volatile("lock xchg %0, %1"
:"+m"(addr),
"=a"(result)
:"1"(newval)
:"cc");
return result;
}
#define GO 0
#define BLOCK 1
int flag = GO;
void lock(int *addr){
int note = BLOCK;
while(!xchg(addr, note));
}
void unlock_spin(int *addr){
int note = GO;
xchg(addr, note);
}
void spinlock_counter(int a){
while(1) {
lock(&flag);
count++;
unlock_spin(&flag);
}
printf("%d\n", count);
}
您的 while 循环(在 lock()
中)的条件是倒退的。
结果是 lock()
实际上什么也没做。如果另一个线程已经获得了锁,它根本不会旋转,如果锁是 GO
它会旋转一次(在第一次迭代时将锁设置为 BLOCK
以便旋转停止第二次迭代)。
我建议编写代码以 clearer/less confusing/less 容易出错的方式(并且永远不要依赖 C 中 true/false 的值)来描述您的意图,以便这些类型错误被阻止。例如:
void lock(int *addr){
int note = BLOCK;
while(xchg(addr, note) != GO);
}
However I made a breakpoint in the critical zone i.e. "count++" and printed "flag", the flag is "GO"
这可能是一个单独的错误(尽管第一个错误可能会导致另一个线程在您的线程锁定后解锁,但它不容易重现)。具体来说;没有什么能阻止编译器 re-ordering 您的代码,您需要某种障碍来阻止编译器将您的代码转换为 lock(&flag); unlock_spin(&flag);
然后 count++;
的等价物。将内联程序集的破坏列表更改为 "cc, memory"
应该可以防止编译器对函数重新排序。
基本上,我试图在两个线程中 运行 void spinlock_counter(int) 并且计数应该是 2000(参数不执行任何操作我只是太懒了)。然而,我在关键区域做了一个断点,即“count++”并打印了“flag”,标志是“GO”(如果一切正常,标志应该是“BLOCK”)。 不明白为什么这不起作用。
感谢您的回答!
代码:
int xchg(volatile int *addr, int newval){
int result;
asm volatile("lock xchg %0, %1"
:"+m"(addr),
"=a"(result)
:"1"(newval)
:"cc");
return result;
}
#define GO 0
#define BLOCK 1
int flag = GO;
void lock(int *addr){
int note = BLOCK;
while(!xchg(addr, note));
}
void unlock_spin(int *addr){
int note = GO;
xchg(addr, note);
}
void spinlock_counter(int a){
while(1) {
lock(&flag);
count++;
unlock_spin(&flag);
}
printf("%d\n", count);
}
您的 while 循环(在 lock()
中)的条件是倒退的。
结果是 lock()
实际上什么也没做。如果另一个线程已经获得了锁,它根本不会旋转,如果锁是 GO
它会旋转一次(在第一次迭代时将锁设置为 BLOCK
以便旋转停止第二次迭代)。
我建议编写代码以 clearer/less confusing/less 容易出错的方式(并且永远不要依赖 C 中 true/false 的值)来描述您的意图,以便这些类型错误被阻止。例如:
void lock(int *addr){
int note = BLOCK;
while(xchg(addr, note) != GO);
}
However I made a breakpoint in the critical zone i.e. "count++" and printed "flag", the flag is "GO"
这可能是一个单独的错误(尽管第一个错误可能会导致另一个线程在您的线程锁定后解锁,但它不容易重现)。具体来说;没有什么能阻止编译器 re-ordering 您的代码,您需要某种障碍来阻止编译器将您的代码转换为 lock(&flag); unlock_spin(&flag);
然后 count++;
的等价物。将内联程序集的破坏列表更改为 "cc, memory"
应该可以防止编译器对函数重新排序。