| /* wrapclock.cc provides access to time related system calls. | |
| Copyright (C) 2009-2022 Free Software Foundation, Inc. | |
| Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>. | |
| 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 | |
| <http://www.gnu.org/licenses/>. */ | |
| #include "config.h" | |
| #include <m2rts.h> | |
| #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 <sys/time.h> | |
| #endif | |
| #if defined(_GLIBCXX_USE_CLOCK_GETTIME_SYSCALL) | |
| #include <unistd.h> | |
| #include <sys/syscall.h> | |
| #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)); | |
| } |