diff --git a/libc/include/llvm-libc-types/rpc_opcodes_t.h b/libc/include/llvm-libc-types/rpc_opcodes_t.h --- a/libc/include/llvm-libc-types/rpc_opcodes_t.h +++ b/libc/include/llvm-libc-types/rpc_opcodes_t.h @@ -22,4 +22,6 @@ RPC_TEST_STREAM = 9, } rpc_opcode_t; +const char *rpc_client_symbol_name = "__llvm_libc_rpc_client"; + #endif // __LLVM_LIBC_TYPES_RPC_OPCODE_H__ diff --git a/libc/src/__support/RPC/rpc.h b/libc/src/__support/RPC/rpc.h --- a/libc/src/__support/RPC/rpc.h +++ b/libc/src/__support/RPC/rpc.h @@ -343,6 +343,10 @@ private: Process> process; }; +static_assert(cpp::is_trivially_copyable::value && + sizeof(Process>) == + sizeof(Process>), + "The client is not trivially copyable from the server"); /// The RPC server used to respond to the client. template struct Server { diff --git a/libc/src/__support/RPC/rpc_client.cpp b/libc/src/__support/RPC/rpc_client.cpp --- a/libc/src/__support/RPC/rpc_client.cpp +++ b/libc/src/__support/RPC/rpc_client.cpp @@ -16,8 +16,10 @@ Client client; /// Externally visible symbol to signify the usage of an RPC client to -/// whomever needs to run the server. -extern "C" [[gnu::visibility("protected")]] const bool __llvm_libc_rpc = false; +/// whomever needs to run the server as well as provide a way to initialize +/// the client with a copy.. +extern "C" [[gnu::visibility("protected")]] void *__llvm_libc_rpc_client = + &client; } // namespace rpc } // namespace __llvm_libc diff --git a/libc/utils/gpu/server/rpc_server.h b/libc/utils/gpu/server/rpc_server.h --- a/libc/utils/gpu/server/rpc_server.h +++ b/libc/utils/gpu/server/rpc_server.h @@ -86,6 +86,13 @@ /// Obtain a pointer to the memory buffer used to run the RPC client and server. void *rpc_get_buffer(uint32_t device_id); +/// Obtain a pointer to a local client buffer that can be copied directly to the +/// other process. +const void *rpc_get_client_buffer(uint32_t device_id); + +/// Returns the size of the client in bytes to be used for a memory copy. +uint64_t rpc_get_client_size(); + /// Use the \p port to receive and send a buffer using the \p callback. void rpc_recv_and_send(rpc_port_t port, rpc_port_callback_ty callback, void *data); diff --git a/libc/utils/gpu/server/rpc_server.cpp b/libc/utils/gpu/server/rpc_server.cpp --- a/libc/utils/gpu/server/rpc_server.cpp +++ b/libc/utils/gpu/server/rpc_server.cpp @@ -36,6 +36,7 @@ void reset(uint64_t port_count, void *buffer) { std::visit([&](auto &server) { server->reset(port_count, buffer); }, server); + client.reset(port_count, buffer); } uint64_t allocation_size(uint64_t port_count) { @@ -51,6 +52,8 @@ return ret; } + const void *get_client_data() const { return &client; } + rpc_status_t handle_server( std::unordered_map &callbacks, std::unordered_map &callback_data) { @@ -173,6 +176,7 @@ std::unique_ptr>, std::unique_ptr>> server; + rpc::Client client; }; struct Device { @@ -312,6 +316,18 @@ return state->devices[device_id]->server.get_buffer_start(); } +const void *rpc_get_client_buffer(uint32_t device_id) { + if (!state) + return nullptr; + if (device_id >= state->num_devices) + return nullptr; + if (!state->devices[device_id]) + return nullptr; + return state->devices[device_id]->server.get_client_data(); +} + +uint64_t rpc_get_client_size() { return sizeof(rpc::Client); } + void rpc_recv_and_send(rpc_port_t ref, rpc_port_callback_ty callback, void *data) { if (ref.lane_size == 1) {