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
|
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/common/clock.h>
#include <time.h>
static const uint64_t NS_PER_SEC = 1000000000;
#if defined(CLOCK_MONOTONIC_RAW)
# define HIGH_RES_CLOCK CLOCK_MONOTONIC_RAW
#else
# define HIGH_RES_CLOCK CLOCK_MONOTONIC
#endif
/* This entire compilation branch has two goals. First, prior to OSX Sierra, clock_gettime does not exist on OSX, so we
* already need to branch on that. Second, even if we compile on a newer OSX, which we will always do for bindings (e.g.
* python, dotnet, java etc...), we have to worry about the same lib being loaded on an older version, and thus, we'd
* get linker errors at runtime. To avoid this, we do a dynamic load
* to keep the function out of linker tables and only use the symbol if the current running process has access to the
* function. */
#if defined(__MACH__)
# include <AvailabilityMacros.h>
# include <aws/common/thread.h>
# include <dlfcn.h>
# include <sys/time.h>
static int s_legacy_get_time(uint64_t *timestamp) {
struct timeval tv;
int ret_val = gettimeofday(&tv, NULL);
if (ret_val) {
return aws_raise_error(AWS_ERROR_CLOCK_FAILURE);
}
uint64_t secs = (uint64_t)tv.tv_sec;
uint64_t u_secs = (uint64_t)tv.tv_usec;
*timestamp = (secs * NS_PER_SEC) + (u_secs * 1000);
return AWS_OP_SUCCESS;
}
# if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
static aws_thread_once s_thread_once_flag = AWS_THREAD_ONCE_STATIC_INIT;
static int (*s_gettime_fn)(clockid_t clock_id, struct timespec *tp) = NULL;
static void s_do_osx_loads(void *user_data) {
(void)user_data;
s_gettime_fn = (int (*)(clockid_t clock_id, struct timespec * tp)) dlsym(RTLD_DEFAULT, "clock_gettime");
}
int aws_high_res_clock_get_ticks(uint64_t *timestamp) {
aws_thread_call_once(&s_thread_once_flag, s_do_osx_loads, NULL);
int ret_val = 0;
if (s_gettime_fn) {
struct timespec ts;
ret_val = s_gettime_fn(HIGH_RES_CLOCK, &ts);
if (ret_val) {
return aws_raise_error(AWS_ERROR_CLOCK_FAILURE);
}
uint64_t secs = (uint64_t)ts.tv_sec;
uint64_t n_secs = (uint64_t)ts.tv_nsec;
*timestamp = (secs * NS_PER_SEC) + n_secs;
return AWS_OP_SUCCESS;
}
return s_legacy_get_time(timestamp);
}
int aws_sys_clock_get_ticks(uint64_t *timestamp) {
aws_thread_call_once(&s_thread_once_flag, s_do_osx_loads, NULL);
int ret_val = 0;
if (s_gettime_fn) {
struct timespec ts;
ret_val = s_gettime_fn(CLOCK_REALTIME, &ts);
if (ret_val) {
return aws_raise_error(AWS_ERROR_CLOCK_FAILURE);
}
uint64_t secs = (uint64_t)ts.tv_sec;
uint64_t n_secs = (uint64_t)ts.tv_nsec;
*timestamp = (secs * NS_PER_SEC) + n_secs;
return AWS_OP_SUCCESS;
}
return s_legacy_get_time(timestamp);
}
# else
int aws_high_res_clock_get_ticks(uint64_t *timestamp) {
return s_legacy_get_time(timestamp);
}
int aws_sys_clock_get_ticks(uint64_t *timestamp) {
return s_legacy_get_time(timestamp);
}
# endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 */
/* Everywhere else, just link clock_gettime in directly */
#else
int aws_high_res_clock_get_ticks(uint64_t *timestamp) {
int ret_val = 0;
struct timespec ts;
ret_val = clock_gettime(HIGH_RES_CLOCK, &ts);
if (ret_val) {
return aws_raise_error(AWS_ERROR_CLOCK_FAILURE);
}
uint64_t secs = (uint64_t)ts.tv_sec;
uint64_t n_secs = (uint64_t)ts.tv_nsec;
*timestamp = (secs * NS_PER_SEC) + n_secs;
return AWS_OP_SUCCESS;
}
int aws_sys_clock_get_ticks(uint64_t *timestamp) {
int ret_val = 0;
struct timespec ts;
ret_val = clock_gettime(CLOCK_REALTIME, &ts);
if (ret_val) {
return aws_raise_error(AWS_ERROR_CLOCK_FAILURE);
}
uint64_t secs = (uint64_t)ts.tv_sec;
uint64_t n_secs = (uint64_t)ts.tv_nsec;
*timestamp = (secs * NS_PER_SEC) + n_secs;
return AWS_OP_SUCCESS;
}
#endif /* defined(__MACH__) */
|