2010-05-19 15 views
5

Estoy trabajando en una aplicación de espacio de usuario para un proyecto de Linux incrustado utilizando el kernel 2.6.24.3. Mi aplicación pasa datos entre dos nodos de archivos al crear 2 pthreads que cada uno duerme hasta que se completa una operación IO asincrónica en qué punto se activa y ejecuta un controlador de finalización.¿Puedo evitar que un espacio de usuario de Linux genere pthread en código crítico?

Los controladores de finalización necesitan realizar un seguimiento de la cantidad de transferencias pendientes y mantener un puñado de listas vinculadas que un subproceso agregará y el otro eliminará.

// sleep here until events arrive or time out expires 
for(;;) { 
    no_of_events = io_getevents(ctx, 1, num_events, events, &timeout); 
    // Process each aio event that has completed or thrown an error 
    for (i=0; i<no_of_events; i++) { 
     // Get pointer to completion handler 
     io_complete = (io_callback_t) events[i].data; 
     // Get pointer to data object 
     iocb = (struct iocb *) events[i].obj; 
     // Call completion handler and pass it the data object 
     io_complete(ctx, iocb, events[i].res, events[i].res2); 
    } 
} 

Mi pregunta es la siguiente ...

¿Existe una manera sencilla puedo evitar que el hilo activo en ese momento de ceder mientras se ejecuta el manejador de finalización en lugar de ir por el camino de bloqueo mutex/vuelta?

O, en su defecto, ¿puede Linux configurarse para evitar producir un pthread cuando se mantiene un bloqueo mutex/spin?

Respuesta

4

Puede usar la llamada al sistema sched_setscheduler() para establecer temporalmente la política de programación de la secuencia en SCHED_FIFO, y luego volver a establecerla. Desde la página sched_setscheduler() hombre:

Un proceso SCHED_FIFO se ejecuta hasta que que está bloqueada por una solicitud de E/S, se adelantó por un proceso de mayor prioridad , o hasta que llame sched_yield(2).

(En este contexto, "proceso" en realidad significa "hilo").

Sin embargo, este es un requisito bastante sospechoso. ¿Cuál es el problema que estás esperando resolver? Si solo está tratando de proteger su lista vinculada de manejadores de finalización de acceso concurrente, entonces un mutex normal es el camino a seguir. Haga que el hilo de finalización bloquee el mutex, elimine el elemento de la lista, desbloquee el mutex y luego llame al controlador de finalización.

+0

El requisito es principalmente tratar de mantener el código simple, hay varios elementos que requerirían mutex dentro de los manejadores de finalización, pero si pudiera asegurar que solo se producirían fuera de los manejadores, no creo que necesite ningún código . Supongo que la otra opción es simplemente poner un mutex grueso alrededor de todo el controlador. – KermitG

+4

@KermitG: Si le preocupa que el código del manejador de finalización compita con el código en otro hilo, entonces simplemente evitar el adelantamiento no ayudará. El otro subproceso ya podría estar dentro de la sección crítica cuando se inicia el controlador de finalización; incluso si lo pausa mientras se ejecuta el controlador de finalización, aún verá que los datos en los que está trabajando cambian. En general, si el código en el controlador puede competir, el manejador en sí mismo debería ser responsable de bloquearlo. – caf

1

Creo que querrá usar mutexes/locks para evitar condiciones de carrera aquí. Los mutexes de ninguna manera son magia vudú e incluso pueden hacer que su código sea más simple que el uso de características arbitrarias específicas del sistema, que usted necesita para potencialmente transferir puertos a través de los sistemas. Sin embargo, no sé si esto último es un problema para ti.

1

Creo que está tratando de ser más listo que el programador de Linux aquí, por las razones equivocadas.

La solución correcta es usar un mutex para evitar que los manejadores de finalización se ejecuten en paralelo. Deje que el programador haga su trabajo.

Cuestiones relacionadas