
This patch adds corrections to defensively check against glibc functions, structures and contains fallbacks. These fixes were required under Darwin. gcc/m2/ChangeLog: PR modula2/110779 * gm2-libs-iso/SysClock.mod (EpochTime): New procedure. (GetClock): Call EpochTime if the C time functions are unavailable. * gm2-libs-iso/wrapclock.def (istimezone): New function definition. libgm2/ChangeLog: PR modula2/110779 * configure: Regenerate. * configure.ac: Provide special case test for Darwin cross configuration. (GLIBCXX_CONFIGURE): New statement. (GLIBCXX_CHECK_GETTIMEOFDAY): New statement. (GLIBCXX_ENABLE_LIBSTDCXX_TIME): New statement. * libm2iso/wrapclock.cc: New sys/time.h conditional include. (sys/syscall.h): Conditional include. (unistd.h): Conditional include. (GetTimeRealtime): Re-implement. (SetTimeRealtime): Re-implement. (timezone): Re-implement. (istimezone): New function. (daylight): Re-implement. (isdst): Re-implement. (tzname): Re-implement. Signed-off-by: Gaius Mulley <gaiusmod2@gmail.com>
339 lines
7 KiB
C++
339 lines
7 KiB
C++
/* 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
|
|
|
|
|
|
/* 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, unsigned long *sec, unsigned long *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, unsigned long *sec, unsigned long *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, unsigned long sec, unsigned long 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, unsigned long sec, unsigned long nano)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
extern "C" long int
|
|
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;
|
|
}
|
|
else
|
|
#endif
|
|
#endif
|
|
{
|
|
#if defined(HAVE_TIMEZONE)
|
|
return timezone;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* 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));
|
|
}
|