From baf051ca35b40c73e98f4b5246be50209cd966a6 Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Thu, 27 Jun 2002 20:09:26 +0000 Subject: 2002-06-27 Jeff Johnston * libc/sys/linux/Makefile.am: Add new clock routines. * libc/sys/linux/Makefile.in: Regenerated. * libc/sys/linux/clock_getres.c: New file. * libc/sys/linux/clock_gettime.c: Ditto. * libc/sys/linux/clock_settime.c: Ditto. * libc/sys/linux/hp-timing.h: Ditto. * libc/sys/linux/libc-internal.h: Ditto. * libc/sys/linux/sysconf.c: Fix typo. * libc/sys/linux/include/time.h: New file. * libc/sys/linux/machine/hp-timing.h: New file. * libc/sys/linux/machine/i386/Makefile.am: Add new files. * libc/sys/linux/machine/i386/Makefile.in: Regenerated. * libc/sys/linux/machine/i386/get_clockfreq.c: New file. * libc/sys/linux/machine/i386/hp-timing.c: Ditto. * libc/sys/linux/machine/i386/hp-timing.h: Ditto. * libc/sys/linux/sys/linux_time.h: Ditto. * libc/sys/linux/sys/time.h: Remove include of and replace with . --- newlib/libc/sys/linux/Makefile.am | 3 + newlib/libc/sys/linux/Makefile.in | 38 ++-- newlib/libc/sys/linux/clock_getres.c | 94 +++++++++ newlib/libc/sys/linux/clock_gettime.c | 109 ++++++++++ newlib/libc/sys/linux/clock_settime.c | 111 ++++++++++ newlib/libc/sys/linux/hp-timing.h | 1 + newlib/libc/sys/linux/include/time.h | 225 +++++++++++++++++++++ newlib/libc/sys/linux/libc-internal.h | 32 +++ newlib/libc/sys/linux/machine/hp-timing.h | 83 ++++++++ newlib/libc/sys/linux/machine/i386/Makefile.am | 2 +- newlib/libc/sys/linux/machine/i386/Makefile.in | 9 +- newlib/libc/sys/linux/machine/i386/get_clockfreq.c | 117 +++++++++++ newlib/libc/sys/linux/machine/i386/hp-timing.c | 24 +++ newlib/libc/sys/linux/machine/i386/hp-timing.h | 187 +++++++++++++++++ newlib/libc/sys/linux/sys/linux_time.h | 73 +++++++ newlib/libc/sys/linux/sys/time.h | 2 +- newlib/libc/sys/linux/sysconf.c | 2 +- 17 files changed, 1090 insertions(+), 22 deletions(-) create mode 100644 newlib/libc/sys/linux/clock_getres.c create mode 100644 newlib/libc/sys/linux/clock_gettime.c create mode 100644 newlib/libc/sys/linux/clock_settime.c create mode 100644 newlib/libc/sys/linux/hp-timing.h create mode 100644 newlib/libc/sys/linux/include/time.h create mode 100644 newlib/libc/sys/linux/libc-internal.h create mode 100644 newlib/libc/sys/linux/machine/hp-timing.h create mode 100644 newlib/libc/sys/linux/machine/i386/get_clockfreq.c create mode 100644 newlib/libc/sys/linux/machine/i386/hp-timing.c create mode 100644 newlib/libc/sys/linux/machine/i386/hp-timing.h create mode 100644 newlib/libc/sys/linux/sys/linux_time.h (limited to 'newlib/libc/sys') diff --git a/newlib/libc/sys/linux/Makefile.am b/newlib/libc/sys/linux/Makefile.am index b7a474127..a21963ca6 100644 --- a/newlib/libc/sys/linux/Makefile.am +++ b/newlib/libc/sys/linux/Makefile.am @@ -12,6 +12,9 @@ SUBLIBS = \ LIB_SOURCES = \ brk.c \ cfspeed.c \ + clock_getres.c \ + clock_gettime.c \ + clock_settime.c \ flockfile.c \ ftok.c \ funlockfile.c \ diff --git a/newlib/libc/sys/linux/Makefile.in b/newlib/libc/sys/linux/Makefile.in index 0ff77e986..f740b67a1 100644 --- a/newlib/libc/sys/linux/Makefile.in +++ b/newlib/libc/sys/linux/Makefile.in @@ -109,6 +109,9 @@ SUBLIBS = \ LIB_SOURCES = \ brk.c \ cfspeed.c \ + clock_getres.c \ + clock_gettime.c \ + clock_settime.c \ flockfile.c \ ftok.c \ funlockfile.c \ @@ -206,13 +209,14 @@ DEFS = @DEFS@ -I. -I$(srcdir) CPPFLAGS = @CPPFLAGS@ LIBS = @LIBS@ @USE_LIBTOOL_FALSE@lib_a_OBJECTS = brk.$(OBJEXT) cfspeed.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@flockfile.$(OBJEXT) ftok.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@funlockfile.$(OBJEXT) getdate.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@getdate_err.$(OBJEXT) gethostname.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@getoptlong.$(OBJEXT) getreent.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@ids.$(OBJEXT) inode.$(OBJEXT) io.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@io64.$(OBJEXT) ipc.$(OBJEXT) linux.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@mmap.$(OBJEXT) mq_close.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@clock_getres.$(OBJEXT) clock_gettime.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@clock_settime.$(OBJEXT) flockfile.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@ftok.$(OBJEXT) funlockfile.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@getdate.$(OBJEXT) getdate_err.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@gethostname.$(OBJEXT) getoptlong.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@getreent.$(OBJEXT) ids.$(OBJEXT) inode.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@io.$(OBJEXT) io64.$(OBJEXT) ipc.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@linux.$(OBJEXT) mmap.$(OBJEXT) mq_close.$(OBJEXT) \ @USE_LIBTOOL_FALSE@mq_getattr.$(OBJEXT) mq_notify.$(OBJEXT) \ @USE_LIBTOOL_FALSE@mq_open.$(OBJEXT) mq_receive.$(OBJEXT) \ @USE_LIBTOOL_FALSE@mq_send.$(OBJEXT) mq_setattr.$(OBJEXT) \ @@ -234,15 +238,17 @@ LIBS = @LIBS@ @USE_LIBTOOL_FALSE@usleep.$(OBJEXT) wait.$(OBJEXT) LTLIBRARIES = $(noinst_LTLIBRARIES) -@USE_LIBTOOL_TRUE@liblinux_la_OBJECTS = brk.lo cfspeed.lo flockfile.lo \ -@USE_LIBTOOL_TRUE@ftok.lo funlockfile.lo getdate.lo getdate_err.lo \ -@USE_LIBTOOL_TRUE@gethostname.lo getoptlong.lo getreent.lo ids.lo \ -@USE_LIBTOOL_TRUE@inode.lo io.lo io64.lo ipc.lo linux.lo mmap.lo \ -@USE_LIBTOOL_TRUE@mq_close.lo mq_getattr.lo mq_notify.lo mq_open.lo \ -@USE_LIBTOOL_TRUE@mq_receive.lo mq_send.lo mq_setattr.lo mq_unlink.lo \ -@USE_LIBTOOL_TRUE@ntp_gettime.lo pread.lo pread64.lo process.lo \ -@USE_LIBTOOL_TRUE@psignal.lo pwrite.lo pwrite64.lo raise.lo realpath.lo \ -@USE_LIBTOOL_TRUE@rename.lo resource.lo sched.lo select.lo seteuid.lo \ +@USE_LIBTOOL_TRUE@liblinux_la_OBJECTS = brk.lo cfspeed.lo \ +@USE_LIBTOOL_TRUE@clock_getres.lo clock_gettime.lo clock_settime.lo \ +@USE_LIBTOOL_TRUE@flockfile.lo ftok.lo funlockfile.lo getdate.lo \ +@USE_LIBTOOL_TRUE@getdate_err.lo gethostname.lo getoptlong.lo \ +@USE_LIBTOOL_TRUE@getreent.lo ids.lo inode.lo io.lo io64.lo ipc.lo \ +@USE_LIBTOOL_TRUE@linux.lo mmap.lo mq_close.lo mq_getattr.lo \ +@USE_LIBTOOL_TRUE@mq_notify.lo mq_open.lo mq_receive.lo mq_send.lo \ +@USE_LIBTOOL_TRUE@mq_setattr.lo mq_unlink.lo ntp_gettime.lo pread.lo \ +@USE_LIBTOOL_TRUE@pread64.lo process.lo psignal.lo pwrite.lo \ +@USE_LIBTOOL_TRUE@pwrite64.lo raise.lo realpath.lo rename.lo \ +@USE_LIBTOOL_TRUE@resource.lo sched.lo select.lo seteuid.lo \ @USE_LIBTOOL_TRUE@sethostname.lo shm_open.lo shm_unlink.lo sig.lo \ @USE_LIBTOOL_TRUE@sigaction.lo sigqueue.lo signal.lo siglongjmp.lo \ @USE_LIBTOOL_TRUE@sigset.lo sigwait.lo socket.lo sleep.lo stack.lo \ diff --git a/newlib/libc/sys/linux/clock_getres.c b/newlib/libc/sys/linux/clock_getres.c new file mode 100644 index 000000000..8bf648f51 --- /dev/null +++ b/newlib/libc/sys/linux/clock_getres.c @@ -0,0 +1,94 @@ +/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +#if HP_TIMING_AVAIL +/* Clock frequency of the processor. */ +static long int nsec; +#endif + + +/* Get resolution of clock. */ +int +clock_getres (clockid_t clock_id, struct timespec *res) +{ + int retval = -1; + + switch (clock_id) + { + case CLOCK_REALTIME: + { + long int clk_tck = sysconf (_SC_CLK_TCK); + + if (__builtin_expect (clk_tck != -1, 1)) + { + /* This implementation assumes that the realtime clock has a + resolution higher than 1 second. This is the case for any + reasonable implementation. */ + res->tv_sec = 0; + res->tv_nsec = 1000000000 / clk_tck; + + retval = 0; + } + } + break; + +#if HP_TIMING_AVAIL + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_THREAD_CPUTIME_ID: + { + if (__builtin_expect (nsec == 0, 0)) + { + hp_timing_t freq; + + /* This can only happen if we haven't initialized the `freq' + variable yet. Do this now. We don't have to protect this + code against multiple execution since all of them should + lead to the same result. */ + freq = __get_clockfreq (); + if (__builtin_expect (freq == 0, 0)) + /* Something went wrong. */ + break; + + nsec = MAX (UINT64_C (1000000000) / freq, 1); + } + + /* File in the values. The seconds are always zero (unless we + have a 1Hz machine). */ + res->tv_sec = 0; + res->tv_nsec = nsec; + + retval = 0; + } + break; +#endif + + default: + __set_errno (EINVAL); + break; + } + + return retval; +} diff --git a/newlib/libc/sys/linux/clock_gettime.c b/newlib/libc/sys/linux/clock_gettime.c new file mode 100644 index 000000000..a86786bb2 --- /dev/null +++ b/newlib/libc/sys/linux/clock_gettime.c @@ -0,0 +1,109 @@ +/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +#if HP_TIMING_AVAIL +/* Clock frequency of the processor. We make it a 64-bit variable + because some jokers are already playing with processors with more + than 4GHz. */ +static hp_timing_t freq; + + +/* We need the starting time for the process. */ +extern hp_timing_t _dl_cpuclock_offset; + + +/* This function is defined in the thread library. */ +extern int __pthread_clock_gettime (hp_timing_t freq, struct timespec *tp) + __attribute__ ((__weak__)); +#endif + + +/* Get current value of CLOCK and store it in TP. */ +int +clock_gettime (clockid_t clock_id, struct timespec *tp) +{ + struct timeval tv; + int retval = -1; + + switch (clock_id) + { + case CLOCK_REALTIME: + retval = gettimeofday (&tv, NULL); + if (retval == 0) + /* Convert into `timespec'. */ + TIMEVAL_TO_TIMESPEC (&tv, tp); + break; + +#if HP_TIMING_AVAIL + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_THREAD_CPUTIME_ID: + { + hp_timing_t tsc; + + if (__builtin_expect (freq == 0, 0)) + { + /* This can only happen if we haven't initialized the `freq' + variable yet. Do this now. We don't have to protect this + code against multiple execution since all of them should + lead to the same result. */ + freq = __get_clockfreq (); + if (__builtin_expect (freq == 0, 0)) + /* Something went wrong. */ + break; + } + + if (clock_id == CLOCK_THREAD_CPUTIME_ID + && __pthread_clock_gettime != NULL) + { + retval = __pthread_clock_gettime (freq, tp); + break; + } + + /* Get the current counter. */ + HP_TIMING_NOW (tsc); + + /* Compute the offset since the start time of the process. */ + tsc -= _dl_cpuclock_offset; + + /* Compute the seconds. */ + tp->tv_sec = tsc / freq; + + /* And the nanoseconds. This computation should be stable until + we get machines with about 16GHz frequency. */ + tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq; + + retval = 0; + } + break; +#endif + + default: + __set_errno (EINVAL); + break; + } + + return retval; +} diff --git a/newlib/libc/sys/linux/clock_settime.c b/newlib/libc/sys/linux/clock_settime.c new file mode 100644 index 000000000..79a9b564a --- /dev/null +++ b/newlib/libc/sys/linux/clock_settime.c @@ -0,0 +1,111 @@ +/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +#if HP_TIMING_AVAIL +/* Clock frequency of the processor. We make it a 64-bit variable + because some jokers are already playing with processors with more + than 4GHz. */ +static hp_timing_t freq; + + +/* We need the starting time for the process. */ +extern hp_timing_t _dl_cpuclock_offset; + + +/* This function is defined in the thread library. */ +extern void __pthread_clock_settime (hp_timing_t offset) + __attribute__ ((__weak__)); +#endif + + +/* Set CLOCK to value TP. */ +int +clock_settime (clockid_t clock_id, const struct timespec *tp) +{ + struct timeval tv; + int retval; + + /* Make sure the time cvalue is OK. */ + if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + return -1; + } + + switch (clock_id) + { + case CLOCK_REALTIME: + TIMESPEC_TO_TIMEVAL (&tv, tp); + + retval = settimeofday (&tv, NULL); + break; + +#if HP_TIMING_AVAIL + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_THREAD_CPUTIME_ID: + { + hp_timing_t tsc; + hp_timing_t usertime; + + /* First thing is to get the current time. */ + HP_TIMING_NOW (tsc); + + if (__builtin_expect (freq == 0, 0)) + { + /* This can only happen if we haven't initialized the `freq' + variable yet. Do this now. We don't have to protect this + code against multiple execution since all of them should + lead to the same result. */ + freq = __get_clockfreq (); + if (__builtin_expect (freq == 0, 0)) + { + /* Something went wrong. */ + retval = -1; + break; + } + } + + /* Convert the user-provided time into CPU ticks. */ + usertime = tp->tv_sec * freq + (tp->tv_nsec * freq) / 1000000000ull; + + /* Determine the offset and use it as the new base value. */ + if (clock_id != CLOCK_THREAD_CPUTIME_ID + || __pthread_clock_settime == NULL) + _dl_cpuclock_offset = tsc - usertime; + else + __pthread_clock_settime (tsc - usertime); + + retval = 0; + } + break; +#endif + + default: + __set_errno (EINVAL); + retval = -1; + break; + } + + return retval; +} diff --git a/newlib/libc/sys/linux/hp-timing.h b/newlib/libc/sys/linux/hp-timing.h new file mode 100644 index 000000000..0507f444c --- /dev/null +++ b/newlib/libc/sys/linux/hp-timing.h @@ -0,0 +1 @@ +#include diff --git a/newlib/libc/sys/linux/include/time.h b/newlib/libc/sys/linux/include/time.h new file mode 100644 index 000000000..c27e502e6 --- /dev/null +++ b/newlib/libc/sys/linux/include/time.h @@ -0,0 +1,225 @@ +/* + * time.h + * + * Struct and function declarations for dealing with time. + */ + +#ifndef _TIME_H_ +#define _TIME_H_ + +#include "_ansi.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NULL +#define NULL 0 +#endif + +/* Get _CLOCKS_PER_SEC_ */ +#include + +#ifndef _CLOCKS_PER_SEC_ +#define _CLOCKS_PER_SEC_ 1000 +#endif + +#define CLOCKS_PER_SEC _CLOCKS_PER_SEC_ +#define CLK_TCK CLOCKS_PER_SEC +#define __need_size_t +#include + +#include + +struct tm +{ + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +#ifndef __timer_t_defined +# define __timer_t_defined 1 +typedef __timer_t timer_t; +#endif + +clock_t _EXFUN(clock, (void)); +double _EXFUN(difftime, (time_t _time2, time_t _time1)); +time_t _EXFUN(mktime, (struct tm *_timeptr)); +time_t _EXFUN(time, (time_t *_timer)); +#ifndef _REENT_ONLY +char *_EXFUN(asctime, (const struct tm *_tblock)); +char *_EXFUN(ctime, (const time_t *_time)); +struct tm *_EXFUN(gmtime, (const time_t *_timer)); +struct tm *_EXFUN(localtime,(const time_t *_timer)); +#endif +size_t _EXFUN(strftime, (char *_s, size_t _maxsize, const char *_fmt, const struct tm *_t)); + +char *_EXFUN(asctime_r, (const struct tm *, char *)); +char *_EXFUN(ctime_r, (const time_t *, char *)); +struct tm *_EXFUN(gmtime_r, (const time_t *, struct tm *)); +struct tm *_EXFUN(localtime_r, (const time_t *, struct tm *)); + +#ifndef __STRICT_ANSI__ +char *_EXFUN(strptime, (const char *, const char *, struct tm *)); +_VOID _EXFUN(tzset, (_VOID)); +_VOID _EXFUN(_tzset_r, (struct _reent *)); + +/* getdate functions */ + +#ifndef _REENT_ONLY +#define getdate_err (*__getdate_err()) +int *_EXFUN(__getdate_err,(_VOID)); + +struct tm * _EXFUN(getdate, (const char *)); +/* getdate_err is set to one of the following values to indicate the error. + 1 the DATEMSK environment variable is null or undefined, + 2 the template file cannot be opened for reading, + 3 failed to get file status information, + 4 the template file is not a regular file, + 5 an error is encountered while reading the template file, + 6 memory allication failed (not enough memory available), + 7 there is no line in the template that matches the input, + 8 invalid input specification */ +#endif /* !_REENT_ONLY */ + +/* getdate_r returns the error code as above */ +int _EXFUN(getdate_r, (const char *, struct tm *)); + +/* defines for the opengroup specifications Derived from Issue 1 of the SVID. */ +extern __IMPORT time_t _timezone; +extern __IMPORT int _daylight; +extern __IMPORT char *_tzname[2]; + +/* POSIX defines the external tzname being defined in time.h */ +#ifndef tzname +#define tzname _tzname +#endif + +/* CYGWIN also exposes daylight and timezone in the name space */ +#ifdef __CYGWIN__ +#ifndef daylight +#define daylight _daylight +#endif +#if timezonevar +#ifndef timezone +#define timezone ((long int) _timezone) +#endif +#else +char *_EXFUN(timezone, (void)); +#endif +#endif /* __CYGWIN__ */ +#endif /* !__STRICT_ANSI__ */ + +#include + +#if defined(_POSIX_TIMERS) + +#include + +/* Clocks, P1003.1b-1993, p. 263 */ + +int _EXFUN(clock_settime, (clockid_t clock_id, const struct timespec *tp)); +int _EXFUN(clock_gettime, (clockid_t clock_id, struct timespec *tp)); +int _EXFUN(clock_getres, (clockid_t clock_id, struct timespec *res)); + +/* Create a Per-Process Timer, P1003.1b-1993, p. 264 */ + +int _EXFUN(timer_create, + (clockid_t clock_id, struct sigevent *evp, timer_t *timerid)); + +/* Delete a Per_process Timer, P1003.1b-1993, p. 266 */ + +int _EXFUN(timer_delete, (timer_t timerid)); + +/* Per-Process Timers, P1003.1b-1993, p. 267 */ + +int _EXFUN(timer_settime, + (timer_t timerid, int flags, const struct itimerspec *value, + struct itimerspec *ovalue)); +int _EXFUN(timer_gettime, (timer_t timerid, struct itimerspec *value)); +int _EXFUN(timer_getoverrun, (timer_t timerid)); + +/* High Resolution Sleep, P1003.1b-1993, p. 269 */ + +int _EXFUN(nanosleep, (const struct timespec *rqtp, struct timespec *rmtp)); + +#endif /* _POSIX_TIMERS */ + +/* CPU-time Clock Attributes, P1003.4b/D8, p. 54 */ + +/* values for the clock enable attribute */ + +#define CLOCK_ENABLED 1 /* clock is enabled, i.e. counting execution time */ +#define CLOCK_DISABLED 0 /* clock is disabled */ + +/* values for the pthread cputime_clock_allowed attribute */ + +#define CLOCK_ALLOWED 1 /* If a thread is created with this value a */ + /* CPU-time clock attached to that thread */ + /* shall be accessible. */ +#define CLOCK_DISALLOWED 0 /* If a thread is created with this value, the */ + /* thread shall not have a CPU-time clock */ + /* accessible. */ + +/* Manifest Constants, P1003.1b-1993, p. 262 */ + +#define CLOCK_REALTIME (clockid_t)1 + +/* Flag indicating time is "absolute" with respect to the clock + associated with a time. */ + +#define TIMER_ABSTIME 4 + +/* Manifest Constants, P1003.4b/D8, p. 55 */ + +#if defined(_POSIX_CPUTIME) + +/* When used in a clock or timer function call, this is interpreted as + the identifier of the CPU_time clock associated with the PROCESS + making the function call. */ + +#define CLOCK_PROCESS_CPUTIME (clockid_t)2 + +#endif + +#if defined(_POSIX_THREAD_CPUTIME) + +/* When used in a clock or timer function call, this is interpreted as + the identifier of the CPU_time clock associated with the THREAD + making the function call. */ + +#define CLOCK_THREAD_CPUTIME (clockid_t)3 + +#endif + +#if defined(_POSIX_CPUTIME) + +/* Accessing a Process CPU-time CLock, P1003.4b/D8, p. 55 */ + +int _EXFUN(clock_getcpuclockid, (pid_t pid, clockid_t *clock_id)); + +#endif /* _POSIX_CPUTIME */ + +#if defined(_POSIX_CPUTIME) || defined(_POSIX_THREAD_CPUTIME) + +/* CPU-time Clock Attribute Access, P1003.4b/D8, p. 56 */ + +int _EXFUN(clock_setenable_attr, (clockid_t clock_id, int attr)); +int _EXFUN(clock_getenable_attr, (clockid_t clock_id, int *attr)); + +#endif /* _POSIX_CPUTIME or _POSIX_THREAD_CPUTIME */ + +#ifdef __cplusplus +} +#endif +#endif /* _TIME_H_ */ + diff --git a/newlib/libc/sys/linux/libc-internal.h b/newlib/libc/sys/linux/libc-internal.h new file mode 100644 index 000000000..a443ced18 --- /dev/null +++ b/newlib/libc/sys/linux/libc-internal.h @@ -0,0 +1,32 @@ +/* This file contains a number of internal prototype declarations that + don't fit anywhere else. */ + +#ifndef _LIBC_INTERNAL +# define _LIBC_INTERNAL 1 + +#include + +/* macro to set errno */ +#define __set_errno(x) (errno = (x)) + +/* Initialize the `__libc_enable_secure' flag. */ +extern void __libc_init_secure (void); + +/* This function will be called from _init in init-first.c. */ +extern void __libc_global_ctors (void); + +/* Discover the tick frequency of the machine if something goes wrong, + we return 0, an impossible hertz. */ +extern int __profile_frequency (void); + +/* Hooks for the instrumenting functions. */ +extern void __cyg_profile_func_enter (void *this_fn, void *call_site); +extern void __cyg_profile_func_exit (void *this_fn, void *call_site); + +/* Get frequency of the system processor. */ +extern hp_timing_t __get_clockfreq (void); + +/* Free all allocated resources. */ +extern void __libc_freeres (void); + +#endif /* _LIBC_INTERNAL */ diff --git a/newlib/libc/sys/linux/machine/hp-timing.h b/newlib/libc/sys/linux/machine/hp-timing.h new file mode 100644 index 000000000..099342db8 --- /dev/null +++ b/newlib/libc/sys/linux/machine/hp-timing.h @@ -0,0 +1,83 @@ +/* High precision, low overhead timing functions. Generic version. + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _HP_TIMING_H +#define _HP_TIMING_H 1 + + +/* There are no generic definitions for the times. We could write something + using the `gettimeofday' system call where available but the overhead of + the system call might be too high. + + In case a platform supports timers in the hardware the following macros + and types must be defined: + + - HP_TIMING_AVAIL: test for availability. + + - HP_TIMING_INLINE: this macro is non-zero if the functionality is not + implemented using function calls but instead uses some inlined code + which might simply consist of a few assembler instructions. We have to + know this since we might want to use the macros here in places where we + cannot make function calls. + + - hp_timing_t: This is the type for variables used to store the time + values. + + - HP_TIMING_ZERO: clear `hp_timing_t' object. + + - HP_TIMING_NOW: place timestamp for current time in variable given as + parameter. + + - HP_TIMING_DIFF_INIT: do whatever is necessary to be able to use the + HP_TIMING_DIFF macro. + + - HP_TIMING_DIFF: compute difference between two times and store it + in a third. Source and destination might overlap. + + - HP_TIMING_ACCUM: add time difference to another variable. This might + be a bit more complicated to implement for some platforms as the + operation should be thread-safe and 64bit arithmetic on 32bit platforms + is not. + + - HP_TIMING_ACCUM_NT: this is the variant for situations where we know + there are no threads involved. + + - HP_TIMING_PRINT: write decimal representation of the timing value into + the given string. This operation need not be inline even though + HP_TIMING_INLINE is specified. + +*/ + +/* Provide dummy definitions. */ +#define HP_TIMING_AVAIL (0) +#define HP_TIMING_INLINE (0) +typedef int hp_timing_t; +#define HP_TIMING_ZERO(Var) +#define HP_TIMING_NOW(var) +#define HP_TIMING_DIFF_INIT() +#define HP_TIMING_DIFF(Diff, Start, End) +#define HP_TIMING_ACCUM(Sum, Diff) +#define HP_TIMING_ACCUM_NT(Sum, Diff) +#define HP_TIMING_PRINT(Buf, Len, Val) + +/* Since this implementation is not available we tell the user about it. */ +#define HP_TIMING_NONAVAIL 1 + +#endif /* hp-timing.h */ diff --git a/newlib/libc/sys/linux/machine/i386/Makefile.am b/newlib/libc/sys/linux/machine/i386/Makefile.am index 596ff3e71..c64c43e0f 100644 --- a/newlib/libc/sys/linux/machine/i386/Makefile.am +++ b/newlib/libc/sys/linux/machine/i386/Makefile.am @@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS = cygnus INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) -LIB_SOURCES = setjmp.S sigaction.c +LIB_SOURCES = get_clockfreq.c hp-timing.c setjmp.S sigaction.c liblinuxi386_la_LDFLAGS = -Xcompiler -nostdlib diff --git a/newlib/libc/sys/linux/machine/i386/Makefile.in b/newlib/libc/sys/linux/machine/i386/Makefile.in index 78e2123b9..ac6d9589b 100644 --- a/newlib/libc/sys/linux/machine/i386/Makefile.in +++ b/newlib/libc/sys/linux/machine/i386/Makefile.in @@ -98,7 +98,7 @@ AUTOMAKE_OPTIONS = cygnus INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) -LIB_SOURCES = setjmp.S sigaction.c +LIB_SOURCES = get_clockfreq.c hp-timing.c setjmp.S sigaction.c liblinuxi386_la_LDFLAGS = -Xcompiler -nostdlib @@ -122,11 +122,14 @@ DEFS = @DEFS@ -I. -I$(srcdir) CPPFLAGS = @CPPFLAGS@ LIBS = @LIBS@ lib_a_LIBADD = -@USE_LIBTOOL_FALSE@lib_a_OBJECTS = setjmp.$(OBJEXT) sigaction.$(OBJEXT) +@USE_LIBTOOL_FALSE@lib_a_OBJECTS = get_clockfreq.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@hp-timing.$(OBJEXT) setjmp.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@sigaction.$(OBJEXT) LTLIBRARIES = $(noinst_LTLIBRARIES) liblinuxi386_la_LIBADD = -@USE_LIBTOOL_TRUE@liblinuxi386_la_OBJECTS = setjmp.lo sigaction.lo +@USE_LIBTOOL_TRUE@liblinuxi386_la_OBJECTS = get_clockfreq.lo \ +@USE_LIBTOOL_TRUE@hp-timing.lo setjmp.lo sigaction.lo CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) diff --git a/newlib/libc/sys/linux/machine/i386/get_clockfreq.c b/newlib/libc/sys/linux/machine/i386/get_clockfreq.c new file mode 100644 index 000000000..ea46ed427 --- /dev/null +++ b/newlib/libc/sys/linux/machine/i386/get_clockfreq.c @@ -0,0 +1,117 @@ +/* Get frequency of the system processor. i386/Linux version. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +static +void *memmem (const void *a, size_t len1, const void *b, size_t len2) +{ + char *end, *start; + char *ptr1, *ptr2; + + if (len2 > len1) + return NULL; + + start = (char *)a; + end = start + len1; + + while (start < end) + { + size_t len = len2; + ptr1 = start; + ptr2 = (char *)b; + while (len > 0 && *ptr1++ == *ptr2++) + --len; + if (len == 0) + return start; + ++start; + } + + return NULL; +} + +hp_timing_t +__get_clockfreq (void) +{ + /* We read the information from the /proc filesystem. It contains at + least one line like + cpu MHz : 497.840237 + or also + cpu MHz : 497.841 + We search for this line and convert the number in an integer. */ + static hp_timing_t result; + int fd; + + /* If this function was called before, we know the result. */ + if (result != 0) + return result; + + fd = open ("/proc/cpuinfo", O_RDONLY); + if (__builtin_expect (fd != -1, 1)) + { + /* XXX AFAIK the /proc filesystem can generate "files" only up + to a size of 4096 bytes. */ + char buf[4096]; + ssize_t n; + + n = read (fd, buf, sizeof buf); + if (__builtin_expect (n, 1) > 0) + { + char *mhz = memmem (buf, n, "cpu MHz", 7); + + if (__builtin_expect (mhz != NULL, 1)) + { + char *endp = buf + n; + int seen_decpoint = 0; + int ndigits = 0; + + /* Search for the beginning of the string. */ + while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n') + ++mhz; + + while (mhz < endp && *mhz != '\n') + { + if (*mhz >= '0' && *mhz <= '9') + { + result *= 10; + result += *mhz - '0'; + if (seen_decpoint) + ++ndigits; + } + else if (*mhz == '.') + seen_decpoint = 1; + + ++mhz; + } + + /* Compensate for missing digits at the end. */ + while (ndigits++ < 6) + result *= 10; + } + } + + close (fd); + } + + return result; +} diff --git a/newlib/libc/sys/linux/machine/i386/hp-timing.c b/newlib/libc/sys/linux/machine/i386/hp-timing.c new file mode 100644 index 000000000..c52099c73 --- /dev/null +++ b/newlib/libc/sys/linux/machine/i386/hp-timing.c @@ -0,0 +1,24 @@ +/* Support for high precision, low overhead timing functions. i686 version. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* We have to define the variable for the overhead. */ +hp_timing_t __libc_hp_timing_overhead; diff --git a/newlib/libc/sys/linux/machine/i386/hp-timing.h b/newlib/libc/sys/linux/machine/i386/hp-timing.h new file mode 100644 index 000000000..a34965ec8 --- /dev/null +++ b/newlib/libc/sys/linux/machine/i386/hp-timing.h @@ -0,0 +1,187 @@ +/* High precision, low overhead timing functions. i686 version. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Modified for newlib by Jeff Johnston - June 27, 2002 */ + +#ifndef _HP_TIMING_H +#define _HP_TIMING_H 1 + +#include +#include +#include + +#ifdef __i686__ + +/* The macros defined here use the timestamp counter in i586 and up versions + of the x86 processors. They provide a very accurate way to measure the + time with very little overhead. The time values themself have no real + meaning, only differences are interesting. + + This version is for the i686 processors. The difference to the i586 + version is that the timerstamp register is unconditionally used. This is + not the case for the i586 version where we have to perform runtime test + whether the processor really has this capability. We have to make this + distinction since the sysdeps/i386/i586 code is supposed to work on all + platforms while the i686 already contains i686-specific code. + + The list of macros we need includes the following: + + - HP_TIMING_AVAIL: test for availability. + + - HP_TIMING_INLINE: this macro is non-zero if the functionality is not + implemented using function calls but instead uses some inlined code + which might simply consist of a few assembler instructions. We have to + know this since we might want to use the macros here in places where we + cannot make function calls. + + - hp_timing_t: This is the type for variables used to store the time + values. + + - HP_TIMING_ZERO: clear `hp_timing_t' object. + + - HP_TIMING_NOW: place timestamp for current time in variable given as + parameter. + + - HP_TIMING_DIFF_INIT: do whatever is necessary to be able to use the + HP_TIMING_DIFF macro. + + - HP_TIMING_DIFF: compute difference between two times and store it + in a third. Source and destination might overlap. + + - HP_TIMING_ACCUM: add time difference to another variable. This might + be a bit more complicated to implement for some platforms as the + operation should be thread-safe and 64bit arithmetic on 32bit platforms + is not. + + - HP_TIMING_ACCUM_NT: this is the variant for situations where we know + there are no threads involved. + + - HP_TIMING_PRINT: write decimal representation of the timing value into + the given string. This operation need not be inline even though + HP_TIMING_INLINE is specified. + +*/ + +/* We always assume having the timestamp register. */ +#define HP_TIMING_AVAIL (1) + +/* We indeed have inlined functions. */ +#define HP_TIMING_INLINE (1) + +/* We use 64bit values for the times. */ +typedef unsigned long long int hp_timing_t; + +/* Internal variable used to store the overhead of the measurement + opcodes. */ +extern hp_timing_t __libc_hp_timing_overhead; + +/* Set timestamp value to zero. */ +#define HP_TIMING_ZERO(Var) (Var) = (0) + +/* That's quite simple. Use the `rdtsc' instruction. Note that the value + might not be 100% accurate since there might be some more instructions + running in this moment. This could be changed by using a barrier like + 'cpuid' right before the `rdtsc' instruciton. But we are not interested + in accurate clock cycles here so we don't do this. */ +#define HP_TIMING_NOW(Var) __asm__ __volatile__ ("rdtsc" : "=A" (Var)) + +/* Use two 'rdtsc' instructions in a row to find out how long it takes. */ +#define HP_TIMING_DIFF_INIT() \ + do { \ + int __cnt = 5; \ + __libc_hp_timing_overhead = ~0ull; \ + do \ + { \ + hp_timing_t __t1, __t2; \ + HP_TIMING_NOW (__t1); \ + HP_TIMING_NOW (__t2); \ + if (__t2 - __t1 < __libc_hp_timing_overhead) \ + __libc_hp_timing_overhead = __t2 - __t1; \ + } \ + while (--__cnt > 0); \ + } while (0) + +/* It's simple arithmetic for us. */ +#define HP_TIMING_DIFF(Diff, Start, End) (Diff) = ((End) - (Start)) + +/* We have to jump through hoops to get this correctly implemented. */ +#define HP_TIMING_ACCUM(Sum, Diff) \ + do { \ + char __not_done; \ + hp_timing_t __oldval = (Sum); \ + hp_timing_t __diff = (Diff) - __libc_hp_timing_overhead; \ + do \ + { \ + hp_timing_t __newval = __oldval + __diff; \ + int __temp0, __temp1; \ + __asm__ __volatile__ ("xchgl %4, %%ebx\n\t" \ + "lock; cmpxchg8b %1\n\t" \ + "sete %0\n\t" \ + "movl %4, %%ebx" \ + : "=q" (__not_done), "=m" (Sum), \ + "=A" (__oldval), "=c" (__temp0), \ + "=SD" (__temp1) \ + : "1" (Sum), "2" (__oldval), \ + "3" (__newval >> 32), \ + "4" (__newval & 0xffffffff) \ + : "memory"); \ + } \ + while (__not_done); \ + } while (0) + +/* No threads, no extra work. */ +#define HP_TIMING_ACCUM_NT(Sum, Diff) (Sum) += (Diff) + +/* Print the time value. */ +#define HP_TIMING_PRINT(Buf, Len, Val) \ + do { \ + char __buf[20]; \ + char *__cp = __buf + sizeof (__buf); \ + int __len = (Len); \ + char *__dest = (Buf); \ + do { \ + *--__cp = Val % 10; \ + Val /= 10; \ + } while (Val > 0); \ + while (__len-- > 0 && __cp < __buf + sizeof (__buf)) \ + *__dest++ = *__cp++; \ + memcpy (__dest, " clock cycles", MIN (__len, sizeof (" clock cycles"))); \ + } while (0) + +#else /* !__i686__ */ + +/* Provide dummy definitions. */ +#define HP_TIMING_AVAIL (0) +#define HP_TIMING_INLINE (0) +typedef int hp_timing_t; +#define HP_TIMING_ZERO(Var) +#define HP_TIMING_NOW(var) +#define HP_TIMING_DIFF_INIT() +#define HP_TIMING_DIFF(Diff, Start, End) +#define HP_TIMING_ACCUM(Sum, Diff) +#define HP_TIMING_ACCUM_NT(Sum, Diff) +#define HP_TIMING_PRINT(Buf, Len, Val) + +/* Since this implementation is not available we tell the user about it. */ +#define HP_TIMING_NONAVAIL 1 + +#endif + +#endif /* hp-timing.h */ diff --git a/newlib/libc/sys/linux/sys/linux_time.h b/newlib/libc/sys/linux/sys/linux_time.h new file mode 100644 index 000000000..9328aec58 --- /dev/null +++ b/newlib/libc/sys/linux/sys/linux_time.h @@ -0,0 +1,73 @@ +#ifndef _LINUX_TIME_H +#define _LINUX_TIME_H + +#include +#include + +#ifndef _STRUCT_TIMESPEC +#define _STRUCT_TIMESPEC +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; +#endif /* _STRUCT_TIMESPEC */ + +/* + * Change timeval to jiffies, trying to avoid the + * most obvious overflows.. + * + * And some not so obvious. + * + * Note that we don't want to return MAX_LONG, because + * for various timeout reasons we often end up having + * to wait "jiffies+1" in order to guarantee that we wait + * at _least_ "jiffies" - so "jiffies+1" had better still + * be positive. + */ +#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1) + +static __inline__ unsigned long +timespec_to_jiffies(struct timespec *value) +{ + unsigned long sec = value->tv_sec; + long nsec = value->tv_nsec; + + if (sec >= (MAX_JIFFY_OFFSET / HZ)) + return MAX_JIFFY_OFFSET; + nsec += 1000000000L / HZ - 1; + nsec /= 1000000000L / HZ; + return HZ * sec + nsec; +} + +static __inline__ void +jiffies_to_timespec(unsigned long jiffies, struct timespec *value) +{ + value->tv_nsec = (jiffies % HZ) * (1000000000L / HZ); + value->tv_sec = jiffies / HZ; +} + +struct timeval { + time_t tv_sec; /* seconds */ + suseconds_t tv_usec; /* microseconds */ +}; + +struct timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +#define ITIMER_REAL 0 +#define ITIMER_VIRTUAL 1 +#define ITIMER_PROF 2 + +struct itimerspec { + struct timespec it_interval; /* timer period */ + struct timespec it_value; /* timer expiration */ +}; + +struct itimerval { + struct timeval it_interval; /* timer interval */ + struct timeval it_value; /* current value */ +}; + +#endif diff --git a/newlib/libc/sys/linux/sys/time.h b/newlib/libc/sys/linux/sys/time.h index 42487d62e..d18076477 100644 --- a/newlib/libc/sys/linux/sys/time.h +++ b/newlib/libc/sys/linux/sys/time.h @@ -42,7 +42,7 @@ #define _SYS_TIME_H #include -#include +#include /* Macros for converting between `struct timeval' and `struct timespec'. */ # define TIMEVAL_TO_TIMESPEC(tv, ts) { \ diff --git a/newlib/libc/sys/linux/sysconf.c b/newlib/libc/sys/linux/sysconf.c index f953efe5d..037ae54bf 100644 --- a/newlib/libc/sys/linux/sysconf.c +++ b/newlib/libc/sys/linux/sysconf.c @@ -201,7 +201,7 @@ sysconf (int name) case _SC_ASYNCHRONOUS_IO: #ifdef _POSIX_ASYNCHRONOUS_IO - return 1;TZNAME_MAX; + return 1; #else return -1; #endif -- cgit v1.2.3