TTAS 一致性问题?

问题描述

我正在作为本科生的一部分参加操作系统课程,但我遇到了一个令人沮丧的错误,该错误仅在使用 -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”。
如果我用 TAS 交换 TTAS,它似乎可以工作。

void
TAS(int *s)
{
    /* While lock is locked,do nothing */
        While( xchange(s)  != UNLOCKED){}
}

我无法确定是什么导致了这种行为,希望你们中的一些人可以帮助我推理。\

编辑: 更正了 xchange 上错误的无效返回

解决方法

下面的参考评论和来自 Peter Cordes 的指导正确的解决方案是:

#define UNLOCKED 0
#define LOCKED 1
#define TRUE 1


static int
xchg(int volatile *s) {
    int val = LOCKED;

    asm("xchg %0,%1" : "+m"(*s),"+r"(val)::"memory");
    return val;
}

void
TTAS_acquire(int volatile *s) {

    while(TRUE){
        while(*s == LOCKED){}
        if(xchg(s) == UNLOCKED){
            return;
        }
    }
}


void
TTAS_release(int volatile *s) {
    asm("":::"memory");
    *s = UNLOCKED;
}

编辑: 猜猜我在这个上跳了枪!提出的解决方案似乎解决了问题,但这只是症状。我收回这个!还改了错误的返回值,从来没有void。

编辑2: 用 Peter Cordes 指导重写了答案,还包括发布功能,请参阅评论。