[LTP] [PATCH] nanosleep: use POSIX runtime detection for CLOCK_MONOTONIC

Andrea Cervesato andrea.cervesato@suse.de
Thu Apr 16 08:59:59 CEST 2026


From: Andrea Cervesato <andrea.cervesato@suse.com>

All nanosleep POSIX conformance tests used a compile-time #ifdef on
_POSIX_MONOTONIC_CLOCK to select the clock for measuring elapsed
sleep duration. This was incorrect for two reasons:

1. Three test files (1-1.c, 2-1.c, 10000-1.c) did not include
   <unistd.h>, so the macro was never defined and the tests silently
   fell back to CLOCK_REALTIME.

2. On Linux/glibc, _POSIX_MONOTONIC_CLOCK is defined as 0, meaning
   support is optional and must be verified at runtime via
   sysconf(_SC_MONOTONIC_CLOCK). The #ifdef treated 0 the same as
   >0 (always available), which is not POSIX-correct.

Using CLOCK_REALTIME caused sporadic test failures when NTP or VM
time sync adjusted the wall clock during sleep, producing results
like "slept 32s >> 10s".

Extract the clock selection logic into a shared helpers.h with a
get_supported_clock() function that performs proper POSIX runtime
detection via sysconf(), and use it across all affected tests.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Some nanosleep tests are not recognizing CLOCK_MONOTONIC at runtime
even if it's available:

CLOCK_MONOTONIC unavailable, test may fail due to external clock adjustments
sleep 0 sec 30000000 nsec
PASS - slept 0s30078623ns ~= 0s30000000ns
sleep 1 sec 0 nsec
PASS - slept 1s97618ns ~= 1s0ns
sleep 1 sec 30000000 nsec
PASS - slept 1s30109248ns ~= 1s30000000ns
sleep 2 sec 0 nsec
PASS - slept 2s147180ns ~= 2s0ns
sleep 10 sec 5000 nsec
FAIL - slept 32s630120452ns >> 10s5000ns
sleep 13 sec 5 nsec
PASS - slept 13s146848ns ~= 13s5ns
sleep -1 sec -1 nsec
sleep 0 sec -1 nsec
sleep 1 sec 1000000000 nsec
sleep 2 sec 1000000000 nsec
sleep -2147483647 sec -2147483647 nsec
sleep 1 sec 2147483647 nsec
sleep 0 sec 1075002478 nsec
At least one test FAILED
---
 .../conformance/interfaces/nanosleep/1-1.c         | 16 ++++---------
 .../conformance/interfaces/nanosleep/1-2.c         | 17 ++++---------
 .../conformance/interfaces/nanosleep/1-3.c         | 17 ++++---------
 .../conformance/interfaces/nanosleep/10000-1.c     | 16 ++++---------
 .../conformance/interfaces/nanosleep/2-1.c         | 16 ++++---------
 .../conformance/interfaces/nanosleep/3-2.c         | 17 ++++---------
 .../conformance/interfaces/nanosleep/7-2.c         | 17 ++++---------
 .../conformance/interfaces/nanosleep/helpers.h     | 28 ++++++++++++++++++++++
 8 files changed, 56 insertions(+), 88 deletions(-)

diff --git a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/1-1.c b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/1-1.c
index 75b34346f13d9b62e2333dbc78023a812fc9c908..803569b138a1f17c0dede0c03406d3c7e52c4215 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/1-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/1-1.c
@@ -11,24 +11,16 @@
 #include <stdio.h>
 #include <time.h>
 #include "posixtest.h"
-
-#ifdef _POSIX_MONOTONIC_CLOCK
-#define TEST_CLOCK CLOCK_MONOTONIC
-#else
-#define TEST_CLOCK CLOCK_REALTIME
-#endif
+#include "helpers.h"
 
 int main(void)
 {
 	struct timespec tssleepfor, tsstorage, tsbefore, tsafter;
 	int sleepnsec = 3;
 	int slepts = 0, sleptns = 0;
+	clockid_t test_clock = get_supported_clock();
 
-#ifndef _POSIX_MONOTONIC_CLOCK
-	printf("CLOCK_MONOTONIC unavailable, test may fail due to external clock adjustments\n");
-#endif
-
-	if (clock_gettime(TEST_CLOCK, &tsbefore) == -1) {
+	if (clock_gettime(test_clock, &tsbefore) == -1) {
 		perror("Error in clock_gettime()\n");
 		return PTS_UNRESOLVED;
 	}
@@ -40,7 +32,7 @@ int main(void)
 		return PTS_UNRESOLVED;
 	}
 
-	if (clock_gettime(TEST_CLOCK, &tsafter) == -1) {
+	if (clock_gettime(test_clock, &tsafter) == -1) {
 		perror("Error in clock_gettime()\n");
 		return PTS_UNRESOLVED;
 	}
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/1-2.c b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/1-2.c
index 4a38bd507bba47792b942feb53954b95e92dc222..2a038bce93ff81c4ba4b8e55671a7fcb55196eb6 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/1-2.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/1-2.c
@@ -11,27 +11,18 @@
 #include <stdio.h>
 #include <time.h>
 #include <signal.h>
-#include <unistd.h>
 #include <sys/wait.h>
 #include "posixtest.h"
-
-#ifdef _POSIX_MONOTONIC_CLOCK
-#define TEST_CLOCK CLOCK_MONOTONIC
-#else
-#define TEST_CLOCK CLOCK_REALTIME
-#endif
+#include "helpers.h"
 
 int main(void)
 {
 	struct timespec tssleepfor, tsstorage, tsbefore, tsafter;
 	int sleepsec = 30;
 	int pid;
+	clockid_t test_clock = get_supported_clock();
 
-#ifndef _POSIX_MONOTONIC_CLOCK
-	printf("CLOCK_MONOTONIC unavailable, test may fail due to external clock adjustments\n");
-#endif
-
-	if (clock_gettime(TEST_CLOCK, &tsbefore) == -1) {
+	if (clock_gettime(test_clock, &tsbefore) == -1) {
 		perror("Error in clock_gettime()\n");
 		return PTS_UNRESOLVED;
 	}
@@ -56,7 +47,7 @@ int main(void)
 			perror("Error waiting for child to exit\n");
 			return PTS_UNRESOLVED;
 		}
-		if (clock_gettime(TEST_CLOCK, &tsafter) == -1) {
+		if (clock_gettime(test_clock, &tsafter) == -1) {
 			perror("Error in clock_gettime()\n");
 			return PTS_UNRESOLVED;
 		}
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/1-3.c b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/1-3.c
index 7d5600788d6bc4682f228ccc7c669576827c397a..9d81fdfad5549c656a4e2ae9e2b23c6a54a88eba 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/1-3.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/1-3.c
@@ -12,15 +12,9 @@
 #include <stdio.h>
 #include <time.h>
 #include <signal.h>
-#include <unistd.h>
 #include <sys/wait.h>
 #include "posixtest.h"
-
-#ifdef _POSIX_MONOTONIC_CLOCK
-#define TEST_CLOCK CLOCK_MONOTONIC
-#else
-#define TEST_CLOCK CLOCK_REALTIME
-#endif
+#include "helpers.h"
 
 static void handler(int signo PTS_ATTRIBUTE_UNUSED)
 {
@@ -33,12 +27,9 @@ int main(void)
 	int sleepsec = 30;
 	int pid;
 	struct sigaction act;
+	clockid_t test_clock = get_supported_clock();
 
-#ifndef _POSIX_MONOTONIC_CLOCK
-	printf("CLOCK_MONOTONIC unavailable, test may fail due to external clock adjustments\n");
-#endif
-
-	if (clock_gettime(TEST_CLOCK, &tsbefore) == -1) {
+	if (clock_gettime(test_clock, &tsbefore) == -1) {
 		perror("Error in clock_gettime()\n");
 		return PTS_UNRESOLVED;
 	}
@@ -74,7 +65,7 @@ int main(void)
 			perror("Error waiting for child to exit\n");
 			return PTS_UNRESOLVED;
 		}
-		if (clock_gettime(TEST_CLOCK, &tsafter) == -1) {
+		if (clock_gettime(test_clock, &tsafter) == -1) {
 			perror("Error in clock_gettime()\n");
 			return PTS_UNRESOLVED;
 		}
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/10000-1.c b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/10000-1.c
index ebcf366acb52fd149f19951a6e4e0764bd503807..c9d1cc303c629d7bbcf0fb4451103ef1729e4609 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/10000-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/10000-1.c
@@ -18,12 +18,7 @@
 #include <time.h>
 #include <errno.h>
 #include "posixtest.h"
-
-#ifdef _POSIX_MONOTONIC_CLOCK
-#define TEST_CLOCK CLOCK_MONOTONIC
-#else
-#define TEST_CLOCK CLOCK_REALTIME
-#endif
+#include "helpers.h"
 
 #define NUMVALID 6
 #define NUMINVALID 7
@@ -56,23 +51,20 @@ int main(void)
 	int i;
 	int failure = 0;
 	int slepts = 0, sleptns = 0;
-
-#ifndef _POSIX_MONOTONIC_CLOCK
-	printf("CLOCK_MONOTONIC unavailable, test may fail due to external clock adjustments\n");
-#endif
+	clockid_t test_clock = get_supported_clock();
 
 	for (i = 0; i < NUMVALID; i++) {
 		tssleepfor.tv_sec = sleepvalid[i][0];
 		tssleepfor.tv_nsec = sleepvalid[i][1];
 		printf("sleep %d sec %d nsec\n",
 		       (int)tssleepfor.tv_sec, (int)tssleepfor.tv_nsec);
-		if (clock_gettime(TEST_CLOCK, &tsbefore) == -1) {
+		if (clock_gettime(test_clock, &tsbefore) == -1) {
 			perror("Error in clock_gettime()\n");
 			return PTS_UNRESOLVED;
 		}
 
 		if (nanosleep(&tssleepfor, &tsstorage) == 0) {
-			if (clock_gettime(TEST_CLOCK, &tsafter) == -1) {
+			if (clock_gettime(test_clock, &tsafter) == -1) {
 				perror("Error in clock_gettime()\n");
 				return PTS_UNRESOLVED;
 			}
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/2-1.c b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/2-1.c
index 8586e0ecec023029b60bce8ad5e1e72206daee34..02b122a786ef4e735d4e74f1a96e5263cd7333b1 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/2-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/2-1.c
@@ -12,12 +12,7 @@
 #include <stdio.h>
 #include <time.h>
 #include "posixtest.h"
-
-#ifdef _POSIX_MONOTONIC_CLOCK
-#define TEST_CLOCK CLOCK_MONOTONIC
-#else
-#define TEST_CLOCK CLOCK_REALTIME
-#endif
+#include "helpers.h"
 
 #define NUMINTERVALS 13
 int main(void)
@@ -30,12 +25,9 @@ int main(void)
 	int i;
 	int failure = 0;
 	int slepts, sleptns;
+	clockid_t test_clock = get_supported_clock();
 
-#ifndef _POSIX_MONOTONIC_CLOCK
-	printf("CLOCK_MONOTONIC unavailable, test may fail due to external clock adjustments\n");
-#endif
-
-	if (clock_gettime(TEST_CLOCK, &tsbefore) == -1) {
+	if (clock_gettime(test_clock, &tsbefore) == -1) {
 		perror("Error in clock_gettime()\n");
 		return PTS_UNRESOLVED;
 	}
@@ -48,7 +40,7 @@ int main(void)
 			return PTS_UNRESOLVED;
 		}
 
-		if (clock_gettime(TEST_CLOCK, &tsafter) == -1) {
+		if (clock_gettime(test_clock, &tsafter) == -1) {
 			perror("Error in clock_gettime()\n");
 			return PTS_UNRESOLVED;
 		}
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/3-2.c b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/3-2.c
index 1329a7e988055ed3815e4e4037f331f576264d1a..3d945450f0c83da8ada82f3919d91a519fcf5bc3 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/3-2.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/3-2.c
@@ -11,16 +11,10 @@
 #include <stdio.h>
 #include <time.h>
 #include <signal.h>
-#include <unistd.h>
 #include <sys/wait.h>
 #include <stdlib.h>
 #include "posixtest.h"
-
-#ifdef _POSIX_MONOTONIC_CLOCK
-#define TEST_CLOCK CLOCK_MONOTONIC
-#else
-#define TEST_CLOCK CLOCK_REALTIME
-#endif
+#include "helpers.h"
 
 #define SLEEPSEC 5
 
@@ -31,12 +25,9 @@ int main(void)
 {
 	int pid, slepts;
 	struct timespec tsbefore, tsafter;
+	clockid_t test_clock = get_supported_clock();
 
-#ifndef _POSIX_MONOTONIC_CLOCK
-	printf("CLOCK_MONOTONIC unavailable, test may fail due to external clock adjustments\n");
-#endif
-
-	if (clock_gettime(TEST_CLOCK, &tsbefore) != 0) {
+	if (clock_gettime(test_clock, &tsbefore) != 0) {
 		perror("clock_gettime() did not return success\n");
 		return PTS_UNRESOLVED;
 	}
@@ -84,7 +75,7 @@ int main(void)
 			return PTS_FAIL;
 		}
 
-		if (clock_gettime(TEST_CLOCK, &tsafter) == -1) {
+		if (clock_gettime(test_clock, &tsafter) == -1) {
 			perror("Error in clock_gettime()\n");
 			return PTS_UNRESOLVED;
 		}
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/7-2.c b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/7-2.c
index 70eeca9ff8eb10ac052b81f102853747a5066685..f0390c6dbb054e465c06c5fdb7e510487ecdc043 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/7-2.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/7-2.c
@@ -12,16 +12,10 @@
 #include <stdio.h>
 #include <time.h>
 #include <signal.h>
-#include <unistd.h>
 #include <sys/wait.h>
 #include <stdlib.h>
 #include "posixtest.h"
-
-#ifdef _POSIX_MONOTONIC_CLOCK
-#define TEST_CLOCK CLOCK_MONOTONIC
-#else
-#define TEST_CLOCK CLOCK_REALTIME
-#endif
+#include "helpers.h"
 
 #define CHILDSUCCESS 1
 #define CHILDFAILURE 0
@@ -39,12 +33,9 @@ int main(void)
 	int sleepsec = 30;
 	int pid;
 	struct sigaction act;
+	clockid_t test_clock = get_supported_clock();
 
-#ifndef _POSIX_MONOTONIC_CLOCK
-	printf("CLOCK_MONOTONIC unavailable, test may fail due to external clock adjustments\n");
-#endif
-
-	if (clock_gettime(TEST_CLOCK, &tsbefore) == -1) {
+	if (clock_gettime(test_clock, &tsbefore) == -1) {
 		perror("Error in clock_gettime()\n");
 		return PTS_UNRESOLVED;
 	}
@@ -70,7 +61,7 @@ int main(void)
 			return CHILDFAILURE;
 		}
 
-		if (clock_gettime(TEST_CLOCK, &tsafter) == -1) {
+		if (clock_gettime(test_clock, &tsafter) == -1) {
 			perror("Error in clock_gettime()\n");
 			return CHILDFAILURE;
 		}
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/helpers.h b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/helpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..a70e4c290c76c61adc55e9b006b65597dde4677d
--- /dev/null
+++ b/testcases/open_posix_testsuite/conformance/interfaces/nanosleep/helpers.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2026, Linux Test Project
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef NANOSLEEP_HELPERS_H
+#define NANOSLEEP_HELPERS_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+
+static inline clockid_t get_supported_clock(void)
+{
+#ifdef _POSIX_MONOTONIC_CLOCK
+	if (_POSIX_MONOTONIC_CLOCK > 0)
+		return CLOCK_MONOTONIC;
+
+	if (!_POSIX_MONOTONIC_CLOCK && sysconf(_SC_MONOTONIC_CLOCK) > 0)
+		return CLOCK_MONOTONIC;
+#endif
+
+	printf("CLOCK_MONOTONIC unavailable, test may fail due to "
+	       "external clock adjustments\n");
+	return CLOCK_REALTIME;
+}
+
+#endif /* NANOSLEEP_HELPERS_H */

---
base-commit: 620d596c79493af089ba6a1c4dc79efcc76a67c7
change-id: 20260416-fix_nanosleep_include-edcc8f01f0e0

Best regards,
-- 
Andrea Cervesato <andrea.cervesato@suse.com>



More information about the ltp mailing list