Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _XOPEN_SOURCE 700
- #include <setjmp.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdlib.h>
- #include <signal.h>
- //#define USE_ALARM
- int sauvegarderProcessus(int idx);
- void commut();
- /****************************************/
- /* Pour la commutation avec les signaux */
- /* 2eme partie du TP */
- /****************************************/
- #ifdef USE_ALARM
- #define MASK_ALARM() sigprocmask(SIG_BLOCK, &mask_alarm, 0)
- #define UNMASK_ALARM() sigprocmask(SIG_UNBLOCK, &mask_alarm, 0)
- #define delay 400000
- sigset_t mask_alarm;
- void handler_clock(int n) {
- commut();
- }
- void initSig() {
- struct sigaction sa;
- sigemptyset(&mask_alarm);
- sigaddset(&mask_alarm, SIGALRM);
- sigaction(SIGALRM, 0, &sa);
- sa.sa_handler = handler_clock;
- sa.sa_flags |= SA_RESTART;
- sigaction(SIGALRM, &sa, 0);
- ualarm(delay, delay);
- }
- #endif
- /*************************/
- /* Gestion des processus */
- /*************************/
- // On utilisera cette variable "globale" pour retenir l'adresse du haut de la pile
- char *top_stack;
- // la dernière entrée du tableau (NPROC) est utilisée pour sauvegarder le main
- #define SNONE 0
- #define SSLEEP 1
- #define SRUN 2
- #define MAX_STACK_SIZE 2048
- #define NPROC 10
- // Cette structure contient tous ce qui necessaire a la gestion d'un processus
- struct proc_s {
- int flag;
- jmp_buf buf;
- char stack[MAX_STACK_SIZE];
- int size;
- } ;
- // La derniere entree du tableau (NPROC) est utilisee pour sauvegarder le main
- struct proc_s tproc[NPROC+1];
- // Identifiant du processus courant
- int cur = -1;
- int election(int old) {
- // Cette fonction implemente un simple round robin :
- // => les taches accedent au CPU les une après les autres sans se doubler
- // => on cherche (circulairement) dans le tableau le prochain processus pret (SRUN)
- // Valeur de retour :
- // - index du processus elu qui doit etre a l'etat SRUN
- // - NPROC (id du main) s'il n'y a plus de processus
- //
- // Attention : cette fonction de modifie pas la variable "cur".
- // Elle ne fait que retourner l'index d'un processus.
- for (int i = (old + 1) % NPROC; i != old; i = (i + 1) % NPROC)
- if (tproc[i].flag == SRUN)
- return i;
- return NPROC;
- }
- int new_proc(int (*nomFonction)(int), int argFonction) {
- // #####################################
- // ############ A COMPLETER ############
- // #####################################
- // Au demarrage :
- // 1) chercher une entree libre dans la table proc
- // 2) initialiser la structure
- // 3) sauvegarder le processus
- // 4) retourner 0
- // Apres le retour :
- // 1) demarrer la fonction
- // Apres la fin de la foncton (fin du processus)
- // 2) liberer l'entree (etat et desallocation pile)
- // 3) forcer le commut pour laisser la place a un autre processus.
- int i;
- for (i = 0; i < NPROC; i++) {
- if (tproc[i].flag == SNONE)
- break;
- }
- // pas d'entree libre dans la table
- if (i >= NPROC) {
- return -1;
- }
- tproc[i].flag = SRUN; // FIXME
- if (sauvegarderProcessus(i) != 0) {
- printf("launching %d\n", i);
- nomFonction(argFonction);
- tproc[i].flag = SNONE;
- commut();
- }
- return 0;
- }
- /***************************************/
- /* Fonctions permettant la commutation */
- /***************************************/
- int sauvegarderProcessus(int idx) {
- printf("sauvegarderProcessus(%d)\n", idx);
- // Lors de l'appel a la fonction :
- // 1) sauvegarder la pile
- // 2) sauvegarder de la taille de pile. Pourquoi la variable locale ne suffit pas ?
- // 3) sauvegarder les registres
- // 4) retourner 0
- // En cas de restauration :
- // 1) restaurer la pile
- // 2) UNMASK_ALARM() dans la deuxieme partie (avec les signaux)
- // 3) retourne la valeur fournie par le longjmp
- char bs;
- register int res;
- tproc[idx].size = top_stack - &bs;
- memcpy(tproc[idx].stack, top_stack - tproc[idx].size, tproc[idx].size);
- if ((res = setjmp(tproc[idx].buf)) == 0)
- return 0;
- else {
- #ifdef USE_ALARM
- UNMASK_ALARM();
- #endif
- return res;
- }
- }
- int restaurerProcessus(int idx) {
- printf("restaurerProcessus(%d)\n", idx);
- // 1) enregistre l'index du nouveau processus (idx) comme processus courant
- // 2) lance la restauration des pointeurs
- // ?) la restauration de la pile peut elle avoir lieu dans cette fonction ?
- cur = idx;
- // force inlined memcpy to restore stack
- // memcpy(top_stack - tproc[idx].size, tproc[idx].stack, tproc[idx].size);
- for (register int i = 0; i < tproc[idx].size; i++)
- ((char*)(top_stack - tproc[idx].size))[i] = ((char*)(tproc[idx].stack))[i];
- longjmp(tproc[idx].buf, 1);
- }
- void commut() {
- printf("commut()\n");
- #ifdef USE_ALARM
- MASK_ALARM();
- #endif
- if(sauvegarderProcessus(cur) == 0)
- restaurerProcessus(election(cur));
- }
- int f(int p) {
- int n = 0;
- int j;
- for(j=0; j<15; j++) { // 20
- printf("f(%d) -> %d\n", p, n++);
- usleep(500000);
- #ifndef USE_ALARM
- commut();
- #endif
- }
- return 0;
- }
- int g(int p) {
- int n = 0;
- int j;
- for(j=0; j<12; j++) {// 50
- printf("g(%d) -> %d\n", p, n++);
- usleep(300000);
- #ifndef USE_ALARM
- if(j%2 == 0) commut();
- #endif
- }
- return 0;
- }
- int main() {
- char bs;
- // sauvegarder l'adresse du sommet de la pile dans la variable globale "top_stack"
- top_stack = &bs;
- new_proc(g, 0);
- new_proc(f, 4);
- // Comme explique plus haut le main a pour id NPROC (derniere case du
- // tableau)
- cur = NPROC;
- #ifdef USE_ALARM
- initSig();
- #endif
- commut();
- printf("exit!!!\n");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement