简体   繁体   English

尝试通过“lock xchg”程序集实现自旋锁

[英]Trying to implement a spin-lock via "lock xchg" assembly

Basically, I'm trying to run void spinlock_counter(int) in two threads and count ought to be 2000(parameter doesn't do anything I'm just too lazy).基本上,我试图在两个线程中运行 void spinlock_counter(int) 并且计数应该是 2000(参数不做任何事情我只是太懒了)。 However I made a breakpoint in the critical zone ie "count++" and printed "flag", the flag is "GO" (the flag should be "BLOCK" if everything worked).然而,我在临界区下了一个断点,即“count++”并打印了“flag”,标志是“GO”(如果一切正常,标志应该是“BLOCK”)。 didn't get why this hadn't worked.不明白为什么这不起作用。

Thank you for your answers!谢谢您的回答!

code:代码:

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);
}

The condition in your while loop (in lock() ) is backwards. while 循环中的条件(在lock()中)是倒退的。

The consequence is that lock() effectively does nothing.结果是lock()实际上什么都不做。 If another thread already acquired the lock it won't spin at all, and if the lock was GO it'll spin once (setting the lock to BLOCK on the first iteration so that the spinning stops on the 2nd iteration).如果另一个线程已经获得锁,它根本不会旋转,如果锁是GO ,它会旋转一次(在第一次迭代时将锁设置为BLOCK ,以便在第二次迭代时停止旋转)。

I'd recommend writing code that describes your intent in a clearer/less confusing/less error prone way (and never relying on the value of true/false in C) so that these kinds of bugs are prevented.我建议编写代码以更清晰/更不易混淆/更不容易出错的方式(并且从不依赖 C 中的 true/false 值)来描述您的意图,以便防止这些类型的错误。 Eg:例如:

void lock(int *addr){
    int note = BLOCK;
    while(xchg(addr, note) != GO);
}

However I made a breakpoint in the critical zone ie "count++" and printed "flag", the flag is "GO"但是我在临界区下了一个断点,即“count++”并打印了“flag”,flag是“GO”

This is probably a separate bug (although the first bug can cause a different thread to unlock after your thread locks it wouldn't be easily reproducible).这可能是一个单独的错误(尽管第一个错误可能会导致另一个线程在您的线程锁定后解锁,但它不容易重现)。 Specifically;具体来说; nothing prevents the compiler from re-ordering your code and you'll want some kind of barrier to prevent the compiler transforming your code into the equivalent of lock(&flag); unlock_spin(&flag);没有什么能阻止编译器对您的代码重新排序,您需要某种障碍来防止编译器将您的代码转换为lock(&flag); unlock_spin(&flag); lock(&flag); unlock_spin(&flag); then count++;然后count++; . . Changing the clobber list for your inline assembly to "cc, memory" should prevent the compiler from reordering functions.将内联程序集的 clobber 列表更改为"cc, memory"应该可以防止编译器对函数重新排序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM