1 //==========================================================================
5 // A test of the dining philosophers problem
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
46 // Description: A test of the dining philosophers problem
47 //####DESCRIPTIONEND####
50 #include <cyg/kernel/kernel.hxx>
52 #include <cyg/hal/hal_io.h>
54 // -------------------------------------------------------------------------
55 // Data for the philosophers problem
57 #define PHILOSOPHERS 15 // number of philosophers
58 #define STACKSIZE (2*1024) // size of thread stack
60 #define NTHREADS PHILOSOPHERS
61 #include "testaux.hxx"
63 // array of chopsticks
64 Cyg_Binary_Semaphore chopstick[PHILOSOPHERS];
67 //cyg_thread_entry Philosopher;
69 // -------------------------------------------------------------------------
70 // State recording and display
72 static char pstate[PHILOSOPHERS+1]; // state vector showing what each
73 // philosopher is doing
75 Cyg_Mutex state_mutex;
77 #ifdef CYG_HAL_MN10300_MN103002
78 static cyg_count8 eaters = 0;
81 void change_state(int id, char newstate)
83 CYG_INSTRUMENT_USER( 1, 0, 0);
85 CYG_INSTRUMENT_USER( 2, 0, 0);
87 #ifdef CYG_HAL_MN10300_MN103002
88 if( pstate[id] == 'E' ) eaters--;
89 if( newstate == 'E' ) eaters++;
93 pstate[id] = newstate;
95 diag_write_string(pstate);
98 diag_write_dec(Cyg_Scheduler::get_thread_switches());
100 diag_write_char('\n');
102 CYG_INSTRUMENT_USER( 3, 0, 0);
103 state_mutex.unlock();
104 CYG_INSTRUMENT_USER( 4, 0, 0);
108 char get_state( int id)
114 state_mutex.unlock();
119 // -------------------------------------------------------------------------
120 // Thread to behave like a philosopher
122 void Philosopher( CYG_ADDRESS id )
124 Cyg_Thread *self = Cyg_Thread::self();
125 Cyg_Binary_Semaphore *first_stick = &chopstick[id];
126 Cyg_Binary_Semaphore *second_stick = &chopstick[(id+1)%PHILOSOPHERS];
127 #ifdef CYGPKG_INFRA_DEBUG
128 int left_philo = ((id==0)?PHILOSOPHERS:id)-1;
129 int right_philo = (id==PHILOSOPHERS-1)?0:(id+1);
132 CYG_ASSERT( id >= 0 && id < PHILOSOPHERS, "Bad id");
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.
139 if( id == PHILOSOPHERS-1 )
141 Cyg_Binary_Semaphore *t = first_stick;
142 first_stick = second_stick;
146 // The following variable is shared by all philosophers.
147 // It is incremented unprotected, but this does not matter
148 // since it is only present to introduce a little variability
149 // into the think and eat times.
151 static int cycle = 0;
157 self->delay((id+cycle++)%12); // Cogito ergo sum...
159 // I am now hungry, try to get the chopsticks
161 change_state(id,'H');
163 // Get the first stick
164 CYG_INSTRUMENT_USER( 5, 0, 0);
166 CYG_INSTRUMENT_USER( 6, 0, 0);
168 // Get the second stick
169 CYG_INSTRUMENT_USER( 7, 0, 0);
170 second_stick->wait();
171 CYG_INSTRUMENT_USER( 8, 0, 0);
175 change_state(id,'E');
177 // Check that the world is as I think it is...
178 CYG_ASSERT( !first_stick->posted(), "Not got first stick");
179 CYG_ASSERT( !second_stick->posted(), "Not got second stick");
180 CYG_ASSERT( get_state(left_philo) != 'E', "Left neighbour also eating!!");
181 CYG_ASSERT( get_state(right_philo) != 'E', "Right neighbour also eating!!");
183 self->delay((id+cycle++)%6); // munch munch
185 // Finished eating, put down sticks.
187 change_state(id,'T');
189 CYG_INSTRUMENT_USER( 9, 0, 0);
191 CYG_INSTRUMENT_USER( 10, 0, 0);
192 second_stick->post();
193 CYG_INSTRUMENT_USER( 11, 0, 0);
195 // Cyg_Scheduler::lock();
196 // Cyg_Scheduler::unlock();
197 CYG_INSTRUMENT_USER( 12, 0, 0);
202 // -------------------------------------------------------------------------
207 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
208 cyg_hal_invoke_constructors();
212 diag_write_string("Philosophers\n");
213 diag_write_string("Started\n");
215 // Zero last element in state so it acts like
217 pstate[PHILOSOPHERS] = 0;
220 for( int i = 0; i < PHILOSOPHERS; i++ )
222 change_state(i,'T'); // starting state
224 // Start the philosopher
225 Cyg_Thread *t = new_thread( Philosopher, i );
230 // and make the matching chopstick present
235 // Get the world going
236 Cyg_Scheduler::scheduler.start();
240 // -------------------------------------------------------------------------