mirror of
https://github.com/intel/llvm.git
synced 2026-01-25 01:07:04 +08:00
[libc] Increase RPC opcode to 32-bit and use a class byte (#116905)
Summary: Currently, the RPC interface uses a basic opcode to communicate with the server. This currently is 16 bits. There's no reason for this to be 16 bits, because on the GPU a 32-bit write is the same as a 16-bit write performance wise. Additionally, I am now making all the `libc` based opcodes qualified with the 'c' type, mimiciing how Linux handles `ioctls` all coming from the same driver. This will make it easier to extend the interface when it's exported directly.
This commit is contained in:
@@ -302,6 +302,6 @@ associated with relocatable device code linking.
|
||||
Extensions
|
||||
----------
|
||||
|
||||
We describe which operation the RPC server should take with a 16-bit opcode. We
|
||||
consider the first 32768 numbers to be reserved while the others are free to
|
||||
use.
|
||||
The opcode is a 32-bit integer that must be unique to the requested operation.
|
||||
All opcodes used by ``libc`` internally have the character ``c`` in the most
|
||||
significant byte.
|
||||
|
||||
@@ -9,38 +9,41 @@
|
||||
#ifndef LLVM_LIBC_TYPES_RPC_OPCODES_T_H
|
||||
#define LLVM_LIBC_TYPES_RPC_OPCODES_T_H
|
||||
|
||||
#define LLVM_LIBC_RPC_BASE 'c'
|
||||
#define LLVM_LIBC_OPCODE(n) (LLVM_LIBC_RPC_BASE << 24 | n)
|
||||
|
||||
typedef enum {
|
||||
RPC_NOOP = 0,
|
||||
RPC_EXIT,
|
||||
RPC_WRITE_TO_STDOUT,
|
||||
RPC_WRITE_TO_STDERR,
|
||||
RPC_WRITE_TO_STREAM,
|
||||
RPC_WRITE_TO_STDOUT_NEWLINE,
|
||||
RPC_READ_FROM_STREAM,
|
||||
RPC_READ_FGETS,
|
||||
RPC_OPEN_FILE,
|
||||
RPC_CLOSE_FILE,
|
||||
RPC_MALLOC,
|
||||
RPC_FREE,
|
||||
RPC_HOST_CALL,
|
||||
RPC_ABORT,
|
||||
RPC_FEOF,
|
||||
RPC_FERROR,
|
||||
RPC_CLEARERR,
|
||||
RPC_FSEEK,
|
||||
RPC_FTELL,
|
||||
RPC_FFLUSH,
|
||||
RPC_UNGETC,
|
||||
RPC_PRINTF_TO_STDOUT,
|
||||
RPC_PRINTF_TO_STDERR,
|
||||
RPC_PRINTF_TO_STREAM,
|
||||
RPC_PRINTF_TO_STDOUT_PACKED,
|
||||
RPC_PRINTF_TO_STDERR_PACKED,
|
||||
RPC_PRINTF_TO_STREAM_PACKED,
|
||||
RPC_REMOVE,
|
||||
RPC_RENAME,
|
||||
RPC_SYSTEM,
|
||||
RPC_LAST = 0xFFFF,
|
||||
RPC_NOOP = LLVM_LIBC_OPCODE(0),
|
||||
RPC_EXIT = LLVM_LIBC_OPCODE(1),
|
||||
RPC_WRITE_TO_STDOUT = LLVM_LIBC_OPCODE(2),
|
||||
RPC_WRITE_TO_STDERR = LLVM_LIBC_OPCODE(3),
|
||||
RPC_WRITE_TO_STREAM = LLVM_LIBC_OPCODE(4),
|
||||
RPC_WRITE_TO_STDOUT_NEWLINE = LLVM_LIBC_OPCODE(5),
|
||||
RPC_READ_FROM_STREAM = LLVM_LIBC_OPCODE(6),
|
||||
RPC_READ_FGETS = LLVM_LIBC_OPCODE(7),
|
||||
RPC_OPEN_FILE = LLVM_LIBC_OPCODE(8),
|
||||
RPC_CLOSE_FILE = LLVM_LIBC_OPCODE(9),
|
||||
RPC_MALLOC = LLVM_LIBC_OPCODE(10),
|
||||
RPC_FREE = LLVM_LIBC_OPCODE(11),
|
||||
RPC_HOST_CALL = LLVM_LIBC_OPCODE(12),
|
||||
RPC_ABORT = LLVM_LIBC_OPCODE(13),
|
||||
RPC_FEOF = LLVM_LIBC_OPCODE(14),
|
||||
RPC_FERROR = LLVM_LIBC_OPCODE(15),
|
||||
RPC_CLEARERR = LLVM_LIBC_OPCODE(16),
|
||||
RPC_FSEEK = LLVM_LIBC_OPCODE(17),
|
||||
RPC_FTELL = LLVM_LIBC_OPCODE(18),
|
||||
RPC_FFLUSH = LLVM_LIBC_OPCODE(19),
|
||||
RPC_UNGETC = LLVM_LIBC_OPCODE(20),
|
||||
RPC_PRINTF_TO_STDOUT = LLVM_LIBC_OPCODE(21),
|
||||
RPC_PRINTF_TO_STDERR = LLVM_LIBC_OPCODE(22),
|
||||
RPC_PRINTF_TO_STREAM = LLVM_LIBC_OPCODE(23),
|
||||
RPC_PRINTF_TO_STDOUT_PACKED = LLVM_LIBC_OPCODE(24),
|
||||
RPC_PRINTF_TO_STDERR_PACKED = LLVM_LIBC_OPCODE(25),
|
||||
RPC_PRINTF_TO_STREAM_PACKED = LLVM_LIBC_OPCODE(26),
|
||||
RPC_REMOVE = LLVM_LIBC_OPCODE(27),
|
||||
RPC_RENAME = LLVM_LIBC_OPCODE(28),
|
||||
RPC_SYSTEM = LLVM_LIBC_OPCODE(29),
|
||||
RPC_LAST = 0xFFFFFFFF,
|
||||
} rpc_opcode_t;
|
||||
|
||||
#endif // LLVM_LIBC_TYPES_RPC_OPCODES_T_H
|
||||
|
||||
@@ -51,7 +51,7 @@ static_assert(sizeof(Buffer) == 64, "Buffer size mismatch");
|
||||
/// perform and which threads are active in the slots.
|
||||
struct Header {
|
||||
uint64_t mask;
|
||||
uint16_t opcode;
|
||||
uint32_t opcode;
|
||||
};
|
||||
|
||||
/// The maximum number of parallel ports that the RPC interface can support.
|
||||
@@ -319,11 +319,11 @@ public:
|
||||
template <typename A>
|
||||
LIBC_INLINE void recv_n(void **dst, uint64_t *size, A &&alloc);
|
||||
|
||||
LIBC_INLINE uint16_t get_opcode() const {
|
||||
LIBC_INLINE uint32_t get_opcode() const {
|
||||
return process.header[index].opcode;
|
||||
}
|
||||
|
||||
LIBC_INLINE uint16_t get_index() const { return index; }
|
||||
LIBC_INLINE uint32_t get_index() const { return index; }
|
||||
|
||||
LIBC_INLINE void close() {
|
||||
// Wait for all lanes to finish using the port.
|
||||
@@ -357,7 +357,7 @@ struct Client {
|
||||
: process(port_count, buffer) {}
|
||||
|
||||
using Port = rpc::Port<false>;
|
||||
template <uint16_t opcode> LIBC_INLINE Port open();
|
||||
template <uint32_t opcode> LIBC_INLINE Port open();
|
||||
|
||||
private:
|
||||
Process<false> process;
|
||||
@@ -518,7 +518,7 @@ LIBC_INLINE void Port<T>::recv_n(void **dst, uint64_t *size, A &&alloc) {
|
||||
/// port. Each port instance uses an associated \p opcode to tell the server
|
||||
/// what to do. The Client interface provides the appropriate lane size to the
|
||||
/// port using the platform's returned value.
|
||||
template <uint16_t opcode>
|
||||
template <uint32_t opcode>
|
||||
[[clang::convergent]] LIBC_INLINE Client::Port Client::open() {
|
||||
// Repeatedly perform a naive linear scan for a port that can be opened to
|
||||
// send data.
|
||||
|
||||
@@ -49,7 +49,7 @@ LIBC_INLINE ::FILE *to_stream(uintptr_t f) {
|
||||
return stream;
|
||||
}
|
||||
|
||||
template <uint16_t opcode>
|
||||
template <uint32_t opcode>
|
||||
LIBC_INLINE uint64_t write_impl(::FILE *file, const void *data, size_t size) {
|
||||
uint64_t ret = 0;
|
||||
rpc::Client::Port port = rpc::client.open<opcode>();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
|
||||
template <uint16_t opcode>
|
||||
template <uint32_t opcode>
|
||||
LIBC_INLINE int vfprintf_impl(::FILE *__restrict file,
|
||||
const char *__restrict format, size_t format_size,
|
||||
va_list vlist) {
|
||||
|
||||
@@ -79,7 +79,7 @@ rpc_status_t rpc_handle_server(rpc_device_t rpc_device);
|
||||
/// Register a callback to handle an opcode from the RPC client. The associated
|
||||
/// data must remain accessible as long as the user intends to handle the server
|
||||
/// with this callback.
|
||||
rpc_status_t rpc_register_callback(rpc_device_t rpc_device, uint16_t opcode,
|
||||
rpc_status_t rpc_register_callback(rpc_device_t rpc_device, uint32_t opcode,
|
||||
rpc_opcode_callback_ty callback, void *data);
|
||||
|
||||
/// Obtain a pointer to a local client buffer that can be copied directly to the
|
||||
|
||||
@@ -215,8 +215,8 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
|
||||
template <uint32_t lane_size>
|
||||
rpc_status_t handle_server_impl(
|
||||
rpc::Server &server,
|
||||
const std::unordered_map<uint16_t, rpc_opcode_callback_ty> &callbacks,
|
||||
const std::unordered_map<uint16_t, void *> &callback_data,
|
||||
const std::unordered_map<uint32_t, rpc_opcode_callback_ty> &callbacks,
|
||||
const std::unordered_map<uint32_t, void *> &callback_data,
|
||||
uint32_t &index) {
|
||||
auto port = server.try_open(lane_size, index);
|
||||
if (!port)
|
||||
@@ -477,8 +477,8 @@ struct Device {
|
||||
void *buffer;
|
||||
rpc::Server server;
|
||||
rpc::Client client;
|
||||
std::unordered_map<uint16_t, rpc_opcode_callback_ty> callbacks;
|
||||
std::unordered_map<uint16_t, void *> callback_data;
|
||||
std::unordered_map<uint32_t, rpc_opcode_callback_ty> callbacks;
|
||||
std::unordered_map<uint32_t, void *> callback_data;
|
||||
};
|
||||
|
||||
rpc_status_t rpc_server_init(rpc_device_t *rpc_device, uint64_t num_ports,
|
||||
@@ -528,7 +528,7 @@ rpc_status_t rpc_handle_server(rpc_device_t rpc_device) {
|
||||
}
|
||||
}
|
||||
|
||||
rpc_status_t rpc_register_callback(rpc_device_t rpc_device, uint16_t opcode,
|
||||
rpc_status_t rpc_register_callback(rpc_device_t rpc_device, uint32_t opcode,
|
||||
rpc_opcode_callback_ty callback,
|
||||
void *data) {
|
||||
if (!rpc_device.handle)
|
||||
|
||||
Reference in New Issue
Block a user