Skip to content

Commit c033832

Browse files
Yifan ZhuSchrodingerZhu
authored andcommitted
[libc] fix
1 parent 801abf3 commit c033832

File tree

7 files changed

+187
-16
lines changed

7 files changed

+187
-16
lines changed

libc/hdr/types/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,12 @@ add_proxy_header_library(
126126
libc.include.llvm-libc-types.atexithandler_t
127127
libc.include.stdlib
128128
)
129+
130+
add_proxy_header_library(
131+
struct_sigaction
132+
HDRS
133+
struct_sigaction.h
134+
FULL_BUILD_DEPENDS
135+
libc.include.llvm-libc-types.struct_sigaction
136+
libc.include.signal
137+
)

libc/hdr/types/struct_sigaction.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Proxy for struct sigaction ---------------------------------------===//
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+
#ifndef LLVM_LIBC_HDR_TYPES_STRUCT_SIGACTION_H
9+
#define LLVM_LIBC_HDR_TYPES_STRUCT_SIGACTION_H
10+
11+
#ifdef LIBC_FULL_BUILD
12+
13+
#include "include/llvm-libc-types/struct_sigaction.h"
14+
15+
#else
16+
17+
#include <signal.h>
18+
19+
#endif // LIBC_FULL_BUILD
20+
21+
#endif // LLVM_LIBC_HDR_TYPES_STRUCT_SIGACTION_H

libc/src/sched/linux/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ add_entrypoint_object(
2929
HDRS
3030
../sched_getcpucount.h
3131
DEPENDS
32-
libc.include.sched
32+
libc.hdr.types.cpu_set_t
3333
)
3434

3535
add_entrypoint_object(

libc/src/signal/linux/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ add_entrypoint_object(
6060
DEPENDS
6161
.__restore
6262
libc.hdr.types.sigset_t
63+
libc.hdr.types.struct_sigaction
6364
libc.include.sys_syscall
6465
libc.src.__support.OSUtil.osutil
6566
libc.src.errno.errno

libc/src/signal/sigaction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#ifndef LLVM_LIBC_SRC_SIGNAL_SIGACTION_H
1010
#define LLVM_LIBC_SRC_SIGNAL_SIGACTION_H
1111

12-
#include <signal.h>
12+
#include <hdr/types/struct_sigaction.h>
1313

1414
namespace LIBC_NAMESPACE {
1515

libc/test/src/__support/OSUtil/linux/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@ add_libc_test(
88
SRCS vdso_test.cpp
99
DEPENDS
1010
libc.src.__support.OSUtil.linux.vdso
11+
libc.src.__support.OSUtil.osutil
12+
libc.hdr.types.struct_sigaction
1113
libc.hdr.types.struct_timeval
1214
libc.hdr.types.struct_timespec
1315
libc.hdr.types.clockid_t
16+
libc.hdr.types.time_t
1417
libc.hdr.time_macros
18+
libc.hdr.signal_macros
19+
libc.src.signal.sigaction
20+
libc.src.signal.raise
1521
)

libc/test/src/__support/OSUtil/linux/vdso_test.cpp

Lines changed: 148 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,46 +6,58 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "hdr/signal_macros.h"
910
#include "hdr/time_macros.h"
1011
#include "hdr/types/clockid_t.h"
12+
#include "hdr/types/struct_sigaction.h"
1113
#include "hdr/types/struct_timespec.h"
1214
#include "hdr/types/struct_timeval.h"
13-
#include "include/llvm-libc-macros/linux/time-macros.h"
15+
#include "hdr/types/time_t.h"
1416
#include "src/__support/OSUtil/linux/vdso.h"
17+
#include "src/__support/OSUtil/syscall.h"
18+
#include "src/signal/raise.h"
19+
#include "src/signal/sigaction.h"
20+
#include "test/UnitTest/ErrnoSetterMatcher.h"
1521
#include "test/UnitTest/LibcTest.h"
1622
#include "test/UnitTest/Test.h"
23+
#include <linux/time_types.h>
24+
#include <sys/syscall.h>
1725

1826
namespace LIBC_NAMESPACE {
19-
TEST(LlvmLibcOSUtilVDSOTest, SymbolsDefined) {
20-
for (size_t i = 0; i < static_cast<size_t>(vdso::VDSOSym::VDSOSymCount);
21-
++i) {
22-
// riscv_hwprobe is provided only on >=6.4 kernels. Skip it for now.
23-
#ifdef LIBC_VDSO_HAS_RISCV_HWPROBE
24-
if (static_cast<vdso::VDSOSym>(i) == vdso::VDSOSym::RiscvHwProbe)
25-
continue;
26-
#endif
27-
EXPECT_NE(vdso::get_symbol(static_cast<vdso::VDSOSym>(i)),
28-
static_cast<void *>(nullptr));
29-
}
30-
}
31-
3227
#ifdef LIBC_VDSO_HAS_GETTIMEOFDAY
3328
TEST(LlvmLibcOSUtilVDSOTest, GetTimeOfDay) {
3429
using FuncTy = int (*)(timeval *, struct timezone *);
3530
auto func =
3631
reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::GetTimeOfDay));
32+
if (func == nullptr)
33+
return;
3734
timeval tv;
3835
EXPECT_EQ(func(&tv, nullptr), 0);
3936
// hopefully people are not building time machines using our libc.
4037
EXPECT_GT(tv.tv_sec, static_cast<decltype(tv.tv_sec)>(0));
4138
}
4239
#endif
4340

41+
#ifdef LIBC_VDSO_HAS_TIME
42+
TEST(LlvmLibcOSUtilVDSOTest, Time) {
43+
using FuncTy = time_t (*)(time_t *);
44+
auto func = reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::Time));
45+
if (func == nullptr)
46+
return;
47+
time_t a, b;
48+
EXPECT_GT(func(&a), static_cast<time_t>(0));
49+
EXPECT_GT(func(&b), static_cast<time_t>(0));
50+
EXPECT_GE(b, a);
51+
}
52+
#endif
53+
4454
#ifdef LIBC_VDSO_HAS_CLOCK_GETTIME
4555
TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime) {
4656
using FuncTy = int (*)(clockid_t, timespec *);
4757
auto func =
4858
reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::ClockGetTime));
59+
if (func == nullptr)
60+
return;
4961
timespec a, b;
5062
EXPECT_EQ(func(CLOCK_MONOTONIC, &a), 0);
5163
EXPECT_EQ(func(CLOCK_MONOTONIC, &b), 0);
@@ -57,15 +69,137 @@ TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime) {
5769
}
5870
#endif
5971

72+
#ifdef LIBC_VDSO_HAS_CLOCK_GETTIME64
73+
TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime64) {
74+
using FuncTy = int (*)(clockid_t, __kernel_timespec *);
75+
auto func =
76+
reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::ClockGetTime64));
77+
if (func == nullptr)
78+
return;
79+
// See kernel API at
80+
// https://elixir.bootlin.com/linux/latest/source/tools/testing/selftests/vDSO/vdso_test_correctness.c#L155
81+
__kernel_timespec a, b;
82+
EXPECT_EQ(func(CLOCK_MONOTONIC, &a), 0);
83+
EXPECT_EQ(func(CLOCK_MONOTONIC, &b), 0);
84+
if (a.tv_sec == b.tv_sec) {
85+
EXPECT_LT(a.tv_nsec, b.tv_nsec);
86+
} else {
87+
EXPECT_LT(a.tv_sec, b.tv_sec);
88+
}
89+
}
90+
#endif
91+
6092
#ifdef LIBC_VDSO_HAS_CLOCK_GETRES
6193
TEST(LlvmLibcOSUtilVDSOTest, ClockGetRes) {
6294
using FuncTy = int (*)(clockid_t, timespec *);
6395
auto func =
6496
reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::ClockGetRes));
97+
if (func == nullptr)
98+
return;
6599
timespec res{};
66100
EXPECT_EQ(func(CLOCK_MONOTONIC, &res), 0);
67101
EXPECT_TRUE(res.tv_sec > 0 || res.tv_nsec > 0);
68102
}
69103
#endif
70104

105+
#ifdef LIBC_VDSO_HAS_GETCPU
106+
TEST(LlvmLibcOSUtilVDSOTest, GetCpu) {
107+
// The kernel system call has a third argument, which should be passed as
108+
// nullptr.
109+
using FuncTy = int (*)(int *, int *, void *);
110+
auto func = reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::GetCpu));
111+
if (func == nullptr)
112+
return;
113+
int cpu = -1, node = -1;
114+
EXPECT_EQ(func(&cpu, &node, nullptr), 0);
115+
EXPECT_GE(cpu, 0);
116+
EXPECT_GE(node, 0);
117+
}
118+
#endif
119+
120+
// TODO: apply this change to __restore_rt in
121+
// libc/src/signal/linux/sigaction.cpp
122+
// Caution: user application typically should not play with the trampoline.
123+
// Let the libc handle it.
124+
[[gnu::noreturn]] static void __restore_rt() {
125+
#ifdef LIBC_VDSO_HAS_RT_SIGRETURN
126+
using FuncTy = void (*)();
127+
auto func =
128+
reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::RTSigReturn));
129+
if (func) {
130+
func();
131+
__builtin_trap();
132+
}
133+
#endif
134+
LIBC_NAMESPACE::syscall_impl<long>(SYS_rt_sigreturn);
135+
__builtin_trap();
136+
}
137+
138+
static bool flag = false;
139+
140+
static void sigprof_handler [[gnu::used]] (int) { flag = true; }
141+
142+
TEST(LlvmLibcOSUtilVDSOTest, RtSigReturn) {
143+
using namespace testing::ErrnoSetterMatcher;
144+
// must use struct since there is a function of the same name in the same
145+
// scope.
146+
struct sigaction sa{};
147+
struct sigaction old_sa{};
148+
sa.sa_handler = sigprof_handler;
149+
sa.sa_flags = SA_RESTORER;
150+
sa.sa_restorer = __restore_rt;
151+
ASSERT_THAT(LIBC_NAMESPACE::sigaction(SIGPROF, &sa, &old_sa), Succeeds());
152+
raise(SIGPROF);
153+
ASSERT_TRUE(flag);
154+
flag = false;
155+
ASSERT_THAT(LIBC_NAMESPACE::sigaction(SIGPROF, &old_sa, nullptr), Succeeds());
156+
}
157+
158+
#ifdef LIBC_VDSO_HAS_FLUSH_ICACHE
159+
TEST(LlvmLibcOSUtilVDSOTest, FlushICache) {
160+
using FuncTy = void (*)(void *, void *, unsigned long);
161+
auto func =
162+
reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::FlushICache));
163+
if (func == nullptr)
164+
return;
165+
char buf[512];
166+
// we just check that the flush will not panic the program.
167+
// the flags part only take 0/1 as up to kernel 6.10, which is used to
168+
// indicate whether the flush is local to the core or global.
169+
func(buf, buf + sizeof(buf), 0);
170+
func(buf, buf + sizeof(buf), 1);
171+
}
172+
#endif
173+
174+
// https://docs.kernel.org/6.5/riscv/hwprobe.html
175+
176+
#ifdef LIBC_VDSO_HAS_RISCV_HWPROBE
177+
TEST(LlvmLibcOSUtilVDSOTest, RiscvHwProbe) {
178+
using namespace testing::ErrnoSetterMatcher;
179+
struct riscv_hwprobe {
180+
int64_t key;
181+
uint64_t value;
182+
};
183+
using FuncTy =
184+
long (*)(riscv_hwprobe *, size_t, size_t, struct cpu_set_t *, unsigned);
185+
auto func =
186+
reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::RiscvHwProbe));
187+
if (func == nullptr)
188+
return;
189+
// If a key is unknown to the kernel, its key field will be cleared to -1, and
190+
// its value set to 0. We expect probes.value are all 0.
191+
// Usermode can supply NULL for cpus and 0 for cpu_count as a shortcut for all
192+
// online CPUs
193+
riscv_hwprobe probes[2] = {{-1, 1}, {-1, 1}};
194+
ASSERT_THAT(func(/*pairs=*/probes, /*count=*/2, /*cpusetsize=*/0,
195+
/*cpuset=*/nullptr,
196+
/*flags=*/0),
197+
Succeeds());
198+
for (auto &probe : probes) {
199+
EXPECT_EQ(probe.key, static_cast<decltype(probe.key)>(-1));
200+
EXPECT_EQ(probe.value, static_cast<decltype(probe.value)>(0));
201+
}
202+
}
203+
#endif
204+
71205
} // namespace LIBC_NAMESPACE

0 commit comments

Comments
 (0)