Skip to content

[libc] Implement timespec_get #116102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libc/config/baremetal/arm/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.time.gmtime
libc.src.time.gmtime_r
libc.src.time.mktime
libc.src.time.timespec_get

# internal entrypoints
libc.startup.baremetal.init
Expand Down
1 change: 1 addition & 0 deletions libc/config/baremetal/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.time.gmtime
libc.src.time.gmtime_r
libc.src.time.mktime
libc.src.time.timespec_get

# internal entrypoints
libc.startup.baremetal.init
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.time.mktime
libc.src.time.nanosleep
libc.src.time.time
libc.src.time.timespec_get

# unistd.h entrypoints
libc.src.unistd.__llvm_libc_syscall
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.time.mktime
libc.src.time.nanosleep
libc.src.time.time
libc.src.time.timespec_get

# unistd.h entrypoints
libc.src.unistd.__llvm_libc_syscall
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.time.mktime
libc.src.time.nanosleep
libc.src.time.time
libc.src.time.timespec_get

# locale.h entrypoints
libc.src.locale.localeconv
Expand Down
5 changes: 5 additions & 0 deletions libc/include/llvm-libc-macros/time-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,9 @@
#include "linux/time-macros.h"
#endif

#define TIME_UTC 1
#define TIME_MONOTONIC 2
#define TIME_ACTIVE 3
#define TIME_THREAD_ACTIVE 4

#endif // LLVM_LIBC_MACROS_TIME_MACROS_H
7 changes: 7 additions & 0 deletions libc/newhdrgen/yaml/time.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,10 @@ functions:
return_type: time_t
arguments:
- type: time_t *
- name: timespec_get
standard:
- stdc
return_type: int
arguments:
- type: struct timespec *
- type: int
8 changes: 8 additions & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -1676,6 +1676,14 @@ def StdC : StandardSpec<"stdc"> {
RetValSpec<TimeTType>,
[ArgSpec<TimeTTypePtr>]
>,
FunctionSpec<
"timespec_get",
RetValSpec<IntType>,
[
ArgSpec<StructTimeSpecPtr>,
ArgSpec<IntType>,
]
>,
Comment on lines +1679 to +1686
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since #117220 is close to landing, it might be best to skip adding anything to the old headergen files.

]
>;

Expand Down
7 changes: 7 additions & 0 deletions libc/src/time/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.time
)

add_entrypoint_object(
timespec_get
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.timespec_get
)

add_entrypoint_object(
clock
ALIAS
Expand Down
10 changes: 10 additions & 0 deletions libc/src/time/baremetal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
add_entrypoint_object(
timespec_get
SRCS
timespec_get.cpp
HDRS
../timespec_get.h
DEPENDS
libc.hdr.time_macros
libc.hdr.types.struct_timespec
)
27 changes: 27 additions & 0 deletions libc/src/time/baremetal/timespec_get.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===-- Implementation of timespec_get for baremetal ----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/time/timespec_get.h"
#include "hdr/time_macros.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

extern "C" bool __llvm_libc_timespec_get_utc(struct timespec *ts);

LLVM_LIBC_FUNCTION(int, timespec_get, (struct timespec * ts, int base)) {
if (base != TIME_UTC)
return 0;

if (!__llvm_libc_timespec_get_utc(ts))
return 0;
return base;
}

} // namespace LIBC_NAMESPACE_DECL
12 changes: 12 additions & 0 deletions libc/src/time/gpu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,15 @@ add_entrypoint_object(
libc.hdr.types.struct_timespec
.time_utils
)

add_entrypoint_object(
timespec_get
SRCS
timespec_get.cpp
HDRS
../timespec_get.h
DEPENDS
libc.hdr.time_macros
libc.hdr.types.struct_timespec
.time_utils
)
29 changes: 29 additions & 0 deletions libc/src/time/gpu/timespec_get.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===-- Implementation of timespec_get for gpu ----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/time/timespec_get.h"
#include "hdr/time_macros.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(int, timespec_get, (struct timespec * ts, int base)) {
if (base != TIME_MONOTONIC || !ts)
return 0;

uint64_t ns_per_tick = TICKS_PER_SEC / GPU_CLOCKS_PER_SEC;
uint64_t ticks = gpu::fixed_frequency_clock();

ts->tv_nsec = (ticks * ns_per_tick) % TICKS_PER_SEC;
ts->tv_sec = (ticks * ns_per_tick) / TICKS_PER_SEC;

return base;
}

} // namespace LIBC_NAMESPACE_DECL
13 changes: 13 additions & 0 deletions libc/src/time/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@ add_entrypoint_object(
libc.src.errno.errno
)

add_entrypoint_object(
timespec_get
SRCS
timespec_get.cpp
HDRS
../timespec_get.h
DEPENDS
libc.hdr.time_macros
libc.hdr.types.struct_timespec
libc.src.__support.time.linux.clock_gettime
libc.src.errno.errno
)

add_entrypoint_object(
clock
SRCS
Expand Down
45 changes: 45 additions & 0 deletions libc/src/time/linux/timespec_get.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//===-- Implementation of timespec_get for Linux --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/time/timespec_get.h"
#include "hdr/time_macros.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/time/linux/clock_gettime.h"
#include "src/errno/libc_errno.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(int, timespec_get, (struct timespec * ts, int base)) {
clockid_t clockid;
switch (base) {
case TIME_UTC:
clockid = CLOCK_REALTIME;
break;
case TIME_MONOTONIC:
clockid = CLOCK_MONOTONIC;
break;
case TIME_ACTIVE:
clockid = CLOCK_PROCESS_CPUTIME_ID;
break;
case TIME_THREAD_ACTIVE:
clockid = CLOCK_THREAD_CPUTIME_ID;
break;
default:
return 0;
}

auto result = internal::clock_gettime(clockid, ts);
if (!result.has_value()) {
libc_errno = result.error();
return 0;
}
return base;
}

} // namespace LIBC_NAMESPACE_DECL
21 changes: 21 additions & 0 deletions libc/src/time/timespec_get.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header of timespec_get -------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_TIME_TIMESPEC_GET_H
#define LLVM_LIBC_SRC_TIME_TIMESPEC_GET_H

#include "hdr/types/struct_timespec.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

int timespec_get(struct timespec *ts, int base);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_TIME_TIMESPEC_GET_H
10 changes: 10 additions & 0 deletions libc/test/src/time/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,16 @@ add_libc_unittest(
libc.src.errno.errno
)

add_libc_test(
timespec_get_test
SUITE
libc_time_unittests
SRCS
timespec_get_test.cpp
DEPENDS
libc.src.time.timespec_get
)

add_libc_test(
clock_test
SUITE
Expand Down
46 changes: 46 additions & 0 deletions libc/test/src/time/timespec_get_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//===-- Unittests for timespec_get ----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "hdr/time_macros.h"
#include "hdr/types/struct_timespec.h"
#include "src/__support/macros/properties/architectures.h"
#include "src/time/timespec_get.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcTimespecGet, Utc) {
timespec ts;
int result;
result = LIBC_NAMESPACE::timespec_get(&ts, TIME_UTC);
#ifdef LIBC_TARGET_ARCH_IS_GPU
ASSERT_EQ(result, 0);
#else
ASSERT_EQ(result, TIME_UTC);
ASSERT_GT(ts.tv_sec, time_t(0));
#endif
}

TEST(LlvmLibcTimespecGet, Monotonic) {
timespec ts1, ts2;
int result;
result = LIBC_NAMESPACE::timespec_get(&ts1, TIME_MONOTONIC);
ASSERT_EQ(result, TIME_MONOTONIC);
ASSERT_GT(ts1.tv_sec, time_t(0));
result = LIBC_NAMESPACE::timespec_get(&ts2, TIME_MONOTONIC);
ASSERT_EQ(result, TIME_MONOTONIC);
ASSERT_GE(ts2.tv_sec, ts1.tv_sec); // The monotonic time should increase.
if (ts2.tv_sec == ts1.tv_sec) {
ASSERT_GE(ts2.tv_nsec, ts1.tv_nsec);
}
}

TEST(LlvmLibcTimespecGet, Unknown) {
timespec ts;
int result;
result = LIBC_NAMESPACE::timespec_get(&ts, 0);
ASSERT_EQ(result, 0);
}
Loading