⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flag.cxx

📁 ecos为实时嵌入式操作系统
💻 CXX
字号:
//==========================================================================////      flag.cxx////      Flag class implementation////==========================================================================//####COPYRIGHTBEGIN####//// -------------------------------------------// The contents of this file are subject to the Cygnus eCos Public License// Version 1.0 (the "License"); you may not use this file except in// compliance with the License.  You may obtain a copy of the License at// http://sourceware.cygnus.com/ecos// // Software distributed under the License is distributed on an "AS IS"// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the// License for the specific language governing rights and limitations under// the License.// // The Original Code is eCos - Embedded Cygnus Operating System, released// September 30, 1998.// // The Initial Developer of the Original Code is Cygnus.  Portions created// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions.  All Rights Reserved.// -------------------------------------------////####COPYRIGHTEND####//==========================================================================//#####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// -------------------------------------------------------------------------// ConstructorCyg_Flag::Cyg_Flag( Cyg_FlagValue init = 0 ){    CYG_REPORT_FUNCTION();    value = init;    CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// DestructorCyg_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_ASSERTScyg_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.voidCyg_Flag::maskbits( Cyg_FlagValue arg = 0 ){    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.voidCyg_Flag::setbits( Cyg_FlagValue arg = ~0 ){    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_FlagValueCyg_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 );        CYG_ASSERT( 1 == Cyg_Scheduler::get_sched_lock(),                    "Called with non-zero scheduler lock");                // Unlock scheduler and allow other threads to run        Cyg_Scheduler::unlock();        Cyg_Scheduler::lock();        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_TIMERCyg_FlagValueCyg_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 );        CYG_ASSERT( 1 == Cyg_Scheduler::get_sched_lock(),                    "Called with non-zero scheduler lock");                // Unlock scheduler and allow other threads to run        Cyg_Scheduler::unlock();        Cyg_Scheduler::lock();        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_FlagValueCyg_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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -