blob: b77c5e8b9c5d8da5fe1334a423818752b1db80db [file] [log] [blame]
Jakub Jelineka5544972019-01-01 13:31:55 +01001/* Copyright (C) 2013-2019 Free Software Foundation, Inc.
Thomas Schwinge41dbbb32015-01-15 21:11:12 +01002
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 "libgomp_g.h"
32#include "gomp-constants.h"
33#include "oacc-int.h"
Kai Tietz01c0b3b2015-03-25 16:05:02 +010034#ifdef HAVE_INTTYPES_H
35# include <inttypes.h> /* For PRIu64. */
36#endif
Thomas Schwinge41dbbb32015-01-15 21:11:12 +010037#include <string.h>
38#include <stdarg.h>
39#include <assert.h>
Thomas Schwinge41dbbb32015-01-15 21:11:12 +010040
Thomas Schwinge59d59602018-12-28 12:34:14 +010041
42/* In the ABI, the GOACC_FLAGs are encoded as an inverted bitmask, so that we
43 continue to support the following two legacy values. */
44_Static_assert (GOACC_FLAGS_UNMARSHAL (GOMP_DEVICE_ICV) == 0,
45 "legacy GOMP_DEVICE_ICV broken");
46_Static_assert (GOACC_FLAGS_UNMARSHAL (GOMP_DEVICE_HOST_FALLBACK)
47 == GOACC_FLAG_HOST_FALLBACK,
48 "legacy GOMP_DEVICE_HOST_FALLBACK broken");
49
50
Chung-Lin Tang829c6342018-06-20 16:35:15 +000051/* Returns the number of mappings associated with the pointer or pset. PSET
52 have three mappings, whereas pointer have two. */
53
Thomas Schwinge41dbbb32015-01-15 21:11:12 +010054static int
Chung-Lin Tang829c6342018-06-20 16:35:15 +000055find_pointer (int pos, size_t mapnum, unsigned short *kinds)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +010056{
57 if (pos + 1 >= mapnum)
58 return 0;
59
60 unsigned char kind = kinds[pos+1] & 0xff;
61
Chung-Lin Tang829c6342018-06-20 16:35:15 +000062 if (kind == GOMP_MAP_TO_PSET)
63 return 3;
64 else if (kind == GOMP_MAP_POINTER)
65 return 2;
66
67 return 0;
68}
69
70/* Handle the mapping pair that are presented when a
71 deviceptr clause is used with Fortran. */
72
73static void
74handle_ftn_pointers (size_t mapnum, void **hostaddrs, size_t *sizes,
75 unsigned short *kinds)
76{
77 int i;
78
79 for (i = 0; i < mapnum; i++)
80 {
81 unsigned short kind1 = kinds[i] & 0xff;
82
83 /* Handle Fortran deviceptr clause. */
84 if (kind1 == GOMP_MAP_FORCE_DEVICEPTR)
85 {
86 unsigned short kind2;
87
88 if (i < (signed)mapnum - 1)
89 kind2 = kinds[i + 1] & 0xff;
90 else
91 kind2 = 0xffff;
92
93 if (sizes[i] == sizeof (void *))
94 continue;
95
96 /* At this point, we're dealing with a Fortran deviceptr.
97 If the next element is not what we're expecting, then
98 this is an instance of where the deviceptr variable was
99 not used within the region and the pointer was removed
100 by the gimplifier. */
101 if (kind2 == GOMP_MAP_POINTER
102 && sizes[i + 1] == 0
103 && hostaddrs[i] == *(void **)hostaddrs[i + 1])
104 {
105 kinds[i+1] = kinds[i];
106 sizes[i+1] = sizeof (void *);
107 }
108
109 /* Invalidate the entry. */
110 hostaddrs[i] = NULL;
111 }
112 }
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100113}
114
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000115static void goacc_wait (int async, int num_waits, va_list *ap);
116
117
Thomas Schwinge59d59602018-12-28 12:34:14 +0100118/* Launch a possibly offloaded function with FLAGS. FN is the host fn
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000119 address. MAPNUM, HOSTADDRS, SIZES & KINDS describe the memory
120 blocks to be copied to/from the device. Varadic arguments are
121 keyed optional parameters terminated with a zero. */
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100122
123void
Thomas Schwinge59d59602018-12-28 12:34:14 +0100124GOACC_parallel_keyed (int flags_m, void (*fn) (void *),
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000125 size_t mapnum, void **hostaddrs, size_t *sizes,
126 unsigned short *kinds, ...)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100127{
Thomas Schwinge59d59602018-12-28 12:34:14 +0100128 int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
129
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100130 va_list ap;
131 struct goacc_thread *thr;
132 struct gomp_device_descr *acc_dev;
133 struct target_mem_desc *tgt;
134 void **devaddrs;
135 unsigned int i;
136 struct splay_tree_key_s k;
137 splay_tree_key tgt_fn_key;
138 void (*tgt_fn);
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000139 int async = GOMP_ASYNC_SYNC;
140 unsigned dims[GOMP_DIM_MAX];
141 unsigned tag;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100142
Kai Tietz01c0b3b2015-03-25 16:05:02 +0100143#ifdef HAVE_INTTYPES_H
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000144 gomp_debug (0, "%s: mapnum=%"PRIu64", hostaddrs=%p, size=%p, kinds=%p\n",
145 __FUNCTION__, (uint64_t) mapnum, hostaddrs, sizes, kinds);
Kai Tietz01c0b3b2015-03-25 16:05:02 +0100146#else
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000147 gomp_debug (0, "%s: mapnum=%lu, hostaddrs=%p, sizes=%p, kinds=%p\n",
148 __FUNCTION__, (unsigned long) mapnum, hostaddrs, sizes, kinds);
Kai Tietz01c0b3b2015-03-25 16:05:02 +0100149#endif
Julian Brownd93bdab2015-04-08 15:58:33 +0000150 goacc_lazy_initialize ();
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100151
152 thr = goacc_thread ();
153 acc_dev = thr->dev;
154
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000155 handle_ftn_pointers (mapnum, hostaddrs, sizes, kinds);
156
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100157 /* Host fallback if "if" clause is false or if the current device is set to
158 the host. */
Thomas Schwinge59d59602018-12-28 12:34:14 +0100159 if (flags & GOACC_FLAG_HOST_FALLBACK)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100160 {
161 goacc_save_and_set_bind (acc_device_host);
162 fn (hostaddrs);
163 goacc_restore_bind ();
164 return;
165 }
166 else if (acc_device_type (acc_dev->type) == acc_device_host)
167 {
168 fn (hostaddrs);
169 return;
170 }
171
Thomas Schwingef99c3552016-02-23 16:07:54 +0100172 /* Default: let the runtime choose. */
173 for (i = 0; i != GOMP_DIM_MAX; i++)
174 dims[i] = 0;
175
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000176 va_start (ap, kinds);
177 /* TODO: This will need amending when device_type is implemented. */
178 while ((tag = va_arg (ap, unsigned)) != 0)
Nathan Sidwella0911182015-07-20 17:31:46 +0000179 {
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000180 if (GOMP_LAUNCH_DEVICE (tag))
181 gomp_fatal ("device_type '%d' offload parameters, libgomp is too old",
182 GOMP_LAUNCH_DEVICE (tag));
183
184 switch (GOMP_LAUNCH_CODE (tag))
185 {
186 case GOMP_LAUNCH_DIM:
187 {
188 unsigned mask = GOMP_LAUNCH_OP (tag);
189
190 for (i = 0; i != GOMP_DIM_MAX; i++)
191 if (mask & GOMP_DIM_MASK (i))
192 dims[i] = va_arg (ap, unsigned);
193 }
194 break;
195
196 case GOMP_LAUNCH_ASYNC:
197 {
198 /* Small constant values are encoded in the operand. */
199 async = GOMP_LAUNCH_OP (tag);
200
201 if (async == GOMP_LAUNCH_OP_MAX)
202 async = va_arg (ap, unsigned);
203 break;
204 }
205
206 case GOMP_LAUNCH_WAIT:
207 {
208 unsigned num_waits = GOMP_LAUNCH_OP (tag);
Chung-Lin Tang19695f42019-02-19 14:10:15 +0000209 goacc_wait (async, num_waits, &ap);
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000210 break;
211 }
212
213 default:
214 gomp_fatal ("unrecognized offload code '%d',"
215 " libgomp is too old", GOMP_LAUNCH_CODE (tag));
216 }
Nathan Sidwella0911182015-07-20 17:31:46 +0000217 }
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000218 va_end (ap);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100219
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100220 acc_dev->openacc.async_set_async_func (async);
221
222 if (!(acc_dev->capabilities & GOMP_OFFLOAD_CAP_NATIVE_EXEC))
223 {
224 k.host_start = (uintptr_t) fn;
225 k.host_end = k.host_start + 1;
Ilya Verbina51df542015-04-06 12:40:28 +0000226 gomp_mutex_lock (&acc_dev->lock);
227 tgt_fn_key = splay_tree_lookup (&acc_dev->mem_map, &k);
228 gomp_mutex_unlock (&acc_dev->lock);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100229
230 if (tgt_fn_key == NULL)
231 gomp_fatal ("target function wasn't mapped");
232
Julian Brownd93bdab2015-04-08 15:58:33 +0000233 tgt_fn = (void (*)) tgt_fn_key->tgt_offset;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100234 }
235 else
236 tgt_fn = (void (*)) fn;
237
238 tgt = gomp_map_vars (acc_dev, mapnum, hostaddrs, NULL, sizes, kinds, true,
Jakub Jelinekd9a6bd32015-10-13 21:06:23 +0200239 GOMP_MAP_VARS_OPENACC);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100240
Thomas Schwinge6e361142015-01-16 21:05:21 +0100241 devaddrs = gomp_alloca (sizeof (void *) * mapnum);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100242 for (i = 0; i < mapnum; i++)
Jakub Jelinekd9a6bd32015-10-13 21:06:23 +0200243 devaddrs[i] = (void *) (tgt->list[i].key->tgt->tgt_start
Cesar Philippidisfe570ff2018-11-30 12:39:49 -0800244 + tgt->list[i].key->tgt_offset
245 + tgt->list[i].offset);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100246
Nathan Sidwell5c067422015-11-03 20:18:33 +0000247 acc_dev->openacc.exec_func (tgt_fn, mapnum, hostaddrs, devaddrs,
248 async, dims, tgt);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100249
250 /* If running synchronously, unmap immediately. */
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000251 bool copyfrom = true;
Tom de Vriesedbd0382018-05-09 13:52:49 +0000252 if (async_synchronous_p (async))
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100253 gomp_unmap_vars (tgt, true);
254 else
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000255 {
256 bool async_unmap = false;
257 for (size_t i = 0; i < tgt->list_count; i++)
258 {
259 splay_tree_key k = tgt->list[i].key;
260 if (k && k->refcount == 1)
261 {
262 async_unmap = true;
263 break;
264 }
265 }
266 if (async_unmap)
267 tgt->device_descr->openacc.register_async_cleanup_func (tgt, async);
268 else
269 {
270 copyfrom = false;
271 gomp_unmap_vars (tgt, copyfrom);
272 }
273 }
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100274
275 acc_dev->openacc.async_set_async_func (acc_async_sync);
276}
277
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000278/* Legacy entry point, only provide host execution. */
279
280void
Thomas Schwinge59d59602018-12-28 12:34:14 +0100281GOACC_parallel (int flags_m, void (*fn) (void *),
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000282 size_t mapnum, void **hostaddrs, size_t *sizes,
283 unsigned short *kinds,
284 int num_gangs, int num_workers, int vector_length,
285 int async, int num_waits, ...)
286{
287 goacc_save_and_set_bind (acc_device_host);
288 fn (hostaddrs);
289 goacc_restore_bind ();
290}
291
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100292void
Thomas Schwinge59d59602018-12-28 12:34:14 +0100293GOACC_data_start (int flags_m, size_t mapnum,
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100294 void **hostaddrs, size_t *sizes, unsigned short *kinds)
295{
Thomas Schwinge59d59602018-12-28 12:34:14 +0100296 int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
297
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100298 struct target_mem_desc *tgt;
299
Kai Tietz01c0b3b2015-03-25 16:05:02 +0100300#ifdef HAVE_INTTYPES_H
301 gomp_debug (0, "%s: mapnum=%"PRIu64", hostaddrs=%p, size=%p, kinds=%p\n",
302 __FUNCTION__, (uint64_t) mapnum, hostaddrs, sizes, kinds);
303#else
304 gomp_debug (0, "%s: mapnum=%lu, hostaddrs=%p, sizes=%p, kinds=%p\n",
305 __FUNCTION__, (unsigned long) mapnum, hostaddrs, sizes, kinds);
306#endif
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100307
Julian Brownd93bdab2015-04-08 15:58:33 +0000308 goacc_lazy_initialize ();
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100309
310 struct goacc_thread *thr = goacc_thread ();
311 struct gomp_device_descr *acc_dev = thr->dev;
312
313 /* Host fallback or 'do nothing'. */
314 if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
Thomas Schwinge59d59602018-12-28 12:34:14 +0100315 || (flags & GOACC_FLAG_HOST_FALLBACK))
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100316 {
Jakub Jelinekd9a6bd32015-10-13 21:06:23 +0200317 tgt = gomp_map_vars (NULL, 0, NULL, NULL, NULL, NULL, true,
318 GOMP_MAP_VARS_OPENACC);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100319 tgt->prev = thr->mapped_data;
320 thr->mapped_data = tgt;
321
322 return;
323 }
324
325 gomp_debug (0, " %s: prepare mappings\n", __FUNCTION__);
326 tgt = gomp_map_vars (acc_dev, mapnum, hostaddrs, NULL, sizes, kinds, true,
Jakub Jelinekd9a6bd32015-10-13 21:06:23 +0200327 GOMP_MAP_VARS_OPENACC);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100328 gomp_debug (0, " %s: mappings prepared\n", __FUNCTION__);
329 tgt->prev = thr->mapped_data;
330 thr->mapped_data = tgt;
331}
332
333void
334GOACC_data_end (void)
335{
336 struct goacc_thread *thr = goacc_thread ();
337 struct target_mem_desc *tgt = thr->mapped_data;
338
339 gomp_debug (0, " %s: restore mappings\n", __FUNCTION__);
340 thr->mapped_data = tgt->prev;
341 gomp_unmap_vars (tgt, true);
342 gomp_debug (0, " %s: mappings restored\n", __FUNCTION__);
343}
344
345void
Thomas Schwinge59d59602018-12-28 12:34:14 +0100346GOACC_enter_exit_data (int flags_m, size_t mapnum,
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100347 void **hostaddrs, size_t *sizes, unsigned short *kinds,
348 int async, int num_waits, ...)
349{
Thomas Schwinge59d59602018-12-28 12:34:14 +0100350 int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
351
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100352 struct goacc_thread *thr;
353 struct gomp_device_descr *acc_dev;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100354 bool data_enter = false;
355 size_t i;
356
Julian Brownd93bdab2015-04-08 15:58:33 +0000357 goacc_lazy_initialize ();
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100358
359 thr = goacc_thread ();
360 acc_dev = thr->dev;
361
362 if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
Thomas Schwinge59d59602018-12-28 12:34:14 +0100363 || (flags & GOACC_FLAG_HOST_FALLBACK))
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100364 return;
365
Nathan Sidwella0911182015-07-20 17:31:46 +0000366 if (num_waits)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100367 {
368 va_list ap;
369
370 va_start (ap, num_waits);
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000371 goacc_wait (async, num_waits, &ap);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100372 va_end (ap);
373 }
374
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000375 /* Determine whether "finalize" semantics apply to all mappings of this
376 OpenACC directive. */
377 bool finalize = false;
378 if (mapnum > 0)
379 {
380 unsigned char kind = kinds[0] & 0xff;
381 if (kind == GOMP_MAP_DELETE
382 || kind == GOMP_MAP_FORCE_FROM)
383 finalize = true;
384 }
385
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100386 acc_dev->openacc.async_set_async_func (async);
387
388 /* Determine if this is an "acc enter data". */
389 for (i = 0; i < mapnum; ++i)
390 {
391 unsigned char kind = kinds[i] & 0xff;
392
393 if (kind == GOMP_MAP_POINTER || kind == GOMP_MAP_TO_PSET)
394 continue;
395
396 if (kind == GOMP_MAP_FORCE_ALLOC
397 || kind == GOMP_MAP_FORCE_PRESENT
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000398 || kind == GOMP_MAP_FORCE_TO
399 || kind == GOMP_MAP_TO
400 || kind == GOMP_MAP_ALLOC)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100401 {
402 data_enter = true;
403 break;
404 }
405
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000406 if (kind == GOMP_MAP_RELEASE
407 || kind == GOMP_MAP_DELETE
408 || kind == GOMP_MAP_FROM
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100409 || kind == GOMP_MAP_FORCE_FROM)
410 break;
411
412 gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
413 kind);
414 }
415
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000416 /* In c, non-pointers and arrays are represented by a single data clause.
417 Dynamically allocated arrays and subarrays are represented by a data
418 clause followed by an internal GOMP_MAP_POINTER.
419
420 In fortran, scalars and not allocated arrays are represented by a
421 single data clause. Allocated arrays and subarrays have three mappings:
422 1) the original data clause, 2) a PSET 3) a pointer to the array data.
423 */
424
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100425 if (data_enter)
426 {
427 for (i = 0; i < mapnum; i++)
428 {
429 unsigned char kind = kinds[i] & 0xff;
430
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000431 /* Scan for pointers and PSETs. */
432 int pointer = find_pointer (i, mapnum, kinds);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100433
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000434 if (!pointer)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100435 {
436 switch (kind)
437 {
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000438 case GOMP_MAP_ALLOC:
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100439 case GOMP_MAP_FORCE_ALLOC:
440 acc_create (hostaddrs[i], sizes[i]);
441 break;
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000442 case GOMP_MAP_TO:
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100443 case GOMP_MAP_FORCE_TO:
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000444 acc_copyin (hostaddrs[i], sizes[i]);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100445 break;
446 default:
447 gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
448 kind);
449 break;
450 }
451 }
452 else
453 {
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000454 gomp_acc_insert_pointer (pointer, &hostaddrs[i],
455 &sizes[i], &kinds[i]);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100456 /* Increment 'i' by two because OpenACC requires fortran
457 arrays to be contiguous, so each PSET is associated with
458 one of MAP_FORCE_ALLOC/MAP_FORCE_PRESET/MAP_FORCE_TO, and
459 one MAP_POINTER. */
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000460 i += pointer - 1;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100461 }
462 }
463 }
464 else
465 for (i = 0; i < mapnum; ++i)
466 {
467 unsigned char kind = kinds[i] & 0xff;
468
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000469 int pointer = find_pointer (i, mapnum, kinds);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100470
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000471 if (!pointer)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100472 {
473 switch (kind)
474 {
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000475 case GOMP_MAP_RELEASE:
Thomas Schwinge91106e82016-03-17 16:07:54 +0100476 case GOMP_MAP_DELETE:
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000477 if (acc_is_present (hostaddrs[i], sizes[i]))
478 {
479 if (finalize)
480 acc_delete_finalize (hostaddrs[i], sizes[i]);
481 else
482 acc_delete (hostaddrs[i], sizes[i]);
483 }
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100484 break;
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000485 case GOMP_MAP_FROM:
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100486 case GOMP_MAP_FORCE_FROM:
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000487 if (finalize)
488 acc_copyout_finalize (hostaddrs[i], sizes[i]);
489 else
490 acc_copyout (hostaddrs[i], sizes[i]);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100491 break;
492 default:
493 gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
494 kind);
495 break;
496 }
497 }
498 else
499 {
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000500 bool copyfrom = (kind == GOMP_MAP_FORCE_FROM
501 || kind == GOMP_MAP_FROM);
502 gomp_acc_remove_pointer (hostaddrs[i], sizes[i], copyfrom, async,
503 finalize, pointer);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100504 /* See the above comment. */
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000505 i += pointer - 1;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100506 }
507 }
508
509 acc_dev->openacc.async_set_async_func (acc_async_sync);
510}
511
512static void
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000513goacc_wait (int async, int num_waits, va_list *ap)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100514{
Nathan Sidwella0911182015-07-20 17:31:46 +0000515 while (num_waits--)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100516 {
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000517 int qid = va_arg (*ap, int);
Chung-Lin Tang19695f42019-02-19 14:10:15 +0000518
519 /* Waiting on ACC_ASYNC_NOVAL maps to 'wait all'. */
520 if (qid == acc_async_noval)
521 {
522 if (async == acc_async_sync)
523 acc_wait_all ();
524 else
525 acc_wait_all_async (async);
526 break;
527 }
528
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100529 if (acc_async_test (qid))
530 continue;
531
Nathan Sidwella0911182015-07-20 17:31:46 +0000532 if (async == acc_async_sync)
533 acc_wait (qid);
534 else if (qid == async)
535 ;/* If we're waiting on the same asynchronous queue as we're
536 launching on, the queue itself will order work as
537 required, so there's no need to wait explicitly. */
538 else
Chung-Lin Tang19695f42019-02-19 14:10:15 +0000539 acc_wait_async (qid, async);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100540 }
541}
542
543void
Thomas Schwinge59d59602018-12-28 12:34:14 +0100544GOACC_update (int flags_m, size_t mapnum,
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100545 void **hostaddrs, size_t *sizes, unsigned short *kinds,
546 int async, int num_waits, ...)
547{
Thomas Schwinge59d59602018-12-28 12:34:14 +0100548 int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
549
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100550 size_t i;
551
Julian Brownd93bdab2015-04-08 15:58:33 +0000552 goacc_lazy_initialize ();
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100553
554 struct goacc_thread *thr = goacc_thread ();
555 struct gomp_device_descr *acc_dev = thr->dev;
556
557 if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
Thomas Schwinge59d59602018-12-28 12:34:14 +0100558 || (flags & GOACC_FLAG_HOST_FALLBACK))
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100559 return;
560
Nathan Sidwella0911182015-07-20 17:31:46 +0000561 if (num_waits)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100562 {
563 va_list ap;
564
565 va_start (ap, num_waits);
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000566 goacc_wait (async, num_waits, &ap);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100567 va_end (ap);
568 }
569
570 acc_dev->openacc.async_set_async_func (async);
571
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000572 bool update_device = false;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100573 for (i = 0; i < mapnum; ++i)
574 {
575 unsigned char kind = kinds[i] & 0xff;
576
577 switch (kind)
578 {
579 case GOMP_MAP_POINTER:
580 case GOMP_MAP_TO_PSET:
581 break;
582
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000583 case GOMP_MAP_ALWAYS_POINTER:
584 if (update_device)
585 {
586 /* Save the contents of the host pointer. */
587 void *dptr = acc_deviceptr (hostaddrs[i-1]);
588 uintptr_t t = *(uintptr_t *) hostaddrs[i];
589
590 /* Update the contents of the host pointer to reflect
591 the value of the allocated device memory in the
592 previous pointer. */
593 *(uintptr_t *) hostaddrs[i] = (uintptr_t)dptr;
594 acc_update_device (hostaddrs[i], sizeof (uintptr_t));
595
596 /* Restore the host pointer. */
597 *(uintptr_t *) hostaddrs[i] = t;
598 update_device = false;
599 }
600 break;
601
602 case GOMP_MAP_TO:
603 if (!acc_is_present (hostaddrs[i], sizes[i]))
604 {
605 update_device = false;
606 break;
607 }
608 /* Fallthru */
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100609 case GOMP_MAP_FORCE_TO:
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000610 update_device = true;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100611 acc_update_device (hostaddrs[i], sizes[i]);
612 break;
613
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000614 case GOMP_MAP_FROM:
615 if (!acc_is_present (hostaddrs[i], sizes[i]))
616 {
617 update_device = false;
618 break;
619 }
620 /* Fallthru */
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100621 case GOMP_MAP_FORCE_FROM:
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000622 update_device = false;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100623 acc_update_self (hostaddrs[i], sizes[i]);
624 break;
625
626 default:
627 gomp_fatal (">>>> GOACC_update UNHANDLED kind 0x%.2x", kind);
628 break;
629 }
630 }
631
632 acc_dev->openacc.async_set_async_func (acc_async_sync);
633}
634
635void
636GOACC_wait (int async, int num_waits, ...)
637{
Nathan Sidwella0911182015-07-20 17:31:46 +0000638 if (num_waits)
639 {
640 va_list ap;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100641
Nathan Sidwella0911182015-07-20 17:31:46 +0000642 va_start (ap, num_waits);
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000643 goacc_wait (async, num_waits, &ap);
Nathan Sidwella0911182015-07-20 17:31:46 +0000644 va_end (ap);
645 }
646 else if (async == acc_async_sync)
647 acc_wait_all ();
Thomas Schwingec8ab8aa2018-12-14 21:42:50 +0100648 else
649 acc_wait_all_async (async);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100650}
651
652int
653GOACC_get_num_threads (void)
654{
655 return 1;
656}
657
658int
659GOACC_get_thread_num (void)
660{
661 return 0;
662}
James Norris6e232ba2015-11-12 22:20:41 +0000663
664void
Thomas Schwinge59d59602018-12-28 12:34:14 +0100665GOACC_declare (int flags_m, size_t mapnum,
James Norris6e232ba2015-11-12 22:20:41 +0000666 void **hostaddrs, size_t *sizes, unsigned short *kinds)
667{
668 int i;
669
670 for (i = 0; i < mapnum; i++)
671 {
672 unsigned char kind = kinds[i] & 0xff;
673
674 if (kind == GOMP_MAP_POINTER || kind == GOMP_MAP_TO_PSET)
675 continue;
676
677 switch (kind)
678 {
679 case GOMP_MAP_FORCE_ALLOC:
James Norris6e232ba2015-11-12 22:20:41 +0000680 case GOMP_MAP_FORCE_FROM:
681 case GOMP_MAP_FORCE_TO:
682 case GOMP_MAP_POINTER:
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000683 case GOMP_MAP_RELEASE:
Thomas Schwinge91106e82016-03-17 16:07:54 +0100684 case GOMP_MAP_DELETE:
Thomas Schwinge59d59602018-12-28 12:34:14 +0100685 GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
Tom de Vriesf5ad16f2018-05-09 16:01:30 +0000686 &kinds[i], GOMP_ASYNC_SYNC, 0);
James Norris6e232ba2015-11-12 22:20:41 +0000687 break;
688
689 case GOMP_MAP_FORCE_DEVICEPTR:
690 break;
691
692 case GOMP_MAP_ALLOC:
693 if (!acc_is_present (hostaddrs[i], sizes[i]))
Thomas Schwinge59d59602018-12-28 12:34:14 +0100694 GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
Tom de Vriesf5ad16f2018-05-09 16:01:30 +0000695 &kinds[i], GOMP_ASYNC_SYNC, 0);
James Norris6e232ba2015-11-12 22:20:41 +0000696 break;
697
698 case GOMP_MAP_TO:
Thomas Schwinge59d59602018-12-28 12:34:14 +0100699 GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
Tom de Vriesf5ad16f2018-05-09 16:01:30 +0000700 &kinds[i], GOMP_ASYNC_SYNC, 0);
James Norris6e232ba2015-11-12 22:20:41 +0000701
702 break;
703
704 case GOMP_MAP_FROM:
Thomas Schwinge59d59602018-12-28 12:34:14 +0100705 GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
Tom de Vriesf5ad16f2018-05-09 16:01:30 +0000706 &kinds[i], GOMP_ASYNC_SYNC, 0);
James Norris6e232ba2015-11-12 22:20:41 +0000707 break;
708
709 case GOMP_MAP_FORCE_PRESENT:
710 if (!acc_is_present (hostaddrs[i], sizes[i]))
711 gomp_fatal ("[%p,%ld] is not mapped", hostaddrs[i],
712 (unsigned long) sizes[i]);
713 break;
714
715 default:
716 assert (0);
717 break;
718 }
719 }
720}