Mercurial > flash_v2
changeset 1062:e8b69d9c90a6
* 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.
| author | nickg |
|---|---|
| date | Mon, 23 Jun 2003 18:09:59 +0000 |
| parents | 13900936a2c4 |
| children | e54a552c19f9 |
| files | packages/kernel/current/ChangeLog packages/kernel/current/cdl/kernel.cdl packages/kernel/current/include/instrmnt.h packages/kernel/current/include/sema.hxx packages/kernel/current/src/sync/bin_sem.cxx packages/kernel/current/src/sync/cnt_sem.cxx packages/kernel/current/tests/bin_sem3.cxx |
| diffstat | 7 files changed, 249 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/kernel/current/ChangeLog +++ b/packages/kernel/current/ChangeLog @@ -1,3 +1,24 @@ +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
--- a/packages/kernel/current/cdl/kernel.cdl +++ b/packages/kernel/current/cdl/kernel.cdl @@ -322,7 +322,7 @@ cdl_package CYGPKG_KERNEL { 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" : "")
--- a/packages/kernel/current/include/instrmnt.h +++ b/packages/kernel/current/include/instrmnt.h @@ -190,6 +190,7 @@ externC char * cyg_instrument_msg(CYG_WO #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
--- a/packages/kernel/current/include/sema.hxx +++ b/packages/kernel/current/include/sema.hxx @@ -81,6 +81,10 @@ public: 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
--- a/packages/kernel/current/src/sync/bin_sem.cxx +++ b/packages/kernel/current/src/sync/bin_sem.cxx @@ -77,6 +77,7 @@ Cyg_Binary_Semaphore::Cyg_Binary_Semapho Cyg_Binary_Semaphore::~Cyg_Binary_Semaphore ( ) { + CYG_ASSERT( queue.empty(), "Destroying semaphore with waiting threads"); } // ------------------------------------------------------------------------- @@ -132,6 +133,84 @@ cyg_bool Cyg_Binary_Semaphore::wait() } // ------------------------------------------------------------------------- +// 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() {
--- a/packages/kernel/current/src/sync/cnt_sem.cxx +++ b/packages/kernel/current/src/sync/cnt_sem.cxx @@ -156,10 +156,12 @@ Cyg_Counting_Semaphore::wait( cyg_tick_c 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 ) {
new file mode 100644 --- /dev/null +++ b/packages/kernel/current/tests/bin_sem3.cxx @@ -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
