| /* 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)); |
| } |