PR modula2/110779 SysClock can not read the clock (Darwin portability fixes)

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>
This commit is contained in:
Gaius Mulley 2023-08-12 18:17:41 +01:00
parent 46905fcde0
commit 63fb0bedb8
5 changed files with 227 additions and 96 deletions

View File

@ -173,6 +173,26 @@ BEGIN
END ExtractDate ;
(*
EpochTime - assigns all fields of userData to 0 or FALSE.
*)
PROCEDURE EpochTime (VAR userData: DateTime) ;
BEGIN
WITH userData DO
second := 0 ;
minute := 0 ;
hour := 0 ;
year := 0 ;
month := 0 ;
day := 0 ;
fractions := 0 ;
zone := 0 ;
summerTimeFlag := FALSE
END
END EpochTime ;
PROCEDURE GetClock (VAR userData: DateTime) ;
(* Assigns local date and time of the day to userData *)
VAR
@ -207,10 +227,10 @@ BEGIN
summerTimeFlag := (isdst () = 1)
END
ELSE
HALT
EpochTime (userData)
END
ELSE
HALT
EpochTime (userData)
END ;
ts := KillTimespec (ts)
END
@ -310,13 +330,11 @@ BEGIN
userData.month, userData.year) ;
offset := timezone () ;
sec := VAL (LONGINT, sec) - offset ;
IF SetTimespec (ts, sec, nano) = 0
IF SetTimespec (ts, sec, nano) = 1
THEN
HALT
END ;
IF SetTimeRealtime (ts) # 0
THEN
HALT
IF SetTimeRealtime (ts) = 0
THEN
END
END ;
ts := KillTimespec (ts)
END

View File

@ -36,11 +36,23 @@ TYPE
timezone - return the glibc timezone value.
This contains the difference between UTC and the latest
local standard time, in seconds west of UTC.
If the underlying timezone is unavailable and
clock_gettime, localtime_r, tm_gmtoff
is unavailable then 0 is returned.
*)
PROCEDURE timezone () : LONGINT ;
(*
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.
*)
PROCEDURE istimezone () : INTEGER ;
(*
daylight - return the glibc daylight value.
This variable has a nonzero value if Daylight Saving

40
libgm2/configure vendored
View File

@ -3976,6 +3976,42 @@ test -n "$target_alias" &&
target_alias=${target_alias-$host_alias}
if test "$build" != "$host"; then
# We are being configured with some form of cross compiler.
GLIBCXX_IS_NATIVE=false
case "$host","$target" in
# Darwin crosses can use the host system's libraries and headers,
# because of the fat library support. Of course, it must be the
# same version of Darwin on both sides. Allow the user to
# just say --target=foo-darwin without a version number to mean
# "the version on this system".
*-*-darwin*,*-*-darwin*)
hostos=`echo $host | sed 's/.*-darwin/darwin/'`
targetos=`echo $target | sed 's/.*-darwin/darwin/'`
if test $hostos = $targetos || test $targetos = darwin ; then
GLIBCXX_IS_NATIVE=true
fi
;;
*)
;;
esac
else
GLIBCXX_IS_NATIVE=true
fi
# Runs configure.host, and assorted other critical bits. Sets
# up critical shell variables.
GLIBCXX_CONFIGURE
# For gettimeofday support.
GLIBCXX_CHECK_GETTIMEOFDAY
# For clock_gettime, nanosleep and sched_yield support.
GLIBCXX_ENABLE_LIBSTDCXX_TIME
am__api_version='1.15'
# Find a good install program. We prefer a C program (faster),
@ -12702,7 +12738,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 12705 "configure"
#line 12741 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -12808,7 +12844,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 12811 "configure"
#line 12847 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H

View File

@ -42,6 +42,42 @@ AC_CANONICAL_SYSTEM
target_alias=${target_alias-$host_alias}
AC_SUBST(target_alias)
if test "$build" != "$host"; then
# We are being configured with some form of cross compiler.
GLIBCXX_IS_NATIVE=false
case "$host","$target" in
# Darwin crosses can use the host system's libraries and headers,
# because of the fat library support. Of course, it must be the
# same version of Darwin on both sides. Allow the user to
# just say --target=foo-darwin without a version number to mean
# "the version on this system".
*-*-darwin*,*-*-darwin*)
hostos=`echo $host | sed 's/.*-darwin/darwin/'`
targetos=`echo $target | sed 's/.*-darwin/darwin/'`
if test $hostos = $targetos || test $targetos = darwin ; then
GLIBCXX_IS_NATIVE=true
fi
;;
*)
GCC_NO_EXECUTABLES
;;
esac
else
GLIBCXX_IS_NATIVE=true
fi
# Runs configure.host, and assorted other critical bits. Sets
# up critical shell variables.
GLIBCXX_CONFIGURE
# For gettimeofday support.
GLIBCXX_CHECK_GETTIMEOFDAY
# For clock_gettime, nanosleep and sched_yield support.
GLIBCXX_ENABLE_LIBSTDCXX_TIME
AM_INIT_AUTOMAKE([1.15.1 no-define foreign no-dist -Wall -Wno-portability])
AH_TEMPLATE(PACKAGE, [Name of package])

View File

@ -51,6 +51,18 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#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
@ -64,91 +76,19 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif
extern "C" long int
EXPORT(timezone) (void)
{
#if defined(HAVE_STRUCT_TM) && defined(HAVE_STRUCT_TIMESPEC)
struct tm result;
struct timespec ts;
#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_TM_TM_GMTOFF)
if (clock_gettime (CLOCK_REALTIME, &ts) == 0)
{
time_t time = ts.tv_sec;
localtime_r (&time, &result);
return result.tm_gmtoff;
}
else
#endif
#endif
return timezone;
}
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_TM) && defined(HAVE_STRUCT_TIMESPEC)
struct tm result;
struct timespec ts;
#if defined(HAVE_CLOCK_SETTIME)
if (clock_gettime (CLOCK_REALTIME, &ts) == 0)
{
time_t time = ts.tv_sec;
localtime_r (&time, &result);
return result.tm_isdst;
}
else
#endif
#endif
return 0;
}
/* 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
}
/* 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)
#if defined(HAVE_STRUCT_TIMESPEC) && defined(_GLIBCXX_USE_CLOCK_REALTIME)
extern "C" int
EXPORT(GetTimeRealtime) (struct timespec *ts)
{
#if defined(HAVE_CLOCK_GETTIME)
return clock_gettime (CLOCK_REALTIME, ts);
timespec tp;
#if defined(_GLIBCXX_USE_CLOCK_GETTIME_SYSCALL)
return syscall (SYS_clock_gettime, CLOCK_REALTIME, ts);
#else
return 1;
return clock_gettime (CLOCK_REALTIME, ts);
#endif
}
@ -161,16 +101,17 @@ EXPORT(GetTimeRealtime) (void *ts)
}
#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)
#if defined(HAVE_STRUCT_TIMESPEC) && defined(_GLIBCXX_USE_CLOCK_REALTIME)
extern "C" int
EXPORT(SetTimeRealtime) (struct timespec *ts)
{
#if defined(HAVE_CLOCK_GETTIME)
#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;
@ -186,7 +127,6 @@ EXPORT(SetTimeRealtime) (void *ts)
}
#endif
/* InitTimespec returns a newly created opaque type. */
#if defined(HAVE_STRUCT_TIMESPEC)
@ -209,7 +149,6 @@ EXPORT(InitTimespec) (void)
}
#endif
/* KillTimeval deallocates the memory associated with an opaque type. */
#if defined(HAVE_STRUCT_TIMESPEC)
@ -231,9 +170,8 @@ EXPORT(KillTimespec) (void *ts)
}
#endif
/* GetTimespec retrieves the number of seconds and nanoseconds from the
timespec. */
timespec. 1 is returned if successful and 0 otherwise. */
#if defined(HAVE_STRUCT_TIMESPEC)
extern "C" int
@ -256,8 +194,8 @@ EXPORT(GetTimespec) (void *ts, unsigned long *sec, unsigned long *nano)
}
#endif
/* SetTimespec sets the number of seconds and nanoseconds into timespec. */
/* 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
@ -281,6 +219,97 @@ EXPORT(SetTimespec) (void *ts, unsigned long sec, unsigned long nano)
}
#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 */