blob: 6354b61fbf976e484181a57d9a1459cb207028c4 [file] [edit]
//===----------------------------------------------------------------------===//
//
// 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 <sycl/__impl/usm_functions.hpp>
#include <detail/device_impl.hpp>
#include <detail/offload/offload_utils.hpp>
#include <OffloadAPI.h>
#include <algorithm>
_LIBSYCL_BEGIN_NAMESPACE_SYCL
// SYCL 2020 4.8.3.2. Device allocation functions.
void *aligned_alloc_device(size_t alignment, size_t numBytes,
const device &syclDevice, const context &syclContext,
const property_list &propList) {
return aligned_alloc(alignment, numBytes, syclDevice, syclContext,
usm::alloc::device, propList);
}
void *aligned_alloc_device(size_t alignment, size_t numBytes,
const queue &syclQueue,
const property_list &propList) {
return aligned_alloc_device(alignment, numBytes, syclQueue.get_device(),
syclQueue.get_context(), propList);
}
void *malloc_device(std::size_t numBytes, const device &syclDevice,
const context &syclContext, const property_list &propList) {
return malloc(numBytes, syclDevice, syclContext, usm::alloc::device,
propList);
}
void *malloc_device(std::size_t numBytes, const queue &syclQueue,
const property_list &propList) {
return malloc_device(numBytes, syclQueue.get_device(),
syclQueue.get_context(), propList);
}
// SYCL 2020 4.8.3.3. Host allocation functions.
static device getHostAllocDevice(const context &syclContext) {
auto ContextDevices = syclContext.get_devices();
auto It = std::find_if(
ContextDevices.begin(), ContextDevices.end(),
[](const device &Dev) { return Dev.has(aspect::usm_host_allocations); });
if (It == ContextDevices.end()) {
throw sycl::exception(
sycl::errc::feature_not_supported,
"None of the context's devices support host USM allocations.");
}
return *It;
}
void *aligned_alloc_host(size_t alignment, size_t numBytes,
const context &syclContext,
const property_list &propList) {
auto device = getHostAllocDevice(syclContext);
return aligned_alloc(alignment, numBytes, device, syclContext,
usm::alloc::host, propList);
}
void *aligned_alloc_host(size_t alignment, size_t numBytes,
const queue &syclQueue,
const property_list &propList) {
return aligned_alloc_host(alignment, numBytes, syclQueue.get_context(),
propList);
}
void *malloc_host(std::size_t numBytes, const context &syclContext,
const property_list &propList) {
return aligned_alloc_host(0, numBytes, syclContext, propList);
}
void *malloc_host(std::size_t numBytes, const queue &syclQueue,
const property_list &propList) {
return malloc_host(numBytes, syclQueue.get_context(), propList);
}
// SYCL 2020 4.8.3.4. Shared allocation functions.
void *aligned_alloc_shared(size_t alignment, size_t numBytes,
const device &syclDevice, const context &syclContext,
const property_list &propList) {
return aligned_alloc(alignment, numBytes, syclDevice, syclContext,
usm::alloc::shared, propList);
}
void *aligned_alloc_shared(size_t alignment, size_t numBytes,
const queue &syclQueue,
const property_list &propList) {
return aligned_alloc_shared(alignment, numBytes, syclQueue.get_device(),
syclQueue.get_context(), propList);
}
void *malloc_shared(std::size_t numBytes, const device &syclDevice,
const context &syclContext, const property_list &propList) {
return malloc(numBytes, syclDevice, syclContext, usm::alloc::shared,
propList);
}
void *malloc_shared(std::size_t numBytes, const queue &syclQueue,
const property_list &propList) {
return malloc_shared(numBytes, syclQueue.get_device(),
syclQueue.get_context(), propList);
}
// SYCL 2020 4.8.3.5. Parameterized allocation functions.
static aspect getAspectByAllocationKind(usm::alloc kind) {
switch (kind) {
case usm::alloc::host:
return aspect::usm_host_allocations;
case usm::alloc::device:
return aspect::usm_device_allocations;
case usm::alloc::shared:
return aspect::usm_shared_allocations;
case usm::alloc::unknown:
// usm::alloc::unknown can be returned to user from get_pointer_type but
// it can't be converted to a valid backend type.
throw exception(sycl::make_error_code(sycl::errc::invalid),
"Invalid USM allocation kind requested");
}
}
void *aligned_alloc(std::size_t alignment, std::size_t numBytes,
const device &syclDevice, const context &syclContext,
usm::alloc kind, const property_list &propList) {
auto ContextDevices = syclContext.get_devices();
if (std::none_of(ContextDevices.begin(), ContextDevices.end(),
[&syclDevice](device Dev) { return Dev == syclDevice; }))
throw exception(make_error_code(errc::invalid),
"Specified device is not contained by specified context.");
if (!syclDevice.has(getAspectByAllocationKind(kind)))
throw sycl::exception(
sycl::errc::feature_not_supported,
"Device doesn't support requested kind of USM allocation");
if (!numBytes)
return nullptr;
void *Ptr{};
auto OLDevice = detail::getSyclObjImpl(syclDevice)->getOLHandle();
ol_result_t Result{};
if (alignment == 0) {
Result =
kind == usm::alloc::host
? detail::callNoCheck(olMemAllocHost, OLDevice, numBytes, &Ptr)
: detail::callNoCheck(olMemAlloc, OLDevice,
detail::getOlAllocType(kind), numBytes, &Ptr);
} else {
Result = kind == usm::alloc::host
? detail::callNoCheck(olMemAllocAlignedHost, OLDevice,
numBytes, alignment, &Ptr)
: detail::callNoCheck(olMemAllocAligned, OLDevice,
detail::getOlAllocType(kind), numBytes,
alignment, &Ptr);
}
return detail::isFailed(Result) ? nullptr : Ptr;
}
void *aligned_alloc(std::size_t alignment, std::size_t numBytes,
const queue &syclQueue, usm::alloc kind,
const property_list &propList) {
return aligned_alloc(alignment, numBytes, syclQueue.get_device(),
syclQueue.get_context(), kind, propList);
}
void *malloc(std::size_t numBytes, const device &syclDevice,
const context &syclContext, usm::alloc kind,
const property_list &propList) {
return aligned_alloc(0, numBytes, syclDevice, syclContext, kind, propList);
}
void *malloc(std::size_t numBytes, const queue &syclQueue, usm::alloc kind,
const property_list &propList) {
return malloc(numBytes, syclQueue.get_device(), syclQueue.get_context(), kind,
propList);
}
// SYCL 2020 4.8.3.6. Memory deallocation functions.
void free(void *ptr, const context &ctxt) {
std::ignore = ctxt;
detail::callAndThrow(olMemFree, ptr);
}
void free(void *ptr, const queue &q) { return free(ptr, q.get_context()); }
_LIBSYCL_END_NAMESPACE_SYCL