質問

私は奇妙なエラーを取得しています。私は、これらの二つの機能を実装します:

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

と2つの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 100万かそこらの反復があった後、私は私にアサート火を取得します:

  

./ a.outの   0 == RES &&(0!=(*フラグ))1 261129 1094433

この手段のsyscallこと - それによってはdo_futex() - 0マン返されたが、それが唯一もしそうならdo_futex(WAKE)の呼び出しによってウェイクアップすればいいと言います。私はWAKE呼び出しを行う前に、しかし、その後、私はフラグがまだ1であることが表示されますここで0にフラグを設定します。

これは、強力なメモリモデルを意味インテル、です。だから私は、スレッド2でのシステムコールの結果を参照してくださいスレッド1であれば、私はまた、呼び出しの前にしたスレッド2の書き込みの結果を参照してくださいする必要があります。

旗とそれへのすべてのポインタは、私はgccが正しい値を読み取ることができない可能性がどのように表示されていないので、揮発性である。

私は困惑しています。

ありがとうございます。

役に立ちましたか?

解決

スレッド2は、

から行くと、スレッド1がフルサイクルと再入力するWAITコールを行くとき

レースが起こります

(*flag) = 0;

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

テストが故障しているので。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top