|
0
|
1 //========================================================================== |
|
|
2 // |
|
|
3 // kphilo.c |
|
|
4 // |
|
|
5 // A test of the dining philosophers problem |
|
|
6 // |
|
|
7 //========================================================================== |
|
|
8 //####COPYRIGHTBEGIN#### |
|
|
9 // |
|
|
10 // ------------------------------------------- |
|
|
11 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
12 // Version 1.0 (the "License"); you may not use this file except in |
|
|
13 // compliance with the License. You may obtain a copy of the License at |
|
|
14 // http://sourceware.cygnus.com/ecos |
|
|
15 // |
|
|
16 // Software distributed under the License is distributed on an "AS IS" |
|
|
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
18 // License for the specific language governing rights and limitations under |
|
|
19 // the License. |
|
|
20 // |
|
|
21 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
22 // September 30, 1998. |
|
|
23 // |
|
|
24 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
|
25 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. |
|
|
26 // ------------------------------------------- |
|
|
27 // |
|
|
28 //####COPYRIGHTEND#### |
|
|
29 //========================================================================== |
|
|
30 //#####DESCRIPTIONBEGIN#### |
|
|
31 // |
|
|
32 // Author(s): dsm |
|
|
33 // Contributors: dsm |
|
|
34 // Date: 1998-02-24 |
|
|
35 // Description: A test of the dining philosophers problem |
|
|
36 //####DESCRIPTIONEND#### |
|
|
37 // |
|
|
38 |
|
|
39 #include <cyg/kernel/kapi.h> |
|
|
40 |
|
|
41 #include <cyg/infra/cyg_ass.h> |
|
|
42 #include <cyg/kernel/diag.h> |
|
|
43 |
|
|
44 // ------------------------------------------------------------------------- |
|
|
45 // Data for the philosophers problem |
|
|
46 |
|
|
47 #define PHILOSOPHERS 15 // number of philosophers |
|
|
48 #define STACKSIZE (2*1024) // size of thread stack |
|
|
49 |
|
|
50 // array of stacks for philosopher threads |
|
|
51 char thread_stack[PHILOSOPHERS][STACKSIZE]; |
|
|
52 |
|
|
53 // array of threads. |
|
|
54 cyg_thread thread[PHILOSOPHERS]; |
|
|
55 |
|
|
56 cyg_handle_t thread_handle[PHILOSOPHERS]; |
|
|
57 |
|
|
58 // array of chopsticks |
|
|
59 cyg_sem_t chopstick[PHILOSOPHERS]; |
|
|
60 |
|
|
61 cyg_ucount32 data_index; |
|
|
62 |
|
|
63 // ------------------------------------------------------------------------- |
|
|
64 // State recording and display |
|
|
65 |
|
|
66 static char pstate[PHILOSOPHERS+1]; // state vector showing what each |
|
|
67 // philosopher is doing |
|
|
68 |
|
|
69 cyg_mutex_t state_mutex; |
|
|
70 |
|
|
71 #ifdef CYG_HAL_MN10300_MN103002 |
|
|
72 static cyg_count8 eaters = 0; |
|
|
73 #endif |
|
|
74 |
|
|
75 void change_state(int id, char newstate) |
|
|
76 { |
|
|
77 cyg_mutex_lock(&state_mutex); |
|
|
78 |
|
|
79 #ifdef CYG_HAL_MN10300_MN103002 |
|
|
80 if( pstate[id] == 'E' ) eaters--; |
|
|
81 if( newstate == 'E' ) eaters++; |
|
|
82 // led(eaters); |
|
|
83 #endif |
|
|
84 |
|
|
85 pstate[id] = newstate; |
|
|
86 |
|
|
87 diag_write_string(pstate); |
|
|
88 #if 0 |
|
|
89 diag_write_char(' '); |
|
|
90 diag_write_dec(Cyg_Scheduler::get_thread_switches()); |
|
|
91 #endif |
|
|
92 diag_write_char('\n'); |
|
|
93 |
|
|
94 cyg_mutex_unlock(&state_mutex); |
|
|
95 |
|
|
96 } |
|
|
97 |
|
|
98 char get_state( int id) |
|
|
99 { |
|
|
100 char s; |
|
|
101 cyg_mutex_lock(&state_mutex); |
|
|
102 |
|
|
103 s = pstate[id]; |
|
|
104 |
|
|
105 cyg_mutex_unlock(&state_mutex); |
|
|
106 |
|
|
107 return s; |
|
|
108 } |
|
|
109 |
|
|
110 // ------------------------------------------------------------------------- |
|
|
111 // Thread to behave like a philosopher |
|
|
112 |
|
|
113 void Philosopher( cyg_addrword_t vid ) |
|
|
114 { |
|
|
115 cyg_uint32 id = (cyg_uint32)vid; |
|
|
116 cyg_sem_t *first_stick = &chopstick[id]; |
|
|
117 cyg_sem_t *second_stick = &chopstick[(id+1)%PHILOSOPHERS]; |
|
|
118 #ifdef CYGPKG_INFRA_DEBUG |
|
|
119 int left_philo = ((id==0)?PHILOSOPHERS:id)-1; |
|
|
120 int right_philo = (id==PHILOSOPHERS-1)?0:(id+1); |
|
|
121 #endif |
|
|
122 |
|
|
123 CYG_ASSERT( id >= 0 && id < PHILOSOPHERS, "Bad id"); |
|
|
124 |
|
|
125 // Deadlock avoidance. The easiest way to make the philosophers |
|
|
126 // behave is to make each pick up the lowest numbered stick |
|
|
127 // first. This is how it works out anyway for all the philosophers |
|
|
128 // except the last, who must have his sticks swapped. |
|
|
129 |
|
|
130 if( id == PHILOSOPHERS-1 ) |
|
|
131 { |
|
|
132 cyg_sem_t *t = first_stick; |
|
|
133 first_stick = second_stick; |
|
|
134 second_stick = t; |
|
|
135 } |
|
|
136 |
|
|
137 for(;;) |
|
|
138 { |
|
|
139 cyg_ucount32 val; |
|
|
140 |
|
|
141 // The following variable is shared by all philosophers. |
|
|
142 // It is incremented unprotected, but this does not matter |
|
|
143 // since it is only present to introduce a little variability |
|
|
144 // into the think and eat times. |
|
|
145 |
|
|
146 static volatile int cycle = 0; |
|
|
147 |
|
|
148 // Think for a bit |
|
|
149 |
|
|
150 cyg_thread_delay((id+cycle++)%12); // Cogito ergo sum... |
|
|
151 |
|
|
152 // I am now hungry, try to get the chopsticks |
|
|
153 |
|
|
154 change_state(id,'H'); |
|
|
155 |
|
|
156 // Get the first stick |
|
|
157 cyg_semaphore_wait(first_stick); |
|
|
158 |
|
|
159 // Get the second stick |
|
|
160 cyg_semaphore_wait(second_stick); |
|
|
161 |
|
|
162 // Got them, now eat |
|
|
163 |
|
|
164 change_state(id,'E'); |
|
|
165 |
|
|
166 // Check that the world is as I think it is... |
|
|
167 cyg_semaphore_peek( first_stick, &val); |
|
|
168 CYG_ASSERT( val == 0, "Not got first stick"); |
|
|
169 cyg_semaphore_peek( second_stick, &val); |
|
|
170 CYG_ASSERT( val == 0, "Not got second stick"); |
|
|
171 CYG_ASSERT( get_state(left_philo) != 'E', "Left neighbour also eating!!"); |
|
|
172 CYG_ASSERT( get_state(right_philo) != 'E', "Right neighbour also eating!!"); |
|
|
173 |
|
|
174 cyg_thread_delay((id+cycle++)%6); // munch munch |
|
|
175 |
|
|
176 // Finished eating, put down sticks. |
|
|
177 |
|
|
178 change_state(id,'T'); |
|
|
179 |
|
|
180 cyg_semaphore_post( first_stick ); |
|
|
181 cyg_semaphore_post( second_stick ); |
|
|
182 |
|
|
183 } |
|
|
184 } |
|
|
185 |
|
|
186 // ------------------------------------------------------------------------- |
|
|
187 |
|
|
188 externC void |
|
|
189 cyg_start( void ) |
|
|
190 { |
|
|
191 int i; |
|
|
192 |
|
|
193 diag_init(); |
|
|
194 |
|
|
195 diag_write_string("Philosophers\n"); |
|
|
196 diag_write_string("Started\n"); |
|
|
197 |
|
|
198 // Zero last element in state so it acts like |
|
|
199 // a string. |
|
|
200 pstate[PHILOSOPHERS] = 0; |
|
|
201 |
|
|
202 #if 1 |
|
|
203 for( i = 0; i < PHILOSOPHERS; i++ ) |
|
|
204 { |
|
|
205 change_state(i,'T'); // starting state |
|
|
206 |
|
|
207 cyg_thread_create(4, Philosopher, (cyg_addrword_t)i, "philosopher", |
|
|
208 (void *)(&thread_stack[i]), STACKSIZE, |
|
|
209 &thread_handle[i], &thread[i]); |
|
|
210 |
|
|
211 // resume it |
|
|
212 cyg_thread_resume(thread_handle[i]); |
|
|
213 |
|
|
214 // and make the matching chopstick present |
|
|
215 cyg_semaphore_init( &chopstick[i], 1); |
|
|
216 } |
|
|
217 #endif |
|
|
218 |
|
|
219 // Get the world going |
|
|
220 cyg_scheduler_start(); |
|
|
221 |
|
|
222 } |
|
|
223 |
|
|
224 // ------------------------------------------------------------------------- |
|
|
225 // EOF kphilo.c |