#include #include #include #include #include #include #include #define NUM_THREADS 31 enum thead_id_status { THREAD_AT_HOME = 0, THREAD_AT_PARTY = 1, THREAD_DONE = 2, }; struct bin { bool ready; int food[NUM_THREADS+1]; int trash[NUM_THREADS+1]; int tid_status[NUM_THREADS+1]; pthread_mutex_t mutex; }; struct party_ticket { long threadid; struct bin *party; }; struct bin *party; static void sleep_random(void) { unsigned int val; val = 10000LL * rand() / RAND_MAX; srand(getpid()); usleep(val); } void eat(long tid) { bool eat_in_order = true; long t; pthread_mutex_lock(&party->mutex); /* If anyone ate out of place lets take notice of that... */ for (t=0; t < NUM_THREADS; t++) { if (t == tid) continue; if (party->tid_status[t] >= THREAD_AT_PARTY && party->food[t]) eat_in_order = false; } sleep_random(); if (party->food[tid]) if (eat_in_order) party->food[tid] = 0; pthread_mutex_unlock(&party->mutex); } void cleanup(long tid) { bool clean_follow = true; long t; for (t=0; t < NUM_THREADS; t++) { if (t == tid) continue; if (party->tid_status[t] >= THREAD_DONE && !party->trash[t]) clean_follow = false; } if (clean_follow) party->trash[tid] = 1; } void *thread_party(void *t) { long tid = (long)t; party->tid_status[tid] = THREAD_AT_PARTY; eat(tid); if (tid % 2 == 1) sleep_random(); cleanup(tid); party->tid_status[tid] = THREAD_DONE; pthread_exit(NULL); } void show_party(struct bin *party) { long t; printf("FOOD: [ "); for (t=0; t < NUM_THREADS; t++) { if (party->food[t]) printf("*"); else printf(" "); } printf(" ]\n"); printf("TRASH: [ "); for (t=0; t < NUM_THREADS; t++) { if (party->trash[t]) printf("*"); else printf(" "); } printf(" ]\n"); } #define pthread_mutex_protects_3(mutex, var1, var2, var3) int main(int argc, char *argv[]) { pthread_t threads[NUM_THREADS]; int ret; long t; pthread_attr_t attr; void *status; party = malloc(sizeof(struct bin)); if (!party) return -ENOMEM; memset(party, 0, sizeof(struct bin)); for (t=0; t <= NUM_THREADS; t++) { party->food[t] = 1; party->trash[t] = 0; party->tid_status[t] = THREAD_AT_HOME; } party->ready = true; printf("Before party:\n"); show_party(party); pthread_mutex_init(&party->mutex, NULL); pthread_mutex_protects_3(&party->mutex, party->food, party->trash, party->tid_status); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); for (t=0; t < NUM_THREADS; t++) { ret = pthread_create(&threads[t], &attr, thread_party, (void *)t); if (ret){ printf("ERROR; return code from pthread_create() is %d\n", ret); exit(-1); } } pthread_attr_destroy(&attr); for (t=0; t < NUM_THREADS; t++) pthread_join(threads[t], &status); printf("\nAfter party:\n"); show_party(party); pthread_mutex_destroy(&party->mutex); pthread_exit(NULL); free(party); }