#include #include #include #include #include #include /* For O_* constants */ #include /* For mode constants */ #include #include /* ***D02*** N = 10 il programma crea N threads; esiste un contatore condiviso tra thread. ogni thread scrive un messaggio del tipo: "thread numero %d, contatore = %d\n" dove il primo numero è un id passato come parametro al thread (id compreso tra 0 a N-1); ogni thread incrementa il contatore. gli N thread arrivano ad un "tornello"; quando tutti gli N thread sono arrivati li, allora possono proseguire. Ciascun thread prosegue scrivendo il messaggio "thread numero %d - fine\n". */ #define N 10 // contatore condiviso tra i thread // dovrò usare un mutex per regolare l'accesso concorrente al contatore int thread_counter; pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; // come implemento il tornello? // con un semaforo inizializzato a valore 0 sem_t tornello; void * thread_func(void * arg) { // trucco: passo il parametro di int come fosse un indirizzo long int id = (long int) arg; int temp; if (pthread_mutex_lock(&mtx) == -1) { perror("pthread_mutex_lock"); exit(1); } thread_counter++; temp = thread_counter; if (pthread_mutex_unlock(&mtx) == -1) { perror("pthread_mutex_unlock"); exit(1); } printf("thread id=%ld counter=%d\n", id, temp); if (thread_counter == N) { printf("sono l'ultimo thread (id=%ld) che arriva al tornello,\n" "ora apro il tornello così " "tutti i thread in attesa\npossono passare (uno alla volta)\n", id); // variante dell'esercizio: // prima di aprire il tornello, // aspetta 3 secondi // l'ultimo thread apre il tornello if (sem_post(&tornello) == -1) { perror("sem_pos"); exit(1); } } // adesso andiamo al tornello // il tornello viene aperto dal thread N-mo // ovvero l'ultimo thread che arriva al tornello // i primi n-1 threads si fermano qui (tornello chiuso) if (sem_wait(&tornello) == -1) { perror("sem_wait"); exit(1); } // quando il tornello è aperto, passa un thread alla volta if (sem_post(&tornello) == -1) { perror("sem_pos"); exit(1); } printf("dopo il tornello, thread %ld\n", id); return NULL; } int main() { int res; pthread_t threads[N]; // inizializziamo il tornello if (sem_init(&tornello, 0, 0) == -1) { perror("sem_init"); exit(1); } // creiamo gli N threads for (long int i = 0; i < N; i++) { res = pthread_create(&threads[i], NULL, thread_func, (void *)i); if (res != 0) { perror("pthread_create"); exit(1); } } // aspettiamo la conclusione degli N threads for (int i = 0; i < N; i++) { res = pthread_join(threads[i], NULL); if (res != 0) { perror("pthread_join"); exit(1); } } printf("[main thread] bye\n"); return 0; }