197 lines
6.0 KiB
C
197 lines
6.0 KiB
C
|
#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");
|
|||
|
}
|
|||
|
}
|