Calcolatori Elettronici Cheat Sheet

A Programming › C cheat sheet in italiano (Italian) by Gray00

Cheatsheet per l'insegnamento di Calcolatori Elettronici relativo al nucleo v6.x, università di Pisa

4,617 views 1,229 downloads 7 Jun 2022 History

Semafori

sem_wa­it(­sem);
Esegue counter-- e nel caso aggiunge a waiting il processo.
sem_si­gna­l(sem);
Rilascia un gettone. Esegue counter++ ed estrae dalla lista dei waiting.
sem_in­i($­get­toni);
Restit­uisce il primo semaforo libero insere­ndovi $gettoni gettoni. 0xFFFFFFFF se qualcosa è andato storto.
sem_va­lid­(id);
Verifica la validità di un semaforo.
Mutex: $gettone = 1
Sync: $gettone = 0
Nota: tutti gli errori sono 0xFFFFFFFF
Attenz­ione: Tutti gli id sono natl

Processi

des_p(id);
Restit­uisce un des_proc* a partire dall'id.
c_abor­t_p();
Porta all'­int­err­uzione del processo. Non effettua return ed è utile nei casi di errore.
p->­con­testo[I_RAX] = $value;
Ritorno della funzione di value.
rimozi­one­_li­sta­($l­ista);
Rimuove la testa dalla lista (max prio)
inspro­nti();
Inserisce esecuzione in testa a pronti
Tutti gli id sono natl

Preemption

des_proc* work = rimozione_lista($lista);
inspronti();
inserimento_lista(pronti, work);
schedulatore();
Alla fine ci sarà sicura­mente 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 inform­azioni
LOG_WARN: costante per avviso

Tab iter

tab_iter it(tab, begin, dim);
Utile per scorrere le entrate dell'albero degli indirizzi
it.down();
Per scorrere in profon­dità, vedi vm.h
it.is_­leaf();
restit­uisce true se è una foglia
tab_en­try­& e = it.get­_e();
Restit­uisce un riferi­mento al descri­ttore corrente
vaddr v = it.get­_v();
Restit­uisce l'in­dirizzo virtuale asdsociato alla entry in it
paddr p = extr_I­ND_­FIS­ICO­($e);
Restit­uisce l'in­dirizzo fisico associato alla entry
set_IN­D_F­ISI­CO($e, $paddr);
Setta l'in­dirizzo fisico corris­pon­dente alla entry $e
alloca­_tab();
Alloca un frame libero destinato a contenere una tabella di traduzione restit­uendo l'in­dirizzo del frame
copy_d­es(­paddr src, paddr dst, natl i, natl n);
Copia '­n' descri­ttori da src in dst a partire dall'indice i
set_de­s(paddr dst, natl i, natl n, tab_entry e);
Setta il valore '­e' su '­n' descri­ttori 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

trasfo­rma­(va­ddr);
Restit­uisce il paddr relativo a un vaddr
tipo_l­ive­llo­_ac­cesso
Vedere le note
alloca­_fr­ame();
restit­uisce l'in­dirizzo del frame caricato
rilasc­ia_­fra­me(­$pa­ddr);
Libera il frame in cui è contenuto $paddr
paddr base = p & ~0xFFF;
base di un frame
natl indice = p / DIM_PA­GINA;
Indice di frame
invali­da_­ent­rat­a_T­LB(­$va­ddr);
Invalida l'en­trata del TLB del processo in esecuzione
cr0
Abilita la pagina­zione
cr1
Non implem­entato
cr2
Indirizzo che ha causato page fault
cr3
paddr albero di traduzione del processo
vdf[];
array dei descri­ttori 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'in­ter­vallo [begin, end) restit­uendo il primo che non è riuscito a tradurre
unmap(­p->cr3, vaddr begin, vaddr end, getpaddr);
Rimuove le traduzioni nell'in­ter­vallo [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)
z = inputx(reg);
Inserisce il valore al registro reg in z
outputx(value, reg);
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'in­ter­ruz­ione?
- Chi prepara il descri­ttore?
- Cosa deve fare l'in­ter­ruz­ione?
- Come rispon­diamo all'­int­err­uzione?
- Come ci prepariamo alla prossima interr­uzione?

Nota: nei casi, perlomeno di lettura, potrebbe essere sensato impostare i valori passati come parametri dalla primitiva all'­interno del descri­ttore. Sarà poi l'in­ter­ruzione (se chiamata ogni tot) a sistemare questi valori già inizia­lizzati con i valori aggior­nati. Se invece dovesse essere richiamata solo alla fine del processo, sarà compito della read fare tutto il processo e abilitare le interr­uzioni alla fine facendo riattivare la estern_ce

Nota2: quando in una read viene passato un buffer, questo dovrà essere copiato nel descri­ttore 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 interm­edio, dobbiamo necess­ari­amente 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 scorri­mento tab_iter

it.post(); it; it.nex­t_p­ost()
Effettua un accesso postic­ipato. Viene solita­mente utilizzato quando devo cancellare un albero.
tab_iter it(ese­cuz­ion­e->cr3, v, n); it; it.next()
Effettua un accesso anticipato. Viene solita­mente utilizzato quando si deve sempli­cemente scorrere l'albero per farci operazioni di qualsiasi tipo.

inspronti e inseri­men­to_­lis­ta(­pronti, esecuz­ione)

La primitiva
 ­ ­ ­  inspro­nti();
inserisce il processo in esecuzione in testa alla coda pronti.
La primitiva
 ­ ­ ­  inseri­men­to_­lis­ta(­pronti, esecuz­ione);
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 esecuz­ione, quest'u­ltimo verrà inserito nella lista dopo il processo P1.
inspro­nti(); : esecuzione -> P1
inseri­men­to_­lis­ta(­pronti, esecuz­ione); : P1 -> esecuzione

Primitive con tipo di ritorno

Se abbiamo una primitiva del tipo
bool primit­iva­(pa­ram­etri)
dovremo implem­entarla 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 esecuz­ione.
extern "­C" void primit­iva­(pa­ram­etri) {
//oper­azioni
esecuz­ion­e->­con­tes­to[­I_RAX] = valore­_ri­torno;
}
I/O: possiamo utilizzare i tipi di ritorno delle primitive nel seguente modo:
extern "­C" bool primit­iva­(pa­ram­etri) {
//oper­azioni
return valore­_ri­torno;
}

Comments

No comments yet.

Cheatography n. The art of mapping complex subjects into clear, instantly navigable reference guides.