blob: 301f9d819715fc3d28df1d78da07bef203ee48b2 (
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
104
105
106
107
108
109
110
111
112
113
114
|
#include <stdio.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <time.h>
#include "WAVM/Inline/Assert.h"
#include "WAVM/Inline/Errors.h"
#include "WAVM/Inline/I128.h"
#include "WAVM/Inline/Time.h"
#include "WAVM/Platform/Clock.h"
using namespace WAVM;
using namespace WAVM::Platform;
static I128 timespecToNS(timespec t) { return I128(U64(t.tv_sec)) * 1000000000 + U64(t.tv_nsec); }
static I128 getClockAsI128(clockid_t clockId)
{
timespec clockTime;
WAVM_ERROR_UNLESS(!clock_gettime(clockId, &clockTime));
return timespecToNS(clockTime);
}
static I128 getClockResAsI128(clockid_t clockId)
{
timespec clockResolution;
WAVM_ERROR_UNLESS(!clock_getres(clockId, &clockResolution));
return timespecToNS(clockResolution);
}
#if defined(__APPLE__)
#include <mach/mach_time.h>
static mach_timebase_info_data_t getTimebaseInfoData()
{
mach_timebase_info_data_t timebaseInfoData;
WAVM_ERROR_UNLESS(mach_timebase_info(&timebaseInfoData) == KERN_SUCCESS);
return timebaseInfoData;
}
static mach_timebase_info_data_t getCachedTimebaseInfoData()
{
static mach_timebase_info_data_t cachedTimebaseInfoData = getTimebaseInfoData();
return cachedTimebaseInfoData;
}
static I128 getMachAbsoluteClock()
{
mach_timebase_info_data_t cachedTimebaseInfoData = getCachedTimebaseInfoData();
const I128 ticks = mach_absolute_time();
const I128 ns = ticks * cachedTimebaseInfoData.numer / cachedTimebaseInfoData.denom;
return ns;
}
static I128 getMachAbsoluteClockResolution()
{
mach_timebase_info_data_t cachedTimebaseInfoData = getCachedTimebaseInfoData();
I128 ticksPerNanosecond = I128(cachedTimebaseInfoData.numer) / cachedTimebaseInfoData.denom;
if(ticksPerNanosecond == 0) { ticksPerNanosecond = 1; }
return ticksPerNanosecond;
}
#endif
Time Platform::getClockTime(Clock clock)
{
switch(clock)
{
case Clock::realtime: return Time{getClockAsI128(CLOCK_REALTIME)};
case Clock::monotonic: {
#if defined(__APPLE__)
return Time{getMachAbsoluteClock()};
#elif defined(CLOCK_MONOTONIC)
return Time{getClockAsI128(CLOCK_MONOTONIC)};
#else
#error CLOCK_MONOTONIC not supported on this platform.
#endif
}
case Clock::processCPUTime: {
#ifdef CLOCK_PROCESS_CPUTIME_ID
return Time{getClockAsI128(CLOCK_PROCESS_CPUTIME_ID)};
#else
struct rusage ru;
WAVM_ERROR_UNLESS(!getrusage(RUSAGE_SELF, &ru));
return Time{timevalToNS(ru.ru_stime) + timevalToNS(ru.ru_utime)};
#endif
}
default: WAVM_UNREACHABLE();
}
}
Time Platform::getClockResolution(Clock clock)
{
switch(clock)
{
case Clock::realtime: return Time{getClockResAsI128(CLOCK_REALTIME)};
case Clock::monotonic: {
#if defined(__APPLE__)
return Time{getMachAbsoluteClockResolution()};
#elif defined(CLOCK_MONOTONIC)
return Time{getClockResAsI128(CLOCK_MONOTONIC)};
#else
#error CLOCK_MONOTONIC not supported on this platform.
#endif
}
case Clock::processCPUTime: {
#ifdef CLOCK_PROCESS_CPUTIME_ID
return Time{getClockResAsI128(CLOCK_PROCESS_CPUTIME_ID)};
#else
return Time{1000};
#endif
}
default: WAVM_UNREACHABLE();
}
}
|