📄 barber.c
字号:
/******************************************************************************
Copyright (c) 2006 by RockOS.
All rights reserved.
This software is supported by the Rock Software Workroom only.
Any bugs please contact the author with e-mail or QQ:
E-mail : baobaoba520@yahoo.com.cn
QQ : 59681888
*******************************************************************************
File name : barber.c
Description : A classical IPC issue - barber's room
:
:
Auther : sunxinqiu
History :
2006-03-15 first release.
******************************************************************************/
#include "os.h"
#define BARBERS 5 /* 提供服务的理发师数 */
#define CHAIRS 10 /* 为等候的顾客准备的椅子数. */
#define HAIRCUT_DURATION 5 /* 每个顾客的理发时长. */
HSEMA barbers; /* 理发店的理发师数. */
HSEMA mutex; /* 用于互斥. */
HSEMA customers; /* 等候服务的顾客数. */
int waiting; /* 等候服务的顾客数. */
enum
{
WAITING = 1, /* 顾客在椅子上等待理发 */
HAIRCUTTING = 2, /* 正在理发中 */
HAIRCUT_OVER = 3 /* 理好了, 满意地离去 */
};
HQUEUE hCustomQueue;
volatile int CustomerState[MAX_SYS_TASK];
int customer_come (int argc, char * argv[]);
void barber(void * p);
void customer(void * p);
void cut_hair (int employeeId, int customerId);
void get_haircut(void);
/* 为每个理发师创建一个任务. */
STATUS app_entry()
{
int i;
TASK_INFO taskInfo;
hCustomQueue = q_create(OS_QUEUE_FIFO, CHAIRS, NULL_TASK, "customer queue");
customers = semCreate(OS_SEMA_SYNC, 0, "waiting customers count");
barbers = semCreate(OS_SEMA_SYNC, BARBERS, "barbers count");
mutex = semCreate(OS_SEMA_MUTEX, 1, "waiting mutex");
for (i = 0; i < BARBERS; i++)
{
taskInfo.priority = 10;
sprintf(&taskInfo.name[0], "barber%d", i);
taskInfo.taskEntry = barber;
taskInfo.pData = (void*)i;
taskInfo.msgQSize = 0;
taskInfo.semaQSize = DEFAULT_MUTEX_Q_SIZE;
taskInfo.stackSize = TICK_TASK_STACK_SIZE;
taskInfo.option = OPT_TASK_DEFAULT;
taskCreate(&taskInfo);
}
/* 在shell命令行执行"c"命令, 理发店里就来一个顾客 */
regShellCmd(customer_come, "c", "Classic IPC: in barbers");
return OS_SUCCESS;
}
/* 创建顾客任务, 由用户在Shell上输入"c"命令激活 */
int customer_come (int argc, char * argv[])
{
TASK_INFO taskInfo;
if (getTaskCount() >= MAX_SYS_TASK)
{
OS_printf("customer over flow.\n");
return 0;
}
taskInfo.priority = 10;
sprintf(&taskInfo.name[0], "customer");
taskInfo.taskEntry = customer;
taskInfo.pData = (void*)0;
taskInfo.msgQSize = 0;
taskInfo.semaQSize = DEFAULT_MUTEX_Q_SIZE;
taskInfo.stackSize = TICK_TASK_STACK_SIZE;
taskInfo.option = OPT_TASK_DEFAULT;
taskCreate(&taskInfo);
return MAX_SYS_TASK - getTaskCount(); /* 返回空闲的任务数, 如果空闲任务数为0, 就不能再加顾客了. */
}
/* 理发师的行为 */
void barber(void * p)
{
int employeeId;
int customerId;
employeeId = (int)p;
while(1)
{
semTake(customers, OS_WAIT_FOR_EVER); /* 如果顾客数是0, 则睡觉 */
semTake(mutex, OS_WAIT_FOR_EVER); /* 要求进程等候 */
waiting --; /* 等候的顾客数减一 */
q_enum(hCustomQueue, (HANDLE *)&customerId); /* 该理发了 */
CustomerState[customerId] = HAIRCUTTING;
semGive(barbers); /* 理发师现在开始理发了 */
semGive(mutex); /* 释放等候 */
cut_hair(employeeId, customerId); /* 理发, (非临界区操作) */
OS_printf("Barber [%d]: Well, the next one.....\n", taskIdSelf());
}
}
/* 顾客的行为, 只需要一次理发, 所以不需要循环 */
void customer(void * p)
{
int customerId;
(void)p;
customerId = taskIdSelf();
semTake(mutex, OS_WAIT_FOR_EVER); /* 进入临界区 */
if (waiting < CHAIRS) /* 如果没有空的椅子, 就离开 */
{
waiting++; /* 等候的顾客数加一 */
CustomerState[customerId] = WAITING;
q_add(hCustomQueue, customerId, 0); /* 坐上椅子 */
semGive(customers); /* 如果必要的话,唤醒理发师 */
semGive(mutex); /* 释放访问等候 */
semTake(barbers, OS_WAIT_FOR_EVER); /* 如果理发师数为0, 就睡觉 */
get_haircut(); /* 坐下等候服务 */
}
else
{
semGive(mutex); /* 店里人满了, 走吧 */
OS_printf("\nTNND, so many peoples, let\'s go.\n");
}
}
/* 理发师正在理发. */
void cut_hair (int employeeId, int customerId)
{
int duration;
duration = HAIRCUT_DURATION;
while (duration > 0)
{
/* 理发师在工作时, 每秒打印一次. */
OS_printf("Barber [%d]: cutting hair for Custom [%d].....[%d] left.\n",
taskIdSelf(), customerId, duration);
taskDelay(sec2Tick(1));
duration--;
}
/* 理好了 */
CustomerState[customerId] = HAIRCUT_OVER;
OS_printf("Barber [%d]: cutting hair completed.\n", taskIdSelf());
}
void get_haircut()
{
while(CustomerState[taskIdSelf()] != HAIRCUT_OVER) /* 等待理发结束. */
{
taskDelay(sec2Tick(1));
}
OS_printf("Customer [%d]: Thanks, it\'s fine\n", taskIdSelf()); /* 理好了, 该走了. */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -