Frage

Ich erhalte einen seltsamen Fehler. Ich implementiert diese beiden Funktionen:

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

und Test sie durch Ausführen von zwei Posix-Themen:

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

Nach thread2 eine Million oder so Iterationen hatte, habe ich das assert Feuer auf mir:

  

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

Das bedeutet, dass die syscall - und damit do_futex () - zurück 0. Man sagt, es sollte nur dann tun, wenn von einem do_futex (WAKE) Anruf geweckt. Aber dann, bevor ich einen Weckruf zu tun, habe ich das Flag auf 0 Hier scheint es, dass Flag noch 1 ist.

Dies ist Intel, das starke Speichermodell bedeutet. Also, wenn in thread1 Ich sehe die Ergebnisse einer syscall in thread2, muss ich auch die Ergebnisse des Schreib in Thread 2, die vor dem Aufruf war sehen.

Flag und alle Zeiger auf sie flüchtig sind, so sehe ich nicht, wie gcc scheitern könnte den richtigen Wert zu lesen.

Ich bin ratlos.

Danke!

War es hilfreich?

Lösung

passiert, wenn das Rennen Faden 1 den vollständigen Zyklus geht und wieder eintritt, wenn WAIT Anruf Gewinde 2 geht von

(*flag) = 0;

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

So ist der Test fehlerhaft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top