Blame gl/gettimeofday.c

Packit aea12f
/* Provide gettimeofday for systems that don't have it or for which it's broken.
Packit aea12f
Packit Service 991b93
   Copyright (C) 2001-2003, 2005-2007, 2009-2020 Free Software Foundation, Inc.
Packit aea12f
Packit aea12f
   This program is free software; you can redistribute it and/or modify
Packit Service 991b93
   it under the terms of the GNU Lesser General Public License as published by
Packit Service 991b93
   the Free Software Foundation; either version 2.1, or (at your option)
Packit aea12f
   any later version.
Packit aea12f
Packit aea12f
   This program is distributed in the hope that it will be useful,
Packit aea12f
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit aea12f
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 991b93
   GNU Lesser General Public License for more details.
Packit aea12f
Packit Service 991b93
   You should have received a copy of the GNU Lesser General Public License
Packit aea12f
   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
Packit aea12f
Packit aea12f
/* written by Jim Meyering */
Packit aea12f
Packit aea12f
#include <config.h>
Packit aea12f
Packit aea12f
/* Specification.  */
Packit aea12f
#include <sys/time.h>
Packit aea12f
Packit aea12f
#include <time.h>
Packit aea12f
Packit aea12f
#if defined _WIN32 && ! defined __CYGWIN__
Packit aea12f
# define WINDOWS_NATIVE
Packit aea12f
# include <windows.h>
Packit aea12f
#endif
Packit aea12f
Packit aea12f
#include "localtime-buffer.h"
Packit aea12f
Packit aea12f
#ifdef WINDOWS_NATIVE
Packit aea12f
Packit Service 991b93
# if !(_WIN32_WINNT >= _WIN32_WINNT_WIN8)
Packit Service 991b93
Packit aea12f
/* Avoid warnings from gcc -Wcast-function-type.  */
Packit Service 991b93
#  define GetProcAddress \
Packit Service 991b93
    (void *) GetProcAddress
Packit aea12f
Packit aea12f
/* GetSystemTimePreciseAsFileTime was introduced only in Windows 8.  */
Packit aea12f
typedef void (WINAPI * GetSystemTimePreciseAsFileTimeFuncType) (FILETIME *lpTime);
Packit aea12f
static GetSystemTimePreciseAsFileTimeFuncType GetSystemTimePreciseAsFileTimeFunc = NULL;
Packit aea12f
static BOOL initialized = FALSE;
Packit aea12f
Packit aea12f
static void
Packit aea12f
initialize (void)
Packit aea12f
{
Packit aea12f
  HMODULE kernel32 = LoadLibrary ("kernel32.dll");
Packit aea12f
  if (kernel32 != NULL)
Packit aea12f
    {
Packit aea12f
      GetSystemTimePreciseAsFileTimeFunc =
Packit aea12f
        (GetSystemTimePreciseAsFileTimeFuncType) GetProcAddress (kernel32, "GetSystemTimePreciseAsFileTime");
Packit aea12f
    }
Packit aea12f
  initialized = TRUE;
Packit aea12f
}
Packit aea12f
Packit Service 991b93
# else
Packit Service 991b93
Packit Service 991b93
#  define GetSystemTimePreciseAsFileTimeFunc GetSystemTimePreciseAsFileTime
Packit Service 991b93
Packit Service 991b93
# endif
Packit Service 991b93
Packit aea12f
#endif
Packit aea12f
Packit aea12f
/* This is a wrapper for gettimeofday.  It is used only on systems
Packit aea12f
   that lack this function, or whose implementation of this function
Packit aea12f
   causes problems.
Packit aea12f
   Work around the bug in some systems whereby gettimeofday clobbers
Packit aea12f
   the static buffer that localtime uses for its return value.  The
Packit aea12f
   gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has
Packit aea12f
   this problem.  */
Packit aea12f
Packit aea12f
int
Packit aea12f
gettimeofday (struct timeval *restrict tv, void *restrict tz)
Packit aea12f
{
Packit aea12f
#undef gettimeofday
Packit aea12f
#ifdef WINDOWS_NATIVE
Packit aea12f
Packit aea12f
  /* On native Windows, there are two ways to get the current time:
Packit aea12f
     GetSystemTimeAsFileTime
Packit aea12f
     <https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime>
Packit aea12f
     or
Packit aea12f
     GetSystemTimePreciseAsFileTime
Packit aea12f
     <https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime>.
Packit aea12f
     GetSystemTimeAsFileTime produces values that jump by increments of
Packit aea12f
     15.627 milliseconds (!) on average.
Packit aea12f
     Whereas GetSystemTimePreciseAsFileTime values usually jump by 1 or 2
Packit aea12f
     microseconds.
Packit aea12f
     More discussion on this topic:
Packit aea12f
     <http://www.windowstimestamp.com/description>.  */
Packit aea12f
  FILETIME current_time;
Packit aea12f
Packit Service 991b93
# if !(_WIN32_WINNT >= _WIN32_WINNT_WIN8)
Packit aea12f
  if (!initialized)
Packit aea12f
    initialize ();
Packit Service 991b93
# endif
Packit aea12f
  if (GetSystemTimePreciseAsFileTimeFunc != NULL)
Packit aea12f
    GetSystemTimePreciseAsFileTimeFunc (&current_time);
Packit aea12f
  else
Packit aea12f
    GetSystemTimeAsFileTime (&current_time);
Packit aea12f
Packit aea12f
  /* Convert from FILETIME to 'struct timeval'.  */
Packit aea12f
  /* FILETIME: <https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-filetime> */
Packit aea12f
  ULONGLONG since_1601 =
Packit aea12f
    ((ULONGLONG) current_time.dwHighDateTime << 32)
Packit aea12f
    | (ULONGLONG) current_time.dwLowDateTime;
Packit aea12f
  /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89 leap
Packit aea12f
     years, in total 134774 days.  */
Packit aea12f
  ULONGLONG since_1970 =
Packit aea12f
    since_1601 - (ULONGLONG) 134774 * (ULONGLONG) 86400 * (ULONGLONG) 10000000;
Packit aea12f
  ULONGLONG microseconds_since_1970 = since_1970 / (ULONGLONG) 10;
Packit aea12f
  tv->tv_sec = microseconds_since_1970 / (ULONGLONG) 1000000;
Packit aea12f
  tv->tv_usec = microseconds_since_1970 % (ULONGLONG) 1000000;
Packit aea12f
Packit aea12f
  return 0;
Packit aea12f
Packit aea12f
#else
Packit aea12f
Packit aea12f
# if HAVE_GETTIMEOFDAY
Packit aea12f
#  if GETTIMEOFDAY_CLOBBERS_LOCALTIME
Packit aea12f
  /* Save and restore the contents of the buffer used for localtime's
Packit aea12f
     result around the call to gettimeofday.  */
Packit aea12f
  struct tm save = *localtime_buffer_addr;
Packit aea12f
#  endif
Packit aea12f
Packit aea12f
#  if defined timeval /* 'struct timeval' overridden by gnulib?  */
Packit aea12f
#   undef timeval
Packit aea12f
  struct timeval otv;
Packit aea12f
  int result = gettimeofday (&otv, (struct timezone *) tz);
Packit aea12f
  if (result == 0)
Packit aea12f
    {
Packit aea12f
      tv->tv_sec = otv.tv_sec;
Packit aea12f
      tv->tv_usec = otv.tv_usec;
Packit aea12f
    }
Packit aea12f
#  else
Packit aea12f
  int result = gettimeofday (tv, (struct timezone *) tz);
Packit aea12f
#  endif
Packit aea12f
Packit aea12f
#  if GETTIMEOFDAY_CLOBBERS_LOCALTIME
Packit aea12f
  *localtime_buffer_addr = save;
Packit aea12f
#  endif
Packit aea12f
Packit aea12f
  return result;
Packit aea12f
Packit aea12f
# else
Packit aea12f
Packit aea12f
#  if !defined OK_TO_USE_1S_CLOCK
Packit aea12f
#   error "Only 1-second nominal clock resolution found.  Is that intended?" \
Packit aea12f
          "If so, compile with the -DOK_TO_USE_1S_CLOCK option."
Packit aea12f
#  endif
Packit aea12f
  tv->tv_sec = time (NULL);
Packit aea12f
  tv->tv_usec = 0;
Packit aea12f
Packit aea12f
  return 0;
Packit aea12f
Packit aea12f
# endif
Packit aea12f
#endif
Packit aea12f
}