]>
Commit | Line | Data |
---|---|---|
9d73ec14 IV |
1 | /* Plugin for offload execution on Intel MIC devices. |
2 | ||
df26a50d | 3 | Copyright (C) 2014-2016 Free Software Foundation, Inc. |
9d73ec14 IV |
4 | |
5 | Contributed by Ilya Verbin <ilya.verbin@intel.com>. | |
6 | ||
f1f3453e TS |
7 | This file is part of the GNU Offloading and Multi Processing Library |
8 | (libgomp). | |
9d73ec14 IV |
9 | |
10 | Libgomp is free software; you can redistribute it and/or modify it | |
11 | under the terms of the GNU General Public License as published by | |
12 | the Free Software Foundation; either version 3, or (at your option) | |
13 | any later version. | |
14 | ||
15 | Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY | |
16 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
17 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
18 | more details. | |
19 | ||
20 | Under Section 7 of GPL version 3, you are granted additional | |
21 | permissions described in the GCC Runtime Library Exception, version | |
22 | 3.1, as published by the Free Software Foundation. | |
23 | ||
24 | You should have received a copy of the GNU General Public License and | |
25 | a copy of the GCC Runtime Library Exception along with this program; | |
26 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
27 | <http://www.gnu.org/licenses/>. */ | |
28 | ||
29 | /* Host side part of a libgomp plugin. */ | |
30 | ||
31 | #include <stdint.h> | |
32 | #include <stdio.h> | |
33 | #include <stdlib.h> | |
34 | #include <string.h> | |
35 | #include <utility> | |
36 | #include <vector> | |
a51df54e | 37 | #include <map> |
41dbbb37 | 38 | #include "libgomp-plugin.h" |
9d73ec14 IV |
39 | #include "compiler_if_host.h" |
40 | #include "main_target_image.h" | |
8e87588a | 41 | #include "gomp-constants.h" |
9d73ec14 | 42 | |
44799f87 | 43 | #define OFFLOAD_ACTIVE_WAIT_ENV "OFFLOAD_ACTIVE_WAIT" |
9d73ec14 IV |
44 | |
45 | #ifdef DEBUG | |
46 | #define TRACE(...) \ | |
47 | { \ | |
48 | fprintf (stderr, "HOST:\t%s:%s ", __FILE__, __FUNCTION__); \ | |
49 | fprintf (stderr, __VA_ARGS__); \ | |
50 | fprintf (stderr, "\n"); \ | |
51 | } | |
52 | #else | |
53 | #define TRACE { } | |
54 | #endif | |
55 | ||
56 | ||
a51df54e IV |
57 | /* Start/end addresses of functions and global variables on a device. */ |
58 | typedef std::vector<addr_pair> AddrVect; | |
59 | ||
60 | /* Addresses for one image and all devices. */ | |
61 | typedef std::vector<AddrVect> DevAddrVect; | |
62 | ||
63 | /* Addresses for all images and all devices. */ | |
afb2d80b | 64 | typedef std::map<const void *, DevAddrVect> ImgDevAddrMap; |
a51df54e | 65 | |
4219ddb3 IV |
66 | /* Image descriptor needed by __offload_[un]register_image. */ |
67 | struct TargetImageDesc { | |
68 | int64_t size; | |
69 | /* 10 characters is enough for max int value. */ | |
70 | char name[sizeof ("lib0000000000.so")]; | |
71 | char data[]; | |
72 | }; | |
73 | ||
74 | /* Image descriptors, indexed by a pointer obtained from libgomp. */ | |
75 | typedef std::map<const void *, TargetImageDesc *> ImgDescMap; | |
76 | ||
a51df54e IV |
77 | |
78 | /* Total number of available devices. */ | |
79 | static int num_devices; | |
80 | ||
81 | /* Total number of shared libraries with offloading to Intel MIC. */ | |
82 | static int num_images; | |
83 | ||
84 | /* Two dimensional array: one key is a pointer to image, | |
85 | second key is number of device. Contains a vector of pointer pairs. */ | |
86 | static ImgDevAddrMap *address_table; | |
87 | ||
4219ddb3 IV |
88 | /* Descriptors of all images, registered in liboffloadmic. */ |
89 | static ImgDescMap *image_descriptors; | |
90 | ||
a51df54e IV |
91 | /* Thread-safe registration of the main image. */ |
92 | static pthread_once_t main_image_is_registered = PTHREAD_ONCE_INIT; | |
93 | ||
9d73ec14 IV |
94 | static VarDesc vd_host2tgt = { |
95 | { 1, 1 }, /* dst, src */ | |
96 | { 1, 0 }, /* in, out */ | |
97 | 1, /* alloc_if */ | |
98 | 1, /* free_if */ | |
99 | 4, /* align */ | |
100 | 0, /* mic_offset */ | |
101 | { 0, 0, 0, 0, 0, 0, 0, 0 }, /* is_static, is_static_dstn, has_length, | |
102 | is_stack_buf, sink_addr, alloc_disp, | |
103 | is_noncont_src, is_noncont_dst */ | |
104 | 0, /* offset */ | |
105 | 0, /* size */ | |
106 | 1, /* count */ | |
107 | 0, /* alloc */ | |
108 | 0, /* into */ | |
109 | 0 /* ptr */ | |
110 | }; | |
111 | ||
112 | static VarDesc vd_tgt2host = { | |
113 | { 1, 1 }, /* dst, src */ | |
114 | { 0, 1 }, /* in, out */ | |
115 | 1, /* alloc_if */ | |
116 | 1, /* free_if */ | |
117 | 4, /* align */ | |
118 | 0, /* mic_offset */ | |
119 | { 0, 0, 0, 0, 0, 0, 0, 0 }, /* is_static, is_static_dstn, has_length, | |
120 | is_stack_buf, sink_addr, alloc_disp, | |
121 | is_noncont_src, is_noncont_dst */ | |
122 | 0, /* offset */ | |
123 | 0, /* size */ | |
124 | 1, /* count */ | |
125 | 0, /* alloc */ | |
126 | 0, /* into */ | |
127 | 0 /* ptr */ | |
128 | }; | |
129 | ||
130 | ||
9d73ec14 IV |
131 | __attribute__((constructor)) |
132 | static void | |
a51df54e | 133 | init (void) |
9d73ec14 | 134 | { |
44799f87 IV |
135 | const char *active_wait = getenv (OFFLOAD_ACTIVE_WAIT_ENV); |
136 | ||
137 | /* Disable active wait by default to avoid useless CPU usage. */ | |
138 | if (!active_wait) | |
139 | setenv (OFFLOAD_ACTIVE_WAIT_ENV, "0", 0); | |
9d73ec14 | 140 | |
a51df54e | 141 | address_table = new ImgDevAddrMap; |
4219ddb3 | 142 | image_descriptors = new ImgDescMap; |
a51df54e | 143 | num_devices = _Offload_number_of_devices (); |
9d73ec14 IV |
144 | } |
145 | ||
41dbbb37 TS |
146 | extern "C" const char * |
147 | GOMP_OFFLOAD_get_name (void) | |
148 | { | |
149 | const char *res = "intelmic"; | |
150 | TRACE ("(): return %s", res); | |
151 | return res; | |
152 | } | |
153 | ||
154 | extern "C" unsigned int | |
155 | GOMP_OFFLOAD_get_caps (void) | |
156 | { | |
157 | unsigned int res = GOMP_OFFLOAD_CAP_OPENMP_400; | |
158 | TRACE ("(): return %x", res); | |
159 | return res; | |
160 | } | |
161 | ||
dced339c | 162 | extern "C" int |
9d73ec14 IV |
163 | GOMP_OFFLOAD_get_type (void) |
164 | { | |
165 | enum offload_target_type res = OFFLOAD_TARGET_TYPE_INTEL_MIC; | |
166 | TRACE ("(): return %d", res); | |
167 | return res; | |
168 | } | |
169 | ||
170 | extern "C" int | |
171 | GOMP_OFFLOAD_get_num_devices (void) | |
172 | { | |
a51df54e IV |
173 | TRACE ("(): return %d", num_devices); |
174 | return num_devices; | |
9d73ec14 IV |
175 | } |
176 | ||
6c84c8bf MR |
177 | extern "C" union gomp_device_property_value |
178 | GOMP_OFFLOAD_get_property (int n, int prop) | |
179 | { | |
180 | union gomp_device_property_value nullval = { .val = 0 }; | |
181 | ||
182 | if (n >= num_devices) | |
183 | { | |
184 | GOMP_PLUGIN_error | |
185 | ("Request for a property of a non-existing Intel MIC device %i", n); | |
186 | return nullval; | |
187 | } | |
188 | ||
189 | switch (prop) | |
190 | { | |
191 | case GOMP_DEVICE_PROPERTY_VENDOR: | |
192 | return (union gomp_device_property_value) { .ptr = "Intel" }; | |
193 | default: | |
194 | return nullval; | |
195 | } | |
196 | } | |
197 | ||
6ce13072 | 198 | static bool |
9d73ec14 | 199 | offload (const char *file, uint64_t line, int device, const char *name, |
4219ddb3 | 200 | int num_vars, VarDesc *vars, const void **async_data) |
9d73ec14 IV |
201 | { |
202 | OFFLOAD ofld = __offload_target_acquire1 (&device, file, line); | |
203 | if (ofld) | |
e4606348 JJ |
204 | { |
205 | if (async_data == NULL) | |
6ce13072 CLT |
206 | return __offload_offload1 (ofld, name, 0, num_vars, vars, NULL, 0, |
207 | NULL, NULL); | |
e4606348 JJ |
208 | else |
209 | { | |
210 | OffloadFlags flags; | |
211 | flags.flags = 0; | |
212 | flags.bits.omp_async = 1; | |
6ce13072 CLT |
213 | return __offload_offload3 (ofld, name, 0, num_vars, vars, NULL, 0, |
214 | NULL, async_data, 0, NULL, flags, NULL); | |
e4606348 JJ |
215 | } |
216 | } | |
9d73ec14 IV |
217 | else |
218 | { | |
6ce13072 CLT |
219 | GOMP_PLUGIN_error ("%s:%d: Offload target acquire failed\n", file, line); |
220 | return false; | |
9d73ec14 IV |
221 | } |
222 | } | |
223 | ||
224 | static void | |
225 | register_main_image () | |
226 | { | |
4219ddb3 IV |
227 | /* Do not check the return value, because old versions of liboffloadmic did |
228 | not have return values. */ | |
9d73ec14 | 229 | __offload_register_image (&main_target_image); |
e4606348 JJ |
230 | |
231 | /* liboffloadmic will call GOMP_PLUGIN_target_task_completion when | |
232 | asynchronous task on target is completed. */ | |
233 | __offload_register_task_callback (GOMP_PLUGIN_target_task_completion); | |
9d73ec14 IV |
234 | } |
235 | ||
a51df54e IV |
236 | /* liboffloadmic loads and runs offload_target_main on all available devices |
237 | during a first call to offload (). */ | |
6ce13072 | 238 | extern "C" bool |
9d73ec14 IV |
239 | GOMP_OFFLOAD_init_device (int device) |
240 | { | |
4219ddb3 | 241 | TRACE ("(device = %d)", device); |
9d73ec14 | 242 | pthread_once (&main_image_is_registered, register_main_image); |
6ce13072 CLT |
243 | return offload (__FILE__, __LINE__, device, "__offload_target_init_proc", 0, |
244 | NULL, NULL); | |
9d73ec14 IV |
245 | } |
246 | ||
6ce13072 | 247 | extern "C" bool |
41dbbb37 TS |
248 | GOMP_OFFLOAD_fini_device (int device) |
249 | { | |
4219ddb3 | 250 | TRACE ("(device = %d)", device); |
d84ffc0a IV |
251 | |
252 | /* liboffloadmic will finalize target processes on all available devices. */ | |
253 | __offload_unregister_image (&main_target_image); | |
6ce13072 | 254 | return true; |
41dbbb37 TS |
255 | } |
256 | ||
6ce13072 | 257 | static bool |
9d73ec14 IV |
258 | get_target_table (int device, int &num_funcs, int &num_vars, void **&table) |
259 | { | |
260 | VarDesc vd1[2] = { vd_tgt2host, vd_tgt2host }; | |
261 | vd1[0].ptr = &num_funcs; | |
262 | vd1[0].size = sizeof (num_funcs); | |
263 | vd1[1].ptr = &num_vars; | |
264 | vd1[1].size = sizeof (num_vars); | |
9d73ec14 | 265 | |
6ce13072 CLT |
266 | if (!offload (__FILE__, __LINE__, device, "__offload_target_table_p1", 2, |
267 | vd1, NULL)) | |
268 | return false; | |
9d73ec14 IV |
269 | |
270 | int table_size = num_funcs + 2 * num_vars; | |
271 | if (table_size > 0) | |
272 | { | |
273 | table = new void * [table_size]; | |
274 | ||
275 | VarDesc vd2; | |
276 | vd2 = vd_tgt2host; | |
277 | vd2.ptr = table; | |
278 | vd2.size = table_size * sizeof (void *); | |
9d73ec14 | 279 | |
6ce13072 CLT |
280 | return offload (__FILE__, __LINE__, device, "__offload_target_table_p2", |
281 | 1, &vd2, NULL); | |
9d73ec14 | 282 | } |
6ce13072 | 283 | return true; |
9d73ec14 IV |
284 | } |
285 | ||
a51df54e IV |
286 | /* Offload TARGET_IMAGE to all available devices and fill address_table with |
287 | corresponding target addresses. */ | |
288 | ||
6ce13072 | 289 | static bool |
afb2d80b | 290 | offload_image (const void *target_image) |
9d73ec14 | 291 | { |
a51df54e IV |
292 | void *image_start = ((void **) target_image)[0]; |
293 | void *image_end = ((void **) target_image)[1]; | |
9d73ec14 | 294 | |
a51df54e IV |
295 | TRACE ("(target_image = %p { %p, %p })", |
296 | target_image, image_start, image_end); | |
9d73ec14 IV |
297 | |
298 | int64_t image_size = (uintptr_t) image_end - (uintptr_t) image_start; | |
4219ddb3 IV |
299 | TargetImageDesc *image = (TargetImageDesc *) malloc (offsetof (TargetImageDesc, data) |
300 | + image_size); | |
9d73ec14 IV |
301 | if (!image) |
302 | { | |
6ce13072 CLT |
303 | GOMP_PLUGIN_error ("%s: Can't allocate memory\n", __FILE__); |
304 | return false; | |
9d73ec14 IV |
305 | } |
306 | ||
307 | image->size = image_size; | |
a51df54e | 308 | sprintf (image->name, "lib%010d.so", num_images++); |
9d73ec14 IV |
309 | memcpy (image->data, image_start, image->size); |
310 | ||
311 | TRACE ("() __offload_register_image %s { %p, %d }", | |
312 | image->name, image_start, image->size); | |
4219ddb3 IV |
313 | /* Do not check the return value, because old versions of liboffloadmic did |
314 | not have return values. */ | |
9d73ec14 IV |
315 | __offload_register_image (image); |
316 | ||
a51df54e IV |
317 | /* Receive tables for target_image from all devices. */ |
318 | DevAddrVect dev_table; | |
6ce13072 | 319 | bool ret = true; |
a51df54e | 320 | for (int dev = 0; dev < num_devices; dev++) |
9d73ec14 | 321 | { |
a51df54e IV |
322 | int num_funcs = 0; |
323 | int num_vars = 0; | |
324 | void **table = NULL; | |
9d73ec14 | 325 | |
6ce13072 | 326 | ret &= get_target_table (dev, num_funcs, num_vars, table); |
9d73ec14 | 327 | |
a51df54e | 328 | AddrVect curr_dev_table; |
9d73ec14 | 329 | |
a51df54e IV |
330 | for (int i = 0; i < num_funcs; i++) |
331 | { | |
332 | addr_pair tgt_addr; | |
333 | tgt_addr.start = (uintptr_t) table[i]; | |
334 | tgt_addr.end = tgt_addr.start + 1; | |
335 | TRACE ("() func %d:\t0x%llx..0x%llx", i, | |
336 | tgt_addr.start, tgt_addr.end); | |
337 | curr_dev_table.push_back (tgt_addr); | |
338 | } | |
9d73ec14 | 339 | |
a51df54e IV |
340 | for (int i = 0; i < num_vars; i++) |
341 | { | |
342 | addr_pair tgt_addr; | |
343 | tgt_addr.start = (uintptr_t) table[num_funcs+i*2]; | |
344 | tgt_addr.end = tgt_addr.start + (uintptr_t) table[num_funcs+i*2+1]; | |
345 | TRACE ("() var %d:\t0x%llx..0x%llx", i, tgt_addr.start, tgt_addr.end); | |
346 | curr_dev_table.push_back (tgt_addr); | |
347 | } | |
9d73ec14 | 348 | |
a51df54e | 349 | dev_table.push_back (curr_dev_table); |
4219ddb3 | 350 | delete [] table; |
9d73ec14 IV |
351 | } |
352 | ||
a51df54e | 353 | address_table->insert (std::make_pair (target_image, dev_table)); |
4219ddb3 | 354 | image_descriptors->insert (std::make_pair (target_image, image)); |
6ce13072 | 355 | return ret; |
9d73ec14 IV |
356 | } |
357 | ||
2a21ff19 NS |
358 | /* Return the libgomp version number we're compatible with. There is |
359 | no requirement for cross-version compatibility. */ | |
360 | ||
361 | extern "C" unsigned | |
362 | GOMP_OFFLOAD_version (void) | |
363 | { | |
364 | return GOMP_VERSION; | |
365 | } | |
366 | ||
9d73ec14 | 367 | extern "C" int |
2a21ff19 | 368 | GOMP_OFFLOAD_load_image (int device, const unsigned version, |
dced339c | 369 | const void *target_image, addr_pair **result) |
9d73ec14 | 370 | { |
a51df54e | 371 | TRACE ("(device = %d, target_image = %p)", device, target_image); |
9d73ec14 | 372 | |
2a21ff19 | 373 | if (GOMP_VERSION_DEV (version) > GOMP_VERSION_INTEL_MIC) |
6ce13072 CLT |
374 | { |
375 | GOMP_PLUGIN_error ("Offload data incompatible with intelmic plugin" | |
376 | " (expected %u, received %u)", | |
377 | GOMP_VERSION_INTEL_MIC, GOMP_VERSION_DEV (version)); | |
378 | return -1; | |
379 | } | |
2a21ff19 | 380 | |
a51df54e IV |
381 | /* If target_image is already present in address_table, then there is no need |
382 | to offload it. */ | |
383 | if (address_table->count (target_image) == 0) | |
6ce13072 CLT |
384 | { |
385 | /* If fail, return -1 as error code. */ | |
386 | if (!offload_image (target_image)) | |
387 | return -1; | |
388 | } | |
9d73ec14 | 389 | |
a51df54e IV |
390 | AddrVect *curr_dev_table = &(*address_table)[target_image][device]; |
391 | int table_size = curr_dev_table->size (); | |
392 | addr_pair *table = (addr_pair *) malloc (table_size * sizeof (addr_pair)); | |
393 | if (table == NULL) | |
394 | { | |
6ce13072 CLT |
395 | GOMP_PLUGIN_error ("%s: Can't allocate memory\n", __FILE__); |
396 | return -1; | |
a51df54e | 397 | } |
9d73ec14 | 398 | |
a51df54e IV |
399 | std::copy (curr_dev_table->begin (), curr_dev_table->end (), table); |
400 | *result = table; | |
9d73ec14 IV |
401 | return table_size; |
402 | } | |
403 | ||
6ce13072 | 404 | extern "C" bool |
2a21ff19 NS |
405 | GOMP_OFFLOAD_unload_image (int device, unsigned version, |
406 | const void *target_image) | |
a51df54e | 407 | { |
2a21ff19 | 408 | if (GOMP_VERSION_DEV (version) > GOMP_VERSION_INTEL_MIC) |
6ce13072 CLT |
409 | { |
410 | GOMP_PLUGIN_error ("Offload data incompatible with intelmic plugin" | |
411 | " (expected %u, received %u)", | |
412 | GOMP_VERSION_INTEL_MIC, GOMP_VERSION_DEV (version)); | |
413 | return false; | |
414 | } | |
2a21ff19 | 415 | |
a51df54e IV |
416 | TRACE ("(device = %d, target_image = %p)", device, target_image); |
417 | ||
4219ddb3 IV |
418 | /* liboffloadmic unloads the image from all available devices. */ |
419 | if (image_descriptors->count (target_image) > 0) | |
420 | { | |
421 | TargetImageDesc *image_desc = (*image_descriptors)[target_image]; | |
422 | __offload_unregister_image (image_desc); | |
423 | free (image_desc); | |
a51df54e | 424 | |
4219ddb3 IV |
425 | address_table->erase (target_image); |
426 | image_descriptors->erase (target_image); | |
427 | } | |
6ce13072 | 428 | return true; |
a51df54e IV |
429 | } |
430 | ||
9d73ec14 IV |
431 | extern "C" void * |
432 | GOMP_OFFLOAD_alloc (int device, size_t size) | |
433 | { | |
4219ddb3 | 434 | TRACE ("(device = %d, size = %d)", device, size); |
9d73ec14 IV |
435 | |
436 | void *tgt_ptr; | |
4219ddb3 IV |
437 | VarDesc vd[2] = { vd_host2tgt, vd_tgt2host }; |
438 | vd[0].ptr = &size; | |
439 | vd[0].size = sizeof (size); | |
440 | vd[1].ptr = &tgt_ptr; | |
441 | vd[1].size = sizeof (void *); | |
442 | ||
6ce13072 CLT |
443 | if (!offload (__FILE__, __LINE__, device, "__offload_target_alloc", 2, |
444 | vd, NULL)) | |
445 | return NULL; | |
4219ddb3 | 446 | |
9d73ec14 IV |
447 | return tgt_ptr; |
448 | } | |
449 | ||
6ce13072 | 450 | extern "C" bool |
9d73ec14 IV |
451 | GOMP_OFFLOAD_free (int device, void *tgt_ptr) |
452 | { | |
4219ddb3 | 453 | TRACE ("(device = %d, tgt_ptr = %p)", device, tgt_ptr); |
9d73ec14 | 454 | |
4219ddb3 IV |
455 | VarDesc vd = vd_host2tgt; |
456 | vd.ptr = &tgt_ptr; | |
457 | vd.size = sizeof (void *); | |
9d73ec14 | 458 | |
6ce13072 CLT |
459 | return offload (__FILE__, __LINE__, device, "__offload_target_free", 1, |
460 | &vd, NULL); | |
9d73ec14 IV |
461 | } |
462 | ||
6ce13072 | 463 | extern "C" bool |
9d73ec14 IV |
464 | GOMP_OFFLOAD_host2dev (int device, void *tgt_ptr, const void *host_ptr, |
465 | size_t size) | |
466 | { | |
4219ddb3 IV |
467 | TRACE ("(device = %d, tgt_ptr = %p, host_ptr = %p, size = %d)", |
468 | device, tgt_ptr, host_ptr, size); | |
9d73ec14 | 469 | if (!size) |
6ce13072 | 470 | return true; |
9d73ec14 IV |
471 | |
472 | VarDesc vd1[2] = { vd_host2tgt, vd_host2tgt }; | |
473 | vd1[0].ptr = &tgt_ptr; | |
474 | vd1[0].size = sizeof (void *); | |
475 | vd1[1].ptr = &size; | |
476 | vd1[1].size = sizeof (size); | |
9d73ec14 | 477 | |
6ce13072 CLT |
478 | if (!offload (__FILE__, __LINE__, device, "__offload_target_host2tgt_p1", 2, |
479 | vd1, NULL)) | |
480 | return false; | |
9d73ec14 IV |
481 | |
482 | VarDesc vd2 = vd_host2tgt; | |
483 | vd2.ptr = (void *) host_ptr; | |
484 | vd2.size = size; | |
9d73ec14 | 485 | |
6ce13072 CLT |
486 | return offload (__FILE__, __LINE__, device, "__offload_target_host2tgt_p2", 1, |
487 | &vd2, NULL); | |
9d73ec14 IV |
488 | } |
489 | ||
6ce13072 | 490 | extern "C" bool |
9d73ec14 IV |
491 | GOMP_OFFLOAD_dev2host (int device, void *host_ptr, const void *tgt_ptr, |
492 | size_t size) | |
493 | { | |
4219ddb3 IV |
494 | TRACE ("(device = %d, host_ptr = %p, tgt_ptr = %p, size = %d)", |
495 | device, host_ptr, tgt_ptr, size); | |
9d73ec14 | 496 | if (!size) |
6ce13072 | 497 | return true; |
9d73ec14 IV |
498 | |
499 | VarDesc vd1[2] = { vd_host2tgt, vd_host2tgt }; | |
500 | vd1[0].ptr = &tgt_ptr; | |
501 | vd1[0].size = sizeof (void *); | |
502 | vd1[1].ptr = &size; | |
503 | vd1[1].size = sizeof (size); | |
9d73ec14 | 504 | |
6ce13072 CLT |
505 | if (!offload (__FILE__, __LINE__, device, "__offload_target_tgt2host_p1", 2, |
506 | vd1, NULL)) | |
507 | return false; | |
9d73ec14 IV |
508 | |
509 | VarDesc vd2 = vd_tgt2host; | |
510 | vd2.ptr = (void *) host_ptr; | |
511 | vd2.size = size; | |
9d73ec14 | 512 | |
6ce13072 CLT |
513 | return offload (__FILE__, __LINE__, device, "__offload_target_tgt2host_p2", 1, |
514 | &vd2, NULL); | |
9d73ec14 IV |
515 | } |
516 | ||
6ce13072 | 517 | extern "C" bool |
d9a6bd32 JJ |
518 | GOMP_OFFLOAD_dev2dev (int device, void *dst_ptr, const void *src_ptr, |
519 | size_t size) | |
520 | { | |
4219ddb3 IV |
521 | TRACE ("(device = %d, dst_ptr = %p, src_ptr = %p, size = %d)", |
522 | device, dst_ptr, src_ptr, size); | |
d9a6bd32 | 523 | if (!size) |
6ce13072 | 524 | return true; |
d9a6bd32 | 525 | |
4219ddb3 IV |
526 | VarDesc vd[3] = { vd_host2tgt, vd_host2tgt, vd_host2tgt }; |
527 | vd[0].ptr = &dst_ptr; | |
528 | vd[0].size = sizeof (void *); | |
529 | vd[1].ptr = &src_ptr; | |
530 | vd[1].size = sizeof (void *); | |
531 | vd[2].ptr = &size; | |
532 | vd[2].size = sizeof (size); | |
d9a6bd32 | 533 | |
6ce13072 CLT |
534 | return offload (__FILE__, __LINE__, device, "__offload_target_tgt2tgt", 3, |
535 | vd, NULL); | |
d9a6bd32 JJ |
536 | } |
537 | ||
9d73ec14 | 538 | extern "C" void |
e4606348 | 539 | GOMP_OFFLOAD_async_run (int device, void *tgt_fn, void *tgt_vars, |
b2b40051 | 540 | void **, void *async_data) |
9d73ec14 | 541 | { |
e4606348 JJ |
542 | TRACE ("(device = %d, tgt_fn = %p, tgt_vars = %p, async_data = %p)", device, |
543 | tgt_fn, tgt_vars, async_data); | |
9d73ec14 | 544 | |
e4606348 JJ |
545 | VarDesc vd[2] = { vd_host2tgt, vd_host2tgt }; |
546 | vd[0].ptr = &tgt_fn; | |
547 | vd[0].size = sizeof (void *); | |
548 | vd[1].ptr = &tgt_vars; | |
549 | vd[1].size = sizeof (void *); | |
550 | ||
4219ddb3 | 551 | offload (__FILE__, __LINE__, device, "__offload_target_run", 2, vd, |
e4606348 JJ |
552 | (const void **) async_data); |
553 | } | |
554 | ||
555 | extern "C" void | |
b2b40051 | 556 | GOMP_OFFLOAD_run (int device, void *tgt_fn, void *tgt_vars, void **) |
e4606348 JJ |
557 | { |
558 | TRACE ("(device = %d, tgt_fn = %p, tgt_vars = %p)", device, tgt_fn, tgt_vars); | |
9d73ec14 | 559 | |
23a80f4d | 560 | GOMP_OFFLOAD_async_run (device, tgt_fn, tgt_vars, NULL, NULL); |
9d73ec14 | 561 | } |