open Instr open Machine type process_state = Ready | Waitpid of int | Zombie of int type process = { mutable pcode : int; (* pointeur de code *) mutable preg : int array; (* sauvegarde des registres *) mutable quantum : int; (* quantum restant *) pid : int; (* numéro du processus *) mutable ppid : int; (* numéro du processus père *) mutable state : process_state (* état du processus *) } type state = { processes : (int, process) Hashtbl.t; (* table des processus *) active_processes : process list ref; (* liste des processus prêts *) mutable current : process; (* processus éxécuté *) codes : instr array array; (* tout le code *) mutable last_pid : int; (* dernier PID utilisé *) } let rec new_pid system_state = system_state.last_pid <- system_state.last_pid + 1; if Hashtbl.mem system_state.processes system_state.last_pid then new_pid system_state else system_state.last_pid;; let init_state process codes = let pids = Hashtbl.create 13 in Hashtbl.add pids process.pid process; { processes = pids; active_processes = ref [ process ]; current = process; codes = codes; last_pid = process.pid; };; let max_quantum = 4;; exception Not_implemented of int;; let system_traps = let not_implemented i state = raise (Not_implemented i) in Array.init 10 not_implemented;; let syscall system_state = if !verbose then Printf.eprintf "pid=%d: Syscall %d (a0=%d, a1=%d): %!" system_state.current.pid machine.reg.(v0) machine.reg.(a0) machine.reg.(a1); system_traps.(machine.reg.(v0)) system_state;; exception Halt;; exception Invalid_code;; let rec run system_state = if !verbose then Printf.eprintf "pid=%d starts running\n%!" system_state.current.pid; let code = system_state.current.pcode in try process system_state.codes.(code) with Trap -> syscall system_state | Signal -> signal system_state | Invalid_argument s -> raise Invalid_code and signal system_state = run system_state and schedule system_state = let p = match !(system_state.active_processes) with | [] -> raise Halt | h :: t -> h in if !verbose then Printf.eprintf "resuming=%d\n%!" p.pid; system_state.current <- p; machine.reg <- p.preg; run system_state;; (** exit avec en argument le registre a0 *) let sys_Exit = 0;; let exit system_state = if !verbose then Printf.eprintf "Exit\n%!"; let p = system_state.current in system_state.active_processes := List.filter ((<>) p) !(system_state.active_processes); (* system_state.current.state <- Zombie p.preg.(a0); *) Hashtbl.remove system_state.processes system_state.current.pid; schedule system_state in system_traps.(sys_Exit) <- exit;; (** écrit la valeur du registre a0 sur le sortie standard et place le nombre d'entiers écrits (1) dans v0 *) let sys_Write = 1;; let rec write system_state = let p = system_state.current in if !verbose then Printf.eprintf "Write (%d)\n%!" p.preg.(a0); let v = p.preg.(a0) in Printf.printf "%d\n%!" v; p.preg.(v0) <- 1; run system_state in system_traps.(sys_Write) <- write;; (** crée un nouveau processus, place la valeur de retour dans v0 *) let sys_Fork = 2;; (** récupère le pid du processus et le place dans v0 *) let sys_Getpid = 3;; (** récupère le pid du père et le place dans v0 *) let sys_Getppid = 4;; (** demande l'exécution d'un nouveau code dont le numéro est dans a0 la valeur de retour est placée dans v0 *) let sys_Exec = 5;; (** attend la fin d'un processus particulier dont le numéro est placé dans a0. La valeur de retour (0 ou -1) est placée dans v0 et celle (exit) du processus attendu dans v1 *) let sys_Waitpid = 6;;