Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177422941
D60799.1794346306.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
4 KB
Referenced Files
None
Subscribers
None
D60799.1794346306.diff
View Options
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -483,6 +483,7 @@
posix_spawnattr_getprocdescp_np;
posix_spawnattr_setexecfd_np;
posix_spawnattr_setprocdescp_np;
+ timespec_getres;
uexterr_set;
};
diff --git a/lib/libc/gen/timespec_getres.3 b/lib/libc/gen/timespec_getres.3
--- a/lib/libc/gen/timespec_getres.3
+++ b/lib/libc/gen/timespec_getres.3
@@ -3,7 +3,7 @@
.\"
.\" SPDX-License-Identifier: BSD-2-Clause
.\"
-.Dd May 14, 2026
+.Dd October 20, 2026
.Dt TIMESPEC_GETRES 3
.Os
.Sh NAME
@@ -43,7 +43,11 @@
.St -isoC-2023 .
.Sh HISTORY
This interface first appeared in
-.Fx 14 .
+.Fx 14.0 ,
+but it was not exported from the shared C library until
+.Fx 14.6
+and
+.Fx 15.2 .
.Sh AUTHORS
The
.Nm
diff --git a/lib/libc/tests/gen/Makefile b/lib/libc/tests/gen/Makefile
--- a/lib/libc/tests/gen/Makefile
+++ b/lib/libc/tests/gen/Makefile
@@ -42,6 +42,7 @@
.endif
ATF_TESTS_C+= sig2str_test
ATF_TESTS_C+= sigsetops_test
+ATF_TESTS_C+= timespec_getres_test
ATF_TESTS_C+= wordexp_test
# TODO: t_closefrom, t_fmtcheck, t_randomid,
diff --git a/lib/libc/tests/gen/timespec_getres_test.c b/lib/libc/tests/gen/timespec_getres_test.c
new file mode 100644
--- /dev/null
+++ b/lib/libc/tests/gen/timespec_getres_test.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2026 Faraz Vahedi <kfv@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * Tests for timespec_getres() as per ISO/IEC 9899:2024 §7.29.2.7.
+ */
+
+#include <sys/param.h>
+#include <limits.h>
+#include <time.h>
+
+#include <atf-c.h>
+
+static const struct {
+ int base;
+ clockid_t clock;
+} bases[] = {
+ { TIME_UTC, CLOCK_REALTIME },
+ { TIME_MONOTONIC, CLOCK_MONOTONIC },
+};
+
+static const int bad_bases[] = {
+ INT_MIN, -1, 0, INT_MAX,
+};
+
+static void
+check_res(const struct timespec *ts)
+{
+ ATF_CHECK(ts->tv_sec >= 0);
+ ATF_CHECK(ts->tv_nsec >= 0 && ts->tv_nsec < 1000000000);
+ ATF_CHECK(ts->tv_sec != 0 || ts->tv_nsec != 0);
+}
+
+ATF_TC_WITHOUT_HEAD(timespec_getres_supported);
+ATF_TC_BODY(timespec_getres_supported, tc)
+{
+ struct timespec ts;
+
+ for (size_t i = 0; i < nitems(bases); i++) {
+ ATF_CHECK_EQ(timespec_getres(&ts, bases[i].base),
+ bases[i].base);
+ check_res(&ts);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(timespec_getres_clock);
+ATF_TC_BODY(timespec_getres_clock, tc)
+{
+ struct timespec ts, cts;
+
+ for (size_t i = 0; i < nitems(bases); i++) {
+ ATF_REQUIRE_EQ(timespec_getres(&ts, bases[i].base),
+ bases[i].base);
+ ATF_REQUIRE_EQ(clock_getres(bases[i].clock, &cts), 0);
+ ATF_CHECK_EQ(ts.tv_sec, cts.tv_sec);
+ ATF_CHECK_EQ(ts.tv_nsec, cts.tv_nsec);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(timespec_getres_null);
+ATF_TC_BODY(timespec_getres_null, tc)
+{
+ for (size_t i = 0; i < nitems(bases); i++)
+ ATF_CHECK_EQ(timespec_getres(NULL, bases[i].base),
+ bases[i].base);
+ for (size_t i = 0; i < nitems(bad_bases); i++)
+ ATF_CHECK_EQ(timespec_getres(NULL, bad_bases[i]), 0);
+}
+
+ATF_TC_WITHOUT_HEAD(timespec_getres_unsupported);
+ATF_TC_BODY(timespec_getres_unsupported, tc)
+{
+ struct timespec ts;
+
+ for (size_t i = 0; i < nitems(bad_bases); i++) {
+ ts.tv_sec = -1;
+ ts.tv_nsec = -1;
+ ATF_CHECK_EQ(timespec_getres(&ts, bad_bases[i]), 0);
+ ATF_CHECK_EQ(ts.tv_sec, -1);
+ ATF_CHECK_EQ(ts.tv_nsec, -1);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(timespec_getres_timespec_get);
+ATF_TC_BODY(timespec_getres_timespec_get, tc)
+{
+ struct timespec ts;
+
+ for (int base = -1; base <= TIME_MONOTONIC + 8; base++)
+ ATF_CHECK_EQ_MSG(timespec_getres(&ts, base) != 0,
+ timespec_get(&ts, base) != 0, "base %d", base);
+}
+
+ATF_TC_WITHOUT_HEAD(timespec_getres_stable);
+ATF_TC_BODY(timespec_getres_stable, tc)
+{
+ struct timespec first, ts;
+
+ for (size_t i = 0; i < nitems(bases); i++) {
+ ATF_REQUIRE_EQ(timespec_getres(&first, bases[i].base),
+ bases[i].base);
+ for (int n = 0; n < 100; n++) {
+ ATF_REQUIRE_EQ(timespec_getres(&ts, bases[i].base),
+ bases[i].base);
+ ATF_CHECK_EQ(ts.tv_sec, first.tv_sec);
+ ATF_CHECK_EQ(ts.tv_nsec, first.tv_nsec);
+ }
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, timespec_getres_supported);
+ ATF_TP_ADD_TC(tp, timespec_getres_clock);
+ ATF_TP_ADD_TC(tp, timespec_getres_null);
+ ATF_TP_ADD_TC(tp, timespec_getres_unsupported);
+ ATF_TP_ADD_TC(tp, timespec_getres_timespec_get);
+ ATF_TP_ADD_TC(tp, timespec_getres_stable);
+
+ return (atf_no_error());
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Nov 10, 9:31 PM (14 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41646752
Default Alt Text
D60799.1794346306.diff (4 KB)
Attached To
Mode
D60799: libc: Export timespec_getres(3) and add tests
Attached
Detach File
Event Timeline