Domanda

Ricevo un errore di strano. Ho implementato queste due funzioni:

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

e li prova eseguendo due thread 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;
}

Dopo Thread2 ha avuto circa un milione di iterazioni, ho ottenere il fuoco asserzione su di me:

  

./ a.out   0 == res && (0! = (* Bandiera)) 1 261.129 1.094.433

Ciò significa che la chiamata di sistema - e in tal modo do_futex () - tornato a 0. L'uomo dice che dovrebbe farlo solo se svegliato da una chiamata do_futex (WAKE). Ma poi prima di fare un campanello d'allarme, ho impostato la bandiera a 0. Qui sembra che la bandiera è ancora 1.

Questa è Intel, il che significa una forte modello di memoria. Quindi, se in Thread1 vedo i risultati di una chiamata di sistema in Thread2, devo anche vedere i risultati della scrittura in filo 2, che era prima della chiamata.

Flag e tutti i puntatori ad esso sono volatili, quindi non vedo come gcc poteva non leggere il valore corretto.

io sono sconcertato.

Grazie!

È stato utile?

Soluzione

corsa avviene quando il filo 1 va il ciclo completo e rientra chiamata WAIT quando il filo 2 passa da

(*flag) = 0;

a

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

Quindi, il test è difettoso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top