2010-07-08 7 views
6

Ich brauche einen Pool von Threads mit unterschiedlichen Prioritäten zu verwalten, so schrieb ich die folgende Threads Startprozedur:pThreads mit Echtzeit-Priorität

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

Im Prinzip ist der unprivilegierten Benutzer soll nicht diesen Code auszuführen erlaubt sein: Der Aufruf pthread_create() sollte EPERM zurückliefern, da der Thread mit hoher Priorität ausgeführt wird.

Unerwartet funktioniert es für den normalen Benutzer, aber es respektiert die gegebene Priorität überhaupt nicht.

Ich habe versucht, den Code zu ändern, indem die pthread_attr_t zu entfernen und durch die Einplanung Attribut Einstellung, wenn der Thread erstellt wurde:

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

Dieser Ansatz durch die Art und Weise schwierig ist, viel mehr zu verwalten, da im Fall von Fehler Ich muss den neu erstellten Thread beenden. Zumindest scheint es in Bezug auf Berechtigungsanforderungen korrekt zu funktionieren (nur root kann dies ausführen), aber die Prioritäten werden nicht eingehalten.

Mache ich etwas falsch?

EDIT

Ich habe soeben das folgende Stück Code, die von jedem Thread ausgeführt wird:

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

Bei der ersten Methode (nämlich pthread_attr_t Ansatz) es stellt sich heraus, dass der pthread_attr_setschedpolicy ist absolut nicht effektiv, da die Priorität 0 ist und die Richtlinie nicht SCHED_FIFO ist.

Mit der zweiten Methode (nämlich pthread_setschedparam Ansatz) druckt die Funktion die erwarteten Daten, aber die Ausführung verhält sich falsch.

+1

Wie stellen Sie fest, dass die Anrufe nicht eingehalten werden? Ich bin auf etwas Ähnliches gestoßen, aber die API wurde einfach nicht implementiert und als solche fehlgeschlagen. – Ioan

+0

@Ioan: Sehen Sie sich die aktualisierte Version der Frage an. – Dacav

+1

OT: Legen Sie keinen Code innerhalb 'assert()'. Wenn dies mit deaktiviertem Assert kompiliert wird, wird der Code nicht ausgeführt. – bstpierre

Antwort

8

Ich denke, Sie müssen auch pthread_attr_setinheritsched verwenden, um sicherzustellen, dass Ihre Änderungen an der Prioritätseinstellung berücksichtigt werden. Aus der Manpage:

PTHREAD_INHERIT_SCHED Gibt an, dass die Planungsrichtlinie und die zugehörigen Attribute sind von der Erstellung Thread vererbt werden, und die Scheduling-Attribut in diesem attr Argumente ist ignoriert werden.

PTHREAD_EXPLICIT_SCHED Gibt an, dass die Planungsrichtlinie und zugehörigen Attribute sind auf die entsprechenden Werte von diesem Attribut-Objekt gesetzt werden.

Und ein wenig weiter in der Manpage, Sie haben:

Die Standardeinstellung des inherit-Scheduler-Attribut in einem neu initialisiert Thread-Attribute Objekt PTHREAD_INHERIT_SCHED wird.

+0

Es hat funktioniert! Vielen Dank: Das löst eines der beiden Probleme. Aber es ist eher widersinnig: Wenn ich Ihnen eine Priorität vorschlage, dann ist es wahrscheinlich, weil ich möchte, dass Sie es benutzen, oder? :) Jetzt werde ich den Grund für das falsche Verhalten finden: Vielleicht ein Bug? – Dacav

+0

@Dacav: Könnten Sie Ihr zweites Problem ein wenig mehr ausarbeiten? nicht sicher, dass ich es verstehe. Bugs in diesem Bereich (aber deine eigenen ;-) sind sehr unwahrscheinlich. Sie haben nicht viel über das System gesagt, das Sie betreiben, aber heutzutage werden Thread-Implementierungen jeden Tag millionenfach getestet. –

+0

für den Moment ist mein Programm nur ein Gerüst: echte Geschäftslogik soll später hinzugefügt werden. Um die Priorität zu testen, beginnt jeder Thread mit dem Warten auf eine Zustandsvariable, die anschließend gesendet wird. Dann schreibt jeder Thread falsch auf stderr. Was ich erwarte, ist das Ansehen von Threads mit höherer Priorität vor falschen Threads. Ich vermute, dass mein Dual-Core für das unerwartete Interleaving verantwortlich ist ... Ich denke gerade über einen guten Test nach. – Dacav