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 <errno.h>
19 #include <semaphore.h>
20 #include <pthread.h>
21 
22 #include "posixtest.h"
23 
24 #define	PH_NUM		5
25 #define LOOP_NUM	20
26 #define thinking	0
27 #define hungry		1
28 #define eating		2
29 
30 sem_t ph[PH_NUM];
31 sem_t lock;
32 
33 int state[PH_NUM];
34 
think(int ID)35 int think(int ID)
36 {
37 	printf("Philosoper [%d] is thinking... \n", ID);
38 	return 0;
39 }
40 
eat(int ID)41 int eat(int ID)
42 {
43 	printf("Philosoper [%d] is eating... \n", ID);
44 	return 0;
45 }
46 
test(int ID)47 int test(int ID)
48 {
49 	int preID = 0, postID = 0;
50 	if ((ID - 1) < 0)
51 		preID = PH_NUM + (ID - 1);
52 	else
53 		preID = (ID - 1) % PH_NUM;
54 
55 	if ((ID + 1) >= PH_NUM)
56 		postID = ID + 1 - PH_NUM;
57 	else
58 		postID = (ID + 1) % PH_NUM;
59 
60 	if ((state[ID] == hungry) && (state[preID] != eating)
61 	    && (state[postID] != eating)) {
62 		state[ID] = eating;
63 		sem_post(&ph[ID]);
64 	}
65 	return 0;
66 
67 }
68 
philosopher(void * ID)69 int philosopher(void *ID)
70 {
71 	int PhID = *(int *)ID;
72 	int prePH, postPH;
73 	int i;
74 
75 	for (i = 0; i < LOOP_NUM; i++) {
76 		think(PhID);
77 		sleep(1);
78 		if (-1 == sem_wait(&lock)) {
79 			perror("sem_wait didn't return success \n");
80 			pthread_exit((void *)1);
81 		}
82 		state[PhID] = hungry;
83 		test(PhID);
84 		if (-1 == sem_post(&lock)) {
85 			perror("sem_post didn't return success \n");
86 			pthread_exit((void *)1);
87 		}
88 		if (-1 == sem_wait(&ph[PhID])) {
89 			perror("sem_wait didn't return success \n");
90 			pthread_exit((void *)1);
91 		}
92 		eat(PhID);
93 		sleep(1);
94 		if (-1 == sem_wait(&lock)) {
95 			perror("sem_wait didn't return success \n");
96 			pthread_exit((void *)1);
97 		}
98 		state[PhID] = thinking;
99 		if ((PhID - 1) < 0)
100 			prePH = PH_NUM + (PhID - 1);
101 		else
102 			prePH = (PhID - 1) % PH_NUM;
103 		if ((PhID + 1) >= PH_NUM)
104 			postPH = PhID + 1 - PH_NUM;
105 		else
106 			postPH = (PhID + 1) % PH_NUM;
107 		test(prePH);
108 		test(postPH);
109 		if (-1 == sem_post(&lock)) {
110 			perror("sem_post didn't return success \n");
111 			pthread_exit((void *)1);
112 		}
113 	}
114 	pthread_exit(NULL);
115 }
116 
main(void)117 int main(void)
118 {
119 	pthread_t phi[PH_NUM];
120 	int PhID[PH_NUM];
121 	int shared = 1;
122 	int ph_value = 0;
123 	int lock_value = 1;
124 	int i;
125 
126 #ifndef  _POSIX_SEMAPHORES
127 	printf("_POSIX_SEMAPHORES is not defined \n");
128 	return PTS_UNRESOLVED;
129 #endif
130 	for (i = 0; i < PH_NUM; i++) {
131 		if (-1 == sem_init(&ph[i], shared, ph_value)) {
132 			perror("sem_init didn't return success \n");
133 			return PTS_UNRESOLVED;
134 		}
135 		state[i] = 0;
136 	}
137 	if (-1 == sem_init(&lock, shared, lock_value)) {
138 		perror("sem_init didn't return success \n");
139 		return PTS_UNRESOLVED;
140 	}
141 
142 	for (i = 0; i < PH_NUM; i++) {
143 		PhID[i] = i;
144 		pthread_create(&phi[i], NULL, (void *)philosopher, &PhID[i]);
145 	}
146 
147 	for (i = 0; i < PH_NUM; i++) {
148 		pthread_join(phi[i], NULL);
149 	}
150 
151 	for (i = 0; i < PH_NUM; i++) {
152 		if (-1 == sem_destroy(&ph[i])) {
153 			perror("sem_destroy didn't return success \n");
154 			return PTS_UNRESOLVED;
155 		}
156 	}
157 	if (-1 == sem_destroy(&lock)) {
158 		perror("sem_destroy didn't return success \n");
159 		return PTS_UNRESOLVED;
160 	}
161 	return PTS_PASS;
162 }
163