/* wrapclock.cc provides access to time related system calls. Copyright (C) 2009-2022 Free Software Foundation, Inc. Contributed by Gaius Mulley . This file is part of GNU Modula-2. GNU Modula-2 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 3, or (at your option) any later version. GNU Modula-2 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. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ #include "config.h" #include #define EXPORT(FUNC) m2iso ## _wrapclock_ ## FUNC #define M2EXPORT(FUNC) m2iso ## _M2_wrapclock_ ## FUNC #define M2LIBNAME "m2iso" #if defined(HAVE_STDLIB_H) #include "stdlib.h" #endif #if defined(HAVE_UNISTD_H) #include "unistd.h" #endif #if defined(HAVE_SYS_TYPES_H) #include "sys/types.h" #endif #if defined(HAVE_SYS_TIME_H) #include "sys/time.h" #endif #if defined(HAVE_TIME_H) #include "time.h" #endif // Conditional inclusion of sys/time.h for gettimeofday #if !defined(_GLIBCXX_USE_CLOCK_MONOTONIC) && \ !defined(_GLIBCXX_USE_CLOCK_REALTIME) && \ defined(_GLIBCXX_USE_GETTIMEOFDAY) #include #endif #if defined(_GLIBCXX_USE_CLOCK_GETTIME_SYSCALL) #include #include #endif #if defined(HAVE_MALLOC_H) #include "malloc.h" #endif #if defined(HAVE_LIMITS_H) #include "limits.h" #endif #if !defined(NULL) #define NULL (void *)0 #endif typedef long long int longint_t; /* GetTimeRealtime performs return gettime (CLOCK_REALTIME, ts). gettime returns 0 on success and -1 on failure. If the underlying system does not have gettime then GetTimeRealtime returns 1. */ #if defined(HAVE_STRUCT_TIMESPEC) && defined(_GLIBCXX_USE_CLOCK_REALTIME) extern "C" int EXPORT(GetTimeRealtime) (struct timespec *ts) { timespec tp; #if defined(_GLIBCXX_USE_CLOCK_GETTIME_SYSCALL) return syscall (SYS_clock_gettime, CLOCK_REALTIME, ts); #else return clock_gettime (CLOCK_REALTIME, ts); #endif } #else extern "C" int EXPORT(GetTimeRealtime) (void *ts) { return 1; } #endif /* SetTimeRealtime performs return settime (CLOCK_REALTIME, ts). gettime returns 0 on success and -1 on failure. If the underlying system does not have gettime then GetTimeRealtime returns 1. */ #if defined(HAVE_STRUCT_TIMESPEC) && defined(_GLIBCXX_USE_CLOCK_REALTIME) extern "C" int EXPORT(SetTimeRealtime) (struct timespec *ts) { #if defined(_GLIBCXX_USE_CLOCK_SETTIME_SYSCALL) return syscall (SYS_clock_settime, CLOCK_REALTIME, ts); #elif defined(HAVE_CLOCK_SETTIME) return clock_settime (CLOCK_REALTIME, ts); #else return 1; #endif } #else extern "C" int EXPORT(SetTimeRealtime) (void *ts) { return 1; } #endif /* InitTimespec returns a newly created opaque type. */ #if defined(HAVE_STRUCT_TIMESPEC) extern "C" struct timespec * EXPORT(InitTimespec) (void) { #if defined(HAVE_STRUCT_TIMESPEC) && defined(HAVE_MALLOC_H) return (struct timespec *)malloc (sizeof (struct timespec)); #else return NULL; #endif } #else extern "C" void * EXPORT(InitTimespec) (void) { return NULL; } #endif /* KillTimeval deallocates the memory associated with an opaque type. */ #if defined(HAVE_STRUCT_TIMESPEC) extern "C" struct timespec * EXPORT(KillTimespec) (void *ts) { #if defined(HAVE_MALLOC_H) free (ts); #endif return NULL; } #else extern "C" void * EXPORT(KillTimespec) (void *ts) { return NULL; } #endif /* GetTimespec retrieves the number of seconds and nanoseconds from the timespec. 1 is returned if successful and 0 otherwise. */ #if defined(HAVE_STRUCT_TIMESPEC) extern "C" int EXPORT(GetTimespec) (timespec *ts, longint_t *sec, longint_t *nano) { #if defined(HAVE_STRUCT_TIMESPEC) *sec = ts->tv_sec; *nano = ts->tv_nsec; return 1; #else return 0; #endif } #else extern "C" int EXPORT(GetTimespec) (void *ts, longint_t *sec, longint_t *nano) { return 0; } #endif /* SetTimespec sets the number of seconds and nanoseconds into timespec. 1 is returned if successful and 0 otherwise. */ #if defined(HAVE_STRUCT_TIMESPEC) extern "C" int EXPORT(SetTimespec) (timespec *ts, longint_t sec, longint_t nano) { #if defined(HAVE_STRUCT_TIMESPEC) ts->tv_sec = sec; ts->tv_nsec = nano; return 1; #else return 0; #endif } #else extern "C" int EXPORT(SetTimespec) (void *ts, longint_t sec, longint_t nano) { return 0; } #endif extern "C" longint_t EXPORT(timezone) (void) { #if defined(HAVE_STRUCT_TIMESPEC) struct tm result; struct timespec ts; #if defined(HAVE_TM_TM_GMTOFF) if (EXPORT(GetTimeRealtime) (&ts) == 0) { time_t time = ts.tv_sec; localtime_r (&time, &result); return result.tm_gmtoff; } #endif #endif return 0; } /* istimezone returns 1 if timezone in wrapclock.cc can resolve the timezone value using the timezone C library call or by using clock_gettime, localtime_r and tm_gmtoff. */ extern "C" int EXPORT(istimezone) (void) { #if defined(HAVE_STRUCT_TIMESPEC) #if defined(HAVE_TM_TM_GMTOFF) #if defined(_GLIBCXX_USE_CLOCK_REALTIME) return 1; #endif #endif #endif return 0; } extern "C" int EXPORT(daylight) (void) { #if defined(HAVE_DAYLIGHT) return daylight; #else return 0; #endif } /* isdst returns 1 if daylight saving time is currently in effect and returns 0 if it is not. */ extern "C" int EXPORT(isdst) (void) { #if defined(HAVE_STRUCT_TIMESPEC) struct tm result; struct timespec ts; if (EXPORT(GetTimeRealtime) (&ts) == 0) { time_t time = ts.tv_sec; localtime_r (&time, &result); return result.tm_isdst; } else return 0; #else return 0; #endif } /* tzname returns the string associated with the local timezone. The daylight value is 0 or 1. The value 0 returns the non daylight saving timezone string and the value of 1 returns the daylight saving timezone string. It returns NULL if tzname is unavailable. */ extern "C" char * EXPORT(tzname) (int daylight) { #if defined(HAVE_TZNAME) return tzname[daylight]; #else return NULL; #endif } /* init - init/finish functions for the module */ /* GNU Modula-2 linking hooks. */ extern "C" void M2EXPORT(init) (int, char **, char **) { } extern "C" void M2EXPORT(fini) (int, char **, char **) { } extern "C" void M2EXPORT(dep) (void) { } extern "C" void __attribute__((__constructor__)) M2EXPORT(ctor) (void) { m2iso_M2RTS_RegisterModule ("wrapclock", M2LIBNAME, M2EXPORT(init), M2EXPORT(fini), M2EXPORT(dep)); }