| //===----------------------------------------------------------------------===// |
| // |
| // 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 |