Interior Decor et son Micro-Noyau
par Jean Bellec
Une des originalités des systèmes GCOS7
est l'inclusion dans l'architecture du code d'instructions de fonctions habituellement
incluses dans le système d'exploitation proprement dit: les fonctions de gestion de
processus (dispatching), de gestion et de protection de l'espace d'adressage
(segmentation) et de synchronisation des threads
visibles du programmeur entre elles et avec les opérations d'entrées-sorties.
Ces fonctions étaient bien identifiées par les théoriciens des systèmes
d'exploitation dans la seconde moitié des années 1960, mais un accord sur leur
systématisation et leur "architecturisation"
semblait éloigné. Multics avait introduit une gestion de l'espace
d'adressage commune aux processus (vus comme le travail du programmeur individuel) et au
système de fichiers. IBM avait réalisé une gestion uniforme des entrées-sorties mais
avait laissé la gestion des espaces d'adresses aux initiatives des créateurs de
systèmes d'exploitation. Les mini-ordinateurs se caractérisaient davantage par la
possibilité de réaliser des systèmes d'exploitation différents que par la continuité
et l'efficacité de ceux-ci.
Ce qu'était l'APL OS en 1968 et qui deviendra GCOS64 à l'annonce et GCOS7 plus tard, c'était un système d'exploitation universel capable d'assurer les fonctions de traitements par lots (batch processing) que les clients héritaient de leurs années 1960, de permettre une utilisation efficace de ressources matériel encore très coûteuses, et de permettre la réalisation de systèmes interactifs transactionnels qui émergeaient à l'époque sur des systèmes beaucoup plus onéreux mais dont nous prévoyions la généralisation dans les années 1970.
Une autre caractéristique un peu contingente, la technologie, influença la décision de développer hors du système d'exploitation ces fonctions de micro-kernel. Les mémoires centrales (tout d'abord envisagées à tores magnétiques puis réalisées en DRAM) étaient relativement lentes par rapport à la technologie bipolaire utilisées pour les circuits et les mémoires mortes dédiées à l'interprétation du code d'instructions. De plus, la vitesse d'exécution du logiciel était un peu pénalisée par la rigueur du système de protection des accès à la mémoire principale. C'est ainsi que l'implémentation en PROM du code du dispatcher de tâches permettait de diviser par trois l'overhead d'une fonction sollicitée en permanence dans un système de gestion transactionnelle.
Le système d'adressage de la NPL était segmenté, c'est à
dire que les adresses indiquées dans les instructions comprenaient un numéro de segment
et un déplacement à l'intérieur du segment. La table de segments était comme dans
Multics spécifique de chaque thread. Cependant, sur NPL, les segments sont classés en
plusieurs catégories suivant leurs caractéristiques de partage: les segments communs à
tout le système (type 0), les segments privés de la thread (type 3) les segments communs aux threads partageant un même espace d'adresse (type
2) et les segments alloués dynamiquement (type 1).
Deux catégories de taille de segments furent retenues : celle de 64 K octets et
celle de 4 M octets. Chaque catégorie était disponible dans les différents types de
segments.
Le dispatcher
de threads connaît pour chaque thread son état (y compris les registres de
travail et l'espace d'adresse. Il effectue la commutation de threads sur des critères de priorité et de
disponibilité. Ce dispatcher est bien entendu multi-processeurs.
Le nombre de threads actives dans le
système était limité à 256 groupes (process
groups) de 256 threads (appelées process dans le jargon NPL). Ce nombre pouvait
s'avérer insuffisant dans des systèmes transactionnels où un multiplexage par logiciel
s'avérait nécessaire entre une thread active
et une transaction multi-échanges.
Le mécanisme de synchronisation de threads fait lui aussi partie de l'architecture et
est basé sur des sémaphores (introduits en
1965 par Dijkstra) utilisés par des primitives de signalisation (V-op) et de mise conditionnelle en attente (P-op). En plus du compteur associé à ces
opérations, les sémaphores peuvent comporter une liste de messages. Un mécanisme
supplémentaire de test de l'état du sémaphore permet la réalisation de wait multiples.
Le mécanisme de sémaphore est non seulement utilisé pour la synchronisation de threads du logiciel s'exécutant dans la mémoire
du (ou des) processeurs, mais également pour synchroniser ces threads avec les entrées-sorties (plus exactement
avec les pseudo-threads exécutant des
programmes canaux).
Une autre fonction du micro-kernel est la gestion du système de protection inter-procédural au cours
de l'exécution d'une thread. Les segments
correspondant au code d'une procédure sont associées à un des quatre anneaux de
protection (rings) du système. Une thread est exécutée dans l'un de ces anneaux
selon le type associé au segment procédure. Une procédure peut appeler une procédure
de rang plus privilégié mais ne peut accéder à ses données tandis qu'une procédure
privilégiée accède aux données de son appelant (mais à l'intérieur de l'espace
d'adresse de la thread). Les paramètres sont
passés par l'intermédiaire d'une pile (avec une pile par anneau). Le micro-kernel reporte les violations de
protections à des procédures privilégiées.
De plus, seules des procédures de ring
0 peuvent exécuter des instructions privilégiées touchant au matériel
(entrées-sorties, manipulation des adresses absolues).
Ce mécanisme est complètement applicable à tous les éléments du logiciel, y compris les émulateurs de modes non natifs.
Le micro-kernel se présente sous la forme de code non modifiable dynamiquement (initialement en PROM), de données de travail en registres ou en mémoire cachée sous BAR et de tables accessibles au logiciel uniquement en mode privilégié. Il est écrit en une version simplifiée des instructions de base de l'interior decor (by-passant en particulier les contrôles d'adressage et d'intégrité). Sur le DPS-7 Leo, les micro-programmes de l'unité centrale seront exécutés depuis une mémoire de contrôle en SRAM et chargés depuis un fichier spécial sur le disque système. Le code du micro-kernel a subi quelques modifications sur les différentes architectures de processeurs, mais l'interface avec le système d'exploitation est resté strictement compatible.
Au total, cette innovation de GCOS7 a
recueilli la désapprobation des promoteurs (italiens) de petits systèmes qui ont argué
du coût des mécanismes d'adressage (mémoire virtuelle et segmentation) pour obtenir le
droit de définir une architecture indépendante (vaguement compatible au niveau source
assembleur) et donc la réalisation d'une ligne de produits propre. Elle a recueilli le
scepticisme des défenseurs (Phoeniciens) de l'architecture des systèmes GE-600 qui
estimaient que la définition d'un micro-kernel
(et son figeage dans le hardware) limiterait les ambitions et les innovations chez les
utilisateurs avancés.
Elle a cependant servi d'argumentaire commercial en attendant que le logiciel soit
complètement réalisé: les promoteurs vendaient les sémaphores en 1974-1975, mais
ensuite ils ont cessé de les mentionner, surtout que cela pouvait concurrencer des lignes
qui n'avaient pas la même rigueur architecturale.
Au bout du compte, cette architecture s'est avérée solide, adaptée à la plupart des besoins des logiciels qui contrairement à beaucoup de systèmes ont su évoluer sans révolution coûteuse pendant plusieurs décennies.