[libc] Cleanup RPC helpers and comments

Summary:
Mostly NFC, replaced some inconsistent comments and replaces `class`
with `typename` to be consistent. Also fix incomplete type detection I
forgot to merge in the RPC helper PR.
This commit is contained in:
Joseph Huber 2026-02-11 16:41:54 -06:00
parent 9f85fa2a52
commit 39f2ce3685
4 changed files with 60 additions and 44 deletions

View File

@ -36,7 +36,7 @@ to learn about the defaults for your platform and target.
- ``LIBC_ADD_NULL_CHECKS``: Add nullptr checks in the library's implementations to some functions for which passing nullptr is undefined behavior.
* **"math" options**
- ``LIBC_CONF_FREXP_INF_NAN_EXPONENT``: The value written back to the second parameter when calling frexp/frexpf/frexpl` with `+/-Inf`/`NaN` is unspecified. Configure an explicit exp value for Inf/NaN inputs.
- ``LIBC_CONF_MATH_OPTIMIZATIONS``: Configure optimizations for math functions. Values accepted are LIBC_MATH_SKIP_ACCURATE_PASS, LIBC_MATH_SMALL_TABLES, LIBC_MATH_NO_ERRNO, LIBC_MATH_NO_EXCEPT, and LIBC_MATH_FAST.
- ``LIBC_CONF_MATH_OPTIMIZATIONS``: Configure optimizations for math functions. Values accepted are LIBC_MATH_SKIP_ACCURATE_PASS, LIBC_MATH_SMALL_TABLES, LIBC_MATH_NO_ERRNO, LIBC_MATH_NO_EXCEPT, LIBC_MATH_FAST, and LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT.
- ``LIBC_CONF_MATH_USE_SYSTEM_FENV``: Use C standard fenv.h calls from the system libc instead our internal fenv implementations.
* **"printf" options**
- ``LIBC_CONF_PRINTF_DISABLE_FIXED_POINT``: Disable printing fixed point values in printf and friends.

View File

@ -138,8 +138,8 @@ template <bool Invert> struct Process {
return inverted_outbox;
}
// Given the current outbox and inbox values, wait until the inbox changes
// to indicate that this thread owns the buffer element.
/// Given the current outbox and inbox values, wait until the inbox changes
/// to indicate that this thread owns the buffer element.
RPC_ATTRS void wait_for_ownership(uint64_t lane_mask, uint32_t index,
uint32_t outbox, uint32_t in) {
while (buffer_unavailable(in, outbox)) {
@ -169,9 +169,10 @@ template <bool Invert> struct Process {
/// single lock on success, e.g. the result of rpc::get_lane_mask()
/// The lock is held when the n-th bit of the lock bitfield is set.
RPC_ATTRS bool try_lock(uint64_t lane_mask, uint32_t index) {
// On amdgpu, test and set to the nth lock bit and a sync_lane would suffice
// On volta, need to handle differences between the threads running and
// the threads that were detected in the previous call to get_lane_mask()
// On AMDGPU, test and set to the n-th lock bit and a sync_lane would
// suffice On NVIDIA with ITS we need to handle differences between the
// threads running and the threads that were detected in the previous call
// to get_lane_mask()
//
// All threads in lane_mask try to claim the lock. At most one can succeed.
// There may be threads active which are not in lane mask which must not

View File

@ -13,7 +13,7 @@ namespace rpc {
namespace {
// Forward declarations needed for the server, we assume these are present.
extern "C" void *malloc(uint64_t);
extern "C" void *malloc(__SIZE_TYPE__);
extern "C" void free(void *);
// Traits to convert between a tuple and binary representation of an argument
@ -57,8 +57,9 @@ struct tuple_bytes<rpc::tuple<Ts...>> : tuple_bytes<Ts...> {};
template <uint64_t Idx, typename Tuple>
RPC_ATTRS constexpr void prepare_arg(rpc::Client::Port &port, Tuple &t) {
using ArgTy = rpc::tuple_element_t<Idx, Tuple>;
if constexpr (rpc::is_pointer_v<ArgTy> &&
!rpc::is_void_v<rpc::remove_pointer_t<ArgTy>>) {
using ElemTy = rpc::remove_pointer_t<ArgTy>;
if constexpr (rpc::is_pointer_v<ArgTy> && rpc::is_complete_v<ElemTy> &&
!rpc::is_void_v<ElemTy>) {
// We assume all constant character arrays are C-strings.
uint64_t size{};
if constexpr (rpc::is_same_v<ArgTy, const char *>)
@ -77,8 +78,9 @@ RPC_ATTRS constexpr void prepare_arg(rpc::Client::Port &port, Tuple &t) {
template <uint32_t NUM_LANES, typename Tuple, uint64_t Idx>
RPC_ATTRS constexpr void prepare_arg(rpc::Server::Port &port) {
using ArgTy = rpc::tuple_element_t<Idx, Tuple>;
if constexpr (rpc::is_pointer_v<ArgTy> &&
!rpc::is_void_v<rpc::remove_pointer_t<ArgTy>>) {
using ElemTy = rpc::remove_pointer_t<ArgTy>;
if constexpr (rpc::is_pointer_v<ArgTy> && rpc::is_complete_v<ElemTy> &&
!rpc::is_void_v<ElemTy>) {
void *args[NUM_LANES]{};
uint64_t sizes[NUM_LANES]{};
port.recv_n(args, sizes, [](uint64_t size) {
@ -102,7 +104,7 @@ RPC_ATTRS constexpr void finish_arg(rpc::Client::Port &port, Tuple &t) {
using ArgTy = rpc::tuple_element_t<Idx, Tuple>;
using MemoryTy = rpc::remove_const_t<rpc::remove_pointer_t<ArgTy>> *;
if constexpr (rpc::is_pointer_v<ArgTy> && !rpc::is_const_v<ArgTy> &&
!rpc::is_void_v<rpc::remove_pointer_t<ArgTy>>) {
rpc::is_complete_v<MemoryTy> && !rpc::is_void_v<MemoryTy>) {
uint64_t size{};
void *buf{};
port.recv_n(&buf, &size, [&](uint64_t) {
@ -118,8 +120,9 @@ template <uint32_t NUM_LANES, uint64_t Idx, typename Tuple>
RPC_ATTRS constexpr void finish_arg(rpc::Server::Port &port,
Tuple (&t)[NUM_LANES]) {
using ArgTy = rpc::tuple_element_t<Idx, Tuple>;
using ElemTy = rpc::remove_pointer_t<ArgTy>;
if constexpr (rpc::is_pointer_v<ArgTy> && !rpc::is_const_v<ArgTy> &&
!rpc::is_void_v<rpc::remove_pointer_t<ArgTy>>) {
rpc::is_complete_v<ElemTy> && !rpc::is_void_v<ElemTy>) {
const void *buffer[NUM_LANES]{};
size_t sizes[NUM_LANES]{};
for (uint32_t id = 0; id < NUM_LANES; ++id) {
@ -131,8 +134,8 @@ RPC_ATTRS constexpr void finish_arg(rpc::Server::Port &port,
port.send_n(buffer, sizes);
}
if constexpr (rpc::is_pointer_v<ArgTy> &&
!rpc::is_void_v<rpc::remove_pointer_t<ArgTy>>) {
if constexpr (rpc::is_pointer_v<ArgTy> && rpc::is_complete_v<ElemTy> &&
!rpc::is_void_v<ElemTy>) {
for (uint32_t id = 0; id < NUM_LANES; ++id) {
if (port.get_lane_mask() & (uint64_t(1) << id))
free(const_cast<void *>(

View File

@ -38,32 +38,32 @@ template <typename T> struct type_identity {
using type = T;
};
template <class T, T v> struct type_constant {
template <typename T, T v> struct type_constant {
static inline constexpr T value = v;
};
/// Freestanding type trait helpers.
template <class T> struct remove_cv : type_identity<T> {};
template <class T> struct remove_cv<const T> : type_identity<T> {};
template <class T> using remove_cv_t = typename remove_cv<T>::type;
template <typename T> struct remove_cv : type_identity<T> {};
template <typename T> struct remove_cv<const T> : type_identity<T> {};
template <typename T> using remove_cv_t = typename remove_cv<T>::type;
template <class T> struct remove_pointer : type_identity<T> {};
template <class T> struct remove_pointer<T *> : type_identity<T> {};
template <class T> using remove_pointer_t = typename remove_pointer<T>::type;
template <typename T> struct remove_pointer : type_identity<T> {};
template <typename T> struct remove_pointer<T *> : type_identity<T> {};
template <typename T> using remove_pointer_t = typename remove_pointer<T>::type;
template <class T> struct remove_const : type_identity<T> {};
template <class T> struct remove_const<const T> : type_identity<T> {};
template <class T> using remove_const_t = typename remove_const<T>::type;
template <typename T> struct remove_const : type_identity<T> {};
template <typename T> struct remove_const<const T> : type_identity<T> {};
template <typename T> using remove_const_t = typename remove_const<T>::type;
template <class T> struct remove_reference : type_identity<T> {};
template <class T> struct remove_reference<T &> : type_identity<T> {};
template <class T> struct remove_reference<T &&> : type_identity<T> {};
template <class T>
template <typename T> struct remove_reference : type_identity<T> {};
template <typename T> struct remove_reference<T &> : type_identity<T> {};
template <typename T> struct remove_reference<T &&> : type_identity<T> {};
template <typename T>
using remove_reference_t = typename remove_reference<T>::type;
template <class T> struct is_const : type_constant<bool, false> {};
template <class T> struct is_const<const T> : type_constant<bool, true> {};
template <class T> RPC_ATTRS constexpr bool is_const_v = is_const<T>::value;
template <typename T> struct is_const : type_constant<bool, false> {};
template <typename T> struct is_const<const T> : type_constant<bool, true> {};
template <typename T> RPC_ATTRS constexpr bool is_const_v = is_const<T>::value;
template <typename T> struct is_pointer : type_constant<bool, false> {};
template <typename T> struct is_pointer<T *> : type_constant<bool, true> {};
@ -78,32 +78,42 @@ template <typename T> struct is_same<T, T> : type_constant<bool, true> {};
template <typename T, typename U>
RPC_ATTRS constexpr bool is_same_v = is_same<T, U>::value;
template <class T> struct is_void : type_constant<bool, false> {};
template <typename T> struct is_void : type_constant<bool, false> {};
template <> struct is_void<void> : type_constant<bool, true> {};
template <typename T> RPC_ATTRS constexpr bool is_void_v = is_void<T>::value;
template <class T>
template <typename...> using void_t = void;
template <typename T, typename = void>
struct is_complete : type_constant<bool, false> {};
template <typename T>
struct is_complete<T, void_t<decltype(sizeof(T))>> : type_constant<bool, true> {
};
template <typename T>
inline constexpr bool is_complete_v = is_complete<T>::value;
template <typename T>
struct is_trivially_copyable
: public type_constant<bool, __is_trivially_copyable(T)> {};
template <class T>
template <typename T>
RPC_ATTRS constexpr bool is_trivially_copyable_v =
is_trivially_copyable<T>::value;
template <class T, class... Args>
template <typename T, typename... Args>
struct is_trivially_constructible
: type_constant<bool, __is_trivially_constructible(T, Args...)> {};
template <class T, class... Args>
template <typename T, typename... Args>
RPC_ATTRS constexpr bool is_trivially_constructible_v =
is_trivially_constructible<T>::value;
template <bool B, class T, class F> struct conditional : type_identity<T> {};
template <class T, class F>
template <bool B, typename T, typename F>
struct conditional : type_identity<T> {};
template <typename T, typename F>
struct conditional<false, T, F> : type_identity<F> {};
template <bool B, class T, class F>
template <bool B, typename T, typename F>
using conditional_t = typename conditional<B, T, F>::type;
/// Freestanding implementation of std::move.
template <class T>
template <typename T>
RPC_ATTRS constexpr typename remove_reference<T>::type &&move(T &&t) {
return static_cast<typename remove_reference<T>::type &&>(t);
}
@ -153,7 +163,7 @@ constexpr inline in_place_t in_place{};
constexpr inline nullopt_t nullopt{};
/// Freestanding and minimal implementation of std::optional.
template <typename T> class optional {
template <typename T> struct optional {
template <typename U> struct OptionalStorage {
union {
char empty;
@ -437,11 +447,13 @@ template <typename R, typename... Args> struct function_traits<R (*)(Args...)> {
static constexpr uint64_t ARITY = sizeof...(Args);
};
template <class T, class U> RPC_ATTRS constexpr T max(const T &a, const U &b) {
template <typename T, typename U>
RPC_ATTRS constexpr T max(const T &a, const U &b) {
return (a < b) ? b : a;
}
template <class T, class U> RPC_ATTRS constexpr T min(const T &a, const U &b) {
template <typename T, typename U>
RPC_ATTRS constexpr T min(const T &a, const U &b) {
return (a < b) ? a : b;
}