TSL指令参考

时间:2014-03-15 13:06:54

标签: assembly masm

我想使用" TSL"汇编中的指令,但它没有参考理解。在一些文章中,该指令是针对互斥问题引入的,但它没有完全理解的参考或完整的例子。

3 个答案:

答案 0 :(得分:7)

TSL(测试和设置锁定)是一般在处理互斥问题时经常出现的操作,但这并不意味着这样的指令实际上存在于任何架构中正在使用;或者,即使它确实存在,它也称为TSL。

例如,在x86上,您可以使用XCHG指令执行TSL。

答案 1 :(得分:2)

XCNG不是有条件的,它只是用内存位置交换寄存器。你想要的是具有LOCK前缀的CMPXCHG。后者将使其在多核机器上成为原子。

此外,您可以使用LOCK XADD实现原子比较和设置,但这将需要一个循环。

参考:http://en.wikipedia.org/wiki/Compare-and-swap

答案 2 :(得分:1)

我认为@Jester和@Seva Alekseyev已经在回答这个问题方面做得很好但是这里是一个简单的C语言实现,通过在x86 Ubuntu机器上使用pthreads进行内联汇编。

在以下示例中,有两个长时间运行的线程。两个线程分别具有关键和非关键部分,critical_region()和noncritical_region。他们都必须调用 enter_region()才能获得锁定。一旦线程获得锁定,它就可以开始运行其关键部分。另一个线程被阻塞,直到带锁的线程将调用 leave_region()

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


void enter_region() {
    asm(
        ".data\n\t"
        "lock:\n\t"
        ".byte 0\n\t"
        ".text\n\t"

        "_enter_region:\n\t"
        "movb $1, %al\n\t" /* move 1 to AL */
        "xchgb (lock),%al\n\t" 
        "cmp $0, %al\n\t"
        "jne _enter_region\n\t"

    );
}

void leave_region() {
    asm("movb $0, (lock)");
}


void critical_region() {

}

void noncritical_region() {

}

static void* f1(void* p) {
    while(1) {
        puts("wait for f2");
        enter_region();
        printf("f1 can start its critical section\n");
        critical_region();
        leave_region();
        noncritical_region();
    }
    return NULL;
}

static void* f2(void* p) {
    while(1) {
        puts("wait for f1");
        enter_region();
        printf("f2 can start its critical section\n");
        critical_region();
        leave_region();

        /* if you call sleep, you can see that the non-critical section of this thread won't
        *  block the other thread from running its critical section as many times as it wants
        */
        // sleep(1);
        noncritical_region();
    }
    return NULL;
}

int main() {
    int rc;

    pthread_t t1, t2;

    rc = pthread_create(&t1, NULL, f1, NULL);
    if(rc != 0) {
        fprintf(stderr, "pthread f1 failed\n");
        return EXIT_FAILURE;
    }

    rc = pthread_create(&t2, NULL, f2, NULL);
    if(rc != 0) {
        fprintf(stderr, "pthread f2 failed\n");
        return EXIT_FAILURE;
    }

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    puts("All threads finished.");
    return 0;
}