= Architecture = = Design = == [Scheduler] == Si e' scelto di rendere il piu' modulare possibile lo scheduler, distinguendo la specifica azione di scheduling, intesa come il calcolo del nuovo processo da mandare in esecuzione e del relativo tempo da assegnargli, dalla piu' generica azione di dispatching, intendendo il complesso delle attivita' che sono invece proprie della struttura di Phase 2. Si sono quindi definiti i confini della capsula che lo avvolge, oscurando i dettagli implementativi al suo interno e al contempo palesare l'interfaccia verso l'esterno, al fine di poter favorirne l'adattabilita'. Non sarebbe una cattiva idea confinare lo scheduler in un modulo tutto suo: fatto [TODO]: descrizione accurata delle interfacce = Hacks = == [CPU Timing] == L'accounting dei tempi di CPU utilizzati dai vari processi viene realizzato tenendone traccia in un campo del processo. L'uso della CPU e' da distinguersi in due tipi: uso diretto e indiretto. Ci si riferisce al primo nel caso il processo stia utilizzando effettivamente il processore con il suo codice, mentre si parla di uso indiretto quando il codice e' in realta' esterno al processo stesso [syscall e interrupts handling (e anche lo stesso tempo richiesto allo scheduling ?)]. Chi si preoccupa di tenere traccia dell'uso diretto e' lo stesso dispatcher, che fara' un timestamp prima del caricamento del pcb, e, una volta reinvocato per la successiva ri-schedulazione, calcolera' la differenza. Nel caso di uso indiretto, il compito e' ripartito fra i gestori delle eccezioni: essi addebiteranno il proprio tempo di esecuzione al processo chiamante (procCurr) nel caso di syscall, trap e breakpoint, oppure al processo realmente interessato nel caso di interrupt; in questo ultimo scenario l'identificazione dell'interessato avviene al momento di verhogen-are un semaforo. Chi si fa carico del calcolo di accounting e' il dispatcher, il quale mette a diposizione nella sua interfaccia due funzioni atte a questo scopo: `dsp_play()` e `dsp_pause()` che segnalano ripettivamente l'inizio e la fine di un periodo di utilizzo della CPU. {{{ Dispatcher Process1 Process2 Syscall Interrupt ___ . . . . || NULL |> 1 | . . . . . ._ . . . schedulazione di P1 . | . . . . | . . . . | . . . . |. . . . . . . . . . ._ . richiesta syscall7 (WAIT4I/O) . . . | . . . . | . . . . | . || 1 _ . . . . . . . . . . . . . . . . .| . passeren sul semaforo del device | . . . . schedule() |. . . . . . . . . . . . _ . . LDST(P2) |> 2 . . | . . . . | . . . . | . . || 2 |> 1 . . | . . . . . . . . . . _ interrupt device . . . . | . . . . | verhogen || 1 |> 2 . . _ . . . . . . . . . . | LDST(P2) . . | . . . . | . . . . | . . . . . . . . . . _ interrupt timer || 2 |> NULL . . . . . . . . . . . . . . . . . . . . . . . .| dispatch() _|_ . . . . }}} === Butta'ti qui === * Interval timer: doppio uso sia per preemption che per la chiamata di sistema dello pseudo clock. * come distinguere? il sistema di crediti risolve questo problema e al contempo garantisce fairness nella lunghezza dei quanti; i crediti fanno parte della interfaccia del dispatcher e lo scheduler ne e' informato. * dsp_play/pause per l'accounting dei tempi di CPU * modularita' dello scheduler/dispatcher, variabili interne protette dall'uso diretto dall'esterno * descrizione della specifica implementazione dei semafori, che modificano l'intero solo in caso di necessita' * passup ottimizzato: la discesa fra i gestori avviene in modo canonico, la risalita e' immediata. l'aggiornamento del pc per permettere il corretto ritorno viene eseguito all'interno dello stato * modularizzazione dello scheduler, completamente indipendente dal dispatcher e parametrizzato in modo tale da permettere cambi di politica e/o meccanismi durante la compilazione * Phase 2 non smanetta robe di Phase 1 * descrivere le invarianti che assunte all'inizio dell'esecuzione di dispatcher: procCurr == NULL -> nessuno in esecuzione '-> crediti == 0 procCurr non e' in ready queue * interrupt handling: ACK anche per errori ragionevoli * ...