time.cxx

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

CXX
701
字号
//==========================================================================////      time.cxx////      POSIX time functions 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:                2000-03-27// Purpose:             POSIX time functions implementation// Description:         This file contains the implementation of the POSIX time//                      functions.//              //              ////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/posix.h>#ifdef CYGPKG_POSIX_CLOCKS#include <pkgconf/hal.h>#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 "pprivate.h"                   // POSIX private header#include <time.h>                       // our header#include <cyg/kernel/thread.hxx>#include <cyg/kernel/clock.hxx>#include <cyg/kernel/thread.inl>#include <cyg/kernel/clock.inl>// -------------------------------------------------------------------------// Internal definitions// Handle entry to a pthread package function. #define TIME_ENTRY() CYG_REPORT_FUNCTYPE( "returning %d" );// Do a time package defined return. This requires the error code// to be placed in errno, and if it is non-zero, -1 returned as the// result of the function. This also gives us a place to put any// generic tidyup handling needed for things like signal delivery and// cancellation.#define TIME_RETURN(err)                        \CYG_MACRO_START                                 \    int __retval = 0;                           \    if( err != 0 ) __retval = -1, errno = err;  \    CYG_REPORT_RETVAL( __retval );              \    return __retval;                            \CYG_MACRO_END//==========================================================================// Timer control structures#ifdef CYGPKG_POSIX_TIMERStypedef struct{    timer_t             id;             // id value for checking    Cyg_Alarm           *alarm;         // eCos alarm object    cyg_bool            armed;          // is alarm enabled?    cyg_bool            pending;        // is expiry pending?    int                 overrun;        // Overrun count    struct sigevent     sigev;          // Sigevent to raise on expiry        // Space for alarm object    cyg_uint8           alarm_obj[sizeof(Cyg_Alarm)];    } posix_timer;// Mutex for controlling access to shared data structuresstatic Cyg_Mutex timer_mutex CYGBLD_POSIX_INIT;// Array of timer objectsstatic posix_timer timer_table[_POSIX_TIMER_MAX];// Index of next timer to allocate from arraystatic int timer_next = 0;// This is used to make timer_t values unique even when reusing// a table slot. This allows _POSIX_TIMER_MAX to range// up to 1024.#define TIMER_ID_COOKIE_INC 0x00000400#define TIMER_ID_COOKIE_MASK (TIMER_ID_COOKIE_INC-1)static timer_t timer_id_cookie = TIMER_ID_COOKIE_INC;#endif // ifdef CYGPKG_POSIX_TIMERS//-----------------------------------------------------------------------------// new operator to allow us to invoke the constructor on// posix_timer.alarm_obj.inline void *operator new(size_t size,  cyg_uint8 *ptr) { return (void *)ptr; };//==========================================================================// Time conversion variables// These are used to interconvert between ticks and POSIX timespecs.// Converters from sec and ns to ticksstatic struct Cyg_Clock::converter ns_converter, sec_converter;// Converters from ticks to sec and nsstatic struct Cyg_Clock::converter ns_inverter, sec_inverter;// tickns is the number of nanoseconds per tick.static cyg_tick_count tickns;static cyg_bool converters_initialized = false;//==========================================================================// Local functionsstatic void init_converters(){    if( !converters_initialized )    {        // Create the converters we need.        Cyg_Clock::real_time_clock->get_other_to_clock_converter( 1, &ns_converter );        Cyg_Clock::real_time_clock->get_other_to_clock_converter( 1000000000, &sec_converter );        Cyg_Clock::real_time_clock->get_clock_to_other_converter( 1, &ns_inverter );            Cyg_Clock::real_time_clock->get_clock_to_other_converter( 1000000000, &sec_inverter );        tickns = Cyg_Clock::convert( 1, &ns_inverter );                    converters_initialized = true;    }}static cyg_bool valid_timespec( const struct timespec *tp ){    // Fail a NULL pointer    if( tp == NULL ) return false;    // Fail illegal nanosecond values    if( tp->tv_nsec < 0 || tp->tv_nsec > 1000000000 )        return false;    return true;}externC cyg_tick_count cyg_timespec_to_ticks( const struct timespec *tp,                                              cyg_bool roundup){    init_converters();    // Short circuit zero timespecs    if( tp->tv_sec == 0 && tp->tv_nsec == 0 )    {        return 0;    }            // Convert the seconds field to ticks.    cyg_tick_count ticks = Cyg_Clock::convert( tp->tv_sec, &sec_converter );    if( roundup )    {        // Convert the nanoseconds. We add (tickns-1) to round the value up        // to the next whole tick.        ticks += Cyg_Clock::convert( (cyg_tick_count)tp->tv_nsec+tickns-1, &ns_converter );        }    else    {        // Convert the nanoseconds. This will round down to nearest whole tick.        ticks += Cyg_Clock::convert( (cyg_tick_count)tp->tv_nsec, &ns_converter );    }    return ticks;}externC void cyg_ticks_to_timespec( cyg_tick_count ticks, struct timespec *tp ){    init_converters();    // short circuit zero ticks values    if( ticks == 0 )    {        tp->tv_sec = 0;        tp->tv_nsec = 0;        return;    }    // Convert everything to nanoseconds with a long long. For 64-bits,    // this is safe for 544 years. We'll think about it more closer to    // the time...    unsigned long long nsecs = Cyg_Clock::convert( ticks, &ns_inverter );    tp->tv_sec = (long)(nsecs / 1000000000ll);    tp->tv_nsec = (long)(nsecs % 1000000000ll);    CYG_POSTCONDITION(valid_timespec(tp), "Failed to make valid timespec!");}//==========================================================================// Startup routine.externC void cyg_posix_clock_start(){    init_converters();}#ifdef CYGPKG_POSIX_TIMERS//==========================================================================// Alarm action routine// This is called each time an alarm set up by a timer expires.static void alarm_action( Cyg_Alarm *alarm, CYG_ADDRWORD data ){    posix_timer *timer = (posix_timer *)data;    if( timer->pending )    {        // If the pending flag is already set, count an overrun and        // do not bother to try and deliver the expiry.                timer->overrun++;    }    else    {        if( timer->sigev.sigev_notify == SIGEV_SIGNAL )        {            // Set the expiry pending and wake a thread to            // deliver the signal.                    timer->pending = true;                sigset_t mask;            sigemptyset( &mask );            sigaddset( &mask, timer->sigev.sigev_signo );            cyg_posix_signal_sigwait();            cyg_posix_pthread_release_thread( &mask );        }        else if( timer->sigev.sigev_notify == SIGEV_THREAD )        {            // Thread style notification            // FIXME: implement SIGEV_THREAD        }        // else do nothing    }}//==========================================================================// Timer ASR routineexternC void cyg_posix_timer_asr( pthread_info *self ){    // Loop over the timers looking for any that have an    // expiry pending and call cyg_sigqueue() for each.        for( int i = 0; i < _POSIX_TIMER_MAX; i++ )    {        posix_timer *timer = &timer_table[i];        if( timer->id != 0 && timer->pending )        {            timer->pending = false;                            // Call into signal subsystem...            cyg_sigqueue( &timer->sigev, SI_TIMER );            timer->overrun = 0;        }    }}#endif // ifdef CYGPKG_POSIX_TIMERS//==========================================================================// Clock functions//-----------------------------------------------------------------------------// Set the clocks current timeexternC int clock_settime( clockid_t clock_id, const struct timespec *tp){    TIME_ENTRY();    if( clock_id != CLOCK_REALTIME )        TIME_RETURN(EINVAL);    if( !valid_timespec( tp ) )        TIME_RETURN(EINVAL);            cyg_tick_count ticks = cyg_timespec_to_ticks( tp );    Cyg_Clock::real_time_clock->set_value( ticks );        TIME_RETURN(0);}//-----------------------------------------------------------------------------// Get the clocks current timeexternC int clock_gettime( clockid_t clock_id, struct timespec *tp){    TIME_ENTRY();    if( clock_id != CLOCK_REALTIME )        TIME_RETURN(EINVAL);    if( tp == NULL )        TIME_RETURN(EINVAL);        cyg_tick_count ticks = Cyg_Clock::real_time_clock->current_value();

⌨️ 快捷键说明

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