[libc] Implement getitimer and setitimer, add proxy headers for itimerval (#134773)

#133983
This commit is contained in:
Tsz Chan 2025-04-14 13:39:42 -07:00 committed by GitHub
parent a2c57e1dec
commit f5c5f9f926
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 348 additions and 0 deletions

View File

@ -363,6 +363,10 @@ set(TARGET_LIBC_ENTRYPOINTS
# sys/uio.h entrypoints
libc.src.sys.uio.writev
libc.src.sys.uio.readv
# sys/time.h entrypoints
libc.src.sys.time.setitimer
libc.src.sys.time.getitimer
)
if(LLVM_LIBC_INCLUDE_SCUDO)

View File

@ -185,6 +185,9 @@ set(TARGET_LIBC_ENTRYPOINTS
# libc.src.sys.epoll.epoll_pwait
# libc.src.sys.epoll.epoll_pwait2
# sys/time.h entrypoints
libc.src.sys.time.setitimer
libc.src.sys.time.getitimer
)
if(LLVM_LIBC_FULL_BUILD)

View File

@ -368,6 +368,10 @@ set(TARGET_LIBC_ENTRYPOINTS
# sys/uio.h entrypoints
libc.src.sys.uio.writev
libc.src.sys.uio.readv
# sys/time.h entrypoints
libc.src.sys.time.setitimer
libc.src.sys.time.getitimer
)
if(LLVM_LIBC_INCLUDE_SCUDO)

View File

@ -190,6 +190,15 @@ add_proxy_header_library(
libc.include.sys_time
)
add_proxy_header_library(
struct_itimerval
HDRS
struct_itimerval.h
FULL_BUILD_DEPENDS
libc.include.llvm-libc-types.struct_itimerval
libc.include.sys_time
)
add_proxy_header_library(
pid_t
HDRS

View File

@ -0,0 +1,21 @@
//===-- Proxy for struct itimerval ----------------------------------------===//
//
// 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_HDR_TYPES_STRUCT_ITIMERVAL_H
#define LLVM_LIBC_HDR_TYPES_STRUCT_ITIMERVAL_H
#ifdef LIBC_FULL_BUILD
#include "include/llvm-libc-types/struct_itimerval.h"
#else
#include <sys/time.h>
#endif // LIBC_FULL_BUILD
#endif // LLVM_LIBC_HDR_TYPES_STRUCT_ITIMERVAL_H

View File

@ -77,6 +77,7 @@ add_header(struct_pollfd HDR struct_pollfd.h)
add_header(struct_rlimit HDR struct_rlimit.h DEPENDS .rlim_t)
add_header(struct_sched_param HDR struct_sched_param.h)
add_header(struct_timeval HDR struct_timeval.h DEPENDS .suseconds_t .time_t)
add_header(struct_itimerval HDR struct_itimerval.h DEPENDS .struct_timeval)
add_header(struct_rusage HDR struct_rusage.h DEPENDS .struct_timeval)
add_header(union_sigval HDR union_sigval.h)
add_header(siginfo_t HDR siginfo_t.h DEPENDS .union_sigval .pid_t .uid_t .clock_t)

View File

@ -0,0 +1,19 @@
//===-- Definition of struct itimerval ------------------------------------===//
//
// 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_TYPES_STRUCT_ITIMERVAL_H
#define LLVM_LIBC_TYPES_STRUCT_ITIMERVAL_H
#include "struct_timeval.h"
struct itimerval {
struct timeval it_interval; /* Interval for periodic timer */
struct timeval it_value; /* Time until next expiration */
};
#endif // LLVM_LIBC_TYPES_STRUCT_ITIMERVAL_H

View File

@ -4,6 +4,7 @@ standards: Linux
macros: []
types:
- type_name: struct_timeval
- type_name: struct_itimerval
enums: []
objects: []
functions:
@ -12,3 +13,20 @@ functions:
arguments:
- type: const char*
- type: const struct timeval*
- name: setitimer
standards:
- POSIX
return_type: int
arguments:
- type: int
- type: const struct itimerval *__restrict
- type: struct itimerval *__restrict
- name: getitimer
standards:
- POSIX
return_type: int
arguments:
- type: int
- type: struct itimerval *

View File

@ -8,3 +8,17 @@ add_entrypoint_object(
DEPENDS
.${LIBC_TARGET_OS}.utimes
)
add_entrypoint_object(
setitimer
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.setitimer
)
add_entrypoint_object(
getitimer
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.getitimer
)

View File

@ -0,0 +1,19 @@
//===-- Implementation header for getitimer -------------------------------===//
//
// 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_SYS_TIME_GETITIMER_H
#define LLVM_LIBC_SRC_SYS_TIME_GETITIMER_H
#include "hdr/types/struct_itimerval.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
int getitimer(int which, struct itimerval *curr_value);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SYS_TIME_GETITIMER_H

View File

@ -14,3 +14,31 @@ add_entrypoint_object(
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
add_entrypoint_object(
setitimer
SRCS
setitimer.cpp
HDRS
../setitimer.h
DEPENDS
libc.hdr.types.struct_itimerval
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
libc.src.__support.common
libc.src.errno.errno
)
add_entrypoint_object(
getitimer
SRCS
getitimer.cpp
HDRS
../getitimer.h
DEPENDS
libc.hdr.types.struct_itimerval
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
libc.src.__support.common
libc.src.errno.errno
)

View File

@ -0,0 +1,29 @@
//===-- Implementation file for getitimer ---------------------------------===//
//
// 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/sys/time/getitimer.h"
#include "hdr/types/struct_itimerval.h"
#include "src/__support/OSUtil/syscall.h"
#include "src/__support/common.h"
#include "src/errno/libc_errno.h"
#include <sys/syscall.h>
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, getitimer, (int which, struct itimerval *curr_value)) {
long ret =
LIBC_NAMESPACE::syscall_impl<long>(SYS_getitimer, which, curr_value);
// On failure, return -1 and set errno.
if (ret < 0) {
libc_errno = static_cast<int>(-ret);
return -1;
}
return 0;
}
} // namespace LIBC_NAMESPACE_DECL

View File

@ -0,0 +1,30 @@
//===-- Implementation file for setitimer ---------------------------------===//
//
// 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/sys/time/setitimer.h"
#include "hdr/types/struct_itimerval.h"
#include "src/__support/OSUtil/syscall.h"
#include "src/__support/common.h"
#include "src/errno/libc_errno.h"
#include <sys/syscall.h>
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, setitimer,
(int which, const struct itimerval *new_value,
struct itimerval *old_value)) {
long ret = LIBC_NAMESPACE::syscall_impl<long>(SYS_setitimer, which, new_value,
old_value);
// On failure, return -1 and set errno.
if (ret < 0) {
libc_errno = static_cast<int>(-ret);
return -1;
}
return 0;
}
} // namespace LIBC_NAMESPACE_DECL

View File

@ -0,0 +1,20 @@
//===-- Implementation header for setitimer -------------------------------===//
//
// 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_SYS_TIME_SETITIMER_H
#define LLVM_LIBC_SRC_SYS_TIME_SETITIMER_H
#include "hdr/types/struct_itimerval.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
int setitimer(int which, const struct itimerval *new_value,
struct itimerval *old_value);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SYS_TIME_SETITIMER_H

View File

@ -19,3 +19,34 @@ add_libc_unittest(
libc.src.sys.stat.stat
libc.test.UnitTest.ErrnoCheckingTest
)
add_libc_unittest(
setitimer_test
SUITE
libc_sys_time_unittests
SRCS
setitimer_test.cpp
DEPENDS
libc.include.signal
libc.src.sys.time.setitimer
libc.src.signal.sigaction
libc.src.signal.sigemptyset
libc.src.__support.common
libc.src.errno.errno
libc.test.UnitTest.ErrnoCheckingTest
libc.test.UnitTest.ErrnoSetterMatcher
)
add_libc_unittest(
getitimer_test
SUITE
libc_sys_time_unittests
SRCS
getitimer_test.cpp
DEPENDS
libc.src.sys.time.getitimer
libc.src.__support.common
libc.src.errno.errno
libc.test.UnitTest.ErrnoCheckingTest
libc.test.UnitTest.ErrnoSetterMatcher
)

View File

@ -0,0 +1,41 @@
//===-- Unittests for getitimer -------------------------------------------===//
//
// 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/types/struct_itimerval.h"
#include "src/sys/time/getitimer.h"
#include "test/UnitTest/ErrnoCheckingTest.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"
using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
using LlvmLibcSysTimeGetitimerTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
TEST_F(LlvmLibcSysTimeGetitimerTest, SmokeTest) {
struct itimerval timer;
timer.it_value.tv_sec = -1;
timer.it_value.tv_usec = -1;
timer.it_interval.tv_sec = -1;
timer.it_interval.tv_usec = -1;
ASSERT_THAT(LIBC_NAMESPACE::getitimer(0, &timer),
returns(EQ(0)).with_errno(EQ(0)));
ASSERT_TRUE(timer.it_value.tv_sec == 0);
ASSERT_TRUE(timer.it_value.tv_usec == 0);
ASSERT_TRUE(timer.it_interval.tv_sec == 0);
ASSERT_TRUE(timer.it_interval.tv_usec == 0);
}
TEST_F(LlvmLibcSysTimeGetitimerTest, InvalidRetTest) {
struct itimerval timer;
// out of range timer type (which)
ASSERT_THAT(LIBC_NAMESPACE::getitimer(99, &timer),
returns(NE(0)).with_errno(NE(0)));
}

View File

@ -0,0 +1,57 @@
//===-- Unittests for setitimer -------------------------------------------===//
//
// 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/types/struct_itimerval.h"
#include "hdr/types/struct_sigaction.h"
#include "src/signal/sigaction.h"
#include "src/signal/sigemptyset.h"
#include "src/sys/time/setitimer.h"
#include "test/UnitTest/ErrnoCheckingTest.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"
using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
using LlvmLibcSysTimeSetitimerTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
static bool timer_fired(false);
extern "C" void handle_sigalrm(int) { timer_fired = true; }
TEST_F(LlvmLibcSysTimeSetitimerTest, SmokeTest) {
LIBC_NAMESPACE::libc_errno = 0;
struct sigaction sa;
sa.sa_handler = handle_sigalrm;
LIBC_NAMESPACE::sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
LIBC_NAMESPACE::sigaction(SIGALRM, &sa, nullptr);
struct itimerval timer;
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 200000;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0; // One-shot timer
ASSERT_THAT(LIBC_NAMESPACE::setitimer(0, &timer, nullptr),
returns(EQ(0)).with_errno(EQ(0)));
while (true) {
if (timer_fired)
break;
}
ASSERT_TRUE(timer_fired);
}
TEST_F(LlvmLibcSysTimeSetitimerTest, InvalidRetTest) {
struct itimerval timer;
// out of range timer type (which)
ASSERT_THAT(LIBC_NAMESPACE::setitimer(99, &timer, nullptr),
returns(NE(0)).with_errno(NE(0)));
}