1/*
2 * Copyright (c) 2002, Intel Corporation. All rights reserved.
3 * Created by:  crystal.xiong REMOVE-THIS AT intel DOT com
4 * This file is licensed under the GPL license.  For the full content
5 * of this license, see the COPYING file at the top level of this
6 * source tree.
7 *
8 * Test the well-known philosophy problem.
9 *
10 */
11#include <stdio.h>
12#include <unistd.h>
13#include <fcntl.h>
14#include <stdlib.h>
15#include <sys/wait.h>
16#include <sys/mman.h>
17#include <string.h>
18#include <getopt.h>
19#include <errno.h>
20#include <semaphore.h>
21#include <pthread.h>
22
23#include "posixtest.h"
24
25#define	PH_NUM		5
26#define LOOP_NUM	20
27#define thinking	0
28#define hungry		1
29#define eating		2
30
31sem_t ph[PH_NUM];
32sem_t lock;
33
34int state[PH_NUM];
35
36int think(int ID)
37{
38	printf("Philosoper [%d] is thinking... \n", ID);
39	return 0;
40}
41int eat(int ID)
42{
43	printf("Philosoper [%d] is eating... \n", ID);
44	return 0;
45}
46int test(int ID)
47{
48	int preID = 0, postID = 0;
49	if ((ID - 1) < 0)
50		preID = PH_NUM + (ID - 1);
51	else
52		preID = (ID - 1)%PH_NUM;
53
54	if ((ID + 1) >= PH_NUM)
55		postID = ID + 1 - PH_NUM;
56	else
57		postID = (ID + 1)%PH_NUM;
58
59	if ((state[ID] == hungry)&&(state[preID]!= eating)&&(state[postID] != eating)) {
60		state[ID] = eating;
61		sem_post(&ph[ID]);
62	}
63	return 0;
64
65}
66int philosopher(void *ID)
67{
68	int PhID = *(int *)ID;
69	int prePH, postPH;
70	int i;
71
72	for (i = 0; i < LOOP_NUM; i++) {
73		think(PhID);
74		sleep(1);
75		if ( -1 == sem_wait(&lock)) {
76			perror("sem_wait didn't return success \n");
77			pthread_exit((void *)1);
78		}
79		state[PhID] = hungry;
80		test(PhID);
81		if ( -1 == sem_post(&lock)) {
82			perror("sem_post didn't return success \n");
83			pthread_exit((void *)1);
84		}
85		if ( -1 == sem_wait(&ph[PhID])) {
86			perror("sem_wait didn't return success \n");
87			pthread_exit((void *)1);
88		}
89		eat(PhID);
90		sleep(1);
91		if ( -1 == sem_wait(&lock)) {
92			perror("sem_wait didn't return success \n");
93			pthread_exit((void *)1);
94		}
95		state[PhID] = thinking;
96		if ((PhID - 1) < 0)
97			prePH = PH_NUM + (PhID - 1);
98		else
99			prePH = (PhID - 1)%PH_NUM;
100		if ((PhID + 1) >= PH_NUM)
101			postPH = PhID + 1 - PH_NUM;
102		else
103			postPH = (PhID + 1)%PH_NUM;
104		test(prePH);
105		test(postPH);
106		if ( -1 == sem_post(&lock)) {
107			perror("sem_post didn't return success \n");
108			pthread_exit((void *)1);
109		}
110	}
111	pthread_exit((void *) 0);
112}
113
114int main(int argc, char *argv[])
115{
116	pthread_t phi[PH_NUM];
117	int PhID[PH_NUM];
118	int shared = 1;
119	int ph_value = 0;
120	int lock_value = 1;
121	int i ;
122
123#ifndef  _POSIX_SEMAPHORES
124	printf("_POSIX_SEMAPHORES is not defined \n");
125	return PTS_UNRESOLVED;
126#endif
127	for (i = 0; i < PH_NUM; i++) {
128		if (-1 == sem_init(&ph[i], shared, ph_value)) {
129			perror("sem_init didn't return success \n");
130			return PTS_UNRESOLVED;
131		}
132		state[i] = 0;
133	}
134	if (-1 == sem_init(&lock, shared, lock_value)) {
135		perror("sem_init didn't return success \n");
136		return PTS_UNRESOLVED;
137	}
138
139	for (i = 0; i< PH_NUM; i++) {
140		PhID[i] = i;
141		pthread_create(&phi[i], NULL, (void *)philosopher, &PhID[i]);
142	}
143
144	for (i = 0; i< PH_NUM; i++) {
145		pthread_join(phi[i], NULL);
146	}
147
148	for (i = 0; i< PH_NUM; i++) {
149		if (-1 == sem_destroy(&ph[i])) {
150			perror("sem_destroy didn't return success \n");
151			return PTS_UNRESOLVED;
152		}
153	}
154	if (-1 == sem_destroy(&lock)) {
155		perror("sem_destroy didn't return success \n");
156		return PTS_UNRESOLVED;
157	}
158	return PTS_PASS;
159}
160