140 lines · cpp
1//===--------- Misc.cpp - OpenMP device misc interfaces ----------- C++ -*-===//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//10//===----------------------------------------------------------------------===//11 12#include "Allocator.h"13#include "Configuration.h"14#include "DeviceTypes.h"15#include "Shared/RPCOpcodes.h"16#include "shared/rpc.h"17 18#include "Debug.h"19 20namespace ompx {21namespace impl {22 23/// Lookup a device-side function using a host pointer /p HstPtr using the table24/// provided by the device plugin. The table is an ordered pair of host and25/// device pointers sorted on the value of the host pointer.26static void *indirectCallLookup(void *HstPtr) {27 if (!HstPtr)28 return nullptr;29 30 struct IndirectCallTable {31 void *HstPtr;32 void *DevPtr;33 };34 IndirectCallTable *Table =35 reinterpret_cast<IndirectCallTable *>(config::getIndirectCallTablePtr());36 uint64_t TableSize = config::getIndirectCallTableSize();37 38 // If the table is empty we assume this is device pointer.39 if (!Table || !TableSize)40 return HstPtr;41 42 uint32_t Left = 0;43 uint32_t Right = TableSize;44 45 // If the pointer is definitely not contained in the table we exit early.46 if (HstPtr < Table[Left].HstPtr || HstPtr > Table[Right - 1].HstPtr)47 return HstPtr;48 49 while (Left != Right) {50 uint32_t Current = Left + (Right - Left) / 2;51 if (Table[Current].HstPtr == HstPtr)52 return Table[Current].DevPtr;53 54 if (HstPtr < Table[Current].HstPtr)55 Right = Current;56 else57 Left = Current;58 }59 60 // If we searched the whole table and found nothing this is a device pointer.61 return HstPtr;62}63 64/// The openmp client instance used to communicate with the server.65[[gnu::visibility("protected"),66 gnu::weak]] rpc::Client Client asm("__llvm_rpc_client");67 68} // namespace impl69} // namespace ompx70 71/// Interfaces72///73///{74 75extern "C" {76int32_t __kmpc_cancellationpoint(IdentTy *, int32_t, int32_t) { return 0; }77 78int32_t __kmpc_cancel(IdentTy *, int32_t, int32_t) { return 0; }79 80double omp_get_wtick(void) {81 // The number of ticks per second for the AMDGPU clock varies by card and can82 // only be retrieved by querying the driver. We rely on the device environment83 // to inform us what the proper frequency is. NVPTX uses a nanosecond84 // resolution, we could omit the global read but this makes it consistent.85 return 1.0 / ompx::config::getClockFrequency();86}87 88double omp_get_wtime(void) {89 return static_cast<double>(__builtin_readsteadycounter()) * omp_get_wtick();90}91 92void *__llvm_omp_indirect_call_lookup(void *HstPtr) {93 return ompx::impl::indirectCallLookup(HstPtr);94}95 96void *omp_alloc(size_t size, omp_allocator_handle_t allocator) {97 switch (allocator) {98 case omp_default_mem_alloc:99 case omp_large_cap_mem_alloc:100 case omp_const_mem_alloc:101 case omp_high_bw_mem_alloc:102 case omp_low_lat_mem_alloc:103 return ompx::allocator::alloc(size);104 default:105 return nullptr;106 }107}108 109void omp_free(void *ptr, omp_allocator_handle_t allocator) {110 switch (allocator) {111 case omp_default_mem_alloc:112 case omp_large_cap_mem_alloc:113 case omp_const_mem_alloc:114 case omp_high_bw_mem_alloc:115 case omp_low_lat_mem_alloc:116 ompx::allocator::free(ptr);117 return;118 case omp_null_allocator:119 default:120 return;121 }122}123 124unsigned long long __llvm_omp_host_call(void *fn, void *data, size_t size) {125 rpc::Client::Port Port = ompx::impl::Client.open<OFFLOAD_HOST_CALL>();126 Port.send_n(data, size);127 Port.send([=](rpc::Buffer *buffer, uint32_t) {128 buffer->data[0] = reinterpret_cast<uintptr_t>(fn);129 });130 unsigned long long Ret;131 Port.recv([&](rpc::Buffer *Buffer, uint32_t) {132 Ret = static_cast<unsigned long long>(Buffer->data[0]);133 });134 Port.close();135 return Ret;136}137}138 139///}140