Skip to content

Commit 99fe595

Browse files
[libc] implement clock_gettime using vDSO (#108458)
supersedes #91805
1 parent 711278e commit 99fe595

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

libc/src/__support/time/linux/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_header_library(
99
libc.src.__support.common
1010
libc.src.__support.error_or
1111
libc.src.__support.OSUtil.osutil
12+
libc.src.__support.OSUtil.vdso
1213
)
1314

1415
add_header_library(

libc/src/__support/time/linux/clock_gettime.h

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,47 @@
1111

1212
#include "hdr/types/clockid_t.h"
1313
#include "hdr/types/struct_timespec.h"
14+
#include "src/__support/OSUtil/linux/vdso.h"
1415
#include "src/__support/OSUtil/syscall.h"
1516
#include "src/__support/common.h"
1617
#include "src/__support/error_or.h"
1718
#include "src/__support/macros/config.h"
1819
#include <sys/syscall.h>
1920

21+
#if defined(SYS_clock_gettime64)
22+
#include <linux/time_types.h>
23+
#endif
24+
2025
namespace LIBC_NAMESPACE_DECL {
2126
namespace internal {
2227
LIBC_INLINE ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
23-
#if SYS_clock_gettime
24-
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime,
25-
static_cast<long>(clockid),
26-
reinterpret_cast<long>(ts));
28+
using namespace vdso;
29+
int ret;
30+
#if defined(SYS_clock_gettime)
31+
TypedSymbol<VDSOSym::ClockGetTime> clock_gettime;
32+
if (LIBC_LIKELY(clock_gettime != nullptr))
33+
ret = clock_gettime(clockid, ts);
34+
else
35+
ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime,
36+
static_cast<long>(clockid),
37+
reinterpret_cast<long>(ts));
2738
#elif defined(SYS_clock_gettime64)
2839
static_assert(
2940
sizeof(time_t) == sizeof(int64_t),
3041
"SYS_clock_gettime64 requires struct timespec with 64-bit members.");
31-
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime64,
32-
static_cast<long>(clockid),
33-
reinterpret_cast<long>(ts));
42+
43+
TypedSymbol<VDSOSym::ClockGetTime64> clock_gettime64;
44+
__kernel_timespec ts64{};
45+
if (LIBC_LIKELY(clock_gettime64 != nullptr))
46+
ret = clock_gettime64(clockid, &ts64);
47+
else
48+
ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime64,
49+
static_cast<long>(clockid),
50+
reinterpret_cast<long>(&ts64));
51+
if (ret == 0) {
52+
ts->tv_sec = static_cast<decltype(ts->tv_sec)>(ts64.tv_sec);
53+
ts->tv_nsec = static_cast<decltype(ts->tv_nsec)>(ts64.tv_nsec);
54+
}
3455
#else
3556
#error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available."
3657
#endif

0 commit comments

Comments
 (0)