time_1.h 6.6 KB

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