Daily bump.
[gcc.git] / libgomp / oacc-parallel.c
1 /* Copyright (C) 2013-2021 Free Software Foundation, Inc.
2
3 Contributed by Mentor Embedded.
4
5 This file is part of the GNU Offloading and Multi Processing Library
6 (libgomp).
7
8 Libgomp is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 more details.
17
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
21
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
26
27 /* This file handles OpenACC constructs. */
28
29 #include "openacc.h"
30 #include "libgomp.h"
31 #include "gomp-constants.h"
32 #include "oacc-int.h"
33 #ifdef HAVE_INTTYPES_H
34 # include <inttypes.h> /* For PRIu64. */
35 #endif
36 #include <string.h>
37 #include <stdarg.h>
38 #include <assert.h>
39
40
41 /* In the ABI, the GOACC_FLAGs are encoded as an inverted bitmask, so that we
42 continue to support the following two legacy values. */
43 _Static_assert (GOACC_FLAGS_UNMARSHAL (GOMP_DEVICE_ICV) == 0,
44 "legacy GOMP_DEVICE_ICV broken");
45 _Static_assert (GOACC_FLAGS_UNMARSHAL (GOMP_DEVICE_HOST_FALLBACK)
46 == GOACC_FLAG_HOST_FALLBACK,
47 "legacy GOMP_DEVICE_HOST_FALLBACK broken");
48
49
50 /* Handle the mapping pair that are presented when a
51 deviceptr clause is used with Fortran. */
52
53 static void
54 handle_ftn_pointers (size_t mapnum, void **hostaddrs, size_t *sizes,
55 unsigned short *kinds)
56 {
57 int i;
58
59 for (i = 0; i < mapnum; i++)
60 {
61 unsigned short kind1 = kinds[i] & 0xff;
62
63 /* Handle Fortran deviceptr clause. */
64 if (kind1 == GOMP_MAP_FORCE_DEVICEPTR)
65 {
66 unsigned short kind2;
67
68 if (i < (signed)mapnum - 1)
69 kind2 = kinds[i + 1] & 0xff;
70 else
71 kind2 = 0xffff;
72
73 if (sizes[i] == sizeof (void *))
74 continue;
75
76 /* At this point, we're dealing with a Fortran deviceptr.
77 If the next element is not what we're expecting, then
78 this is an instance of where the deviceptr variable was
79 not used within the region and the pointer was removed
80 by the gimplifier. */
81 if (kind2 == GOMP_MAP_POINTER
82 && sizes[i + 1] == 0
83 && hostaddrs[i] == *(void **)hostaddrs[i + 1])
84 {
85 kinds[i+1] = kinds[i];
86 sizes[i+1] = sizeof (void *);
87 }
88
89 /* Invalidate the entry. */
90 hostaddrs[i] = NULL;
91 }
92 }
93 }
94
95
96 /* Launch a possibly offloaded function with FLAGS. FN is the host fn
97 address. MAPNUM, HOSTADDRS, SIZES & KINDS describe the memory
98 blocks to be copied to/from the device. Varadic arguments are
99 keyed optional parameters terminated with a zero. */
100
101 void
102 GOACC_parallel_keyed (int flags_m, void (*fn) (void *),
103 size_t mapnum, void **hostaddrs, size_t *sizes,
104 unsigned short *kinds, ...)
105 {
106 int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
107
108 va_list ap;
109 struct goacc_thread *thr;
110 struct gomp_device_descr *acc_dev;
111 struct target_mem_desc *tgt;
112 void **devaddrs;
113 unsigned int i;
114 struct splay_tree_key_s k;
115 splay_tree_key tgt_fn_key;
116 void (*tgt_fn);
117 int async = GOMP_ASYNC_SYNC;
118 unsigned dims[GOMP_DIM_MAX];
119 unsigned tag;
120
121 #ifdef HAVE_INTTYPES_H
122 gomp_debug (0, "%s: mapnum=%"PRIu64", hostaddrs=%p, size=%p, kinds=%p\n",
123 __FUNCTION__, (uint64_t) mapnum, hostaddrs, sizes, kinds);
124 #else
125 gomp_debug (0, "%s: mapnum=%lu, hostaddrs=%p, sizes=%p, kinds=%p\n",
126 __FUNCTION__, (unsigned long) mapnum, hostaddrs, sizes, kinds);
127 #endif
128 goacc_lazy_initialize ();
129
130 thr = goacc_thread ();
131 acc_dev = thr->dev;
132
133 bool profiling_p = GOACC_PROFILING_DISPATCH_P (true);
134
135 acc_prof_info prof_info;
136 if (profiling_p)
137 {
138 thr->prof_info = &prof_info;
139
140 prof_info.event_type = acc_ev_compute_construct_start;
141 prof_info.valid_bytes = _ACC_PROF_INFO_VALID_BYTES;
142 prof_info.version = _ACC_PROF_INFO_VERSION;
143 prof_info.device_type = acc_device_type (acc_dev->type);
144 prof_info.device_number = acc_dev->target_id;
145 prof_info.thread_id = -1;
146 prof_info.async = async;
147 prof_info.async_queue = prof_info.async;
148 prof_info.src_file = NULL;
149 prof_info.func_name = NULL;
150 prof_info.line_no = -1;
151 prof_info.end_line_no = -1;
152 prof_info.func_line_no = -1;
153 prof_info.func_end_line_no = -1;
154 }
155 acc_event_info compute_construct_event_info;
156 if (profiling_p)
157 {
158 compute_construct_event_info.other_event.event_type
159 = prof_info.event_type;
160 compute_construct_event_info.other_event.valid_bytes
161 = _ACC_OTHER_EVENT_INFO_VALID_BYTES;
162 compute_construct_event_info.other_event.parent_construct
163 = acc_construct_parallel;
164 compute_construct_event_info.other_event.implicit = 0;
165 compute_construct_event_info.other_event.tool_info = NULL;
166 }
167 acc_api_info api_info;
168 if (profiling_p)
169 {
170 thr->api_info = &api_info;
171
172 api_info.device_api = acc_device_api_none;
173 api_info.valid_bytes = _ACC_API_INFO_VALID_BYTES;
174 api_info.device_type = prof_info.device_type;
175 api_info.vendor = -1;
176 api_info.device_handle = NULL;
177 api_info.context_handle = NULL;
178 api_info.async_handle = NULL;
179 }
180
181 if (profiling_p)
182 goacc_profiling_dispatch (&prof_info, &compute_construct_event_info,
183 &api_info);
184
185 handle_ftn_pointers (mapnum, hostaddrs, sizes, kinds);
186
187 /* Host fallback if "if" clause is false or if the current device is set to
188 the host. */
189 if (flags & GOACC_FLAG_HOST_FALLBACK)
190 {
191 prof_info.device_type = acc_device_host;
192 api_info.device_type = prof_info.device_type;
193 goacc_save_and_set_bind (acc_device_host);
194 fn (hostaddrs);
195 goacc_restore_bind ();
196 goto out_prof;
197 }
198 else if (acc_device_type (acc_dev->type) == acc_device_host)
199 {
200 fn (hostaddrs);
201 goto out_prof;
202 }
203
204 /* Default: let the runtime choose. */
205 for (i = 0; i != GOMP_DIM_MAX; i++)
206 dims[i] = 0;
207
208 va_start (ap, kinds);
209 /* TODO: This will need amending when device_type is implemented. */
210 while ((tag = va_arg (ap, unsigned)) != 0)
211 {
212 if (GOMP_LAUNCH_DEVICE (tag))
213 gomp_fatal ("device_type '%d' offload parameters, libgomp is too old",
214 GOMP_LAUNCH_DEVICE (tag));
215
216 switch (GOMP_LAUNCH_CODE (tag))
217 {
218 case GOMP_LAUNCH_DIM:
219 {
220 unsigned mask = GOMP_LAUNCH_OP (tag);
221
222 for (i = 0; i != GOMP_DIM_MAX; i++)
223 if (mask & GOMP_DIM_MASK (i))
224 dims[i] = va_arg (ap, unsigned);
225 }
226 break;
227
228 case GOMP_LAUNCH_ASYNC:
229 {
230 /* Small constant values are encoded in the operand. */
231 async = GOMP_LAUNCH_OP (tag);
232
233 if (async == GOMP_LAUNCH_OP_MAX)
234 async = va_arg (ap, unsigned);
235
236 if (profiling_p)
237 {
238 prof_info.async = async;
239 prof_info.async_queue = prof_info.async;
240 }
241
242 break;
243 }
244
245 case GOMP_LAUNCH_WAIT:
246 {
247 unsigned num_waits = GOMP_LAUNCH_OP (tag);
248 goacc_wait (async, num_waits, &ap);
249 break;
250 }
251
252 default:
253 gomp_fatal ("unrecognized offload code '%d',"
254 " libgomp is too old", GOMP_LAUNCH_CODE (tag));
255 }
256 }
257 va_end (ap);
258
259 if (!(acc_dev->capabilities & GOMP_OFFLOAD_CAP_NATIVE_EXEC))
260 {
261 k.host_start = (uintptr_t) fn;
262 k.host_end = k.host_start + 1;
263 gomp_mutex_lock (&acc_dev->lock);
264 tgt_fn_key = splay_tree_lookup (&acc_dev->mem_map, &k);
265 gomp_mutex_unlock (&acc_dev->lock);
266
267 if (tgt_fn_key == NULL)
268 gomp_fatal ("target function wasn't mapped");
269
270 tgt_fn = (void (*)) tgt_fn_key->tgt_offset;
271 }
272 else
273 tgt_fn = (void (*)) fn;
274
275 acc_event_info enter_exit_data_event_info;
276 if (profiling_p)
277 {
278 prof_info.event_type = acc_ev_enter_data_start;
279 enter_exit_data_event_info.other_event.event_type
280 = prof_info.event_type;
281 enter_exit_data_event_info.other_event.valid_bytes
282 = _ACC_OTHER_EVENT_INFO_VALID_BYTES;
283 enter_exit_data_event_info.other_event.parent_construct
284 = compute_construct_event_info.other_event.parent_construct;
285 enter_exit_data_event_info.other_event.implicit = 1;
286 enter_exit_data_event_info.other_event.tool_info = NULL;
287 goacc_profiling_dispatch (&prof_info, &enter_exit_data_event_info,
288 &api_info);
289 }
290
291 goacc_aq aq = get_goacc_asyncqueue (async);
292
293 tgt = gomp_map_vars_async (acc_dev, aq, mapnum, hostaddrs, NULL, sizes, kinds,
294 true, GOMP_MAP_VARS_OPENACC);
295 if (profiling_p)
296 {
297 prof_info.event_type = acc_ev_enter_data_end;
298 enter_exit_data_event_info.other_event.event_type
299 = prof_info.event_type;
300 goacc_profiling_dispatch (&prof_info, &enter_exit_data_event_info,
301 &api_info);
302 }
303
304 devaddrs = gomp_alloca (sizeof (void *) * mapnum);
305 for (i = 0; i < mapnum; i++)
306 devaddrs[i] = (void *) gomp_map_val (tgt, hostaddrs, i);
307
308 if (aq == NULL)
309 acc_dev->openacc.exec_func (tgt_fn, mapnum, hostaddrs, devaddrs, dims,
310 tgt);
311 else
312 acc_dev->openacc.async.exec_func (tgt_fn, mapnum, hostaddrs, devaddrs,
313 dims, tgt, aq);
314
315 if (profiling_p)
316 {
317 prof_info.event_type = acc_ev_exit_data_start;
318 enter_exit_data_event_info.other_event.event_type = prof_info.event_type;
319 enter_exit_data_event_info.other_event.tool_info = NULL;
320 goacc_profiling_dispatch (&prof_info, &enter_exit_data_event_info,
321 &api_info);
322 }
323
324 /* If running synchronously, unmap immediately. */
325 if (aq == NULL)
326 gomp_unmap_vars (tgt, true);
327 else
328 gomp_unmap_vars_async (tgt, true, aq);
329
330 if (profiling_p)
331 {
332 prof_info.event_type = acc_ev_exit_data_end;
333 enter_exit_data_event_info.other_event.event_type = prof_info.event_type;
334 goacc_profiling_dispatch (&prof_info, &enter_exit_data_event_info,
335 &api_info);
336 }
337
338 out_prof:
339 if (profiling_p)
340 {
341 prof_info.event_type = acc_ev_compute_construct_end;
342 compute_construct_event_info.other_event.event_type
343 = prof_info.event_type;
344 goacc_profiling_dispatch (&prof_info, &compute_construct_event_info,
345 &api_info);
346
347 thr->prof_info = NULL;
348 thr->api_info = NULL;
349 }
350 }
351
352 /* Legacy entry point (GCC 5). Only provide host fallback execution. */
353
354 void
355 GOACC_parallel (int flags_m, void (*fn) (void *),
356 size_t mapnum, void **hostaddrs, size_t *sizes,
357 unsigned short *kinds,
358 int num_gangs, int num_workers, int vector_length,
359 int async, int num_waits, ...)
360 {
361 goacc_save_and_set_bind (acc_device_host);
362 fn (hostaddrs);
363 goacc_restore_bind ();
364 }
365
366 void
367 GOACC_data_start (int flags_m, size_t mapnum,
368 void **hostaddrs, size_t *sizes, unsigned short *kinds)
369 {
370 int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
371
372 struct target_mem_desc *tgt;
373
374 #ifdef HAVE_INTTYPES_H
375 gomp_debug (0, "%s: mapnum=%"PRIu64", hostaddrs=%p, size=%p, kinds=%p\n",
376 __FUNCTION__, (uint64_t) mapnum, hostaddrs, sizes, kinds);
377 #else
378 gomp_debug (0, "%s: mapnum=%lu, hostaddrs=%p, sizes=%p, kinds=%p\n",
379 __FUNCTION__, (unsigned long) mapnum, hostaddrs, sizes, kinds);
380 #endif
381
382 goacc_lazy_initialize ();
383
384 struct goacc_thread *thr = goacc_thread ();
385 struct gomp_device_descr *acc_dev = thr->dev;
386
387 bool profiling_p = GOACC_PROFILING_DISPATCH_P (true);
388
389 acc_prof_info prof_info;
390 if (profiling_p)
391 {
392 thr->prof_info = &prof_info;
393
394 prof_info.event_type = acc_ev_enter_data_start;
395 prof_info.valid_bytes = _ACC_PROF_INFO_VALID_BYTES;
396 prof_info.version = _ACC_PROF_INFO_VERSION;
397 prof_info.device_type = acc_device_type (acc_dev->type);
398 prof_info.device_number = acc_dev->target_id;
399 prof_info.thread_id = -1;
400 prof_info.async = acc_async_sync; /* Always synchronous. */
401 prof_info.async_queue = prof_info.async;
402 prof_info.src_file = NULL;
403 prof_info.func_name = NULL;
404 prof_info.line_no = -1;
405 prof_info.end_line_no = -1;
406 prof_info.func_line_no = -1;
407 prof_info.func_end_line_no = -1;
408 }
409 acc_event_info enter_data_event_info;
410 if (profiling_p)
411 {
412 enter_data_event_info.other_event.event_type
413 = prof_info.event_type;
414 enter_data_event_info.other_event.valid_bytes
415 = _ACC_OTHER_EVENT_INFO_VALID_BYTES;
416 enter_data_event_info.other_event.parent_construct = acc_construct_data;
417 for (int i = 0; i < mapnum; ++i)
418 if ((kinds[i] & 0xff) == GOMP_MAP_USE_DEVICE_PTR
419 || (kinds[i] & 0xff) == GOMP_MAP_USE_DEVICE_PTR_IF_PRESENT)
420 {
421 /* If there is one such data mapping kind, then this is actually an
422 OpenACC 'host_data' construct. (GCC maps the OpenACC
423 'host_data' construct to the OpenACC 'data' construct.) Apart
424 from artificial test cases (such as an OpenACC 'host_data'
425 construct's (implicit) device initialization when there hasn't
426 been any device data be set up before...), there can't really
427 any meaningful events be generated from OpenACC 'host_data'
428 constructs, though. */
429 enter_data_event_info.other_event.parent_construct
430 = acc_construct_host_data;
431 break;
432 }
433 enter_data_event_info.other_event.implicit = 0;
434 enter_data_event_info.other_event.tool_info = NULL;
435 }
436 acc_api_info api_info;
437 if (profiling_p)
438 {
439 thr->api_info = &api_info;
440
441 api_info.device_api = acc_device_api_none;
442 api_info.valid_bytes = _ACC_API_INFO_VALID_BYTES;
443 api_info.device_type = prof_info.device_type;
444 api_info.vendor = -1;
445 api_info.device_handle = NULL;
446 api_info.context_handle = NULL;
447 api_info.async_handle = NULL;
448 }
449
450 if (profiling_p)
451 goacc_profiling_dispatch (&prof_info, &enter_data_event_info, &api_info);
452
453 /* Host fallback or 'do nothing'. */
454 if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
455 || (flags & GOACC_FLAG_HOST_FALLBACK))
456 {
457 prof_info.device_type = acc_device_host;
458 api_info.device_type = prof_info.device_type;
459 tgt = gomp_map_vars (NULL, 0, NULL, NULL, NULL, NULL, true,
460 GOMP_MAP_VARS_OPENACC);
461 tgt->prev = thr->mapped_data;
462 thr->mapped_data = tgt;
463
464 goto out_prof;
465 }
466
467 gomp_debug (0, " %s: prepare mappings\n", __FUNCTION__);
468 tgt = gomp_map_vars (acc_dev, mapnum, hostaddrs, NULL, sizes, kinds, true,
469 GOMP_MAP_VARS_OPENACC);
470 gomp_debug (0, " %s: mappings prepared\n", __FUNCTION__);
471 tgt->prev = thr->mapped_data;
472 thr->mapped_data = tgt;
473
474 out_prof:
475 if (profiling_p)
476 {
477 prof_info.event_type = acc_ev_enter_data_end;
478 enter_data_event_info.other_event.event_type = prof_info.event_type;
479 goacc_profiling_dispatch (&prof_info, &enter_data_event_info, &api_info);
480
481 thr->prof_info = NULL;
482 thr->api_info = NULL;
483 }
484 }
485
486 void
487 GOACC_data_end (void)
488 {
489 struct goacc_thread *thr = goacc_thread ();
490 struct gomp_device_descr *acc_dev = thr->dev;
491 struct target_mem_desc *tgt = thr->mapped_data;
492
493 bool profiling_p = GOACC_PROFILING_DISPATCH_P (true);
494
495 acc_prof_info prof_info;
496 if (profiling_p)
497 {
498 thr->prof_info = &prof_info;
499
500 prof_info.event_type = acc_ev_exit_data_start;
501 prof_info.valid_bytes = _ACC_PROF_INFO_VALID_BYTES;
502 prof_info.version = _ACC_PROF_INFO_VERSION;
503 prof_info.device_type = acc_device_type (acc_dev->type);
504 prof_info.device_number = acc_dev->target_id;
505 prof_info.thread_id = -1;
506 prof_info.async = acc_async_sync; /* Always synchronous. */
507 prof_info.async_queue = prof_info.async;
508 prof_info.src_file = NULL;
509 prof_info.func_name = NULL;
510 prof_info.line_no = -1;
511 prof_info.end_line_no = -1;
512 prof_info.func_line_no = -1;
513 prof_info.func_end_line_no = -1;
514 }
515 acc_event_info exit_data_event_info;
516 if (profiling_p)
517 {
518 exit_data_event_info.other_event.event_type
519 = prof_info.event_type;
520 exit_data_event_info.other_event.valid_bytes
521 = _ACC_OTHER_EVENT_INFO_VALID_BYTES;
522 exit_data_event_info.other_event.parent_construct = acc_construct_data;
523 exit_data_event_info.other_event.implicit = 0;
524 exit_data_event_info.other_event.tool_info = NULL;
525 }
526 acc_api_info api_info;
527 if (profiling_p)
528 {
529 thr->api_info = &api_info;
530
531 api_info.device_api = acc_device_api_none;
532 api_info.valid_bytes = _ACC_API_INFO_VALID_BYTES;
533 api_info.device_type = prof_info.device_type;
534 api_info.vendor = -1;
535 api_info.device_handle = NULL;
536 api_info.context_handle = NULL;
537 api_info.async_handle = NULL;
538 }
539
540 if (profiling_p)
541 goacc_profiling_dispatch (&prof_info, &exit_data_event_info, &api_info);
542
543 gomp_debug (0, " %s: restore mappings\n", __FUNCTION__);
544 thr->mapped_data = tgt->prev;
545 gomp_unmap_vars (tgt, true);
546 gomp_debug (0, " %s: mappings restored\n", __FUNCTION__);
547
548 if (profiling_p)
549 {
550 prof_info.event_type = acc_ev_exit_data_end;
551 exit_data_event_info.other_event.event_type = prof_info.event_type;
552 goacc_profiling_dispatch (&prof_info, &exit_data_event_info, &api_info);
553
554 thr->prof_info = NULL;
555 thr->api_info = NULL;
556 }
557 }
558
559 void
560 GOACC_update (int flags_m, size_t mapnum,
561 void **hostaddrs, size_t *sizes, unsigned short *kinds,
562 int async, int num_waits, ...)
563 {
564 int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
565
566 size_t i;
567
568 goacc_lazy_initialize ();
569
570 struct goacc_thread *thr = goacc_thread ();
571 struct gomp_device_descr *acc_dev = thr->dev;
572
573 bool profiling_p = GOACC_PROFILING_DISPATCH_P (true);
574
575 acc_prof_info prof_info;
576 if (profiling_p)
577 {
578 thr->prof_info = &prof_info;
579
580 prof_info.event_type = acc_ev_update_start;
581 prof_info.valid_bytes = _ACC_PROF_INFO_VALID_BYTES;
582 prof_info.version = _ACC_PROF_INFO_VERSION;
583 prof_info.device_type = acc_device_type (acc_dev->type);
584 prof_info.device_number = acc_dev->target_id;
585 prof_info.thread_id = -1;
586 prof_info.async = async;
587 prof_info.async_queue = prof_info.async;
588 prof_info.src_file = NULL;
589 prof_info.func_name = NULL;
590 prof_info.line_no = -1;
591 prof_info.end_line_no = -1;
592 prof_info.func_line_no = -1;
593 prof_info.func_end_line_no = -1;
594 }
595 acc_event_info update_event_info;
596 if (profiling_p)
597 {
598 update_event_info.other_event.event_type
599 = prof_info.event_type;
600 update_event_info.other_event.valid_bytes
601 = _ACC_OTHER_EVENT_INFO_VALID_BYTES;
602 update_event_info.other_event.parent_construct = acc_construct_update;
603 update_event_info.other_event.implicit = 0;
604 update_event_info.other_event.tool_info = NULL;
605 }
606 acc_api_info api_info;
607 if (profiling_p)
608 {
609 thr->api_info = &api_info;
610
611 api_info.device_api = acc_device_api_none;
612 api_info.valid_bytes = _ACC_API_INFO_VALID_BYTES;
613 api_info.device_type = prof_info.device_type;
614 api_info.vendor = -1;
615 api_info.device_handle = NULL;
616 api_info.context_handle = NULL;
617 api_info.async_handle = NULL;
618 }
619
620 if (profiling_p)
621 goacc_profiling_dispatch (&prof_info, &update_event_info, &api_info);
622
623 if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
624 || (flags & GOACC_FLAG_HOST_FALLBACK))
625 {
626 prof_info.device_type = acc_device_host;
627 api_info.device_type = prof_info.device_type;
628
629 goto out_prof;
630 }
631
632 if (num_waits)
633 {
634 va_list ap;
635
636 va_start (ap, num_waits);
637 goacc_wait (async, num_waits, &ap);
638 va_end (ap);
639 }
640
641 bool update_device = false;
642 for (i = 0; i < mapnum; ++i)
643 {
644 unsigned char kind = kinds[i] & 0xff;
645
646 switch (kind)
647 {
648 case GOMP_MAP_POINTER:
649 case GOMP_MAP_TO_PSET:
650 break;
651
652 case GOMP_MAP_ALWAYS_POINTER:
653 if (update_device)
654 {
655 /* Save the contents of the host pointer. */
656 void *dptr = acc_deviceptr (hostaddrs[i-1]);
657 uintptr_t t = *(uintptr_t *) hostaddrs[i];
658
659 /* Update the contents of the host pointer to reflect
660 the value of the allocated device memory in the
661 previous pointer. */
662 *(uintptr_t *) hostaddrs[i] = (uintptr_t)dptr;
663 /* TODO: verify that we really cannot use acc_update_device_async
664 here. */
665 acc_update_device (hostaddrs[i], sizeof (uintptr_t));
666
667 /* Restore the host pointer. */
668 *(uintptr_t *) hostaddrs[i] = t;
669 update_device = false;
670 }
671 break;
672
673 case GOMP_MAP_TO:
674 if (!acc_is_present (hostaddrs[i], sizes[i]))
675 {
676 update_device = false;
677 break;
678 }
679 /* Fallthru */
680 case GOMP_MAP_FORCE_TO:
681 update_device = true;
682 acc_update_device_async (hostaddrs[i], sizes[i], async);
683 break;
684
685 case GOMP_MAP_FROM:
686 if (!acc_is_present (hostaddrs[i], sizes[i]))
687 {
688 update_device = false;
689 break;
690 }
691 /* Fallthru */
692 case GOMP_MAP_FORCE_FROM:
693 update_device = false;
694 acc_update_self_async (hostaddrs[i], sizes[i], async);
695 break;
696
697 default:
698 gomp_fatal (">>>> GOACC_update UNHANDLED kind 0x%.2x", kind);
699 break;
700 }
701 }
702
703 out_prof:
704 if (profiling_p)
705 {
706 prof_info.event_type = acc_ev_update_end;
707 update_event_info.other_event.event_type = prof_info.event_type;
708 goacc_profiling_dispatch (&prof_info, &update_event_info, &api_info);
709
710 thr->prof_info = NULL;
711 thr->api_info = NULL;
712 }
713 }
714
715
716 /* Legacy entry point (GCC 5). */
717
718 int
719 GOACC_get_num_threads (void)
720 {
721 return 1;
722 }
723
724 /* Legacy entry point (GCC 5). */
725
726 int
727 GOACC_get_thread_num (void)
728 {
729 return 0;
730 }
731
732 void
733 GOACC_declare (int flags_m, size_t mapnum,
734 void **hostaddrs, size_t *sizes, unsigned short *kinds)
735 {
736 int i;
737
738 for (i = 0; i < mapnum; i++)
739 {
740 unsigned char kind = kinds[i] & 0xff;
741
742 if (kind == GOMP_MAP_POINTER || kind == GOMP_MAP_TO_PSET)
743 continue;
744
745 switch (kind)
746 {
747 case GOMP_MAP_FORCE_ALLOC:
748 case GOMP_MAP_FORCE_FROM:
749 case GOMP_MAP_FORCE_TO:
750 case GOMP_MAP_POINTER:
751 case GOMP_MAP_RELEASE:
752 case GOMP_MAP_DELETE:
753 GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
754 &kinds[i], GOMP_ASYNC_SYNC, 0);
755 break;
756
757 case GOMP_MAP_FORCE_DEVICEPTR:
758 break;
759
760 case GOMP_MAP_ALLOC:
761 if (!acc_is_present (hostaddrs[i], sizes[i]))
762 GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
763 &kinds[i], GOMP_ASYNC_SYNC, 0);
764 break;
765
766 case GOMP_MAP_TO:
767 GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
768 &kinds[i], GOMP_ASYNC_SYNC, 0);
769
770 break;
771
772 case GOMP_MAP_FROM:
773 GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
774 &kinds[i], GOMP_ASYNC_SYNC, 0);
775 break;
776
777 case GOMP_MAP_FORCE_PRESENT:
778 if (!acc_is_present (hostaddrs[i], sizes[i]))
779 gomp_fatal ("[%p,%ld] is not mapped", hostaddrs[i],
780 (unsigned long) sizes[i]);
781 break;
782
783 default:
784 assert (0);
785 break;
786 }
787 }
788 }