#include <stdio.h> #include <proc.h> #include <sem.h> #include <monitor.h> #include <assert.h> #define N 5 /* 哲学家数目 */ #define LEFT (i-1+N)%N /* i的左邻号码 */ #define RIGHT (i+1)%N /* i的右邻号码 */ #define THINKING 0 /* 哲学家正在思考 */ #define HUNGRY 1 /* 哲学家想取得叉子 */ #define EATING 2 /* 哲学家正在吃面 */ #define TIMES 4 /* 吃4次饭 */ #define SLEEP_TIME 10 //---------- philosophers problem using semaphore ---------------------- int state_sema[N]; /* 记录每个人状态的数组 */ /* 信号量是一个特殊的整型变量 */ semaphore_t mutex; /* 临界区互斥 */ semaphore_t s[N]; /* 每个哲学家一个信号量 */ struct proc_struct *philosopher_proc_sema[N]; void phi_test_sema(i) /* i:哲学家号码从0到N-1 */ { if(state_sema[i]==HUNGRY&&state_sema[LEFT]!=EATING &&state_sema[RIGHT]!=EATING) { state_sema[i]=EATING; up(&s[i]); } } void phi_take_forks_sema(int i) /* i:哲学家号码从0到N-1 */ { down(&mutex); /* 进入临界区 */ state_sema[i]=HUNGRY; /* 记录下哲学家i饥饿的事实 */ phi_test_sema(i); /* 试图得到两只叉子 */ up(&mutex); /* 离开临界区 */ down(&s[i]); /* 如果得不到叉子就阻塞 */ } void phi_put_forks_sema(int i) /* i:哲学家号码从0到N-1 */ { down(&mutex); /* 进入临界区 */ state_sema[i]=THINKING; /* 哲学家进餐结束 */ phi_test_sema(LEFT); /* 看一下左邻居现在是否能进餐 */ phi_test_sema(RIGHT); /* 看一下右邻居现在是否能进餐 */ up(&mutex); /* 离开临界区 */ } int philosopher_using_semaphore(void * arg) /* i:哲学家号码,从0到N-1 */ { int i, iter=0; i=(int)arg; cprintf("I am No.%d philosopher_sema\n",i); while(iter++<TIMES) { /* 无限循环 */ cprintf("Iter %d, No.%d philosopher_sema is thinking\n",iter,i); /* 哲学家正在思考 */ do_sleep(SLEEP_TIME); phi_take_forks_sema(i); /* 需要两只叉子,或者阻塞 */ cprintf("Iter %d, No.%d philosopher_sema is eating\n",iter,i); /* 进餐 */ do_sleep(SLEEP_TIME); phi_put_forks_sema(i); /* 把两把叉子同时放回桌子 */ } cprintf("No.%d philosopher_sema quit\n",i); return 0; } //-----------------philosopher problem using monitor ------------ /*PSEUDO CODE :philosopher problem using monitor * monitor dp * { * enum {thinking, hungry, eating} state[5]; * condition self[5]; * * void pickup(int i) { * state[i] = hungry; * if ((state[(i+4)%5] != eating) && (state[(i+1)%5] != eating)) { * state[i] = eating; * else * self[i].wait(); * } * * void putdown(int i) { * state[i] = thinking; * if ((state[(i+4)%5] == hungry) && (state[(i+3)%5] != eating)) { * state[(i+4)%5] = eating; * self[(i+4)%5].signal(); * } * if ((state[(i+1)%5] == hungry) && (state[(i+2)%5] != eating)) { * state[(i+1)%5] = eating; * self[(i+1)%5].signal(); * } * } * * void init() { * for (int i = 0; i < 5; i++) * state[i] = thinking; * } * } */ struct proc_struct *philosopher_proc_condvar[N]; // N philosopher int state_condvar[N]; // the philosopher's state: EATING, HUNGARY, THINKING monitor_t mt, *mtp=&mt; // monitor void phi_test_condvar (i) { if(state_condvar[i]==HUNGRY&&state_condvar[LEFT]!=EATING &&state_condvar[RIGHT]!=EATING) { cprintf("phi_test_condvar: state_condvar[%d] will eating\n",i); state_condvar[i] = EATING ; cprintf("phi_test_condvar: signal self_cv[%d] \n",i); cond_signal(&mtp->cv[i]) ; } } void phi_take_forks_condvar(int i) { down(&(mtp->mutex)); //--------into routine in monitor-------------- // LAB7 EXERCISE1: YOUR CODE // I am hungry // try to get fork //--------leave routine in monitor-------------- if(mtp->next_count>0) up(&(mtp->next)); else up(&(mtp->mutex)); } void phi_put_forks_condvar(int i) { down(&(mtp->mutex)); //--------into routine in monitor-------------- // LAB7 EXERCISE1: YOUR CODE // I ate over // test left and right neighbors //--------leave routine in monitor-------------- if(mtp->next_count>0) up(&(mtp->next)); else up(&(mtp->mutex)); } //---------- philosophers using monitor (condition variable) ---------------------- int philosopher_using_condvar(void * arg) { /* arg is the No. of philosopher 0~N-1*/ int i, iter=0; i=(int)arg; cprintf("I am No.%d philosopher_condvar\n",i); while(iter++<TIMES) { /* iterate*/ cprintf("Iter %d, No.%d philosopher_condvar is thinking\n",iter,i); /* thinking*/ do_sleep(SLEEP_TIME); phi_take_forks_condvar(i); /* need two forks, maybe blocked */ cprintf("Iter %d, No.%d philosopher_condvar is eating\n",iter,i); /* eating*/ do_sleep(SLEEP_TIME); phi_put_forks_condvar(i); /* return two forks back*/ } cprintf("No.%d philosopher_condvar quit\n",i); return 0; } void check_sync(void){ int i; //check semaphore sem_init(&mutex, 1); for(i=0;i<N;i++){ sem_init(&s[i], 0); int pid = kernel_thread(philosopher_using_semaphore, (void *)i, 0); if (pid <= 0) { panic("create No.%d philosopher_using_semaphore failed.\n"); } philosopher_proc_sema[i] = find_proc(pid); set_proc_name(philosopher_proc_sema[i], "philosopher_sema_proc"); } //check condition variable monitor_init(&mt, N); for(i=0;i<N;i++){ state_condvar[i]=THINKING; int pid = kernel_thread(philosopher_using_condvar, (void *)i, 0); if (pid <= 0) { panic("create No.%d philosopher_using_condvar failed.\n"); } philosopher_proc_condvar[i] = find_proc(pid); set_proc_name(philosopher_proc_condvar[i], "philosopher_condvar_proc"); } }