Skip to content

Commit 8437b7f

Browse files
authored
[libc] Make RPC server handling header only (#131205)
Summary: This patch moves the RPC server handling to be a header only utility stored in the `shared/` directory. This is intended to be shared within LLVM for the loaders and `offload/` handling. Generally, this makes it easier to share code without weird cross-project binaries being plucked out of the build system. It also allows us to soon move the loader interface out of the `libc` project so that we don't need to bootstrap those and can build them in LLVM.
1 parent 214d47a commit 8437b7f

File tree

13 files changed

+110
-113
lines changed

13 files changed

+110
-113
lines changed

Diff for: libc/docs/gpu/rpc.rst

+8-5
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ but the following example shows how it can be used by a standard user.
184184
185185
#include <shared/rpc.h>
186186
#include <shared/rpc_opcodes.h>
187+
#include <shared/rpc_server.h>
187188
188189
[[noreturn]] void handle_error(cudaError_t err) {
189190
fprintf(stderr, "CUDA error: %s\n", cudaGetErrorString(err));
@@ -230,10 +231,10 @@ but the following example shows how it can be used by a standard user.
230231
// Requires non-blocking CUDA kernels but avoids a separate thread.
231232
do {
232233
auto port = server.try_open(warp_size, /*index=*/0);
233-
// From libllvmlibc_rpc_server.a in the installation.
234234
if (!port)
235235
continue;
236236
237+
// Only available in-tree from the 'libc' sources.
237238
handle_libc_opcodes(*port, warp_size);
238239
port->close();
239240
} while (cudaStreamQuery(stream) == cudaErrorNotReady);
@@ -242,14 +243,16 @@ but the following example shows how it can be used by a standard user.
242243
The above code must be compiled in CUDA's relocatable device code mode and with
243244
the advanced offloading driver to link in the library. Currently this can be
244245
done with the following invocation. Using LTO avoids the overhead normally
245-
associated with relocatable device code linking. The C library for GPUs is
246-
linked in by forwarding the static library to the device-side link job.
246+
associated with relocatable device code linking. The C library for GPU's
247+
handling is included through the ``shared/`` directory. This is not currently
248+
installed as it does not use a stable interface.
249+
247250

248251
.. code-block:: sh
249252
250253
$> clang++ -x cuda rpc.cpp --offload-arch=native -fgpu-rdc -lcudart \
251-
-I<install-path>include -L<install-path>/lib -lllvmlibc_rpc_server \
252-
-Xoffload-linker -lc -O3 -foffload-lto -o hello
254+
-I<install-path>include -L<install-path>/lib -Xoffload-linker -lc \
255+
-O3 -foffload-lto -o hello
253256
$> ./hello
254257
Hello world!
255258

Diff for: libc/shared/rpc_opcodes.h

-6
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,4 @@ typedef enum {
5050

5151
#undef LLVM_LIBC_OPCODE
5252

53-
namespace rpc {
54-
// The implementation of this function currently lives in the utility directory
55-
// at 'utils/gpu/server/rpc_server.cpp'.
56-
rpc::Status handle_libc_opcodes(rpc::Server::Port &port, uint32_t num_lanes);
57-
} // namespace rpc
58-
5953
#endif // LLVM_LIBC_SHARED_RPC_OPCODES_H

Diff for: libc/shared/rpc_server.h

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===-- Shared RPC server interface -----------------------------*- C++ -*-===//
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+
9+
#ifndef LLVM_LIBC_SHARED_RPC_SERVER_H
10+
#define LLVM_LIBC_SHARED_RPC_SERVER_H
11+
12+
#include "src/__support/RPC/rpc_server.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
namespace shared {
16+
17+
using LIBC_NAMESPACE::rpc::handle_libc_opcodes;
18+
19+
} // namespace shared
20+
} // namespace LIBC_NAMESPACE_DECL
21+
22+
#endif // LLVM_LIBC_SHARED_RPC_SERVER_H

Diff for: libc/utils/gpu/server/rpc_server.cpp renamed to libc/src/__support/RPC/rpc_server.h

+69-41
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,45 @@
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
8+
//
9+
// This file is intended to be used externally as part of the `shared/`
10+
// interface. For that purpose, we manually define a few options normally
11+
// handled by the libc build system.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_LIBC_SRC___SUPPORT_RPC_RPC_SERVER_H
16+
#define LLVM_LIBC_SRC___SUPPORT_RPC_RPC_SERVER_H
817

918
// Workaround for missing __has_builtin in < GCC 10.
1019
#ifndef __has_builtin
1120
#define __has_builtin(x) 0
1221
#endif
1322

23+
// Configs for using the LLVM libc writer interface.
24+
#define LIBC_COPT_USE_C_ASSERT
25+
#define LIBC_COPT_MEMCPY_USE_EMBEDDED_TINY
26+
#define LIBC_COPT_ARRAY_ARG_LIST
27+
#define LIBC_COPT_PRINTF_DISABLE_WRITE_INT
28+
#define LIBC_COPT_PRINTF_DISABLE_INDEX_MODE
29+
#define LIBC_COPT_PRINTF_DISABLE_STRERROR
30+
31+
// The 'long double' type is 8 byte
32+
#define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64
33+
1434
#include "shared/rpc.h"
1535
#include "shared/rpc_opcodes.h"
1636

17-
#include "src/__support/CPP/type_traits.h"
1837
#include "src/__support/arg_list.h"
1938
#include "src/stdio/printf_core/converter.h"
2039
#include "src/stdio/printf_core/parser.h"
2140
#include "src/stdio/printf_core/writer.h"
2241

23-
#include <stdio.h>
24-
#include <stdlib.h>
42+
#include "hdr/stdio_overlay.h"
43+
#include "hdr/stdlib_overlay.h"
2544

26-
namespace LIBC_NAMESPACE {
45+
namespace LIBC_NAMESPACE_DECL {
46+
namespace internal {
2747

2848
// Minimal replacement for 'std::vector' that works for trivial types.
2949
template <typename T> class TempVector {
@@ -35,68 +55,66 @@ template <typename T> class TempVector {
3555
size_t capacity;
3656

3757
public:
38-
TempVector() : data(nullptr), current(0), capacity(0) {}
58+
LIBC_INLINE TempVector() : data(nullptr), current(0), capacity(0) {}
3959

40-
~TempVector() { free(data); }
60+
LIBC_INLINE ~TempVector() { free(data); }
4161

42-
void push_back(const T &value) {
62+
LIBC_INLINE void push_back(const T &value) {
4363
if (current == capacity)
4464
grow();
4565
data[current] = T(value);
4666
++current;
4767
}
4868

49-
void push_back(T &&value) {
69+
LIBC_INLINE void push_back(T &&value) {
5070
if (current == capacity)
5171
grow();
5272
data[current] = T(static_cast<T &&>(value));
5373
++current;
5474
}
5575

56-
void pop_back() { --current; }
76+
LIBC_INLINE void pop_back() { --current; }
5777

58-
bool empty() { return current == 0; }
78+
LIBC_INLINE bool empty() { return current == 0; }
5979

60-
size_t size() { return current; }
80+
LIBC_INLINE size_t size() { return current; }
6181

62-
T &operator[](size_t index) { return data[index]; }
82+
LIBC_INLINE T &operator[](size_t index) { return data[index]; }
6383

64-
T &back() { return data[current - 1]; }
84+
LIBC_INLINE T &back() { return data[current - 1]; }
6585

6686
private:
67-
void grow() {
87+
LIBC_INLINE void grow() {
6888
size_t new_capacity = capacity ? capacity * 2 : 1;
6989
void *new_data = realloc(data, new_capacity * sizeof(T));
70-
if (!new_data)
71-
abort();
7290
data = static_cast<T *>(new_data);
7391
capacity = new_capacity;
7492
}
7593
};
7694

7795
struct TempStorage {
78-
char *alloc(size_t size) {
96+
LIBC_INLINE char *alloc(size_t size) {
7997
storage.push_back(reinterpret_cast<char *>(malloc(size)));
8098
return storage.back();
8199
}
82100

83-
~TempStorage() {
101+
LIBC_INLINE ~TempStorage() {
84102
for (size_t i = 0; i < storage.size(); ++i)
85103
free(storage[i]);
86104
}
87105

88106
TempVector<char *> storage;
89107
};
90108

91-
enum Stream {
92-
File = 0,
93-
Stdin = 1,
94-
Stdout = 2,
95-
Stderr = 3,
96-
};
97-
98109
// Get the associated stream out of an encoded number.
99-
LIBC_INLINE ::FILE *to_stream(uintptr_t f) {
110+
LIBC_INLINE static ::FILE *to_stream(uintptr_t f) {
111+
enum Stream {
112+
File = 0,
113+
Stdin = 1,
114+
Stdout = 2,
115+
Stderr = 3,
116+
};
117+
100118
::FILE *stream = reinterpret_cast<FILE *>(f & ~0x3ull);
101119
Stream type = static_cast<Stream>(f & 0x3ull);
102120
if (type == Stdin)
@@ -109,7 +127,8 @@ LIBC_INLINE ::FILE *to_stream(uintptr_t f) {
109127
}
110128

111129
template <bool packed, uint32_t num_lanes>
112-
static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
130+
LIBC_INLINE static void handle_printf(rpc::Server::Port &port,
131+
TempStorage &temp_storage) {
113132
FILE *files[num_lanes] = {nullptr};
114133
// Get the appropriate output stream to use.
115134
if (port.get_opcode() == LIBC_PRINTF_TO_STREAM ||
@@ -268,7 +287,8 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
268287
}
269288
}
270289

271-
results[lane] = fwrite(buffer, 1, writer.get_chars_written(), files[lane]);
290+
results[lane] = static_cast<int>(
291+
fwrite(buffer, 1, writer.get_chars_written(), files[lane]));
272292
if (results[lane] != writer.get_chars_written() || ret == -1)
273293
results[lane] = -1;
274294
}
@@ -282,7 +302,7 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
282302
}
283303

284304
template <uint32_t num_lanes>
285-
rpc::Status handle_port_impl(rpc::Server::Port &port) {
305+
LIBC_INLINE static rpc::Status handle_port_impl(rpc::Server::Port &port) {
286306
TempStorage temp_storage;
287307

288308
switch (port.get_opcode()) {
@@ -333,8 +353,9 @@ rpc::Status handle_port_impl(rpc::Server::Port &port) {
333353
void *data[num_lanes] = {nullptr};
334354
port.recv([&](rpc::Buffer *buffer, uint32_t id) {
335355
data[id] = temp_storage.alloc(buffer->data[0]);
336-
const char *str = fgets(reinterpret_cast<char *>(data[id]),
337-
buffer->data[0], to_stream(buffer->data[1]));
356+
const char *str = ::fgets(reinterpret_cast<char *>(data[id]),
357+
static_cast<int>(buffer->data[0]),
358+
to_stream(buffer->data[1]));
338359
sizes[id] = !str ? 0 : __builtin_strlen(str) + 1;
339360
});
340361
port.send_n(data, sizes);
@@ -353,9 +374,9 @@ rpc::Status handle_port_impl(rpc::Server::Port &port) {
353374
break;
354375
}
355376
case LIBC_CLOSE_FILE: {
356-
port.recv_and_send([&](rpc::Buffer *buffer, uint32_t id) {
377+
port.recv_and_send([&](rpc::Buffer *buffer, uint32_t) {
357378
FILE *file = reinterpret_cast<FILE *>(buffer->data[0]);
358-
buffer->data[0] = fclose(file);
379+
buffer->data[0] = ::fclose(file);
359380
});
360381
break;
361382
}
@@ -498,21 +519,28 @@ rpc::Status handle_port_impl(rpc::Server::Port &port) {
498519
return rpc::RPC_SUCCESS;
499520
}
500521

501-
} // namespace LIBC_NAMESPACE
522+
} // namespace internal
523+
} // namespace LIBC_NAMESPACE_DECL
502524

525+
namespace LIBC_NAMESPACE_DECL {
503526
namespace rpc {
504-
// The implementation of this function currently lives in the utility directory
505-
// at 'utils/gpu/server/rpc_server.cpp'.
506-
rpc::Status handle_libc_opcodes(rpc::Server::Port &port, uint32_t num_lanes) {
527+
528+
// Handles any opcode generated from the 'libc' client code.
529+
LIBC_INLINE ::rpc::Status handle_libc_opcodes(::rpc::Server::Port &port,
530+
uint32_t num_lanes) {
507531
switch (num_lanes) {
508532
case 1:
509-
return LIBC_NAMESPACE::handle_port_impl<1>(port);
533+
return internal::handle_port_impl<1>(port);
510534
case 32:
511-
return LIBC_NAMESPACE::handle_port_impl<32>(port);
535+
return internal::handle_port_impl<32>(port);
512536
case 64:
513-
return LIBC_NAMESPACE::handle_port_impl<64>(port);
537+
return internal::handle_port_impl<64>(port);
514538
default:
515-
return rpc::RPC_ERROR;
539+
return ::rpc::RPC_ERROR;
516540
}
517541
}
542+
518543
} // namespace rpc
544+
} // namespace LIBC_NAMESPACE_DECL
545+
546+
#endif // LLVM_LIBC_SRC___SUPPORT_RPC_RPC_SERVER_H

Diff for: libc/utils/gpu/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
add_subdirectory(server)
21
add_subdirectory(loader)

Diff for: libc/utils/gpu/loader/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
add_library(gpu_loader OBJECT Main.cpp)
22

3+
include(FindLibcCommonUtils)
4+
target_link_libraries(gpu_loader PUBLIC llvm-libc-common-utilities)
5+
36
target_include_directories(gpu_loader PUBLIC
47
${CMAKE_CURRENT_SOURCE_DIR}
58
${LIBC_SOURCE_DIR}/include

Diff for: libc/utils/gpu/loader/Loader.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "shared/rpc.h"
1515
#include "shared/rpc_opcodes.h"
16+
#include "shared/rpc_server.h"
1617

1718
#include <cstddef>
1819
#include <cstdint>
@@ -181,7 +182,7 @@ inline uint32_t handle_server(rpc::Server &server, uint32_t index,
181182
break;
182183
}
183184
default:
184-
status = handle_libc_opcodes(*port, num_lanes);
185+
status = LIBC_NAMESPACE::shared::handle_libc_opcodes(*port, num_lanes);
185186
break;
186187
}
187188

Diff for: libc/utils/gpu/loader/amdgpu/CMakeLists.txt

+1-7
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,4 @@ set(LLVM_LINK_COMPONENTS
77
)
88

99
add_llvm_executable(amdhsa-loader amdhsa-loader.cpp)
10-
11-
target_link_libraries(amdhsa-loader
12-
PRIVATE
13-
hsa-runtime64::hsa-runtime64
14-
gpu_loader
15-
llvmlibc_rpc_server
16-
)
10+
target_link_libraries(amdhsa-loader PRIVATE hsa-runtime64::hsa-runtime64 gpu_loader)

Diff for: libc/utils/gpu/loader/nvptx/CMakeLists.txt

+1-7
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,4 @@ set(LLVM_LINK_COMPONENTS
66
)
77

88
add_llvm_executable(nvptx-loader nvptx-loader.cpp)
9-
10-
target_link_libraries(nvptx-loader
11-
PRIVATE
12-
gpu_loader
13-
llvmlibc_rpc_server
14-
CUDA::cuda_driver
15-
)
9+
target_link_libraries(nvptx-loader PRIVATE gpu_loader CUDA::cuda_driver)

Diff for: libc/utils/gpu/server/CMakeLists.txt

-30
This file was deleted.

0 commit comments

Comments
 (0)