diff --git a/libc/src/__support/OSUtil/gpu/io.cpp b/libc/src/__support/OSUtil/gpu/io.cpp index 75ac83ac6909c..dcc3bf76ec068 100644 --- a/libc/src/__support/OSUtil/gpu/io.cpp +++ b/libc/src/__support/OSUtil/gpu/io.cpp @@ -16,14 +16,15 @@ namespace __llvm_libc { void write_to_stderr(const char *msg) { uint64_t length = internal::string_length(msg) + 1; uint64_t buffer_len = sizeof(rpc::Buffer) - sizeof(uint64_t); - for (uint64_t i = 0; i < length; i += buffer_len) + for (uint64_t i = 0; i < length; i += buffer_len) { rpc::client.run( [&](rpc::Buffer *buffer) { buffer->data[0] = rpc::Opcode::PRINT_TO_STDERR; inline_memcpy(reinterpret_cast(&buffer->data[1]), &msg[i], (length > buffer_len ? buffer_len : length)); }, - [](rpc::Buffer *) {}); + [](rpc::Buffer *) { /* void */ }); + } } } // namespace __llvm_libc diff --git a/libc/src/__support/OSUtil/gpu/quick_exit.cpp b/libc/src/__support/OSUtil/gpu/quick_exit.cpp index 9be709552dc5c..56f0427c8d81b 100644 --- a/libc/src/__support/OSUtil/gpu/quick_exit.cpp +++ b/libc/src/__support/OSUtil/gpu/quick_exit.cpp @@ -24,7 +24,7 @@ void quick_exit(int status) { buffer->data[0] = rpc::Opcode::EXIT; buffer->data[1] = status; }, - [](rpc::Buffer *) {}); + [](rpc::Buffer *) { /* void */ }); #if defined(LIBC_TARGET_ARCH_IS_NVPTX) asm("exit" ::: "memory"); diff --git a/libc/src/__support/RPC/rpc.h b/libc/src/__support/RPC/rpc.h index c3df09e3f5db2..d536de49bf5ff 100644 --- a/libc/src/__support/RPC/rpc.h +++ b/libc/src/__support/RPC/rpc.h @@ -5,6 +5,15 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +// +// This file implements a remote procedure call mechanism to communicate between +// heterogeneous devices that can share an address space atomically. We provide +// a client and a server to facilitate the remote call. The client makes request +// to the server using a shared communication channel. We use separate atomic +// signals to indicate which side, the client or the server is in ownership of +// the buffer. +// +//===----------------------------------------------------------------------===// #ifndef LLVM_LIBC_SRC_SUPPORT_RPC_RPC_H #define LLVM_LIBC_SRC_SUPPORT_RPC_RPC_H @@ -55,7 +64,7 @@ struct Client : public Process { /// The RPC server used to respond to the client. struct Server : public Process { - template bool run(W work, C clean); + template bool handle(W work, C clean); }; /// Run the RPC client protocol to communicate with the server. We perform the @@ -68,27 +77,27 @@ template void Client::run(F fill, U use) { bool in = inbox->load(cpp::MemoryOrder::RELAXED); bool out = outbox->load(cpp::MemoryOrder::RELAXED); atomic_thread_fence(cpp::MemoryOrder::ACQUIRE); - // Write to buffer then to the outbox. + // Apply the \p fill to the buffer and signal the server. if (!in & !out) { fill(buffer); atomic_thread_fence(cpp::MemoryOrder::RELEASE); outbox->store(1, cpp::MemoryOrder::RELEASE); out = 1; } - // Wait for the result from the server. + // Wait for the server to work on the buffer and respond. if (!in & out) { while (!in) in = inbox->load(cpp::MemoryOrder::RELAXED); atomic_thread_fence(cpp::MemoryOrder::ACQUIRE); } - // Read from the buffer and then write to outbox. + // Apply \p use to the buffer and signal the server. if (in & out) { use(buffer); atomic_thread_fence(cpp::MemoryOrder::RELEASE); outbox->store(0, cpp::MemoryOrder::RELEASE); out = 0; } - // Wait for server to complete the communication. + // Wait for the server to signal the end of the protocol. if (in & !out) { while (in) in = inbox->load(cpp::MemoryOrder::RELAXED); @@ -103,27 +112,27 @@ template void Client::run(F fill, U use) { /// - Apply \p work to the shared buffer and write 1 to the outbox. /// - Wait until the inbox is 0. /// - Apply \p clean to the shared buffer and write 0 to the outbox. -template bool Server::run(W work, C clean) { +template bool Server::handle(W work, C clean) { bool in = inbox->load(cpp::MemoryOrder::RELAXED); bool out = outbox->load(cpp::MemoryOrder::RELAXED); atomic_thread_fence(cpp::MemoryOrder::ACQUIRE); - // No work to do, exit. + // There is no work to do, exit early. if (!in & !out) return false; - // Do work then write to the outbox. + // Apply \p work to the buffer and signal the client. if (in & !out) { work(buffer); atomic_thread_fence(cpp::MemoryOrder::RELEASE); outbox->store(1, cpp::MemoryOrder::RELEASE); out = 1; } - // Wait for the client to read the result. + // Wait for the client to use the buffer and respond. if (in & out) { while (in) in = inbox->load(cpp::MemoryOrder::RELAXED); atomic_thread_fence(cpp::MemoryOrder::ACQUIRE); } - // Clean up the buffer and signal the client. + // Clean up the buffer and signal the end of the protocol. if (!in & out) { clean(buffer); atomic_thread_fence(cpp::MemoryOrder::RELEASE); diff --git a/libc/utils/gpu/loader/amdgpu/Loader.cpp b/libc/utils/gpu/loader/amdgpu/Loader.cpp index 3136dc2509790..0d631e98aae43 100644 --- a/libc/utils/gpu/loader/amdgpu/Loader.cpp +++ b/libc/utils/gpu/loader/amdgpu/Loader.cpp @@ -43,7 +43,7 @@ static __llvm_libc::rpc::Server server; /// Queries the RPC client at least once and performs server-side work if there /// are any active requests. void handle_server() { - while (server.run( + while (server.handle( [&](__llvm_libc::rpc::Buffer *buffer) { switch (static_cast<__llvm_libc::rpc::Opcode>(buffer->data[0])) { case __llvm_libc::rpc::Opcode::PRINT_TO_STDERR: {