Skip to content

Instantly share code, notes, and snippets.

@baishuai
Created April 20, 2014 10:18
Show Gist options
  • Save baishuai/11110524 to your computer and use it in GitHub Desktop.
Save baishuai/11110524 to your computer and use it in GitHub Desktop.
Ucore中使用信号量和管程解决理发师问题
#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