Skip to content

Commit 3e74c4e

Browse files
Yifan ZhuSchrodingerZhu
authored andcommitted
address CRs and improve inlining of fastpaths
1 parent 4152d5f commit 3e74c4e

File tree

9 files changed

+129
-185
lines changed

9 files changed

+129
-185
lines changed

libc/src/__support/OSUtil/linux/aarch64/vdso.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,6 @@
1010
#include "src/__support/CPP/string_view.h"
1111
namespace LIBC_NAMESPACE {
1212
namespace vdso {
13-
// macro definitions
14-
#define LIBC_VDSO_HAS_RT_SIGRETURN
15-
#define LIBC_VDSO_HAS_GETTIMEOFDAY
16-
#define LIBC_VDSO_HAS_CLOCK_GETTIME
17-
#define LIBC_VDSO_HAS_CLOCK_GETRES
18-
19-
// list of VDSO symbols
20-
// following the order in
21-
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/kernel/vdso/vdso.lds.S
22-
enum class VDSOSym {
23-
RTSigReturn,
24-
GetTimeOfDay,
25-
ClockGetTime,
26-
ClockGetRes,
27-
VDSOSymCount
28-
};
29-
3013
// translate VDSOSym to symbol names
3114
LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
3215
switch (sym) {

libc/src/__support/OSUtil/linux/arm/vdso.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,6 @@
1010
#include "src/__support/CPP/string_view.h"
1111
namespace LIBC_NAMESPACE {
1212
namespace vdso {
13-
// macro definitions
14-
// following the order in
15-
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/vdso/vdso.lds.S
16-
#define LIBC_VDSO_HAS_CLOCK_GETTIME
17-
#define LIBC_VDSO_HAS_GETTIMEOFDAY
18-
#define LIBC_VDSO_HAS_CLOCK_GETRES
19-
#define LIBC_VDSO_HAS_CLOCK_GETTIME64
20-
21-
// list of VDSO symbols
22-
enum class VDSOSym {
23-
ClockGetTime,
24-
GetTimeOfDay,
25-
ClockGetRes,
26-
ClockGetTime64,
27-
VDSOSymCount
28-
};
29-
3013
// translate VDSOSym to symbol names
3114
LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
3215
switch (sym) {

libc/src/__support/OSUtil/linux/riscv/vdso.h

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,6 @@
1010
#include "src/__support/CPP/string_view.h"
1111
namespace LIBC_NAMESPACE {
1212
namespace vdso {
13-
// macro definitions
14-
// following the order in
15-
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/kernel/vdso/vdso.lds.S
16-
#define LIBC_VDSO_HAS_RT_SIGRETURN
17-
#define LIBC_VDSO_HAS_GETTIMEOFDAY
18-
#define LIBC_VDSO_HAS_CLOCK_GETTIME
19-
#define LIBC_VDSO_HAS_CLOCK_GETRES
20-
#define LIBC_VDSO_HAS_GETCPU
21-
#define LIBC_VDSO_HAS_FLUSH_ICACHE
22-
#define LIBC_VDSO_HAS_RISCV_HWPROBE
23-
24-
// list of VDSO symbols
25-
enum class VDSOSym {
26-
RTSigReturn,
27-
GetTimeOfDay,
28-
ClockGetTime,
29-
ClockGetRes,
30-
GetCpu,
31-
FlushICache,
32-
RiscvHwProbe,
33-
VDSOSymCount
34-
};
35-
3613
// translate VDSOSym to symbol names
3714
LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
3815
switch (sym) {

libc/src/__support/OSUtil/linux/vdso.cpp

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,10 @@ unsigned long getauxval(unsigned long id);
3434

3535
namespace vdso {
3636

37-
namespace {
38-
39-
// This class is an internal helper for symbol <-> index conversion and
40-
// improve the readability of the code.
41-
// We keep this class internal on purpose to avoid users from implicitly
42-
// converting between size_t and VDSOSym.
43-
class Symbol {
44-
VDSOSym sym;
45-
46-
public:
47-
static constexpr size_t COUNT = static_cast<size_t>(VDSOSym::VDSOSymCount);
48-
constexpr Symbol(VDSOSym sym) : sym(sym) {}
49-
constexpr Symbol(size_t idx) : sym(static_cast<VDSOSym>(idx)) {}
50-
constexpr cpp::string_view name() const { return symbol_name(sym); }
51-
constexpr cpp::string_view version() const { return symbol_version(sym); }
52-
constexpr operator size_t() const { return static_cast<size_t>(sym); }
53-
};
37+
Symbol::VDSOArray Symbol::global_cache{};
38+
CallOnceFlag Symbol::once_flag = callonce_impl::NOT_CALLED;
5439

40+
namespace {
5541
// See https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/symverdefs.html
5642
struct Verdaux {
5743
ElfW(Word) vda_name; /* Version or dependency names */
@@ -101,10 +87,6 @@ cpp::string_view find_version(Verdef *verdef, ElfW(Half) * versym,
10187
return "";
10288
}
10389

104-
using VDSOArray = cpp::array<void *, Symbol::COUNT>;
105-
106-
VDSOArray symbol_table;
107-
10890
size_t shdr_get_symbol_count(ElfW(Shdr) * vdso_shdr, size_t e_shnum) {
10991
// iterate all sections until we locate the dynamic symbol section
11092
for (size_t i = 0; i < e_shnum; ++i) {
@@ -123,11 +105,14 @@ struct VDSOSymbolTable {
123105
ElfW(Half) * versym;
124106
Verdef *verdef;
125107

126-
void populate_symbol_cache(size_t symbol_count, ElfW(Addr) vdso_addr) {
108+
void populate_symbol_cache(Symbol::VDSOArray &symbol_table,
109+
size_t symbol_count, ElfW(Addr) vdso_addr) {
127110
for (size_t i = 0, e = symbol_table.size(); i < e; ++i) {
128111
Symbol sym = i;
129112
cpp::string_view name = sym.name();
130113
cpp::string_view version = sym.version();
114+
if (name.empty())
115+
return;
131116
for (size_t j = 0; j < symbol_count; ++j) {
132117
if (name == strtab + symtab[j].st_name) {
133118
// we find a symbol with desired name
@@ -200,10 +185,11 @@ struct PhdrInfo {
200185
return VDSOSymbolTable{strtab, symtab, versym, verdef};
201186
}
202187
};
188+
} // namespace
203189

204-
void initialize_vdso_global_cache() {
190+
void Symbol::initialize_vdso_global_cache() {
205191
// first clear the symbol table
206-
for (auto &i : symbol_table)
192+
for (auto &i : global_cache)
207193
i = nullptr;
208194

209195
// get the address of the VDSO, protect errno since getauxval may change
@@ -249,20 +235,8 @@ void initialize_vdso_global_cache() {
249235
return;
250236

251237
// finally, populate the global symbol table cache
252-
vdso_symbol_table->populate_symbol_cache(symbol_count, phdr_info->vdso_addr);
253-
}
254-
} // namespace
255-
256-
void *get_symbol(VDSOSym sym) {
257-
// if sym is invalid, return nullptr
258-
Symbol symbol(sym);
259-
if (symbol >= symbol_table.size())
260-
return nullptr;
261-
262-
static FutexWordType once_flag = 0;
263-
callonce(reinterpret_cast<CallOnceFlag *>(&once_flag),
264-
initialize_vdso_global_cache);
265-
return symbol_table[symbol];
238+
vdso_symbol_table->populate_symbol_cache(global_cache, symbol_count,
239+
phdr_info->vdso_addr);
266240
}
267241
} // namespace vdso
268242
} // namespace LIBC_NAMESPACE

libc/src/__support/OSUtil/linux/vdso.h

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,28 @@
77
//===----------------------------------------------------------------------===//
88
#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_VDSO_H
99
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_VDSO_H
10+
#include "src/__support/CPP/array.h"
1011
#include "src/__support/common.h"
12+
#include "src/__support/macros/attributes.h"
1113
#include "src/__support/macros/properties/architectures.h"
14+
#include "src/__support/threads/callonce.h"
15+
16+
namespace LIBC_NAMESPACE {
17+
namespace vdso {
18+
enum class VDSOSym {
19+
ClockGetTime,
20+
ClockGetTime64,
21+
GetTimeOfDay,
22+
GetCpu,
23+
Time,
24+
ClockGetRes,
25+
RTSigReturn,
26+
FlushICache,
27+
RiscvHwProbe,
28+
VDSOSymCount
29+
};
30+
} // namespace vdso
31+
} // namespace LIBC_NAMESPACE
1232

1333
#if defined(LIBC_TARGET_ARCH_IS_X86)
1434
#include "x86_64/vdso.h"
@@ -24,7 +44,44 @@
2444

2545
namespace LIBC_NAMESPACE {
2646
namespace vdso {
27-
void *get_symbol(VDSOSym);
47+
class Symbol {
48+
VDSOSym sym;
49+
50+
public:
51+
LIBC_INLINE_VAR static constexpr size_t COUNT =
52+
static_cast<size_t>(VDSOSym::VDSOSymCount);
53+
LIBC_INLINE constexpr explicit Symbol(VDSOSym sym) : sym(sym) {}
54+
LIBC_INLINE constexpr Symbol(size_t idx) : sym(static_cast<VDSOSym>(idx)) {}
55+
LIBC_INLINE constexpr cpp::string_view name() const {
56+
return symbol_name(sym);
57+
}
58+
LIBC_INLINE constexpr cpp::string_view version() const {
59+
return symbol_version(sym);
60+
}
61+
LIBC_INLINE constexpr operator size_t() const {
62+
return static_cast<size_t>(sym);
63+
}
64+
LIBC_INLINE constexpr bool is_valid() const {
65+
return *this < Symbol::global_cache.size();
66+
}
67+
using VDSOArray = cpp::array<void *, Symbol::COUNT>;
68+
69+
private:
70+
static CallOnceFlag once_flag;
71+
static VDSOArray global_cache;
72+
static void initialize_vdso_global_cache();
73+
friend void *get_symbol(VDSOSym sym);
74+
75+
public:
76+
template <typename T> LIBC_INLINE T get() {
77+
if (name().empty() || !is_valid())
78+
return nullptr;
79+
80+
callonce(&once_flag, Symbol::initialize_vdso_global_cache);
81+
return cpp::bit_cast<T>(global_cache[*this]);
82+
}
83+
};
84+
2885
} // namespace vdso
2986

3087
} // namespace LIBC_NAMESPACE

libc/src/__support/OSUtil/linux/x86_64/vdso.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,6 @@
1010
#include "src/__support/CPP/string_view.h"
1111
namespace LIBC_NAMESPACE {
1212
namespace vdso {
13-
// macro definitions
14-
// following the order in
15-
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/entry/vdso/vdso.lds.S
16-
#define LIBC_VDSO_HAS_CLOCK_GETTIME
17-
#define LIBC_VDSO_HAS_GETTIMEOFDAY
18-
#define LIBC_VDSO_HAS_GETCPU
19-
#define LIBC_VDSO_HAS_TIME
20-
#define LIBC_VDSO_HAS_CLOCK_GETRES
21-
22-
// list of VDSO symbols
23-
enum class VDSOSym {
24-
ClockGetTime,
25-
GetTimeOfDay,
26-
GetCpu,
27-
Time,
28-
ClockGetRes,
29-
VDSOSymCount
30-
};
31-
3213
// translate VDSOSym to symbol names
3314
// On x86, there are symbols defined without the __vdso_ prefix, however,
3415
// it is suggested that one should use the __vdso_ prefix.

libc/src/__support/threads/callonce.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,38 @@
99
#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_CALLONCE_H
1010
#define LLVM_LIBC_SRC___SUPPORT_THREADS_CALLONCE_H
1111

12+
#include "src/__support/macros/optimization.h"
13+
14+
#ifdef __linux__
15+
#include "src/__support/threads/linux/futex_utils.h"
16+
#else
17+
#error "callonce is not supported on this platform"
18+
#endif
19+
1220
namespace LIBC_NAMESPACE {
1321

14-
struct CallOnceFlag;
22+
#ifdef __linux__
23+
using CallOnceFlag = Futex;
24+
#endif
1525
using CallOnceCallback = void(void);
26+
namespace callonce_impl {
27+
static constexpr FutexWordType NOT_CALLED = 0x0;
28+
static constexpr FutexWordType START = 0x11;
29+
static constexpr FutexWordType WAITING = 0x22;
30+
static constexpr FutexWordType FINISH = 0x33;
31+
int callonce_slowpath(CallOnceFlag *flag, CallOnceCallback *callback);
32+
} // namespace callonce_impl
1633

17-
int callonce(CallOnceFlag *flag, CallOnceCallback *callback);
34+
LIBC_INLINE int callonce(CallOnceFlag *flag, CallOnceCallback *callback) {
35+
using namespace callonce_impl;
36+
// Avoid cmpxchg operation if the function has already been called.
37+
// The destination operand of cmpxchg may receive a write cycle without
38+
// regard to the result of the comparison
39+
if (LIBC_LIKELY(flag->load(cpp::MemoryOrder::RELAXED) == FINISH))
40+
return 0;
1841

42+
return callonce_slowpath(flag, callback);
43+
}
1944
} // namespace LIBC_NAMESPACE
2045

2146
#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_CALLONCE_H

libc/src/__support/threads/linux/callonce.cpp

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,15 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/__support/threads/callonce.h"
10-
#include "src/__support/macros/optimization.h"
1110
#include "src/__support/threads/linux/futex_utils.h"
1211

1312
namespace LIBC_NAMESPACE {
14-
15-
static constexpr FutexWordType NOT_CALLED = 0x0;
16-
static constexpr FutexWordType START = 0x11;
17-
static constexpr FutexWordType WAITING = 0x22;
18-
static constexpr FutexWordType FINISH = 0x33;
19-
20-
int callonce(CallOnceFlag *flag, CallOnceCallback *func) {
13+
namespace callonce_impl {
14+
int callonce_slowpath(CallOnceFlag *flag, CallOnceCallback *func) {
2115
auto *futex_word = reinterpret_cast<Futex *>(flag);
2216

2317
FutexWordType not_called = NOT_CALLED;
2418

25-
// Avoid cmpxchg operation if the function has already been called.
26-
// The destination operand of cmpxchg may receive a write cycle without
27-
// regard to the result of the comparison
28-
if (LIBC_LIKELY(futex_word->load(cpp::MemoryOrder::RELAXED) == FINISH))
29-
return 0;
30-
3119
// The call_once call can return only after the called function |func|
3220
// returns. So, we use futexes to synchronize calls with the same flag value.
3321
if (futex_word->compare_exchange_strong(not_called, START)) {
@@ -46,5 +34,5 @@ int callonce(CallOnceFlag *flag, CallOnceCallback *func) {
4634

4735
return 0;
4836
}
49-
37+
} // namespace callonce_impl
5038
} // namespace LIBC_NAMESPACE

0 commit comments

Comments
 (0)