let time = ref 0;;
let update_frequency = 13;;
let update_quantum current_process _ (* pid *) process =
  if process <> current_process then
    match process.state with
    | Zombie i -> ()
    | _ -> process.quantum <- process.quantum / 2;;

let elect_process active_processes =
  let cmp p1 p2 = compare p1.quantum p2.quantum in
  (* List.sort est stable, ie. preserve l'ordre sur les clés de même valeur.
     List.rev assure un comportement FIFO  à quatum égale, ce qui évite
     les situations de famine. *)

  active_processes := List.sort cmp (List.rev !active_processes);
  match !active_processes with
  | [] -> raise Halt
  | h :: t -> h.quantum <- 0; h;;

(** system_state est inchangé *)
let rec run system_state =
  if !verbose then
    Printf.eprintf "pid=%d  code=%d starts running\n%!"
      system_state.current.pid
      system_state.current.pcode;
  let code = system_state.current.pcode in
  try process  system_state.codes.(codewith
    Trap -> syscall system_state
  | Signal -> signal system_state
  | Invalid_argument _ -> raise Invalid_code

and signal system_state =
  incr time;
  if !time mod update_frequency = 0 then
    Hashtbl.iter (update_quantum system_state.currentsystem_state.processes;
  let p = system_state.current in
  p.quantum <- p.quantum + 1;
  if p.quantum == max_quantum then
    begin
      if !verbose then
        Printf.eprintf "pid=%d  preempted\n%!" system_state.current.pid;
      schedule system_state
    end
  else
    run system_state

and schedule system_state =
  let p = elect_process system_state.active_processes in
  if !verbose then
    Printf.eprintf "resuming=%d\n%!" p.pid;
  system_state.current <- p;
  machine.reg <- p.preg;
  run system_state;;