Skip to content

Commit

Permalink
libc: make pthread_getcpuclockid() compatible with glibc
Browse files Browse the repository at this point in the history
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 cloudius-systems#1286
  • Loading branch information
wkozaczuk authored and nyh committed Dec 18, 2023
1 parent cf0f752 commit 310930b
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 11 deletions.
5 changes: 4 additions & 1 deletion libc/pthread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
6 changes: 0 additions & 6 deletions libc/pthread.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
19 changes: 15 additions & 4 deletions libc/time.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}

Expand All @@ -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);
}
}
Expand Down

0 comments on commit 310930b

Please sign in to comment.