Question

Je reçois une erreur bizarre. Je mis en œuvre ces deux fonctions:

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

et de les tester en exécutant deux threads 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;
}

Après thread2 a eu environ un million d'itérations, je reçois le feu assert sur moi:

  

./ a.out   0 == res && (0! = (* Drapeau)) 1 261129 1094433

Cela signifie que le syscall - et par là do_futex () - retourne 0. L'homme dit qu'il ne devrait le faire si réveillé par un appel do_futex (WAKE). Mais avant de faire un appel WAKE, je mis le drapeau à 0. Ici, il semble que le drapeau est toujours 1.

Ceci est Intel, ce qui signifie fort modèle de mémoire. Donc, si je vois dans thread1 les résultats d'un syscall à thread2, je dois aussi voir les résultats de l'écriture en fil 2 qui était avant l'appel.

Drapeau et tous les pointeurs vers ce sont volatiles, donc je ne vois pas comment gcc pouvait manquer de lire la valeur correcte.

Je suis dérouté.

Merci!

Était-ce utile?

La solution

la course se produit lorsque le fil 1 va le cycle complet et est réadmis ATTENDRE appeler lorsque le fil 2 passe de

(*flag) = 0;

à

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

Le test est défectueux.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top