clock.cxx

来自「eCos操作系统源码」· CXX 代码 · 共 945 行 · 第 1/2 页

CXX
945
字号
//==========================================================================////      common/clock.cxx////      Clock class implementations////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2002 Jonathan Larmour//// 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-15// Purpose:     Clock class implementation// Description: This file contains the definitions of the counter,//              clock and alarm class member functions that are common//              to all clock implementations.////####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/clock.hxx>        // our header#include <cyg/kernel/sched.hxx>        // scheduler definitions#include <cyg/kernel/thread.hxx>       // thread definitions#include <cyg/kernel/intr.hxx>         // interrupt definitions#include <cyg/kernel/sched.inl>        // scheduler inlines#include <cyg/kernel/clock.inl>        // Clock inlines// -------------------------------------------------------------------------// Static variables#ifdef CYGVAR_KERNEL_COUNTERS_CLOCKCyg_Clock *Cyg_Clock::real_time_clock = NULL;   // System real time clock#endif//==========================================================================// Constructor for counter objectCyg_Counter::Cyg_Counter(    cyg_uint32      incr    ){    CYG_REPORT_FUNCTION();    counter = 0;    increment = incr;}// -------------------------------------------------------------------------// Destructor for Counter objectCyg_Counter::~Cyg_Counter(){    CYG_REPORT_FUNCTION();}// -------------------------------------------------------------------------// #ifdef CYGDBG_USE_ASSERTScyg_bool Cyg_Counter::check_this( cyg_assert_class_zeal zeal) const{    // 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:    case cyg_none:    default:        break;    };    return true;}#endif// -------------------------------------------------------------------------// Counter tick functionvoid Cyg_Counter::tick( cyg_uint32 ticks ){//    CYG_REPORT_FUNCTION();    CYG_ASSERTCLASS( this, "Bad counter object" );    // Increment the counter in a loop so we process    // each tick separately. This is easier than trying    // to cope with a range of increments.        while( ticks-- )    {        Cyg_Scheduler::lock();        // increment the counter, note that it is        // allowed to wrap.        counter += increment;        // now check for any expired alarms        Cyg_Alarm_List *alarm_list_ptr;     // pointer to list#if defined(CYGIMP_KERNEL_COUNTERS_SINGLE_LIST)        alarm_list_ptr = &alarm_list;#elif defined(CYGIMP_KERNEL_COUNTERS_MULTI_LIST)        // With multiple lists, each one contains only the alarms        // that will expire at a given tick modulo the list number.        // So we only have a fraction of the alarms to check here.                alarm_list_ptr = &(alarm_list[                               (counter/increment) % CYGNUM_KERNEL_COUNTERS_MULTI_LIST_SIZE ] );    #else#error "No CYGIMP_KERNEL_COUNTERS_x_LIST config"#endif        // Now that we have the list pointer, we can use common code for        // both list organizations.#ifdef CYGIMP_KERNEL_COUNTERS_SORT_LIST        // With a sorted alarm list, we can simply pick alarms off the        // front of the list until we find one that is in the future.        while( !alarm_list_ptr->empty() )        {            Cyg_Alarm *alarm = alarm_list_ptr->get_head();                    CYG_ASSERTCLASS(alarm, "Bad alarm in counter list" );                        if( alarm->trigger <= counter )            {                // remove alarm from list                alarm_list_ptr->rem_head();                if( alarm->interval != 0 )                {                    // The alarm has a retrigger interval.                    // Reset the trigger time and requeue                    // the alarm.                    alarm->trigger += alarm->interval;                    add_alarm( alarm );                }                else alarm->enabled = false;                CYG_INSTRUMENT_ALARM( CALL, this, alarm );                                // call alarm function                alarm->alarm(alarm, alarm->data);                // all done, loop            }            else break;                    } #else        // With unsorted lists we must scan the whole list for        // candidates. However, we must be careful here since it is        // possible for the function of one alarm to add or remove        // other alarms to/from this list. Having the list shift under        // our feet in this way could be disasterous. We solve this by        // restarting the scan from the beginning whenever we call an        // alarm function.        cyg_bool rescan = true;        while( rescan )        {            Cyg_DNode_T<Cyg_Alarm> *node = alarm_list_ptr->get_head();            rescan = false;                        while( node != NULL )            {                Cyg_Alarm *alarm = CYG_CLASSFROMBASE( Cyg_Alarm, Cyg_DNode, node );                Cyg_DNode_T<Cyg_Alarm> *next = alarm->get_next();                CYG_ASSERTCLASS(alarm, "Bad alarm in counter list" );                if( alarm->trigger <= counter )                {                    alarm_list_ptr->remove(alarm);                    if( alarm->interval != 0 )                    {                        // The alarm has a retrigger interval.                        // Reset the trigger time and requeue                        // the alarm.                        alarm->trigger += alarm->interval;                        add_alarm( alarm );                    }                    else alarm->enabled = false;                    CYG_INSTRUMENT_ALARM( CALL, this, alarm );                                    // Call alarm function                    alarm->alarm(alarm, alarm->data);                    rescan = true;                    break;                }                // If the next node is the head of the list, then we have                // looped all the way around. The node == next test                // catches the case where we only had one element to start                // with.                if( next == alarm_list_ptr->get_head() || node == next )                    node = NULL;                else                    node = next;            }        }        #endif                Cyg_Scheduler::unlock();    }    }// -------------------------------------------------------------------------// Add an alarm to this countervoid Cyg_Counter::add_alarm( Cyg_Alarm *alarm ){    CYG_REPORT_FUNCTION();    CYG_ASSERTCLASS( this, "Bad counter object" );    CYG_ASSERTCLASS( alarm, "Bad alarm passed" );    CYG_ASSERT( Cyg_Scheduler::get_sched_lock() > 0, "Scheduler not locked");        // set this now to allow an immediate handler call to manipulate    // this alarm sensibly.    alarm->enabled = true;    // Check here for an alarm that triggers now or in the past and    // call its alarm function immediately.     if( alarm->trigger <= counter )    {        CYG_INSTRUMENT_ALARM( CALL, this, alarm );        // call alarm function. Note that this is being        // called here before the add_alarm has returned.        // Note that this function may disable the alarm.                alarm->alarm(alarm, alarm->data);        // Note that this extra check on alarm->enabled is in case the        // handler function disables this alarm!        if( alarm->interval != 0 && alarm->enabled )        {            // The alarm has a retrigger interval.            // Reset the trigger interval and drop            // through to queue it.            alarm->trigger += alarm->interval;            // ensure the next alarm time is in our future, and in phase            // with the original time requested.            alarm->synchronize();        }        else        {            // The alarm is all done with, disable it            // unlock and return.            alarm->enabled = false;            return;        }    }        CYG_INSTRUMENT_ALARM( ADD, this, alarm );     // Find the pointer to the relevant list _after_ a retrigger    // alarm has been given its new trigger time.    Cyg_Alarm_List *alarm_list_ptr;     // pointer to list#if defined(CYGIMP_KERNEL_COUNTERS_SINGLE_LIST)    alarm_list_ptr = &alarm_list;#elif defined(CYGIMP_KERNEL_COUNTERS_MULTI_LIST)    // Each alarm must go into the list that covers the tick that is    // going to happen _after_ the trigger time (or at it if trigger    // happens to fall on a tick.        alarm_list_ptr = &(alarm_list[        ((alarm->trigger+increment-1)/increment) %        CYGNUM_KERNEL_COUNTERS_MULTI_LIST_SIZE ] );    #else#error "No CYGIMP_KERNEL_COUNTERS_x_LIST config"#endif#ifdef CYGIMP_KERNEL_COUNTERS_SORT_LIST            // Now that we have the list pointer, we can use common code for    // both list organizations.    Cyg_Alarm *list_alarm = alarm_list_ptr->get_head();    if( list_alarm != NULL )    {        do        {            CYG_ASSERTCLASS(list_alarm, "Bad alarm in counter list" );            // The alarms are in ascending trigger order. If we            // find an alarm that triggers later than us, we go            // in front of it.                    if( list_alarm->trigger > alarm->trigger )            {                alarm_list_ptr->insert( list_alarm, alarm );                return;            }            list_alarm = list_alarm->get_next();                    } while( list_alarm != alarm_list_ptr->get_head() );        // a lower or equal alarm time was not found, so drop through        // so it is added to the list tail    }#endif    alarm_list_ptr->add_tail( alarm );}// -------------------------------------------------------------------------// Remove an alarm from this countervoid Cyg_Counter::rem_alarm( Cyg_Alarm *alarm ){    CYG_REPORT_FUNCTION();    CYG_ASSERTCLASS( this, "Bad counter object" );    CYG_ASSERTCLASS( alarm, "Bad alarm passed" );    CYG_ASSERT( Cyg_Scheduler::get_sched_lock() > 0, "Scheduler not locked");        Cyg_Alarm_List *alarm_list_ptr;     // pointer to list#if defined(CYGIMP_KERNEL_COUNTERS_SINGLE_LIST)    alarm_list_ptr = &alarm_list;#elif defined(CYGIMP_KERNEL_COUNTERS_MULTI_LIST)    alarm_list_ptr = &(alarm_list[        ((alarm->trigger+increment-1)/increment) %                              CYGNUM_KERNEL_COUNTERS_MULTI_LIST_SIZE ] );    #else#error "No CYGIMP_KERNEL_COUNTERS_x_LIST config"#endif    // Now that we have the list pointer, we can use common code for    // both list organizations.    CYG_INSTRUMENT_ALARM( REM, this, alarm );    alarm_list_ptr->remove( alarm );        alarm->enabled = false;}//==========================================================================// Constructor for clock objectCyg_Clock::Cyg_Clock(    cyg_resolution      res    ){    CYG_REPORT_FUNCTION();    resolution = res;}// -------------------------------------------------------------------------// Destructor for Clock objectsCyg_Clock::~Cyg_Clock(){    CYG_REPORT_FUNCTION();}// -------------------------------------------------------------------------// #ifdef CYGDBG_USE_ASSERTScyg_bool Cyg_Clock::check_this( cyg_assert_class_zeal zeal) const{    // 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:    case cyg_none:    default:        break;    };    return true;}#endif// -------------------------------------------------------------------------

⌨️ 快捷键说明

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