⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 philosopher.c

📁 介绍ROCK OS操作系统.一般用于汽车电子,类似OCVX.里面是个DEMO文档,内附说明.
💻 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 + -