📄 philosopher.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 : philosopher.c
Description : A classical IPC issue - five philosophers.
:
:
Auther : sunxinqiu
History :
2006-03-15 first release.
******************************************************************************/
#include "os.h"
#define N 5 /* 哲学家数目 */
#define LEFT(i) ((i-1+N)%N) /* i的左邻号码 */
#define RIGHT(i) ((i+1)%N) /* i的右邻号码 */
#define EATING_DURATION 5
enum
{
THINKING = 0, /* 哲学家正在思考 */
HUNGRY = 1, /* 哲学家想取得叉子 */
EATING = 2 /* 哲学家正在吃面 */
};
HTASK hPhilosopher[N]; /*保存哲学家的任务编号*/
int eatingDuration[N];
int state[N]; /* 记录每位哲学家状态的数组 */
HSEMA mutex; /* 临界区互斥 */
HSEMA s[N]; /* 每个哲学家一个信号量 */
void philosopher(void * p);
void take_forks(int philosopher_id);
void put_forks(int philosopher_id);
void test(int philosopher_id);
void think(int philosopher_id);
void eat(int philosopher_id);
int hunger_philosopher (int argc, char * argv[]);
STATUS app_entry()
{
int i;
TASK_INFO taskInfo;
/* 创建互斥信号量 */
mutex = semCreate(OS_SEMA_MUTEX, 1, "mutex philosopher");
/* 创建哲学家信号量 */
for (i = 0; i < N; i++)
{
s[i] = semCreate(OS_SEMA_SYNC, 0, "philosopher state");
}
/* 创建哲学家任务 */
for (i = 0; i < N; i++)
{
taskInfo.priority = 10;
sprintf(&taskInfo.name[0], "philosopher%d", i);
taskInfo.taskEntry = philosopher;
taskInfo.pData = (void*)i;
taskInfo.msgQSize = 1;
taskInfo.semaQSize = DEFAULT_MUTEX_Q_SIZE;
taskInfo.stackSize = TICK_TASK_STACK_SIZE;
taskInfo.option = OPT_TASK_DEFAULT;
hPhilosopher[i] = taskCreate(&taskInfo);
}
/*在Shell上执行命令p,可以使一个正在思考的哲学家变得饥饿. */
regShellCmd(hunger_philosopher, "p", "classic IPC: five philosopher issue");
return OS_SUCCESS;
}
void philosopher(void * p) /* p:哲学家号码,从0到N-1 */
{
int philosopher_id;
philosopher_id = (int)p;
while(1) /* 无限循环 */
{
think(philosopher_id); /* 哲学家正在思考 */
take_forks(philosopher_id); /* 需要两只叉子,或者阻塞 */
eat(philosopher_id); /* 进餐 */
put_forks(philosopher_id); /* 把两把叉子同时放回桌子 */
}
}
void take_forks(int philosopher_id) /* philosopher_id: 哲学家号码从0到N-1 */
{
semTake(mutex, OS_WAIT_FOR_EVER); /* 进入临界区 */
state[philosopher_id]=HUNGRY; /* 记录下哲学家i饥饿的事实 */
test(philosopher_id); /* 试图得到两只叉子 */
semGive(mutex); /* 离开临界区 */
semTake(s[philosopher_id], OS_WAIT_FOR_EVER); /* 如果得不到叉子就阻塞 */
}
void put_forks(int philosopher_id) /* 哲学家号码从0到N-1 */
{
semTake(mutex, OS_WAIT_FOR_EVER); /* 进入临界区 */
state[philosopher_id]=THINKING; /* 哲学家进餐结束 */
test(LEFT(philosopher_id)); /* 看一下左邻居现在是否能进餐 */
test(RIGHT(philosopher_id)); /* 看一下右邻居现在是否能进餐 */
semGive(mutex); /* 离开临界区 */
}
void test(int philosopher_id) /* philosopher_id:哲学家号码从0到N-1 */
{
if(state[philosopher_id]==HUNGRY&&state[LEFT(philosopher_id)]!=EATING
&&state[RIGHT(philosopher_id)]!=EATING)
{
state[philosopher_id]=EATING;
semGive(s[philosopher_id]);
}
}
void think(int philosopher_id) /* 哲学家正在思考,思考时每秒打印一下. */
{
HMSG hmsg;
while ((msgQReceive(&hmsg, OS_NO_WAIT) == OS_FAIL)
{
OS_printf("Philosopher [%d]: I\'m thinking, don\'t disturb me.\n", philosopher_id);
taskDelay(sec2Tick(1));
}
else
{
OS_printf("Philosopher [%d]: I'm hungry.\n", philosopher_id);
}
msgFree(hmsg);
}
void eat(int philosopher_id) /*哲学家正在吃饭, 吃饭时长由EATING_DURATION定义, 吃饭过程中每秒会有一次打印. */
{
eatingDuration[philosopher_id] = EATING_DURATION;
while(eatingDuration[philosopher_id] != 0)
{
OS_printf("Philosopher [%d]: I'm eating.......[%d]\n", philosopher_id, eatingDuration[philosopher_id]);
taskDelay(sec2Tick(1));
eatingDuration[philosopher_id]--;
}
/* 吃饱了. */
OS_printf("Philosopher [%d]: Hmmmm, what a delicious food!!!\n", philosopher_id);
}
/* 使哲学家变得饥饿, 这个函数被登记为Shell命令 */
int hunger_philosopher (int argc, char * argv[])
{
int philosopher_id;
HMSG hmsg;
if (argc <= 1)
{
OS_printf("\tUsage:\n");
OS_printf("\t\tp philosopher_id\n");
OS_printf("\tThe value of philosopher_id is from 0 to %d\n", N-1);
return 0;
}
philosopher_id = str2int(argv[1]);
hmsg = msgAlloc(MINI_MSG_PACK);
if (msgQSend(hmsg, hPhilosopher[philosopher_id], OS_NO_WAIT) == OS_FAIL)
{
/*如果消息队列满, 表示哲学家正在等待或者已经吃上了, 你还想再让他饿, 于是乎......*/
OS_printf("philosopher_id [%d]: TNND, 你想让我撑死呀?!!!\n", philosopher_id);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -