[PATCH] posix: Support CLOCK_MONOTONIC in clock_getres and add tests (#3889)

Hello,

While studying the POSIX compliance layer in RTEMS and looking at Work Item #3889 (“Tests needed for CLOCK_MONOTONIC”), I noticed that clock_getres() currently returns EINVAL when called with CLOCK_MONOTONIC because case CLOCK_MONOTONIC: was missing from the switch statement in cpukit/posix/src/clockgetres.c.

Per IEEE Std 1003.1-2017 (POSIX.1-2017), clock_getres(CLOCK_MONOTONIC, &res) should populate res with the clock resolution (which in RTEMS is determined by the system clock tick). Furthermore, dedicated test assertions for CLOCK_MONOTONIC in testsuites/psxtests/psxclock were missing.

I have implemented the fix and added tests in testsuites/psxtests/psxclock/init.c covering:

  1. clock_settime(CLOCK_MONOTONIC, &tv) rejection with -1 and errno == EINVAL.
  2. clock_getres(CLOCK_MONOTONIC, &tv) resolution query returning 0 and positive nanoseconds.
  3. clock_gettime(CLOCK_MONOTONIC, &tv) progression ensuring non-decreasing monotonic time across delay ticks.

Verified cleanly on the sparc/erc32 BSP under the sparc-rtems7-sis simulator.

Below is the git patch:

From cd14aca4771191f5ec6aff8a9e2f0700d8169aa4 Mon Sep 17 00:00:00 2001
From: Sharvin Neve <sharvinneve67@gmail.com>
Date: Tue, 8 Sep 2026 08:38:19 +0000
Subject: [PATCH] posix: Support CLOCK_MONOTONIC in clock_getres and add tests

Add support for querying CLOCK_MONOTONIC resolution in clock_getres()
matching the system clock tick resolution.

Add tests in testsuites/psxtests/psxclock to verify:
- clock_settime(CLOCK_MONOTONIC) correctly returns -1 with EINVAL
- clock_getres(CLOCK_MONOTONIC) succeeds with positive resolution
- clock_gettime(CLOCK_MONOTONIC) maintains non-decreasing progression

Updates #3889.
---
 cpukit/posix/src/clockgetres.c      |  3 +++
 testsuites/psxtests/psxclock/init.c | 32 +++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/cpukit/posix/src/clockgetres.c b/cpukit/posix/src/clockgetres.c
index e03d0bb86f..49cd333f3d 100644
--- a/cpukit/posix/src/clockgetres.c
+++ b/cpukit/posix/src/clockgetres.c
@@ -61,6 +61,9 @@ int clock_getres( clockid_t clock_id, struct timespec *res )
      */
 
     case CLOCK_REALTIME:
+#ifdef CLOCK_MONOTONIC
+    case CLOCK_MONOTONIC:
+#endif
     case CLOCK_PROCESS_CPUTIME_ID:
     case CLOCK_THREAD_CPUTIME_ID:
       if ( res ) {
diff --git a/testsuites/psxtests/psxclock/init.c b/testsuites/psxtests/psxclock/init.c
index 34f2508943..4869c1517c 100644
--- a/testsuites/psxtests/psxclock/init.c
+++ b/testsuites/psxtests/psxclock/init.c
@@ -367,6 +367,15 @@ static rtems_task Init( rtems_task_argument argument )
   rtems_test_assert( sc == -1 );
   rtems_test_assert( errno == EINVAL );
 
+  /* CLOCK_MONOTONIC cannot be set per POSIX-1.2017 */
+  puts( "Init: clock_settime - CLOCK_MONOTONIC EINVAL" );
+  tv.tv_sec = 946684800;
+  tv.tv_nsec = 0;
+  errno = 0;
+  sc = clock_settime( CLOCK_MONOTONIC, &tv );
+  rtems_test_assert( sc == -1 );
+  rtems_test_assert( errno == EINVAL );
+
   /* exercise clock_getres */
 
   puts( "Init: clock_getres - EINVAL (invalid clockid)" );
@@ -390,6 +399,12 @@ static rtems_task Init( rtems_task_argument argument )
   );
   rtems_test_assert( !sc );
 
+  puts( "Init: clock_getres - CLOCK_MONOTONIC SUCCESSFUL" );
+  sc = clock_getres( CLOCK_MONOTONIC, &tv );
+  rtems_test_assert( !sc );
+  rtems_test_assert( tv.tv_sec >= 0 );
+  rtems_test_assert( tv.tv_nsec > 0 );
+
   /* set the time of day, and print our buffer in multiple ways */
 
   tv.tv_sec = mktime( &tm );
@@ -567,6 +582,23 @@ static rtems_task Init( rtems_task_argument argument )
 
   test_settime_and_sleeping();
 
+  /* verify CLOCK_MONOTONIC non-decreasing progression across delay */
+  {
+    struct timespec mono_start, mono_end;
+    puts( "Init: clock_gettime - CLOCK_MONOTONIC non-decreasing" );
+    sc = clock_gettime( CLOCK_MONOTONIC, &mono_start );
+    rtems_test_assert( sc == 0 );
+
+    wait_ticks( 2 );
+
+    sc = clock_gettime( CLOCK_MONOTONIC, &mono_end );
+    rtems_test_assert( sc == 0 );
+    rtems_test_assert(
+      ( mono_end.tv_sec > mono_start.tv_sec ) ||
+      ( mono_end.tv_sec == mono_start.tv_sec && mono_end.tv_nsec >= mono_start.tv_nsec )
+    );
+  }
+
   TEST_END();
   rtems_test_exit( 0 );
 }
-- 
2.53.0

Any feedback or suggestions on this patch would be greatly appreciated.