(root)/
gcc-13.2.0/
libgfortran/
intrinsics/
time_1.h
       1  /* Wrappers for platform timing functions.
       2     Copyright (C) 2003-2023 Free Software Foundation, Inc.
       3  
       4  This file is part of the GNU Fortran runtime library (libgfortran).
       5  
       6  Libgfortran is free software; you can redistribute it and/or
       7  modify it under the terms of the GNU General Public
       8  License as published by the Free Software Foundation; either
       9  version 3 of the License, or (at your option) any later version.
      10  
      11  Libgfortran is distributed in the hope that it will be useful,
      12  but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14  GNU General Public License for more details.
      15  
      16  Under Section 7 of GPL version 3, you are granted additional
      17  permissions described in the GCC Runtime Library Exception, version
      18  3.1, as published by the Free Software Foundation.
      19  
      20  You should have received a copy of the GNU General Public License and
      21  a copy of the GCC Runtime Library Exception along with this program;
      22  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      23  <http://www.gnu.org/licenses/>.  */
      24  
      25  #ifndef LIBGFORTRAN_TIME_H
      26  #define LIBGFORTRAN_TIME_H
      27  
      28  #ifdef HAVE_UNISTD_H
      29  #include <unistd.h>
      30  #endif
      31  
      32  #include <errno.h>
      33  
      34  /* The time related intrinsics (DTIME, ETIME, CPU_TIME) to "compare
      35     different algorithms on the same computer or discover which parts
      36     are the most expensive", need a way to get the CPU time with the
      37     finest resolution possible. We can only be accurate up to
      38     microseconds.
      39  
      40     As usual with UNIX systems, unfortunately no single way is
      41     available for all systems.  */
      42  
      43  #ifdef HAVE_SYS_TIME_H
      44  #include <sys/time.h>
      45  #endif
      46  
      47  #include <time.h>
      48  
      49  #ifdef HAVE_SYS_TYPES_H
      50       #include <sys/types.h>
      51  #endif
      52  
      53  /* The most accurate way to get the CPU time is getrusage (). */
      54  #if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
      55  #  include <sys/resource.h>
      56  #endif  /* HAVE_GETRUSAGE && HAVE_SYS_RESOURCE_H  */
      57  
      58  /* The most accurate way to get the CPU time is getrusage ().
      59     If we have times(), that's good enough, too.  */
      60  #if !defined (HAVE_GETRUSAGE) || !defined (HAVE_SYS_RESOURCE_H)
      61  /* For times(), we _must_ know the number of clock ticks per second.  */
      62  #  if defined (HAVE_TIMES) && (defined (HZ) || defined (_SC_CLK_TCK) || defined (CLK_TCK))
      63  #    ifdef HAVE_SYS_PARAM_H
      64  #      include <sys/param.h>
      65  #    endif
      66  #    if defined (HAVE_SYS_TIMES_H)
      67  #      include <sys/times.h>
      68  #    endif
      69  #    ifndef HZ
      70  #      if defined _SC_CLK_TCK
      71  #        define HZ  sysconf(_SC_CLK_TCK)
      72  #      else
      73  #        define HZ  CLK_TCK
      74  #      endif
      75  #    endif
      76  #  endif  /* HAVE_TIMES etc.  */
      77  #endif  /* !HAVE_GETRUSAGE || !HAVE_SYS_RESOURCE_H  */
      78  
      79  
      80  /* If the re-entrant version of localtime is not available, provide a
      81     fallback implementation.  On some targets where the _r version is
      82     not available, localtime uses thread-local storage so it's
      83     threadsafe.  */
      84  
      85  #ifndef HAVE_LOCALTIME_R
      86  /* If _POSIX is defined localtime_r gets defined by mingw-w64 headers.  */
      87  #ifdef localtime_r
      88  #undef localtime_r
      89  #endif
      90  
      91  static inline struct tm *
      92  localtime_r (const time_t * timep, struct tm * result)
      93  {
      94    *result = *localtime (timep);
      95    return result;
      96  }
      97  #endif
      98  
      99  
     100  /* Helper function for the actual implementation of the DTIME, ETIME and
     101     CPU_TIME intrinsics.  Returns 0 for success or -1 if no
     102     CPU time could be computed.  */
     103  
     104  #if defined(__MINGW32__)
     105  
     106  #define WIN32_LEAN_AND_MEAN
     107  #include <windows.h>
     108  
     109  static inline int
     110  gf_cputime (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
     111  {
     112    union {
     113      FILETIME ft;
     114      unsigned long long ulltime;
     115    } kernel_time,  user_time;
     116  
     117    FILETIME unused1, unused2;
     118  
     119    /* No support for Win9x.  The high order bit of the DWORD
     120       returned by GetVersion is 0 for NT and higher. */
     121    if (GetVersion () >= 0x80000000)
     122      {
     123        *user_sec = *system_sec = 0;
     124        *user_usec = *system_usec = 0;
     125        return -1;
     126      }
     127  
     128    /* The FILETIME structs filled in by GetProcessTimes represent
     129       time in 100 nanosecond units. */
     130    GetProcessTimes (GetCurrentProcess (), &unused1, &unused2,
     131                	   &kernel_time.ft, &user_time.ft);
     132  
     133    *user_sec = user_time.ulltime / 10000000;
     134    *user_usec = (user_time.ulltime % 10000000) / 10;
     135  
     136    *system_sec = kernel_time.ulltime / 10000000;
     137    *system_usec = (kernel_time.ulltime % 10000000) / 10;
     138    return 0;
     139  }
     140  
     141  #else
     142  
     143  static inline int
     144  gf_cputime (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
     145  {
     146  #if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
     147    struct rusage usage;
     148    int err;
     149    err = getrusage (RUSAGE_SELF, &usage);
     150  
     151    *user_sec = usage.ru_utime.tv_sec;
     152    *user_usec = usage.ru_utime.tv_usec;
     153    *system_sec = usage.ru_stime.tv_sec;
     154    *system_usec = usage.ru_stime.tv_usec;
     155    return err;
     156  
     157  #elif defined HAVE_TIMES
     158    struct tms buf;
     159    clock_t err;
     160    err = times (&buf);
     161    long hz = HZ;
     162    *user_sec = buf.tms_utime / hz;
     163    *user_usec = (buf.tms_utime % hz) * (1000000. / hz);
     164    *system_sec = buf.tms_stime / hz;
     165    *system_usec = (buf.tms_stime % hz) * (1000000. / hz);
     166    if ((err == (clock_t) -1) && errno != 0)
     167      return -1;
     168    return 0;
     169  
     170  #elif defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_PROCESS_CPUTIME_ID) \
     171  				      || defined(CLOCK_THREAD_CPUTIME_ID))
     172    /* Newer versions of VxWorks have CLOCK_THREAD_CPUTIME_ID giving
     173       per-thread CPU time.  CLOCK_PROCESS_CPUTIME_ID would be better
     174       but is not available.  */
     175  #ifndef CLOCK_PROCESS_CPUTIME_ID
     176  #define CLOCK_PROCESS_CPUTIME_ID CLOCK_THREAD_CPUTIME_ID
     177  #endif
     178    struct timespec ts;
     179    int err = clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts);
     180    *user_sec = ts.tv_sec;
     181    *user_usec = ts.tv_nsec / 1000;
     182    *system_sec = *system_usec = 0;
     183    return err;
     184  
     185  #else 
     186    clock_t c = clock ();
     187    *user_sec = c / CLOCKS_PER_SEC;
     188    *user_usec = (c % CLOCKS_PER_SEC) * (1000000. / CLOCKS_PER_SEC);
     189    *system_sec = *system_usec = 0;
     190    if (c == (clock_t) -1)
     191      return -1;
     192    return 0;
     193  
     194  #endif
     195  }
     196  
     197  #endif
     198  
     199  
     200  /* Realtime clock with microsecond resolution, falling back to other
     201     functions if the target does not support gettimeofday().
     202  
     203     Arguments:
     204     secs     - OUTPUT, seconds
     205     usecs    - OUTPUT, microseconds
     206  
     207     The OUTPUT arguments shall represent the number of seconds and
     208     microseconds since the Epoch.
     209  
     210     Return value: 0 for success, -1 for error. In case of error, errno
     211     is set.
     212  */
     213  static inline int
     214  gf_gettime (time_t * secs, long * usecs)
     215  {
     216  #ifdef HAVE_CLOCK_GETTIME
     217    struct timespec ts;
     218    int err = clock_gettime (CLOCK_REALTIME, &ts);
     219    *secs = ts.tv_sec;
     220    *usecs = ts.tv_nsec / 1000;
     221    return err;
     222  #elif defined(HAVE_GETTIMEOFDAY)
     223    struct timeval tv;
     224    int err;
     225    err = gettimeofday (&tv, NULL);
     226    *secs = tv.tv_sec;
     227    *usecs = tv.tv_usec;
     228    return err;
     229  #else
     230    time_t t = time (NULL);
     231    *secs = t;
     232    *usecs = 0;
     233    if (t == ((time_t)-1))
     234      return -1;
     235    return 0;
     236  #endif
     237  }
     238  
     239  
     240  #endif /* LIBGFORTRAN_TIME_H */