| //===------------- Linux VDSO Header ----------------------------*- 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___SUPPORT_OSUTIL_LINUX_VDSO_H |
| #define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_VDSO_H |
| #include "src/__support/CPP/array.h" |
| #include "src/__support/common.h" |
| #include "src/__support/macros/attributes.h" |
| #include "src/__support/macros/properties/architectures.h" |
| #include "src/__support/threads/callonce.h" |
| |
| #if defined(LIBC_TARGET_ARCH_IS_X86) |
| #include "x86_64/vdso.h" |
| #elif defined(LIBC_TARGET_ARCH_IS_AARCH64) |
| #include "aarch64/vdso.h" |
| #elif defined(LIBC_TARGET_ARCH_IS_ARM) |
| #include "arm/vdso.h" |
| #elif defined(LIBC_TARGET_ARCH_IS_ANY_RISCV) |
| #include "riscv/vdso.h" |
| #else |
| #error "unknown arch" |
| #endif |
| |
| namespace LIBC_NAMESPACE_DECL { |
| namespace vdso { |
| |
| class Symbol { |
| VDSOSym sym; |
| |
| public: |
| LIBC_INLINE_VAR static constexpr size_t COUNT = |
| static_cast<size_t>(VDSOSym::VDSOSymCount); |
| LIBC_INLINE constexpr explicit Symbol(VDSOSym sym) : sym(sym) {} |
| LIBC_INLINE constexpr Symbol(size_t idx) : sym(static_cast<VDSOSym>(idx)) {} |
| LIBC_INLINE constexpr cpp::string_view name() const { |
| return symbol_name(sym); |
| } |
| LIBC_INLINE constexpr cpp::string_view version() const { |
| return symbol_version(sym); |
| } |
| LIBC_INLINE constexpr operator size_t() const { |
| return static_cast<size_t>(sym); |
| } |
| LIBC_INLINE constexpr bool is_valid() const { |
| return *this < Symbol::global_cache.size(); |
| } |
| using VDSOArray = cpp::array<void *, Symbol::COUNT>; |
| |
| private: |
| static CallOnceFlag once_flag; |
| static VDSOArray global_cache; |
| static void initialize_vdso_global_cache(); |
| |
| LIBC_INLINE void *get() const { |
| if (name().empty() || !is_valid()) |
| return nullptr; |
| |
| callonce(&once_flag, Symbol::initialize_vdso_global_cache); |
| return (global_cache[*this]); |
| } |
| template <VDSOSym sym> friend struct TypedSymbol; |
| }; |
| |
| template <VDSOSym sym> struct TypedSymbol { |
| LIBC_INLINE constexpr operator VDSOSymType<sym>() const { |
| return cpp::bit_cast<VDSOSymType<sym>>(Symbol{sym}.get()); |
| } |
| template <typename... Args> |
| LIBC_INLINE auto operator()(Args &&...args) const { |
| return this->operator VDSOSymType<sym>()(cpp::forward<Args>(args)...); |
| } |
| }; |
| |
| } // namespace vdso |
| |
| } // namespace LIBC_NAMESPACE_DECL |
| #endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_VDSO_H |