1 /* OpenACC Runtime initialization routines
3 Copyright (C) 2013-2019 Free Software Foundation, Inc.
5 Contributed by Mentor Embedded.
7 This file is part of the GNU Offloading and Multi Processing Library
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)
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
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.
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/>. */
32 #include "gomp-constants.h"
38 /* Return block containing [H->S), or NULL if not contained. The device lock
39 for DEV must be locked on entry, and remains locked on exit. */
42 lookup_host (struct gomp_device_descr
*dev
, void *h
, size_t s
)
44 struct splay_tree_key_s node
;
47 node
.host_start
= (uintptr_t) h
;
48 node
.host_end
= (uintptr_t) h
+ s
;
50 key
= splay_tree_lookup (&dev
->mem_map
, &node
);
55 /* Return block containing [D->S), or NULL if not contained.
56 The list isn't ordered by device address, so we have to iterate
57 over the whole array. This is not expected to be a common
58 operation. The device lock associated with TGT must be locked on entry, and
59 remains locked on exit. */
62 lookup_dev (struct target_mem_desc
*tgt
, void *d
, size_t s
)
65 struct target_mem_desc
*t
;
70 for (t
= tgt
; t
!= NULL
; t
= t
->prev
)
72 if (t
->tgt_start
<= (uintptr_t) d
&& t
->tgt_end
>= (uintptr_t) d
+ s
)
79 for (i
= 0; i
< t
->list_count
; i
++)
83 splay_tree_key k
= &t
->array
[i
].key
;
84 offset
= d
- t
->tgt_start
+ k
->tgt_offset
;
86 if (k
->host_start
+ offset
<= (void *) k
->host_end
)
93 /* OpenACC is silent on how memory exhaustion is indicated. We return
102 goacc_lazy_initialize ();
104 struct goacc_thread
*thr
= goacc_thread ();
108 if (thr
->dev
->capabilities
& GOMP_OFFLOAD_CAP_SHARED_MEM
)
111 acc_prof_info prof_info
;
112 acc_api_info api_info
;
113 bool profiling_p
= GOACC_PROFILING_SETUP_P (thr
, &prof_info
, &api_info
);
115 void *res
= thr
->dev
->alloc_func (thr
->dev
->target_id
, s
);
119 thr
->prof_info
= NULL
;
120 thr
->api_info
= NULL
;
126 /* OpenACC 2.0a (3.2.16) doesn't specify what to do in the event
127 the device address is mapped. We choose to check if it mapped,
128 and if it is, to unmap it. */
137 struct goacc_thread
*thr
= goacc_thread ();
139 assert (thr
&& thr
->dev
);
141 struct gomp_device_descr
*acc_dev
= thr
->dev
;
143 if (acc_dev
->capabilities
& GOMP_OFFLOAD_CAP_SHARED_MEM
)
146 acc_prof_info prof_info
;
147 acc_api_info api_info
;
148 bool profiling_p
= GOACC_PROFILING_SETUP_P (thr
, &prof_info
, &api_info
);
150 gomp_mutex_lock (&acc_dev
->lock
);
152 /* We don't have to call lazy open here, as the ptr value must have
153 been returned by acc_malloc. It's not permitted to pass NULL in
154 (unless you got that null from acc_malloc). */
155 if ((k
= lookup_dev (acc_dev
->openacc
.data_environ
, d
, 1)))
159 offset
= d
- k
->tgt
->tgt_start
+ k
->tgt_offset
;
161 gomp_mutex_unlock (&acc_dev
->lock
);
163 acc_unmap_data ((void *)(k
->host_start
+ offset
));
166 gomp_mutex_unlock (&acc_dev
->lock
);
168 if (!acc_dev
->free_func (acc_dev
->target_id
, d
))
169 gomp_fatal ("error in freeing device memory in %s", __FUNCTION__
);
173 thr
->prof_info
= NULL
;
174 thr
->api_info
= NULL
;
179 memcpy_tofrom_device (bool from
, void *d
, void *h
, size_t s
, int async
,
180 const char *libfnname
)
182 /* No need to call lazy open here, as the device pointer must have
183 been obtained from a routine that did that. */
184 struct goacc_thread
*thr
= goacc_thread ();
186 assert (thr
&& thr
->dev
);
188 if (thr
->dev
->capabilities
& GOMP_OFFLOAD_CAP_SHARED_MEM
)
197 acc_prof_info prof_info
;
198 acc_api_info api_info
;
199 bool profiling_p
= GOACC_PROFILING_SETUP_P (thr
, &prof_info
, &api_info
);
202 prof_info
.async
= async
;
203 prof_info
.async_queue
= prof_info
.async
;
206 goacc_aq aq
= get_goacc_asyncqueue (async
);
208 gomp_copy_dev2host (thr
->dev
, aq
, h
, d
, s
);
210 gomp_copy_host2dev (thr
->dev
, aq
, d
, h
, s
, /* TODO: cbuf? */ NULL
);
214 thr
->prof_info
= NULL
;
215 thr
->api_info
= NULL
;
220 acc_memcpy_to_device (void *d
, void *h
, size_t s
)
222 memcpy_tofrom_device (false, d
, h
, s
, acc_async_sync
, __FUNCTION__
);
226 acc_memcpy_to_device_async (void *d
, void *h
, size_t s
, int async
)
228 memcpy_tofrom_device (false, d
, h
, s
, async
, __FUNCTION__
);
232 acc_memcpy_from_device (void *h
, void *d
, size_t s
)
234 memcpy_tofrom_device (true, d
, h
, s
, acc_async_sync
, __FUNCTION__
);
238 acc_memcpy_from_device_async (void *h
, void *d
, size_t s
, int async
)
240 memcpy_tofrom_device (true, d
, h
, s
, async
, __FUNCTION__
);
243 /* Return the device pointer that corresponds to host data H. Or NULL
247 acc_deviceptr (void *h
)
253 goacc_lazy_initialize ();
255 struct goacc_thread
*thr
= goacc_thread ();
256 struct gomp_device_descr
*dev
= thr
->dev
;
258 if (thr
->dev
->capabilities
& GOMP_OFFLOAD_CAP_SHARED_MEM
)
261 /* In the following, no OpenACC Profiling Interface events can possibly be
264 gomp_mutex_lock (&dev
->lock
);
266 n
= lookup_host (dev
, h
, 1);
270 gomp_mutex_unlock (&dev
->lock
);
274 offset
= h
- n
->host_start
;
276 d
= n
->tgt
->tgt_start
+ n
->tgt_offset
+ offset
;
278 gomp_mutex_unlock (&dev
->lock
);
283 /* Return the host pointer that corresponds to device data D. Or NULL
287 acc_hostptr (void *d
)
293 goacc_lazy_initialize ();
295 struct goacc_thread
*thr
= goacc_thread ();
296 struct gomp_device_descr
*acc_dev
= thr
->dev
;
298 if (thr
->dev
->capabilities
& GOMP_OFFLOAD_CAP_SHARED_MEM
)
301 /* In the following, no OpenACC Profiling Interface events can possibly be
304 gomp_mutex_lock (&acc_dev
->lock
);
306 n
= lookup_dev (acc_dev
->openacc
.data_environ
, d
, 1);
310 gomp_mutex_unlock (&acc_dev
->lock
);
314 offset
= d
- n
->tgt
->tgt_start
+ n
->tgt_offset
;
316 h
= n
->host_start
+ offset
;
318 gomp_mutex_unlock (&acc_dev
->lock
);
323 /* Return 1 if host data [H,+S] is present on the device. */
326 acc_is_present (void *h
, size_t s
)
333 goacc_lazy_initialize ();
335 struct goacc_thread
*thr
= goacc_thread ();
336 struct gomp_device_descr
*acc_dev
= thr
->dev
;
338 if (thr
->dev
->capabilities
& GOMP_OFFLOAD_CAP_SHARED_MEM
)
341 /* In the following, no OpenACC Profiling Interface events can possibly be
344 gomp_mutex_lock (&acc_dev
->lock
);
346 n
= lookup_host (acc_dev
, h
, s
);
348 if (n
&& ((uintptr_t)h
< n
->host_start
349 || (uintptr_t)h
+ s
> n
->host_end
350 || s
> n
->host_end
- n
->host_start
))
353 gomp_mutex_unlock (&acc_dev
->lock
);
358 /* Create a mapping for host [H,+S] -> device [D,+S] */
361 acc_map_data (void *h
, void *d
, size_t s
)
363 struct target_mem_desc
*tgt
= NULL
;
368 unsigned short kinds
= GOMP_MAP_ALLOC
;
370 goacc_lazy_initialize ();
372 struct goacc_thread
*thr
= goacc_thread ();
373 struct gomp_device_descr
*acc_dev
= thr
->dev
;
375 if (acc_dev
->capabilities
& GOMP_OFFLOAD_CAP_SHARED_MEM
)
378 gomp_fatal ("cannot map data on shared-memory system");
382 struct goacc_thread
*thr
= goacc_thread ();
385 gomp_fatal ("[%p,+%d]->[%p,+%d] is a bad map",
386 (void *)h
, (int)s
, (void *)d
, (int)s
);
388 acc_prof_info prof_info
;
389 acc_api_info api_info
;
390 bool profiling_p
= GOACC_PROFILING_SETUP_P (thr
, &prof_info
, &api_info
);
392 gomp_mutex_lock (&acc_dev
->lock
);
394 if (lookup_host (acc_dev
, h
, s
))
396 gomp_mutex_unlock (&acc_dev
->lock
);
397 gomp_fatal ("host address [%p, +%d] is already mapped", (void *)h
,
401 if (lookup_dev (thr
->dev
->openacc
.data_environ
, d
, s
))
403 gomp_mutex_unlock (&acc_dev
->lock
);
404 gomp_fatal ("device address [%p, +%d] is already mapped", (void *)d
,
408 gomp_mutex_unlock (&acc_dev
->lock
);
410 tgt
= gomp_map_vars (acc_dev
, mapnum
, &hostaddrs
, &devaddrs
, &sizes
,
411 &kinds
, true, GOMP_MAP_VARS_OPENACC
);
412 tgt
->list
[0].key
->refcount
= REFCOUNT_INFINITY
;
416 thr
->prof_info
= NULL
;
417 thr
->api_info
= NULL
;
421 gomp_mutex_lock (&acc_dev
->lock
);
422 tgt
->prev
= acc_dev
->openacc
.data_environ
;
423 acc_dev
->openacc
.data_environ
= tgt
;
424 gomp_mutex_unlock (&acc_dev
->lock
);
428 acc_unmap_data (void *h
)
430 struct goacc_thread
*thr
= goacc_thread ();
431 struct gomp_device_descr
*acc_dev
= thr
->dev
;
433 /* No need to call lazy open, as the address must have been mapped. */
435 /* This is a no-op on shared-memory targets. */
436 if (acc_dev
->capabilities
& GOMP_OFFLOAD_CAP_SHARED_MEM
)
439 acc_prof_info prof_info
;
440 acc_api_info api_info
;
441 bool profiling_p
= GOACC_PROFILING_SETUP_P (thr
, &prof_info
, &api_info
);
445 gomp_mutex_lock (&acc_dev
->lock
);
447 splay_tree_key n
= lookup_host (acc_dev
, h
, 1);
448 struct target_mem_desc
*t
;
452 gomp_mutex_unlock (&acc_dev
->lock
);
453 gomp_fatal ("%p is not a mapped block", (void *)h
);
456 host_size
= n
->host_end
- n
->host_start
;
458 if (n
->host_start
!= (uintptr_t) h
)
460 gomp_mutex_unlock (&acc_dev
->lock
);
461 gomp_fatal ("[%p,%d] surrounds %p",
462 (void *) n
->host_start
, (int) host_size
, (void *) h
);
465 /* Mark for removal. */
470 if (t
->refcount
== 2)
472 struct target_mem_desc
*tp
;
474 /* This is the last reference, so pull the descriptor off the
475 chain. This avoids gomp_unmap_vars via gomp_unmap_tgt from
476 freeing the device memory. */
480 for (tp
= NULL
, t
= acc_dev
->openacc
.data_environ
; t
!= NULL
;
487 acc_dev
->openacc
.data_environ
= t
->prev
;
493 gomp_mutex_unlock (&acc_dev
->lock
);
495 gomp_unmap_vars (t
, true);
499 thr
->prof_info
= NULL
;
500 thr
->api_info
= NULL
;
504 #define FLAG_PRESENT (1 << 0)
505 #define FLAG_CREATE (1 << 1)
506 #define FLAG_COPY (1 << 2)
509 present_create_copy (unsigned f
, void *h
, size_t s
, int async
)
515 gomp_fatal ("[%p,+%d] is a bad range", (void *)h
, (int)s
);
517 goacc_lazy_initialize ();
519 struct goacc_thread
*thr
= goacc_thread ();
520 struct gomp_device_descr
*acc_dev
= thr
->dev
;
522 if (acc_dev
->capabilities
& GOMP_OFFLOAD_CAP_SHARED_MEM
)
525 acc_prof_info prof_info
;
526 acc_api_info api_info
;
527 bool profiling_p
= GOACC_PROFILING_SETUP_P (thr
, &prof_info
, &api_info
);
530 prof_info
.async
= async
;
531 prof_info
.async_queue
= prof_info
.async
;
534 gomp_mutex_lock (&acc_dev
->lock
);
536 n
= lookup_host (acc_dev
, h
, s
);
540 d
= (void *) (n
->tgt
->tgt_start
+ n
->tgt_offset
);
542 if (!(f
& FLAG_PRESENT
))
544 gomp_mutex_unlock (&acc_dev
->lock
);
545 gomp_fatal ("[%p,+%d] already mapped to [%p,+%d]",
546 (void *)h
, (int)s
, (void *)d
, (int)s
);
548 if ((h
+ s
) > (void *)n
->host_end
)
550 gomp_mutex_unlock (&acc_dev
->lock
);
551 gomp_fatal ("[%p,+%d] not mapped", (void *)h
, (int)s
);
554 if (n
->refcount
!= REFCOUNT_INFINITY
)
557 n
->dynamic_refcount
++;
559 gomp_mutex_unlock (&acc_dev
->lock
);
561 else if (!(f
& FLAG_CREATE
))
563 gomp_mutex_unlock (&acc_dev
->lock
);
564 gomp_fatal ("[%p,+%d] not mapped", (void *)h
, (int)s
);
568 struct target_mem_desc
*tgt
;
570 unsigned short kinds
;
576 kinds
= GOMP_MAP_ALLOC
;
578 gomp_mutex_unlock (&acc_dev
->lock
);
580 goacc_aq aq
= get_goacc_asyncqueue (async
);
582 tgt
= gomp_map_vars_async (acc_dev
, aq
, mapnum
, &hostaddrs
, NULL
, &s
,
583 &kinds
, true, GOMP_MAP_VARS_OPENACC
);
584 /* Initialize dynamic refcount. */
585 tgt
->list
[0].key
->dynamic_refcount
= 1;
587 gomp_mutex_lock (&acc_dev
->lock
);
590 tgt
->prev
= acc_dev
->openacc
.data_environ
;
591 acc_dev
->openacc
.data_environ
= tgt
;
593 gomp_mutex_unlock (&acc_dev
->lock
);
598 thr
->prof_info
= NULL
;
599 thr
->api_info
= NULL
;
606 acc_create (void *h
, size_t s
)
608 return present_create_copy (FLAG_PRESENT
| FLAG_CREATE
, h
, s
, acc_async_sync
);
612 acc_create_async (void *h
, size_t s
, int async
)
614 present_create_copy (FLAG_PRESENT
| FLAG_CREATE
, h
, s
, async
);
617 /* acc_present_or_create used to be what acc_create is now. */
618 /* acc_pcreate is acc_present_or_create by a different name. */
619 #ifdef HAVE_ATTRIBUTE_ALIAS
620 strong_alias (acc_create
, acc_present_or_create
)
621 strong_alias (acc_create
, acc_pcreate
)
624 acc_present_or_create (void *h
, size_t s
)
626 return acc_create (h
, s
);
630 acc_pcreate (void *h
, size_t s
)
632 return acc_create (h
, s
);
637 acc_copyin (void *h
, size_t s
)
639 return present_create_copy (FLAG_PRESENT
| FLAG_CREATE
| FLAG_COPY
, h
, s
,
644 acc_copyin_async (void *h
, size_t s
, int async
)
646 present_create_copy (FLAG_PRESENT
| FLAG_CREATE
| FLAG_COPY
, h
, s
, async
);
649 /* acc_present_or_copyin used to be what acc_copyin is now. */
650 /* acc_pcopyin is acc_present_or_copyin by a different name. */
651 #ifdef HAVE_ATTRIBUTE_ALIAS
652 strong_alias (acc_copyin
, acc_present_or_copyin
)
653 strong_alias (acc_copyin
, acc_pcopyin
)
656 acc_present_or_copyin (void *h
, size_t s
)
658 return acc_copyin (h
, s
);
662 acc_pcopyin (void *h
, size_t s
)
664 return acc_copyin (h
, s
);
668 #define FLAG_COPYOUT (1 << 0)
669 #define FLAG_FINALIZE (1 << 1)
672 delete_copyout (unsigned f
, void *h
, size_t s
, int async
, const char *libfnname
)
677 struct goacc_thread
*thr
= goacc_thread ();
678 struct gomp_device_descr
*acc_dev
= thr
->dev
;
680 if (acc_dev
->capabilities
& GOMP_OFFLOAD_CAP_SHARED_MEM
)
683 acc_prof_info prof_info
;
684 acc_api_info api_info
;
685 bool profiling_p
= GOACC_PROFILING_SETUP_P (thr
, &prof_info
, &api_info
);
688 prof_info
.async
= async
;
689 prof_info
.async_queue
= prof_info
.async
;
692 gomp_mutex_lock (&acc_dev
->lock
);
694 n
= lookup_host (acc_dev
, h
, s
);
696 /* No need to call lazy open, as the data must already have been
701 gomp_mutex_unlock (&acc_dev
->lock
);
702 gomp_fatal ("[%p,%d] is not mapped", (void *)h
, (int)s
);
705 d
= (void *) (n
->tgt
->tgt_start
+ n
->tgt_offset
706 + (uintptr_t) h
- n
->host_start
);
708 host_size
= n
->host_end
- n
->host_start
;
710 if (n
->host_start
!= (uintptr_t) h
|| host_size
!= s
)
712 gomp_mutex_unlock (&acc_dev
->lock
);
713 gomp_fatal ("[%p,%d] surrounds2 [%p,+%d]",
714 (void *) n
->host_start
, (int) host_size
, (void *) h
, (int) s
);
717 if (n
->refcount
== REFCOUNT_INFINITY
)
720 n
->dynamic_refcount
= 0;
722 if (n
->refcount
< n
->dynamic_refcount
)
724 gomp_mutex_unlock (&acc_dev
->lock
);
725 gomp_fatal ("Dynamic reference counting assert fail\n");
728 if (f
& FLAG_FINALIZE
)
730 n
->refcount
-= n
->dynamic_refcount
;
731 n
->dynamic_refcount
= 0;
733 else if (n
->dynamic_refcount
)
735 n
->dynamic_refcount
--;
739 if (n
->refcount
== 0)
741 if (n
->tgt
->refcount
== 2)
743 struct target_mem_desc
*tp
, *t
;
744 for (tp
= NULL
, t
= acc_dev
->openacc
.data_environ
; t
!= NULL
;
751 acc_dev
->openacc
.data_environ
= t
->prev
;
756 if (f
& FLAG_COPYOUT
)
758 goacc_aq aq
= get_goacc_asyncqueue (async
);
759 gomp_copy_dev2host (acc_dev
, aq
, h
, d
, s
);
761 gomp_remove_var (acc_dev
, n
);
764 gomp_mutex_unlock (&acc_dev
->lock
);
768 thr
->prof_info
= NULL
;
769 thr
->api_info
= NULL
;
774 acc_delete (void *h
, size_t s
)
776 delete_copyout (0, h
, s
, acc_async_sync
, __FUNCTION__
);
780 acc_delete_async (void *h
, size_t s
, int async
)
782 delete_copyout (0, h
, s
, async
, __FUNCTION__
);
786 acc_delete_finalize (void *h
, size_t s
)
788 delete_copyout (FLAG_FINALIZE
, h
, s
, acc_async_sync
, __FUNCTION__
);
792 acc_delete_finalize_async (void *h
, size_t s
, int async
)
794 delete_copyout (FLAG_FINALIZE
, h
, s
, async
, __FUNCTION__
);
798 acc_copyout (void *h
, size_t s
)
800 delete_copyout (FLAG_COPYOUT
, h
, s
, acc_async_sync
, __FUNCTION__
);
804 acc_copyout_async (void *h
, size_t s
, int async
)
806 delete_copyout (FLAG_COPYOUT
, h
, s
, async
, __FUNCTION__
);
810 acc_copyout_finalize (void *h
, size_t s
)
812 delete_copyout (FLAG_COPYOUT
| FLAG_FINALIZE
, h
, s
, acc_async_sync
,
817 acc_copyout_finalize_async (void *h
, size_t s
, int async
)
819 delete_copyout (FLAG_COPYOUT
| FLAG_FINALIZE
, h
, s
, async
, __FUNCTION__
);
823 update_dev_host (int is_dev
, void *h
, size_t s
, int async
)
828 goacc_lazy_initialize ();
830 struct goacc_thread
*thr
= goacc_thread ();
831 struct gomp_device_descr
*acc_dev
= thr
->dev
;
833 if (acc_dev
->capabilities
& GOMP_OFFLOAD_CAP_SHARED_MEM
)
836 acc_prof_info prof_info
;
837 acc_api_info api_info
;
838 bool profiling_p
= GOACC_PROFILING_SETUP_P (thr
, &prof_info
, &api_info
);
841 prof_info
.async
= async
;
842 prof_info
.async_queue
= prof_info
.async
;
845 gomp_mutex_lock (&acc_dev
->lock
);
847 n
= lookup_host (acc_dev
, h
, s
);
851 gomp_mutex_unlock (&acc_dev
->lock
);
852 gomp_fatal ("[%p,%d] is not mapped", h
, (int)s
);
855 d
= (void *) (n
->tgt
->tgt_start
+ n
->tgt_offset
856 + (uintptr_t) h
- n
->host_start
);
858 goacc_aq aq
= get_goacc_asyncqueue (async
);
861 gomp_copy_host2dev (acc_dev
, aq
, d
, h
, s
, /* TODO: cbuf? */ NULL
);
863 gomp_copy_dev2host (acc_dev
, aq
, h
, d
, s
);
865 gomp_mutex_unlock (&acc_dev
->lock
);
869 thr
->prof_info
= NULL
;
870 thr
->api_info
= NULL
;
875 acc_update_device (void *h
, size_t s
)
877 update_dev_host (1, h
, s
, acc_async_sync
);
881 acc_update_device_async (void *h
, size_t s
, int async
)
883 update_dev_host (1, h
, s
, async
);
887 acc_update_self (void *h
, size_t s
)
889 update_dev_host (0, h
, s
, acc_async_sync
);
893 acc_update_self_async (void *h
, size_t s
, int async
)
895 update_dev_host (0, h
, s
, async
);
899 gomp_acc_insert_pointer (size_t mapnum
, void **hostaddrs
, size_t *sizes
,
900 void *kinds
, int async
)
902 struct target_mem_desc
*tgt
;
903 struct goacc_thread
*thr
= goacc_thread ();
904 struct gomp_device_descr
*acc_dev
= thr
->dev
;
906 if (acc_is_present (*hostaddrs
, *sizes
))
909 gomp_mutex_lock (&acc_dev
->lock
);
910 n
= lookup_host (acc_dev
, *hostaddrs
, *sizes
);
911 gomp_mutex_unlock (&acc_dev
->lock
);
914 for (size_t i
= 0; i
< tgt
->list_count
; i
++)
915 if (tgt
->list
[i
].key
== n
)
917 for (size_t j
= 0; j
< mapnum
; j
++)
918 if (i
+ j
< tgt
->list_count
&& tgt
->list
[i
+ j
].key
)
920 tgt
->list
[i
+ j
].key
->refcount
++;
921 tgt
->list
[i
+ j
].key
->dynamic_refcount
++;
925 /* Should not reach here. */
926 gomp_fatal ("Dynamic refcount incrementing failed for pointer/pset");
929 gomp_debug (0, " %s: prepare mappings\n", __FUNCTION__
);
930 goacc_aq aq
= get_goacc_asyncqueue (async
);
931 tgt
= gomp_map_vars_async (acc_dev
, aq
, mapnum
, hostaddrs
,
932 NULL
, sizes
, kinds
, true, GOMP_MAP_VARS_OPENACC
);
933 gomp_debug (0, " %s: mappings prepared\n", __FUNCTION__
);
935 /* Initialize dynamic refcount. */
936 tgt
->list
[0].key
->dynamic_refcount
= 1;
938 gomp_mutex_lock (&acc_dev
->lock
);
939 tgt
->prev
= acc_dev
->openacc
.data_environ
;
940 acc_dev
->openacc
.data_environ
= tgt
;
941 gomp_mutex_unlock (&acc_dev
->lock
);
945 gomp_acc_remove_pointer (void *h
, size_t s
, bool force_copyfrom
, int async
,
946 int finalize
, int mapnum
)
948 struct goacc_thread
*thr
= goacc_thread ();
949 struct gomp_device_descr
*acc_dev
= thr
->dev
;
951 struct target_mem_desc
*t
;
952 int minrefs
= (mapnum
== 1) ? 2 : 3;
954 if (!acc_is_present (h
, s
))
957 gomp_mutex_lock (&acc_dev
->lock
);
959 n
= lookup_host (acc_dev
, h
, 1);
963 gomp_mutex_unlock (&acc_dev
->lock
);
964 gomp_fatal ("%p is not a mapped block", (void *)h
);
967 gomp_debug (0, " %s: restore mappings\n", __FUNCTION__
);
971 if (n
->refcount
< n
->dynamic_refcount
)
973 gomp_mutex_unlock (&acc_dev
->lock
);
974 gomp_fatal ("Dynamic reference counting assert fail\n");
979 n
->refcount
-= n
->dynamic_refcount
;
980 n
->dynamic_refcount
= 0;
982 else if (n
->dynamic_refcount
)
984 n
->dynamic_refcount
--;
988 gomp_mutex_unlock (&acc_dev
->lock
);
990 if (n
->refcount
== 0)
992 if (t
->refcount
== minrefs
)
994 /* This is the last reference, so pull the descriptor off the
995 chain. This prevents gomp_unmap_vars via gomp_unmap_tgt from
996 freeing the device memory. */
997 struct target_mem_desc
*tp
;
998 for (tp
= NULL
, t
= acc_dev
->openacc
.data_environ
; t
!= NULL
;
1006 acc_dev
->openacc
.data_environ
= t
->prev
;
1012 /* Set refcount to 1 to allow gomp_unmap_vars to unmap it. */
1014 t
->refcount
= minrefs
;
1015 for (size_t i
= 0; i
< t
->list_count
; i
++)
1016 if (t
->list
[i
].key
== n
)
1018 t
->list
[i
].copy_from
= force_copyfrom
? 1 : 0;
1022 /* If running synchronously, unmap immediately. */
1023 if (async
< acc_async_noval
)
1024 gomp_unmap_vars (t
, true);
1027 goacc_aq aq
= get_goacc_asyncqueue (async
);
1028 gomp_unmap_vars_async (t
, true, aq
);
1032 gomp_mutex_unlock (&acc_dev
->lock
);
1034 gomp_debug (0, " %s: mappings restored\n", __FUNCTION__
);