= Réplication des tables de pages et des listes de vseg = [[PageOutline]] == __1) Descripteur de vseg__ == Puisque ALMOS-MK n'utilise pas la MMU paginée des processeurs, les table des pages ne sont utilisées que pour définir le mapping des vsegs des processus utilisateur. Un descripteur de vseg contient les informations suivantes : * TYPE : définit la politique de réplication/distribution (CODE / STACK / DATA / HEAP / HEAPXY / FILE / ANON) * FLAGS : définit les droits d’accès * VBASE : adresse virtuelle de base * LENGTH : longueur du segment * BIN : pathname to the .elf file. (seulement pour les types DATA et CODE) * X,Y : coordonnées du cluster où est mappé le vseg (seulement pour un vseg localised) * MAPPER : radix-tree contenant les pages physiques allouées à ce vseg (seulement pour les types CODE, DATA, FILE). == __2) Tables de pages et listes de vsegs__ == Les différentes informations associées à un processus P sont regroupées dans le descripteur de processus (structure process_t). Ce descripteur de processus, ainsi que les structures qu'il contient, est - partiellement - répliqué dans tous les clusters contenant au moins un thread du processus P, appelés clusters actifs. La table des pages est utilisée par le noyau pour stocker le mapping de chaque page de chaque vseg d'un processus. cette table des pages fait partie des informations - partiellement - répliquées, et nous appelons PT(P,K) la table des pages du processus P dans le cluster K. La liste des vsegs définis pour un processus est utilisée par le noyau en cas de défaut de page pour vérifier que l'adresse virtuelle non happée correspond à un segment défini, et pour déterminer le type du segment. Cette liste fait également partie des informations - partiellement - répliquées , et nous appelons VSL(P,K) la liste des vsegs du processus P dans le cluster K. === 2.1) Evolution des PT(P,K) === Pour un même processus P, le contenu des différentes tables de pages PT(P,K) évolue au cours du temps, et il évolue différemment dans les différents clusters actifs: D'une part, le contenu des tables P évolue dynamiquement dans les clusters en fonction des défauts de pages causés par les threads de P s’exécutant chaque cluster. De plus le mapping des segments ''private'' (CODE et STACKS) varie d’un cluster à un autre, puisqu'une même adresse virtuelle correspond à des adresses différentes suivant les clusters. Pour ce qui concerne les vsegs ''public'', seul le cluster de référence contient l’état complet du mapping. === 2.2) Evolution des VSL(P,K) === Pour un même processus P, le contenu des différentes listes de vsegs VSL(P,K) évolue au cours du temps, et n’est pas identique dans tous les clusters. En effet les listes de vsegs doivent être identiques pour ce qui concerne les vsegs ''public'', mais chaque vseg ''private'' n’est enregistré que dans le cluster auquel il appartient. Pour ce qui concerne les vsegs ''public'', tout ajout dynamique d’un nouveau vseg ou toute extension d'un vseg existant doit être répercuté dans tous les clusters actifs. == __3) Enregistrement et destruction des vsegs dans les VSL(P,K)__ == La politique d’enregistrement et de destruction des vsegs dans les VSL(P,X) dépend du type de vseg: === 3.1) DATA === Ce type de vseg est enregistré dans la VSL(P,Z)) du cluster Z propriétaire du processus P au moment de la création de P. Il est enregistré dans la VSL(P,A) d’un autre cluster A chaque fois qu’un thread de P est créé dans le cluster A, si ce cluster ne contenait pas encore de thread du processus P. La longueur est définie par le fichier .elf contenant le code binaire du processus. Il n’y a pas de cluster de mapping pour un vseg ''distributed''. Ce type de vseg n’est détruit que lors de la destruction du processus. === 3.2) CODE === Ce type de vseg est enregistré dans la VSL(P,Z) du cluster Z propriétaire du processus P au moment de la création de P. Il est enregistré dans la VSL(P,A) d’un autre cluster A chaque fois qu’un thread de P est créé dans le cluster A, si ce cluster ne contenait pas encore de thread du processus P. La longueur est définie par le fichier .elf contenant le code binaire du processus. Le cluster de mapping est toujours le cluster local pour un vseg ''private''. Ce type de vseg n’est détruit que lors de la destruction du processus. === 3.3) STACK === Un vseg de type STACK est enregistré dans la VSL(P,X) du cluster X chaque fois qu’un thread est crée dans le cluster X pour le processus P. Les VSL(P,Y) des autres clusters Y n’ont pas besoin d’être mises a jour car un vseg STACK dans un cluster X n’est ni connu ni accédé depuis un autre cluster Y. La longueur est définie par un paramètre global de l’OS : MIN_STACK_SIZE. Le cluster de mapping est toujours le cluster local pour un vseg ''private''. Ce type de vseg est éliminé de la VSL(P,X) lors de la destruction du thread. === 3.4) HEAP === Ce type de vseg est enregistré dans la VSL(P,Z) du cluster Z propriétaire du processus P au moment de la création de P. Il est enregistré dans la VSL(P,A) d’un autre cluster A chaque fois qu’un thread de P est créé dans le cluster A, si celui-ci ne contenait pas encore de thread du processus P. La longueur est un paramètre global de l’OS : STANDARD_MALLOC_HEAP_SIZE. Il n’y a pas de cluster de mapping pour un vseg ''distributed''. Ce type de vseg n’est détruit que lors de la destruction du processus. === 3.5) REMOTE === Ce type de vseg est enregistré dans la VSL(P,A) de tous les clusters A qui contiennent au moins un thread de P, au moment où un thread quelconque de P exécute un remote_malloc(x,y) dans un cluster K. Le noyau du cluster K envoie une VSEG_REQUEST_RPC vers le cluster Z propriétaire de P, si un vseg de type REMOTE n’existe pas déjà dans la VSL(P,K). Les arguments sont le PID et le type du vseg manquant. Si ce type de vseg n’existe pas déjà dans la VSL(P,Z), le noyau de Z broadcaste une VSEG_REGISTER_RPC vers tous les clusters actifs de P. La longueur est un paramètre global de l’OS : REMOTE_MALLOC_HEAP_SIZE. Le cluster de mapping est défini par les arguments (x,y) du remote_malloc(). Ce type de vseg n’est détruit que lors de la destruction du processus. === 3.6) FILE === Ce type de vseg est enregistré dans la VSL(P,A) de tous les cluster A qui contiennent au moins un thread de P, au moment où un thread quelconque de P exécute un mmap(file , size) dans un cluster K. Le noyau du cluster K envoie une VSEG_REQUEST_RPC vers le cluster Z propriétaire de P. Les arguments sont le PID, le type de vseg, le descripteur de fichier et la taille. Le noyau du cluster Z broadcaste une VSEG_REGISTER_RPC vers tous les autres clusters actifs de P. La longueur du vseg est définie par l’argument size du mmap(). Le cluster de mapping est défini par l’argument file, et il est quelconque puisque le cache d’un fichier peut être placé sur n’importe quel cluster (politique de répartition uniforme). Ce type de vseg est détruit lors de l’exécution du munmap(), en utilisant un mécanisme en deux RPC comme pour la création. === 3.7) ANON === Ce type de vseg est enregistré dans la VSL(P,A) de tous les cluster A qui contiennent au moins un thread de P, au moment où un thread quelconque de P exécute un mmap(anonyme , size) dans un cluster K. Le noyau du cluster K envoie une VSEG_REQUEST_RPC vers le cluster Z propriétaire de P. Les arguments sont le PID, le type de vseg, le descripteur de fichier, la taille … To be completed … Le noyau du cluster Z broadcaste une VSEG_REGISTER_BCRPC vers tous les autres clusters actifs de P. La longueur du vseg est définie par l’argument size du mmap(). Il n’y a pas de cluster de mapping pour un vseg distributed. Ce type de vseg est détruit lors de l’exécution du munmap(), en utilisant un mécanisme en deux RPC comme pour la création. == __4) Introduction d’une entrée dans une table des pages__ == L’ajout d’une entrée dans une PT(P,K), pour un processus P dans un cluster K est la conséquence d’un défaut de page causé par n’importe quel thread du processus P s’exécutant dans le cluster K, sur le principe du “on-demand paging”. Tous les threads d’un processus P placés dans un cluster K utilisent exclusivement la PT(P,K) locale, et reportent le défaut de page à l’instance locale du noyau. Le traitement du défaut de page dépend du type du segment : === 4.1) CODE === Il existe un vseg de ce type dans la VSL de tous les clusters contenant au moins un thread du processus P. Si le cluster K qui détecte le défaut de page est différent du cluster propriétaire du processus Z, le noyau du cluster K doit allouer une page physique dans le cluster K. Pour initialiser cette page, il envoie une PT_MISS_RPC au cluster Z propriétaire du processus. Quand il obtient le PTE stocké dans la PT(P,Z), il effectue un remote_memcpy() pour copier le contenu de la page physique du cluster Z vers la page physique du cluster K. Il termine en introduisant le PTE manquant dans la PT(P,K). Si le cluster K est le cluster propriétaire de Z, il alloue une page physique, initialise cette page en s’adressant au système de fichier, pour récupérer le contenu de la page manquante dans le cache du fichier .elf, et met à jour la PT(P,Z). QUESTION : dans le cluster propriétaire Z, faut-il faire une copie de la page du cache de fichier vers une autre page physique ? [AG] === 4.2) STACK === Les vsegs STACK associées aux thread placées dans un cluster X sont mappées dans le cluster X, et sont gérés indépendamment les uns des autres dans les différents clusters. Le noyau du cluster X doit allouer une page physique, et l’enregistrer dans la PT (P,X) locale sans l’initialiser. Si l’adresse demandée tombe dans la dernière page disponible pour le vseg, la longueur du vseg STACK peut être dynamiquement localement augmentée dans la VSL(P,X) locale, si il y a de la place dans dans la zone de l’espace virtuel utilisée pour les piles. Comme suggéré par Franck, on peut imaginer une politique d’allocation par dichotomie utilisant deux arguments : MAX_STACK_SIZE définissant la longueur totale de la zone réservée aux piles, et MIN_STACK_SIZE définissant la longueur minimale d’une pile particulière. === 4.3) DATA === Ce vseg étant ''distributed'', les pages physiques sont distribuées sur tous les clusters suivant les bits de poids faible du VPN. Si le cluster K qui détecte le défaut de page est différent du cluster propriétaire Z, le noyau du cluster K envoie une PT_MISS_RPC au cluster Z, pour obtenir le PTE stocké dans la PT(P,Z). Les arguments sont le PID et le VPN de la page manquante. Quand il reçoit la réponse, il met à jour la PT(P,K). Si le cluster qui détecte le défaut de page est le cluster propriétaire Z, il sélectionne un cluster cible M à partir des bits de poids faible du VPN, et envoie au cluster M une RPC_PMEM_GET_SPP pour obtenir le PPN d’une page physique du cluster M. En réponse à cette RPC, le noyau du cluster M alloue une page physique et renvoie le PPN de celle-ci. Le noyau du cluster Z s’adresse au système de fichier, pour récupérer le contenu de la page manquante dans le cache du fichier .elf, et initialise la page physique dans M au moyen d’un remote_memcpy(). Finalement, il met à jour la PT (P,Z). === 4.4) HEAP === Ce vseg étant ''distributed'', les pages physiques sont distribuées sur tous les clusters suivant les bits de poids faible du VPN. Si le cluster K qui détecte le défaut de page est différent du cluster propriétaire Z, le noyau du cluster K envoie une PT_MISS_RPC au cluster Z, pour obtenir le PTE stocké dans la PT(P,Z). Les arguments sont le PID et le VPN de la page manquante. Quand il reçoit la réponse, il met à jour la PT(P,K). Si le cluster qui détecte le défaut de page est le cluster propriétaire Z, il sélectionne un cluster cible M à partir des bits de poids faible du VPN, et envoie au cluster M RPC_PMEM_GET_SPP pour obtenir le PPN d’une page physique du cluster M. En réponse à cette RPC, le noyau du cluster M alloue une page physique et renvoie le PPN de celle-ci. Quand le noyau du cluster Z obtient le PPN, il met à jour la PT (P,Z). === 4.5) REMOTE === Ce vseg étant ''localised'', les coordonnées du cluster de mapping M sont enregistrées dans le descripteur de vseg. Si le cluster K qui détecte le défaut de page est différent du cluster propriétaire Z, le noyau du cluster K envoie une PT_MISS_RPC au cluster Z, pour obtenir le PTE stocké dans la PT(P,Z). Les arguments sont le PID et le VPN de la page manquante. Quand il reçoit la réponse, il met à jour la PT(P,X). Si le cluster qui détecte le défaut de page est le cluster propriétaire Z, il envoie au cluster M une RPC_PMEM_GET_SPP pour obtenir le PPN d’une page physique du cluster M. En réponse à cette RPC, le noyau du cluster M alloue une page physique, et renvoie le PPN de celle-ci. Quand le noyau du cluster Z obtient le PPN, il met à jour la PT (P,Z). === 4.6) FILE === Ce vseg étant localised, les coordonnées du cluster de mapping M sont enregistrées dans le descripteur de vseg. Si le cluster qui détecte le défaut de page K est différent du cluster propriétaire Z, le noyau du cluster K envoie une PT_MISS_RPC au cluster Z, pour obtenir le PTE stocké dans la PT(P,Z). Les arguments sont le PID et le VPN de la page manquante. Quand il reçoit la réponse, il met à jour la PT(P,K). Si le cluster qui détecte le défaut de page est le cluster propriétaire Z, il envoie au cluster M qui contient le cache du fichier une GET_FILE_CACHE_RPC pour obtenir le PPN. Les arguments sont le PID, le descripteur du fichier, et l’index de la page dans le mapper. En réponse à cette RPC, le noyau du cluster M accède au mapper du vseg et retourne le PPN correspondant. Quand le noyau du cluster Z obtient le PPN, il met à jour la PT (P,Z). === 4.7) ANON === Ce vseg étant distributed, les pages physiques sont distribuées sur tous les clusters suivant les bits de poids faible du VPN. Le traitement d’un défaut de page est le même que pour un vseg HEAP. == __5) Invalidation d’une entrée de la table des pages__ == Dans un cluster Z, propriétaire d’un processus P, le noyau peut décider d’invalider une entrée d’une PT(P,Z). Cela peut se produire par exemple en cas de pénurie de mémoire dans le cluster Z, ou simplement en cas de munmap(). Sauf si le vseg concerné est de type STACK, l’entrée invalidée dans la PT(P,Z) doit aussi être invalidée dans les PT(P,K) des autre clusters. Pour ce faire, le noyau du cluster Z doit broadcaster une PT_INVAL_BCRPC vers tous les autres clusters actifs de P. == __6) Optimisation des RPC broadcast__ == Dans une RPC broadcast, tous les clusters destinataires doivent signaler la terminaison en incrémentant de façon atomique un compteur de réponses, qui est scruté par le cluster initiateur. Pour réduire le nombre de destinatiares, le descripteur du processus P du cluster propriétaire Z peut maintenir quatre variables XMIN, XMAX, YMIN, YMAX définissant le rectangle minimal recouvrant tous les clusters actifs de P à tout instant. Dans ce cas une RPC broadcast ne doit être envoyée qu’a (XMAX - XMIN + 1) * (YMAX - YMIN +1) destinataires. Ces variables sont mises à jour à chaque création de thread. == __7 ) Optimisation du traitement des défauts de page__ == Pour réduire le nombre de RPC causés par les défauts de page, le noyau d’un cluster X qui détecte un défaut de page peut utiliser un remote_read() dans la table PT(P,Z) du cluster de référence au lieu d’une PT_MISS_RPC. Ceci impose cependant d’utiliser un lock multi-lecteurs pour éviter un état incohérent dans le cas d’une transaction PT_INVAL_BC_RPC simultanée initiée par le cluster Z : Ce lock doit être pris systématiquement par le cluster propriétaire avant un PT_INVAL_BC_RPC, et par les autres clusters avant un remote_read(). Il garantit que le PT_INVAL_RPC ne sera lancé qu’après la fin de tous les remote_read() en cours. Il garantit qu’aucun nouveau remote_read() ne sera plus accepté avant la completion du PT_INVAL_RPC.