1 | /******************************************************************************* |
2 | * Copyright 2019-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 | #ifndef COMMON_MEMORY_STORAGE_HPP |
18 | #define COMMON_MEMORY_STORAGE_HPP |
19 | |
20 | #include "common/c_types_map.hpp" |
21 | #include "common/memory_desc_wrapper.hpp" |
22 | #include "common/utils.hpp" |
23 | |
24 | #include <assert.h> |
25 | |
26 | namespace dnnl { |
27 | namespace impl { |
28 | |
29 | // Memory storage is an abstraction providing interfaces to: |
30 | // - set/get the underlying data handle (in form of void pointer) |
31 | // - map/unmap the data to the host |
32 | // |
33 | // Memory storage is engine-specific and has different implementations for |
34 | // different engines. |
35 | struct memory_storage_t : public c_compatible { |
36 | memory_storage_t(engine_t *engine, const memory_storage_t *parent_storage); |
37 | memory_storage_t(engine_t *engine) : memory_storage_t(engine, this) {} |
38 | |
39 | virtual ~memory_storage_t(); |
40 | |
41 | status_t init(unsigned flags, size_t size, void *handle); |
42 | |
43 | engine_t *engine() const { return engine_; } |
44 | |
45 | void *data_handle() const { |
46 | void *handle; |
47 | status_t status = get_data_handle(&handle); |
48 | assert(status == status::success); |
49 | MAYBE_UNUSED(status); |
50 | return handle; |
51 | } |
52 | |
53 | virtual status_t get_data_handle(void **handle) const = 0; |
54 | virtual status_t set_data_handle(void *handle) = 0; |
55 | |
56 | size_t offset() const { return offset_; } |
57 | void set_offset(size_t offset) { offset_ = offset; } |
58 | |
59 | virtual size_t base_offset() const { return 0; } |
60 | |
61 | virtual status_t map_data( |
62 | void **mapped_ptr, stream_t *stream, size_t size) const = 0; |
63 | |
64 | virtual status_t unmap_data(void *mapped_ptr, stream_t *stream) const = 0; |
65 | |
66 | virtual bool is_host_accessible() const { return false; } |
67 | |
68 | /** returns slice of memory storage |
69 | * |
70 | * @note: sub-storage lifetime shall not exceed one of the base memory storage |
71 | * @note: (offset + size) shall not be greater than base memory storage size */ |
72 | virtual std::unique_ptr<memory_storage_t> get_sub_storage( |
73 | size_t offset, size_t size) const = 0; |
74 | |
75 | /** returns shallow copy */ |
76 | virtual std::unique_ptr<memory_storage_t> clone() const = 0; |
77 | |
78 | /** returns true if the pointer associated with the storage is NULL */ |
79 | bool is_null() const { |
80 | void *ptr; |
81 | status_t status = get_data_handle(&ptr); |
82 | assert(status == status::success); |
83 | MAYBE_UNUSED(status); |
84 | return !ptr; |
85 | } |
86 | |
87 | operator bool() const { return !is_null(); } |
88 | |
89 | static memory_storage_t &empty_storage(); |
90 | |
91 | protected: |
92 | virtual status_t init_allocate(size_t size) = 0; |
93 | |
94 | const memory_storage_t *parent_storage() const { return parent_storage_; } |
95 | |
96 | private: |
97 | engine_t *engine_; |
98 | size_t offset_ = 0; |
99 | |
100 | const memory_storage_t *parent_storage_; |
101 | |
102 | DNNL_DISALLOW_COPY_AND_ASSIGN(memory_storage_t); |
103 | }; |
104 | |
105 | struct empty_memory_storage_t : public memory_storage_t { |
106 | empty_memory_storage_t() : memory_storage_t(nullptr) {} |
107 | |
108 | status_t get_data_handle(void **handle) const override { |
109 | *handle = nullptr; |
110 | return status::success; |
111 | } |
112 | |
113 | status_t set_data_handle(void *handle) override { |
114 | assert(!"not expected" ); |
115 | return status::runtime_error; |
116 | } |
117 | |
118 | status_t map_data( |
119 | void **mapped_ptr, stream_t *stream, size_t size) const override { |
120 | UNUSED(mapped_ptr); |
121 | UNUSED(stream); |
122 | UNUSED(size); |
123 | return status::success; |
124 | } |
125 | |
126 | status_t unmap_data(void *mapped_ptr, stream_t *stream) const override { |
127 | UNUSED(mapped_ptr); |
128 | UNUSED(stream); |
129 | return status::success; |
130 | } |
131 | |
132 | std::unique_ptr<memory_storage_t> get_sub_storage( |
133 | size_t offset, size_t size) const override { |
134 | assert(!"not expected" ); |
135 | return nullptr; |
136 | } |
137 | |
138 | std::unique_ptr<memory_storage_t> clone() const override { |
139 | assert(!"not expected" ); |
140 | return nullptr; |
141 | } |
142 | |
143 | protected: |
144 | status_t init_allocate(size_t) override { return status::success; } |
145 | }; |
146 | |
147 | inline memory_storage_t &memory_storage_t::empty_storage() { |
148 | static empty_memory_storage_t instance; |
149 | return instance; |
150 | } |
151 | |
152 | } // namespace impl |
153 | } // namespace dnnl |
154 | |
155 | #endif |
156 | |