[COMMIT osv master] libc: make pthread_getcpuclockid() compatible with glibc

5 views
Skip to first unread message

Commit Bot

unread,
Dec 18, 2023, 9:15:31 AM12/18/23
to osv...@googlegroups.com, Waldemar Kozaczuk
From: Waldemar Kozaczuk <jwkoz...@gmail.com>
Committer: Nadav Har'El <n...@scylladb.com>
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 <jwkoz...@gmail.com>

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);
}
}
Reply all
Reply to author
Forward
0 new messages