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 @@ -348,7 +348,6 @@ LIBC_INLINE ~Client() = default; using Port = rpc::Port>; - template LIBC_INLINE cpp::optional try_open(); template LIBC_INLINE Port open(); LIBC_INLINE void reset(uint32_t port_count, void *buffer) { @@ -517,15 +516,19 @@ } } -/// Attempts to open a port to use as the client. The client can only open a -/// port if we find an index that is in a valid sending state. That is, there -/// are send operations pending that haven't been serviced on this port. Each -/// port instance uses an associated \p opcode to tell the server what to do. -template -[[clang::convergent]] LIBC_INLINE cpp::optional -Client::try_open() { - // Perform a naive linear scan for a port that can be opened to send data. - for (uint32_t index = 0; index < process.port_count; ++index) { +/// Continually attempts to open a port to use as the client. The client can +/// only open a port if we find an index that is in a valid sending state. That +/// is, there are send operations pending that haven't been serviced on this +/// port. Each port instance uses an associated \p opcode to tell the server +/// what to do. +template LIBC_INLINE Client::Port Client::open() { + // Repeatedly perform a naive linear scan for a port that can be opened to + // send data. + for (uint32_t index = 0;; ++index) { + // Start from the beginning if we run out of ports to check. + if (index >= process.port_count) + index = 0; + // Attempt to acquire the lock on this index. uint64_t lane_mask = gpu::get_lane_mask(); if (!process.try_lock(lane_mask, index)) @@ -548,15 +551,6 @@ gpu::sync_lane(lane_mask); return Port(process, lane_mask, index, out); } - return cpp::nullopt; -} - -template LIBC_INLINE Client::Port Client::open() { - for (;;) { - if (cpp::optional p = try_open()) - return cpp::move(p.value()); - sleep_briefly(); - } } /// Attempts to open a port to use as the server. The server can only open a