From: Waldemar Kozaczuk <[email protected]>
Committer: Nadav Har'El <[email protected]>
Branch: master

libc: make pthread_getcpuclockid() compatible with glibc

When we run tst-pthread-clock.cc on OSv with Linux dynamic linker,
it uses the glibc version of pthread_getcpuclockid(). The glibc
pthread_getcpuclockid() uses different scheme (same musl) to encode
the clockid which is actually compatible with what Linux kernel expects
when handling clock_gettime(). In the end, the tst-pthread-clock.cc
fails when calling clock_gettime() with clock_id returned earlier
by pthread_getcpuclockid().

To make this test work correctly on OSv with Linux dynamic linker,
we change the scheme used by pthread_getcpuclockid() and clock_gettime()
to follow what glibc and musl do (see
https://git.musl-libc.org/cgit/musl/tree/src/thread/pthread_getcpuclockid.c
and
https://github.com/bminor/glibc/blob/master/sysdeps/unix/sysv/linux/kernel-posix-cpu-timers.h).

With this patch one can run more tests on OSv with Linux dynamic linker:

scripts/test.py --linux_ld -m modules/tests-with-linux-ld/usr.manifest \
  -d tst-kill \
  -d tst-sigaction \
  -d tst-sigwait \
  -d tst-stdio-rofs \
  -d tst-wctype

Signed-off-by: Waldemar Kozaczuk <[email protected]>

Closes #1286

---
diff --git a/libc/pthread.cc b/libc/pthread.cc
--- a/libc/pthread.cc
+++ b/libc/pthread.cc
@@ -325,7 +325,10 @@ int pthread_getcpuclockid(pthread_t thread, clockid_t 
*clock_id)
     if (clock_id) {
         pthread *p = pthread::from_libc(thread);
         auto id = p->_thread->id();
-        *clock_id = id + _OSV_CLOCK_SLOTS;
+        //Follow the same formula glibc and musl use to create
+        //a negative clock_id that is then used by Linux kernel when
+        //handling get_clocktime (see 
https://git.musl-libc.org/cgit/musl/tree/src/thread/pthread_getcpuclockid.c)
+        *clock_id = (-id - 1) * 8U + 6;
     }
     return 0;
 }
diff --git a/libc/pthread.hh b/libc/pthread.hh
--- a/libc/pthread.hh
+++ b/libc/pthread.hh
@@ -12,12 +12,6 @@
 extern "C" {
 #endif
 
-// Linux's <time.h> defines 9 types of clocks. We reserve space for 16 slots
-// and use the clock ids afterwards for per-thread clocks. This is OSv-
-// specific, and an application doesn't need to know about it - only
-// pthread_getcpuclockid() and clock_gettime() need to know about this.
-#define _OSV_CLOCK_SLOTS 16
-
 #ifdef __cplusplus
 }
 
diff --git a/libc/time.cc b/libc/time.cc
--- a/libc/time.cc
+++ b/libc/time.cc
@@ -96,11 +96,20 @@ int clock_gettime(clockid_t clk_id, struct timespec* ts)
         break;
 
     default:
-        if (clk_id < _OSV_CLOCK_SLOTS) {
+        //At this point we should only let the negative numbers
+        //which represent clock_id for specific thread
+        if (clk_id >= 0) {
             return libc_error(EINVAL);
         } else {
-            auto thread = sched::thread::find_by_id(clk_id - _OSV_CLOCK_SLOTS);
-            fill_ts(thread->thread_clock(), ts);
+            //Reverse the formula used in pthread_getcpuclockid()
+            //and calculate thread id given clk_id
+            pid_t tid = (-clk_id - 2) / 8;
+            auto thread = sched::thread::find_by_id(tid);
+            if (thread) {
+                fill_ts(thread->thread_clock(), ts);
+            } else {
+                return libc_error(EINVAL);
+            }
         }
     }
 
@@ -124,7 +133,9 @@ int clock_getres(clockid_t clk_id, struct timespec* ts)
     case CLOCK_MONOTONIC_RAW:
         break;
     default:
-        if (clk_id < _OSV_CLOCK_SLOTS) {
+        //At this point we should only let the negative numbers
+        //which represent clock_id for specific thread
+        if (clk_id >= 0) {
             return libc_error(EINVAL);
         }
     }

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/000000000000d5ae0d060cc96102%40google.com.

Reply via email to