diff options
Diffstat (limited to 'libc-bottom-half/cloudlibc/src/common')
-rw-r--r-- | libc-bottom-half/cloudlibc/src/common/clock.h | 19 | ||||
-rw-r--r-- | libc-bottom-half/cloudlibc/src/common/limits.h | 35 | ||||
-rw-r--r-- | libc-bottom-half/cloudlibc/src/common/time.h | 63 |
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 |