1/*******************************************************************************
2* Copyright 2021 Intel Corporation
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*******************************************************************************/
16
17#include <CL/cl.h>
18
19#include "common/guard_manager.hpp"
20#include "gpu/ocl/ocl_usm_memory_storage.hpp"
21#include "gpu/ocl/ocl_usm_utils.hpp"
22
23namespace dnnl {
24namespace impl {
25namespace gpu {
26namespace ocl {
27
28struct map_usm_tag;
29
30status_t ocl_usm_memory_storage_t::map_data(
31 void **mapped_ptr, stream_t *stream, size_t size) const {
32
33 if (is_host_accessible()) {
34 *mapped_ptr = usm_ptr();
35 return status::success;
36 }
37
38 if (!usm_ptr() || size == 0) {
39 *mapped_ptr = nullptr;
40 return status::success;
41 }
42
43 if (!stream) CHECK(engine()->get_service_stream(stream));
44
45 void *host_ptr = usm::malloc_host(engine(), size);
46 if (!host_ptr) return status::out_of_memory;
47
48 auto leak_guard = decltype(usm_ptr_)(
49 host_ptr, [=](void *p) { usm::free(engine(), p); });
50 CHECK(usm::memcpy(stream, host_ptr, usm_ptr(), size));
51 CHECK(stream->wait());
52 leak_guard.release();
53
54 auto unmap_callback = [=]() mutable {
55 usm::memcpy(stream, usm_ptr(), host_ptr, size);
56 stream->wait();
57 usm::free(engine(), host_ptr);
58 };
59
60 auto &guard_manager = guard_manager_t<map_usm_tag>::instance();
61
62 *mapped_ptr = host_ptr;
63 return guard_manager.enter(this, unmap_callback);
64}
65
66status_t ocl_usm_memory_storage_t::unmap_data(
67 void *mapped_ptr, stream_t *stream) const {
68 if (!mapped_ptr || is_host_accessible()) return status::success;
69
70 auto &guard_manager = guard_manager_t<map_usm_tag>::instance();
71 return guard_manager.exit(this);
72}
73
74std::unique_ptr<memory_storage_t> ocl_usm_memory_storage_t::get_sub_storage(
75 size_t offset, size_t size) const {
76 void *sub_ptr = usm_ptr_
77 ? reinterpret_cast<uint8_t *>(usm_ptr_.get()) + offset
78 : nullptr;
79
80 auto storage = utils::make_unique<ocl_usm_memory_storage_t>(engine());
81 if (!storage) return nullptr;
82 auto status = storage->init(memory_flags_t::use_runtime_ptr, size, sub_ptr);
83 if (status != status::success) return nullptr;
84 // XXX: Clang has a bug that prevents implicit conversion.
85 return std::unique_ptr<memory_storage_t>(storage.release());
86}
87
88std::unique_ptr<memory_storage_t> ocl_usm_memory_storage_t::clone() const {
89 auto storage = utils::make_unique<ocl_usm_memory_storage_t>(engine());
90 if (!storage) return nullptr;
91
92 auto status = storage->init(memory_flags_t::use_runtime_ptr, 0, nullptr);
93 if (status != status::success) return nullptr;
94
95 storage->usm_ptr_ = decltype(usm_ptr_)(usm_ptr_.get(), [](void *) {});
96 storage->usm_kind_ = usm_kind_;
97
98 // XXX: Clang has a bug that prevents implicit conversion.
99 return std::unique_ptr<memory_storage_t>(storage.release());
100}
101
102} // namespace ocl
103} // namespace gpu
104} // namespace impl
105} // namespace dnnl
106