blob: 5f589cc258c1beeaf9cc029c1761f6e2757a67e5 [file] [log] [blame]
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#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");
}
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_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);
}