Currently we have the `send_n` and `recv_n` routines to stream data, such as a string to print, to the other side. The first operation is to send the size so the other side knows the number of bytes to recieve. However, this wasted 56 bytes that could've been sent. This meant that small values, like the arguments to a function to call on the host for example, needed to perform an extra send. This patch sends the first 56 bytes in the first packet and continues if necessary. Depends on D150992 Reviewed By: JonChesterfield Differential Revision: https://reviews.llvm.org/D151041
97 lines
3.2 KiB
C++
97 lines
3.2 KiB
C++
//===-- Generic RPC server 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIBC_UTILS_GPU_LOADER_RPC_H
|
|
#define LLVM_LIBC_UTILS_GPU_LOADER_RPC_H
|
|
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <stddef.h>
|
|
|
|
#include "src/__support/RPC/rpc.h"
|
|
|
|
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() {
|
|
using namespace __llvm_libc;
|
|
|
|
// Continue servicing the client until there is no work left and we return.
|
|
for (;;) {
|
|
auto port = server.try_open();
|
|
if (!port)
|
|
return;
|
|
|
|
switch (port->get_opcode()) {
|
|
case rpc::Opcode::PRINT_TO_STDERR: {
|
|
uint64_t sizes[rpc::MAX_LANE_SIZE] = {0};
|
|
void *strs[rpc::MAX_LANE_SIZE] = {nullptr};
|
|
port->recv_n(strs, sizes, [&](uint64_t size) { return new char[size]; });
|
|
port->send([](rpc::Buffer *) { /* void */ });
|
|
for (uint64_t i = 0; i < rpc::MAX_LANE_SIZE; ++i) {
|
|
if (strs[i]) {
|
|
fwrite(strs[i], sizes[i], 1, stderr);
|
|
delete[] reinterpret_cast<uint8_t *>(strs[i]);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case rpc::Opcode::EXIT: {
|
|
port->recv([](rpc::Buffer *buffer) {
|
|
exit(reinterpret_cast<uint32_t *>(buffer->data)[0]);
|
|
});
|
|
break;
|
|
}
|
|
case rpc::Opcode::TEST_INCREMENT: {
|
|
port->recv_and_send([](rpc::Buffer *buffer) {
|
|
reinterpret_cast<uint64_t *>(buffer->data)[0] += 1;
|
|
});
|
|
break;
|
|
}
|
|
case rpc::Opcode::TEST_INTERFACE: {
|
|
uint64_t cnt = 0;
|
|
bool end_with_recv;
|
|
port->recv([&](rpc::Buffer *buffer) { end_with_recv = buffer->data[0]; });
|
|
port->recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
|
|
port->send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
|
|
port->recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
|
|
port->send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
|
|
port->recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
|
|
port->recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
|
|
port->send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
|
|
port->send([&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
|
|
if (end_with_recv)
|
|
port->recv([&](rpc::Buffer *buffer) { cnt = buffer->data[0]; });
|
|
else
|
|
port->send(
|
|
[&](rpc::Buffer *buffer) { buffer->data[0] = cnt = cnt + 1; });
|
|
break;
|
|
}
|
|
case rpc::Opcode::TEST_STREAM: {
|
|
uint64_t sizes[rpc::MAX_LANE_SIZE] = {0};
|
|
void *dst[rpc::MAX_LANE_SIZE] = {nullptr};
|
|
port->recv_n(dst, sizes, [](uint64_t size) { return new char[size]; });
|
|
port->send_n(dst, sizes);
|
|
for (uint64_t i = 0; i < rpc::MAX_LANE_SIZE; ++i) {
|
|
if (dst[i])
|
|
delete[] reinterpret_cast<uint8_t *>(dst[i]);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
port->recv([](rpc::Buffer *buffer) {});
|
|
}
|
|
port->close();
|
|
}
|
|
}
|
|
|
|
#endif
|