[Kos-dev] Reentrance de reschedule : un solution ?

Thomas Petazzoni kos-dev@enix.org
Sat, 23 Jun 2001 17:00:43 +0200


> J'ai lu tes idees sur le site Web. Ca fait un moment que l'idee
> d'angliciser le site web me trote aussi dans la tete : au moins la
> presentation, les news et les docs. Mais bon, manque d'envie pour
> ca. Mais sur le principe, d'accord.

max, tu serais pas motive pour t'occuper de cette partie du site ? ca
serait vraiment pas mal de faire profiter a tous les developpeurs des
docs disponibles et regroupees sur le site de kos.

> On est en cpl0 : les mecs qui ecrivent du code ne sont pas autorises a
> ecrire n'importe quoi, ou a faire n'importe quoi sans verification. Si
> il arrive que le mec touche a la main a la pile, ou si il met des
> structures char[1024*1024] sur la pile, c'est tant pis pour le
> systeme. Il y a un minimum de rigueur a avoir quand on ecrit du code
> cpl0. C'est pas le role de l'OS de contourner les (grossieres) erreurs
> du programmeur de l'OS.

d'accord, donc si pour un thread donne, on detecte un acces a la pile
completement en dehors de sa zone normale (non continuite de
l'accroissement de la pile), bin on arrete le systeme. ca me parait pas
mal. mais a ce moment la, les thread_stack_fault, va falloir eviter :o)
> Bon, alors ce que tu crains, c'est le scenario suivant :
> 
>   thread A:
>     ...
>     ----------------
>     | PAF: isr_clock :
>     |   ...
>     |   next_thread = current = reschedule(); // current <- thread A
>     |   ...
>     |   --------------------
>     |   |  PAF: #DF
>     |   |  ...
>     |   |  thread A->state = DELETED;
>     |   |  current = reschedule(); // current <- thread B
>     |   |  IRET
>     |   --------------------
>     |   ... // retour dans isr
>     |   switch_stack_vers_next_thread(); // stack <- stack thread A
>     |   IRET;
>     ----------------
>     RETOUR dans thread A, or thread A->state == DELETED !!!!
> 
> C'est ca que tu crains ?

bin disons que moi je pensais pas que DF ferait un reschedule, mais
admettons (encore que ce soit discutable de faire un reschedule apres un
DF, car le thread peut etre relance directement. enfin bon si tu penses
que c'est mieux... je connais pas grand chose a tous ces problemes, mais
si tu pouvais expliquer les motivations poussant a faire reschedule dans
ton DF...).

a part ca, c'est effectivement un scenario comme celui-la que je
craignais.

>    NI reschedule(), NI ce qui vient apres (cad avant le IRET de
>     l'isr) n'utilisent PLUS ("plusssssse") de pile que ce qui
>     precedait dans l'ISR 

ouais alors la pour prouver ca, ca risque d'etre un peu chaud.

> Mais c'est pas beau comme solution (et chiatique si on se plante dans
> l'estimation de la profondeur de pile necessaire), et c'est pas
> franchement satisfaisant cote perfs (c'est toujours idiot de charger
> une ligne de cache si ca sert a rien, et de faire 2 reschedules en
> rafale : le premier dans le #DF, le 2eme dans l'ISR).

moi aussi, je suis pour laisser tomber une solution aussi peu propre.

> Autre methode proposee (plus srieuse)
> -------------------------------------
> 
> Tout d'abord, il vaudrait mieux avoir au niveau des ISR, un truc du
> genre :
>   reschedule()
>   switch_pile();
>   iret
> Et RIEN d'autre entre reschedule et iret. Avec un postulat important
> sur switch_pile : il n'affecte pas la pile plus que reschedule le
> fait. Donc, si #DF genant il doit y a avoir, il se situe dans le
> reschedule et pas apres. Ca, ca parait pas trop complique a realiser.

tu oublies le set_current_thread, que reschedule ne fait pas lui meme,
justement pour eviter des problemes de consistence. par exemple dans
l'IRQ timer, le reschedule est loin devant le iret, mais le
set_current_thread est juste avant.
quant au switch_pile y'a pas a s'en faire, c'est fait par le pre handler
du ISR (idtasm.S), et ca fait un movl sur esp, pi plein de pop, donc la
y'a plus consommation de pile.

> Ensuite, il est a noter que le reschedule() n'est pas appele que par
> l'ISR clock : mais plutot par toutes les ISR, voire certaines
> exceptions (#PF quand il y a blocage pour aller chercher une page
> swappee par exemple). Bref, on va retrouver ce probleme a d'autre
> endroits. Reste a identifier le probleme. Ce "probleme" est la
> reentrance de reschedule.

belle introduction a ce fameux probleme.

> Le principe, c'est de relancer le reschedule() de plus bas niveau
> (typiquement : dans ISR) quand on se rend compte qu'il a ete
> interrompu par un autre reschedule() de plus haut niveau (typiquement :
> dans #DF). En plus, le reschedule() de plus haut niveau fait le
> minimum (ie ne fait pas un vrai reschedule avec parcours de la liste
> des taches, ...) : il signale juste qu'un reschedule() doit etre
> redemarre au plus bas niveau.

je pense que ta solution convient pour le probleme pose.

> Voila, comme ca, on a resolu le pb de la reentrance de reschedule. En
> rapprochant le reschedule du switch_stack et de l'iret, on resoud le
> probleme de #DF *apres* le reschedule (impossible puisque la stack a
> deja ete utilisee avant par le reschedule, donc est dispo).

ok alors ne serait-il pas bon de coder tout ca directement dans les pre
handlers en asm (idtasm.S) pour etre sur qu'un mauvais codeur de handler
d'irq fasse de betises ? ca pourrait peut etre etre plus esthetique. par
contre l'ennui c'est que cette histoire de reschedule est portable, donc
la mettre dans un fichier en assembleur est plus que discutable.

> Voila les 2 solutions que je vois. Je trouve la 2eme bien meilleure
> (plus belle). Mais comme j'ai pas teste, et que les problemes poses
> sont vraiment tres fins, faudrait s'assurer que c'est Ok. En SMP,
> c'est encore un autre bordel : il faut s'occuper de la reentrance au
> niveau de chaque processeur : pas globalement sur tous les
> processeurs. Donc il faut un moyen d'identifier le processeur qui est
> dans le scheduler, et egalement sur quel processeur il faudra "another
> reschedule". C'est plus complique.

apres en avoir discute avec d2 par icq, je tiens a preciser que meme si
l'application au SMP de cette technique est un peu plus complexe, elle
n'en demeure pas moins tout a fait faisable ! d2 nous expliquera ce qui
est necessaire en temps voulu.


sinon, j'ai lu une des deux docs concernant l'implementation de la
gestion de la memoire virtuelle sous SunOS, et je trouve qu'en gros nos
idees etaient un peu pres les memes. en effet, dans KOS, chaque team a
une sorte d'as (address space) qui est constitue par l'arbre des regions
virtuelles (que eux appelent segments). on a aussi prevu de quoi gerer
les flags de protection.
en gros eux ils proposent *as_alloc() et as_free() qui n'ont pas
vraiment lieu d'exister chez nous, car l'arbre des regions virtuelles
est directement pointe par la structure team_t. ils proposent *as_dup()
qui permet de dupliquer un address space, pour le fork. on peut tout a
fait imaginer une telle fonction pour copier notre arbre.
ils ont un as_map pour mapper un objet dans leur address space. pour
l'instant nous ne mappons que des zones de memoires, et non pas des
fichiers ou des peripheriques, mais nous envisagions de toute facon de
coder une telle fonction un jour. dans SunOS, les fichiers et les
peripheriques sont consideres comme des objets, mais peut etre pourrions
nous considerer les zones de memoire physiques mappees comme des objets.
je ne sais pas si c'est faisable compte tenu du mecanisme de swapping,
et en plus c'est quelque chose que nous avions envisage mais que nous
avons prefere laisser tomber.
as_unmap, sans commentaire.
as_setprot, elle n'est pas encore codee dans KOS, mais toutes les
structures etaient prevues pour pouvoir affecter des droits sur une
partie d'une region virtuelle.
as_chekprot, sans commentaire.
as_fault sert a resoudre une faute. ca pourrait etre utile dans KOS,
pour decharger le handler de page fault ou de double fault par exemple.
en effet, nous voulions generaliser des structures de donnees, pour que
le page fault puisse facilement savoir si l'adresse fautive a bien ete
allouee. il faudrait donc que le handler puisse parcourir les listes de
kvalloc (et peut etre de kmalloc) pour avoir ces informations. peut etre
un machin dans l'esprit de as_fault peut nous aider ?

concernant le hat (hardware address translation) en gros ca sert juste a
pouvoir mapper/unmapper des zones de memoire physique en memoire
virtuelle. c'est la partie non portable qui doit savoir se debrouiller
avec les PT et PD.

concernant leur I/O layer, c'est juste une couche qui s'occupe de
recuperer les pages swappees, d'aller chercher des pages dans les
fichiers (file mapping)...

a priori, je trouve que nous n'avions pas vraiment pris de direction
contraire a celle de l'implementation de la memoire virtuelle proposee
dans SunOS. qu'en pensez-vous ?

amicalement,

thomas

-- 
PETAZZONI Thomas
thomas.petazzoni@meridon.com     UIN : 34937744
Projet KOS : http://kos.enix.org
Page Perso : http://www.enix.org/~thomas/