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
26namespace dnnl {
27namespace 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.
35struct 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
91protected:
92 virtual status_t init_allocate(size_t size) = 0;
93
94 const memory_storage_t *parent_storage() const { return parent_storage_; }
95
96private:
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
105struct 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
143protected:
144 status_t init_allocate(size_t) override { return status::success; }
145};
146
147inline 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