This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
Binary/Counting Semaphore Timeout Support
- From: Nick Garnett <nickg at ecoscentric dot com>
- To: ecos-patches at sources dot redhat dot com
- Date: 23 Jun 2003 19:14:31 +0100
- Subject: 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