comparison packages/kernel/current/tests/bin_sem2.cxx @ 0:3111d98ba7b3 ecos-v1_1-release

Initial commit of eCos version 1.1
author jlarmour
date Tue, 11 May 1999 11:16:07 +0000
parents
children 443894e2e912
comparison
equal deleted inserted replaced
-1:000000000000 0:3111d98ba7b3
1 //==========================================================================
2 //
3 // bin_sem2.cxx
4 //
5 // Binary semaphore test 2
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): nickg,dsm
33 // Contributors: dsm
34 // Date: 1998-03-10
35 // Description:
36 // Dining philosophers test. Based on philo.cxx
37 //####DESCRIPTIONEND####
38
39 #include <pkgconf/kernel.h>
40
41 #include <cyg/kernel/sched.hxx>
42 #include <cyg/kernel/thread.hxx>
43 #include <cyg/kernel/thread.inl>
44 #include <cyg/kernel/mutex.hxx>
45
46 #include <cyg/kernel/sema.hxx>
47
48 #include <cyg/infra/testcase.h>
49
50 #include <cyg/kernel/sched.inl>
51
52 #if defined(CYG_HAL_MIPS_SIM)
53 // Reduce number of loops in simulated TX39 so that
54 // it runs within the timeout.
55 #define PHILO_LOOPS 100
56 #else
57
58 #define PHILO_LOOPS 1000
59
60 #endif
61
62 #define PHILOSOPHERS 15
63 #define NTHREADS PHILOSOPHERS
64 #include "testaux.hxx"
65
66 static Cyg_Binary_Semaphore chopstick[PHILOSOPHERS];
67
68 static char pstate[PHILOSOPHERS+1]; // state of each philosopher
69
70 static cyg_ucount8 state_changes = 0;
71 // state_changes keep track of number of changes to pstate so
72 // we can exit after we've seen enough.
73
74
75 static Cyg_Mutex pstate_mutex;
76 static Cyg_Mutex cycle_mutex;
77
78 static inline int left(cyg_count8 i)
79 {
80 return (0 == i) ? PHILOSOPHERS-1 : i-1 ;
81 }
82 static inline int right(cyg_count8 i)
83 {
84 return (PHILOSOPHERS == i+1) ? 0 : i+1 ;
85 }
86
87 void change_state(int id, char newstate)
88 {
89 if (PHILO_LOOPS == state_changes++)
90 CYG_TEST_PASS_FINISH("Binary Semaphore 2 OK");
91
92
93 pstate_mutex.lock(); {
94 pstate[id] = newstate;
95 bool all_hungry = true; // until proved otherwise
96 for(cyg_ucount8 i=0; i < PHILOSOPHERS; i++) {
97 if('E' == pstate[i]) {
98 CHECK('E' != pstate[left(i)]);
99 CHECK('E' != pstate[right(i)]);
100 }
101 if('H' != pstate[i]) {
102 all_hungry = false;
103 }
104 }
105 // Theoretically it is possible for all the philosophers to be
106 // hungry but not waiting on semaphores. But in practice this
107 // means something is wrong.
108 CHECK(false == all_hungry);
109 } pstate_mutex.unlock();
110 }
111
112 char get_state(int id)
113 {
114 pstate_mutex.lock();
115
116 char s = pstate[id];
117
118 pstate_mutex.unlock();
119
120 return s;
121 }
122
123 // -------------------------------------------------------------------------
124 // Thread to behave like a philosopher
125
126 void Philosopher( CYG_ADDRESS id )
127 {
128 Cyg_Thread *self = Cyg_Thread::self();
129 Cyg_Binary_Semaphore *first_stick = &chopstick[id];
130 Cyg_Binary_Semaphore *second_stick = &chopstick[(id+1)%PHILOSOPHERS];
131
132 CHECK( id >= 0 && id < PHILOSOPHERS);
133
134 // Deadlock avoidance. The easiest way to make the philosophers
135 // behave is to make each pick up the lowest numbered stick
136 // first. This is how it works out anyway for all the philosophers
137 // except the last, who must have his sticks swapped.
138
139 if( id == PHILOSOPHERS-1 )
140 {
141 Cyg_Binary_Semaphore *t = first_stick;
142 first_stick = second_stick;
143 second_stick = t;
144 }
145
146
147 // The following variable is shared by all philosophers.
148 // It is incremented unprotected, but this does not matter
149 // since it is only present to introduce a little variability
150 // into the think and eat times.
151
152 static int cycle = 0;
153
154 for(;;)
155 {
156 // Think for a bit
157
158 self->delay((id+cycle++)%12); // Cogito ergo sum...
159
160 // I am now hungry, try to get the chopsticks
161 change_state(id,'H');
162
163 // Get the sticks
164 first_stick->wait();
165 second_stick->wait();
166
167 // Got them, now eat
168 change_state(id,'E');
169
170 // Check that the world is as I think it is...
171 CYG_TEST_CHECK( !first_stick->posted(),
172 "Not got first stick");
173 CYG_TEST_CHECK( !second_stick->posted(),
174 "Not got second stick");
175 CYG_TEST_CHECK( get_state(left(id)) != 'E',
176 "Left neighbour also eating!!");
177 CYG_TEST_CHECK( get_state(right(id)) != 'E',
178 "Right neighbour also eating!!");
179
180 self->delay((id+cycle++)%6); // munch munch
181
182 // Finished eating, put down sticks.
183
184 change_state(id,'T');
185
186 // put sticks back on table
187 first_stick->post();
188 second_stick->post();
189 }
190 }
191
192 // -------------------------------------------------------------------------
193
194 void bin_sem2_main( void )
195 {
196 CYG_TEST_INIT();
197
198 for( int i = 0; i < PHILOSOPHERS; i++ )
199 {
200 pstate[i] = 'T'; // starting state
201 new_thread(Philosopher, i);
202
203 // make the matching chopstick present
204 chopstick[i].post();
205 }
206
207 Cyg_Scheduler::scheduler.start();
208 }
209
210 externC void
211 cyg_start( void )
212 {
213 bin_sem2_main();
214 }
215 // EOF bin_sem2.cxx