|
From: ljsebald <ljs...@us...> - 2024-06-06 00:53:56
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 6e29d295e92995fda1fb2213d43b35bb168fef71 (commit)
from c86818033aa60180853d8006de031093a26be37f (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 6e29d295e92995fda1fb2213d43b35bb168fef71
Author: Falco Girgis <gyr...@gm...>
Date: Wed Jun 5 19:53:15 2024 -0500
Implemented C23 stdlib features for <time.h> (#550)
* Implemented C23 stdlib features for <time.h>
- New macro for C23 compliance of the file
- Macros were redone to check for existence of C and C++ macros before
"dereferencing"
- New C23 time base types
- asctime() and ctime() are now deprecated in C23
- C23 added timespec_getres() for getting resolution of a time base
- C23 added gmtime_r() and localtime_r() reentrant time converters
- Implemented timespec API by mapping it directly to POSIX clock API
- Removed clock_gettime()'s reliance on timespec_get() for
CLOCK_REALTIME, so that the dependency could be reversed.
- Removed whitespace from RTC
* Implemented timegm() for UTC tm to unix timestamp.
* Updated CHANGELOG.
* Update include/kos/time.h
* Addressed review feedback.
-----------------------------------------------------------------------
Summary of changes:
doc/CHANGELOG | 1 +
include/kos/time.h | 73 ++++++++++++++++++++++++++++++--------
kernel/arch/dreamcast/kernel/rtc.c | 1 -
kernel/libc/c11/Makefile | 4 +--
kernel/libc/c11/timegm.c | 19 ++++++++++
kernel/libc/c11/timespec_get.c | 64 +++++++++++++++++++++++++++------
kernel/libc/posix/clock_gettime.c | 10 +++---
7 files changed, 140 insertions(+), 32 deletions(-)
create mode 100644 kernel/libc/c11/timegm.c
diff --git a/doc/CHANGELOG b/doc/CHANGELOG
index 3b15b50d..d7e1e4c5 100644
--- a/doc/CHANGELOG
+++ b/doc/CHANGELOG
@@ -228,6 +228,7 @@ KallistiOS version 2.1.0 -----------------------------------------------
- *** Added thread support for tracking CPU time + updated clock_gettime() [FG]
- *** Added support for one-shot timers [PC]
- DC Use one-shot timers for timeout and a proper polling mechanism in modem [PC]
+- *** Added full support for <time.h> additions from C23 standard. [FG]
KallistiOS version 2.0.0 -----------------------------------------------
- DC Broadband Adapter driver fixes [Megan Potter == MP]
diff --git a/include/kos/time.h b/include/kos/time.h
index 717f4daf..fe6f2ddc 100644
--- a/include/kos/time.h
+++ b/include/kos/time.h
@@ -8,7 +8,7 @@
/** \file kos/time.h
\brief KOS-implementation of select C11 and POSIX extensions
- Add select POSIX extensions and C11 functionality to time.h which are not
+ Add select POSIX extensions, C11, and C23 functionality to time.h which are not
present within Newlib.
\remark
@@ -23,9 +23,8 @@
\author Falco Girgis
*/
-
#ifndef _TIME_H_
-#error "Do not include this file directly. Use <time.h> instead."
+ #error "Do not include this file directly. Use <time.h> instead."
#endif /* !_TIME_H_ */
#ifndef __KOS_TIME_H
@@ -35,22 +34,66 @@
__BEGIN_DECLS
-#if !defined(__STRICT_ANSI__) || (__STDC_VERSION__ >= 201112L) || (__cplusplus >= 201703L)
+/** \cond */
-/* Forward declaration. */
-struct timespec;
+/* Required definition for a fully C23-compliant <time.h> */
+#define __STDC_VERSION_TIME_H__ 202311L
-#define TIME_UTC 1
+/* Microsecond resolution for clock(), per POSIX standard.. */
+#define CLOCKS_PER_SEC 1000000
-/* Microsecond resolution for clock(), per POSIX standard */
-#define CLOCKS_PER_SEC 1000000
+/* =============== Enable the following for >=c11, >=c++17 =================== */
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
+ (defined(__cplusplus) && (__cplusplus >= 201703L))
+
+/* Only supported base time in C11. */
+#define TIME_UTC 1
/* C11 nanosecond-resolution timing. */
+struct timespec;
extern int timespec_get(struct timespec *ts, int base);
+#endif
+
+/* ============ Enable the following for >=C2x, >C++20+, KOS ============== */
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202000L)) || \
+ (defined(__cplusplus) && (__cplusplus > 202002L)) || \
+ defined(__KOS_LIBC)
+
+/* New POSIX-equivalent base times in C23. */
+#define TIME_MONOTONIC 2
+#define TIME_ACTIVE 3
+#define TIME_THREAD_ACTIVE 4
+
+/* Query for the resolution of a time base. */
+extern int timespec_getres(struct timespec *ts, int base);
+#endif
+
+/* ===================== Enable the following for >=c2y ================== */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202300L)
+
+/* Deprecate legacy time formatters with static internal state. */
+struct tm;
+[[deprecated]] extern char *asctime(const struct tm *timeptr);
+[[deprecated]] extern char *ctime(const __time_t *timer);
+#endif
+
+/* =========== Enable the following for >=c2y, >c++20, KOS ============== */
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202300L)) || \
+ (defined(__cplusplus) && (__cplusplus > 202002L)) || \
+ defined(__KOS_LIBC)
-#endif /* !defined(__STRICT_ANSI__) || (__STDC_VERSION__ >= 201112L) || (__cplusplus >= 201703L) */
+/* POSIX reentrant equivalents of gmtime and localtime added to C23. */
+struct tm;
+extern struct tm *gmtime_r(const __time_t *timer, struct tm *timeptr);
+extern struct tm *localtime_r(const __time_t *timer, struct tm *timeptr);
-#if !defined(__STRICT_ANSI__) || (_POSIX_C_SOURCE >= 199309L)
+/* C23 added POSIX gmtime() for UTC broken-down time to a Unix timestamp. */
+extern __time_t timegm(struct tm *timeptr);
+
+#endif
+
+/* =========== Enable the following for POSIX POSIX.1b (1993) =========== */
+#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L)
/* We do not support POSIX timers!
#ifndef _POSIX_TIMERS
@@ -70,13 +113,15 @@ extern int timespec_get(struct timespec *ts, int base);
#endif
/* Explicitly provided function declarations for POSIX clock API, since
- getting them from Newlib requires supporting the rest of the _POSIX_TIMERS
- API, which is not implemented yet. */
+getting them from Newlib requires supporting the rest of the _POSIX_TIMERS
+API, which is not implemented yet. */
extern int clock_settime(__clockid_t clock_id, const struct timespec *ts);
extern int clock_gettime(__clockid_t clock_id, struct timespec *ts);
extern int clock_getres(__clockid_t clock_id, struct timespec *res);
-#endif /* !defined(__STRICT_ANSI__) || (_POSIX_C_SOURCE >= 199309L) */
+#endif
+
+/** \endcond */
__END_DECLS
diff --git a/kernel/arch/dreamcast/kernel/rtc.c b/kernel/arch/dreamcast/kernel/rtc.c
index db836943..d18c8f18 100644
--- a/kernel/arch/dreamcast/kernel/rtc.c
+++ b/kernel/arch/dreamcast/kernel/rtc.c
@@ -128,7 +128,6 @@ int rtc_set_unix_secs(time_t secs) {
if(adjusted_time < 0 || adjusted_time > UINT32_MAX)
return -1;
-
/* Enable writing by setting LSB of control */
g2_write_32(RTC_CTRL_ADDR, RTC_CTRL_WRITE_EN);
diff --git a/kernel/libc/c11/Makefile b/kernel/libc/c11/Makefile
index 460e5bc1..2c42f70c 100644
--- a/kernel/libc/c11/Makefile
+++ b/kernel/libc/c11/Makefile
@@ -4,13 +4,13 @@
# Copyright (C) 2014, 2015, 2023 Lawrence Sebald
#
-KOS_CFLAGS += -std=c11
+KOS_CFLAGS += -std=gnu11 -D__KOS_LIBC
OBJS = call_once.o cnd_broadcast.o cnd_destroy.o cnd_init.o cnd_signal.o \
cnd_timedwait.o cnd_wait.o mtx_destroy.o mtx_init.o mtx_lock.o \
mtx_timedlock.o mtx_trylock.o mtx_unlock.o thrd_create.o thrd_current.o \
thrd_detach.o thrd_equal.o thrd_exit.o thrd_join.o thrd_sleep.o \
thrd_yield.o tss_create.o tss_delete.o tss_get.o tss_set.o \
- aligned_alloc.o timespec_get.o atomics.o
+ aligned_alloc.o timespec_get.o timegm.o atomics.o
include $(KOS_BASE)/Makefile.prefab
diff --git a/kernel/libc/c11/timegm.c b/kernel/libc/c11/timegm.c
new file mode 100644
index 00000000..63153ed5
--- /dev/null
+++ b/kernel/libc/c11/timegm.c
@@ -0,0 +1,19 @@
+/* KallistiOS ##version##
+
+ timegm.c
+ Copyright (C) 2024 Falco Girgis
+*/
+
+#include <time.h>
+#include <errno.h>
+#include <stdbool.h>
+
+/* C23/POSIX timegm() converts a UTC-based broken-down time to a unix
+ timestamp... and since we have no timezone on the Dreamcast (yet),
+ our local time is already UTC, which means this is going to be
+ equivalent to using mktime()!
+*/
+time_t timegm(struct tm *timeptr) {
+ return mktime(timeptr);
+}
+
diff --git a/kernel/libc/c11/timespec_get.c b/kernel/libc/c11/timespec_get.c
index b913002e..1678ce1f 100644
--- a/kernel/libc/c11/timespec_get.c
+++ b/kernel/libc/c11/timespec_get.c
@@ -2,23 +2,65 @@
timespec_get.c
Copyright (C) 2023 Lawrence Sebald
- Copyright (C) 2023 Falco Girgis
+ Copyright (C) 2023, 2024 Falco Girgis
*/
#include <time.h>
-#include <arch/timer.h>
-#include <arch/rtc.h>
+#include <errno.h>
+#include <stdbool.h>
-int timespec_get(struct timespec *ts, int base) {
- if(base == TIME_UTC && ts) {
- uint32_t s, ns;
+/* Convert a C11 time base into a POSIX Clock ID. */
+static inline bool posix_clk_id(int base, clockid_t *id) {
+ switch(base) {
+ case TIME_UTC:
+ *id = CLOCK_REALTIME;
+ return true;
+
+ case TIME_MONOTONIC:
+ *id = CLOCK_MONOTONIC;
+ return true;
+
+ case TIME_ACTIVE:
+ *id = CLOCK_PROCESS_CPUTIME_ID;
+ return true;
+
+ case TIME_THREAD_ACTIVE:
+ *id = CLOCK_THREAD_CPUTIME_ID;
+ return true;
+
+ default:
+ return false;
+ }
+}
- timer_ns_gettime(&s, &ns);
- ts->tv_sec = rtc_boot_time() + s;
- ts->tv_nsec = ns;
+/* Proxy a call to a C11/C23 timespec function to a POSIX clock function. */
+static int timespec_posix_adapter(struct timespec *ts,
+ int base,
+ int (*clockfn)(clock_t, struct timespec *)) {
+ clockid_t clk_id;
- return base;
+ if(!posix_clk_id(base, &clk_id))
+ return 0;
+
+ if(!ts)
+ return 0;
+
+ /* errno is not modified from the C11/C23 timespec API! */
+ const int old_errno = errno;
+ if(clockfn(clk_id, ts) == -1) {
+ errno = old_errno;
+ return 0;
}
- return 0;
+ return base;
+}
+
+/* C11 timespec_get() -> POSIX clock_gettime(). */
+int timespec_get(struct timespec *ts, int base) {
+ return timespec_posix_adapter(ts, base, clock_gettime);
+}
+
+/* C23 timespec_getres() -> POSIX clock_getres(). */
+int timespec_getres(struct timespec *ts, int base) {
+ return timespec_posix_adapter(ts, base, clock_getres);
}
diff --git a/kernel/libc/posix/clock_gettime.c b/kernel/libc/posix/clock_gettime.c
index 5e389461..f3ea0d64 100644
--- a/kernel/libc/posix/clock_gettime.c
+++ b/kernel/libc/posix/clock_gettime.c
@@ -53,7 +53,7 @@ int clock_getres(clockid_t clk_id, struct timespec *ts) {
int clock_gettime(clockid_t clk_id, struct timespec *ts) {
lldiv_t div_result;
uint64_t ns64;
- uint32_t secs, nsecs;
+ uint32_t secs, nsecs, secs_offset=0;
if(!ts) {
errno = EFAULT;
@@ -61,14 +61,16 @@ int clock_gettime(clockid_t clk_id, struct timespec *ts) {
}
switch(clk_id) {
- /* Use C11's nanosecond-resolution timestamp */
+ /* Use the nanosecond resolution boot time
+ + RTC bios time */
case CLOCK_REALTIME:
- return timespec_get(ts, TIME_UTC) == TIME_UTC ? 0 : -1;
+ secs_offset = rtc_boot_time();
+ /* fall through */
/* Use the nanosecond resolution boot time */
case CLOCK_MONOTONIC:
timer_ns_gettime(&secs, &nsecs);
- ts->tv_sec = secs;
+ ts->tv_sec = secs + secs_offset;
ts->tv_nsec = nsecs;
return 0;
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|