简体   繁体   English

使用xchg旋转锁定

[英]Spin Lock using xchg

I'm trying to implement the simplest spinlock (using TAS) in C using inline assembly with the command xchg. 我正在尝试使用xchg命令的内联汇编在C中实现最简单的自旋锁(使用TAS)。 Since my compiler error messages are getting more and more exotic and I'm starting to grow grey hairs I've decided to ask here. 由于我的编译器错误消息越来越异乎寻常,并且我开始长白发,所以我决定在这里询问。 Also I'm sorry if this question was already answered since I haven't found anything. 另外,对于这个问题,因为我什么都没找到,所以我也很抱歉。

What might needs to be said about my programming experience concerning this topic. 关于这个主题的编程经验,可能需要说些什么。 I'm doing pretty fine with C (in my opinion, considering standard problems). 我用C做得很好(我认为考虑标准问题)。 Also I believe to know the basics about x86 but I'm totally lost when it comes to constraints in inline assembler. 我也相信了解x86的基础知识,但是当涉及到内联汇编程序的约束时,我完全迷失了。 What I found doing some googling is even more confusing to me since many sources say very different stuff. 我发现进行谷歌搜索的做法令我更加困惑,因为许多消息来源说的东西完全不同。

My code so far: 到目前为止,我的代码:

int acquire_lock(int* lock){
    int val = 1;
    int lock_cont;
    while((lock_cont = *lock) != 0){
            __asm__("xchg %0 %1" : "+q" (val), "+m" (lock_cont));
    }
    return 0;
}

This doesn't work for reasons that are probably obvious but are making me go nuts. 这可能不是很明显的原因,但是却让我发疯。 I've also tried some other variants but none of them even compiled. 我也尝试了其他一些变体,但没有一个被编译。 You can probably tell by now that I don't really know what I'm doing so I'd be more than happy for any kind of advice. 您可能现在可以告诉我我真的不知道自己在做什么,因此我对任何建议都非常满意。

Here my compiler messages in case this helps: 这里是我的编译器消息,以防万一:

my_lock.c:17:11: error: unexpected token in argument list
            __asm__("xchg %0 %1" : "+q" (val), "+m" (lock_cont));
                    ^
<inline asm>:1:12: note: instantiated into assembly here
    xchg %eax -16(%rbp)
              ^
1 error generated.

Thanks in advance 提前致谢

A desperate student 一个绝望的学生

EDIT: 编辑:

I got the lock to work.. a do while loop and the comma did the trick. 我得到了锁来工作.. do while循环,而逗号起到了作用。 Now I have a new problem that my lock implementation still doesn't seem to guarantee exclusive access.. I'll post the whole code and would be happy for any suggestions/critics. 现在,我有一个新问题,我的锁实现似乎仍然不能保证排他访问。.我将发布整个代码,并对任何建议/批评感到高兴。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

//shared variable
int x;

//new lock instance that's consistent over function calls
int* new_lock(){
        int* ptr = (int*)(malloc(sizeof(int)));
        *ptr = 0;
        return ptr;
}

//set content of lock atomically to 1
int acquire_lock(int* lock){
        int val = 1;
        do{
                __asm__("xchg %0, %1" : "+q" (val), "+m" (*lock));
        }while(val - (*lock) == 0);
        return 0;
}

//release the lock
int release_lock(int* lock){
        *lock = 0;
        return 0;
}

//free lock
int delete_lock(int* ptr){
        free(ptr);
        return 0;
}

//thread counts to 10^6
void* thread_do(void* arg){
        int* lock = (int*) arg;
        for(int i = 0; i < 100000; i++){
                acquire_lock(lock);
                x++;
                release_lock(lock);
        }
        return NULL;
}

int main(int argc, char** argv){
        pthread_t thread0, thread1;
        int* lock = new_lock();
        pthread_create(&thread0, NULL, thread_do, lock);
        pthread_create(&thread1, NULL, thread_do, lock);
        pthread_join(thread0, NULL);
        pthread_join(thread1, NULL);
        printf("%d\n",x);
        return 0;
}

EDIT2: EDIT2:

My lock actually DOES work as can be seen when locking the whole loop inside the thread_do function. 正如将整个循环锁定在thread_do函数中时所看到的,我的锁实际上确实起作用。 Not quite happy with this result since this locks x for quite a long time but I guess I'll have to live with this.. I assume the problem is that between my asm instruction and the comparison from the while I can't guarantee atomicity when the locking and unlocking is such a fast stream of instructions (for loop in thread_do) since I don't see a workaround in C (suggestions are welcome), I'll stick to this implementations since the general idea seems to be right. 我对这个结果不太满意,因为它锁定了很长时间,但是我想我必须忍受这个。.我认为问题是我的asm指令与我无法保证原子性的比较之间当锁定和解锁是如此快速的指令流(用于thread_do中的循环)时,由于我在C语言中看不到变通方法(欢迎提出建议),我将坚持这种实现,因为总体思路似乎是正确的。

If you're trying to make a spinlock, you'll probably want to use a strong atomic compare exchange. 如果您尝试进行自旋锁,则可能需要使用强大的原子比较交换。

Here is a simple implementation of you acquire_lock using a GCC builtin : 这是使用内置的GCC进行的acquire_lock的简单实现:

int acquire_lock(int* lock) 
{
    while (__sync_val_compare_and_swap (lock, 0, 1) != 0)
    {
        // Do something while waiting for the lock ?
    }
    return 0;
}

Compiler builtins have the advantage of being more readable and somewhat more portable than inline ASM. 与内联ASM相比,编译器内建程序具有更具可读性和可移植性的优势。


Regarding the error in your code, you're missing a comma between the operands. 关于代码中的错误,您在操作数之间缺少逗号。 That line : 那条线:

__asm__("xchg %0 %1" : "+q" (val), "+m" (lock_cont));

Should be : 应该 :

__asm__("xchg %0, %1" : "+q" (val), "+m" (lock_cont));

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

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