[libc-commits] [libc] [libc] Export the RPC interface from `libc` (PR #71432)

Joseph Huber via libc-commits libc-commits at lists.llvm.org
Mon Nov 6 12:21:47 PST 2023


https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/71432

>From bf64ebcc65a1c20830fe029aa7f9a5f8f14939c8 Mon Sep 17 00:00:00 2001
From: Joseph Huber <jhuber6 at vols.utk.edu>
Date: Mon, 6 Nov 2023 13:08:42 -0600
Subject: [PATCH 1/2] [libc] Export the RPC interface from `libc`

Summary:
This patch adds new extensions that allow us to export the RPC interface
from `libc` to other programs. This should allow external users of the
GPU `libc` to interface with the RPC client (which more or less behaves
like syscalls in this context). This is done by wrapping the interface
into a C-style function call.

Obviously, this approach is far less safe than the carefully crafted C++
interface. For example, we now expose the internal packet buffer, and it
is theoretically possible to open a single port with conflicting opcodes
and break the whole interface. So, extra care will be needed when
interacting with this. However, the usage is very similar as shown by
the new test.

I was unsure whether or not to use function pointers to give a `send /
recv` interface that is more true to what the C++ version offers.
However, I elected to simply return the buffer (moving a wait for
ownership inside of this interface) as function pointers on the GPU can
be somewhat difficult to work with. The downside is now that the
interface can hang if it is not ordered correctly, i.e., calling
`rpc_get_buffer` before a `send` call and after a `recv` call. I am open
to changing this if others have opinions.

This somewhat stretches the concept of `libc` just doing `libc` things,
but I think this is important enough to justify it. It is difficult to
split this out, as we do not want to have the situation where we have
multiple RPC clients running at one time, so for now it makes sense to
just leave it in `libc`.
---
 libc/config/gpu/entrypoints.txt               |  5 +
 libc/include/CMakeLists.txt                   |  1 +
 libc/include/gpu/rpc.h.def                    |  3 +
 libc/include/llvm-libc-types/CMakeLists.txt   |  1 +
 libc/include/llvm-libc-types/rpc_port_t.h     | 20 ++++
 libc/spec/gpu_ext.td                          | 32 +++++-
 libc/src/__support/RPC/rpc.h                  | 18 +++-
 libc/src/gpu/CMakeLists.txt                   | 55 +++++++++++
 libc/src/gpu/rpc_close_port.cpp               | 25 +++++
 libc/src/gpu/rpc_close_port.h                 | 20 ++++
 libc/src/gpu/rpc_get_buffer.cpp               | 25 +++++
 libc/src/gpu/rpc_get_buffer.h                 | 20 ++++
 libc/src/gpu/rpc_open_port.cpp                | 26 +++++
 libc/src/gpu/rpc_open_port.h                  | 20 ++++
 libc/src/gpu/rpc_recv.cpp                     | 25 +++++
 libc/src/gpu/rpc_recv.h                       | 20 ++++
 libc/src/gpu/rpc_send.cpp                     | 25 +++++
 libc/src/gpu/rpc_send.h                       | 20 ++++
 .../integration/startup/gpu/CMakeLists.txt    | 13 +++
 .../gpu/rpc_external_interface_test.cpp       | 99 +++++++++++++++++++
 20 files changed, 469 insertions(+), 4 deletions(-)
 create mode 100644 libc/include/llvm-libc-types/rpc_port_t.h
 create mode 100644 libc/src/gpu/rpc_close_port.cpp
 create mode 100644 libc/src/gpu/rpc_close_port.h
 create mode 100644 libc/src/gpu/rpc_get_buffer.cpp
 create mode 100644 libc/src/gpu/rpc_get_buffer.h
 create mode 100644 libc/src/gpu/rpc_open_port.cpp
 create mode 100644 libc/src/gpu/rpc_open_port.h
 create mode 100644 libc/src/gpu/rpc_recv.cpp
 create mode 100644 libc/src/gpu/rpc_recv.h
 create mode 100644 libc/src/gpu/rpc_send.cpp
 create mode 100644 libc/src/gpu/rpc_send.h
 create mode 100644 libc/test/integration/startup/gpu/rpc_external_interface_test.cpp

diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt
index 5dda6aa71d36f81..47bcb36db49d55b 100644
--- a/libc/config/gpu/entrypoints.txt
+++ b/libc/config/gpu/entrypoints.txt
@@ -139,6 +139,11 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # gpu/rpc.h entrypoints
     libc.src.gpu.rpc_host_call
+    libc.src.gpu.rpc_open_port
+    libc.src.gpu.rpc_get_buffer
+    libc.src.gpu.rpc_send
+    libc.src.gpu.rpc_recv
+    libc.src.gpu.rpc_close_port
 )
 
 set(TARGET_LIBM_ENTRYPOINTS
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 9d170603ffa45cd..0f044ff84f28983 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -515,6 +515,7 @@ if(LIBC_TARGET_ARCHITECTURE_IS_GPU)
     DEPENDS
       .llvm_libc_common_h
       .llvm-libc-types.rpc_opcodes_t
+      .llvm-libc-types.rpc_port_t
   )
 endif()
 
diff --git a/libc/include/gpu/rpc.h.def b/libc/include/gpu/rpc.h.def
index 0438cd65e7be22e..f178007ee7083f5 100644
--- a/libc/include/gpu/rpc.h.def
+++ b/libc/include/gpu/rpc.h.def
@@ -11,7 +11,10 @@
 
 #include <__llvm-libc-common.h>
 
+#include <llvm-libc-types/size_t.h>
+
 #include <llvm-libc-types/rpc_opcodes_t.h>
+#include <llvm-libc-types/rpc_port_t.h>
 
 %%public_api()
 
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 3c0cc7bbc71dacb..8e0bf6a50c22bdd 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -91,3 +91,4 @@ add_header(wint_t HDR wint_t.h)
 add_header(sa_family_t HDR sa_family_t.h)
 add_header(struct_sockaddr HDR struct_sockaddr.h)
 add_header(rpc_opcodes_t HDR rpc_opcodes_t.h)
+add_header(rpc_port_t HDR rpc_port_t.h)
diff --git a/libc/include/llvm-libc-types/rpc_port_t.h b/libc/include/llvm-libc-types/rpc_port_t.h
new file mode 100644
index 000000000000000..bebb1bf32b09007
--- /dev/null
+++ b/libc/include/llvm-libc-types/rpc_port_t.h
@@ -0,0 +1,20 @@
+//===-- Definition of type rpc_port_t -------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_TYPES_RPC_PORT_T_H__
+#define __LLVM_LIBC_TYPES_RPC_PORT_T_H__
+
+typedef struct {
+  __UINT8_TYPE__ reserved[32];
+} rpc_port_t;
+
+typedef struct {
+  __UINT64_TYPE__ data[8];
+} rpc_buffer_t;
+
+#endif // __LLVM_LIBC_TYPES_RPC_PORT_T_H__
diff --git a/libc/spec/gpu_ext.td b/libc/spec/gpu_ext.td
index dce81ff7786203b..56094d4d50d3d16 100644
--- a/libc/spec/gpu_ext.td
+++ b/libc/spec/gpu_ext.td
@@ -1,8 +1,13 @@
+def RPCPortT : NamedType<"rpc_port_t">;
+def RPCPortPtrT : PtrType<RPCPortT>;
+def RPCBufferT : NamedType<"rpc_buffer_t">;
+def RPCBufferPtrT : PtrType<RPCBufferT>;
+
 def GPUExtensions : StandardSpec<"GPUExtensions"> {
   HeaderSpec RPC = HeaderSpec<
     "gpu/rpc.h",
     [], // Macros
-    [], // Types
+    [RPCPortT, RPCBufferT, SizeTType], // Types
     [], // Enumerations
     [
         FunctionSpec<
@@ -10,6 +15,31 @@ def GPUExtensions : StandardSpec<"GPUExtensions"> {
             RetValSpec<VoidType>,
             [ArgSpec<VoidPtr>, ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
         >,
+        FunctionSpec<
+            "rpc_open_port",
+            RetValSpec<RPCPortT>,
+            [ArgSpec<UnsignedIntType>]
+        >,
+        FunctionSpec<
+            "rpc_get_buffer",
+            RetValSpec<RPCBufferPtrT>,
+            [ArgSpec<RPCPortPtrT>]
+        >,
+        FunctionSpec<
+            "rpc_send",
+            RetValSpec<VoidType>,
+            [ArgSpec<RPCPortPtrT>]
+        >,
+        FunctionSpec<
+            "rpc_recv",
+            RetValSpec<VoidType>,
+            [ArgSpec<RPCPortPtrT>]
+        >,
+        FunctionSpec<
+            "rpc_close_port",
+            RetValSpec<VoidType>,
+            [ArgSpec<RPCPortPtrT>]
+        >,
     ]
   >;
   let Headers = [
diff --git a/libc/src/__support/RPC/rpc.h b/libc/src/__support/RPC/rpc.h
index 08c1dfd10d6d7f3..66c9fb297767780 100644
--- a/libc/src/__support/RPC/rpc.h
+++ b/libc/src/__support/RPC/rpc.h
@@ -319,6 +319,14 @@ template <bool T, typename S> struct Port {
 
   LIBC_INLINE uint16_t get_index() const { return index; }
 
+  /// Waits until this port owns the buffer and returns a pointer to it.
+  LIBC_INLINE Buffer *get_buffer() const {
+    uint32_t in = owns_buffer ? out ^ T : process.load_inbox(lane_mask, index);
+    process.wait_for_ownership(lane_mask, index, out, in);
+
+    return &process.packet[index].payload.slot[gpu::get_lane_id()];
+  }
+
   LIBC_INLINE void close() {
     // The server is passive, if it own the buffer when it closes we need to
     // give ownership back to the client.
@@ -347,7 +355,9 @@ struct Client {
       : process(port_count, buffer) {}
 
   using Port = rpc::Port<false, Packet<gpu::LANE_SIZE>>;
-  template <uint16_t opcode> LIBC_INLINE Port open();
+
+  template <uint16_t opcode> LIBC_INLINE Port open() { return open(opcode); }
+  LIBC_INLINE Port open(const uint16_t opcode);
 
 private:
   Process<false, Packet<gpu::LANE_SIZE>> process;
@@ -510,8 +520,10 @@ LIBC_INLINE void Port<T, S>::recv_n(void **dst, uint64_t *size, A &&alloc) {
 /// 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 <uint16_t opcode> LIBC_INLINE Client::Port Client::open() {
+/// what to do. It is very important that the \p opcode value is identical
+/// across each lane. Use the template version of this unless absolutely
+/// necessary.
+LIBC_INLINE Client::Port Client::open(const uint16_t opcode) {
   // Repeatedly perform a naive linear scan for a port that can be opened to
   // send data.
   for (uint32_t index = 0;; ++index) {
diff --git a/libc/src/gpu/CMakeLists.txt b/libc/src/gpu/CMakeLists.txt
index e20228516b5112d..822b7ba2f89fe62 100644
--- a/libc/src/gpu/CMakeLists.txt
+++ b/libc/src/gpu/CMakeLists.txt
@@ -8,3 +8,58 @@ add_entrypoint_object(
     libc.src.__support.RPC.rpc_client
     libc.src.__support.GPU.utils
 )
+
+add_entrypoint_object(
+  rpc_open_port
+  SRCS
+    rpc_open_port.cpp
+  HDRS
+    rpc_open_port.h
+  DEPENDS
+    libc.src.__support.RPC.rpc_client
+    libc.src.__support.GPU.utils
+)
+
+add_entrypoint_object(
+  rpc_close_port
+  SRCS
+    rpc_close_port.cpp
+  HDRS
+    rpc_close_port.h
+  DEPENDS
+    libc.src.__support.RPC.rpc_client
+    libc.src.__support.GPU.utils
+)
+
+add_entrypoint_object(
+  rpc_get_buffer
+  SRCS
+    rpc_get_buffer.cpp
+  HDRS
+    rpc_get_buffer.h
+  DEPENDS
+    libc.src.__support.RPC.rpc_client
+    libc.src.__support.GPU.utils
+)
+
+add_entrypoint_object(
+  rpc_send
+  SRCS
+    rpc_send.cpp
+  HDRS
+    rpc_send.h
+  DEPENDS
+    libc.src.__support.RPC.rpc_client
+    libc.src.__support.GPU.utils
+)
+
+add_entrypoint_object(
+  rpc_recv
+  SRCS
+    rpc_recv.cpp
+  HDRS
+    rpc_recv.h
+  DEPENDS
+    libc.src.__support.RPC.rpc_client
+    libc.src.__support.GPU.utils
+)
diff --git a/libc/src/gpu/rpc_close_port.cpp b/libc/src/gpu/rpc_close_port.cpp
new file mode 100644
index 000000000000000..f4d9f4b194a4b7b
--- /dev/null
+++ b/libc/src/gpu/rpc_close_port.cpp
@@ -0,0 +1,25 @@
+//===---------- GPU implementation of the external RPC port interface -----===//
+//
+// 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/gpu/rpc_close_port.h"
+
+#include "src/__support/GPU/utils.h"
+#include "src/__support/RPC/rpc_client.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+static_assert(sizeof(rpc_port_t) == sizeof(rpc::Client::Port), "ABI mismatch");
+static_assert(sizeof(rpc_buffer_t) == sizeof(rpc::Buffer), "ABI mismatch");
+
+LLVM_LIBC_FUNCTION(void, rpc_close_port, (rpc_port_t * handle)) {
+  rpc::Client::Port *port = reinterpret_cast<rpc::Client::Port *>(handle);
+  port->close();
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/gpu/rpc_close_port.h b/libc/src/gpu/rpc_close_port.h
new file mode 100644
index 000000000000000..2be39ce3698a384
--- /dev/null
+++ b/libc/src/gpu/rpc_close_port.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for RPC functions -----------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_GPU_RPC_CLOSE_PORT_H
+#define LLVM_LIBC_SRC_GPU_RPC_CLOSE_PORT_H
+
+#include <gpu/rpc.h>
+
+namespace LIBC_NAMESPACE {
+
+void rpc_close_port(rpc_port_t *handle);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_GPU_RPC_CLOSE_PORT_H
diff --git a/libc/src/gpu/rpc_get_buffer.cpp b/libc/src/gpu/rpc_get_buffer.cpp
new file mode 100644
index 000000000000000..10097b404c81c46
--- /dev/null
+++ b/libc/src/gpu/rpc_get_buffer.cpp
@@ -0,0 +1,25 @@
+//===---------- GPU implementation of the external RPC port interface -----===//
+//
+// 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/gpu/rpc_get_buffer.h"
+
+#include "src/__support/GPU/utils.h"
+#include "src/__support/RPC/rpc_client.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+static_assert(sizeof(rpc_port_t) == sizeof(rpc::Client::Port), "ABI mismatch");
+static_assert(sizeof(rpc_buffer_t) == sizeof(rpc::Buffer), "ABI mismatch");
+
+LLVM_LIBC_FUNCTION(rpc_buffer_t *, rpc_get_buffer, (rpc_port_t * handle)) {
+  rpc::Client::Port *port = reinterpret_cast<rpc::Client::Port *>(handle);
+  return reinterpret_cast<rpc_buffer_t *>(port->get_buffer());
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/gpu/rpc_get_buffer.h b/libc/src/gpu/rpc_get_buffer.h
new file mode 100644
index 000000000000000..5a07db1a5470085
--- /dev/null
+++ b/libc/src/gpu/rpc_get_buffer.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for RPC functions -----------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_GPU_RPC_GET_BUFFER_H
+#define LLVM_LIBC_SRC_GPU_RPC_GET_BUFFER_H
+
+#include <gpu/rpc.h>
+
+namespace LIBC_NAMESPACE {
+
+rpc_buffer_t *rpc_get_buffer(rpc_port_t *handle);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_GPU_RPC_GET_BUFFER_H
diff --git a/libc/src/gpu/rpc_open_port.cpp b/libc/src/gpu/rpc_open_port.cpp
new file mode 100644
index 000000000000000..73dab5066fa1bfb
--- /dev/null
+++ b/libc/src/gpu/rpc_open_port.cpp
@@ -0,0 +1,26 @@
+//===---------- GPU implementation of the external RPC port interface -----===//
+//
+// 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/gpu/rpc_open_port.h"
+
+#include "src/__support/CPP/bit.h"
+#include "src/__support/GPU/utils.h"
+#include "src/__support/RPC/rpc_client.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+static_assert(sizeof(rpc_port_t) == sizeof(rpc::Client::Port), "ABI mismatch");
+static_assert(sizeof(rpc_buffer_t) == sizeof(rpc::Buffer), "ABI mismatch");
+
+LLVM_LIBC_FUNCTION(rpc_port_t, rpc_open_port, (unsigned opcode)) {
+  rpc::Client::Port port = rpc::client.open(static_cast<uint16_t>(opcode));
+  return cpp::bit_cast<rpc_port_t>(port);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/gpu/rpc_open_port.h b/libc/src/gpu/rpc_open_port.h
new file mode 100644
index 000000000000000..553fa59120aaf68
--- /dev/null
+++ b/libc/src/gpu/rpc_open_port.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for RPC functions -----------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_GPU_RPC_OPEN_PORT_H
+#define LLVM_LIBC_SRC_GPU_RPC_OPEN_PORT_H
+
+#include <gpu/rpc.h>
+
+namespace LIBC_NAMESPACE {
+
+rpc_port_t rpc_open_port(unsigned opcode);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_GPU_RPC_OPEN_PORT_H
diff --git a/libc/src/gpu/rpc_recv.cpp b/libc/src/gpu/rpc_recv.cpp
new file mode 100644
index 000000000000000..96086dc2b17a345
--- /dev/null
+++ b/libc/src/gpu/rpc_recv.cpp
@@ -0,0 +1,25 @@
+//===---------- GPU implementation of the external RPC port interface -----===//
+//
+// 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/gpu/rpc_recv.h"
+
+#include "src/__support/GPU/utils.h"
+#include "src/__support/RPC/rpc_client.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+static_assert(sizeof(rpc_port_t) == sizeof(rpc::Client::Port), "ABI mismatch");
+static_assert(sizeof(rpc_buffer_t) == sizeof(rpc::Buffer), "ABI mismatch");
+
+LLVM_LIBC_FUNCTION(void, rpc_recv, (rpc_port_t * handle)) {
+  rpc::Client::Port *port = reinterpret_cast<rpc::Client::Port *>(handle);
+  port->recv([](rpc::Buffer *) { /* Filled by rpc_get_buffer() */ });
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/gpu/rpc_recv.h b/libc/src/gpu/rpc_recv.h
new file mode 100644
index 000000000000000..926565c3b0c16a0
--- /dev/null
+++ b/libc/src/gpu/rpc_recv.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for RPC functions -----------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_GPU_RPC_RECV_H
+#define LLVM_LIBC_SRC_GPU_RPC_RECV_H
+
+#include <gpu/rpc.h>
+
+namespace LIBC_NAMESPACE {
+
+void rpc_recv(rpc_port_t *handle);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_GPU_RPC_RECV_H
diff --git a/libc/src/gpu/rpc_send.cpp b/libc/src/gpu/rpc_send.cpp
new file mode 100644
index 000000000000000..4f4f5bcc2a5eb80
--- /dev/null
+++ b/libc/src/gpu/rpc_send.cpp
@@ -0,0 +1,25 @@
+//===---------- GPU implementation of the external RPC port interface -----===//
+//
+// 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/gpu/rpc_send.h"
+
+#include "src/__support/GPU/utils.h"
+#include "src/__support/RPC/rpc_client.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+static_assert(sizeof(rpc_port_t) == sizeof(rpc::Client::Port), "ABI mismatch");
+static_assert(sizeof(rpc_buffer_t) == sizeof(rpc::Buffer), "ABI mismatch");
+
+LLVM_LIBC_FUNCTION(void, rpc_send, (rpc_port_t * handle)) {
+  rpc::Client::Port *port = reinterpret_cast<rpc::Client::Port *>(handle);
+  port->send([](rpc::Buffer *) { /* Filled by rpc_get_buffer() */ });
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/gpu/rpc_send.h b/libc/src/gpu/rpc_send.h
new file mode 100644
index 000000000000000..e367514181f2ba8
--- /dev/null
+++ b/libc/src/gpu/rpc_send.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for RPC functions -----------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_GPU_RPC_SEND_H
+#define LLVM_LIBC_SRC_GPU_RPC_SEND_H
+
+#include <gpu/rpc.h>
+
+namespace LIBC_NAMESPACE {
+
+void rpc_send(rpc_port_t *handle);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_GPU_RPC_SEND_H
diff --git a/libc/test/integration/startup/gpu/CMakeLists.txt b/libc/test/integration/startup/gpu/CMakeLists.txt
index 7555986b16df452..18764ad2bcaf0b0 100644
--- a/libc/test/integration/startup/gpu/CMakeLists.txt
+++ b/libc/test/integration/startup/gpu/CMakeLists.txt
@@ -44,6 +44,19 @@ add_integration_test(
    rpc_interface_test.cpp
 )
 
+add_integration_test(
+  startup_rpc_external_interface_test
+  SUITE libc-startup-tests
+  SRCS
+    rpc_external_interface_test.cpp
+  DEPENDS
+    libc.src.gpu.rpc_open_port
+    libc.src.gpu.rpc_get_buffer
+    libc.src.gpu.rpc_send
+    libc.src.gpu.rpc_recv
+    libc.src.gpu.rpc_close_port
+)
+
 add_integration_test(
   startup_rpc_stream_test
   SUITE libc-startup-tests
diff --git a/libc/test/integration/startup/gpu/rpc_external_interface_test.cpp b/libc/test/integration/startup/gpu/rpc_external_interface_test.cpp
new file mode 100644
index 000000000000000..ae5221f58fc901d
--- /dev/null
+++ b/libc/test/integration/startup/gpu/rpc_external_interface_test.cpp
@@ -0,0 +1,99 @@
+//===-- Loader test to check the external RPC interface with the loader ---===//
+//
+// 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 <gpu/rpc.h>
+
+#include "src/gpu/rpc_close_port.h"
+#include "src/gpu/rpc_get_buffer.h"
+#include "src/gpu/rpc_open_port.h"
+#include "src/gpu/rpc_recv.h"
+#include "src/gpu/rpc_send.h"
+
+#include "include/llvm-libc-types/test_rpc_opcodes_t.h"
+#include "src/__support/GPU/utils.h"
+#include "src/__support/RPC/rpc_client.h"
+#include "test/IntegrationTest/test.h"
+
+using namespace LIBC_NAMESPACE;
+
+// Test to ensure that we can use aribtrary combinations of sends and recieves
+// as long as they are mirrored using the external interface.
+static void test_interface(bool end_with_send) {
+  uint64_t cnt = 0;
+  // rpc::Client::Port port = rpc::client.open<RPC_TEST_INTERFACE>();
+  rpc_port_t port = LIBC_NAMESPACE::rpc_open_port(RPC_TEST_INTERFACE);
+
+  // port.send([&](rpc::Buffer *buffer) { buffer->data[0] = end_with_send; });
+  rpc_buffer_t *buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
+  buffer->data[0] = end_with_send;
+  LIBC_NAMESPACE::rpc_send(&port);
+
+  // port.send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
+  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
+  buffer->data[0] = cnt = cnt + 1;
+  LIBC_NAMESPACE::rpc_send(&port);
+
+  // port.recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
+  LIBC_NAMESPACE::rpc_recv(&port);
+  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
+  cnt = buffer->data[0];
+
+  // port.send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
+  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
+  buffer->data[0] = cnt = cnt + 1;
+  LIBC_NAMESPACE::rpc_send(&port);
+
+  // port.recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
+  LIBC_NAMESPACE::rpc_recv(&port);
+  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
+  cnt = buffer->data[0];
+
+  // port.send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
+  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
+  buffer->data[0] = cnt = cnt + 1;
+  LIBC_NAMESPACE::rpc_send(&port);
+
+  // port.send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
+  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
+  buffer->data[0] = cnt = cnt + 1;
+  LIBC_NAMESPACE::rpc_send(&port);
+
+  // port.recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
+  LIBC_NAMESPACE::rpc_recv(&port);
+  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
+  cnt = buffer->data[0];
+
+  // port.recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
+  LIBC_NAMESPACE::rpc_recv(&port);
+  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
+  cnt = buffer->data[0];
+
+  if (end_with_send) {
+    // port.send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
+    buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
+    buffer->data[0] = cnt = cnt + 1;
+    LIBC_NAMESPACE::rpc_send(&port);
+  } else {
+    // port.recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
+    LIBC_NAMESPACE::rpc_recv(&port);
+    buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
+    cnt = buffer->data[0];
+  }
+
+  // port.close();
+  LIBC_NAMESPACE::rpc_close_port(&port);
+
+  ASSERT_TRUE(cnt == 9 && "Invalid number of increments");
+}
+
+TEST_MAIN(int argc, char **argv, char **envp) {
+  test_interface(true);
+  test_interface(false);
+
+  return 0;
+}

>From cc84b96affcdb42376a96ddcb0d391107327d219 Mon Sep 17 00:00:00 2001
From: Joseph Huber <jhuber6 at vols.utk.edu>
Date: Mon, 6 Nov 2023 14:17:01 -0600
Subject: [PATCH 2/2] [libc] Change the interface to use function pointers
 instead

Summary:
This patch changes the interface to use function pointers rather than
provide the buffer directly. This is more correct as it doesn't
introduce another failure mode, but it's a little cumbersome and may
impact performance comparatively if full inlining isn't possible.
However, the timing is going to be massively dominated by the time to
communicate with the other side.
---
 libc/config/gpu/entrypoints.txt               |   1 -
 libc/include/gpu/rpc.h.def                    |   2 +-
 libc/include/llvm-libc-types/CMakeLists.txt   |   2 +-
 .../{rpc_port_t.h => rpc_client_t.h}          |   3 +
 libc/spec/gpu_ext.td                          |  12 +--
 libc/src/__support/RPC/rpc.h                  |   8 --
 libc/src/gpu/rpc_get_buffer.cpp               |  25 -----
 libc/src/gpu/rpc_get_buffer.h                 |  20 ----
 libc/src/gpu/rpc_recv.cpp                     |   7 +-
 libc/src/gpu/rpc_recv.h                       |   2 +-
 libc/src/gpu/rpc_send.cpp                     |   7 +-
 libc/src/gpu/rpc_send.h                       |   2 +-
 .../integration/startup/gpu/CMakeLists.txt    |   1 -
 .../gpu/rpc_external_interface_test.cpp       | 101 ++++++++++++------
 14 files changed, 87 insertions(+), 106 deletions(-)
 rename libc/include/llvm-libc-types/{rpc_port_t.h => rpc_client_t.h} (84%)
 delete mode 100644 libc/src/gpu/rpc_get_buffer.cpp
 delete mode 100644 libc/src/gpu/rpc_get_buffer.h

diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt
index 47bcb36db49d55b..a3e268c15526818 100644
--- a/libc/config/gpu/entrypoints.txt
+++ b/libc/config/gpu/entrypoints.txt
@@ -140,7 +140,6 @@ set(TARGET_LIBC_ENTRYPOINTS
     # gpu/rpc.h entrypoints
     libc.src.gpu.rpc_host_call
     libc.src.gpu.rpc_open_port
-    libc.src.gpu.rpc_get_buffer
     libc.src.gpu.rpc_send
     libc.src.gpu.rpc_recv
     libc.src.gpu.rpc_close_port
diff --git a/libc/include/gpu/rpc.h.def b/libc/include/gpu/rpc.h.def
index f178007ee7083f5..9f427996e6c0277 100644
--- a/libc/include/gpu/rpc.h.def
+++ b/libc/include/gpu/rpc.h.def
@@ -14,7 +14,7 @@
 #include <llvm-libc-types/size_t.h>
 
 #include <llvm-libc-types/rpc_opcodes_t.h>
-#include <llvm-libc-types/rpc_port_t.h>
+#include <llvm-libc-types/rpc_client_t.h>
 
 %%public_api()
 
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 8e0bf6a50c22bdd..e76024e11e7a709 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -91,4 +91,4 @@ add_header(wint_t HDR wint_t.h)
 add_header(sa_family_t HDR sa_family_t.h)
 add_header(struct_sockaddr HDR struct_sockaddr.h)
 add_header(rpc_opcodes_t HDR rpc_opcodes_t.h)
-add_header(rpc_port_t HDR rpc_port_t.h)
+add_header(rpc_port_t HDR rpc_client_t.h)
diff --git a/libc/include/llvm-libc-types/rpc_port_t.h b/libc/include/llvm-libc-types/rpc_client_t.h
similarity index 84%
rename from libc/include/llvm-libc-types/rpc_port_t.h
rename to libc/include/llvm-libc-types/rpc_client_t.h
index bebb1bf32b09007..7f7306895f30751 100644
--- a/libc/include/llvm-libc-types/rpc_port_t.h
+++ b/libc/include/llvm-libc-types/rpc_client_t.h
@@ -17,4 +17,7 @@ typedef struct {
   __UINT64_TYPE__ data[8];
 } rpc_buffer_t;
 
+typedef void (*rpc_callback_t)(rpc_buffer_t *buffer, void *data,
+                               __UINT32_TYPE__ id);
+
 #endif // __LLVM_LIBC_TYPES_RPC_PORT_T_H__
diff --git a/libc/spec/gpu_ext.td b/libc/spec/gpu_ext.td
index 56094d4d50d3d16..051b488f9356a70 100644
--- a/libc/spec/gpu_ext.td
+++ b/libc/spec/gpu_ext.td
@@ -2,12 +2,13 @@ def RPCPortT : NamedType<"rpc_port_t">;
 def RPCPortPtrT : PtrType<RPCPortT>;
 def RPCBufferT : NamedType<"rpc_buffer_t">;
 def RPCBufferPtrT : PtrType<RPCBufferT>;
+def RPCCallbackT : NamedType<"rpc_callback_t">;
 
 def GPUExtensions : StandardSpec<"GPUExtensions"> {
   HeaderSpec RPC = HeaderSpec<
     "gpu/rpc.h",
     [], // Macros
-    [RPCPortT, RPCBufferT, SizeTType], // Types
+    [RPCPortT, RPCBufferT,  RPCCallbackT, SizeTType], // Types
     [], // Enumerations
     [
         FunctionSpec<
@@ -20,20 +21,15 @@ def GPUExtensions : StandardSpec<"GPUExtensions"> {
             RetValSpec<RPCPortT>,
             [ArgSpec<UnsignedIntType>]
         >,
-        FunctionSpec<
-            "rpc_get_buffer",
-            RetValSpec<RPCBufferPtrT>,
-            [ArgSpec<RPCPortPtrT>]
-        >,
         FunctionSpec<
             "rpc_send",
             RetValSpec<VoidType>,
-            [ArgSpec<RPCPortPtrT>]
+            [ArgSpec<RPCPortPtrT>, ArgSpec<RPCCallbackT>, ArgSpec<VoidPtr>]
         >,
         FunctionSpec<
             "rpc_recv",
             RetValSpec<VoidType>,
-            [ArgSpec<RPCPortPtrT>]
+            [ArgSpec<RPCPortPtrT>, ArgSpec<RPCCallbackT>, ArgSpec<VoidPtr>]
         >,
         FunctionSpec<
             "rpc_close_port",
diff --git a/libc/src/__support/RPC/rpc.h b/libc/src/__support/RPC/rpc.h
index 66c9fb297767780..653452edc8759b1 100644
--- a/libc/src/__support/RPC/rpc.h
+++ b/libc/src/__support/RPC/rpc.h
@@ -319,14 +319,6 @@ template <bool T, typename S> struct Port {
 
   LIBC_INLINE uint16_t get_index() const { return index; }
 
-  /// Waits until this port owns the buffer and returns a pointer to it.
-  LIBC_INLINE Buffer *get_buffer() const {
-    uint32_t in = owns_buffer ? out ^ T : process.load_inbox(lane_mask, index);
-    process.wait_for_ownership(lane_mask, index, out, in);
-
-    return &process.packet[index].payload.slot[gpu::get_lane_id()];
-  }
-
   LIBC_INLINE void close() {
     // The server is passive, if it own the buffer when it closes we need to
     // give ownership back to the client.
diff --git a/libc/src/gpu/rpc_get_buffer.cpp b/libc/src/gpu/rpc_get_buffer.cpp
deleted file mode 100644
index 10097b404c81c46..000000000000000
--- a/libc/src/gpu/rpc_get_buffer.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===---------- GPU implementation of the external RPC port interface -----===//
-//
-// 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/gpu/rpc_get_buffer.h"
-
-#include "src/__support/GPU/utils.h"
-#include "src/__support/RPC/rpc_client.h"
-#include "src/__support/common.h"
-
-namespace LIBC_NAMESPACE {
-
-static_assert(sizeof(rpc_port_t) == sizeof(rpc::Client::Port), "ABI mismatch");
-static_assert(sizeof(rpc_buffer_t) == sizeof(rpc::Buffer), "ABI mismatch");
-
-LLVM_LIBC_FUNCTION(rpc_buffer_t *, rpc_get_buffer, (rpc_port_t * handle)) {
-  rpc::Client::Port *port = reinterpret_cast<rpc::Client::Port *>(handle);
-  return reinterpret_cast<rpc_buffer_t *>(port->get_buffer());
-}
-
-} // namespace LIBC_NAMESPACE
diff --git a/libc/src/gpu/rpc_get_buffer.h b/libc/src/gpu/rpc_get_buffer.h
deleted file mode 100644
index 5a07db1a5470085..000000000000000
--- a/libc/src/gpu/rpc_get_buffer.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//===-- Implementation header for RPC functions -----------------*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIBC_SRC_GPU_RPC_GET_BUFFER_H
-#define LLVM_LIBC_SRC_GPU_RPC_GET_BUFFER_H
-
-#include <gpu/rpc.h>
-
-namespace LIBC_NAMESPACE {
-
-rpc_buffer_t *rpc_get_buffer(rpc_port_t *handle);
-
-} // namespace LIBC_NAMESPACE
-
-#endif // LLVM_LIBC_SRC_GPU_RPC_GET_BUFFER_H
diff --git a/libc/src/gpu/rpc_recv.cpp b/libc/src/gpu/rpc_recv.cpp
index 96086dc2b17a345..5f6b4d919d26b92 100644
--- a/libc/src/gpu/rpc_recv.cpp
+++ b/libc/src/gpu/rpc_recv.cpp
@@ -17,9 +17,12 @@ namespace LIBC_NAMESPACE {
 static_assert(sizeof(rpc_port_t) == sizeof(rpc::Client::Port), "ABI mismatch");
 static_assert(sizeof(rpc_buffer_t) == sizeof(rpc::Buffer), "ABI mismatch");
 
-LLVM_LIBC_FUNCTION(void, rpc_recv, (rpc_port_t * handle)) {
+LLVM_LIBC_FUNCTION(void, rpc_recv,
+                   (rpc_port_t * handle, rpc_callback_t callback, void *data)) {
   rpc::Client::Port *port = reinterpret_cast<rpc::Client::Port *>(handle);
-  port->recv([](rpc::Buffer *) { /* Filled by rpc_get_buffer() */ });
+  port->recv([=](rpc::Buffer *buffer, uint32_t id) {
+    callback(reinterpret_cast<rpc_buffer_t *>(buffer), data, id);
+  });
 }
 
 } // namespace LIBC_NAMESPACE
diff --git a/libc/src/gpu/rpc_recv.h b/libc/src/gpu/rpc_recv.h
index 926565c3b0c16a0..cbc392d2b7141ca 100644
--- a/libc/src/gpu/rpc_recv.h
+++ b/libc/src/gpu/rpc_recv.h
@@ -13,7 +13,7 @@
 
 namespace LIBC_NAMESPACE {
 
-void rpc_recv(rpc_port_t *handle);
+void rpc_recv(rpc_port_t *handle, rpc_callback_t callback, void *data);
 
 } // namespace LIBC_NAMESPACE
 
diff --git a/libc/src/gpu/rpc_send.cpp b/libc/src/gpu/rpc_send.cpp
index 4f4f5bcc2a5eb80..c5d0bbbbf3844aa 100644
--- a/libc/src/gpu/rpc_send.cpp
+++ b/libc/src/gpu/rpc_send.cpp
@@ -17,9 +17,12 @@ namespace LIBC_NAMESPACE {
 static_assert(sizeof(rpc_port_t) == sizeof(rpc::Client::Port), "ABI mismatch");
 static_assert(sizeof(rpc_buffer_t) == sizeof(rpc::Buffer), "ABI mismatch");
 
-LLVM_LIBC_FUNCTION(void, rpc_send, (rpc_port_t * handle)) {
+LLVM_LIBC_FUNCTION(void, rpc_send,
+                   (rpc_port_t * handle, rpc_callback_t callback, void *data)) {
   rpc::Client::Port *port = reinterpret_cast<rpc::Client::Port *>(handle);
-  port->send([](rpc::Buffer *) { /* Filled by rpc_get_buffer() */ });
+  port->send([=](rpc::Buffer *buffer, uint32_t id) {
+    callback(reinterpret_cast<rpc_buffer_t *>(buffer), data, id);
+  });
 }
 
 } // namespace LIBC_NAMESPACE
diff --git a/libc/src/gpu/rpc_send.h b/libc/src/gpu/rpc_send.h
index e367514181f2ba8..f158247d8031de5 100644
--- a/libc/src/gpu/rpc_send.h
+++ b/libc/src/gpu/rpc_send.h
@@ -13,7 +13,7 @@
 
 namespace LIBC_NAMESPACE {
 
-void rpc_send(rpc_port_t *handle);
+void rpc_send(rpc_port_t *handle, rpc_callback_t callback, void *data);
 
 } // namespace LIBC_NAMESPACE
 
diff --git a/libc/test/integration/startup/gpu/CMakeLists.txt b/libc/test/integration/startup/gpu/CMakeLists.txt
index 18764ad2bcaf0b0..79c09c1c7022ff7 100644
--- a/libc/test/integration/startup/gpu/CMakeLists.txt
+++ b/libc/test/integration/startup/gpu/CMakeLists.txt
@@ -51,7 +51,6 @@ add_integration_test(
     rpc_external_interface_test.cpp
   DEPENDS
     libc.src.gpu.rpc_open_port
-    libc.src.gpu.rpc_get_buffer
     libc.src.gpu.rpc_send
     libc.src.gpu.rpc_recv
     libc.src.gpu.rpc_close_port
diff --git a/libc/test/integration/startup/gpu/rpc_external_interface_test.cpp b/libc/test/integration/startup/gpu/rpc_external_interface_test.cpp
index ae5221f58fc901d..6f446b6fbdc53aa 100644
--- a/libc/test/integration/startup/gpu/rpc_external_interface_test.cpp
+++ b/libc/test/integration/startup/gpu/rpc_external_interface_test.cpp
@@ -9,7 +9,6 @@
 #include <gpu/rpc.h>
 
 #include "src/gpu/rpc_close_port.h"
-#include "src/gpu/rpc_get_buffer.h"
 #include "src/gpu/rpc_open_port.h"
 #include "src/gpu/rpc_recv.h"
 #include "src/gpu/rpc_send.h"
@@ -28,61 +27,93 @@ static void test_interface(bool end_with_send) {
   // rpc::Client::Port port = rpc::client.open<RPC_TEST_INTERFACE>();
   rpc_port_t port = LIBC_NAMESPACE::rpc_open_port(RPC_TEST_INTERFACE);
 
-  // port.send([&](rpc::Buffer *buffer) { buffer->data[0] = end_with_send; });
-  rpc_buffer_t *buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
-  buffer->data[0] = end_with_send;
-  LIBC_NAMESPACE::rpc_send(&port);
+  LIBC_NAMESPACE::rpc_send(
+      &port,
+      [](rpc_buffer_t *buffer, void *data, uint32_t) {
+        buffer->data[0] = *reinterpret_cast<bool *>(data);
+      },
+      &end_with_send);
 
   // port.send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
-  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
-  buffer->data[0] = cnt = cnt + 1;
-  LIBC_NAMESPACE::rpc_send(&port);
+  LIBC_NAMESPACE::rpc_send(
+      &port,
+      [](rpc_buffer_t *buffer, void *data, uint32_t) {
+        buffer->data[0] = *reinterpret_cast<uint64_t *>(data) += 1;
+      },
+      &cnt);
 
   // port.recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
-  LIBC_NAMESPACE::rpc_recv(&port);
-  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
-  cnt = buffer->data[0];
+  LIBC_NAMESPACE::rpc_recv(
+      &port,
+      [](rpc_buffer_t *buffer, void *data, uint32_t) {
+        *reinterpret_cast<uint64_t *>(data) = buffer->data[0];
+      },
+      &cnt);
 
   // port.send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
-  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
-  buffer->data[0] = cnt = cnt + 1;
-  LIBC_NAMESPACE::rpc_send(&port);
+  LIBC_NAMESPACE::rpc_send(
+      &port,
+      [](rpc_buffer_t *buffer, void *data, uint32_t) {
+        buffer->data[0] = *reinterpret_cast<uint64_t *>(data) += 1;
+      },
+      &cnt);
 
   // port.recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
-  LIBC_NAMESPACE::rpc_recv(&port);
-  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
-  cnt = buffer->data[0];
+  LIBC_NAMESPACE::rpc_recv(
+      &port,
+      [](rpc_buffer_t *buffer, void *data, uint32_t) {
+        *reinterpret_cast<uint64_t *>(data) = buffer->data[0];
+      },
+      &cnt);
 
   // port.send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
-  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
-  buffer->data[0] = cnt = cnt + 1;
-  LIBC_NAMESPACE::rpc_send(&port);
+  LIBC_NAMESPACE::rpc_send(
+      &port,
+      [](rpc_buffer_t *buffer, void *data, uint32_t) {
+        buffer->data[0] = *reinterpret_cast<uint64_t *>(data) += 1;
+      },
+      &cnt);
 
   // port.send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
-  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
-  buffer->data[0] = cnt = cnt + 1;
-  LIBC_NAMESPACE::rpc_send(&port);
+  LIBC_NAMESPACE::rpc_send(
+      &port,
+      [](rpc_buffer_t *buffer, void *data, uint32_t) {
+        buffer->data[0] = *reinterpret_cast<uint64_t *>(data) += 1;
+      },
+      &cnt);
 
   // port.recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
-  LIBC_NAMESPACE::rpc_recv(&port);
-  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
-  cnt = buffer->data[0];
+  LIBC_NAMESPACE::rpc_recv(
+      &port,
+      [](rpc_buffer_t *buffer, void *data, uint32_t) {
+        *reinterpret_cast<uint64_t *>(data) = buffer->data[0];
+      },
+      &cnt);
 
   // port.recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
-  LIBC_NAMESPACE::rpc_recv(&port);
-  buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
-  cnt = buffer->data[0];
+  LIBC_NAMESPACE::rpc_recv(
+      &port,
+      [](rpc_buffer_t *buffer, void *data, uint32_t) {
+        *reinterpret_cast<uint64_t *>(data) = buffer->data[0];
+      },
+      &cnt);
 
   if (end_with_send) {
     // port.send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
-    buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
-    buffer->data[0] = cnt = cnt + 1;
-    LIBC_NAMESPACE::rpc_send(&port);
+    LIBC_NAMESPACE::rpc_send(
+        &port,
+        [](rpc_buffer_t *buffer, void *data, uint32_t) {
+          buffer->data[0] = *reinterpret_cast<uint64_t *>(data) += 1;
+        },
+        &cnt);
   } else {
     // port.recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
-    LIBC_NAMESPACE::rpc_recv(&port);
-    buffer = LIBC_NAMESPACE::rpc_get_buffer(&port);
-    cnt = buffer->data[0];
+    LIBC_NAMESPACE::rpc_recv(
+        &port,
+        [](rpc_buffer_t *buffer, void *data, uint32_t) {
+          *reinterpret_cast<uint64_t *>(data) = buffer->data[0];
+        },
+        &cnt);
   }
 
   // port.close();



More information about the libc-commits mailing list