brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.0 KiB · 102c6c6 Raw
99 lines · c
1//===--- GPU helper functions for file I/O using RPC ----------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "hdr/stdio_macros.h" // For stdin/out/err10#include "hdr/types/FILE.h"11#include "src/__support/RPC/rpc_client.h"12#include "src/__support/common.h"13#include "src/__support/macros/attributes.h"14 15namespace LIBC_NAMESPACE_DECL {16namespace file {17 18enum Stream {19  File = 0,20  Stdin = 1,21  Stdout = 2,22  Stderr = 3,23};24 25// When copying between the client and server we need to indicate if this is one26// of the special streams. We do this by enocding the low order bits of the27// pointer to indicate if we need to use the host's standard stream.28LIBC_INLINE uintptr_t from_stream(::FILE *f) {29  if (f == stdin)30    return reinterpret_cast<uintptr_t>(f) | Stdin;31  if (f == stdout)32    return reinterpret_cast<uintptr_t>(f) | Stdout;33  if (f == stderr)34    return reinterpret_cast<uintptr_t>(f) | Stderr;35  return reinterpret_cast<uintptr_t>(f);36}37 38// Get the associated stream out of an encoded number.39LIBC_INLINE ::FILE *to_stream(uintptr_t f) {40  ::FILE *stream = reinterpret_cast<FILE *>(f & ~0x3ull);41  Stream type = static_cast<Stream>(f & 0x3ull);42  if (type == Stdin)43    return stdin;44  if (type == Stdout)45    return stdout;46  if (type == Stderr)47    return stderr;48  return stream;49}50 51template <uint32_t opcode>52LIBC_INLINE uint64_t write_impl(::FILE *file, const void *data, size_t size) {53  uint64_t ret = 0;54  rpc::Client::Port port = rpc::client.open<opcode>();55 56  if constexpr (opcode == LIBC_WRITE_TO_STREAM) {57    port.send([&](rpc::Buffer *buffer, uint32_t) {58      buffer->data[0] = reinterpret_cast<uintptr_t>(file);59    });60  }61 62  port.send_n(data, size);63  port.recv([&](rpc::Buffer *buffer, uint32_t) {64    ret = reinterpret_cast<uint64_t *>(buffer->data)[0];65  });66  port.close();67  return ret;68}69 70LIBC_INLINE uint64_t write(::FILE *f, const void *data, size_t size) {71  if (f == stdout)72    return write_impl<LIBC_WRITE_TO_STDOUT>(f, data, size);73  else if (f == stderr)74    return write_impl<LIBC_WRITE_TO_STDERR>(f, data, size);75  else76    return write_impl<LIBC_WRITE_TO_STREAM>(f, data, size);77}78 79LIBC_INLINE uint64_t read_from_stream(::FILE *file, void *buf, size_t size) {80  uint64_t ret = 0;81  uint64_t recv_size;82  rpc::Client::Port port = rpc::client.open<LIBC_READ_FROM_STREAM>();83  port.send([=](rpc::Buffer *buffer, uint32_t) {84    buffer->data[0] = size;85    buffer->data[1] = from_stream(file);86  });87  port.recv_n(&buf, &recv_size, [&](uint64_t) { return buf; });88  port.recv([&](rpc::Buffer *buffer, uint32_t) { ret = buffer->data[0]; });89  port.close();90  return ret;91}92 93LIBC_INLINE uint64_t read(::FILE *f, void *data, size_t size) {94  return read_from_stream(f, data, size);95}96 97} // namespace file98} // namespace LIBC_NAMESPACE_DECL99