This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Binary/Counting Semaphore Timeout Support


This is David Brennan's patch of a few weeks ago, tweaked a little by
me (mainly in the ChangeLog) and with a suggested modification to the
counting semaphore semantics included.


Index: ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/ChangeLog,v
retrieving revision 1.102
diff -u -5 -r1.102 ChangeLog
--- ChangeLog	20 May 2003 08:56:42 -0000	1.102
+++ ChangeLog	23 Jun 2003 18:08:04 -0000
@@ -1,5 +1,26 @@
+2003-06-06  David Brennan  <eCos@brennanhome.com>
+2003-06-23  Nick Garnett  <nickg@balti.calivar.com>
+
+	* cdl/kernel.cdl: Added tests/bin_sem3 to list of kernel tests.
+
+	* include/sema.hxx: Added declaration for wait with timeout for
+        Cyg_Binary_Semaphore.
+	
+	* include/instrmnt.h: Added instrumentation point for binary semaphore
+        timeout.
+	
+        * src/sync/bin_sem.cxx: Added wait with time-out function to 
+        Cyg_Binary_Semaphore class. 
+
+	* src/sync/cnt_sem.cxx: Modified semantics slightly to claim an
+	available semaphore even with a timeout in the past. This is in
+	line with the new timed wait in bin_sem.cxx. 
+
+	* tests/bin_sem3.cxx: Created new test for timed wait binary
+        semaphore.
+		
 2003-05-20  Andrew Lunn  <andrew.lunn@ascom.ch>
 
 	* src/common/kapi.cxx (cyg_thread_get_next): Passing a *current
 	pointer as NULL if how you start the walk of the linked list. So
 	don't assert on NULL. Reported by Daniel Lidsten.
Index: cdl/kernel.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/cdl/kernel.cdl,v
retrieving revision 1.18
diff -u -5 -r1.18 kernel.cdl
--- cdl/kernel.cdl	24 Feb 2003 14:06:55 -0000	1.18
+++ cdl/kernel.cdl	23 Jun 2003 18:08:04 -0000
@@ -320,11 +320,11 @@
         cdl_option CYGPKG_KERNEL_TESTS {
             display "Kernel tests"
             flavor  data
             no_define
             calculated { 
-                "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/clock0 tests/clock1 tests/clockcnv tests/clocktruth tests/cnt_sem0 tests/cnt_sem1 tests/except1 tests/flag0 tests/flag1 tests/intr0 tests/kill tests/mbox1 tests/mqueue1 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/release tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2" 
+                "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/bin_sem3 tests/clock0 tests/clock1 tests/clockcnv tests/clocktruth tests/cnt_sem0 tests/cnt_sem1 tests/except1 tests/flag0 tests/flag1 tests/intr0 tests/kill tests/mbox1 tests/mqueue1 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/release tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2" 
                 . ((CYGFUN_KERNEL_API_C) ? " tests/kclock0 tests/kclock1 tests/kexcept1 tests/kflag0 tests/kflag1 tests/kintr0 tests/klock tests/kmbox1 tests/kmutex0 tests/kmutex1 tests/kmutex3 tests/kmutex4 tests/ksched1 tests/ksem0 tests/ksem1 tests/kthread0 tests/kthread1 tests/stress_threads tests/thread_gdb tests/timeslice tests/tm_basic tests/fptest" : "")
                 . ((!CYGPKG_INFRA_DEBUG && !CYGPKG_KERNEL_INSTRUMENT && CYGFUN_KERNEL_API_C) ? " tests/dhrystone" : "")
                 . ((CYGPKG_KERNEL_SMP_SUPPORT && CYGFUN_KERNEL_API_C) ? " tests/smp" : "")
                 . ((!CYGINT_HAL_TESTS_NO_CACHES && CYGFUN_KERNEL_API_C) ? " tests/kcache1 tests/kcache2" : "")
             }
Index: include/instrmnt.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/include/instrmnt.h,v
retrieving revision 1.11
diff -u -5 -r1.11 instrmnt.h
--- include/instrmnt.h	12 Dec 2002 18:31:44 -0000	1.11
+++ include/instrmnt.h	23 Jun 2003 18:08:05 -0000
@@ -188,10 +188,11 @@
 #define CYG_INSTRUMENT_EVENT_BINSEM_WAIT        2
 #define CYG_INSTRUMENT_EVENT_BINSEM_WOKE        3
 #define CYG_INSTRUMENT_EVENT_BINSEM_TRY         4
 #define CYG_INSTRUMENT_EVENT_BINSEM_POST        5
 #define CYG_INSTRUMENT_EVENT_BINSEM_WAKE        6
+#define CYG_INSTRUMENT_EVENT_BINSEM_TIMEOUT     7
 
 // Counting semaphore events
 #define CYG_INSTRUMENT_EVENT_CNTSEM_CLAIM       1
 #define CYG_INSTRUMENT_EVENT_CNTSEM_WAIT        2
 #define CYG_INSTRUMENT_EVENT_CNTSEM_WOKE        3
Index: include/sema.hxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/include/sema.hxx,v
retrieving revision 1.7
diff -u -5 -r1.7 sema.hxx
--- include/sema.hxx	23 May 2002 23:06:51 -0000	1.7
+++ include/sema.hxx	23 Jun 2003 18:08:05 -0000
@@ -79,10 +79,14 @@
 
     ~Cyg_Binary_Semaphore();            // Destructor
         
     cyg_bool    wait();                 // Wait until state == true
 
+#ifdef CYGFUN_KERNEL_THREADS_TIMER
+    cyg_bool    wait( cyg_tick_count timeout );
+#endif                                  // Wait until state == true or timeout
+
     cyg_bool    trywait();              // Set state false if possible
         
     void        post();                 // Increment count
 
     cyg_bool    posted();               // Get current state
Index: src/sync/bin_sem.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/src/sync/bin_sem.cxx,v
retrieving revision 1.7
diff -u -5 -r1.7 bin_sem.cxx
--- src/sync/bin_sem.cxx	23 May 2002 23:06:55 -0000	1.7
+++ src/sync/bin_sem.cxx	23 Jun 2003 18:08:06 -0000
@@ -75,10 +75,11 @@
 
 // -------------------------------------------------------------------------
 
 Cyg_Binary_Semaphore::~Cyg_Binary_Semaphore ( )
 {
+    CYG_ASSERT( queue.empty(), "Destroying semaphore with waiting threads");
 }
 
 // -------------------------------------------------------------------------
 
 cyg_bool Cyg_Binary_Semaphore::wait()
@@ -128,10 +129,88 @@
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
 
     return result;
 }
+
+// -------------------------------------------------------------------------
+// Wait until the state can be set false or timeout
+
+#ifdef CYGFUN_KERNEL_THREADS_TIMER
+
+cyg_bool
+Cyg_Binary_Semaphore::wait( cyg_tick_count timeout )
+{
+    cyg_bool result = true;
+    Cyg_Thread *self = Cyg_Thread::self();
+    
+    // Prevent preemption
+    Cyg_Scheduler::lock();
+
+    CYG_INSTRUMENT_BINSEM( CLAIM, this, state );
+        
+    // Set the timer _once_ outside the loop.
+    self->set_timer( timeout, Cyg_Thread::TIMEOUT  );
+
+    // If the timeout is in the past, the wake reason will have been
+    // set to something other than NONE already. If the semaphore is
+    // not available, set the result false to force an immediate
+    // return. If it is available, then go ahead and claim it.
+    
+    if( self->get_wake_reason() != Cyg_Thread::NONE && !state )
+        result = false;
+            
+    while ( !state && result ) {
+
+        // must reset the sleep reason every time
+        self->set_sleep_reason( Cyg_Thread::TIMEOUT );
+
+        self->sleep();
+
+        queue.enqueue( self );
+
+        CYG_INSTRUMENT_BINSEM( WAIT, this, 0 );
+
+        // Allow other threads to run
+        Cyg_Scheduler::reschedule();
+
+        CYG_INSTRUMENT_BINSEM( WOKE, this, state );
+
+        switch( self->get_wake_reason() )
+        {
+        case Cyg_Thread::TIMEOUT:
+            result = false;
+            CYG_INSTRUMENT_BINSEM( TIMEOUT, this, state);
+            break;
+            
+        case Cyg_Thread::DESTRUCT:
+        case Cyg_Thread::BREAK:
+            result = false;
+            break;
+            
+        case Cyg_Thread::EXIT:            
+            self->exit();
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    // Clear the timeout. It is irrelevant whether the alarm has
+    // actually gone off or not.
+    self->clear_timer();
+        
+    if( result ) state = false;
+
+    // Unlock the scheduler and maybe switch threads
+    Cyg_Scheduler::unlock();
+
+    return result;
+}
+
+#endif // CYGFUN_KERNEL_THREADS_TIMER
 
 // -------------------------------------------------------------------------
 
 cyg_bool Cyg_Binary_Semaphore::trywait()
 {
Index: src/sync/cnt_sem.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/src/sync/cnt_sem.cxx,v
retrieving revision 1.7
diff -u -5 -r1.7 cnt_sem.cxx
--- src/sync/cnt_sem.cxx	23 May 2002 23:06:55 -0000	1.7
+++ src/sync/cnt_sem.cxx	23 Jun 2003 18:08:06 -0000
@@ -154,14 +154,16 @@
         
     // Set the timer _once_ outside the loop.
     self->set_timer( timeout, Cyg_Thread::TIMEOUT  );
 
     // If the timeout is in the past, the wake reason will have been
-    // set to something other than NONE already. Set the result false
-    // to force an immediate return.
+    // set to something other than NONE already. If the count is zero,
+    // set the result false to force an immediate return. If the count
+    // is non-zero, then this wait will succeed anyway.
     
-    if( self->get_wake_reason() != Cyg_Thread::NONE )
+    if( self->get_wake_reason() != Cyg_Thread::NONE &&
+        0 == count )
         result = false;
             
     while ( 0 == count && result ) {
 
         // must reset the sleep reason every time
Index: tests/bin_sem3.cxx
===================================================================
RCS file: tests/bin_sem3.cxx
diff -N tests/bin_sem3.cxx
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/bin_sem3.cxx	23 Jun 2003 18:08:06 -0000
@@ -0,0 +1,138 @@
+//==========================================================================
+//
+//        bin_sem3.cxx
+//
+//        Binary semaphore test 3
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     David Brennan
+// Contributors:  David Brennan
+// Date:          2003-06-06
+// Description:   Tests basic binary semaphore timeout functionality.
+//####DESCRIPTIONEND####
+
+#include <pkgconf/kernel.h>
+
+#include <cyg/kernel/sched.hxx>        // Cyg_Scheduler::start()
+#include <cyg/kernel/thread.hxx>       // Cyg_Thread
+#include <cyg/kernel/thread.inl>
+
+#include <cyg/kernel/sema.hxx>
+
+#include <cyg/infra/testcase.h>
+
+#include <cyg/kernel/sched.inl>
+
+#define NTHREADS 2
+
+#include "testaux.hxx"
+
+static Cyg_Binary_Semaphore s0(true), s1(false), s2;
+
+static volatile cyg_ucount8 q = 0;
+
+static void entry0( CYG_ADDRWORD data )
+{
+    s0.wait();
+    CHECK( 0 == q++ );
+    s1.post();
+    s0.wait();
+    CHECK( 2 == q++ );
+    CHECK( ! s0.posted() );
+#ifndef CYGFUN_KERNEL_THREADS_TIMER
+    CHECK( ! s0.trywait() );
+#else // !CYGFUN_KERNEL_THREADS_TIMER
+    CHECK( ! s0.wait(10) );
+#endif // !CYGFUN_KERNEL_THREADS_TIMER
+    s0.post();
+    CHECK( 3 == q++ );
+    CHECK( s0.posted() );
+    s1.post();
+    CHECK( ! s2.posted() );
+    s2.wait();
+    CHECK( 5 == q++ );
+    CYG_TEST_PASS_FINISH("Binary Semaphore 3 OK");
+}
+
+static void entry1( CYG_ADDRWORD data )
+{
+    CHECK( s1.posted() );
+    s1.wait();
+    CHECK( 1 == q++ );
+    CHECK( ! s0.posted() );
+    s0.post();
+    s1.wait();
+    CHECK( 4 == q++ );
+    CHECK( s0.posted() );
+#ifndef CYGFUN_KERNEL_THREADS_TIMER
+    CHECK( s0.trywait() );
+#else // !CYGFUN_KERNEL_THREADS_TIMER
+    CHECK( s0.wait(10) );
+#endif // !CYGFUN_KERNEL_THREADS_TIMER
+    CHECK( ! s0.posted() );
+    s2.post();
+    s0.wait();
+    CYG_TEST_FAIL_FINISH("Not reached");
+}
+
+void bin_sem3_main( void )
+{
+    CYG_TEST_INIT();
+
+    new_thread( entry0, 0);
+    new_thread( entry1, 1);
+    
+#ifdef CYGIMP_THREAD_PRIORITY
+    thread[0]->set_priority( 4 );
+    thread[1]->set_priority( 5 ); // make sure the threads execute as intended
+#endif
+
+    Cyg_Scheduler::start();
+    
+    CYG_TEST_FAIL_FINISH("Not reached");
+}
+
+externC void
+cyg_start( void )
+{ 
+#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
+    cyg_hal_invoke_constructors();
+#endif
+    bin_sem3_main();
+}
+// EOF bin_sem1.cxx


-- 
Nick Garnett                    eCos Kernel Architect
http://www.ecoscentric.com/     The eCos and RedBoot experts


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]