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 @@ -20,6 +20,10 @@ /// The maxium number of ports that can be opened for any server. const uint64_t RPC_MAXIMUM_PORT_COUNT = 64; +/// The symbol name associated with the client for use with the LLVM C library +/// implementation. +static const char *rpc_client_symbol_name = "__llvm_libc_rpc_client"; + /// status codes. typedef enum { RPC_STATUS_SUCCESS = 0x0, @@ -86,6 +90,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 @@ -179,6 +179,7 @@ template Device(std::unique_ptr &&server) : server(std::move(server)) {} Server server; + rpc::Client client; std::unordered_map callbacks; std::unordered_map callback_data; }; @@ -250,6 +251,7 @@ return RPC_STATUS_ERROR; state->devices[device_id]->server.reset(num_ports, buffer); + state->devices[device_id]->client.reset(num_ports, buffer); return RPC_STATUS_SUCCESS; } @@ -303,15 +305,19 @@ } void *rpc_get_buffer(uint32_t device_id) { - if (!state) - return nullptr; - if (device_id >= state->num_devices) - return nullptr; - if (!state->devices[device_id]) + if (!state || device_id >= state->num_devices || !state->devices[device_id]) return nullptr; return state->devices[device_id]->server.get_buffer_start(); } +const void *rpc_get_client_buffer(uint32_t device_id) { + if (!state || device_id >= state->num_devices || !state->devices[device_id]) + return nullptr; + return &state->devices[device_id]->client; +} + +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) {