OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/rtos/ecos-2.0/packages/kernel/v2_0/src/sync
    from Rev 27 to Rev 174
    Reverse comparison

Rev 27 → Rev 174

/mqueue.cxx
0,0 → 1,65
//==========================================================================
//
// sync/mqueue.cxx
//
// Mqueue message queue non-inline implementation
//
//==========================================================================
//####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): jlarmour
// Contributors:
// Date: 2001-10-12
// Purpose: Non-inlined implementation of mqueue message queue.
// Description: This file contains the non-inlined instantiations of the
// mqueue message queue implementation functions.
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
#include <pkgconf/kernel.h>
 
#ifdef CYGIMP_KERNEL_SYNCH_MQUEUE_NOT_INLINE
 
#define CYGPRI_KERNEL_SYNCH_MQUEUE_INLINE
#include <cyg/kernel/mqueue.hxx>
#include <cyg/kernel/mqueue.inl>
 
#endif
 
// -------------------------------------------------------------------------
// EOF sync/mqueue.cxx
/mutex.cxx
0,0 → 1,863
//==========================================================================
//
// sync/mutex.cxx
//
// Mutex and condition variable implementation
//
//==========================================================================
//####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): nickg
// Contributors: nickg, jlarmour
// Date: 1999-02-17
// Purpose: Mutex implementation
// Description: This file contains the implementations of the mutex
// and condition variable classes.
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/ktypes.h> // base kernel types
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <cyg/kernel/instrmnt.h> // instrumentation
 
#include <cyg/kernel/mutex.hxx> // our header
 
#include <cyg/kernel/thread.inl> // thread inlines
#include <cyg/kernel/sched.inl> // scheduler inlines
#include <cyg/kernel/clock.inl> // clock inlines
 
// -------------------------------------------------------------------------
// Mutex protocol test macros.
// If the dynamic protocol option is enabled, then these generate appropriate
// tests on the protocol field. If there is no dynamic choice then they simply
// result in empty statements.
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
 
#define IF_PROTOCOL_INHERIT if( protocol == INHERIT )
#define IF_PROTOCOL_CEILING if( protocol == CEILING )
#define IF_PROTOCOL_ACTIVE if( protocol != NONE )
 
#else
 
#define IF_PROTOCOL_INHERIT
#define IF_PROTOCOL_CEILING
#define IF_PROTOCOL_ACTIVE
 
#endif
 
// -------------------------------------------------------------------------
// Constructor
 
Cyg_Mutex::Cyg_Mutex()
{
CYG_REPORT_FUNCTION();
locked = false;
owner = NULL;
 
#if defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT) && \
defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC)
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_INHERIT
protocol = INHERIT;
#endif
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_CEILING
protocol = CEILING;
ceiling = CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY;
#endif
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_NONE
protocol = NONE;
#endif
 
#else // not (DYNAMIC and DEFAULT defined)
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY
 
// if there is a default priority ceiling defined, use that to initialize
// the ceiling.
ceiling = CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY;
 
#else
 
// Otherwise set it to zero.
ceiling = 0;
#endif
#endif
 
#endif // DYNAMIC and DEFAULT defined
CYG_REPORT_RETURN();
}
 
// -------------------------------------------------------------------------
// Construct with defined protocol
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
 
Cyg_Mutex::Cyg_Mutex( cyg_protcol protocol_arg )
{
CYG_REPORT_FUNCTION();
locked = false;
owner = NULL;
 
protocol = protocol_arg;
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY
 
// if there is a default priority ceiling defined, use that to initialize
// the ceiling.
ceiling = CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY;
 
#else
 
// Otherwise set it to zero.
ceiling = 0;
#endif
#endif
CYG_REPORT_RETURN();
}
 
#endif
 
// -------------------------------------------------------------------------
// Destructor
 
Cyg_Mutex::~Cyg_Mutex()
{
CYG_REPORT_FUNCTION();
CYG_ASSERT( owner == NULL, "Deleting mutex with owner");
CYG_ASSERT( queue.empty(), "Deleting mutex with waiting threads");
CYG_REPORT_RETURN();
}
 
// -------------------------------------------------------------------------
 
#ifdef CYGDBG_USE_ASSERTS
 
cyg_bool
Cyg_Mutex::check_this( cyg_assert_class_zeal zeal) const
{
// CYG_REPORT_FUNCTION();
// check that we have a non-NULL pointer first
if( this == NULL ) return false;
switch( zeal )
{
case cyg_system_test:
case cyg_extreme:
case cyg_thorough:
case cyg_quick:
case cyg_trivial:
if( locked && owner == NULL ) return false;
if( !locked && owner != NULL ) return false;
case cyg_none:
default:
break;
};
 
return true;
}
 
#endif
 
// -------------------------------------------------------------------------
// Lock and/or wait
 
cyg_bool
Cyg_Mutex::lock(void)
{
CYG_REPORT_FUNCTYPE("returning %d");
 
cyg_bool result = true;
Cyg_Thread *self = Cyg_Thread::self();
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_INSTRUMENT_MUTEX(LOCK, this, 0);
 
// Loop while the mutex is locked, sleeping each time around
// the loop. This copes with the possibility of a higher priority
// thread grabbing the mutex between the wakeup in unlock() and
// this thread actually starting.
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL
 
IF_PROTOCOL_ACTIVE
self->count_mutex();
 
#endif
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
IF_PROTOCOL_CEILING
self->set_priority_ceiling(ceiling);
 
#endif
while( locked && result )
{
CYG_ASSERT( self != owner, "Locking mutex I already own");
self->set_sleep_reason( Cyg_Thread::WAIT );
self->sleep();
queue.enqueue( self );
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
 
IF_PROTOCOL_INHERIT
owner->inherit_priority(self);
 
#endif
 
CYG_INSTRUMENT_MUTEX(WAIT, this, 0);
 
// Allow other threads to run
Cyg_Scheduler::reschedule();
CYG_ASSERTCLASS( this, "Bad this pointer");
 
switch( self->get_wake_reason() )
{
case Cyg_Thread::DESTRUCT:
case Cyg_Thread::BREAK:
result = false;
break;
case Cyg_Thread::EXIT:
self->exit();
break;
 
default:
break;
}
 
}
 
if( result )
{
locked = true;
owner = self;
 
CYG_INSTRUMENT_MUTEX(LOCKED, this, 0);
}
else
{
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL
 
IF_PROTOCOL_ACTIVE
self->uncount_mutex();
 
#endif
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
 
IF_PROTOCOL_INHERIT
self->disinherit_priority();
 
#endif
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
 
IF_PROTOCOL_CEILING
self->clear_priority_ceiling();
 
#endif
}
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
 
CYG_ASSERTCLASS( this, "Bad this pointer");
 
CYG_REPORT_RETVAL(result);
 
return result;
}
 
// -------------------------------------------------------------------------
// Try to lock and return success
 
cyg_bool
Cyg_Mutex::trylock(void)
{
CYG_REPORT_FUNCTYPE("returning %d");
CYG_ASSERTCLASS( this, "Bad this pointer");
cyg_bool result = true;
// Prevent preemption
Cyg_Scheduler::lock();
 
// If the mutex is not locked, grab it
// for ourself. Otherwise return failure.
if( !locked )
{
Cyg_Thread *self = Cyg_Thread::self();
locked = true;
owner = self;
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL
 
IF_PROTOCOL_ACTIVE
self->count_mutex();
 
#endif
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
 
IF_PROTOCOL_CEILING
self->set_priority_ceiling(ceiling);
#endif
}
else result = false;
 
CYG_INSTRUMENT_MUTEX(TRY, this, result);
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
CYG_REPORT_RETVAL(result);
return result;
}
 
// -------------------------------------------------------------------------
// unlock
 
void
Cyg_Mutex::unlock(void)
{
CYG_REPORT_FUNCTION();
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_MUTEX(UNLOCK, this, 0);
 
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_ASSERT( locked, "Unlock mutex that is not locked");
CYG_ASSERT( owner == Cyg_Thread::self(), "Unlock mutex I do not own");
if( !queue.empty() ) {
 
// The queue is non-empty, so grab the next
// thread from it and wake it up.
 
Cyg_Thread *thread = queue.dequeue();
 
CYG_ASSERTCLASS( thread, "Bad thread pointer");
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
 
// Give the owner-to-be a chance to inherit from the remaining
// queue or the relinquishing thread:
 
IF_PROTOCOL_INHERIT
thread->relay_priority(owner, &queue);
 
#endif
 
thread->set_wake_reason( Cyg_Thread::DONE );
thread->wake();
 
CYG_INSTRUMENT_MUTEX(WAKE, this, thread);
}
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL
 
IF_PROTOCOL_ACTIVE
owner->uncount_mutex();
 
#endif
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
 
IF_PROTOCOL_INHERIT
owner->disinherit_priority();
#endif
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
 
IF_PROTOCOL_CEILING
owner->clear_priority_ceiling();
#endif
locked = false;
owner = NULL;
CYG_ASSERTCLASS( this, "Bad this pointer");
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
 
CYG_REPORT_RETURN();
}
 
// -------------------------------------------------------------------------
// Release all waiting threads.
 
void Cyg_Mutex::release()
{
CYG_REPORT_FUNCTION();
 
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_MUTEX(RELEASE, this, 0);
 
CYG_ASSERTCLASS( this, "Bad this pointer");
while( !queue.empty() )
{
// The queue is non-empty, so grab each
// thread from it and release it.
 
Cyg_Thread *thread = queue.dequeue();
 
CYG_ASSERTCLASS( thread, "Bad thread pointer");
 
thread->release();
 
CYG_INSTRUMENT_MUTEX(RELEASED, this, thread);
}
 
CYG_ASSERTCLASS( this, "Bad this pointer");
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
 
CYG_REPORT_RETURN();
}
 
// -------------------------------------------------------------------------
// Set ceiling priority for priority ceiling protocol
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
 
void Cyg_Mutex::set_ceiling( cyg_priority priority )
{
CYG_REPORT_FUNCTION();
 
// CYG_ASSERT( priority >= CYG_THREAD_MAX_PRIORITY, "Priority out of range");
// CYG_ASSERT( priority <= CYG_THREAD_MIN_PRIORITY, "Priority out of range");
// Prevent preemption
Cyg_Scheduler::lock();
 
ceiling = priority;
// Unlock the scheduler
Cyg_Scheduler::unlock();
 
CYG_REPORT_RETURN();
}
 
#endif
 
// -------------------------------------------------------------------------
// Set priority inversion protocol
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
void Cyg_Mutex::set_protocol( cyg_protcol new_protocol )
{
CYG_REPORT_FUNCTION();
 
// Prevent preemption
Cyg_Scheduler::lock();
protocol = new_protocol;
// Unlock the scheduler
Cyg_Scheduler::unlock();
CYG_REPORT_RETURN();
}
 
#endif
 
 
//==========================================================================
// Condition variables
 
Cyg_Condition_Variable::Cyg_Condition_Variable(
Cyg_Mutex &mx // linked mutex
)
{
CYG_REPORT_FUNCTION();
mutex = &mx;
 
CYG_ASSERTCLASS( mutex, "Invalid mutex argument");
 
CYG_REPORT_RETURN();
}
 
Cyg_Condition_Variable::Cyg_Condition_Variable()
{
CYG_REPORT_FUNCTION();
mutex = NULL;
 
CYG_REPORT_RETURN();
}
 
// -------------------------------------------------------------------------
// Destructor
 
Cyg_Condition_Variable::~Cyg_Condition_Variable()
{
CYG_REPORT_FUNCTION();
CYG_ASSERT( queue.empty(), "Deleting condvar with waiting threads");
 
CYG_REPORT_RETURN();
}
 
// -------------------------------------------------------------------------
 
#ifdef CYGDBG_USE_ASSERTS
 
cyg_bool
Cyg_Condition_Variable::check_this( cyg_assert_class_zeal zeal) const
{
bool result = true;
 
CYG_REPORT_FUNCTYPE("returning %d");
CYG_REPORT_FUNCARG1("zeal = %d", zeal);
// check that we have a non-NULL pointer first
if( this == NULL )
result = false;
else {
switch( zeal )
{
case cyg_system_test:
case cyg_extreme:
case cyg_thorough:
if( mutex != NULL && !mutex->check_this(zeal) )
result = false;
case cyg_quick:
case cyg_trivial:
case cyg_none:
default:
break;
}
}
 
CYG_REPORT_RETVAL(result);
return result;
}
 
#endif
 
// -------------------------------------------------------------------------
// Wait for condition to be true
// Note: if this function is entered with the scheduler locked (e.g. to
// suspend DSR processing) then there is no need to take the lock. Also
// in this case, exit with the scheduler locked, which allows this function
// to be used in a totally thread-safe manner.
 
cyg_bool
Cyg_Condition_Variable::wait_inner( Cyg_Mutex *mx )
{
CYG_REPORT_FUNCTION();
 
cyg_bool result = true;
Cyg_Thread *self = Cyg_Thread::self();
 
Cyg_Scheduler::lock();
 
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_ASSERTCLASS( mx, "Corrupt mutex");
CYG_ASSERTCLASS( self, "Bad self thread");
 
CYG_INSTRUMENT_CONDVAR(WAIT, this, 0);
mx->unlock();
 
self->set_sleep_reason( Cyg_Thread::WAIT );
self->sleep();
queue.enqueue( self );
 
// Avoid calling ASRs during the following unlock.
self->set_asr_inhibit();
// Unlock the scheduler and switch threads
Cyg_Scheduler::unlock_reschedule();
 
// Allow ASRs again
self->clear_asr_inhibit();
CYG_INSTRUMENT_CONDVAR(WOKE, this, self->get_wake_reason());
 
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_ASSERTCLASS( mx, "Corrupt mutex");
 
switch( self->get_wake_reason() )
{
case Cyg_Thread::DESTRUCT: // which, the cv or the mutex?
case Cyg_Thread::BREAK:
result = false;
break;
case Cyg_Thread::EXIT:
self->exit();
break;
 
default:
break;
}
 
// When we awake, we must re-acquire the mutex. Note that while
// it is essential to release the mutex and queue on the CV
// atomically relative to other threads, to avoid races, it is not
// necessary for us to re-acquire the mutex in the same atomic
// action. Hence we can do it after unlocking the scheduler.
// We need to loop here in case the thread is released while waiting
// for the mutex. It is essential that we exit this function with the
// mutex claimed.
 
while ( !mx->lock() )
continue;
 
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_ASSERTCLASS( mx, "Corrupt mutex");
CYG_ASSERT( mx->owner == self, "Not mutex owner");
 
CYG_REPORT_RETURN();
 
return result;
}
 
// -------------------------------------------------------------------------
// Wake one thread
 
void
Cyg_Condition_Variable::signal(void)
{
CYG_REPORT_FUNCTION();
CYG_ASSERTCLASS( this, "Bad this pointer");
 
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_CONDVAR(SIGNAL, this, 0);
if( !queue.empty() )
{
// The queue is non-empty, so grab the next
// thread from it and wake it up.
 
Cyg_Thread *thread = queue.dequeue();
 
CYG_ASSERTCLASS( thread, "Bad thread pointer");
thread->set_wake_reason( Cyg_Thread::DONE );
thread->wake();
 
CYG_INSTRUMENT_CONDVAR(WAKE, this, thread);
}
CYG_ASSERTCLASS( this, "Bad this pointer");
 
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
 
CYG_REPORT_RETURN();
}
 
// -------------------------------------------------------------------------
// Set cond true, wake all threads
 
void
Cyg_Condition_Variable::broadcast(void)
{
CYG_REPORT_FUNCTION();
CYG_ASSERTCLASS( this, "Bad this pointer");
 
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_CONDVAR(BROADCAST, this, 0);
// Grab all the threads from the queue and let them
// go.
while( !queue.empty() )
{
Cyg_Thread *thread = queue.dequeue();
 
CYG_ASSERTCLASS( thread, "Bad thread pointer");
thread->set_wake_reason( Cyg_Thread::DONE );
thread->wake();
 
CYG_INSTRUMENT_CONDVAR(WAKE, this, thread);
}
CYG_ASSERTCLASS( this, "Bad this pointer");
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
 
CYG_REPORT_RETURN();
}
 
// -------------------------------------------------------------------------
// Optional timed wait on a CV
 
#if defined(CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT)
 
cyg_bool
Cyg_Condition_Variable::wait_inner( Cyg_Mutex *mx, cyg_tick_count timeout )
{
CYG_REPORT_FUNCTYPE("returning %d");
CYG_REPORT_FUNCARG1("timeout = %d", timeout);
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_ASSERTCLASS( mx, "Corrupt mutex");
 
cyg_bool result = true;
Cyg_Thread *self = Cyg_Thread::self();
 
CYG_ASSERTCLASS( self, "Bad self thread");
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_CONDVAR(TIMED_WAIT, this, 0 );
mx->unlock();
 
// The ordering of sleep() and set_timer() here are
// important. If the timeout is in the past, the thread
// will be woken up immediately and will not sleep.
self->sleep();
// Set the timer and sleep reason
self->set_timer( timeout, Cyg_Thread::TIMEOUT );
 
// Only enqueue if the timeout has not already fired.
if( self->get_wake_reason() == Cyg_Thread::NONE )
queue.enqueue( self );
 
// Avoid calling ASRs during the following unlock.
self->set_asr_inhibit();
// Unlock the scheduler and switch threads
Cyg_Scheduler::unlock_reschedule();
 
// Allow ASRs again
self->clear_asr_inhibit();
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_ASSERTCLASS( mx, "Corrupt mutex");
self->clear_timer();
 
CYG_INSTRUMENT_CONDVAR(WOKE, this, self->get_wake_reason());
switch( self->get_wake_reason() )
{
case Cyg_Thread::TIMEOUT:
case Cyg_Thread::DESTRUCT: // which, the cv or the mutex?
case Cyg_Thread::BREAK:
result = false;
break;
case Cyg_Thread::EXIT:
self->exit();
break;
 
default:
break;
}
 
// When we awake, we must re-acquire the mutex. Note that while
// it is essential to release the mutex and queue on the CV
// atomically relative to other threads, to avoid races, it is not
// necessary for us to re-acquire the mutex in the same atomic
// action. Hence we can do it after unlocking the scheduler.
 
while ( !mx->lock() )
continue;
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_ASSERTCLASS( mx, "Corrupt mutex");
 
CYG_REPORT_RETVAL(result);
return result;
}
 
#endif
 
 
// -------------------------------------------------------------------------
// EOF sync/mutex.cxx
/mbox.cxx
0,0 → 1,170
//==========================================================================
//
// mbox.cxx
//
// Mbox mbox template class implementation
//
//==========================================================================
//####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): hmt
// Contributors: hmt
// Date: 1998-02-11
// Purpose: Mbox implementation
// Description: This file contains the implementations of the mbox class
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/ktypes.h> // base kernel types
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <cyg/kernel/instrmnt.h> // instrumentation
 
#include <cyg/kernel/thread.inl> // Cyg_Thread inlines
 
#include <cyg/kernel/mbox.hxx> // our own header
 
#ifndef CYGIMP_MBOXT_INLINE // force inlining
#define CYGIMP_MBOXT_INLINE // of implementation
#endif
 
#ifdef CYGIMP_MBOX_USE_MBOXT_PLAIN
#include <cyg/kernel/mboxt.inl> // mbox template implementation
#else
#include <cyg/kernel/mboxt2.inl> // mbox template implementation
#endif
 
// -------------------------------------------------------------------------
// This module exists to cause exactly one instance of these functions to
// exist; this is just like a vanilla class, except we use the template
// class to acquire an implementation. The template functions are inlined
// in each of these methods.
 
 
// -------------------------------------------------------------------------
// Constructor
 
Cyg_Mbox::Cyg_Mbox()
{
}
 
// -------------------------------------------------------------------------
// Destructor
 
Cyg_Mbox::~Cyg_Mbox()
{
}
 
// -------------------------------------------------------------------------
// debugging/assert function
 
#ifdef CYGDBG_USE_ASSERTS
cyg_bool
Cyg_Mbox::check_this(cyg_assert_class_zeal zeal) const
{
return m.check_this(zeal);
}
#endif
 
// -------------------------------------------------------------------------
// now the members themselves:
void *
Cyg_Mbox::get()
{
void * p;
if ( ! m.get( p ) )
return NULL;
return p;
}
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
void *
Cyg_Mbox::get( cyg_tick_count timeout )
{
void * p;
if ( ! m.get( p, timeout ) )
return NULL;
return p;
}
#endif
 
void *
Cyg_Mbox::tryget()
{
void * p;
if ( ! m.tryget( p ) )
return NULL;
return p;
}
 
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
cyg_bool
Cyg_Mbox::put( void *item )
{
return m.put( item );
}
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
cyg_bool
Cyg_Mbox::put( void *item, cyg_tick_count timeout )
{
return m.put( item, timeout );
}
#endif
#endif // CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
 
cyg_bool
Cyg_Mbox::tryput( void *item )
{
return m.tryput( item );
}
 
void *
Cyg_Mbox::peek_item() // Get next item to be returned
{
void *p;
if ( ! m.peek_item( p ) )
return NULL;
return p;
}
 
// -------------------------------------------------------------------------
// EOF mbox.cxx
/cnt_sem.cxx
0,0 → 1,281
//==========================================================================
//
// sync/cnt_sem.cxx
//
// Counting semaphore implementation
//
//==========================================================================
//####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): nickg
// Contributors: nickg
// Date: 1997-09-24
// Purpose: Cyg_Counting_Semaphore implementation
// Description: This file contains the implementations of the counting semaphore
// class.
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/ktypes.h> // base kernel types
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <cyg/kernel/instrmnt.h> // instrumentation
 
#include <cyg/kernel/thread.inl> // Cyg_Thread inlines
 
#include <cyg/kernel/sema.hxx> // our header
 
#include <cyg/kernel/sched.inl> // scheduler inlines
 
// -------------------------------------------------------------------------
// Constructor
 
Cyg_Counting_Semaphore::Cyg_Counting_Semaphore(
cyg_count32 init_count // Initial count value
)
{
count = init_count;
}
 
// -------------------------------------------------------------------------
// Destructor
 
Cyg_Counting_Semaphore::~Cyg_Counting_Semaphore()
{
CYG_ASSERT( queue.empty(), "Destroying semaphore with waiting threads");
}
// -------------------------------------------------------------------------
// Wait until the count can be decremented without it becoming
// negative.
 
cyg_bool Cyg_Counting_Semaphore::wait()
{
cyg_bool result = true;
Cyg_Thread *self = Cyg_Thread::self();
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_CNTSEM( CLAIM, this, count );
while( count == 0 && result )
{
self->set_sleep_reason( Cyg_Thread::WAIT );
self->sleep();
queue.enqueue( self );
 
CYG_INSTRUMENT_CNTSEM( WAIT, this, 0 );
 
// Allow other threads to run
Cyg_Scheduler::reschedule();
 
CYG_INSTRUMENT_CNTSEM( WOKE, this, count );
 
switch( self->get_wake_reason() )
{
case Cyg_Thread::DESTRUCT:
case Cyg_Thread::BREAK:
result = false;
break;
case Cyg_Thread::EXIT:
self->exit();
break;
 
default:
break;
}
}
 
if( result ) count--;
// Unlock the scheduler
Cyg_Scheduler::unlock();
 
return result;
}
 
// -------------------------------------------------------------------------
// Wait until the count can be decremented without it becoming
// negative.
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
 
cyg_bool
Cyg_Counting_Semaphore::wait( cyg_tick_count timeout )
{
cyg_bool result = true;
Cyg_Thread *self = Cyg_Thread::self();
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_CNTSEM( CLAIM, this, count );
// 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.
if( self->get_wake_reason() != Cyg_Thread::NONE )
result = false;
while ( 0 == count && result ) {
 
// must reset the sleep reason every time
self->set_sleep_reason( Cyg_Thread::TIMEOUT );
 
self->sleep();
 
queue.enqueue( self );
 
CYG_INSTRUMENT_CNTSEM( WAIT, this, 0 );
 
// Allow other threads to run
Cyg_Scheduler::reschedule();
 
CYG_INSTRUMENT_CNTSEM( WOKE, this, count );
 
switch( self->get_wake_reason() )
{
case Cyg_Thread::TIMEOUT:
result = false;
CYG_INSTRUMENT_CNTSEM( TIMEOUT, this, count);
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 ) count--;
 
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
 
return result;
}
 
#endif // CYGFUN_KERNEL_THREADS_TIMER
 
// -------------------------------------------------------------------------
// Try to decrement, but fail if not possible
 
cyg_bool Cyg_Counting_Semaphore::trywait()
{
cyg_bool result = true;
// Prevent preemption
Cyg_Scheduler::lock();
 
if( count > 0 ) count--;
else result = false;
 
CYG_INSTRUMENT_CNTSEM( TRY, this, result );
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
return result;
}
// -------------------------------------------------------------------------
// Increment count
 
void Cyg_Counting_Semaphore::post()
{
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_CNTSEM( POST, this, 0 );
count++;
if( !queue.empty() ) {
 
// The queue is non-empty, so grab the next
// thread from it and wake it up. The waiter
// will decrement the count when he is awakened.
 
Cyg_Thread *thread = queue.dequeue();
 
thread->set_wake_reason( Cyg_Thread::DONE );
thread->wake();
 
CYG_INSTRUMENT_CNTSEM( WAKE, this, thread );
}
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
}
 
// -------------------------------------------------------------------------
// Get current count value
 
cyg_count32 Cyg_Counting_Semaphore::peek() const
{
// This is a single read of the value of count.
// This is already atomic, hence there is no need
// to lock the scheduler.
return count;
}
 
// -------------------------------------------------------------------------
// EOF sync/cnt_sem.cxx
/flag.cxx
0,0 → 1,418
//==========================================================================
//
// flag.cxx
//
// Flag class implementation
//
//==========================================================================
//####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): hmt
// Contributors: hmt
// Date: 1998-02-11
// Purpose: Flag implementation
// Description: This file contains the implementations of the flag class
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/ktypes.h> // base kernel types
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <cyg/kernel/instrmnt.h> // instrumentation
 
#include <cyg/kernel/thread.inl> // thread inlines
 
#include <cyg/kernel/flag.hxx> // our own header
 
#include <cyg/kernel/sched.inl> // scheduler inlines
#include <cyg/kernel/clock.inl> // clock inlines
 
// -------------------------------------------------------------------------
// Constructor
 
Cyg_Flag::Cyg_Flag( Cyg_FlagValue init )
{
CYG_REPORT_FUNCTION();
value = init;
CYG_REPORT_RETURN();
}
 
// -------------------------------------------------------------------------
// Destructor
 
Cyg_Flag::~Cyg_Flag()
{
CYG_REPORT_FUNCTION();
#if 0
CYG_ASSERT( queue.empty(), "Deleting flag with threads waiting");
#endif
// Prevent preemption
Cyg_Scheduler::lock();
 
while ( ! queue.empty() ) {
Cyg_Thread *thread = queue.dequeue();
thread->set_wake_reason( Cyg_Thread::DESTRUCT );
thread->wake();
}
 
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
CYG_REPORT_RETURN();
}
 
// -------------------------------------------------------------------------
// debugging/assert function
 
#ifdef CYGDBG_USE_ASSERTS
cyg_bool
Cyg_Flag::check_this(cyg_assert_class_zeal zeal) const
{
CYG_REPORT_FUNCTION();
if ( Cyg_Thread::DESTRUCT == Cyg_Thread::self()->get_wake_reason() )
// then the whole thing is invalid, and we know it.
// so return OK, since this check should NOT make an error.
return true;
 
// check that we have a non-NULL pointer first
if( this == NULL ) {
CYG_REPORT_RETVAL( false );
return false;
}
 
// there ain't a lot to check here.
CYG_REPORT_RETVAL( true );
return true;
}
#endif
 
// -------------------------------------------------------------------------
// now the members themselves:
// clear some bits in the value (all of them by default) by ANDing with the
// argument. This cannot make a wait condition become true, so there's not
// much to it.
void
Cyg_Flag::maskbits( Cyg_FlagValue arg )
{
CYG_REPORT_FUNCTION();
// Prevent preemption
Cyg_Scheduler::lock();
 
value &= arg;
// no need to wake anyone up; no waiter can become valid in
// consequence of this operation.
 
// Unlock scheduler and allow other threads to run
Cyg_Scheduler::unlock();
CYG_REPORT_RETURN();
}
 
 
// -------------------------------------------------------------------------
// set some bits in the value (all of them by default) and wake up any
// affected waiting threads; we do the decision making here so as to get
// atomicity wrt the other threads waking up - the value might have changed
// by the time they get to run.
 
void
Cyg_Flag::setbits( Cyg_FlagValue arg )
{
CYG_REPORT_FUNCTION();
CYG_ASSERTCLASS( this, "Bad this pointer");
 
// Prevent preemption
Cyg_Scheduler::lock();
// OR in the argument to get a new flag value.
value |= arg;
 
// anyone waiting?
if ( !(queue.empty()) ) {
FlagWaitInfo *p;
Cyg_Thread *thread;
Cyg_ThreadQueue holding;
 
do {
thread = queue.dequeue();
p = (FlagWaitInfo *)(thread->get_wait_info());
 
CYG_ASSERT( (p->allmask == 0) != (p->anymask == 0),
"Both masks set" );
CYG_ASSERT( 0 == p->value_out, "Thread already awoken?" );
 
if ( ((p->allmask != 0) && (p->allmask & value) == p->allmask) ||
((p->anymask & value) != 0 ) ) {
// success! awaken the thread
thread->set_wake_reason( Cyg_Thread::DONE );
thread->wake();
// return the successful value to it
p->value_out = value;
// do we clear the value; is this the end?
if ( p->do_clear ) {
// we can break here but need to preserve ordering
value = 0;
// so let it cycle the whole queue regardless
}
}
else {
// preserve the entry on the holding queue
holding.enqueue( thread );
}
} while ( !(queue.empty()) );
// Now re-queue the unaffected threads back into the flag queue
while ( !(holding.empty()) ) {
queue.enqueue( holding.dequeue() );
}
}
// Unlock scheduler and allow other threads to run
Cyg_Scheduler::unlock();
CYG_REPORT_RETURN();
}
 
// -------------------------------------------------------------------------
// Wait for a match on our pattern, according to the flags given.
// Return the matching value.
Cyg_FlagValue
Cyg_Flag::wait( Cyg_FlagValue pattern, WaitMode mode )
{
CYG_REPORT_FUNCTION();
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_ASSERT( Cyg_Flag::MASK >= mode, "Bad mode" );
 
Cyg_FlagValue result;
 
// Prevent preemption so that we compare atomically
Cyg_Scheduler::lock();
 
// try the current value
result = poll( pattern, mode );
 
if ( 0 != result ) {
Cyg_Scheduler::unlock();
CYG_REPORT_RETVAL( result );
return result; // all done
}
 
// we have to wait until we are awoken
Cyg_Thread *self = Cyg_Thread::self();
 
FlagWaitInfo saveme;
saveme.allmask = (Cyg_Flag::OR & mode) ? 0 : pattern;
saveme.anymask = (Cyg_Flag::OR & mode) ? pattern : 0;
saveme.do_clear = (0 != (Cyg_Flag::CLR & mode));
 
self->set_wait_info( (CYG_ADDRWORD)&saveme );
 
result = true; // just being used as an early-out flag now
// this loop allows us to deal correctly with spurious wakeups
while ( result && (0 == saveme.value_out) ) {
self->set_sleep_reason( Cyg_Thread::WAIT );
self->sleep();
// keep track of myself on the queue of waiting threads
queue.enqueue( self );
 
// Allow other threads to run
Cyg_Scheduler::reschedule();
 
CYG_ASSERT( ((CYG_ADDRWORD)&saveme) ==
Cyg_Thread::self()->get_wait_info(),
"Wait info lost" );
 
switch( self->get_wake_reason() )
{
case Cyg_Thread::DESTRUCT:
case Cyg_Thread::BREAK:
result = false;
break;
case Cyg_Thread::EXIT:
self->exit();
break;
 
default:
break;
}
}
 
CYG_ASSERT( (false == result) ^ (0 != saveme.value_out),
"Break out but also good result!" );
 
// Unlock scheduler and allow other threads to run
Cyg_Scheduler::unlock();
CYG_REPORT_RETVAL( saveme.value_out );
return saveme.value_out;
}
 
// -------------------------------------------------------------------------
// Wait for a match on our pattern, with a timeout.
// Return the matching value, or zero if timed out.
// (zero cannot match any pattern).
#ifdef CYGFUN_KERNEL_THREADS_TIMER
Cyg_FlagValue
Cyg_Flag::wait( Cyg_FlagValue pattern, WaitMode mode,
cyg_tick_count abs_timeout )
{
CYG_REPORT_FUNCTION();
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_ASSERT( Cyg_Flag::MASK >= mode, "Bad mode" );
 
Cyg_FlagValue result;
 
// Prevent preemption so that we compare atomically
Cyg_Scheduler::lock();
 
// try the current value
result = poll( pattern, mode );
 
if ( 0 != result ) {
Cyg_Scheduler::unlock();
CYG_REPORT_RETVAL( result );
return result; // all done
}
 
// we have to wait until we are awoken
Cyg_Thread *self = Cyg_Thread::self();
 
FlagWaitInfo saveme;
saveme.allmask = (Cyg_Flag::OR & mode) ? 0 : pattern;
saveme.anymask = (Cyg_Flag::OR & mode) ? pattern : 0;
saveme.do_clear = (0 != (Cyg_Flag::CLR & mode));
 
self->set_wait_info( (CYG_ADDRWORD)&saveme );
 
// Set the timer _once_ outside the loop.
self->set_timer( abs_timeout, Cyg_Thread::TIMEOUT );
 
// If the timeout was in the past, it will have changed the value
// of wake_reason, so avoid going into the loop.
if( self->get_wake_reason() != Cyg_Thread::NONE )
result = false;
else result = true;
 
// Result is just being used as an early-out flag now. This loop
// allows us to deal correctly with spurious wakeups.
 
while ( result && (0 == saveme.value_out) ) {
self->set_sleep_reason( Cyg_Thread::TIMEOUT );
self->sleep();
// keep track of myself on the queue of waiting threads
queue.enqueue( self );
 
// Allow other threads to run
Cyg_Scheduler::reschedule();
 
CYG_ASSERT( ((CYG_ADDRWORD)&saveme) ==
Cyg_Thread::self()->get_wait_info(),
"Wait info lost" );
 
switch( self->get_wake_reason() )
{
case Cyg_Thread::TIMEOUT:
result = false;
break;
case Cyg_Thread::DESTRUCT:
case Cyg_Thread::BREAK:
result = false;
break;
case Cyg_Thread::EXIT:
self->exit();
break;
 
default:
break;
}
}
 
CYG_ASSERT( (false == result) ^ (0 != saveme.value_out),
"Break out but also good result!" );
 
// clear the timer; if it actually fired, no worries.
self->clear_timer();
 
// Unlock scheduler and allow other threads to run
Cyg_Scheduler::unlock();
// in this version, value_out might be zero meaning timed out.
CYG_REPORT_RETVAL( saveme.value_out );
return saveme.value_out;
}
#endif // CYGFUN_KERNEL_THREADS_TIMER
 
// -------------------------------------------------------------------------
// Test for a match on our pattern, according to the flags given.
// Return the matching value if success, else zero.
Cyg_FlagValue
Cyg_Flag::poll( Cyg_FlagValue pattern, WaitMode mode )
{
CYG_REPORT_FUNCTION();
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_ASSERT( Cyg_Flag::MASK >= mode, "Bad mode" );
 
// Prevent preemption so that we compare atomically
Cyg_Scheduler::lock();
 
Cyg_FlagValue result = 0;
 
if ( Cyg_Flag::OR & mode ) {
if ( 0 != (value & pattern) )
result = value;
}
else { // Cyg_Flag::AND - all must be set
if ( (pattern != 0) && (pattern == (value & pattern)) )
result = value;
}
 
// result != 0 <=> test passed
if ( result && (Cyg_Flag::CLR & mode) )
value = 0;
 
Cyg_Scheduler::unlock();
 
CYG_REPORT_RETVAL( result );
return result;
}
 
 
// -------------------------------------------------------------------------
// EOF flag.cxx
/cnt_sem2.cxx
0,0 → 1,295
//==========================================================================
//
// sync/cnt_sem2.cxx
//
// Counting semaphore implementation
//
//==========================================================================
//####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): nickg
// Contributors: nickg
// Date: 1997-09-24
// Purpose: Cyg_Counting_Semaphore implementation
// Description: This file contains the implementations of the counting semaphore
// class.
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/ktypes.h> // base kernel types
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <cyg/kernel/instrmnt.h> // instrumentation
 
#include <cyg/kernel/thread.inl> // Cyg_Thread inlines
 
#include <cyg/kernel/sema2.hxx> // our header
 
#include <cyg/kernel/sched.inl> // scheduler inlines
 
// -------------------------------------------------------------------------
// Constructor
 
Cyg_Counting_Semaphore2::Cyg_Counting_Semaphore2(
cyg_count32 init_count // Initial count value
)
{
count = init_count;
}
 
// -------------------------------------------------------------------------
// Destructor
 
Cyg_Counting_Semaphore2::~Cyg_Counting_Semaphore2()
{
CYG_REPORT_FUNCTION();
#if 0
CYG_ASSERT( queue.empty(), "Destroying semaphore with waiting threads");
#endif
// Prevent preemption
Cyg_Scheduler::lock();
while ( ! queue.empty() ) {
Cyg_Thread *thread = queue.dequeue();
thread->set_wake_reason( Cyg_Thread::DESTRUCT );
thread->wake();
}
 
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
CYG_REPORT_RETURN();
}
// -------------------------------------------------------------------------
// Wait until the count can be decremented without it becoming
// negative.
 
cyg_bool Cyg_Counting_Semaphore2::wait()
{
CYG_REPORT_FUNCTION();
Cyg_Thread *self = Cyg_Thread::self();
cyg_bool result = true;
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_CNTSEM( CLAIM, this, count );
if ( 0 < count ) {
count--;
Cyg_Scheduler::unlock();
}
else {
self->set_sleep_reason( Cyg_Thread::WAIT );
self->sleep();
queue.enqueue( self );
 
CYG_INSTRUMENT_CNTSEM( WAIT, this, 0 );
 
Cyg_Scheduler::unlock();
 
CYG_INSTRUMENT_CNTSEM( WOKE, this, count );
 
switch( self->get_wake_reason() )
{
case Cyg_Thread::DESTRUCT:
case Cyg_Thread::BREAK:
result = false;
break;
case Cyg_Thread::EXIT:
self->exit();
break;
default:
break;
}
}
 
CYG_REPORT_RETVAL( result );
return result;
}
 
// -------------------------------------------------------------------------
// Wait until the count can be decremented without it becoming
// negative.
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
 
cyg_bool
Cyg_Counting_Semaphore2::wait( cyg_tick_count abs_timeout )
{
CYG_REPORT_FUNCTION();
Cyg_Thread *self = Cyg_Thread::self();
cyg_bool result = true;
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_CNTSEM( CLAIM, this, count );
if ( 0 < count ) {
count--;
Cyg_Scheduler::unlock();
}
else {
 
// Put thread in sleep state before setting timer since if the
// timeout is in the past, it will be re-awoken
// immediately. If this happens then wake_reason will not be
// NONE.
self->sleep();
 
self->set_timer( abs_timeout, Cyg_Thread::TIMEOUT );
 
// only enqueue if the timeout did not already happen
if( Cyg_Thread::NONE == self->get_wake_reason() )
queue.enqueue( self );
 
CYG_INSTRUMENT_CNTSEM( WAIT, this, 0 );
 
Cyg_Scheduler::unlock();
 
// Clear the timeout. It is irrelevant whether the alarm has
// actually gone off or not.
self->clear_timer();
 
CYG_INSTRUMENT_CNTSEM( WOKE, this, count );
 
switch( self->get_wake_reason() )
{
case Cyg_Thread::TIMEOUT:
result = false;
CYG_INSTRUMENT_CNTSEM( TIMEOUT, this, count);
break;
case Cyg_Thread::DESTRUCT:
case Cyg_Thread::BREAK:
result = false;
break;
case Cyg_Thread::EXIT:
self->exit();
break;
 
default:
break;
}
}
 
CYG_REPORT_RETVAL( result );
return result;
}
 
#endif // CYGFUN_KERNEL_THREADS_TIMER
 
// -------------------------------------------------------------------------
// Try to decrement, but fail if not possible
 
cyg_bool Cyg_Counting_Semaphore2::trywait()
{
CYG_REPORT_FUNCTION();
cyg_bool result = true;
// Prevent preemption
Cyg_Scheduler::lock();
 
if( 0 < count ) count--;
else result = false;
 
CYG_INSTRUMENT_CNTSEM( TRY, this, result );
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
CYG_REPORT_RETVAL( result );
return result;
}
// -------------------------------------------------------------------------
// Increment count
 
void Cyg_Counting_Semaphore2::post()
{
CYG_REPORT_FUNCTION();
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_CNTSEM( POST, this, 0 );
if( queue.empty() ) {
count++;
}
else {
// The queue is non-empty, so grab the next
// thread from it and wake it up. The waiter
// won't decrement the count when he is awakened,
// for we never incremented it in the first place
 
Cyg_Thread *thread = queue.dequeue();
 
thread->set_wake_reason( Cyg_Thread::DONE );
thread->wake();
 
CYG_INSTRUMENT_CNTSEM( WAKE, this, thread );
}
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
CYG_REPORT_RETURN();
}
 
// -------------------------------------------------------------------------
// Get current count value
 
cyg_count32 Cyg_Counting_Semaphore2::peek() const
{
// This is a single read of the value of count.
// This is already atomic, hence there is no need
// to lock the scheduler.
return count;
}
 
// -------------------------------------------------------------------------
// EOF sync/cnt_sem2.cxx
/bin_sem.cxx
0,0 → 1,197
//==========================================================================
//
// sync/bin_sem.cxx
//
// Binary semaphore implementation
//
//==========================================================================
//####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): nickg
// Contributors: nickg
// Date: 1997-09-24
// Purpose: Cyg_Binary_Semaphore implementation
// Description: This file contains the implementations of the binary semaphore
// class.
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/ktypes.h> // base kernel types
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <cyg/kernel/instrmnt.h> // instrumentation
 
#include <cyg/kernel/thread.inl> // Cyg_Thread inlines
 
#include <cyg/kernel/sema.hxx> // our header
 
#include <cyg/kernel/sched.inl> // scheduler inlines
 
// -------------------------------------------------------------------------
 
Cyg_Binary_Semaphore::Cyg_Binary_Semaphore (
cyg_bool init_state
)
{
state = init_state;
}
 
// -------------------------------------------------------------------------
 
Cyg_Binary_Semaphore::~Cyg_Binary_Semaphore ( )
{
}
 
// -------------------------------------------------------------------------
 
cyg_bool Cyg_Binary_Semaphore::wait()
{
cyg_bool result = true;
Cyg_Thread *self = Cyg_Thread::self();
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_BINSEM( CLAIM, this, state );
while( !state && result )
{
self->set_sleep_reason( Cyg_Thread::WAIT );
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::DESTRUCT:
case Cyg_Thread::BREAK:
result = false;
break;
case Cyg_Thread::EXIT:
self->exit();
break;
 
default:
break;
}
}
 
if( result ) state = false;
 
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
 
return result;
}
 
// -------------------------------------------------------------------------
 
cyg_bool Cyg_Binary_Semaphore::trywait()
{
cyg_bool result = true;
// Prevent preemption
Cyg_Scheduler::lock();
 
if( state ) state = false;
else result = false;
CYG_INSTRUMENT_BINSEM( TRY, this, result );
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
return result;
}
 
// -------------------------------------------------------------------------
 
void Cyg_Binary_Semaphore::post()
{
// Prevent preemption
Cyg_Scheduler::lock();
 
CYG_INSTRUMENT_BINSEM( POST, this, 0 );
state = true;
if( !queue.empty() ) {
 
// The queue is non-empty, so grab the next
// thread from it and wake it up. The waiter
// will clear the flag.
 
Cyg_Thread *thread = queue.dequeue();
 
thread->set_wake_reason( Cyg_Thread::DONE );
thread->wake();
 
CYG_INSTRUMENT_BINSEM( WAKE, this, thread );
}
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
}
 
// -------------------------------------------------------------------------
 
cyg_bool Cyg_Binary_Semaphore::posted()
{
// This is a single read of the value of state.
// This is already atomic, hence there is no need
// to lock the scheduler.
return state;
}
 
// -------------------------------------------------------------------------
// EOF sync/bin_sem.cxx

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.