Created
April 20, 2014 10:18
-
-
Save baishuai/11110524 to your computer and use it in GitHub Desktop.
Ucore中使用信号量和管程解决理发师问题
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <proc.h> | |
#include <sem.h> | |
#include <monitor.h> | |
#include <assert.h> | |
#define Chair 5 | |
#define SLEEP_TIME 4 | |
//----------理发师问题 使用信号量解法 | |
semaphore_t mutex; //临界区互斥 | |
semaphore_t chairs;//等候椅一般信号量,可用椅子数 | |
semaphore_t barber;//理发师 | |
int waiting_sem; //正在等候的顾客数量 | |
bool close_sem; | |
int manager_using_semaphore(void *arg){ | |
do_sleep(500); | |
down(&mutex); | |
close_sem = 1; //打烊了 | |
up(&chairs); //如果理发师还在睡觉,叫醒理发师 | |
up(&mutex); | |
} | |
int barber_using_semaphore(void *arg) //理发师,只有一个理发师进程运行此函数 | |
{ | |
while(1){ | |
if(waiting_sem == 0) | |
cprintf("There's no customer, I will sleep\n"); | |
down(&chairs); //找一位正在等候的顾客来理发,如果没有顾客则一直睡觉 | |
up(&barber); //开始理发 | |
do_sleep(SLEEP_TIME); //正在理发 | |
if (close_sem) | |
break; | |
} | |
//收尾。禁止在进来,如果椅子上还有人等,则替他们理发 | |
{ | |
int left = Chair; | |
while(left-- > 0){ | |
up(&barber); //开始理发 | |
do_sleep(SLEEP_TIME); //正在理发 | |
} | |
} | |
cprintf("Today's work is over\n"); | |
return 0; | |
} | |
int customer_using_semaphore(void *arg){ | |
int i = (int)arg; //顾客ID | |
if(waiting_sem == Chair){ | |
cprintf("So much customers, I No.%d will leave\n", i); | |
}else{ | |
down(&mutex); | |
up(&chairs); | |
cprintf("I am No.%d customer, I'm in. There are %d other people except me\n",i, waiting_sem); | |
waiting_sem ++; | |
up(&mutex); | |
down(&barber); //等待理发 | |
down(&mutex); //进入临界区 | |
waiting_sem --; //等候顾客数减1 | |
up(&mutex); | |
cprintf("I am No.%d customer, I'm getting a haircut\n",i); | |
return 0; | |
} | |
return 0; | |
} | |
//------------管程解法-------- | |
int waiting_mon; | |
bool close_mon = 0; | |
monitor_t mt, *mtb = &mt; | |
int manager_using_monitor(void *arg){ | |
do_sleep(500); | |
down(&(mtb->mutex)); | |
//--------into routine in monitor-------------- | |
close_mon = 1; //打烊了 | |
cond_signal(&(mtb->cv[0])); //如果理发师还在睡觉,叫醒理发师 | |
//--------leave routine in monitor-------------- | |
if(mtb->next_count>0) | |
up(&(mtb->next)); | |
else | |
up(&(mtb->mutex)); | |
} | |
//-------------barber using monitor ------------ | |
int barber_using_monitor(void *arg){ | |
while(1){ | |
down(&(mtb->mutex)); | |
//--------into routine in monitor-------------- | |
if (waiting_mon == 0){ | |
cprintf("There's no customer, I will sleep\n"); | |
cond_wait(&(mtb->cv[0])); //等待顾客进来 | |
} | |
cond_signal(&(mtb->cv[1])); //告诉顾客 | |
//--------leave routine in monitor-------------- | |
if(mtb->next_count>0) | |
up(&(mtb->next)); | |
else | |
up(&(mtb->mutex)); | |
//理发 | |
do_sleep(SLEEP_TIME); | |
if (close_mon){ | |
break; | |
} | |
} | |
//收尾,如果椅子上还有人等,则替他们理发 | |
{ | |
int left = Chair; //最多有这么多人在等 | |
while(left-- > 0){ | |
down(&(mtb->mutex)); | |
//--------into routine in monitor-------------- | |
cond_signal(&(mtb->cv[1])); //告诉顾客 | |
//--------leave routine in monitor-------------- | |
if(mtb->next_count>0) | |
up(&(mtb->next)); | |
else | |
up(&(mtb->mutex)); | |
//理发 | |
do_sleep(SLEEP_TIME); | |
} | |
} | |
cprintf("Today's work is over\n"); | |
return 0; | |
} | |
int customer_using_monitor(void *arg){ | |
int i = (int)arg; //顾客ID | |
down(&(mtb->mutex)); | |
//--------into routine in monitor-------------- | |
if(close_mon){ | |
cprintf("Closed, I No.%d will leave\n", i); | |
}else if (waiting_mon == Chair){ | |
cprintf("So much customers, I No.%d will leave\n", i); | |
}else{ | |
waiting_mon ++; | |
cprintf("I am No.%d customer, I'm in. There are %d people\n",i, waiting_mon); | |
cond_signal(&(mtb->cv[0])); //告诉理发师有人进来了 | |
cond_wait(&(mtb->cv[1])); //等理发师 | |
waiting_mon --; | |
cprintf("I am No.%d customer, I'm getting a haircut\n",i); | |
} | |
//--------leave routine in monitor-------------- | |
if(mtb->next_count>0) | |
up(&(mtb->next)); | |
else | |
up(&(mtb->mutex)); | |
} | |
//------------- | |
void check_barber_sync(void){ | |
int i = 0, pid = 0; | |
//check semaphore | |
sem_init(&mutex,1); | |
sem_init(&barber,0); | |
sem_init(&chairs,0); | |
waiting_sem = 0; | |
close_sem = 0; | |
pid = kernel_thread(manager_using_semaphore, (void *)0, 0); | |
if (pid <= 0) { | |
panic("create manage_using_semaphore failed.\n"); | |
} | |
pid = kernel_thread(barber_using_semaphore, (void *)0, 0); | |
if (pid <= 0) { | |
panic("create barber_using_semaphore failed.\n"); | |
} | |
for(i = 0; i < 30; i++) { | |
do_sleep(3); | |
pid=kernel_thread(customer_using_semaphore,(void *)i,0);//创建顾客线程 | |
if(pid<=0) { | |
cprintf("Customer is not created.\n"); | |
} | |
} | |
do_sleep(45); | |
for(; i < 60; i++) { | |
do_sleep(5); | |
pid=kernel_thread(customer_using_semaphore,(void *)i,0);//创建顾客线程 | |
if(pid<=0) { | |
cprintf("Customer is not created.\n"); | |
} | |
} | |
//check condition variable | |
monitor_init(&mt, 2); | |
waiting_mon = 0; | |
close_mon = 0; | |
pid = kernel_thread(manager_using_monitor, (void *)0, 0); | |
if (pid <= 0) { | |
panic("create manage_using_semaphore failed.\n"); | |
} | |
pid = kernel_thread(barber_using_monitor, (void *)0, 0); | |
if (pid <= 0) { | |
panic("create barber_using_semaphore failed.\n"); | |
} | |
for(i = 0; i < 30; i++) { | |
do_sleep(3); | |
pid=kernel_thread(customer_using_monitor,(void *)i,0);//创建顾客线程 | |
if(pid<=0) { | |
cprintf("Customer is not created.\n"); | |
} | |
} | |
do_sleep(45); | |
for(; i < 60; i++) { | |
do_sleep(5); | |
pid=kernel_thread(customer_using_monitor,(void *)i,0);//创建顾客线程 | |
if(pid<=0) { | |
cprintf("Customer is not created.\n"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment