Semafori
|
Esegue counter--
e nel caso aggiunge a waiting il processo. |
|
Rilascia un gettone. Esegue counter++
ed estrae dalla lista dei waiting. |
|
Restituisce il primo semaforo libero inserendovi $gettoni gettoni. 0xFFFFFFFF se qualcosa è andato storto. |
|
Verifica la validità di un semaforo. |
Mutex: $gettone = 1
Sync: $gettone = 0
Nota: tutti gli errori sono 0xFFFFFFFF
Attenzione: Tutti gli id sono natl
Processi
|
Restituisce un des_proc* a partire dall'id. |
|
Porta all'interruzione del processo. Non effettua return ed è utile nei casi di errore. |
p->contesto[I_RAX] = $value;
|
Ritorno della funzione di value. |
|
Rimuove la testa dalla lista (max prio) |
|
Inserisce esecuzione in testa a pronti |
Preemption
des_proc* work = rimozione_lista($lista);
inspronti();
inserimento_lista(pronti, work);
schedulatore();
|
Alla fine ci sarà sicuramente uno tra il processo in esecuzione e work attivo
Utilità
flog(MODE, "msg"); |
Mostra a schermo il messaggio msg |
LOG_DEBUG: costante per debug
LOG_INFO: costante per informazioni
LOG_WARN: costante per avviso
Tab iter
tab_iter it(tab, begin, dim);
|
Utile per scorrere le entrate dell'albero degli indirizzi |
|
Per scorrere in profondità, vedi vm.h |
|
restituisce true
se è una foglia |
tab_entry& e = it.get_e();
|
Restituisce un riferimento al descrittore corrente |
|
Restituisce l'indirizzo virtuale asdsociato alla entry in it |
paddr p = extr_IND_FISICO($e);
|
Restituisce l'indirizzo fisico associato alla entry |
set_IND_FISICO($e, $paddr);
|
Setta l'indirizzo fisico corrispondente alla entry $e |
|
Alloca un frame libero destinato a contenere una tabella di traduzione restituendo l'indirizzo del frame |
copy_des(paddr src, paddr dst, natl i, natl n);
|
Copia 'n' descrittori da src in dst a partire dall'indice i |
set_des(paddr dst, natl i, natl n, tab_entry e);
|
Setta il valore 'e' su 'n' descrittori a partire dall'indice 'i' |
Utilizzo tab_iter
for (tab_iter it(p->cr3, ini_utn_p, dim); it; it.next()) {
if (!it.is_leaf())
continue;
tab_entry& e = it.get_e();
vaddr v = it.get_v();
paddr p = extr_IND_FISICO(e); // or set
/* e &= ~BIT_RW;
abbiamo modificato RW: invalidamo
le entrate nel TLB
invalida_entrata_TLB(v);*/
}
|
Memoria Virtuale
|
Restituisce il paddr relativo a un vaddr |
|
Vedere le note |
|
restituisce l'indirizzo del frame caricato |
|
Libera il frame in cui è contenuto $paddr |
|
base di un frame |
natl indice = p / DIM_PAGINA;
|
Indice di frame |
invalida_entrata_TLB($vaddr);
|
Invalida l'entrata del TLB del processo in esecuzione |
cr0 |
Abilita la paginazione |
cr1 |
Non implementato |
cr2 |
Indirizzo che ha causato page fault |
cr3 |
paddr albero di traduzione del processo |
vdf[]; |
array dei descrittori di frame |
memcpy( (void) dst, (void) src, int nbytes);
|
copia da dst a src nbytes |
map(p->cr3, vaddr begin, vaddr end, FLAGS, putpaddr);
|
Mappa gli indirizzi fisici passati da putpaddr nell'intervallo [begin, end) restituendo il primo che non è riuscito a tradurre |
unmap(p->cr3, vaddr begin, vaddr end, getpaddr);
|
Rimuove le traduzioni nell'intervallo [begin, end) da p->cr3 |
- tipo: ini, fin
- livello: utn, sis
- accesso: p, c
Livello tabelle: 4, 3, 2, 1
FLAGS: bit_RW, bit_US
|
|
Funtore
class Funtore{
public:
paddr pa[DIM_PAGINA];
natl i;
// init di i a 0
Funtore() : i(0) {}
// per la map
paddr operator()(vaddr v){
return pa[i++];
}
// per la unmap
void operator()(vaddr, paddr p, int){
pa[i++] = p;
// oppure trasforma(v);
}
}; // attento a ; !!!
|
Elimina da lista
des_proc elimina_da_lista(des_proc& testa, des_proc* p){
des_proc *prec = &testa, scorri = testa;
while (scorri && scorri != p) {
prec = &scorri->puntatore;
scorri = scorri->puntatore;
}
if (scorri)
*prec = scorri->puntatore;
return scorri;
}
|
Rimuove dalla lista puntata da $testa
il des_proc* p
.
I/O
access(vaddr b, natq dim, bool w, bool s);
|
Controlla il cavallo di Troia per w(ritable) e s(hared) |
|
Inserisce il valore al registro reg in z |
|
Inserisce nel registro reg il valore value |
des_x y = new(align_val_t{dim}) des_x;
|
Allinea il nuovo valore in memoria |
natl spostabili = DIM_PAGINA - (paddr & 0xFFF);
|
Calcola il numero di byte spostabili per esaurire il frame |
x: b(yte), l(ong), q(uad)
Approccio I/O
- Quando viene chiamata l'interruzione?
- Chi prepara il descrittore?
- Cosa deve fare l'interruzione?
- Come rispondiamo all'interruzione?
- Come ci prepariamo alla prossima interruzione?
Nota: nei casi, perlomeno di lettura, potrebbe essere sensato impostare i valori passati come parametri dalla primitiva all'interno del descrittore. Sarà poi l'interruzione (se chiamata ogni tot) a sistemare questi valori già inizializzati con i valori aggiornati. Se invece dovesse essere richiamata solo alla fine del processo, sarà compito della read fare tutto il processo e abilitare le interruzioni alla fine facendo riattivare la estern_ce
Nota2: quando in una read viene passato un buffer, questo dovrà essere copiato nel descrittore in quanto è il buffer in cui la periferica dovrà scrivere i valori che dovremo leggere.
Nota3: se il passaggio di byte tra utente e periferica viene effettuato tramite un buffer di appoggio intermedio, dobbiamo necessariamente usare la memcpy, in quanto questi dati devono essere copiati in una zona di memoria. |
Estern CE
// chiamata dalla periferica con un'interruzione
extern "C" void estern_ce(natl id){
// recuperare periferica
for(;;){
// sem_wait(mutex);
// libera il sync occupato nella primitiva
// sem_signal(sync);
// sem_signal(mutex);
wfi();
}
}
|
Metodi di scorrimento tab_iter
it.post()
; it; it.next_post() |
Effettua un accesso posticipato. Viene solitamente utilizzato quando devo cancellare un albero. |
tab_iter it(esecuzione->cr3, v, n); it; it.next()
|
Effettua un accesso anticipato. Viene solitamente utilizzato quando si deve semplicemente scorrere l'albero per farci operazioni di qualsiasi tipo. |
inspronti e inserimento_lista(pronti, esecuzione)
La primitiva inspronti(); inserisce il processo in esecuzione in testa alla coda pronti. |
La primitiva inserimento_lista(pronti, esecuzione); inserisce il processo in esecuzione nella coda pronti in maniera ordinata. Quindi, se nella coda pronti c'è un processo P1 con priorità uguale a quella del processo in esecuzione, quest'ultimo verrà inserito nella lista dopo il processo P1. |
inspronti();
: esecuzione -> P1 |
inserimento_lista(pronti, esecuzione);
: P1 -> esecuzione |
Primitive con tipo di ritorno
Se abbiamo una primitiva del tipo
bool primitiva(parametri)
dovremo implementarla in due modi diversi nel modulo sistema e nel modulo I/O.
SISTEMA: non possiamo farle restituire un tipo (deve essere void), quindi il valore di ritorno dovremo inserirlo nel contesto del processo in esecuzione.
extern "C" void primitiva(parametri) {
//operazioni
esecuzione->contesto[I_RAX] = valore_ritorno;
}
I/O: possiamo utilizzare i tipi di ritorno delle primitive nel seguente modo:
extern "C" bool primitiva(parametri) {
//operazioni
return valore_ritorno;
}
|
|
Created By
Metadata
Comments
No comments yet. Add yours below!
Add a Comment
Related Cheat Sheets
More Cheat Sheets by Gray00