My Project
Chargement...
Recherche...
Aucune correspondance
scheduler.c
Aller à la documentation de ce fichier.
1/*----------------------------------------------------------------------------*/
2/* Implantation des fonctions de base du scheduler. */
3/* */
4/* A voir : le paramètre "nouvelleConsole" n'a pas de sens s'il n'y a pas de */
5/* consoles virtuelles, à supprimer dans ce cas ? Ca rendra le code moins */
6/* lisible. */
7/* (C) Manu Chaput 2000-2025 */
8/*----------------------------------------------------------------------------*/
9#include <manux/config.h>
10#include <manux/scheduler.h>
11
12#define DEBUG_MANUX_SCHEDULER
13
14#include <manux/errno.h>
15#ifdef MANUX_CONSOLE
16# include <manux/console.h>
17#endif
18#include <manux/io.h>
19#include <manux/memoire.h> /* NULL, allouerPage */
20#if defined(MANUX_SYNCHRONISATION)
21# include <manux/atomique.h> /* Pour le verrou sur le scheduler */
22# if defined(MANUX_EXCLUSION_MUTUELLE)
24# endif
25# if defined(MANUX_CONDITION)
26# include <manux/condition.h>
27# endif
28#endif
29#include <manux/printk.h> /* printk() */
30#include <manux/debug.h> /* debug() paniqueNoyau() */
31#include <manux/interruptions.h> /* nbTopHorloge */
32#include <manux/i386.h> /* ltr */
33#include <manux/appelsysteme.h> /* console() */
34
35#ifdef MANUX_DUMMY_TASK
36# include <manux/dummy-task.h>
37#endif
38
40
41/*
42 * Une variable globale permettant d'identifier la tache du scheduler
43 */
45
48
49/*
50 * Ce qui suit n'est pas trés joli, mais ça ne devrait pas rester.
51 */
53
54booleen basculerTacheDemande = TRUE; // WARNING à virer ? C'est pour
55 // faire du "pas à pas"
56
64#if defined(MANUX_TACHES) && defined(MANUX_SYNCHRONISATION) && !defined(MANUX_REENTRANT)
65ExclusionMutuelle verrouGeneralDuNoyau;
66TacheID tacheDansLeNoyau = 0;
67#endif
68
77
82
87
92
98void ordonnanceur(void)
99{
100 Tache * tachePrecedente = tacheEnCours;
101
103
104 printk_debug(DBG_KERNEL_ORDON, "in (de tache %d)\n", tachePrecedente->numero);
105
106#ifdef MANUX_CONSOLES_VIRTUELLES
107 // Basculement entre les consoles virtuelles WARNING pourquoi ici
108 // !? A faire faire par dummyTask
111 basculerVersConsoleSuivante();
112 }
113#endif
114
115 // Attention, si la tâche en cours n'est pas préemptible
117 printk_debug(DBG_KERNEL_ORDON, "abandon (tache %d non preemptible)\n", tachePrecedente->numero);
118 return;
119 }
120
121 // (1) On s'occupe de la tâche en cours
122
123 // On cumule le temps d'écution dont elle vient de profiter
125
126 // Si on n'est pas là spontanément, on se considère en cours, mais
127 // c'est fini pour le moment !
130
134 }
135
136 // Dans les autres cas, la tâche est sensée être dans une file
137 // correspondant à son état
138
139 // (2) on cherche la tâche suivante
140 // On prend la première tâche prête, il y en a au moins une : la dummy
141 printk_debug(DBG_KERNEL_ORDON, "on cherche la suivante ...\n");
142 do {
144 } while (tacheEnCours->etat != Tache_Prete);
145 printk_debug(DBG_KERNEL_ORDON, "... ce sera la %d\n", tacheEnCours->numero);
146
148
149 /* On note la date pour pouvoir mesurer le temps dont elle va profiter */
151
152 if (tacheEnCours != tachePrecedente){
153 printk_debug(DBG_KERNEL_ORDON, "On passe a la tache %d de TSS 0x%x \n",
156
157 /* Une activation de plus pour elle */
159
160 printk_debug(DBG_KERNEL_ORDON, "out (vers tache %d)\n", tacheEnCours->numero);
162 }
163 printk_debug(DBG_KERNEL_ORDON, "back (vers tache %d)\n", tacheEnCours->numero);
164}
165
172{
174 tache,
175 (CelluleTache*)tache+sizeof(Tache));
176}
177
182{
183 Tache * t1; // Le fil d'exécution en cours, qui deviendra init
184#ifdef MANUX_DUMMY_TASK
185 Tache * t2; // Ce sera la "dummy" task
186#endif // MANUX_DUMMY_TASK
187
189
190 printk_debug(DBG_KERNEL_ORDON, "initialisation du scheduler ...\n");
191
192 // Initialisation de la liste (vide) des tâches en cours
194
195 // Initialisation de la liste (vide) de toutes les tâches
197
198 // Initialisation de la liste (vide) des tâches terminées
200
201 // Création d'une tâche pour le fil actuel (premier numéro)
202 t1 = tacheCreer(NULL);
203 if (t1 == NULL) {
204 paniqueNoyau("impossible de creer la premiere tache !\n");
205 }
206#ifdef MANUX_TACHE_CONSOLE
207 tacheSetConsole(t1, consoleNoyau());
208#endif
209 /* Cas particulier de la première tâche : */
210 /* . on la déclare comme en cours. */
211 tacheEnCours = t1;
212 t1->etat = Tache_En_Cours;
213
214 /* . on charge son task register ; */
216
217 // Avant de permettre à une deuxième tâche d'entrer en concurrence,
218 // il faut s'assurer qu'on a la main sur le noyau.
219#if !defined(MANUX_REENTRANT) && defined(MANUX_EXCLUSION_MUTUELLE)
220 printk_debug(DBG_KERNEL_ORDON, "on verouille le verrou\n");
221
222 exclusionMutuelleEntrer(&verrouGeneralDuNoyau);
223 assert(tacheDansLeNoyau == 0);
224 tacheDansLeNoyau = tacheEnCours->numero;
225#endif
226
227#ifdef MANUX_DUMMY_TASK
228 printk_debug(DBG_KERNEL_ORDON, "creons la dummy\n");
229
230 // Initialisation de la tache "aDummyKernelTask" (numéro 2)
232
233 if (t2 == NULL) {
234 paniqueNoyau("impossible de creer la seconde tache !\n");
235 }
236
237 printk_debug(DBG_KERNEL_ORDON, "la dummy est la ...\n");
238
239#define MANUX_DUMMY_TASK_CONSOLE
240#ifdef MANUX_TACHE_CONSOLE
241#ifdef MANUX_DUMMY_TASK_CONSOLE
242 tacheSetConsole(t2, creerConsoleVirtuelle());
243#else
244 tacheSetConsole(t2, consoleNoyau());
245#endif
246#endif
247
248 printk_debug(DBG_KERNEL_ORDON, "on ajoute la t2 dans l'ordo\n");
249
250 // A partir de maintenant, nous ne sommes plus seuls
252
253#endif // MANUX_DUMMY_TASK
254
255 printk_debug(DBG_KERNEL_ORDON, "scheduler is done\n");
256}
257
258#ifdef MANUX_APPELS_SYSTEME
262int sys_identifiantTache(void)
263{
264 return (int)tacheEnCours->numero;
265}
266
267#ifdef MANUX_TACHE_CONSOLE
274{
275 if (schedulerEnCours) {
276 return (uint32_t)tacheScheduler->console;
277 } else if (tacheEnCours) {
278 return (uint32_t)tacheEnCours->console;
279 } else {
280 return (uint32_t) NULL;
281 }
282}
283#endif // MANUX_TACHE_CONSOLE
284
289{
290 (void) as;
291
293
294 ordonnanceur();
295
296 return 0;
297}
298
307TacheID sys_creerTache(ParametreAS as, CorpsTache corpsTache, booleen shareConsole)
308{
309 Tache * tache;
310#ifdef MANUX_TACHE_CONSOLE
311 Console * console;
312#endif
313
314 (void) as;
315
317
318 printk_debug(DBG_KERNEL_ORDON, "corpsTache = 0x%x, share=%d\n", corpsTache, shareConsole);
319
320 // Création de la tâche
321 tache = tacheCreer(corpsTache);
322 if (tache == NULL) {
323 return -ENOENT;
324 }
325
326#ifdef MANUX_TACHE_CONSOLE
327 // Affectation de la console
328# ifdef MANUX_CONSOLES_VIRTUELLES // WARNING : MANUX_TACHE_CONSOLE plutôt ?
329 if (shareConsole) {
330 console = tacheEnCours->console;
331 } else {
332 console = creerConsoleVirtuelle();
333 }
334# else
335 console = consoleNoyau();
336# endif // MANUX_CONSOLES_VIRTUELLES
337 tacheSetConsole(tache, console);
338#endif
339
341
342 return tache->numero;
343}
344#endif // MANUX_APPELS_SYSTEME
345
350{
351 Tache * tache;
352
354
355 printk_debug(DBG_KERNEL_ORDON, "corpsTache = 0x%x\n", corpsTache);
356
357 // Création de la tâche
358 tache = tacheCreer(corpsTache);
359 if (tache == NULL) {
360 return -ENOENT;
361 }
362
363#ifdef MANUX_TACHE_CONSOLE
364 // Affectation de la console
365 tacheSetConsole(tache, consoleNoyau());
366#endif
367
369
370 return tache->numero;
371}
372
373
374
375
376
377
378
379
380
381
382
383#ifdef SUPPRIME
384/*
385 * Insertion d'une nouvelle tâche dans l'ordonnanceur. La valeur
386 * retournée est l'id de la tâche ou un code d'erreur.
387 * WARNING a virer dès que la précédente est OK
388 */
389TacheID ordonnancerTache(CorpsTache corpsTache, console * cons)
390{
391 Tache * tache;
392
393#ifdef MANUX_TACHE_CONSOLE
394 Console * cons;
395# ifdef MANUX_CONSOLES_VIRTUELLES
396 if (nouvelleConsole) {
397 cons = creerConsoleVirtuelle();
398 } else {
399 if (tacheEnCours != NULL) {
400 cons = tacheEnCours->console;
401 } else { // Pour la première a priori
402 cons = NULL;//consoleNoyau();
403 }
404 }
405# endif // MANUX_CONSOLES_VIRTUELLES
406#endif // MANUX_TACHE_CONSOLE
407
408 /* Création de la tache */
409#ifdef MANUX_TACHE_CONSOLE
410 tache = creerTache(corpsTache, cons);
411#else
412 tache = creerTache(corpsTache);
413#endif
414 if (tache == NULL) {
415 return -ENOMEM;
416 }
417
418 /* On insère la nouvelle tâche à la fin de la liste */
419 if (corpsTache) {
421 tache,
422 (CelluleTache*)tache+sizeof(Tache));
423 printk_debug(DBG_KERNEL_TACHE, "Tache inseree\n");
424
425 } else {
426 //printk("99999\n");
427 /* Cas particulier de la première tâche : */
428 /* . on charge son task register ; */
429 ltr(tache->indiceTSSDescriptor);
430 /* . et on la déclare comme en cours. */
431 tacheEnCours = tache;
432 }
433 //printk("00000\n");
434
435 return tache->numero;
436}
437#endif
Définition des opérations de synchronisation de ManuX.
uint32_t Atomique
Definition atomique.h:19
Définition des exlusions mutuelles.
void exclusionMutuelleEntrer(ExclusionMutuelle *em)
Entrée en exclusion mutuelle.
Temps nbTopHorloge
Definition horloge.c:22
Définition des fonctions de base d'accés à la console.
Console * consoleNoyau(void)
Obtention d'un pointeur sur la console par défaut.
Definition console.c:808
#define ENOENT
Definition errno.h:12
#define ENOMEM
Definition errno.h:13
#define ltr(tr)
Definition i386.h:23
typedef void(Handler(void))
Définition des fonctions de base d'entrée-sortie du noyau.
#define NULL
Definition stddef.h:10
unsigned long uint32_t
Definition types.h:20
uint16_t TacheID
Definition types.h:61
int booleen
Definition types.h:32
#define TRUE
Definition types.h:36
#define FALSE
Definition types.h:40
int32_t Temps
Definition types.h:71
void insererCelluleTache(ListeTache *listeTaches, struct _Tache *tache, CelluleTache *celluleTache)
Definition listetaches.c:17
struct _Tache * extraireTache(ListeTache *listeTaches)
Definition listetaches.c:46
void initialiserListeTache(ListeTache *listeTache)
Definition listetaches.c:11
#define DBG_KERNEL_TACHE
Definition debug.h:26
#define assert(cond)
Definition debug.h:126
#define paniqueNoyau(fmt, args...)
Definition debug.h:107
#define DBG_KERNEL_ORDON
Definition debug.h:25
#define printk_debug(lvl, fmt, args...)
Definition debug.h:86
Définition d'une tâche minimaliste qui est là pour afficher quelques éléments à la demande de l’utili...
void aDummyKernelTask(void)
Le corps d'une tâche à exécuter lorsqu'on n'a que ça à faire, ...
Definition dummy-task.c:396
ListeTache listeTachesTerminees
: La liste des tâches achevées.
Definition scheduler.c:86
ListeTache listeToutesLesTaches
: La liste de toutes les tâches existant sur le système.
Definition scheduler.c:81
void initialiserScheduler(void)
Initialisation de l'ordonnanceur.
Definition scheduler.c:181
booleen basculerTacheDemande
Definition scheduler.c:54
TacheID numeroProchaineTache
:Le numero de la prochaine tache (WARNING : et si on cycle ?)
Definition tache.c:34
Atomique schedulerEnCours
Definition scheduler.c:47
ListeTache listeTachesPretes
Identifiant de la tâche actuellement en cours d'exécution dans le noyau (0 si aucune)
Definition scheduler.c:76
Tache * tacheEnCours
: La tâche en cours
Definition scheduler.c:91
booleen basculeConsoleDemandee
Definition scheduler.c:52
Temps dateDernierOrdonnancement
Definition scheduler.c:46
void ordonnanceur(void)
Le coeur de l'ordonnanceur.
Definition scheduler.c:98
TacheID ordonnanceurCreerTacheNoyau(CorpsTache corpsTache)
Création et ordonnancement d'une tâche noyau.
Definition scheduler.c:349
Tache * tacheScheduler
Definition scheduler.c:44
void ordonnanceurAddTache(Tache *tache)
Ajout d'une tâche dans l'ordonnanceur.
Definition scheduler.c:171
int sys_identifiantTache(void)
uint32_t AS_console(void)
TacheID sys_creerTache(ParametreAS as, CorpsTache corpsTache, booleen shareConsole)
int sys_basculerTache(ParametreAS as)
Structure d'une console.
Definition console.h:37
Définition des exclusions mutuelles.
: Définition du type décrivant une tache.
Definition tache.h:83
EtatTache etat
Definition tache.h:89
uint32_t nbActivations
Definition tache.h:104
Temps tempsExecution
Definition tache.h:105
uint16_t indiceTSSDescriptor
Definition tache.h:86
TacheID numero
Definition tache.h:88
uint8_t nonPreemptible
Definition tache.h:94
@ Tache_En_Cours
Definition tache.h:29
@ Tache_Prete
Definition tache.h:30
void basculerVersTache(Tache *tache)
Definition tache.c:38
Tache * tacheCreer(CorpsTache corpsTache)
Création d'une nouvelle tâche.
Definition tache.c:113