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 + -
显示快捷键?