summaryrefslogtreecommitdiffstats
path: root/libc-bottom-half/cloudlibc/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'libc-bottom-half/cloudlibc/src/common')
-rw-r--r--libc-bottom-half/cloudlibc/src/common/clock.h19
-rw-r--r--libc-bottom-half/cloudlibc/src/common/limits.h35
-rw-r--r--libc-bottom-half/cloudlibc/src/common/time.h63
3 files changed, 117 insertions, 0 deletions
diff --git a/libc-bottom-half/cloudlibc/src/common/clock.h b/libc-bottom-half/cloudlibc/src/common/clock.h
new file mode 100644
index 0000000..58d40a1
--- /dev/null
+++ b/libc-bottom-half/cloudlibc/src/common/clock.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+//
+// SPDX-License-Identifier: BSD-2-Clause
+
+#ifndef COMMON_CLOCK_H
+#define COMMON_CLOCK_H
+
+#include <wasi/api.h>
+
+// In this implementation we define clockid_t as a pointer type, so that
+// we can implement them as full objects. Right now we only use those
+// objects to store the raw ABI-level clock identifier, but in the
+// future we can use this to provide support for pthread_getcpuclockid()
+// and clock file descriptors.
+struct __clockid {
+ __wasi_clockid_t id;
+};
+
+#endif
diff --git a/libc-bottom-half/cloudlibc/src/common/limits.h b/libc-bottom-half/cloudlibc/src/common/limits.h
new file mode 100644
index 0000000..67e2f07
--- /dev/null
+++ b/libc-bottom-half/cloudlibc/src/common/limits.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2015 Nuxi, https://nuxi.nl/
+//
+// SPDX-License-Identifier: BSD-2-Clause
+
+#ifndef COMMON_LIMITS_H
+#define COMMON_LIMITS_H
+
+#include <limits.h>
+
+#define NUMERIC_MIN(t) \
+ _Generic((t)0, char \
+ : CHAR_MIN, signed char \
+ : SCHAR_MIN, unsigned char : 0, short \
+ : SHRT_MIN, unsigned short : 0, int \
+ : INT_MIN, unsigned int : 0, long \
+ : LONG_MIN, unsigned long : 0, long long \
+ : LLONG_MIN, unsigned long long : 0, default \
+ : (void)0)
+
+#define NUMERIC_MAX(t) \
+ _Generic((t)0, char \
+ : CHAR_MAX, signed char \
+ : SCHAR_MAX, unsigned char \
+ : UCHAR_MAX, short \
+ : SHRT_MAX, unsigned short \
+ : USHRT_MAX, int \
+ : INT_MAX, unsigned int \
+ : UINT_MAX, long \
+ : LONG_MAX, unsigned long \
+ : ULONG_MAX, long long \
+ : LLONG_MAX, unsigned long long \
+ : ULLONG_MAX, default \
+ : (void)0)
+
+#endif
diff --git a/libc-bottom-half/cloudlibc/src/common/time.h b/libc-bottom-half/cloudlibc/src/common/time.h
new file mode 100644
index 0000000..08e2852
--- /dev/null
+++ b/libc-bottom-half/cloudlibc/src/common/time.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/
+//
+// SPDX-License-Identifier: BSD-2-Clause
+
+#ifndef COMMON_TIME_H
+#define COMMON_TIME_H
+
+#include <common/limits.h>
+
+#include <sys/time.h>
+
+#include <wasi/api.h>
+#include <stdbool.h>
+#include <time.h>
+
+#define NSEC_PER_SEC 1000000000
+
+static inline bool timespec_to_timestamp_exact(
+ const struct timespec *timespec, __wasi_timestamp_t *timestamp) {
+ // Invalid nanoseconds field.
+ if (timespec->tv_nsec < 0 || timespec->tv_nsec >= NSEC_PER_SEC)
+ return false;
+
+ // Timestamps before the Epoch are not supported.
+ if (timespec->tv_sec < 0)
+ return false;
+
+ // Make sure our timestamp does not overflow.
+ return !__builtin_mul_overflow(timespec->tv_sec, NSEC_PER_SEC, timestamp) &&
+ !__builtin_add_overflow(*timestamp, timespec->tv_nsec, timestamp);
+}
+
+static inline bool timespec_to_timestamp_clamp(
+ const struct timespec *timespec, __wasi_timestamp_t *timestamp) {
+ // Invalid nanoseconds field.
+ if (timespec->tv_nsec < 0 || timespec->tv_nsec >= NSEC_PER_SEC)
+ return false;
+
+ if (timespec->tv_sec < 0) {
+ // Timestamps before the Epoch are not supported.
+ *timestamp = 0;
+ } else if (__builtin_mul_overflow(timespec->tv_sec, NSEC_PER_SEC, timestamp) ||
+ __builtin_add_overflow(*timestamp, timespec->tv_nsec, timestamp)) {
+ // Make sure our timestamp does not overflow.
+ *timestamp = NUMERIC_MAX(__wasi_timestamp_t);
+ }
+ return true;
+}
+
+static inline struct timespec timestamp_to_timespec(
+ __wasi_timestamp_t timestamp) {
+ // Decompose timestamp into seconds and nanoseconds.
+ return (struct timespec){.tv_sec = timestamp / NSEC_PER_SEC,
+ .tv_nsec = timestamp % NSEC_PER_SEC};
+}
+
+static inline struct timeval timestamp_to_timeval(
+ __wasi_timestamp_t timestamp) {
+ struct timespec ts = timestamp_to_timespec(timestamp);
+ return (struct timeval){.tv_sec = ts.tv_sec, ts.tv_nsec / 1000};
+}
+
+#endif