Mercurial > ecos-v3_0-branch
diff packages/kernel/current/src/sync/bin_sem.cxx @ 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 | d2c90368aeef |
| children | 74dbf4c3f2e1 |
line wrap: on
line diff
--- 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() {
