forked from ColinIanKing/stress-ng
-
Notifications
You must be signed in to change notification settings - Fork 0
/
core-time.c
155 lines (135 loc) · 4.07 KB
/
core-time.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
* Copyright (C) 2013-2021 Canonical, Ltd.
* Copyright (C) 2022 Colin Ian King.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "stress-ng.h"
#define SECONDS_IN_MINUTE (60.0)
#define SECONDS_IN_HOUR (60.0 * SECONDS_IN_MINUTE)
#define SECONDS_IN_DAY (24.0 * SECONDS_IN_HOUR)
#define SECONDS_IN_YEAR (365.2425 * SECONDS_IN_DAY)
/* Approx, for Gregorian calendar */
/*
* stress_timeval_to_double()
* convert timeval to seconds as a double
*/
double OPTIMIZE3 stress_timeval_to_double(const struct timeval *tv)
{
return (double)tv->tv_sec + ((double)tv->tv_usec * ONE_MILLIONTH);
}
/*
* stress_timespec_to_double()
* convert timespec to seconds as a double
*/
double OPTIMIZE3 stress_timespec_to_double(const struct timespec *ts)
{
return (double)ts->tv_sec + ((double)ts->tv_nsec * ONE_BILLIONTH);
}
static OPTIMIZE3 double stress_time_now_timeval(void)
{
struct timeval now;
if (gettimeofday(&now, NULL) < 0)
return -1.0;
return stress_timeval_to_double(&now);
}
static OPTIMIZE3 double stress_time_now_timespec(void)
{
#if defined(HAVE_CLOCK_GETTIME) && \
defined(CLOCK_MONOTONIC)
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
return -1.0;
return stress_timespec_to_double(&ts);
#else
return -1.0;
#endif
}
static double (*stress_time_now_func)(void) = stress_time_now_timespec;
/*
* stress_time_now()
* time in seconds as a double
*/
double OPTIMIZE3 stress_time_now(void)
{
const double now = stress_time_now_func();
if (LIKELY(now) >= 0.0)
return now;
/*
* It failed, check if we used clock_gettime and if so
* drop back to use gettimeofday instead
*/
if (LIKELY(stress_time_now_func == stress_time_now_timespec)) {
/*
* Drop to older 1/1000000th second resolution clock
*/
stress_time_now_func = stress_time_now_timeval;
return stress_time_now_timeval();
}
/* Unlikey, no time available! */
return -1.0;
}
/*
* stress_format_time()
* format a unit of time into human readable format
*/
static inline void stress_format_time(
const bool last, /* Last unit to format */
const double secs_in_units, /* Seconds in the specific time unit */
const char *units, /* Unit of time */
char **ptr, /* Destination string ptr */
double *duration, /* Duration left in seconds */
size_t *len) /* Length of string left at ptr */
{
const unsigned long val = (unsigned long)(*duration / secs_in_units);
if (last || (val > 0)) {
int ret;
if (last)
ret = snprintf(*ptr, *len, "%.2f %ss", *duration, units);
else
ret = snprintf(*ptr, *len, "%lu %s%s, ", val, units,
(val > 1) ? "s" : "");
if (ret > 0) {
*len -= (size_t)ret;
*ptr += ret;
}
}
*duration -= secs_in_units * (double)val;
}
/*
* stress_duration_to_str
* duration in seconds to a human readable string
*/
const char *stress_duration_to_str(const double duration)
{
static char str[128];
char *ptr = str;
size_t len = sizeof(str) - 1;
double dur = duration;
*str = '\0';
if (duration > 60.0) {
(void)shim_strlcpy(ptr, " (", len);
ptr += 2;
len -= 2;
stress_format_time(false, SECONDS_IN_YEAR, "year", &ptr, &dur, &len);
stress_format_time(false, SECONDS_IN_DAY, "day", &ptr, &dur, &len);
stress_format_time(false, SECONDS_IN_HOUR, "hour", &ptr, &dur, &len);
stress_format_time(false, SECONDS_IN_MINUTE, "min", &ptr, &dur, &len);
stress_format_time(true, 1, "sec", &ptr, &dur, &len);
(void)shim_strlcpy(ptr, ")", len);
}
return str;
}