// to compile: gcc tokenring_threads_sem.c -o tokenring_threads_sem -lpthread // to execute: tokenring_threads_sem // // This code simulates a token ring, using THREADS + 1 lightweight processes (or threads), being 01 master and more THREAD threads. // The master code creates THREADS threads and releases the first thread, using a semaphore. // Each thread unlocks, increases tkn and then releases the next thread, in a circular queue. // Master thread, when released, prints the new tkn. // // Code uses POSIX Semaphores (IEEE Std 1003.1b). // // copyrights: Paulo S. L. de Souza and Davi J. Conte // #include #include #include #include #define THREADS 4 sem_t permit[THREADS]; int tkn = 0; void *slave(void *p_arg) { int p, next; p = (int) *((int *)p_arg); next = p + 1; sem_wait(&permit[p]); tkn ++; printf("Node %d with token %d \n", p,tkn); if (next < THREADS) sem_post(&permit[next]); pthread_exit(0); } // end slave int main(void) { pthread_t handle[THREADS]; int i, p[THREADS], initial = 0; for (i=0; i < THREADS; i++) { p[i] = i; if (pthread_create(&handle[ i ], 0, (void *) slave, (void *) &p[ i ] ) != 0) { printf("Error creating thread %d! Exiting! \n", i); fflush(0); exit(0); } sem_init (&permit[i], 0 , initial); } // thread master releases first thread and waits from last one, after pthread_join() sem_post(&permit[0]); for (i=0; i < THREADS; i++) { pthread_join(handle[ i ], 0); sem_destroy(&permit[i]); printf("Node %d out! \n", i); } printf("Token = %d \n", tkn); exit(0); } // end main()