#include #include #include #include #include #include #include #include #include #include #include #include #include #define N 5 /* pocet filosofu */ #define THINK_COUNT (3 + rand() %5) /* kolikrat budu premyslet - jist */ #define THINK_PERIOD (1 + rand()%3) /* jak dlouho budu premyslet */ #define EAT_PERIOD (1 + rand()%5) /* jak dlouho budu jist */ #define LEFT (i > 0 ? i-1 : N-1) #define RIGHT ((i+1) % N) enum status { THINK, HUNGRY, EAT, LEAVE }; enum status *state; /* pole stavu ve kterem se nachazeji filosofove */ int segment_id; /* identifikace zdilene pameti */ sem_t *mutex; sem_t *s[N]; char sname[10]; /* jmeno semaforu */ int myid; /* index filosofa, v kazem vlaknu unikatni */ void init() { int i; /** alokace zdilene pameti **/ segment_id = shmget(IPC_PRIVATE, sizeof(enum status)*N, IPC_CREAT | S_IRUSR | S_IWUSR); if(!segment_id) { perror("shmget"); } state = (enum status *) shmat(segment_id, NULL, 0); /** inicializace semaforu */ mutex = sem_open("mutex", O_CREAT, 0, 1); if (mutex == SEM_FAILED) { perror("Error creating mutex semaphore"); exit(1); } for (i = 0; i < N; i++) { state[i] = THINK; sprintf(sname,"s%d",i); s[i] = sem_open(sname, O_CREAT, 0, 0); if (s[i] == SEM_FAILED) { perror("Error creating s semaphore"); exit(1); } } } void destroy() { int i; sem_close(mutex); sem_unlink("mutex"); for (i = 0; i < N; i++) { sem_close(s[i]); sprintf(sname,"s%d",i); sem_unlink(sname); } shmdt(state); shmctl(segment_id, IPC_RMID, NULL); } void show_table() { int i; for(i = 0; i < N; i++) { switch(state[i]) { case THINK: printf("T "); break; case HUNGRY: printf("H "); break; case EAT: printf("E "); break; case LEAVE: printf(" "); break; } } printf("\n"); for(i = 0; i < N; i++) { if(state[i] != EAT) continue; if(state[LEFT] == EAT || state[RIGHT] == EAT) { fprintf(stderr,"Chybna logika !\n"); exit(1); } } } void think() { sleep(THINK_PERIOD); } void eat() { sleep(EAT_PERIOD); } void test(int i) { if (state[i] == HUNGRY && state[LEFT] != EAT && state[RIGHT] != EAT) { state[i] = EAT; show_table(); if(sem_post(s[i])) perror("sem_post(s[...)"); } } void take_forks(int i) { sem_wait(mutex); state[i] = HUNGRY; show_table(); test(i); sem_post(mutex); sem_wait(s[i]); } void put_forks(int i) { sem_wait(mutex); if(state[i] == HUNGRY) { printf("hungry is going to think %d\n",i); } state[i] = THINK; show_table(); test(LEFT); test(RIGHT); sem_post(mutex); } void philosopher(int i) { int s = THINK_COUNT; while (--s) { think(); take_forks(i); eat(); put_forks(i); } state[i] = LEAVE; show_table(); } int main(void) { int i; pid_t pid; pid_t filosofove[N]; init(); for (i = 0; i < N; i++) { if (!(pid = fork())) { // jsem potomek (filosof) sleep(i + 1); break; } filosofove[i] = pid; } if (pid) { for (i = 0; i < N; i++) { waitpid(filosofove[i], NULL, 0); } destroy(); printf("Konec\n"); return 0; } srand(time(NULL)); myid = i; philosopher(myid); return 0; }