blob: d8a08e974a23ae0df852ef7efea4f0c65f8ab371 [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);
209
210 if (num_waits)
211 goacc_wait (async, num_waits, &ap);
212 break;
213 }
214
215 default:
216 gomp_fatal ("unrecognized offload code '%d',"
217 " libgomp is too old", GOMP_LAUNCH_CODE (tag));
218 }
Nathan Sidwella0911182015-07-20 17:31:46 +0000219 }
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000220 va_end (ap);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100221
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100222 acc_dev->openacc.async_set_async_func (async);
223
224 if (!(acc_dev->capabilities & GOMP_OFFLOAD_CAP_NATIVE_EXEC))
225 {
226 k.host_start = (uintptr_t) fn;
227 k.host_end = k.host_start + 1;
Ilya Verbina51df542015-04-06 12:40:28 +0000228 gomp_mutex_lock (&acc_dev->lock);
229 tgt_fn_key = splay_tree_lookup (&acc_dev->mem_map, &k);
230 gomp_mutex_unlock (&acc_dev->lock);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100231
232 if (tgt_fn_key == NULL)
233 gomp_fatal ("target function wasn't mapped");
234
Julian Brownd93bdab2015-04-08 15:58:33 +0000235 tgt_fn = (void (*)) tgt_fn_key->tgt_offset;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100236 }
237 else
238 tgt_fn = (void (*)) fn;
239
240 tgt = gomp_map_vars (acc_dev, mapnum, hostaddrs, NULL, sizes, kinds, true,
Jakub Jelinekd9a6bd32015-10-13 21:06:23 +0200241 GOMP_MAP_VARS_OPENACC);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100242
Thomas Schwinge6e361142015-01-16 21:05:21 +0100243 devaddrs = gomp_alloca (sizeof (void *) * mapnum);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100244 for (i = 0; i < mapnum; i++)
Jakub Jelinekd9a6bd32015-10-13 21:06:23 +0200245 devaddrs[i] = (void *) (tgt->list[i].key->tgt->tgt_start
Cesar Philippidisfe570ff2018-11-30 12:39:49 -0800246 + tgt->list[i].key->tgt_offset
247 + tgt->list[i].offset);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100248
Nathan Sidwell5c067422015-11-03 20:18:33 +0000249 acc_dev->openacc.exec_func (tgt_fn, mapnum, hostaddrs, devaddrs,
250 async, dims, tgt);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100251
252 /* If running synchronously, unmap immediately. */
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000253 bool copyfrom = true;
Tom de Vriesedbd0382018-05-09 13:52:49 +0000254 if (async_synchronous_p (async))
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100255 gomp_unmap_vars (tgt, true);
256 else
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000257 {
258 bool async_unmap = false;
259 for (size_t i = 0; i < tgt->list_count; i++)
260 {
261 splay_tree_key k = tgt->list[i].key;
262 if (k && k->refcount == 1)
263 {
264 async_unmap = true;
265 break;
266 }
267 }
268 if (async_unmap)
269 tgt->device_descr->openacc.register_async_cleanup_func (tgt, async);
270 else
271 {
272 copyfrom = false;
273 gomp_unmap_vars (tgt, copyfrom);
274 }
275 }
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100276
277 acc_dev->openacc.async_set_async_func (acc_async_sync);
278}
279
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000280/* Legacy entry point, only provide host execution. */
281
282void
Thomas Schwinge59d59602018-12-28 12:34:14 +0100283GOACC_parallel (int flags_m, void (*fn) (void *),
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000284 size_t mapnum, void **hostaddrs, size_t *sizes,
285 unsigned short *kinds,
286 int num_gangs, int num_workers, int vector_length,
287 int async, int num_waits, ...)
288{
289 goacc_save_and_set_bind (acc_device_host);
290 fn (hostaddrs);
291 goacc_restore_bind ();
292}
293
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100294void
Thomas Schwinge59d59602018-12-28 12:34:14 +0100295GOACC_data_start (int flags_m, size_t mapnum,
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100296 void **hostaddrs, size_t *sizes, unsigned short *kinds)
297{
Thomas Schwinge59d59602018-12-28 12:34:14 +0100298 int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
299
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100300 struct target_mem_desc *tgt;
301
Kai Tietz01c0b3b2015-03-25 16:05:02 +0100302#ifdef HAVE_INTTYPES_H
303 gomp_debug (0, "%s: mapnum=%"PRIu64", hostaddrs=%p, size=%p, kinds=%p\n",
304 __FUNCTION__, (uint64_t) mapnum, hostaddrs, sizes, kinds);
305#else
306 gomp_debug (0, "%s: mapnum=%lu, hostaddrs=%p, sizes=%p, kinds=%p\n",
307 __FUNCTION__, (unsigned long) mapnum, hostaddrs, sizes, kinds);
308#endif
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100309
Julian Brownd93bdab2015-04-08 15:58:33 +0000310 goacc_lazy_initialize ();
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100311
312 struct goacc_thread *thr = goacc_thread ();
313 struct gomp_device_descr *acc_dev = thr->dev;
314
315 /* Host fallback or 'do nothing'. */
316 if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
Thomas Schwinge59d59602018-12-28 12:34:14 +0100317 || (flags & GOACC_FLAG_HOST_FALLBACK))
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100318 {
Jakub Jelinekd9a6bd32015-10-13 21:06:23 +0200319 tgt = gomp_map_vars (NULL, 0, NULL, NULL, NULL, NULL, true,
320 GOMP_MAP_VARS_OPENACC);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100321 tgt->prev = thr->mapped_data;
322 thr->mapped_data = tgt;
323
324 return;
325 }
326
327 gomp_debug (0, " %s: prepare mappings\n", __FUNCTION__);
328 tgt = gomp_map_vars (acc_dev, mapnum, hostaddrs, NULL, sizes, kinds, true,
Jakub Jelinekd9a6bd32015-10-13 21:06:23 +0200329 GOMP_MAP_VARS_OPENACC);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100330 gomp_debug (0, " %s: mappings prepared\n", __FUNCTION__);
331 tgt->prev = thr->mapped_data;
332 thr->mapped_data = tgt;
333}
334
335void
336GOACC_data_end (void)
337{
338 struct goacc_thread *thr = goacc_thread ();
339 struct target_mem_desc *tgt = thr->mapped_data;
340
341 gomp_debug (0, " %s: restore mappings\n", __FUNCTION__);
342 thr->mapped_data = tgt->prev;
343 gomp_unmap_vars (tgt, true);
344 gomp_debug (0, " %s: mappings restored\n", __FUNCTION__);
345}
346
347void
Thomas Schwinge59d59602018-12-28 12:34:14 +0100348GOACC_enter_exit_data (int flags_m, size_t mapnum,
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100349 void **hostaddrs, size_t *sizes, unsigned short *kinds,
350 int async, int num_waits, ...)
351{
Thomas Schwinge59d59602018-12-28 12:34:14 +0100352 int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
353
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100354 struct goacc_thread *thr;
355 struct gomp_device_descr *acc_dev;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100356 bool data_enter = false;
357 size_t i;
358
Julian Brownd93bdab2015-04-08 15:58:33 +0000359 goacc_lazy_initialize ();
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100360
361 thr = goacc_thread ();
362 acc_dev = thr->dev;
363
364 if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
Thomas Schwinge59d59602018-12-28 12:34:14 +0100365 || (flags & GOACC_FLAG_HOST_FALLBACK))
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100366 return;
367
Nathan Sidwella0911182015-07-20 17:31:46 +0000368 if (num_waits)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100369 {
370 va_list ap;
371
372 va_start (ap, num_waits);
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000373 goacc_wait (async, num_waits, &ap);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100374 va_end (ap);
375 }
376
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000377 /* Determine whether "finalize" semantics apply to all mappings of this
378 OpenACC directive. */
379 bool finalize = false;
380 if (mapnum > 0)
381 {
382 unsigned char kind = kinds[0] & 0xff;
383 if (kind == GOMP_MAP_DELETE
384 || kind == GOMP_MAP_FORCE_FROM)
385 finalize = true;
386 }
387
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100388 acc_dev->openacc.async_set_async_func (async);
389
390 /* Determine if this is an "acc enter data". */
391 for (i = 0; i < mapnum; ++i)
392 {
393 unsigned char kind = kinds[i] & 0xff;
394
395 if (kind == GOMP_MAP_POINTER || kind == GOMP_MAP_TO_PSET)
396 continue;
397
398 if (kind == GOMP_MAP_FORCE_ALLOC
399 || kind == GOMP_MAP_FORCE_PRESENT
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000400 || kind == GOMP_MAP_FORCE_TO
401 || kind == GOMP_MAP_TO
402 || kind == GOMP_MAP_ALLOC)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100403 {
404 data_enter = true;
405 break;
406 }
407
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000408 if (kind == GOMP_MAP_RELEASE
409 || kind == GOMP_MAP_DELETE
410 || kind == GOMP_MAP_FROM
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100411 || kind == GOMP_MAP_FORCE_FROM)
412 break;
413
414 gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
415 kind);
416 }
417
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000418 /* In c, non-pointers and arrays are represented by a single data clause.
419 Dynamically allocated arrays and subarrays are represented by a data
420 clause followed by an internal GOMP_MAP_POINTER.
421
422 In fortran, scalars and not allocated arrays are represented by a
423 single data clause. Allocated arrays and subarrays have three mappings:
424 1) the original data clause, 2) a PSET 3) a pointer to the array data.
425 */
426
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100427 if (data_enter)
428 {
429 for (i = 0; i < mapnum; i++)
430 {
431 unsigned char kind = kinds[i] & 0xff;
432
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000433 /* Scan for pointers and PSETs. */
434 int pointer = find_pointer (i, mapnum, kinds);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100435
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000436 if (!pointer)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100437 {
438 switch (kind)
439 {
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000440 case GOMP_MAP_ALLOC:
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100441 case GOMP_MAP_FORCE_ALLOC:
442 acc_create (hostaddrs[i], sizes[i]);
443 break;
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000444 case GOMP_MAP_TO:
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100445 case GOMP_MAP_FORCE_TO:
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000446 acc_copyin (hostaddrs[i], sizes[i]);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100447 break;
448 default:
449 gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
450 kind);
451 break;
452 }
453 }
454 else
455 {
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000456 gomp_acc_insert_pointer (pointer, &hostaddrs[i],
457 &sizes[i], &kinds[i]);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100458 /* Increment 'i' by two because OpenACC requires fortran
459 arrays to be contiguous, so each PSET is associated with
460 one of MAP_FORCE_ALLOC/MAP_FORCE_PRESET/MAP_FORCE_TO, and
461 one MAP_POINTER. */
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000462 i += pointer - 1;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100463 }
464 }
465 }
466 else
467 for (i = 0; i < mapnum; ++i)
468 {
469 unsigned char kind = kinds[i] & 0xff;
470
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000471 int pointer = find_pointer (i, mapnum, kinds);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100472
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000473 if (!pointer)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100474 {
475 switch (kind)
476 {
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000477 case GOMP_MAP_RELEASE:
Thomas Schwinge91106e82016-03-17 16:07:54 +0100478 case GOMP_MAP_DELETE:
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000479 if (acc_is_present (hostaddrs[i], sizes[i]))
480 {
481 if (finalize)
482 acc_delete_finalize (hostaddrs[i], sizes[i]);
483 else
484 acc_delete (hostaddrs[i], sizes[i]);
485 }
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100486 break;
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000487 case GOMP_MAP_FROM:
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100488 case GOMP_MAP_FORCE_FROM:
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000489 if (finalize)
490 acc_copyout_finalize (hostaddrs[i], sizes[i]);
491 else
492 acc_copyout (hostaddrs[i], sizes[i]);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100493 break;
494 default:
495 gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
496 kind);
497 break;
498 }
499 }
500 else
501 {
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000502 bool copyfrom = (kind == GOMP_MAP_FORCE_FROM
503 || kind == GOMP_MAP_FROM);
504 gomp_acc_remove_pointer (hostaddrs[i], sizes[i], copyfrom, async,
505 finalize, pointer);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100506 /* See the above comment. */
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000507 i += pointer - 1;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100508 }
509 }
510
511 acc_dev->openacc.async_set_async_func (acc_async_sync);
512}
513
514static void
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000515goacc_wait (int async, int num_waits, va_list *ap)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100516{
517 struct goacc_thread *thr = goacc_thread ();
518 struct gomp_device_descr *acc_dev = thr->dev;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100519
Nathan Sidwella0911182015-07-20 17:31:46 +0000520 while (num_waits--)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100521 {
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000522 int qid = va_arg (*ap, int);
523
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100524 if (acc_async_test (qid))
525 continue;
526
Nathan Sidwella0911182015-07-20 17:31:46 +0000527 if (async == acc_async_sync)
528 acc_wait (qid);
529 else if (qid == async)
530 ;/* If we're waiting on the same asynchronous queue as we're
531 launching on, the queue itself will order work as
532 required, so there's no need to wait explicitly. */
533 else
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100534 acc_dev->openacc.async_wait_async_func (qid, async);
535 }
536}
537
538void
Thomas Schwinge59d59602018-12-28 12:34:14 +0100539GOACC_update (int flags_m, size_t mapnum,
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100540 void **hostaddrs, size_t *sizes, unsigned short *kinds,
541 int async, int num_waits, ...)
542{
Thomas Schwinge59d59602018-12-28 12:34:14 +0100543 int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
544
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100545 size_t i;
546
Julian Brownd93bdab2015-04-08 15:58:33 +0000547 goacc_lazy_initialize ();
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100548
549 struct goacc_thread *thr = goacc_thread ();
550 struct gomp_device_descr *acc_dev = thr->dev;
551
552 if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
Thomas Schwinge59d59602018-12-28 12:34:14 +0100553 || (flags & GOACC_FLAG_HOST_FALLBACK))
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100554 return;
555
Nathan Sidwella0911182015-07-20 17:31:46 +0000556 if (num_waits)
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100557 {
558 va_list ap;
559
560 va_start (ap, num_waits);
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000561 goacc_wait (async, num_waits, &ap);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100562 va_end (ap);
563 }
564
565 acc_dev->openacc.async_set_async_func (async);
566
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000567 bool update_device = false;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100568 for (i = 0; i < mapnum; ++i)
569 {
570 unsigned char kind = kinds[i] & 0xff;
571
572 switch (kind)
573 {
574 case GOMP_MAP_POINTER:
575 case GOMP_MAP_TO_PSET:
576 break;
577
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000578 case GOMP_MAP_ALWAYS_POINTER:
579 if (update_device)
580 {
581 /* Save the contents of the host pointer. */
582 void *dptr = acc_deviceptr (hostaddrs[i-1]);
583 uintptr_t t = *(uintptr_t *) hostaddrs[i];
584
585 /* Update the contents of the host pointer to reflect
586 the value of the allocated device memory in the
587 previous pointer. */
588 *(uintptr_t *) hostaddrs[i] = (uintptr_t)dptr;
589 acc_update_device (hostaddrs[i], sizeof (uintptr_t));
590
591 /* Restore the host pointer. */
592 *(uintptr_t *) hostaddrs[i] = t;
593 update_device = false;
594 }
595 break;
596
597 case GOMP_MAP_TO:
598 if (!acc_is_present (hostaddrs[i], sizes[i]))
599 {
600 update_device = false;
601 break;
602 }
603 /* Fallthru */
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100604 case GOMP_MAP_FORCE_TO:
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000605 update_device = true;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100606 acc_update_device (hostaddrs[i], sizes[i]);
607 break;
608
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000609 case GOMP_MAP_FROM:
610 if (!acc_is_present (hostaddrs[i], sizes[i]))
611 {
612 update_device = false;
613 break;
614 }
615 /* Fallthru */
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100616 case GOMP_MAP_FORCE_FROM:
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000617 update_device = false;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100618 acc_update_self (hostaddrs[i], sizes[i]);
619 break;
620
621 default:
622 gomp_fatal (">>>> GOACC_update UNHANDLED kind 0x%.2x", kind);
623 break;
624 }
625 }
626
627 acc_dev->openacc.async_set_async_func (acc_async_sync);
628}
629
630void
631GOACC_wait (int async, int num_waits, ...)
632{
Nathan Sidwella0911182015-07-20 17:31:46 +0000633 if (num_waits)
634 {
635 va_list ap;
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100636
Nathan Sidwella0911182015-07-20 17:31:46 +0000637 va_start (ap, num_waits);
Nathan Sidwell3e32ee12015-09-28 19:37:33 +0000638 goacc_wait (async, num_waits, &ap);
Nathan Sidwella0911182015-07-20 17:31:46 +0000639 va_end (ap);
640 }
641 else if (async == acc_async_sync)
642 acc_wait_all ();
Thomas Schwingec8ab8aa2018-12-14 21:42:50 +0100643 else
644 acc_wait_all_async (async);
Thomas Schwinge41dbbb32015-01-15 21:11:12 +0100645}
646
647int
648GOACC_get_num_threads (void)
649{
650 return 1;
651}
652
653int
654GOACC_get_thread_num (void)
655{
656 return 0;
657}
James Norris6e232ba2015-11-12 22:20:41 +0000658
659void
Thomas Schwinge59d59602018-12-28 12:34:14 +0100660GOACC_declare (int flags_m, size_t mapnum,
James Norris6e232ba2015-11-12 22:20:41 +0000661 void **hostaddrs, size_t *sizes, unsigned short *kinds)
662{
663 int i;
664
665 for (i = 0; i < mapnum; i++)
666 {
667 unsigned char kind = kinds[i] & 0xff;
668
669 if (kind == GOMP_MAP_POINTER || kind == GOMP_MAP_TO_PSET)
670 continue;
671
672 switch (kind)
673 {
674 case GOMP_MAP_FORCE_ALLOC:
James Norris6e232ba2015-11-12 22:20:41 +0000675 case GOMP_MAP_FORCE_FROM:
676 case GOMP_MAP_FORCE_TO:
677 case GOMP_MAP_POINTER:
Chung-Lin Tang829c6342018-06-20 16:35:15 +0000678 case GOMP_MAP_RELEASE:
Thomas Schwinge91106e82016-03-17 16:07:54 +0100679 case GOMP_MAP_DELETE:
Thomas Schwinge59d59602018-12-28 12:34:14 +0100680 GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
Tom de Vriesf5ad16f2018-05-09 16:01:30 +0000681 &kinds[i], GOMP_ASYNC_SYNC, 0);
James Norris6e232ba2015-11-12 22:20:41 +0000682 break;
683
684 case GOMP_MAP_FORCE_DEVICEPTR:
685 break;
686
687 case GOMP_MAP_ALLOC:
688 if (!acc_is_present (hostaddrs[i], sizes[i]))
Thomas Schwinge59d59602018-12-28 12:34:14 +0100689 GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
Tom de Vriesf5ad16f2018-05-09 16:01:30 +0000690 &kinds[i], GOMP_ASYNC_SYNC, 0);
James Norris6e232ba2015-11-12 22:20:41 +0000691 break;
692
693 case GOMP_MAP_TO:
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
697 break;
698
699 case GOMP_MAP_FROM:
Thomas Schwinge59d59602018-12-28 12:34:14 +0100700 GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
Tom de Vriesf5ad16f2018-05-09 16:01:30 +0000701 &kinds[i], GOMP_ASYNC_SYNC, 0);
James Norris6e232ba2015-11-12 22:20:41 +0000702 break;
703
704 case GOMP_MAP_FORCE_PRESENT:
705 if (!acc_is_present (hostaddrs[i], sizes[i]))
706 gomp_fatal ("[%p,%ld] is not mapped", hostaddrs[i],
707 (unsigned long) sizes[i]);
708 break;
709
710 default:
711 assert (0);
712 break;
713 }
714 }
715}