[libc-commits] [libc] [libc] Skip the RPC doorbell interrupt when the mailbox is uninitialized (PR #214037)
Minseob Shin via libc-commits
libc-commits at lists.llvm.org
Tue Aug 4 11:53:36 PDT 2026
https://github.com/minseobshin11 updated https://github.com/llvm/llvm-project/pull/214037
>From 9e8a6a35589f84f8ecdea4763e48aaa72e580610 Mon Sep 17 00:00:00 2001
From: Minseob Shin <minseob.shin11 at gmail.com>
Date: Tue, 4 Aug 2026 13:39:03 -0500
Subject: [PATCH] [libc] Skip the RPC doorbell interrupt when the mailbox is
uninitialized
---
libc/shared/rpc.h | 15 +++--
libc/test/src/__support/RPC/CMakeLists.txt | 10 ++++
.../src/__support/RPC/rpc_doorbell_test.cpp | 57 +++++++++++++++++++
3 files changed, 77 insertions(+), 5 deletions(-)
create mode 100644 libc/test/src/__support/RPC/rpc_doorbell_test.cpp
diff --git a/libc/shared/rpc.h b/libc/shared/rpc.h
index 5bc518ab97af7..eb6051f329e4a 100644
--- a/libc/shared/rpc.h
+++ b/libc/shared/rpc.h
@@ -158,11 +158,16 @@ template <bool Invert> struct Process {
if (rpc::is_first_lane(lane_mask)) {
if (!__scoped_atomic_fetch_add(doorbell->value, 1UL, __ATOMIC_RELAXED,
__MEMORY_SCOPE_SYSTEM)) {
- __scoped_atomic_store_n(doorbell->mailbox,
- static_cast<uint64_t>(doorbell->event_id),
- __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
- __scoped_atomic_thread_fence(__ATOMIC_RELEASE, __MEMORY_SCOPE_SYSTEM);
- signal_interrupt(event_id);
+ // A doorbell that is not interrupt-backed has no mailbox. The counter
+ // incremented above already publishes the work, so skipping the
+ // interrupt is safe.
+ if (doorbell->mailbox) {
+ __scoped_atomic_store_n(doorbell->mailbox,
+ static_cast<uint64_t>(doorbell->event_id),
+ __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ __scoped_atomic_thread_fence(__ATOMIC_RELEASE, __MEMORY_SCOPE_SYSTEM);
+ signal_interrupt(event_id);
+ }
}
}
#endif
diff --git a/libc/test/src/__support/RPC/CMakeLists.txt b/libc/test/src/__support/RPC/CMakeLists.txt
index 8f79a49cec40c..11d09226077c8 100644
--- a/libc/test/src/__support/RPC/CMakeLists.txt
+++ b/libc/test/src/__support/RPC/CMakeLists.txt
@@ -9,3 +9,13 @@ add_libc_test(
DEPENDS
libc.src.__support.RPC.rpc
)
+
+add_libc_test(
+ rpc_doorbell_test
+ SUITE
+ libc-rpc-tests
+ SRCS
+ rpc_doorbell_test.cpp
+ DEPENDS
+ libc.src.__support.RPC.rpc
+)
diff --git a/libc/test/src/__support/RPC/rpc_doorbell_test.cpp b/libc/test/src/__support/RPC/rpc_doorbell_test.cpp
new file mode 100644
index 0000000000000..f836b29f6bcce
--- /dev/null
+++ b/libc/test/src/__support/RPC/rpc_doorbell_test.cpp
@@ -0,0 +1,57 @@
+//===-- tests for the RPC doorbell ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/RPC/rpc.h"
+
+#include "test/UnitTest/Test.h"
+
+namespace {
+enum { port_count = 4 };
+
+using ProcType = LIBC_NAMESPACE::rpc::Process<false>;
+
+enum { alloc_size = ProcType::allocation_size(port_count, 1) };
+
+alignas(64) char buffer[alloc_size] = {0};
+
+// At namespace scope so the doorbell never refers to a dead local.
+uint64_t pending = 0;
+} // namespace
+
+// A doorbell can be only partially initialized. The AMDGPU offload plugin sets
+// 'value' to the address of a field inside its HSA signal, so it is never null,
+// while 'mailbox' is that signal's event mailbox pointer, which is null unless
+// the signal is backed by an interrupt. Ringing such a doorbell must not
+// dereference the null mailbox, and must still publish the pending work so a
+// polling server makes progress.
+TEST(LlvmLibcRPCDoorbell, NotifyWithoutMailbox) {
+ ProcType Proc(port_count, buffer);
+
+ pending = 0;
+ Proc.doorbell->value = &pending;
+ Proc.doorbell->mailbox = nullptr;
+ Proc.doorbell->event_id = 0;
+
+ Proc.notify(/*lane_mask=*/1);
+
+ // notify() has no effect when built with MSVC.
+#ifndef _MSC_VER
+ EXPECT_EQ(pending, static_cast<uint64_t>(1));
+#endif
+}
+
+// A doorbell that was never configured at all is ignored entirely.
+TEST(LlvmLibcRPCDoorbell, NotifyWithoutDoorbell) {
+ ProcType Proc(port_count, buffer);
+
+ Proc.doorbell->value = nullptr;
+ Proc.doorbell->mailbox = nullptr;
+ Proc.doorbell->event_id = 0;
+
+ Proc.notify(/*lane_mask=*/1);
+}
More information about the libc-commits
mailing list