Swisslinux.org

− Le carrefour GNU/Linux en Suisse −

 

Langue

 

Le Forum

Vous n'êtes pas identifié.

#1 23 Jul 2008 13:06:40

[GO]Skywalker13
Modérateur
Lieu: Choëx (VS)
Date d'inscription: 05 Oct 2004
Messages: 896
Site web

[C] problème de priorité entre threads (Résolu autrement)

Hello,

J'aimerais rendre un thread plus prioritaire qu'un autre mais je suis confronté à plusieurs problèmes. Tout d'abord le soft doit fonctionner en userland. Ainsi je ne peux pas utiliser les schedulers SCHED_RR ou SCHED_FIFO qui ne peuvent être paramétrés qu'en root. Et donc face à SCHED_OTHER, j'ai droit comme priorité max : 0 et comme priorité min: 0.

Mon but n'étant pas que mon processus soit plus prioritaire qu'un autre.. je veux uniquement qu'un des thread dans mon processus le soit. Sachant que Linux considère les threads comme des process au niveau du scheduler je peux comprendre que ça ne puisse pas se faire au niveau userland.

Mais comment le faire en interne? Bloquer tous les threads avec un cond_wait le temps que le thread que j'aimerais avoir en plus haute priorité ait fait son job? C'est moche et avec toutes les synchro que j'utilise déjà ca devient complexe (mais faisable).. quitte a réécrire un scheduler en interne ce qui est ridicule à mon avis..  bref je sais plus quoi faire...

Le contexte c'est ca:

J'ai un thread superviseur qui gère toutes les actions entre l'utilisateur de la librairie (donc l'API public) et le backend de la lib (un soft ou d'autres libs).
La dedans j'ai également un event handler qui se charge de renvoyer les events du backend au superviseur, et le superviseur renvoit les events au user.

en résumé je veux :

(priorité normal) USER --> superviseur --> backend
(haute priorité) USER <-- superviseur <-- event handler <-- backend


Actuellement le """problème""" c'est que l'event handler à ""la même (on se comprend)"" priorité que le superviseur (SCHED_OTHER).. Et j'aimerais que dès que l'event handler a du job a faire (donc quand c'est lui qui cause au superviseur et pas le user), il soit prioritaire..
Car actuellement si je flood le superviseur depuis le USER, j'ai souvent des events qui arrivent vachement en retard.

J'ai testé en SCHED_RR (donc en root) et c'est parfait.. mais comment le faire en userland?


Merci


EDIT (pour que se sois plus compréhensible):

Le bleu doit être plus prioritaire que le jaune.
http://www.geexbox.org/~schroeterm/libp … ternal.png

http://www.geexbox.org/~schroeterm/libplayer/internal.png


Mathieu SCHROETER
log.schroetersa.ch

Hors ligne

 

#2 25 Jul 2008 12:53:35

[GO]Skywalker13
Modérateur
Lieu: Choëx (VS)
Date d'inscription: 05 Oct 2004
Messages: 896
Site web

Re: [C] problème de priorité entre threads (Résolu autrement)

Je bloque toujours mais voilà où j'en suis..

Selon POSIX il est possible avec les PThread de gérer le scheduling uniquement à l'intérieur du process et pas par rapport à tout le système. C'est sensé être le joli flag PTHREAD_SCOPE_PROCESS à la place du PTHREAD_SCOPE_SYSTEM qui est utilisé par défaut.. Mais pas de chance, le noyau Linux ne connait que le scope system. A noter tout de même que FreeBSD sait gérer les deux scopes (peut être que ca demande aussi les privilèges root, je ne sais pas.. quoi qu'il en soit ça ne change rien à mon problème)...

J'ai pensé faire une entrée sur le superviseur spécialement pour les évènements. Néanmoins ça me demande qu'en même de devoir bloquer le superviseur dès que l'event handler choppe un event, mais je ne veux pas de lien directe entre l'event handler et le superviseur. Ils n'ont pas conscience l'un de l'autre et je ne veux pas changer par cohérence.

J'ai essayé de freiner la queue du superviseur avec tous les controls qui ne sont pas des events (avec un simple mutex). Ca augmente la priorité pour les events néanmoins ca ne le fait qu'au niveau de la queue. Finallement c'est moche et ça ne les empêche pas d'arriver souvent en retard jusque là. (en plus tout devient moins réactif.. c'est pas énorme mais ca se ressent qu'en même)

J'ai pensé aussi au signaux mais la majorité des fonctions pthread ne sont de toute façon pas Async-signal safe et c'est donc le meilleur moyen de tout tourner en deadlocks.

J'ai bien peur qu'au final je devrais revoir le concept..


Mathieu SCHROETER
log.schroetersa.ch

Hors ligne

 

#3 25 Jul 2008 19:43:59

[GO]Skywalker13
Modérateur
Lieu: Choëx (VS)
Date d'inscription: 05 Oct 2004
Messages: 896
Site web

Re: [C] problème de priorité entre threads (Résolu autrement)

Bon je continue le monologue,  j'ai une solution satisfaisante (même assez bonne dans l'ensemble) mais j'ai du revoir mon concept. J'utilisais précédemment le superviseur pour sérialiser le callback externe avec les actions de l'utilisateur. L'avantage c'était surtout que je n'avais pas besoin d'effectuer de synchro sur l'event handler car le superviseur finissait de toute façon par renvoyer le callback au user entre deux autres actions.

J'ai donc supprimé le retour du callback par le superviseur pour le mettre directement sur le même thread que l'event handler. Ainsi je suis obligé de synchroniser le superviseur avec l'event handler pour ne pas que la librairie soit concourante par rapport au USER.
Et cette fois le job du SCHED_OTHER est bon, dans le sens ou j'ai deux queues en parallèles (et non plus une seule queue qui recevait également les events pour les renvoyer au user), le superviseur et l'event handler se passe le témoin chacun leur tour pour autant qu'ils aient les deux du job. J'ai qu'en même pu indirectement garder une séparation entre le superviseur et l'event handler en passant uniquement les pointeurs adéquats (cond, mutex, etc,..) entre les deux, le temps de l'initialisation (et il n'y a donc pas de dépendance d'header).

http://www.geexbox.org/~schroeterm/libp … nal.r1.png

http://www.geexbox.org/~schroeterm/libplayer/internal.r1.png


Mathieu SCHROETER
log.schroetersa.ch

Hors ligne

 

#4 12 Feb 2009 15:55:51

[GO]Skywalker13
Modérateur
Lieu: Choëx (VS)
Date d'inscription: 05 Oct 2004
Messages: 896
Site web

Re: [C] problème de priorité entre threads (Résolu autrement)

[mode=déterrage state=on]

J'ai enfin trouvé comment modifier la priorité d'un thread en étant simple utilisateur.

Petit rappel de base: un thread est identifié par un TID du point de vue des PThread, mais du point de vue de Linux c'est un PID (se ne sont pas du tout les mêmes identifiants).
Pour changer la priorité d'un thread, il faut changer de scheduler (par défaut SCHED_OTHER) et passer en SHED_RR ou SCHED_FIFO, SCHED_OTHER n'étant pas paramétrable. Et la où ca coince c'est que seul le root peut utiliser SCHED_RR et SCHED_FIFO. (et alors on traite des priorités temps réelles)

Donc la solution c'est de modifier la priorité du PID étant donné que pour Linux, un thread c'est un process. Pour cela il faut connaître le PID du thread. Normalement la libc fournit une fonction gettid() mais pas de bol, elle n'existe pas en glibc. L'astuce c'est donc de passer par un appel système.


Code:

#include <unistd.h>
#include <sys/resource.h>
#include <sys/syscall.h>

void
my_setpriority (int prio)
{
  pid_t pid = syscall (SYS_gettid);
  setpriority (PRIO_PROCESS, pid, prio);
}

et le tour est joué.. si votre application (et donc vos threads) sont exécutés avec la priorité 0, avec cette fonction vous pouvez baisser la priorité de 0 à 19. Bien entendu, pour augmenter la priorité il faut être root. Mais ici il est donc possible de favoriser un thread plutôt qu'un autre.. Et surtout, il est possible de créer des tâches de fond!


IMPORTANT: j'entends déjà ceux venir me dire.. tu fais getpid() et t'as le PID.. Alors non, pas du tout! getpid() renvoit le PID du processus du main() et pas celui du thread depuis lequel il est exécuté! (sauf erreur ça marche avec un kernel 2.4.x, c'est donc un problème et sans chercher à être portable, je pense que l'appel système fonctionne sur tous les kernels Linux, mais ça demande une confirmation)

[/mode]


Mathieu SCHROETER
log.schroetersa.ch

Hors ligne

 

Pied de page des forums

Powered by FluxBB