summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/aws-c-common/source/posix/clock.c
diff options
context:
space:
mode:
authorDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/restricted/aws/aws-c-common/source/posix/clock.c
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/restricted/aws/aws-c-common/source/posix/clock.c')
-rw-r--r--contrib/restricted/aws/aws-c-common/source/posix/clock.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/contrib/restricted/aws/aws-c-common/source/posix/clock.c b/contrib/restricted/aws/aws-c-common/source/posix/clock.c
new file mode 100644
index 00000000000..90e213ea7c8
--- /dev/null
+++ b/contrib/restricted/aws/aws-c-common/source/posix/clock.c
@@ -0,0 +1,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__) */