Pregunta

Estoy recibiendo un error extraño. He implementado estas dos funciones:

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

y prueba de ellos mediante la ejecución de dos hilos 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;
}

Después de thread2 ha tenido un millón o más iteraciones, me sale el fuego en mí afirman:

  

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

Esto significa que la llamada al sistema - y por lo tanto do_futex () - devuelto 0. El hombre dice que sólo debería hacerlo si despertado por una llamada do_futex (despertar). Pero a continuación, antes de hacer una llamada de atención, me puse la bandera a 0. Aquí parece que la bandera sigue siendo 1.

Este es Intel, lo que significa una fuerte modelo de memoria. Así que si en Thread1 veo el resultado de una llamada al sistema de thread2, me será necesario ver también los resultados de la escritura en la rosca 2 que era antes de la llamada.

bandera y todos los punteros a que son volátiles, por lo que no veo cómo gcc podría dejar de leer el valor correcto.

Estoy desconcertado.

Gracias!

¿Fue útil?

Solución

la carrera pasa cuando el hilo 1 va el ciclo completo y vuelve a entrar en la llamada espera cuando el hilo pasa de 2

(*flag) = 0;

a

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

Así que la prueba es defectuoso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top