2010-07-08 25 views
6

devo gestire un pool di thread aventi differenti priorità, così ho scritto la seguente procedura di avvio filo:pthreads con tempo reale priorità

static 
int startup(thrd_t *thrd, thrd_sync_t *sync, int prio) 
{ 
    pthread_attr_t attr; 
    int err; 
    struct sched_param param = { 
     .sched_priority = prio 
    }; 

    assert(pthread_attr_init(&attr) == 0); 
    assert(pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0); 
    assert(pthread_attr_setschedparam(&attr, &param) == 0); 
    err = pthread_create(&thrd->handler, &attr, thread_routine, (void *)thrd); 
    pthread_attr_destroy(&attr); 

    return err; 
} 

In linea di principio l'utente non privilegiato non dovrebbe essere consentito di eseguire questo codice: la chiamata pthread_create() dovrebbe restituire EPERM a causa delle implicazioni di sicurezza nell'esecuzione di un thread con priorità alta.

Inaspettatamente funziona per l'utente normale, ma non rispetta affatto la priorità data.

Ho provato a modificare il codice rimuovendo il pthread_attr_t e impostando l'attributo schedulazione Una volta creato il filo:

static 
int startup(thrd_t *thrd, thrd_sync_t *sync, int prio) 
{ 
    pthread_attr_t attr; 
    int err; 
    struct sched_param param = { 
     .sched_priority = prio 
    }; 

    err = pthread_create(&thrd->handler, NULL /*&attr*/, thread_routine, 
         (void *)thrd); 
    if (err != 0) return err; 

    err = pthread_setschedparam(thrd->handler, SCHED_FIFO, &param); 
    if (err != 0) return err; 

    return err; 
} 

Questo approccio proposito è molto più difficile da gestire, in quanto in caso di errore Ho bisogno di uccidere il thread appena creato. Almeno sembra funzionare correttamente rispetto ai requisiti di autorizzazione (solo root può eseguirlo), ma le priorità non vengono rispettate.

Sto facendo qualcosa di sbagliato?

EDIT

Ho appena aggiunto il seguente pezzo di codice che viene eseguito da ogni filo:

static 
void getinfo() 
{ 
    struct sched_param param; 
    int policy; 

    sched_getparam(0, &param); 
    DEBUG_FMT("Priority of this process: %d", param.sched_priority); 

    pthread_getschedparam(pthread_self(), &policy, &param); 

    DEBUG_FMT("Priority of the thread: %d, current policy is: %d and should be %d", 
       param.sched_priority, policy, SCHED_FIFO); 
} 

Con il primo metodo (cioè pthread_attr_t approccio) risulta che il pthread_attr_setschedpolicy non è totalmente efficace, poiché la priorità è 0 e la politica non è SCHED_FIFO.

Con il secondo metodo (ovvero l'approccio pthread_setschedparam) la funzione stampa i dati previsti, ma l'esecuzione continua a comportarsi in modo errato.

+1

Come si determinano le chiamate non vengono rispettate? Ho riscontrato qualcosa di simile, ma l'API non è stata semplicemente implementata e non è riuscita in quanto tale. – Ioan

+0

@Ioan: vedere la versione aggiornata della domanda. – Dacav

+1

OT: non inserire il codice all'interno di 'assert()'. Se questo è compilato con assert disabilitato, il codice non verrà eseguito. – bstpierre

risposta

8

Penso che sia necessario utilizzare pthread_attr_setinheritsched per garantire che le modifiche alle impostazioni prioritarie vengano prese in considerazione. Dalla pagina man:

PTHREAD_INHERIT_SCHED Specifica che la politica di pianificazione e gli attributi associati sono essere ereditata dalla creazione filo, e attributi la programmazione in questa argomentazione attr devono essere ignorato.

PTHREAD_EXPLICIT_SCHED Specifica che la politica di scheduling e gli attributi associati sono da impostare i valori corrispondenti da questo oggetto attributo.

E un po 'più avanti nella pagina man, si ha:

L'impostazione di default dell'attributo inherit-scheduler in un thread appena inizializzato attributi degli oggetti è PTHREAD_INHERIT_SCHED.

+0

Ha funzionato! Grazie mille: questo risolve uno dei due problemi. Tuttavia è piuttosto controintuitivo: se ti sto specificando una priorità, probabilmente è perché voglio che tu la usi, giusto? :) Ora troverò il motivo del comportamento sbagliato: forse un bug? – Dacav

+0

@Dacav: potresti approfondire un po 'di più il tuo secondo problema? non sono sicuro di averlo capito. Insetti in quella zona (ma i tuoi ;-) sono molto improbabili. Non hai detto molto sul sistema che stai utilizzando, ma oggigiorno le implementazioni di thread sono davvero ben testate miliardi di volte al giorno. –

+0

per il momento il mio programma è solo un'impalcatura: la logica di business reale sarà aggiunta in seguito. Per testare la priorità, ogni thread inizia in attesa di una variabile di condizione, che viene successivamente trasmessa. Quindi ogni thread continua a scrivere fasulli su stderr. Quello che mi aspetto è guardare i thread con priorità più alta "falsi prima dei thread con priorità più bassa". Sospetto che il mio dual-core sia responsabile di un interleaving inaspettato ... Sto pensando a un buon test, proprio ora. – Dacav