In tutti gli esercizi seguenti, il main() deve creare i thread necessari e poi scegliere una strategia tra le due seguenti: - chiamare opportunamente pthread_join() per aspettare che tutti i thread terminino, oppure - chiamare pthread_exit() e terminare, in modo da lasciare che i thread creati continuino a vivere fino alla loro terminazione. 1. Scrivere in C un programma che prenda in ingresso da linea di comando un numero intero N. Il programma definisce una variable globale intera 'count' inizializzata a 0, e crea N thread. Ciascun thread incrementa la variabile globale 'count' e stampa il proprio indice seguito dal nuovo valore assunto dalla variabile. L'indice del thread e' cosi' determinato: il primo thread creato ha indice 0, il secondo 1, ..., l'N-esimo ha indice N-1. Il programma deve garantire che l'ultimo valore di 'count' stampato sia N. 2. Problema del PRODUTTORE/CONSUMATORE in C. Si consideri un array circolare di caratteri (buffer), di dimensione LEN = 20. Il buffer e' gestito con strategia FIFO (First In First Out) per gli inserimenti e le estrazioni. Il programma crea 3 thread che operano concorrentemente sull'array: - Il thread 1 (produttore) esegue per LEN volte la seguente operazione, ogni volta in mutua esclusione: - Se il buffer non e' pieno, aggiunge il carattere 'o' in coda; altrimenti aspetta che una cella del buffer si liberi; - Il thread 2 si comporta esattamente come il thread 1, ma scrivendo 'x' al posto di 'o'. - Il thread 3 (consumatore) esegue per 2*LEN volte la seguente operazione, ogni volta in mutua esclusione: se il buffer non e' vuoto, estrae un carattere dalla testa del buffer, e lo stampa; altrimenti aspetta che il buffer diventi non vuoto. Provare a risolvere il problema con i semafori classici e/o con le variabili condition. 3. Scrivere un programma in C che usa tre thread per gestire una variabile globale di tipo intero 'count', inizializzata a zero. Il primo thread attende che il valore di 'count' diventi maggiore o uguale di THRESH=15, e quando cio' accade stampa il messaggio "Threshold reached". Gli altri due thread effettuano per N=20 volte le seguenti operazioni, in mutua esclusione: a) incrementa la variabile 'count' b) stampa a video il proprio indice e il valore aggiornato di 'count' c) notifica opportunamente il primo thread Il programma deve essere implementato utilizzando le variabili condition. 4. Scrivere in C un programma che prenda in ingresso da linea di comando N interi compresi tra 0 e 10. N e' una costante nota a tempo di compilazione, per esempio 5. Il programma crea N thread, che si comportano come segue: a) Il thread i-esimo dorme per un numero di secondi pari al valore dell'i-esimo numero intero specificato dall'utente. b) Al risveglio, l'i-esimo thread stampa il seguente messaggio "Thread #i: Woken up!" c) Dopodiche' il thread i-esimo aspetta che gli altri siano arrivati allo stesso punto (barriera). d) Dopo la barriera, ciascun thread stampa un messaggio di chiusura "Thread #i: Closing" Si implementi il punto c prima con i semafori classici (semafori generici) e successivamente con le variabili condition. Nota: la funzione di libreria sleep(int n) sospende il thread corrente per un numero n di secondi.