Skip to content

Commit 123bf08

Browse files
[libc] Unify gettime implementations (#65383)
Similar to D159208, this patch unifies the calls to a syscall, in this patch it is the syscall SYS_clock_gettime/SYS_clock_gettime64. This patch also fixes calls to SYS_clock_gettime64 by creating a timespec64 object, passing it to the syscall and rewriting the timespec given by the caller with timespec64 object's contents. This fixes cases where timespec has a 4 bytes long time_t member, but SYS_clock_gettime is not available (e.g., rv32).
1 parent 5f16a3a commit 123bf08

File tree

7 files changed

+112
-83
lines changed

7 files changed

+112
-83
lines changed

libc/src/time/CMakeLists.txt

+14-27
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,6 @@ add_entrypoint_object(
3535
libc.include.time
3636
)
3737

38-
add_entrypoint_object(
39-
clock_gettime
40-
SRCS
41-
clock_gettime.cpp
42-
HDRS
43-
clock_gettime.h
44-
DEPENDS
45-
libc.include.time
46-
libc.include.sys_syscall
47-
libc.src.__support.OSUtil.osutil
48-
libc.src.errno.errno
49-
)
50-
5138
add_entrypoint_object(
5239
difftime
5340
SRCS
@@ -58,20 +45,6 @@ add_entrypoint_object(
5845
libc.include.time
5946
)
6047

61-
add_entrypoint_object(
62-
gettimeofday
63-
SRCS
64-
gettimeofday.cpp
65-
HDRS
66-
gettimeofday.h
67-
DEPENDS
68-
.clock_gettime
69-
libc.include.time
70-
libc.include.sys_syscall
71-
libc.src.__support.OSUtil.osutil
72-
libc.src.errno.errno
73-
)
74-
7548
add_entrypoint_object(
7649
gmtime
7750
SRCS
@@ -126,3 +99,17 @@ add_entrypoint_object(
12699
DEPENDS
127100
.${LIBC_TARGET_OS}.nanosleep
128101
)
102+
103+
add_entrypoint_object(
104+
clock_gettime
105+
ALIAS
106+
DEPENDS
107+
.${LIBC_TARGET_OS}.clock_gettime
108+
)
109+
110+
add_entrypoint_object(
111+
gettimeofday
112+
ALIAS
113+
DEPENDS
114+
.${LIBC_TARGET_OS}.gettimeofday
115+
)

libc/src/time/linux/CMakeLists.txt

+26
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,29 @@ add_entrypoint_object(
3838
libc.src.__support.OSUtil.osutil
3939
libc.src.errno.errno
4040
)
41+
42+
add_entrypoint_object(
43+
clock_gettime
44+
SRCS
45+
clock_gettime.cpp
46+
HDRS
47+
../clock_gettime.h
48+
DEPENDS
49+
libc.include.time
50+
libc.include.sys_syscall
51+
libc.src.__support.OSUtil.osutil
52+
libc.src.errno.errno
53+
)
54+
55+
add_entrypoint_object(
56+
gettimeofday
57+
SRCS
58+
gettimeofday.cpp
59+
HDRS
60+
../gettimeofday.h
61+
DEPENDS
62+
libc.include.time
63+
libc.include.sys_syscall
64+
libc.src.__support.OSUtil.osutil
65+
libc.src.errno.errno
66+
)

libc/src/time/linux/clock.cpp

+5-13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
1313
#include "src/__support/common.h"
1414
#include "src/errno/libc_errno.h"
15+
#include "src/time/linux/clockGetTimeImpl.h"
1516

1617
#include <sys/syscall.h> // For syscall numbers.
1718
#include <time.h>
@@ -20,19 +21,10 @@ namespace __llvm_libc {
2021

2122
LLVM_LIBC_FUNCTION(clock_t, clock, ()) {
2223
struct timespec ts;
23-
#if SYS_clock_gettime
24-
int ret = __llvm_libc::syscall_impl<int>(
25-
SYS_clock_gettime, CLOCK_PROCESS_CPUTIME_ID, reinterpret_cast<long>(&ts));
26-
#elif defined(SYS_clock_gettime64)
27-
int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime64,
28-
CLOCK_PROCESS_CPUTIME_ID,
29-
reinterpret_cast<long>(&ts));
30-
#else
31-
#error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available."
32-
#endif
33-
if (ret < 0) {
34-
libc_errno = -ret;
35-
return clock_t(-1);
24+
auto result = internal::clock_gettimeimpl(CLOCK_PROCESS_CPUTIME_ID, &ts);
25+
if (!result.has_value()) {
26+
libc_errno = result.error();
27+
return -1;
3628
}
3729

3830
// The above syscall gets the CPU time in seconds plus nanoseconds.
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,47 @@
1-
//===---------- Linux implementation of the POSIX clock_gettime function --===//
1+
//===- Linux implementation of the POSIX clock_gettime function -*- C++ -*-===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "src/time/clock_gettime.h"
9+
#ifndef LLVM_LIBC_SRC_TIME_LINUX_CLOCKGETTIMEIMPL_H
10+
#define LLVM_LIBC_SRC_TIME_LINUX_CLOCKGETTIMEIMPL_H
1011

1112
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
1213
#include "src/__support/common.h"
14+
#include "src/__support/error_or.h"
1315
#include "src/errno/libc_errno.h"
1416

1517
#include <sys/syscall.h> // For syscall numbers.
1618
#include <time.h>
1719

1820
namespace __llvm_libc {
21+
namespace internal {
1922

20-
// TODO(michaelrj): Move this into time/linux with the other syscalls.
21-
LLVM_LIBC_FUNCTION(int, clock_gettime,
22-
(clockid_t clockid, struct timespec *tp)) {
23+
LIBC_INLINE ErrorOr<int> clock_gettimeimpl(clockid_t clockid,
24+
struct timespec *ts) {
2325
#if SYS_clock_gettime
2426
int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime,
2527
static_cast<long>(clockid),
26-
reinterpret_cast<long>(tp));
28+
reinterpret_cast<long>(ts));
2729
#elif defined(SYS_clock_gettime64)
30+
struct timespec64 ts64;
2831
int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime64,
2932
static_cast<long>(clockid),
30-
reinterpret_cast<long>(tp));
33+
reinterpret_cast<long>(&ts64));
34+
ts->tv_sec = static_cast<time_t>(ts64.tv_sec);
35+
ts->tv_nsec = static_cast<long>(ts64.tv_nsec);
3136
#else
3237
#error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available."
3338
#endif
34-
35-
// A negative return value indicates an error with the magnitude of the
36-
// value being the error code.
37-
if (ret < 0) {
38-
libc_errno = -ret;
39-
return -1;
40-
}
41-
42-
return 0;
39+
if (ret < 0)
40+
return Error(-ret);
41+
return ret;
4342
}
4443

44+
} // namespace internal
4545
} // namespace __llvm_libc
46+
47+
#endif // LLVM_LIBC_SRC_TIME_LINUX_CLOCKGETTIMEIMPL_H

libc/src/time/linux/clock_gettime.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===---------- Linux implementation of the POSIX clock_gettime function --===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/time/clock_gettime.h"
10+
11+
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
12+
#include "src/__support/common.h"
13+
#include "src/errno/libc_errno.h"
14+
#include "src/time/linux/clockGetTimeImpl.h"
15+
16+
#include <sys/syscall.h> // For syscall numbers.
17+
#include <time.h>
18+
19+
namespace __llvm_libc {
20+
21+
// TODO(michaelrj): Move this into time/linux with the other syscalls.
22+
LLVM_LIBC_FUNCTION(int, clock_gettime,
23+
(clockid_t clockid, struct timespec *ts)) {
24+
auto result = internal::clock_gettimeimpl(clockid, ts);
25+
26+
// A negative return value indicates an error with the magnitude of the
27+
// value being the error code.
28+
if (!result.has_value()) {
29+
libc_errno = result.error();
30+
return -1;
31+
}
32+
return 0;
33+
}
34+
35+
} // namespace __llvm_libc

libc/src/time/gettimeofday.cpp renamed to libc/src/time/linux/gettimeofday.cpp

+10-16
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
1212
#include "src/__support/common.h"
1313
#include "src/errno/libc_errno.h"
14+
#include "src/time/linux/clockGetTimeImpl.h"
1415

1516
#include <sys/syscall.h> // For syscall numbers.
1617

@@ -21,26 +22,19 @@ LLVM_LIBC_FUNCTION(int, gettimeofday,
2122
(struct timeval * tv, [[maybe_unused]] void *unused)) {
2223
if (tv == nullptr)
2324
return 0;
24-
struct timespec tp;
25-
#if SYS_clock_gettime
26-
int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime,
27-
static_cast<long>(CLOCK_REALTIME),
28-
reinterpret_cast<long>(&tp));
29-
#elif defined(SYS_clock_gettime64)
30-
int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime64,
31-
static_cast<long>(CLOCK_REALTIME),
32-
reinterpret_cast<long>(&tp));
33-
#else
34-
#error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available."
35-
#endif
25+
26+
struct timespec ts;
27+
auto result = internal::clock_gettimeimpl(CLOCK_REALTIME, &ts);
28+
3629
// A negative return value indicates an error with the magnitude of the
3730
// value being the error code.
38-
if (ret < 0) {
39-
libc_errno = -ret;
31+
if (!result.has_value()) {
32+
libc_errno = result.error();
4033
return -1;
4134
}
42-
tv->tv_sec = tp.tv_sec;
43-
tv->tv_usec = static_cast<suseconds_t>(tp.tv_nsec / 1000);
35+
36+
tv->tv_sec = ts.tv_sec;
37+
tv->tv_usec = static_cast<suseconds_t>(ts.tv_nsec / 1000);
4438
return 0;
4539
}
4640

libc/src/time/linux/time.cpp

+4-11
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
1212
#include "src/__support/common.h"
1313
#include "src/errno/libc_errno.h"
14+
#include "src/time/linux/clockGetTimeImpl.h"
1415

1516
#include <sys/syscall.h> // For syscall numbers.
1617
#include <time.h>
@@ -20,17 +21,9 @@ namespace __llvm_libc {
2021
LLVM_LIBC_FUNCTION(time_t, time, (time_t * tp)) {
2122
// TODO: Use the Linux VDSO to fetch the time and avoid the syscall.
2223
struct timespec ts;
23-
#if SYS_clock_gettime
24-
int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime, CLOCK_REALTIME,
25-
reinterpret_cast<long>(&ts));
26-
#elif defined(SYS_clock_gettime64)
27-
int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime64, CLOCK_REALTIME,
28-
reinterpret_cast<long>(&ts));
29-
#else
30-
#error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available."
31-
#endif
32-
if (ret < 0) {
33-
libc_errno = -ret;
24+
auto result = internal::clock_gettimeimpl(CLOCK_REALTIME, &ts);
25+
if (!result.has_value()) {
26+
libc_errno = result.error();
3427
return -1;
3528
}
3629

0 commit comments

Comments
 (0)