Merge remote-tracking branch 'origin/release-v4.6.1'
[WRF.git] / frame / hires_timer.c
blob163f5e3b58e8305470c78fe328c7369cda909741
1 /* hires_timer: this implements a cross-platform, high temporal
2 resolution timer using POSIX standard C routines. Call
3 init_hires_timer to initialize and call hires_timer to get the time
4 in seconds since the call to init_hires_timer as a double (fortran
5 REAL(KIND=8)).
7 On platforms that support clock_gettime, nanosecond resolution will
8 be provided. On platforms that don't, gettimeofday will be used,
9 and microsecond resolution will be provided.
11 If init_hires_timer is never called, the time returned is seconds
12 since the system epoch, but with lower precision. On unix, the
13 epoch is midnight, the morning of January 1, 1970, in either UTC or
14 GMT depending on your particular flavor of unix. However, a
15 double-precision floating point number cannot represent the time in
16 seconds since that epoch to nanosecond resolution, so you'll end up
17 with something more like 10^-5 second resolution unless you call
18 init_hires_timer.
21 #include <time.h>
22 #include <sys/time.h>
23 #include <stdlib.h>
25 #if defined(OLD_TIMERS)
26 /* User does not want to use the high-res timers. To
27 make sure they are not used, we don't even compile
28 them. We'll make sure the object file isn't empty
29 though, to avoid confusing ld: */
30 void hires_timer_dummy() {
31 return;
33 #else
35 static int initialized=0; /* =1 if start and startnano are valid */
37 static time_t start_ipart=0; /* integer part of starting time in seconds */
38 static double start_fpart=0; /* fractional part */
40 /* DETERMINE IF CLOCK_GETTIME IS AVAILABLE */
42 #define USE_HIRES 0
43 #if defined(_POSIX_TIMERS)
44 #if ( _POSIX_TIMERS > 0 )
45 /* According to the POSIX standard, we only get here if the system
46 supports clock_gettime. */
47 #define USE_HIRES 1
48 #endif
49 #endif
51 void init_hires_timer() {
52 #if ( USE_HIRES == 1 )
53 struct timespec when;
54 if(!clock_gettime(CLOCK_REALTIME,&when)) {
55 start_ipart=when.tv_sec;
56 start_fpart=when.tv_nsec/1e9;
57 } else { /* clock_gettime failed */
58 #endif
59 struct timeval tv;
60 if(!gettimeofday(&tv,NULL)) {
61 start_ipart=tv.tv_sec;
62 start_fpart=tv.tv_usec/1e6;
63 } else {
64 /* Should never get here; gettimeofday never fails
65 unless tv is outside of the address space. Just
66 as a paranoid fallback, we check for a failure
67 and use time() */
68 start_ipart=time(NULL);
69 start_fpart=0;
71 #if ( USE_HIRES == 1 )
73 #endif
74 initialized=1;
78 void hires_timer(double *d) {
79 struct timeval tv;
80 #if ( USE_HIRES == 1 )
81 struct timespec when;
82 #endif
83 if(!initialized) init_hires_timer();
84 #if ( USE_HIRES == 1 )
85 if(!clock_gettime(CLOCK_REALTIME,&when)) {
86 *d=(double)(when.tv_sec-start_ipart) + ( ((double)when.tv_nsec)/1e9 - start_fpart );
87 } else { /* clock_gettime failed */
88 #endif
89 if(!gettimeofday(&tv,NULL)) {
90 *d=(double)(tv.tv_sec-start_ipart) + ( ((double)tv.tv_usec)/1e6 - start_fpart );
91 } else {
92 /* Should never get here; gettimeofday never fails
93 unless tv is outside of the address space. Just
94 as a paranoid fallback, we check for a failure
95 and use time() */
96 *d=(double)(time(NULL)-start_ipart) - start_fpart;
98 #if ( USE_HIRES == 1 )
100 #endif
103 /* Support all common fortran name mangling schemes: */
104 void hires_timer_(double *d) { hires_timer(d); }
105 void hires_timer__(double *d) { hires_timer(d); }
106 void HIRES_TIMER(double *d) { hires_timer(d); }
107 void HIRES_TIMER_(double *d) { hires_timer(d); }
108 void HIRES_TIMER__(double *d) { hires_timer(d); }
110 void init_hires_timer_() { init_hires_timer(); }
111 void init_hires_timer__() { init_hires_timer(); }
112 void INIT_HIRES_TIMER() { init_hires_timer(); }
113 void INIT_HIRES_TIMER_() { init_hires_timer(); }
114 void INIT_HIRES_TIMER__() { init_hires_timer(); }
116 #endif /* ELSE for the "if(OLD_TIMERS)" */