Università degli Studi della Calabria Corso di Laurea in Ingegneria Informatica A.A. 2001/2002 Sistemi Operativi Corsi A e B Esercitazioni 1 e 2 Sincronizzazione dei Processi (1a parte) n Introduzione n Il problema della sezione critica n Soluzioni hardware per la sincronizzazione n Semafori Sistemi Operativi P.Trunfio – R.Ortale 1 Introduzione n L’accesso concorrente a dati condivisi può portare all’inconsistenza dei dati. n Per garantire la consistenza dei dati sono necessari meccanismi per assicurare l’esecuzione ordinata dei processi cooperanti. Sistemi Operativi P.Trunfio – R.Ortale Bounded-Buffer (1) n Dati condivisi class item { ... } … int BUFFER_SIZE = 10; item buffer[] = new item [BUFFER_SIZE]; int in = 0; int out = 0; int counter = 0; … Sistemi Operativi P.Trunfio – R.Ortale 2 Bounded-Buffer (2) n Processo produttore item nextProduced; while (true) { nextProduced = new item (…); while (counter == BUFFER_SIZE) ; /* do nothing */ buffer[in] = nextProduced; in = (in + 1) % BUFFER_SIZE; counter++; } Sistemi Operativi P.Trunfio – R.Ortale Bounded-Buffer (3) n Processo consumatore item nextConsumed; while (true) { while (counter == 0) ; /* do nothing */ nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; counter--; } Sistemi Operativi P.Trunfio – R.Ortale 3 Bounded-Buffer (4) n Le istruzioni: counter++; counter--; devono essere eseguite atomicamente. n Una operazione atomica è una operazione che si completa nella sua interezza senza interruzioni. Sistemi Operativi P.Trunfio – R.Ortale Bounded-Buffer (5) n L’istruzione “counter++” può essere implementata in linguaggio macchina come: register1 = counter register1 = register1 + 1 counter = register1 n L’istruzione “counter--” può essere implementata come: register2 = counter register2 = register2 – 1 counter = register2 Sistemi Operativi P.Trunfio – R.Ortale 4 Bounded-Buffer (6) n Nel caso in cui il produttore ed il consumatore cercassero di aggiornare il buffer contemporaneamente, le istruzioni in linguaggio assembly potrebbero risultare interfogliate (interleaved). n L’interleaving dipende da come i due processi produttore e consumatore sono schedulati. Sistemi Operativi P.Trunfio – R.Ortale Bounded-Buffer (7) n Si assuma che counter sia inizialmente 5. Un possibile interleaving delle istruzioni è: producer: register1 = counter (register1 = 5) producer: register1 = register1 + 1 (register1 = 6) consumer: register2 = counter (register2 = 5) consumer: register2 = register2 – 1 (register2 = 4) producer: counter = register1 (counter = 6) consumer: counter = register2 (counter = 4) n Il valore di counter potrebbe essere o 4 o 6, mentre il valore corretto dovrebbe essere 5. Sistemi Operativi P.Trunfio – R.Ortale 5 Race Condition n Race condition: la situazione in cui più processi accedono e manipolano dati condivisi in modo concorrente. Il valore finale dei dati condivisi dipende da quale processo ha finito per ultimo. n Per eliminare le race condition, i processi concorrenti devono essere sincronizzati. Sistemi Operativi P.Trunfio – R.Ortale Il problema della sezione critica n n processi che competono per usare dati condivisi. n Ciascun processo ha un segmento di codice, chiamato sezione critica, nel quale i dati condivisi sono acceduti. n Problema: garantire che quando un processo è in esecuzione nella sua sezione critica, nessun altro processo sia autorizzato ad eseguire la propria sezione critica. Sistemi Operativi P.Trunfio – R.Ortale 6 Soluzione al problema della sezione critica Devono essere soddisfatti i seguenti requisiti: 1) Mutua esclusione. Se il processo Pi è in esecuzione nella propria sezione critica, nessuna altro processo può essere in esecuzione nella sua sezione critica. 2) Progresso. se nessun processo è in esecuzione nella propria sezione critica, allora soltanto i processi che cercano di entrare nella sezione critica partecipano alla decisione di chi entrerà davvero, e questa decisione deve avvenire in un tempo finito. 3) Attesa limitata. Deve esistere un limite nel numero di volte che altri processi sono autorizzati ad entrare nelle rispettive sezioni critiche dopo che un processo Pi ha fatto richiesta di entrare nella propria sezione critica e prima che quella richiesta sia soddisfatta. Ø Si assume che ciascun processo esegua a velocità non nulla Ø Nessuna assunzione deve essere fatta sulla velocità relativa degli n processi. Sistemi Operativi P.Trunfio – R.Ortale Sezione critica: soluzioni n Soltanto 2 processi, P0 e P1 n Struttura generale del processo Pi while (true) { entry section sezione critica exit section sezione non critica } n I processi possono far uso di variabili condivise per sincronizzare le loro azioni. Sistemi Operativi P.Trunfio – R.Ortale 7 Algoritmo 1 n Variabili condivise: F int turn; F Inizialmente turn = 0 F Quando turn = i ⇒ Pi può entrare in esecuzione nella propria sezione critica n Processo Pi while (true) { while (turn != i) ; sezione critica turn = j; sezione non critica } n Soddisfa la condizione della mutua esclusione, ma non quella del progresso (richiede una stretta alternanza dei processi) Sistemi Operativi P.Trunfio – R.Ortale Algoritmo 2 n Variabili condivise: F boolean flag[] = new boolean[2]; F Inizialmente flag[0] e flag[1] sono false. F Quando flag[i] = true ⇒ Pi è pronto ad entrare nella sua sezione critica n Processo Pi while (true) { flag[i] = true; while (flag[j]) ; sezione critica flag[i] = false; sezione non critica } n Soddisfa la condizione della mutua esclusione, ma non quella del progresso Sistemi Operativi P.Trunfio – R.Ortale 8 Algoritmo 3 n Usa le variabili condivise degli algoritmi 1 e 2. n Processo Pi while (true) { flag[i] = true; turn = j; while (flag[j] && turn == j) ; sezione critica flag[i] = false; sezione non critica } n Soddisfa tutti e tre i requisiti; tuttavia vale solo per due processi. Sistemi Operativi P.Trunfio – R.Ortale Algoritmo del Fornaio (1) Sezione critica per n processi: n Prima di entrare nella sezione critica, il processo riceve un numero. Il possessore del numero più piccolo entra nella sezione critica. n Se i processi Pi e Pj ricevono lo stesso numero, se i < j, allora Pi è servito prima; altrimenti Pj è servito prima. n Lo schema di numerazione genera sempre numeri in ordine crescente; ad esempio: 1,2,3,3,3,3,4,5... Sistemi Operativi P.Trunfio – R.Ortale 9 Algoritmo del Fornaio (2) n La notazione < indica l’ordinamento lessicografico tra coppie del tipo: (ticket #, process id #) F (a,b) < (c,d) se a < c oppure a == c && b < d F max (a0,…, an-1) è un numero k, tale che k ≥ ai per i : 0,…, n – 1 n Dati condivisi boolean choosing[] = new boolean[n]; int number[] = new int [n]; Le strutture dati sono inizializzate a false e 0 rispettivamente Sistemi Operativi P.Trunfio – R.Ortale Algoritmo del Fornaio (3) while (true) { choosing[i] = true; number[i] = max(number[0], number[1], …, number [n – 1])+1; choosing[i] = false; for (j = 0; j < n; j++) { while (choosing[j]) ; while ((number[j] != 0) && ( (number[j],j) < (number[i],i) ) ; } sezione critica number[i] = 0; sezione non critica } Sistemi Operativi P.Trunfio – R.Ortale 10 Soluzioni hardware per la sincronizzazione n Controlla e modifica atomicamente il contenuto di una parola. boolean TestAndSet (boolean &target) { boolean rv = target; target = true; return rv; } Sistemi Operativi P.Trunfio – R.Ortale Mutua esclusione con Test-and-Set n Dati condivisi: boolean lock = false; n Processo Pi while (true) { while (TestAndSet(lock)) ; sezione critica lock = false; sezione non critica } Sistemi Operativi P.Trunfio – R.Ortale 11 Hardware di Sincronizzazione n Scambia atomicamente il valore di due variabili. void Swap (boolean &a, boolean &b) { boolean temp = a; a = b; b = temp; } Sistemi Operativi P.Trunfio – R.Ortale Mutua Esclusione con Swap n Dati condivisi: boolean lock, key; // lock inizializzato a false n Processo Pi while (true) { key = true; while (key == true) Swap(lock,key); sezione critica lock = false; sezione non critica } Sistemi Operativi P.Trunfio – R.Ortale 12 Semafori n Strumento di sincronizzazione che in determinate implementazioni non richiede busy waiting. n Semaforo S: variabile intera n Può essere acceduta esclusivamente attraverso due operazioni indivisibili (atomiche): wait (S): while (S <= 0) ; /* do no-op */ S--; signal (S): S++; Sistemi Operativi P.Trunfio – R.Ortale Sezione critica di n Processi n Dati condivisi: semaforo mutex; // inizialmente mutex = 1 n Processo Pi : while (true) { wait(mutex); sezione critica signal(mutex); sezione non critica; } Sistemi Operativi P.Trunfio – R.Ortale 13 Implementazione dei Semafori n Definiamo un semaforo: class Semaforo { int value; List listaProcessi = new List (); } n Assumiamo che esistano le seguenti operazioni: F block() sospende il processo che la invoca. F wakeup(P) riprende l’esecuzione del processo bloccato P. Sistemi Operativi P.Trunfio – R.Ortale Operazioni associate ai Semafori Supponiamo che sia dichiarato il Semaforo S: wait(S): S.value--; if (S.value < 0) { aggiunge questo processo a S.listaProcessi; block(); } signal(S): S.value++; if (S.value <= 0) { rimuove un processo P da S.listaProcessi; wakeup(P); } Sistemi Operativi P.Trunfio – R.Ortale 14 Semaforo come strumento generale di sincronizzazione n Esegue B in Pj solo dopo che A esegue in Pi n Usa il semaforo flag inizializzato a 0 n Codice: Pi M A signal(flag) Pj M wait(flag) B Sistemi Operativi P.Trunfio – R.Ortale Deadlock e Starvation n Deadlock – due o più processi sono indefinitamente in attesa per un evento che può essere causato da uno soltanto dei processi in attesa. n Siano S e Q due semafori inizializzati a 1 P0 P1 wait(S); wait(Q); wait(Q); wait(S); M M signal(S); signal(Q); signal(Q) signal(S); n Starvation – blocking indefinito. Un processo A potrebbe non essere mai rimosso dalla coda del semaforo in cui è sospeso. Sistemi Operativi P.Trunfio – R.Ortale 15 Due tipi di semafori n Semaforo contatore – valore intero che può spaziare su un dominio illimitato. n Semaforo binario – valore intero che può valere solo 0 e 1; può essere più semplice da implementare. n E’ possibile implementare un semaforo contatore usando semafori binari. Sistemi Operativi P.Trunfio – R.Ortale 16