diff 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
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/packages/kernel/current/tests/bin_sem2.cxx
@@ -0,0 +1,215 @@
+//==========================================================================
+//
+//        bin_sem2.cxx
+//
+//        Binary semaphore test 2
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//
+// -------------------------------------------
+// The contents of this file are subject to the Cygnus eCos Public License
+// Version 1.0 (the "License"); you may not use this file except in
+// compliance with the License.  You may obtain a copy of the License at
+// http://sourceware.cygnus.com/ecos
+// 
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the
+// License for the specific language governing rights and limitations under
+// the License.
+// 
+// The Original Code is eCos - Embedded Cygnus Operating System, released
+// September 30, 1998.
+// 
+// The Initial Developer of the Original Code is Cygnus.  Portions created
+// by Cygnus are Copyright (C) 1998 Cygnus Solutions.  All Rights Reserved.
+// -------------------------------------------
+//
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     nickg,dsm
+// Contributors:    dsm
+// Date:          1998-03-10
+// Description:
+//     Dining philosophers test.  Based on philo.cxx
+//####DESCRIPTIONEND####
+
+#include <pkgconf/kernel.h>
+
+#include <cyg/kernel/sched.hxx>
+#include <cyg/kernel/thread.hxx>
+#include <cyg/kernel/thread.inl>
+#include <cyg/kernel/mutex.hxx>
+
+#include <cyg/kernel/sema.hxx>
+
+#include <cyg/infra/testcase.h>
+
+#include <cyg/kernel/sched.inl>
+
+#if defined(CYG_HAL_MIPS_SIM)
+// Reduce number of loops in simulated TX39 so that
+// it runs within the timeout.
+#define PHILO_LOOPS     100   
+#else
+
+#define PHILO_LOOPS     1000
+ 
+#endif    
+
+#define PHILOSOPHERS 15
+#define NTHREADS PHILOSOPHERS
+#include "testaux.hxx"
+
+static Cyg_Binary_Semaphore chopstick[PHILOSOPHERS];
+
+static char pstate[PHILOSOPHERS+1];       // state of each philosopher
+
+static cyg_ucount8 state_changes = 0;
+// state_changes keep track of number of changes to pstate so
+// we can exit after we've seen enough.
+
+
+static Cyg_Mutex pstate_mutex;
+static Cyg_Mutex cycle_mutex;
+
+static inline int left(cyg_count8 i)
+{
+    return (0 == i) ? PHILOSOPHERS-1 : i-1 ;
+}
+static inline int right(cyg_count8 i)
+{
+    return (PHILOSOPHERS == i+1) ? 0 : i+1 ;
+}
+
+void change_state(int id, char newstate)
+{
+    if (PHILO_LOOPS == state_changes++) 
+        CYG_TEST_PASS_FINISH("Binary Semaphore 2 OK");
+    
+
+    pstate_mutex.lock(); {
+        pstate[id] = newstate;
+        bool all_hungry = true;         // until proved otherwise
+        for(cyg_ucount8 i=0; i < PHILOSOPHERS; i++) {
+            if('E' == pstate[i]) {
+                CHECK('E' != pstate[left(i)]);
+                CHECK('E' != pstate[right(i)]);
+            }
+            if('H' != pstate[i]) {
+                all_hungry = false;
+            }
+        }
+        // Theoretically it is possible for all the philosophers to be
+        // hungry but not waiting on semaphores.  But in practice this
+        // means something is wrong.
+        CHECK(false == all_hungry);        
+    } pstate_mutex.unlock();
+}
+
+char get_state(int id)
+{
+    pstate_mutex.lock();
+    
+    char s = pstate[id];
+
+    pstate_mutex.unlock();
+
+    return s;
+}
+
+// -------------------------------------------------------------------------
+// Thread to behave like a philosopher
+
+void Philosopher( CYG_ADDRESS id )
+{
+    Cyg_Thread *self = Cyg_Thread::self();
+    Cyg_Binary_Semaphore *first_stick = &chopstick[id];
+    Cyg_Binary_Semaphore *second_stick = &chopstick[(id+1)%PHILOSOPHERS];
+    
+    CHECK( id >= 0 && id < PHILOSOPHERS);
+
+    // Deadlock avoidance. The easiest way to make the philosophers
+    // behave is to make each pick up the lowest numbered stick
+    // first. This is how it works out anyway for all the philosophers
+    // except the last, who must have his sticks swapped.
+    
+    if( id == PHILOSOPHERS-1 )
+    {
+        Cyg_Binary_Semaphore *t = first_stick;
+        first_stick = second_stick;
+        second_stick = t;
+    }
+    
+    
+    // The following variable is shared by all philosophers.
+    // It is incremented unprotected, but this does not matter
+    // since it is only present to introduce a little variability
+    // into the think and eat times.
+    
+    static int cycle = 0;
+    
+    for(;;)
+    {
+        // Think for a bit
+
+        self->delay((id+cycle++)%12);    // Cogito ergo sum...
+
+        // I am now hungry, try to get the chopsticks
+        change_state(id,'H');
+
+        // Get the sticks
+        first_stick->wait();
+        second_stick->wait();
+
+        // Got them, now eat
+        change_state(id,'E');
+                
+        // Check that the world is as I think it is...
+        CYG_TEST_CHECK( !first_stick->posted(),
+                        "Not got first stick");
+        CYG_TEST_CHECK( !second_stick->posted(),
+                        "Not got second stick");
+        CYG_TEST_CHECK( get_state(left(id)) != 'E',
+                        "Left neighbour also eating!!");
+        CYG_TEST_CHECK( get_state(right(id)) != 'E',
+                        "Right neighbour also eating!!");
+        
+        self->delay((id+cycle++)%6);    // munch munch
+
+        // Finished eating, put down sticks.
+
+        change_state(id,'T');   
+
+        // put sticks back on table
+        first_stick->post();
+        second_stick->post();
+    }
+}
+
+// -------------------------------------------------------------------------
+
+void bin_sem2_main( void )
+{
+    CYG_TEST_INIT();
+
+    for( int i = 0; i < PHILOSOPHERS; i++ )
+    {
+        pstate[i] = 'T';            // starting state
+        new_thread(Philosopher, i);
+
+        // make the matching chopstick present
+        chopstick[i].post();
+    }
+    
+    Cyg_Scheduler::scheduler.start();
+}
+
+externC void
+cyg_start( void )
+{ 
+    bin_sem2_main();
+}
+// EOF bin_sem2.cxx