aboutsummaryrefslogtreecommitdiffstats
path: root/util/system/datetime.cpp
blob: b07b50679a6ec49831b979170d969334f1f06f98 (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
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
#include "datetime.h"
#include "yassert.h"
#include "platform.h"
#include "cpu_id.h"

#include <util/datetime/systime.h>

#include <ctime>
#include <cerrno>

#ifdef _darwin_
    #include <AvailabilityMacros.h>
    #if defined(MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
        #define Y_HAS_CLOCK_GETTIME
    #endif
#elif defined(_linux_) || defined(_freebsd_) || defined(_cygwin_)
    #define Y_HAS_CLOCK_GETTIME
#endif

static ui64 ToMicroSeconds(const struct timeval& tv) {
    return (ui64)tv.tv_sec * 1000000 + (ui64)tv.tv_usec;
}

#if defined(_win_)
static ui64 ToMicroSeconds(const FILETIME& ft) {
    return (((ui64)ft.dwHighDateTime << 32) + (ui64)ft.dwLowDateTime) / (ui64)10;
}
#elif defined(Y_HAS_CLOCK_GETTIME)
static ui64 ToMicroSeconds(const struct timespec& ts) {
    return (ui64)ts.tv_sec * 1000000 + (ui64)ts.tv_nsec / 1000;
}
#endif

ui64 MicroSeconds() noexcept {
    struct timeval tv;
    gettimeofday(&tv, nullptr);

    return ToMicroSeconds(tv);
}

ui64 ThreadCPUUserTime() noexcept {
#if defined(_win_)
    FILETIME creationTime, exitTime, kernelTime, userTime;
    GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime, &userTime);
    return ToMicroSeconds(userTime);
#else
    return 0;
#endif
}

ui64 ThreadCPUSystemTime() noexcept {
#if defined(_win_)
    FILETIME creationTime, exitTime, kernelTime, userTime;
    GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime, &userTime);
    return ToMicroSeconds(kernelTime);
#else
    return 0;
#endif
}

ui64 ThreadCPUTime() noexcept {
#if defined(_win_)
    FILETIME creationTime, exitTime, kernelTime, userTime;
    GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime, &userTime);
    return ToMicroSeconds(userTime) + ToMicroSeconds(kernelTime);
#elif defined(Y_HAS_CLOCK_GETTIME)
    struct timespec ts;
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
    return ToMicroSeconds(ts);
#else
    return 0;
#endif
}

ui32 Seconds() noexcept {
    struct timeval tv;
    gettimeofday(&tv, nullptr);
    return tv.tv_sec;
}

void NanoSleep(ui64 ns) noexcept {
#if defined(_win_)
    Sleep(ns / 1000000);
#else
    const ui64 NS = 1000 * 1000 * 1000;
    struct timespec req;
    req.tv_sec = ns / NS;
    req.tv_nsec = ns % NS;
    struct timespec left;
    while (nanosleep(&req, &left) < 0) {
        Y_ASSERT(errno == EINTR);
        req = left;
    }
#endif
}

#if defined(_x86_)
extern const bool HaveRdtscp = NX86::HaveRDTSCP();
#endif

#ifdef Y_HAS_CLOCK_GETTIME
    #undef Y_HAS_CLOCK_GETTIME
#endif