blob: d2e1191c84f448e36ed64f96bb3e004d19fda320 (
plain) (
blame)
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
|
#include "uptime.h"
#if defined(_win_)
#include <util/system/winint.h>
#elif defined(_linux_)
#include <util/stream/file.h>
#include <util/string/cast.h>
#elif defined(_darwin_)
#include <sys/sysctl.h>
#endif
#if defined(_darwin_)
namespace {
TInstant GetBootTime() {
struct timeval timeSinceBoot;
size_t len = sizeof(timeSinceBoot);
int request[2] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(request, 2, &timeSinceBoot, &len, nullptr, 0) < 0) {
ythrow yexception() << "cannot get kern.boottime from sysctl";
}
return TInstant::MicroSeconds(timeSinceBoot.tv_sec * 1'000'000 + timeSinceBoot.tv_usec);
}
TDuration GetDarwinUptime() {
TInstant beforeNow;
TInstant afterNow;
TInstant now;
// avoid race when NTP changes machine time between getting Now() and uptime
afterNow = GetBootTime();
do {
beforeNow = afterNow;
now = Now();
afterNow = GetBootTime();
} while (afterNow != beforeNow);
return now - beforeNow;
}
}
#endif // _darwin_
TDuration Uptime() {
#if defined(_win_)
return TDuration::MilliSeconds(GetTickCount64());
#elif defined(_linux_)
TUnbufferedFileInput in("/proc/uptime");
TString uptimeStr = in.ReadLine();
double up, idle;
if (sscanf(uptimeStr.data(), "%lf %lf", &up, &idle) < 2) {
ythrow yexception() << "cannot read values from /proc/uptime";
}
return TDuration::MilliSeconds(up * 1000.0);
#elif defined(_darwin_)
return GetDarwinUptime();
#elif defined(_emscripten_)
ythrow yexception() << "unimplemented";
#else
#error "Implement this method"
#endif
}
|