Somehow conflict with define in wingdi.h.
Fix build failures:
[ 52%] Building CXX object
projects/offload/plugins-nextgen/common/CMakeFiles/PluginCommon.dir/src/RPC.cpp.obj
In file included from
...llvm\offload\plugins-nextgen\common\src\RPC.cpp:16:
...\llvm\libc\shared\rpc.h(48,3): error: expected identifier
48 | ERROR = 0x1000,
| ^
c:\Program files (x86)\Windows
Kits\10\include\10.0.22000.0\um\wingdi.h(118,29): note: expanded from
macro 'ERROR'
118 | #define ERROR 0
| ^
...\llvm\offload\plugins-nextgen\common\src\RPC.cpp(75,17): error:
expected unqualified-id
75 | return rpc::ERROR;
| ^
c:\Program files (x86)\Windows
Kits\10\include\10.0.22000.0\um\wingdi.h(118,29): note: expanded from
macro 'ERROR'
118 | #define ERROR 0
| ^
2 errors generated.
143 lines
4.7 KiB
C++
143 lines
4.7 KiB
C++
//===- RPC.h - Interface for remote procedure calls from the GPU ----------===//
|
|
//
|
|
// 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 "RPC.h"
|
|
|
|
#include "Shared/Debug.h"
|
|
#include "Shared/RPCOpcodes.h"
|
|
|
|
#include "PluginInterface.h"
|
|
|
|
#include "shared/rpc.h"
|
|
#include "shared/rpc_opcodes.h"
|
|
|
|
using namespace llvm;
|
|
using namespace omp;
|
|
using namespace target;
|
|
|
|
template <uint32_t NumLanes>
|
|
rpc::Status handle_offload_opcodes(plugin::GenericDeviceTy &Device,
|
|
rpc::Server::Port &Port) {
|
|
|
|
switch (Port.get_opcode()) {
|
|
case LIBC_MALLOC: {
|
|
Port.recv_and_send([&](rpc::Buffer *Buffer, uint32_t) {
|
|
Buffer->data[0] = reinterpret_cast<uintptr_t>(Device.allocate(
|
|
Buffer->data[0], nullptr, TARGET_ALLOC_DEVICE_NON_BLOCKING));
|
|
});
|
|
break;
|
|
}
|
|
case LIBC_FREE: {
|
|
Port.recv([&](rpc::Buffer *Buffer, uint32_t) {
|
|
Device.free(reinterpret_cast<void *>(Buffer->data[0]),
|
|
TARGET_ALLOC_DEVICE_NON_BLOCKING);
|
|
});
|
|
break;
|
|
}
|
|
case OFFLOAD_HOST_CALL: {
|
|
uint64_t Sizes[NumLanes] = {0};
|
|
unsigned long long Results[NumLanes] = {0};
|
|
void *Args[NumLanes] = {nullptr};
|
|
Port.recv_n(Args, Sizes, [&](uint64_t Size) { return new char[Size]; });
|
|
Port.recv([&](rpc::Buffer *buffer, uint32_t ID) {
|
|
using FuncPtrTy = unsigned long long (*)(void *);
|
|
auto Func = reinterpret_cast<FuncPtrTy>(buffer->data[0]);
|
|
Results[ID] = Func(Args[ID]);
|
|
});
|
|
Port.send([&](rpc::Buffer *Buffer, uint32_t ID) {
|
|
Buffer->data[0] = static_cast<uint64_t>(Results[ID]);
|
|
delete[] reinterpret_cast<char *>(Args[ID]);
|
|
});
|
|
break;
|
|
}
|
|
default:
|
|
return rpc::RPC_UNHANDLED_OPCODE;
|
|
break;
|
|
}
|
|
return rpc::RPC_SUCCESS;
|
|
}
|
|
|
|
static rpc::Status handle_offload_opcodes(plugin::GenericDeviceTy &Device,
|
|
rpc::Server::Port &Port,
|
|
uint32_t NumLanes) {
|
|
if (NumLanes == 1)
|
|
return handle_offload_opcodes<1>(Device, Port);
|
|
else if (NumLanes == 32)
|
|
return handle_offload_opcodes<32>(Device, Port);
|
|
else if (NumLanes == 64)
|
|
return handle_offload_opcodes<64>(Device, Port);
|
|
else
|
|
return rpc::RPC_ERROR;
|
|
}
|
|
|
|
RPCServerTy::RPCServerTy(plugin::GenericPluginTy &Plugin)
|
|
: Buffers(Plugin.getNumDevices()) {}
|
|
|
|
llvm::Expected<bool>
|
|
RPCServerTy::isDeviceUsingRPC(plugin::GenericDeviceTy &Device,
|
|
plugin::GenericGlobalHandlerTy &Handler,
|
|
plugin::DeviceImageTy &Image) {
|
|
return Handler.isSymbolInImage(Device, Image, "__llvm_rpc_client");
|
|
}
|
|
|
|
Error RPCServerTy::initDevice(plugin::GenericDeviceTy &Device,
|
|
plugin::GenericGlobalHandlerTy &Handler,
|
|
plugin::DeviceImageTy &Image) {
|
|
uint64_t NumPorts =
|
|
std::min(Device.requestedRPCPortCount(), rpc::MAX_PORT_COUNT);
|
|
void *RPCBuffer = Device.allocate(
|
|
rpc::Server::allocation_size(Device.getWarpSize(), NumPorts), nullptr,
|
|
TARGET_ALLOC_HOST);
|
|
if (!RPCBuffer)
|
|
return plugin::Plugin::error(
|
|
"Failed to initialize RPC server for device %d", Device.getDeviceId());
|
|
|
|
// Get the address of the RPC client from the device.
|
|
plugin::GlobalTy ClientGlobal("__llvm_rpc_client", sizeof(rpc::Client));
|
|
if (auto Err =
|
|
Handler.getGlobalMetadataFromDevice(Device, Image, ClientGlobal))
|
|
return Err;
|
|
|
|
rpc::Client client(NumPorts, RPCBuffer);
|
|
if (auto Err = Device.dataSubmit(ClientGlobal.getPtr(), &client,
|
|
sizeof(rpc::Client), nullptr))
|
|
return Err;
|
|
Buffers[Device.getDeviceId()] = RPCBuffer;
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
Error RPCServerTy::runServer(plugin::GenericDeviceTy &Device) {
|
|
uint64_t NumPorts =
|
|
std::min(Device.requestedRPCPortCount(), rpc::MAX_PORT_COUNT);
|
|
rpc::Server Server(NumPorts, Buffers[Device.getDeviceId()]);
|
|
|
|
auto Port = Server.try_open(Device.getWarpSize());
|
|
if (!Port)
|
|
return Error::success();
|
|
|
|
int Status = handle_offload_opcodes(Device, *Port, Device.getWarpSize());
|
|
|
|
// Let the `libc` library handle any other unhandled opcodes.
|
|
#ifdef LIBOMPTARGET_RPC_SUPPORT
|
|
if (Status == rpc::RPC_UNHANDLED_OPCODE)
|
|
Status = handle_libc_opcodes(*Port, Device.getWarpSize());
|
|
#endif
|
|
|
|
Port->close();
|
|
if (Status != rpc::RPC_SUCCESS)
|
|
return createStringError("RPC server given invalid opcode!");
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
Error RPCServerTy::deinitDevice(plugin::GenericDeviceTy &Device) {
|
|
Device.free(Buffers[Device.getDeviceId()], TARGET_ALLOC_HOST);
|
|
return Error::success();
|
|
}
|