]> git.ipfire.org Git - thirdparty/gcc.git/blob - liboffloadmic/runtime/offload_table.h
cc4caad47a156725d93de6329b81a73a317cc0c9
[thirdparty/gcc.git] / liboffloadmic / runtime / offload_table.h
1 /*
2 Copyright (c) 2014 Intel Corporation. All Rights Reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30
31 /*! \file
32 \brief Function and Variable tables used by the runtime library
33 */
34
35 #ifndef OFFLOAD_TABLE_H_INCLUDED
36 #define OFFLOAD_TABLE_H_INCLUDED
37
38 #include <iterator>
39 #include "offload_util.h"
40
41 // Template representing double linked list of tables
42 template <typename T> class TableList {
43 public:
44 // table type
45 typedef T Table;
46
47 // List node
48 struct Node {
49 Table table;
50 Node* prev;
51 Node* next;
52 };
53
54 public:
55 explicit TableList(Node *node = 0) : m_head(node) {}
56
57 void add_table(Node *node) {
58 m_lock.lock();
59
60 if (m_head != 0) {
61 node->next = m_head;
62 m_head->prev = node;
63 }
64 m_head = node;
65
66 m_lock.unlock();
67 }
68
69 void remove_table(Node *node) {
70 m_lock.lock();
71
72 if (node->next != 0) {
73 node->next->prev = node->prev;
74 }
75 if (node->prev != 0) {
76 node->prev->next = node->next;
77 }
78 if (m_head == node) {
79 m_head = node->next;
80 }
81
82 m_lock.unlock();
83 }
84
85 protected:
86 Node* m_head;
87 mutex_t m_lock;
88 };
89
90 // Function lookup table.
91 struct FuncTable {
92 //! Function table entry
93 /*! This table contains functions created from offload regions. */
94 /*! Each entry consists of a pointer to the function's "key"
95 and the function address. */
96 /*! Each shared library or executable may contain one such table. */
97 /*! The end of the table is marked with an entry whose name field
98 has value -1. */
99 struct Entry {
100 const char* name; //!< Name of the function
101 void* func; //!< Address of the function
102 };
103
104 // entries
105 const Entry *entries;
106
107 // max name length
108 int64_t max_name_len;
109 };
110
111 // Function table
112 class FuncList : public TableList<FuncTable> {
113 public:
114 explicit FuncList(Node *node = 0) : TableList<Table>(node),
115 m_max_name_len(-1)
116 {}
117
118 // add table to the list
119 void add_table(Node *node) {
120 // recalculate max function name length
121 m_max_name_len = -1;
122
123 // add table
124 TableList<Table>::add_table(node);
125 }
126
127 // find function address for the given name
128 const void* find_addr(const char *name);
129
130 // find function name for the given address
131 const char* find_name(const void *addr);
132
133 // max name length from all tables in the list
134 int64_t max_name_length(void);
135
136 // debug dump
137 void dump(void);
138
139 private:
140 // max name length within from all tables
141 int64_t m_max_name_len;
142 };
143
144 // Table entry for static variables
145 struct VarTable {
146 //! Variable table entry
147 /*! This table contains statically allocated variables marked with
148 __declspec(target(mic) or #pragma omp declare target. */
149 /*! Each entry consists of a pointer to the variable's "key",
150 the variable address and its size in bytes. */
151 /*! Because memory allocation is done from the host,
152 the MIC table does not need the size of the variable. */
153 /*! Padding to make the table entry size a power of 2 is necessary
154 to avoid "holes" between table contributions from different object
155 files on Windows when debug information is specified with /Zi. */
156 struct Entry {
157 const char* name; //!< Name of the variable
158 void* addr; //!< Address of the variable
159
160 #if HOST_LIBRARY
161 uint64_t size;
162
163 #ifdef TARGET_WINNT
164 // padding to make entry size a power of 2
165 uint64_t padding;
166 #endif // TARGET_WINNT
167 #endif
168 };
169
170 // Table terminated by an entry with name == -1
171 const Entry *entries;
172 };
173
174 // List of var tables
175 class VarList : public TableList<VarTable> {
176 public:
177 VarList() : TableList<Table>()
178 {}
179
180 // debug dump
181 void dump();
182
183 public:
184 // var table list iterator
185 class Iterator : public std::iterator<std::input_iterator_tag,
186 Table::Entry> {
187 public:
188 Iterator() : m_node(0), m_entry(0) {}
189
190 explicit Iterator(Node *node) {
191 new_node(node);
192 }
193
194 Iterator& operator++() {
195 if (m_entry != 0) {
196 m_entry++;
197 while (m_entry->name == 0) {
198 m_entry++;
199 }
200 if (m_entry->name == reinterpret_cast<const char*>(-1)) {
201 new_node(m_node->next);
202 }
203 }
204 return *this;
205 }
206
207 bool operator==(const Iterator &other) const {
208 return m_entry == other.m_entry;
209 }
210
211 bool operator!=(const Iterator &other) const {
212 return m_entry != other.m_entry;
213 }
214
215 const Table::Entry* operator*() const {
216 return m_entry;
217 }
218
219 private:
220 void new_node(Node *node) {
221 m_node = node;
222 m_entry = 0;
223 while (m_node != 0) {
224 m_entry = m_node->table.entries;
225 while (m_entry->name == 0) {
226 m_entry++;
227 }
228 if (m_entry->name != reinterpret_cast<const char*>(-1)) {
229 break;
230 }
231 m_node = m_node->next;
232 m_entry = 0;
233 }
234 }
235
236 private:
237 Node *m_node;
238 const Table::Entry *m_entry;
239 };
240
241 Iterator begin() const {
242 return Iterator(m_head);
243 }
244
245 Iterator end() const {
246 return Iterator();
247 }
248
249 public:
250 // Entry representation in a copy buffer
251 struct BufEntry {
252 intptr_t name;
253 intptr_t addr;
254 };
255
256 // Calculate the number of elements in the table and
257 // returns the size of buffer for the table
258 int64_t table_size(int64_t &nelems);
259
260 // Copy table contents to given buffer. It is supposed to be large
261 // enough to hold all elements as string table.
262 void table_copy(void *buf, int64_t nelems);
263
264 // Patch name offsets in a table after it's been copied to other side
265 static void table_patch_names(void *buf, int64_t nelems);
266 };
267
268 extern FuncList __offload_entries;
269 extern FuncList __offload_funcs;
270 extern VarList __offload_vars;
271
272 // Section names where the lookup tables are stored
273 #ifdef TARGET_WINNT
274 #define OFFLOAD_ENTRY_TABLE_SECTION_START ".OffloadEntryTable$a"
275 #define OFFLOAD_ENTRY_TABLE_SECTION_END ".OffloadEntryTable$z"
276
277 #define OFFLOAD_FUNC_TABLE_SECTION_START ".OffloadFuncTable$a"
278 #define OFFLOAD_FUNC_TABLE_SECTION_END ".OffloadFuncTable$z"
279
280 #define OFFLOAD_VAR_TABLE_SECTION_START ".OffloadVarTable$a"
281 #define OFFLOAD_VAR_TABLE_SECTION_END ".OffloadVarTable$z"
282
283 #define OFFLOAD_CRTINIT_SECTION_START ".CRT$XCT"
284
285 #pragma section(OFFLOAD_CRTINIT_SECTION_START, read)
286
287 #else // TARGET_WINNT
288
289 #define OFFLOAD_ENTRY_TABLE_SECTION_START ".OffloadEntryTable."
290 #define OFFLOAD_ENTRY_TABLE_SECTION_END ".OffloadEntryTable."
291
292 #define OFFLOAD_FUNC_TABLE_SECTION_START ".OffloadFuncTable."
293 #define OFFLOAD_FUNC_TABLE_SECTION_END ".OffloadFuncTable."
294
295 #define OFFLOAD_VAR_TABLE_SECTION_START ".OffloadVarTable."
296 #define OFFLOAD_VAR_TABLE_SECTION_END ".OffloadVarTable."
297 #endif // TARGET_WINNT
298
299 #pragma section(OFFLOAD_ENTRY_TABLE_SECTION_START, read, write)
300 #pragma section(OFFLOAD_ENTRY_TABLE_SECTION_END, read, write)
301
302 #pragma section(OFFLOAD_FUNC_TABLE_SECTION_START, read, write)
303 #pragma section(OFFLOAD_FUNC_TABLE_SECTION_END, read, write)
304
305 #pragma section(OFFLOAD_VAR_TABLE_SECTION_START, read, write)
306 #pragma section(OFFLOAD_VAR_TABLE_SECTION_END, read, write)
307
308
309 // register/unregister given tables
310 extern "C" void __offload_register_tables(
311 FuncList::Node *entry_table,
312 FuncList::Node *func_table,
313 VarList::Node *var_table
314 );
315
316 extern "C" void __offload_unregister_tables(
317 FuncList::Node *entry_table,
318 FuncList::Node *func_table,
319 VarList::Node *var_table
320 );
321 #endif // OFFLOAD_TABLE_H_INCLUDED