passenger 5.0.26 → 5.0.27

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +17 -0
  3. data/CONTRIBUTORS +1 -0
  4. data/build/cxx_dependency_map.rb +113 -157
  5. data/build/cxx_tests.rb +8 -1
  6. data/src/agent/Core/ApplicationPool/TestSession.h +5 -1
  7. data/src/agent/Core/Controller/CheckoutSession.cpp +1 -1
  8. data/src/agent/Core/Controller/ForwardResponse.cpp +9 -0
  9. data/src/agent/Core/Controller/InternalUtils.cpp +9 -1
  10. data/src/agent/Core/Controller/SendRequest.cpp +13 -7
  11. data/src/agent/Core/Controller/StateInspectionAndConfiguration.cpp +3 -2
  12. data/src/agent/Core/CoreMain.cpp +3 -0
  13. data/src/agent/Core/SpawningKit/SmartSpawner.h +1 -1
  14. data/src/agent/Core/SpawningKit/Spawner.h +2 -2
  15. data/src/agent/Core/UnionStation/StopwatchLog.h +3 -4
  16. data/src/agent/Shared/Base.cpp +32 -0
  17. data/src/agent/Shared/Base.h +2 -0
  18. data/src/agent/UstRouter/UstRouterMain.cpp +3 -0
  19. data/src/agent/Watchdog/AgentWatcher.cpp +1 -3
  20. data/src/agent/Watchdog/WatchdogMain.cpp +31 -6
  21. data/src/apache2_module/Hooks.cpp +2 -2
  22. data/src/cxx_supportlib/BackgroundEventLoop.cpp +12 -2
  23. data/src/cxx_supportlib/Constants.h +1 -1
  24. data/src/cxx_supportlib/DataStructures/LString.cpp +39 -0
  25. data/src/cxx_supportlib/DataStructures/LString.h +35 -6
  26. data/src/cxx_supportlib/FileDescriptor.h +3 -1
  27. data/src/cxx_supportlib/Integrations/LibevJsonUtils.h +92 -0
  28. data/src/cxx_supportlib/ResourceLocator.h +10 -8
  29. data/src/cxx_supportlib/ServerKit/CookieUtils.h +4 -0
  30. data/src/cxx_supportlib/ServerKit/FileBufferedChannel.h +2 -0
  31. data/src/cxx_supportlib/ServerKit/HttpServer.h +6 -2
  32. data/src/cxx_supportlib/Utils.cpp +4 -5
  33. data/src/cxx_supportlib/Utils.h +2 -2
  34. data/src/cxx_supportlib/Utils/IOUtils.cpp +1 -1
  35. data/src/cxx_supportlib/Utils/JsonUtils.h +12 -10
  36. data/src/cxx_supportlib/Utils/MessagePassing.h +4 -4
  37. data/src/cxx_supportlib/Utils/StrIntUtils.cpp +7 -3
  38. data/src/cxx_supportlib/Utils/SystemTime.cpp +15 -4
  39. data/src/cxx_supportlib/Utils/SystemTime.h +228 -54
  40. data/src/cxx_supportlib/Utils/Timer.h +14 -41
  41. data/src/cxx_supportlib/WatchdogLauncher.h +1 -1
  42. data/src/cxx_supportlib/vendor-copy/libuv/Makefile.in +198 -59
  43. data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/output.0 +15477 -0
  44. data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/output.1 +15477 -0
  45. data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/requests +324 -0
  46. data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/traces.0 +3105 -0
  47. data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/traces.1 +703 -0
  48. data/src/cxx_supportlib/vendor-copy/libuv/configure +115 -12
  49. data/src/cxx_supportlib/vendor-copy/libuv/ltmain.sh +15 -8
  50. data/src/cxx_supportlib/vendor-copy/libuv/m4/ltversion.m4 +5 -5
  51. data/src/cxx_supportlib/vendor-modified/psg_sysqueue.h +1 -0
  52. data/src/nginx_module/ngx_http_passenger_module.c +1 -1
  53. data/src/nodejs_supportlib/phusion_passenger/ustreporter.js +1 -1
  54. data/src/ruby_native_extension/passenger_native_support.c +1 -1
  55. data/src/ruby_supportlib/phusion_passenger.rb +15 -1
  56. data/src/ruby_supportlib/phusion_passenger/common_library.rb +4 -0
  57. data/src/ruby_supportlib/phusion_passenger/packaging.rb +1 -0
  58. data/src/ruby_supportlib/phusion_passenger/ruby_core_io_enhancements.rb +5 -20
  59. metadata +9 -2
@@ -286,11 +286,10 @@ resolveSymlink(const StaticString &path) {
286
286
 
287
287
  string
288
288
  extractDirName(const StaticString &path) {
289
- char *path_copy = strdup(path.c_str());
290
- char *result = dirname(path_copy);
291
- string result_string(result);
292
- free(path_copy);
293
- return result_string;
289
+ DynamicBuffer pathCopy(path.size() + 1);
290
+ memcpy(pathCopy.data, path.data(), path.size());
291
+ pathCopy.data[path.size()] = '\0';
292
+ return string(dirname(pathCopy.data));
294
293
  }
295
294
 
296
295
  StaticString
@@ -178,8 +178,8 @@ string canonicalizePath(const string &path);
178
178
  string resolveSymlink(const StaticString &path);
179
179
 
180
180
  /**
181
- * Given a path, extracts its directory name.
182
- * <em>path</em> MUST be null-terminated!
181
+ * Given a path, extracts its directory name. 'path' does not
182
+ * have to be NULL terminated.
183
183
  *
184
184
  * @ingroup Support
185
185
  */
@@ -772,7 +772,7 @@ waitUntilIOEvent(int fd, short event, unsigned long long *timeout) {
772
772
  pfd.events = event;
773
773
  pfd.revents = 0;
774
774
 
775
- Timer timer;
775
+ Timer<> timer;
776
776
  ret = syscalls::poll(&pfd, 1, *timeout / 1000);
777
777
  if (ret == -1) {
778
778
  int e = errno;
@@ -208,27 +208,29 @@ timeToJson(unsigned long long timestamp, unsigned long long now = 0) {
208
208
  }
209
209
 
210
210
  Json::Value doc;
211
- time_t time = (time_t) timestamp / 1000000;
212
- char buf[32];
211
+ time_t wallClockTime = (time_t) (timestamp / 1000000ull);
212
+ char wallClockTimeStr[32];
213
213
  size_t len;
214
214
 
215
215
  if (now == 0) {
216
216
  now = SystemTime::getUsec();
217
217
  }
218
218
 
219
- doc["timestamp"] = timestamp / (double) 1000000;
220
-
221
- ctime_r(&time, buf);
222
- len = strlen(buf);
219
+ ctime_r(&wallClockTime, wallClockTimeStr);
220
+ len = strlen(wallClockTimeStr);
223
221
  if (len > 0) {
224
222
  // Get rid of trailing newline
225
- buf[len - 1] = '\0';
223
+ wallClockTimeStr[len - 1] = '\0';
226
224
  }
227
- doc["local"] = buf;
225
+
226
+ doc["timestamp"] = timestamp / 1000000.0;
227
+ doc["local"] = wallClockTimeStr;
228
228
  if (timestamp > now) {
229
- doc["relative"] = distanceOfTimeInWords(time) + " from now";
229
+ doc["relative_timestamp"] = (timestamp - now) / 1000000.0;
230
+ doc["relative"] = distanceOfTimeInWords(wallClockTime, now / 1000000ull) + " from now";
230
231
  } else {
231
- doc["relative"] = distanceOfTimeInWords(time) + " ago";
232
+ doc["relative_timestamp"] = (now - timestamp) / -1000000.0;
233
+ doc["relative"] = distanceOfTimeInWords(wallClockTime, now / 1000000ull) + " ago";
232
234
  }
233
235
 
234
236
  return doc;
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2012-2015 Phusion Holding B.V.
3
+ * Copyright (c) 2012-2016 Phusion Holding B.V.
4
4
  *
5
5
  * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
6
  * trademarks of Phusion Holding B.V.
@@ -183,7 +183,7 @@ class MessageBox: public boost::enable_shared_from_this<MessageBox> {
183
183
  }
184
184
 
185
185
  void substractTimePassed(unsigned long long *timeout, unsigned long long beginTime) {
186
- unsigned long long now = SystemTime::getMsec();
186
+ unsigned long long now = SystemTime::getMonotonicUsec();
187
187
  unsigned long long diff;
188
188
  if (now > beginTime) {
189
189
  diff = now - beginTime;
@@ -224,7 +224,7 @@ public:
224
224
  posix_time::ptime deadline;
225
225
  unsigned long long beginTime = 0; // Shut up compiler warning.
226
226
  if (timeout != NULL) {
227
- beginTime = SystemTime::getUsec();
227
+ beginTime = SystemTime::getMonotonicUsec();
228
228
  deadline = posix_time::microsec_clock::local_time() +
229
229
  posix_time::microsec(*timeout);
230
230
  }
@@ -263,7 +263,7 @@ public:
263
263
  posix_time::ptime deadline;
264
264
  unsigned long long beginTime = 0; // Shut up compiler warning.
265
265
  if (timeout != NULL) {
266
- beginTime = SystemTime::getUsec();
266
+ beginTime = SystemTime::getMonotonicUsec();
267
267
  deadline = posix_time::microsec_clock::local_time() +
268
268
  posix_time::microsec(*timeout);
269
269
  }
@@ -654,9 +654,13 @@ escapeHTML(const StaticString &input) {
654
654
  if (ch & 128) {
655
655
  // Multibyte UTF-8 character.
656
656
  const char *prev = current;
657
- utf8::advance(current, 1, end);
658
- result.append(prev, current - prev);
659
-
657
+ try {
658
+ utf8::advance(current, 1, end);
659
+ result.append(prev, current - prev);
660
+ } catch (const utf8::invalid_utf8 &e) {
661
+ result.append("?"); // Oops, not UTF-8 after all, don't parse it.
662
+ current++;
663
+ }
660
664
  } else {
661
665
  // ASCII character <= 127.
662
666
  if (ch == '<') {
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2010 Phusion Holding B.V.
3
+ * Copyright (c) 2010-2016 Phusion Holding B.V.
4
4
  *
5
5
  * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
6
  * trademarks of Phusion Holding B.V.
@@ -24,15 +24,26 @@
24
24
  * THE SOFTWARE.
25
25
  */
26
26
 
27
- #include <time.h>
27
+ #include <Utils/SystemTime.h>
28
28
 
29
29
  namespace Passenger {
30
30
  namespace SystemTimeData {
31
+ bool initialized = false;
31
32
  bool hasForcedValue = false;
32
33
  time_t forcedValue = 0;
33
- bool hasForcedMsecValue = false;
34
- unsigned long long forcedMsecValue = 0;
35
34
  bool hasForcedUsecValue = false;
36
35
  unsigned long long forcedUsecValue = 0;
36
+
37
+ #if BOOST_OS_MACOS
38
+ mach_timebase_info_data_t timeInfo;
39
+ #elif defined(SYSTEM_TIME_HAVE_MONOTONIC_CLOCK)
40
+ #ifdef SYSTEM_TIME_HAVE_CLOCK_MONOTONIC_COARSE
41
+ unsigned long long monotonicCoarseResolutionNs = 0;
42
+ #endif
43
+ #ifdef SYSTEM_TIME_HAVE_CLOCK_MONOTONIC_FAST
44
+ unsigned long long monotonicFastResolutionNs = 0;
45
+ #endif
46
+ unsigned long long monotonicResolutionNs;
47
+ #endif
37
48
  }
38
49
  }
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2010 Phusion Holding B.V.
3
+ * Copyright (c) 2010-2016 Phusion Holding B.V.
4
4
  *
5
5
  * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
6
  * trademarks of Phusion Holding B.V.
@@ -27,34 +27,221 @@
27
27
  #define _PASSENGER_SYSTEM_TIME_H_
28
28
 
29
29
  #include <boost/thread.hpp>
30
+ #include <boost/predef.h>
31
+ #include <oxt/macros.hpp>
30
32
  #include <oxt/system_calls.hpp>
31
- #include "../Exceptions.h"
33
+ #include <sys/time.h>
34
+ #include <cerrno>
35
+ #include <time.h>
36
+ #include <unistd.h>
37
+ #include <Exceptions.h>
38
+
39
+ #if BOOST_OS_MACOS
40
+ #include <mach/mach.h>
41
+ #include <mach/mach_time.h>
42
+ #include <cstring>
43
+ #elif BOOST_OS_AIX
44
+ #include <sys/systemcfg.h>
45
+ #elif defined(_POSIX_MONOTONIC_CLOCK) || defined(CLOCK_MONOTONIC)
46
+ #define SYSTEM_TIME_HAVE_MONOTONIC_CLOCK
47
+ #ifdef CLOCK_MONOTONIC_COARSE
48
+ #define SYSTEM_TIME_HAVE_CLOCK_MONOTONIC_COARSE
49
+ #endif
50
+ #ifdef CLOCK_MONOTONIC_FAST
51
+ #define SYSTEM_TIME_HAVE_CLOCK_MONOTONIC_FAST
52
+ #endif
53
+ #endif
32
54
 
33
55
  namespace Passenger {
34
56
 
57
+ using namespace std;
35
58
  using namespace oxt;
36
59
 
37
60
  namespace SystemTimeData {
61
+ extern bool initialized;
38
62
  extern bool hasForcedValue;
39
63
  extern time_t forcedValue;
40
- extern bool hasForcedMsecValue;
41
- extern unsigned long long forcedMsecValue;
42
64
  extern bool hasForcedUsecValue;
43
65
  extern unsigned long long forcedUsecValue;
66
+
67
+ #if BOOST_OS_MACOS
68
+ extern mach_timebase_info_data_t timeInfo;
69
+ #elif defined(SYSTEM_TIME_HAVE_MONOTONIC_CLOCK)
70
+ #ifdef SYSTEM_TIME_HAVE_CLOCK_MONOTONIC_COARSE
71
+ extern unsigned long long monotonicCoarseResolutionNs;
72
+ #endif
73
+ #ifdef SYSTEM_TIME_HAVE_CLOCK_MONOTONIC_FAST
74
+ extern unsigned long long monotonicFastResolutionNs;
75
+ #endif
76
+ extern unsigned long long monotonicResolutionNs;
77
+ #endif
44
78
  }
45
79
 
80
+ typedef unsigned long long MonotonicTimeUsec;
81
+
46
82
  /**
47
83
  * This class allows one to obtain the system time, similar to time() and
48
84
  * gettimeofday(). Unlike time(), it is possible to force a certain time
49
85
  * to be returned, which is useful for testing code that depends on the
50
86
  * system time.
51
87
  *
52
- * get() provides seconds resolution while getMsec() provides milliseconds
88
+ * get() provides seconds resolution while getUsec() provides microseconds
53
89
  * resolution. Both clocks can be independently forced to a certain value
54
- * through force() and forceMsec().
90
+ * through force() and forceUsec().
91
+ *
92
+ * In addition, getMonotonicUsec() returns the monotonic clock in
93
+ * microseconds. This can also be forced to a certain value using forceUsec().
94
+ *
95
+ * Before using any SystemTime functions, you should call
96
+ * SystemTime::initialize(). If you don't do that, then initialize() will be
97
+ * called for you, but since initialize() isn't thread-safe you should
98
+ * call it at the beginning of your program.
55
99
  */
56
100
  class SystemTime {
57
101
  public:
102
+ enum Granularity {
103
+ GRAN_1SEC = 1000000000, // 1 millisecond granularity
104
+ GRAN_10MSEC = 10000000, // 10 milliseconds granularity
105
+ GRAN_1MSEC = 1000000, // 1 millisecond granularity
106
+ GRAN_1USEC = 1000 // 1 microsecond granularty
107
+ };
108
+
109
+ private:
110
+ static void initializeIfNeeded() {
111
+ if (OXT_UNLIKELY(!SystemTimeData::initialized)) {
112
+ initialize();
113
+ }
114
+ }
115
+
116
+ template<Granularity granularityNs>
117
+ static MonotonicTimeUsec _getMonotonicUsec() {
118
+ if (OXT_UNLIKELY(SystemTimeData::hasForcedUsecValue)) {
119
+ return SystemTimeData::hasForcedValue;
120
+ }
121
+
122
+ #if BOOST_OS_MACOS
123
+ initializeIfNeeded();
124
+ if (SystemTimeData::timeInfo.numer == 0
125
+ && SystemTimeData::timeInfo.denom == 0)
126
+ {
127
+ return getUsec();
128
+ } else {
129
+ return mach_absolute_time()
130
+ * SystemTimeData::timeInfo.numer
131
+ / SystemTimeData::timeInfo.denom
132
+ / 1000;
133
+ }
134
+
135
+ #elif BOOST_OS_SOLARIS
136
+ return gethrtime() / 1000ull;
137
+
138
+ #elif BOOST_OS_AIX
139
+ timebasestruct_t t;
140
+ read_wall_time(&t, TIMEBASE_SZ);
141
+ time_base_to_time(&t, TIMEBASE_SZ);
142
+ return t.tb_high * 1000000ull + t.tb_low / 1000ull;
143
+
144
+ #elif defined(SYSTEM_TIME_HAVE_MONOTONIC_CLOCK)
145
+ clockid_t clockId = (clockid_t) -1;
146
+ struct timespec ts;
147
+ int ret;
148
+
149
+ initializeIfNeeded();
150
+
151
+ // We choose a different monotonic clock
152
+ // based on the resolution we need. In general,
153
+ // coarser resolutions are faster, for example
154
+ // because (on Linux) they are implemented
155
+ // through VDSOs instead of system calls.
156
+ //
157
+ // Benchmarks and properties as of 10 March 2016:
158
+ //
159
+ // FreeBSD 10.2 (200000 iterations):
160
+ // CLOCK_MONOTONIC 1m 9s 11 nanosec resolution
161
+ // CLOCK_MONOTONIC_PRECISE 1m 9s 11 nanosec resolution
162
+ // CLOCK_MONOTONIC_FAST 2s 11 nanosec resolution
163
+ // gettimeofday 1m 9s
164
+ //
165
+ // Linux 3.13.0 (100000000 iterations):
166
+ // CLOCK_MONOTONIC 1.5s 1 nanosec resolution
167
+ // CLOCK_MONOTONIC_COARSE 0.45s 4 millisec resolution
168
+ // gettimeofday 1.5s
169
+
170
+ #ifdef SYSTEM_TIME_HAVE_CLOCK_MONOTONIC_COARSE
171
+ if (clockId == -1
172
+ && SystemTimeData::monotonicCoarseResolutionNs != 0
173
+ && SystemTimeData::monotonicCoarseResolutionNs <= granularityNs)
174
+ {
175
+ clockId = CLOCK_MONOTONIC_COARSE;
176
+ }
177
+ #endif
178
+ #ifdef SYSTEM_TIME_HAVE_CLOCK_MONOTONIC_FAST
179
+ if (clockId == -1
180
+ && SystemTimeData::monotonicFastResolutionNs != 0
181
+ && SystemTimeData::monotonicFastResolutionNs <= granularityNs)
182
+ {
183
+ clockId = CLOCK_MONOTONIC_FAST;
184
+ }
185
+ #endif
186
+ if (clockId == -1
187
+ && SystemTimeData::monotonicResolutionNs != 0
188
+ && SystemTimeData::monotonicResolutionNs <= granularityNs)
189
+ {
190
+ clockId = CLOCK_MONOTONIC;
191
+ }
192
+
193
+ if (clockId == (clockid_t) -1) {
194
+ return getUsec();
195
+ } else {
196
+ do {
197
+ ret = clock_gettime(clockId, &ts);
198
+ } while (ret == -1 && errno == EINTR);
199
+ if (ret == -1) {
200
+ int e = errno;
201
+ throw TimeRetrievalException(
202
+ "Unable to retrieve the system time",
203
+ e);
204
+ }
205
+ return ts.tv_sec * 1000000ull + ts.tv_nsec / 1000ull;
206
+ }
207
+
208
+ #else
209
+ return getUsec();
210
+ #endif
211
+ }
212
+
213
+ public:
214
+ static void initialize() {
215
+ SystemTimeData::initialized = true;
216
+ #if BOOST_OS_MACOS
217
+ if (mach_timebase_info(&SystemTimeData::timeInfo) != KERN_SUCCESS) {
218
+ memset(&SystemTimeData::timeInfo, 0, sizeof(SystemTimeData::timeInfo));
219
+ }
220
+ #elif defined(SYSTEM_TIME_HAVE_MONOTONIC_CLOCK)
221
+ struct timespec ts;
222
+
223
+ #ifdef CLOCK_MONOTONIC_COARSE
224
+ if (clock_getres(CLOCK_MONOTONIC_COARSE, &ts) == 0) {
225
+ SystemTimeData::monotonicCoarseResolutionNs =
226
+ ts.tv_sec * 1000000000ull +
227
+ ts.tv_nsec;
228
+ }
229
+ #endif
230
+ #ifdef CLOCK_MONOTONIC_FAST
231
+ if (clock_getres(CLOCK_MONOTONIC_FAST, &ts) == 0) {
232
+ SystemTimeData::monotonicFastResolutionNs =
233
+ ts.tv_sec * 1000000000ull +
234
+ ts.tv_nsec;
235
+ }
236
+ #endif
237
+ if (clock_getres(CLOCK_MONOTONIC, &ts) == 0) {
238
+ SystemTimeData::monotonicResolutionNs =
239
+ ts.tv_sec * 1000000000ull +
240
+ ts.tv_nsec;
241
+ }
242
+ #endif
243
+ }
244
+
58
245
  /**
59
246
  * Returns the time since the Epoch, measured in seconds. Or, if a time
60
247
  * was forced with force(), then the forced time is returned instead.
@@ -63,7 +250,7 @@ public:
63
250
  * @throws boost::thread_interrupted
64
251
  */
65
252
  static time_t get() {
66
- if (SystemTimeData::hasForcedValue) {
253
+ if (OXT_UNLIKELY(SystemTimeData::hasForcedValue)) {
67
254
  return SystemTimeData::forcedValue;
68
255
  } else {
69
256
  time_t ret = syscalls::time(NULL);
@@ -78,16 +265,15 @@ public:
78
265
  }
79
266
 
80
267
  /**
81
- * Returns the time since the Epoch, measured in milliseconds. Or, if a
82
- * time was forced with forceMsec(), then the forced time is returned instead.
268
+ * Returns the time since the Epoch, measured in microseconds. Or, if a
269
+ * time was forced with forceUsec(), then the forced time is returned instead.
83
270
  *
84
- * @param real Whether to get the real time, even if a value was forced.
85
271
  * @throws TimeRetrievalException Something went wrong while retrieving the time.
86
272
  * @throws boost::thread_interrupted
87
273
  */
88
- static unsigned long long getMsec(bool real = false) {
89
- if (SystemTimeData::hasForcedMsecValue && !real) {
90
- return SystemTimeData::forcedMsecValue;
274
+ static unsigned long long getUsec() {
275
+ if (OXT_UNLIKELY(SystemTimeData::hasForcedUsecValue)) {
276
+ return SystemTimeData::forcedUsecValue;
91
277
  } else {
92
278
  struct timeval t;
93
279
  int ret;
@@ -101,35 +287,41 @@ public:
101
287
  "Unable to retrieve the system time",
102
288
  e);
103
289
  }
104
- return (unsigned long long) t.tv_sec * 1000 + t.tv_usec / 1000;
290
+ return (unsigned long long) t.tv_sec * 1000000 + t.tv_usec;
105
291
  }
106
292
  }
107
293
 
108
294
  /**
109
- * Returns the time since the Epoch, measured in microseconds. Or, if a
110
- * time was forced with forceUsec(), then the forced time is returned instead.
295
+ * Returns the time since an unspecified point in the last, measured in
296
+ * microseconds, using the monotonic clock.
297
+ *
298
+ * The monotonic clock is not subject to clock drift, even if the user
299
+ * changes the wall clock time. It is ideal for measuring time between
300
+ * two intervals.
301
+ *
302
+ * The returned time is guaranteed to have a granularity of 1 microsecond
303
+ * or better. In general, querying with coarser granularities is faster.
304
+ * If you want a coarser granularity, use `getMonotonicUsecWithGranularity()`
305
+ * instead.
306
+ *
307
+ * If the monotonic clock is not available (e.g. because the operating
308
+ * system doesn't support it), then this function returns the regular
309
+ * wall clock time instead (using `getUsec()`). If the monotonic clock
310
+ * is available, but an error occurred querying it, then a
311
+ * `TimeRetrievalException` is thrown.
312
+ *
313
+ * If the time was forced with forceUsed(), then the forced time is returned
314
+ * instead.
111
315
  *
112
316
  * @throws TimeRetrievalException Something went wrong while retrieving the time.
113
- * @throws boost::thread_interrupted
114
317
  */
115
- static unsigned long long getUsec() {
116
- if (SystemTimeData::hasForcedUsecValue) {
117
- return SystemTimeData::forcedUsecValue;
118
- } else {
119
- struct timeval t;
120
- int ret;
318
+ static MonotonicTimeUsec getMonotonicUsec() {
319
+ return _getMonotonicUsec<GRAN_1USEC>();
320
+ }
121
321
 
122
- do {
123
- ret = gettimeofday(&t, NULL);
124
- } while (ret == -1 && errno == EINTR);
125
- if (ret == -1) {
126
- int e = errno;
127
- throw TimeRetrievalException(
128
- "Unable to retrieve the system time",
129
- e);
130
- }
131
- return (unsigned long long) t.tv_sec * 1000000 + t.tv_usec;
132
- }
322
+ template<Granularity granularity>
323
+ static MonotonicTimeUsec getMonotonicUsecWithGranularity() {
324
+ return _getMonotonicUsec<granularity>();
133
325
  }
134
326
 
135
327
  /**
@@ -140,14 +332,6 @@ public:
140
332
  SystemTimeData::forcedValue = value;
141
333
  }
142
334
 
143
- /**
144
- * Force getMsec() to return the given value.
145
- */
146
- static void forceMsec(unsigned long long value) {
147
- SystemTimeData::hasForcedMsecValue = true;
148
- SystemTimeData::forcedMsecValue = value;
149
- }
150
-
151
335
  /**
152
336
  * Force getUsec() to return the given value.
153
337
  */
@@ -158,7 +342,6 @@ public:
158
342
 
159
343
  static void forceAll(unsigned long long usec) {
160
344
  force(usec / 1000000);
161
- forceMsec(usec / 1000);
162
345
  forceUsec(usec);
163
346
  }
164
347
 
@@ -170,14 +353,6 @@ public:
170
353
  SystemTimeData::hasForcedValue = false;
171
354
  }
172
355
 
173
- /**
174
- * Release the previously forced msec value, so that getMsec()
175
- * returns the system time once again.
176
- */
177
- static void releaseMsec() {
178
- SystemTimeData::hasForcedMsecValue = false;
179
- }
180
-
181
356
  /**
182
357
  * Release the previously forced usec value, so that getUsec()
183
358
  * returns the system time once again.
@@ -187,12 +362,11 @@ public:
187
362
  }
188
363
 
189
364
  /**
190
- * Release all previously forced values, so that get(), getMsec()
191
- * and getUsec() return the system time once again.
365
+ * Release all previously forced values, so that get() and
366
+ * getUsec() return the system time once again.
192
367
  */
193
368
  static void releaseAll() {
194
369
  SystemTimeData::hasForcedValue = false;
195
- SystemTimeData::hasForcedMsecValue = false;
196
370
  SystemTimeData::hasForcedUsecValue = false;
197
371
  }
198
372
  };