我得到一个奇怪的错误。我实现这两个功能:

int flag_and_sleep(volatile unsigned int *flag)
{
    int res = 0;

    (*flag) = 1;

    res = syscall(__NR_futex, flag, FUTEX_WAIT, 1, NULL, NULL, 0);
    if(0 == res && (0 != (*flag)))
        die("0 == res && (0 != (*flag))");
    return 0;
}

int wake_up_if_any(volatile unsigned int *flag)
{
    if(1 == (*flag))
    {
        (*flag) = 0;
        return syscall(__NR_futex, flag, FUTEX_WAKE, 1, NULL, NULL, 0);
    }
    return 0;
}

和由运行两个POSIX线程测试它们:

static void die(const char *msg)
{
    fprintf(stderr, "%s %u %lu %lu\n", msg, thread1_waits, thread1_count, thread2_count);
    _exit( 1 );
}

volatile unsigned int thread1_waits = 0;

void* threadf1(void *p)
{
    int res = 0;
    while( 1 )
    {
        res = flag_and_sleep( &thread1_waits );
        thread1_count++;
    }
    return NULL;
}

void* threadf2(void *p)
{
    int res = 0;
    while( 1 )
    {
        res = wake_up_if_any( &thread1_waits );
        thread2_count++;
    }

    return NULL;
}

线程2已经有一百万左右的迭代之后,我得到的断言火对我道:

  

./ a.out的   0 == RES &&(0!=(*标记))1 261129 1094433

这意味着该系统调用 - 从而do_futex() - 返回0人认为它应该只由do_futex(WAKE)调用这样做,如果唤醒。但是,我做WAKE呼叫之前,我将该标志设置为0.这似乎标志仍然是1。

这是英特尔,这意味着强存储器模型。所以,如果在线程1我看到从线程2系统调用的结果,我还必须看到在螺纹2的写入这是在呼叫前的结果。

标记和所有指针它是挥发性的,所以我不明白怎么会GCC无法读取正确的值。

我感到困惑。

谢谢!

有帮助吗?

解决方案

比赛时发生线程1变为全周期和重新进入WAIT呼叫时线程2从进

(*flag) = 0;

return syscall(__NR_futex, flag, FUTEX_WAKE, 1, NULL, NULL, 0);

因此,测试有故障。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top