annotate libgomp/target.c @ 121:49957f95a4d1

fix fntype
author anatofuz
date Fri, 09 Mar 2018 19:18:14 +0900
parents 04ced10e8804
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Copyright (C) 2013-2017 Free Software Foundation, Inc.
kono
parents:
diff changeset
2 Contributed by Jakub Jelinek <jakub@redhat.com>.
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is part of the GNU Offloading and Multi Processing Library
kono
parents:
diff changeset
5 (libgomp).
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 Libgomp is free software; you can redistribute it and/or modify it
kono
parents:
diff changeset
8 under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
9 the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
10 any later version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
kono
parents:
diff changeset
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
kono
parents:
diff changeset
15 more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 Under Section 7 of GPL version 3, you are granted additional
kono
parents:
diff changeset
18 permissions described in the GCC Runtime Library Exception, version
kono
parents:
diff changeset
19 3.1, as published by the Free Software Foundation.
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 You should have received a copy of the GNU General Public License and
kono
parents:
diff changeset
22 a copy of the GCC Runtime Library Exception along with this program;
kono
parents:
diff changeset
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
kono
parents:
diff changeset
24 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
25
kono
parents:
diff changeset
26 /* This file contains the support of offloading. */
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 #include "config.h"
kono
parents:
diff changeset
29 #include "libgomp.h"
kono
parents:
diff changeset
30 #include "oacc-plugin.h"
kono
parents:
diff changeset
31 #include "oacc-int.h"
kono
parents:
diff changeset
32 #include "gomp-constants.h"
kono
parents:
diff changeset
33 #include <limits.h>
kono
parents:
diff changeset
34 #include <stdbool.h>
kono
parents:
diff changeset
35 #include <stdlib.h>
kono
parents:
diff changeset
36 #ifdef HAVE_INTTYPES_H
kono
parents:
diff changeset
37 # include <inttypes.h> /* For PRIu64. */
kono
parents:
diff changeset
38 #endif
kono
parents:
diff changeset
39 #include <string.h>
kono
parents:
diff changeset
40 #include <assert.h>
kono
parents:
diff changeset
41 #include <errno.h>
kono
parents:
diff changeset
42
kono
parents:
diff changeset
43 #ifdef PLUGIN_SUPPORT
kono
parents:
diff changeset
44 #include <dlfcn.h>
kono
parents:
diff changeset
45 #include "plugin-suffix.h"
kono
parents:
diff changeset
46 #endif
kono
parents:
diff changeset
47
kono
parents:
diff changeset
48 static void gomp_target_init (void);
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 /* The whole initialization code for offloading plugins is only run one. */
kono
parents:
diff changeset
51 static pthread_once_t gomp_is_initialized = PTHREAD_ONCE_INIT;
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 /* Mutex for offload image registration. */
kono
parents:
diff changeset
54 static gomp_mutex_t register_lock;
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 /* This structure describes an offload image.
kono
parents:
diff changeset
57 It contains type of the target device, pointer to host table descriptor, and
kono
parents:
diff changeset
58 pointer to target data. */
kono
parents:
diff changeset
59 struct offload_image_descr {
kono
parents:
diff changeset
60 unsigned version;
kono
parents:
diff changeset
61 enum offload_target_type type;
kono
parents:
diff changeset
62 const void *host_table;
kono
parents:
diff changeset
63 const void *target_data;
kono
parents:
diff changeset
64 };
kono
parents:
diff changeset
65
kono
parents:
diff changeset
66 /* Array of descriptors of offload images. */
kono
parents:
diff changeset
67 static struct offload_image_descr *offload_images;
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 /* Total number of offload images. */
kono
parents:
diff changeset
70 static int num_offload_images;
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 /* Array of descriptors for all available devices. */
kono
parents:
diff changeset
73 static struct gomp_device_descr *devices;
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 /* Total number of available devices. */
kono
parents:
diff changeset
76 static int num_devices;
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 /* Number of GOMP_OFFLOAD_CAP_OPENMP_400 devices. */
kono
parents:
diff changeset
79 static int num_devices_openmp;
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 /* Similar to gomp_realloc, but release register_lock before gomp_fatal. */
kono
parents:
diff changeset
82
kono
parents:
diff changeset
83 static void *
kono
parents:
diff changeset
84 gomp_realloc_unlock (void *old, size_t size)
kono
parents:
diff changeset
85 {
kono
parents:
diff changeset
86 void *ret = realloc (old, size);
kono
parents:
diff changeset
87 if (ret == NULL)
kono
parents:
diff changeset
88 {
kono
parents:
diff changeset
89 gomp_mutex_unlock (&register_lock);
kono
parents:
diff changeset
90 gomp_fatal ("Out of memory allocating %lu bytes", (unsigned long) size);
kono
parents:
diff changeset
91 }
kono
parents:
diff changeset
92 return ret;
kono
parents:
diff changeset
93 }
kono
parents:
diff changeset
94
kono
parents:
diff changeset
95 attribute_hidden void
kono
parents:
diff changeset
96 gomp_init_targets_once (void)
kono
parents:
diff changeset
97 {
kono
parents:
diff changeset
98 (void) pthread_once (&gomp_is_initialized, gomp_target_init);
kono
parents:
diff changeset
99 }
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 attribute_hidden int
kono
parents:
diff changeset
102 gomp_get_num_devices (void)
kono
parents:
diff changeset
103 {
kono
parents:
diff changeset
104 gomp_init_targets_once ();
kono
parents:
diff changeset
105 return num_devices_openmp;
kono
parents:
diff changeset
106 }
kono
parents:
diff changeset
107
kono
parents:
diff changeset
108 static struct gomp_device_descr *
kono
parents:
diff changeset
109 resolve_device (int device_id)
kono
parents:
diff changeset
110 {
kono
parents:
diff changeset
111 if (device_id == GOMP_DEVICE_ICV)
kono
parents:
diff changeset
112 {
kono
parents:
diff changeset
113 struct gomp_task_icv *icv = gomp_icv (false);
kono
parents:
diff changeset
114 device_id = icv->default_device_var;
kono
parents:
diff changeset
115 }
kono
parents:
diff changeset
116
kono
parents:
diff changeset
117 if (device_id < 0 || device_id >= gomp_get_num_devices ())
kono
parents:
diff changeset
118 return NULL;
kono
parents:
diff changeset
119
kono
parents:
diff changeset
120 gomp_mutex_lock (&devices[device_id].lock);
kono
parents:
diff changeset
121 if (devices[device_id].state == GOMP_DEVICE_UNINITIALIZED)
kono
parents:
diff changeset
122 gomp_init_device (&devices[device_id]);
kono
parents:
diff changeset
123 else if (devices[device_id].state == GOMP_DEVICE_FINALIZED)
kono
parents:
diff changeset
124 {
kono
parents:
diff changeset
125 gomp_mutex_unlock (&devices[device_id].lock);
kono
parents:
diff changeset
126 return NULL;
kono
parents:
diff changeset
127 }
kono
parents:
diff changeset
128 gomp_mutex_unlock (&devices[device_id].lock);
kono
parents:
diff changeset
129
kono
parents:
diff changeset
130 return &devices[device_id];
kono
parents:
diff changeset
131 }
kono
parents:
diff changeset
132
kono
parents:
diff changeset
133
kono
parents:
diff changeset
134 static inline splay_tree_key
kono
parents:
diff changeset
135 gomp_map_lookup (splay_tree mem_map, splay_tree_key key)
kono
parents:
diff changeset
136 {
kono
parents:
diff changeset
137 if (key->host_start != key->host_end)
kono
parents:
diff changeset
138 return splay_tree_lookup (mem_map, key);
kono
parents:
diff changeset
139
kono
parents:
diff changeset
140 key->host_end++;
kono
parents:
diff changeset
141 splay_tree_key n = splay_tree_lookup (mem_map, key);
kono
parents:
diff changeset
142 key->host_end--;
kono
parents:
diff changeset
143 if (n)
kono
parents:
diff changeset
144 return n;
kono
parents:
diff changeset
145 key->host_start--;
kono
parents:
diff changeset
146 n = splay_tree_lookup (mem_map, key);
kono
parents:
diff changeset
147 key->host_start++;
kono
parents:
diff changeset
148 if (n)
kono
parents:
diff changeset
149 return n;
kono
parents:
diff changeset
150 return splay_tree_lookup (mem_map, key);
kono
parents:
diff changeset
151 }
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 static inline splay_tree_key
kono
parents:
diff changeset
154 gomp_map_0len_lookup (splay_tree mem_map, splay_tree_key key)
kono
parents:
diff changeset
155 {
kono
parents:
diff changeset
156 if (key->host_start != key->host_end)
kono
parents:
diff changeset
157 return splay_tree_lookup (mem_map, key);
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 key->host_end++;
kono
parents:
diff changeset
160 splay_tree_key n = splay_tree_lookup (mem_map, key);
kono
parents:
diff changeset
161 key->host_end--;
kono
parents:
diff changeset
162 return n;
kono
parents:
diff changeset
163 }
kono
parents:
diff changeset
164
kono
parents:
diff changeset
165 static inline void
kono
parents:
diff changeset
166 gomp_device_copy (struct gomp_device_descr *devicep,
kono
parents:
diff changeset
167 bool (*copy_func) (int, void *, const void *, size_t),
kono
parents:
diff changeset
168 const char *dst, void *dstaddr,
kono
parents:
diff changeset
169 const char *src, const void *srcaddr,
kono
parents:
diff changeset
170 size_t size)
kono
parents:
diff changeset
171 {
kono
parents:
diff changeset
172 if (!copy_func (devicep->target_id, dstaddr, srcaddr, size))
kono
parents:
diff changeset
173 {
kono
parents:
diff changeset
174 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
175 gomp_fatal ("Copying of %s object [%p..%p) to %s object [%p..%p) failed",
kono
parents:
diff changeset
176 src, srcaddr, srcaddr + size, dst, dstaddr, dstaddr + size);
kono
parents:
diff changeset
177 }
kono
parents:
diff changeset
178 }
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 static void
kono
parents:
diff changeset
181 gomp_copy_host2dev (struct gomp_device_descr *devicep,
kono
parents:
diff changeset
182 void *d, const void *h, size_t sz)
kono
parents:
diff changeset
183 {
kono
parents:
diff changeset
184 gomp_device_copy (devicep, devicep->host2dev_func, "dev", d, "host", h, sz);
kono
parents:
diff changeset
185 }
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 static void
kono
parents:
diff changeset
188 gomp_copy_dev2host (struct gomp_device_descr *devicep,
kono
parents:
diff changeset
189 void *h, const void *d, size_t sz)
kono
parents:
diff changeset
190 {
kono
parents:
diff changeset
191 gomp_device_copy (devicep, devicep->dev2host_func, "host", h, "dev", d, sz);
kono
parents:
diff changeset
192 }
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 static void
kono
parents:
diff changeset
195 gomp_free_device_memory (struct gomp_device_descr *devicep, void *devptr)
kono
parents:
diff changeset
196 {
kono
parents:
diff changeset
197 if (!devicep->free_func (devicep->target_id, devptr))
kono
parents:
diff changeset
198 {
kono
parents:
diff changeset
199 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
200 gomp_fatal ("error in freeing device memory block at %p", devptr);
kono
parents:
diff changeset
201 }
kono
parents:
diff changeset
202 }
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 /* Handle the case where gomp_map_lookup, splay_tree_lookup or
kono
parents:
diff changeset
205 gomp_map_0len_lookup found oldn for newn.
kono
parents:
diff changeset
206 Helper function of gomp_map_vars. */
kono
parents:
diff changeset
207
kono
parents:
diff changeset
208 static inline void
kono
parents:
diff changeset
209 gomp_map_vars_existing (struct gomp_device_descr *devicep, splay_tree_key oldn,
kono
parents:
diff changeset
210 splay_tree_key newn, struct target_var_desc *tgt_var,
kono
parents:
diff changeset
211 unsigned char kind)
kono
parents:
diff changeset
212 {
kono
parents:
diff changeset
213 tgt_var->key = oldn;
kono
parents:
diff changeset
214 tgt_var->copy_from = GOMP_MAP_COPY_FROM_P (kind);
kono
parents:
diff changeset
215 tgt_var->always_copy_from = GOMP_MAP_ALWAYS_FROM_P (kind);
kono
parents:
diff changeset
216 tgt_var->offset = newn->host_start - oldn->host_start;
kono
parents:
diff changeset
217 tgt_var->length = newn->host_end - newn->host_start;
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 if ((kind & GOMP_MAP_FLAG_FORCE)
kono
parents:
diff changeset
220 || oldn->host_start > newn->host_start
kono
parents:
diff changeset
221 || oldn->host_end < newn->host_end)
kono
parents:
diff changeset
222 {
kono
parents:
diff changeset
223 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
224 gomp_fatal ("Trying to map into device [%p..%p) object when "
kono
parents:
diff changeset
225 "[%p..%p) is already mapped",
kono
parents:
diff changeset
226 (void *) newn->host_start, (void *) newn->host_end,
kono
parents:
diff changeset
227 (void *) oldn->host_start, (void *) oldn->host_end);
kono
parents:
diff changeset
228 }
kono
parents:
diff changeset
229
kono
parents:
diff changeset
230 if (GOMP_MAP_ALWAYS_TO_P (kind))
kono
parents:
diff changeset
231 gomp_copy_host2dev (devicep,
kono
parents:
diff changeset
232 (void *) (oldn->tgt->tgt_start + oldn->tgt_offset
kono
parents:
diff changeset
233 + newn->host_start - oldn->host_start),
kono
parents:
diff changeset
234 (void *) newn->host_start,
kono
parents:
diff changeset
235 newn->host_end - newn->host_start);
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 if (oldn->refcount != REFCOUNT_INFINITY)
kono
parents:
diff changeset
238 oldn->refcount++;
kono
parents:
diff changeset
239 }
kono
parents:
diff changeset
240
kono
parents:
diff changeset
241 static int
kono
parents:
diff changeset
242 get_kind (bool short_mapkind, void *kinds, int idx)
kono
parents:
diff changeset
243 {
kono
parents:
diff changeset
244 return short_mapkind ? ((unsigned short *) kinds)[idx]
kono
parents:
diff changeset
245 : ((unsigned char *) kinds)[idx];
kono
parents:
diff changeset
246 }
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 static void
kono
parents:
diff changeset
249 gomp_map_pointer (struct target_mem_desc *tgt, uintptr_t host_ptr,
kono
parents:
diff changeset
250 uintptr_t target_offset, uintptr_t bias)
kono
parents:
diff changeset
251 {
kono
parents:
diff changeset
252 struct gomp_device_descr *devicep = tgt->device_descr;
kono
parents:
diff changeset
253 struct splay_tree_s *mem_map = &devicep->mem_map;
kono
parents:
diff changeset
254 struct splay_tree_key_s cur_node;
kono
parents:
diff changeset
255
kono
parents:
diff changeset
256 cur_node.host_start = host_ptr;
kono
parents:
diff changeset
257 if (cur_node.host_start == (uintptr_t) NULL)
kono
parents:
diff changeset
258 {
kono
parents:
diff changeset
259 cur_node.tgt_offset = (uintptr_t) NULL;
kono
parents:
diff changeset
260 /* FIXME: see comment about coalescing host/dev transfers below. */
kono
parents:
diff changeset
261 gomp_copy_host2dev (devicep,
kono
parents:
diff changeset
262 (void *) (tgt->tgt_start + target_offset),
kono
parents:
diff changeset
263 (void *) &cur_node.tgt_offset,
kono
parents:
diff changeset
264 sizeof (void *));
kono
parents:
diff changeset
265 return;
kono
parents:
diff changeset
266 }
kono
parents:
diff changeset
267 /* Add bias to the pointer value. */
kono
parents:
diff changeset
268 cur_node.host_start += bias;
kono
parents:
diff changeset
269 cur_node.host_end = cur_node.host_start;
kono
parents:
diff changeset
270 splay_tree_key n = gomp_map_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
271 if (n == NULL)
kono
parents:
diff changeset
272 {
kono
parents:
diff changeset
273 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
274 gomp_fatal ("Pointer target of array section wasn't mapped");
kono
parents:
diff changeset
275 }
kono
parents:
diff changeset
276 cur_node.host_start -= n->host_start;
kono
parents:
diff changeset
277 cur_node.tgt_offset
kono
parents:
diff changeset
278 = n->tgt->tgt_start + n->tgt_offset + cur_node.host_start;
kono
parents:
diff changeset
279 /* At this point tgt_offset is target address of the
kono
parents:
diff changeset
280 array section. Now subtract bias to get what we want
kono
parents:
diff changeset
281 to initialize the pointer with. */
kono
parents:
diff changeset
282 cur_node.tgt_offset -= bias;
kono
parents:
diff changeset
283 /* FIXME: see comment about coalescing host/dev transfers below. */
kono
parents:
diff changeset
284 gomp_copy_host2dev (devicep, (void *) (tgt->tgt_start + target_offset),
kono
parents:
diff changeset
285 (void *) &cur_node.tgt_offset, sizeof (void *));
kono
parents:
diff changeset
286 }
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 static void
kono
parents:
diff changeset
289 gomp_map_fields_existing (struct target_mem_desc *tgt, splay_tree_key n,
kono
parents:
diff changeset
290 size_t first, size_t i, void **hostaddrs,
kono
parents:
diff changeset
291 size_t *sizes, void *kinds)
kono
parents:
diff changeset
292 {
kono
parents:
diff changeset
293 struct gomp_device_descr *devicep = tgt->device_descr;
kono
parents:
diff changeset
294 struct splay_tree_s *mem_map = &devicep->mem_map;
kono
parents:
diff changeset
295 struct splay_tree_key_s cur_node;
kono
parents:
diff changeset
296 int kind;
kono
parents:
diff changeset
297 const bool short_mapkind = true;
kono
parents:
diff changeset
298 const int typemask = short_mapkind ? 0xff : 0x7;
kono
parents:
diff changeset
299
kono
parents:
diff changeset
300 cur_node.host_start = (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
301 cur_node.host_end = cur_node.host_start + sizes[i];
kono
parents:
diff changeset
302 splay_tree_key n2 = splay_tree_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
303 kind = get_kind (short_mapkind, kinds, i);
kono
parents:
diff changeset
304 if (n2
kono
parents:
diff changeset
305 && n2->tgt == n->tgt
kono
parents:
diff changeset
306 && n2->host_start - n->host_start == n2->tgt_offset - n->tgt_offset)
kono
parents:
diff changeset
307 {
kono
parents:
diff changeset
308 gomp_map_vars_existing (devicep, n2, &cur_node,
kono
parents:
diff changeset
309 &tgt->list[i], kind & typemask);
kono
parents:
diff changeset
310 return;
kono
parents:
diff changeset
311 }
kono
parents:
diff changeset
312 if (sizes[i] == 0)
kono
parents:
diff changeset
313 {
kono
parents:
diff changeset
314 if (cur_node.host_start > (uintptr_t) hostaddrs[first - 1])
kono
parents:
diff changeset
315 {
kono
parents:
diff changeset
316 cur_node.host_start--;
kono
parents:
diff changeset
317 n2 = splay_tree_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
318 cur_node.host_start++;
kono
parents:
diff changeset
319 if (n2
kono
parents:
diff changeset
320 && n2->tgt == n->tgt
kono
parents:
diff changeset
321 && n2->host_start - n->host_start
kono
parents:
diff changeset
322 == n2->tgt_offset - n->tgt_offset)
kono
parents:
diff changeset
323 {
kono
parents:
diff changeset
324 gomp_map_vars_existing (devicep, n2, &cur_node, &tgt->list[i],
kono
parents:
diff changeset
325 kind & typemask);
kono
parents:
diff changeset
326 return;
kono
parents:
diff changeset
327 }
kono
parents:
diff changeset
328 }
kono
parents:
diff changeset
329 cur_node.host_end++;
kono
parents:
diff changeset
330 n2 = splay_tree_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
331 cur_node.host_end--;
kono
parents:
diff changeset
332 if (n2
kono
parents:
diff changeset
333 && n2->tgt == n->tgt
kono
parents:
diff changeset
334 && n2->host_start - n->host_start == n2->tgt_offset - n->tgt_offset)
kono
parents:
diff changeset
335 {
kono
parents:
diff changeset
336 gomp_map_vars_existing (devicep, n2, &cur_node, &tgt->list[i],
kono
parents:
diff changeset
337 kind & typemask);
kono
parents:
diff changeset
338 return;
kono
parents:
diff changeset
339 }
kono
parents:
diff changeset
340 }
kono
parents:
diff changeset
341 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
342 gomp_fatal ("Trying to map into device [%p..%p) structure element when "
kono
parents:
diff changeset
343 "other mapped elements from the same structure weren't mapped "
kono
parents:
diff changeset
344 "together with it", (void *) cur_node.host_start,
kono
parents:
diff changeset
345 (void *) cur_node.host_end);
kono
parents:
diff changeset
346 }
kono
parents:
diff changeset
347
kono
parents:
diff changeset
348 static inline uintptr_t
kono
parents:
diff changeset
349 gomp_map_val (struct target_mem_desc *tgt, void **hostaddrs, size_t i)
kono
parents:
diff changeset
350 {
kono
parents:
diff changeset
351 if (tgt->list[i].key != NULL)
kono
parents:
diff changeset
352 return tgt->list[i].key->tgt->tgt_start
kono
parents:
diff changeset
353 + tgt->list[i].key->tgt_offset
kono
parents:
diff changeset
354 + tgt->list[i].offset;
kono
parents:
diff changeset
355 if (tgt->list[i].offset == ~(uintptr_t) 0)
kono
parents:
diff changeset
356 return (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
357 if (tgt->list[i].offset == ~(uintptr_t) 1)
kono
parents:
diff changeset
358 return 0;
kono
parents:
diff changeset
359 if (tgt->list[i].offset == ~(uintptr_t) 2)
kono
parents:
diff changeset
360 return tgt->list[i + 1].key->tgt->tgt_start
kono
parents:
diff changeset
361 + tgt->list[i + 1].key->tgt_offset
kono
parents:
diff changeset
362 + tgt->list[i + 1].offset
kono
parents:
diff changeset
363 + (uintptr_t) hostaddrs[i]
kono
parents:
diff changeset
364 - (uintptr_t) hostaddrs[i + 1];
kono
parents:
diff changeset
365 return tgt->tgt_start + tgt->list[i].offset;
kono
parents:
diff changeset
366 }
kono
parents:
diff changeset
367
kono
parents:
diff changeset
368 attribute_hidden struct target_mem_desc *
kono
parents:
diff changeset
369 gomp_map_vars (struct gomp_device_descr *devicep, size_t mapnum,
kono
parents:
diff changeset
370 void **hostaddrs, void **devaddrs, size_t *sizes, void *kinds,
kono
parents:
diff changeset
371 bool short_mapkind, enum gomp_map_vars_kind pragma_kind)
kono
parents:
diff changeset
372 {
kono
parents:
diff changeset
373 size_t i, tgt_align, tgt_size, not_found_cnt = 0;
kono
parents:
diff changeset
374 bool has_firstprivate = false;
kono
parents:
diff changeset
375 const int rshift = short_mapkind ? 8 : 3;
kono
parents:
diff changeset
376 const int typemask = short_mapkind ? 0xff : 0x7;
kono
parents:
diff changeset
377 struct splay_tree_s *mem_map = &devicep->mem_map;
kono
parents:
diff changeset
378 struct splay_tree_key_s cur_node;
kono
parents:
diff changeset
379 struct target_mem_desc *tgt
kono
parents:
diff changeset
380 = gomp_malloc (sizeof (*tgt) + sizeof (tgt->list[0]) * mapnum);
kono
parents:
diff changeset
381 tgt->list_count = mapnum;
kono
parents:
diff changeset
382 tgt->refcount = pragma_kind == GOMP_MAP_VARS_ENTER_DATA ? 0 : 1;
kono
parents:
diff changeset
383 tgt->device_descr = devicep;
kono
parents:
diff changeset
384
kono
parents:
diff changeset
385 if (mapnum == 0)
kono
parents:
diff changeset
386 {
kono
parents:
diff changeset
387 tgt->tgt_start = 0;
kono
parents:
diff changeset
388 tgt->tgt_end = 0;
kono
parents:
diff changeset
389 return tgt;
kono
parents:
diff changeset
390 }
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392 tgt_align = sizeof (void *);
kono
parents:
diff changeset
393 tgt_size = 0;
kono
parents:
diff changeset
394 if (pragma_kind == GOMP_MAP_VARS_TARGET)
kono
parents:
diff changeset
395 {
kono
parents:
diff changeset
396 size_t align = 4 * sizeof (void *);
kono
parents:
diff changeset
397 tgt_align = align;
kono
parents:
diff changeset
398 tgt_size = mapnum * sizeof (void *);
kono
parents:
diff changeset
399 }
kono
parents:
diff changeset
400
kono
parents:
diff changeset
401 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
402 if (devicep->state == GOMP_DEVICE_FINALIZED)
kono
parents:
diff changeset
403 {
kono
parents:
diff changeset
404 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
405 free (tgt);
kono
parents:
diff changeset
406 return NULL;
kono
parents:
diff changeset
407 }
kono
parents:
diff changeset
408
kono
parents:
diff changeset
409 for (i = 0; i < mapnum; i++)
kono
parents:
diff changeset
410 {
kono
parents:
diff changeset
411 int kind = get_kind (short_mapkind, kinds, i);
kono
parents:
diff changeset
412 if (hostaddrs[i] == NULL
kono
parents:
diff changeset
413 || (kind & typemask) == GOMP_MAP_FIRSTPRIVATE_INT)
kono
parents:
diff changeset
414 {
kono
parents:
diff changeset
415 tgt->list[i].key = NULL;
kono
parents:
diff changeset
416 tgt->list[i].offset = ~(uintptr_t) 0;
kono
parents:
diff changeset
417 continue;
kono
parents:
diff changeset
418 }
kono
parents:
diff changeset
419 else if ((kind & typemask) == GOMP_MAP_USE_DEVICE_PTR)
kono
parents:
diff changeset
420 {
kono
parents:
diff changeset
421 cur_node.host_start = (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
422 cur_node.host_end = cur_node.host_start;
kono
parents:
diff changeset
423 splay_tree_key n = gomp_map_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
424 if (n == NULL)
kono
parents:
diff changeset
425 {
kono
parents:
diff changeset
426 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
427 gomp_fatal ("use_device_ptr pointer wasn't mapped");
kono
parents:
diff changeset
428 }
kono
parents:
diff changeset
429 cur_node.host_start -= n->host_start;
kono
parents:
diff changeset
430 hostaddrs[i]
kono
parents:
diff changeset
431 = (void *) (n->tgt->tgt_start + n->tgt_offset
kono
parents:
diff changeset
432 + cur_node.host_start);
kono
parents:
diff changeset
433 tgt->list[i].key = NULL;
kono
parents:
diff changeset
434 tgt->list[i].offset = ~(uintptr_t) 0;
kono
parents:
diff changeset
435 continue;
kono
parents:
diff changeset
436 }
kono
parents:
diff changeset
437 else if ((kind & typemask) == GOMP_MAP_STRUCT)
kono
parents:
diff changeset
438 {
kono
parents:
diff changeset
439 size_t first = i + 1;
kono
parents:
diff changeset
440 size_t last = i + sizes[i];
kono
parents:
diff changeset
441 cur_node.host_start = (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
442 cur_node.host_end = (uintptr_t) hostaddrs[last]
kono
parents:
diff changeset
443 + sizes[last];
kono
parents:
diff changeset
444 tgt->list[i].key = NULL;
kono
parents:
diff changeset
445 tgt->list[i].offset = ~(uintptr_t) 2;
kono
parents:
diff changeset
446 splay_tree_key n = splay_tree_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
447 if (n == NULL)
kono
parents:
diff changeset
448 {
kono
parents:
diff changeset
449 size_t align = (size_t) 1 << (kind >> rshift);
kono
parents:
diff changeset
450 if (tgt_align < align)
kono
parents:
diff changeset
451 tgt_align = align;
kono
parents:
diff changeset
452 tgt_size -= (uintptr_t) hostaddrs[first]
kono
parents:
diff changeset
453 - (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
454 tgt_size = (tgt_size + align - 1) & ~(align - 1);
kono
parents:
diff changeset
455 tgt_size += cur_node.host_end - (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
456 not_found_cnt += last - i;
kono
parents:
diff changeset
457 for (i = first; i <= last; i++)
kono
parents:
diff changeset
458 tgt->list[i].key = NULL;
kono
parents:
diff changeset
459 i--;
kono
parents:
diff changeset
460 continue;
kono
parents:
diff changeset
461 }
kono
parents:
diff changeset
462 for (i = first; i <= last; i++)
kono
parents:
diff changeset
463 gomp_map_fields_existing (tgt, n, first, i, hostaddrs,
kono
parents:
diff changeset
464 sizes, kinds);
kono
parents:
diff changeset
465 i--;
kono
parents:
diff changeset
466 continue;
kono
parents:
diff changeset
467 }
kono
parents:
diff changeset
468 else if ((kind & typemask) == GOMP_MAP_ALWAYS_POINTER)
kono
parents:
diff changeset
469 {
kono
parents:
diff changeset
470 tgt->list[i].key = NULL;
kono
parents:
diff changeset
471 tgt->list[i].offset = ~(uintptr_t) 1;
kono
parents:
diff changeset
472 has_firstprivate = true;
kono
parents:
diff changeset
473 continue;
kono
parents:
diff changeset
474 }
kono
parents:
diff changeset
475 cur_node.host_start = (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
476 if (!GOMP_MAP_POINTER_P (kind & typemask))
kono
parents:
diff changeset
477 cur_node.host_end = cur_node.host_start + sizes[i];
kono
parents:
diff changeset
478 else
kono
parents:
diff changeset
479 cur_node.host_end = cur_node.host_start + sizeof (void *);
kono
parents:
diff changeset
480 if ((kind & typemask) == GOMP_MAP_FIRSTPRIVATE)
kono
parents:
diff changeset
481 {
kono
parents:
diff changeset
482 tgt->list[i].key = NULL;
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 size_t align = (size_t) 1 << (kind >> rshift);
kono
parents:
diff changeset
485 if (tgt_align < align)
kono
parents:
diff changeset
486 tgt_align = align;
kono
parents:
diff changeset
487 tgt_size = (tgt_size + align - 1) & ~(align - 1);
kono
parents:
diff changeset
488 tgt_size += cur_node.host_end - cur_node.host_start;
kono
parents:
diff changeset
489 has_firstprivate = true;
kono
parents:
diff changeset
490 continue;
kono
parents:
diff changeset
491 }
kono
parents:
diff changeset
492 splay_tree_key n;
kono
parents:
diff changeset
493 if ((kind & typemask) == GOMP_MAP_ZERO_LEN_ARRAY_SECTION)
kono
parents:
diff changeset
494 {
kono
parents:
diff changeset
495 n = gomp_map_0len_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
496 if (!n)
kono
parents:
diff changeset
497 {
kono
parents:
diff changeset
498 tgt->list[i].key = NULL;
kono
parents:
diff changeset
499 tgt->list[i].offset = ~(uintptr_t) 1;
kono
parents:
diff changeset
500 continue;
kono
parents:
diff changeset
501 }
kono
parents:
diff changeset
502 }
kono
parents:
diff changeset
503 else
kono
parents:
diff changeset
504 n = splay_tree_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
505 if (n && n->refcount != REFCOUNT_LINK)
kono
parents:
diff changeset
506 gomp_map_vars_existing (devicep, n, &cur_node, &tgt->list[i],
kono
parents:
diff changeset
507 kind & typemask);
kono
parents:
diff changeset
508 else
kono
parents:
diff changeset
509 {
kono
parents:
diff changeset
510 tgt->list[i].key = NULL;
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 size_t align = (size_t) 1 << (kind >> rshift);
kono
parents:
diff changeset
513 not_found_cnt++;
kono
parents:
diff changeset
514 if (tgt_align < align)
kono
parents:
diff changeset
515 tgt_align = align;
kono
parents:
diff changeset
516 tgt_size = (tgt_size + align - 1) & ~(align - 1);
kono
parents:
diff changeset
517 tgt_size += cur_node.host_end - cur_node.host_start;
kono
parents:
diff changeset
518 if ((kind & typemask) == GOMP_MAP_TO_PSET)
kono
parents:
diff changeset
519 {
kono
parents:
diff changeset
520 size_t j;
kono
parents:
diff changeset
521 for (j = i + 1; j < mapnum; j++)
kono
parents:
diff changeset
522 if (!GOMP_MAP_POINTER_P (get_kind (short_mapkind, kinds, j)
kono
parents:
diff changeset
523 & typemask))
kono
parents:
diff changeset
524 break;
kono
parents:
diff changeset
525 else if ((uintptr_t) hostaddrs[j] < cur_node.host_start
kono
parents:
diff changeset
526 || ((uintptr_t) hostaddrs[j] + sizeof (void *)
kono
parents:
diff changeset
527 > cur_node.host_end))
kono
parents:
diff changeset
528 break;
kono
parents:
diff changeset
529 else
kono
parents:
diff changeset
530 {
kono
parents:
diff changeset
531 tgt->list[j].key = NULL;
kono
parents:
diff changeset
532 i++;
kono
parents:
diff changeset
533 }
kono
parents:
diff changeset
534 }
kono
parents:
diff changeset
535 }
kono
parents:
diff changeset
536 }
kono
parents:
diff changeset
537
kono
parents:
diff changeset
538 if (devaddrs)
kono
parents:
diff changeset
539 {
kono
parents:
diff changeset
540 if (mapnum != 1)
kono
parents:
diff changeset
541 {
kono
parents:
diff changeset
542 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
543 gomp_fatal ("unexpected aggregation");
kono
parents:
diff changeset
544 }
kono
parents:
diff changeset
545 tgt->to_free = devaddrs[0];
kono
parents:
diff changeset
546 tgt->tgt_start = (uintptr_t) tgt->to_free;
kono
parents:
diff changeset
547 tgt->tgt_end = tgt->tgt_start + sizes[0];
kono
parents:
diff changeset
548 }
kono
parents:
diff changeset
549 else if (not_found_cnt || pragma_kind == GOMP_MAP_VARS_TARGET)
kono
parents:
diff changeset
550 {
kono
parents:
diff changeset
551 /* Allocate tgt_align aligned tgt_size block of memory. */
kono
parents:
diff changeset
552 /* FIXME: Perhaps change interface to allocate properly aligned
kono
parents:
diff changeset
553 memory. */
kono
parents:
diff changeset
554 tgt->to_free = devicep->alloc_func (devicep->target_id,
kono
parents:
diff changeset
555 tgt_size + tgt_align - 1);
kono
parents:
diff changeset
556 if (!tgt->to_free)
kono
parents:
diff changeset
557 {
kono
parents:
diff changeset
558 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
559 gomp_fatal ("device memory allocation fail");
kono
parents:
diff changeset
560 }
kono
parents:
diff changeset
561
kono
parents:
diff changeset
562 tgt->tgt_start = (uintptr_t) tgt->to_free;
kono
parents:
diff changeset
563 tgt->tgt_start = (tgt->tgt_start + tgt_align - 1) & ~(tgt_align - 1);
kono
parents:
diff changeset
564 tgt->tgt_end = tgt->tgt_start + tgt_size;
kono
parents:
diff changeset
565 }
kono
parents:
diff changeset
566 else
kono
parents:
diff changeset
567 {
kono
parents:
diff changeset
568 tgt->to_free = NULL;
kono
parents:
diff changeset
569 tgt->tgt_start = 0;
kono
parents:
diff changeset
570 tgt->tgt_end = 0;
kono
parents:
diff changeset
571 }
kono
parents:
diff changeset
572
kono
parents:
diff changeset
573 tgt_size = 0;
kono
parents:
diff changeset
574 if (pragma_kind == GOMP_MAP_VARS_TARGET)
kono
parents:
diff changeset
575 tgt_size = mapnum * sizeof (void *);
kono
parents:
diff changeset
576
kono
parents:
diff changeset
577 tgt->array = NULL;
kono
parents:
diff changeset
578 if (not_found_cnt || has_firstprivate)
kono
parents:
diff changeset
579 {
kono
parents:
diff changeset
580 if (not_found_cnt)
kono
parents:
diff changeset
581 tgt->array = gomp_malloc (not_found_cnt * sizeof (*tgt->array));
kono
parents:
diff changeset
582 splay_tree_node array = tgt->array;
kono
parents:
diff changeset
583 size_t j, field_tgt_offset = 0, field_tgt_clear = ~(size_t) 0;
kono
parents:
diff changeset
584 uintptr_t field_tgt_base = 0;
kono
parents:
diff changeset
585
kono
parents:
diff changeset
586 for (i = 0; i < mapnum; i++)
kono
parents:
diff changeset
587 if (tgt->list[i].key == NULL)
kono
parents:
diff changeset
588 {
kono
parents:
diff changeset
589 int kind = get_kind (short_mapkind, kinds, i);
kono
parents:
diff changeset
590 if (hostaddrs[i] == NULL)
kono
parents:
diff changeset
591 continue;
kono
parents:
diff changeset
592 switch (kind & typemask)
kono
parents:
diff changeset
593 {
kono
parents:
diff changeset
594 size_t align, len, first, last;
kono
parents:
diff changeset
595 splay_tree_key n;
kono
parents:
diff changeset
596 case GOMP_MAP_FIRSTPRIVATE:
kono
parents:
diff changeset
597 align = (size_t) 1 << (kind >> rshift);
kono
parents:
diff changeset
598 tgt_size = (tgt_size + align - 1) & ~(align - 1);
kono
parents:
diff changeset
599 tgt->list[i].offset = tgt_size;
kono
parents:
diff changeset
600 len = sizes[i];
kono
parents:
diff changeset
601 gomp_copy_host2dev (devicep,
kono
parents:
diff changeset
602 (void *) (tgt->tgt_start + tgt_size),
kono
parents:
diff changeset
603 (void *) hostaddrs[i], len);
kono
parents:
diff changeset
604 tgt_size += len;
kono
parents:
diff changeset
605 continue;
kono
parents:
diff changeset
606 case GOMP_MAP_FIRSTPRIVATE_INT:
kono
parents:
diff changeset
607 case GOMP_MAP_USE_DEVICE_PTR:
kono
parents:
diff changeset
608 case GOMP_MAP_ZERO_LEN_ARRAY_SECTION:
kono
parents:
diff changeset
609 continue;
kono
parents:
diff changeset
610 case GOMP_MAP_STRUCT:
kono
parents:
diff changeset
611 first = i + 1;
kono
parents:
diff changeset
612 last = i + sizes[i];
kono
parents:
diff changeset
613 cur_node.host_start = (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
614 cur_node.host_end = (uintptr_t) hostaddrs[last]
kono
parents:
diff changeset
615 + sizes[last];
kono
parents:
diff changeset
616 if (tgt->list[first].key != NULL)
kono
parents:
diff changeset
617 continue;
kono
parents:
diff changeset
618 n = splay_tree_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
619 if (n == NULL)
kono
parents:
diff changeset
620 {
kono
parents:
diff changeset
621 size_t align = (size_t) 1 << (kind >> rshift);
kono
parents:
diff changeset
622 tgt_size -= (uintptr_t) hostaddrs[first]
kono
parents:
diff changeset
623 - (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
624 tgt_size = (tgt_size + align - 1) & ~(align - 1);
kono
parents:
diff changeset
625 tgt_size += (uintptr_t) hostaddrs[first]
kono
parents:
diff changeset
626 - (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
627 field_tgt_base = (uintptr_t) hostaddrs[first];
kono
parents:
diff changeset
628 field_tgt_offset = tgt_size;
kono
parents:
diff changeset
629 field_tgt_clear = last;
kono
parents:
diff changeset
630 tgt_size += cur_node.host_end
kono
parents:
diff changeset
631 - (uintptr_t) hostaddrs[first];
kono
parents:
diff changeset
632 continue;
kono
parents:
diff changeset
633 }
kono
parents:
diff changeset
634 for (i = first; i <= last; i++)
kono
parents:
diff changeset
635 gomp_map_fields_existing (tgt, n, first, i, hostaddrs,
kono
parents:
diff changeset
636 sizes, kinds);
kono
parents:
diff changeset
637 i--;
kono
parents:
diff changeset
638 continue;
kono
parents:
diff changeset
639 case GOMP_MAP_ALWAYS_POINTER:
kono
parents:
diff changeset
640 cur_node.host_start = (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
641 cur_node.host_end = cur_node.host_start + sizeof (void *);
kono
parents:
diff changeset
642 n = splay_tree_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
643 if (n == NULL
kono
parents:
diff changeset
644 || n->host_start > cur_node.host_start
kono
parents:
diff changeset
645 || n->host_end < cur_node.host_end)
kono
parents:
diff changeset
646 {
kono
parents:
diff changeset
647 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
648 gomp_fatal ("always pointer not mapped");
kono
parents:
diff changeset
649 }
kono
parents:
diff changeset
650 if ((get_kind (short_mapkind, kinds, i - 1) & typemask)
kono
parents:
diff changeset
651 != GOMP_MAP_ALWAYS_POINTER)
kono
parents:
diff changeset
652 cur_node.tgt_offset = gomp_map_val (tgt, hostaddrs, i - 1);
kono
parents:
diff changeset
653 if (cur_node.tgt_offset)
kono
parents:
diff changeset
654 cur_node.tgt_offset -= sizes[i];
kono
parents:
diff changeset
655 gomp_copy_host2dev (devicep,
kono
parents:
diff changeset
656 (void *) (n->tgt->tgt_start
kono
parents:
diff changeset
657 + n->tgt_offset
kono
parents:
diff changeset
658 + cur_node.host_start
kono
parents:
diff changeset
659 - n->host_start),
kono
parents:
diff changeset
660 (void *) &cur_node.tgt_offset,
kono
parents:
diff changeset
661 sizeof (void *));
kono
parents:
diff changeset
662 cur_node.tgt_offset = n->tgt->tgt_start + n->tgt_offset
kono
parents:
diff changeset
663 + cur_node.host_start - n->host_start;
kono
parents:
diff changeset
664 continue;
kono
parents:
diff changeset
665 default:
kono
parents:
diff changeset
666 break;
kono
parents:
diff changeset
667 }
kono
parents:
diff changeset
668 splay_tree_key k = &array->key;
kono
parents:
diff changeset
669 k->host_start = (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
670 if (!GOMP_MAP_POINTER_P (kind & typemask))
kono
parents:
diff changeset
671 k->host_end = k->host_start + sizes[i];
kono
parents:
diff changeset
672 else
kono
parents:
diff changeset
673 k->host_end = k->host_start + sizeof (void *);
kono
parents:
diff changeset
674 splay_tree_key n = splay_tree_lookup (mem_map, k);
kono
parents:
diff changeset
675 if (n && n->refcount != REFCOUNT_LINK)
kono
parents:
diff changeset
676 gomp_map_vars_existing (devicep, n, k, &tgt->list[i],
kono
parents:
diff changeset
677 kind & typemask);
kono
parents:
diff changeset
678 else
kono
parents:
diff changeset
679 {
kono
parents:
diff changeset
680 k->link_key = NULL;
kono
parents:
diff changeset
681 if (n && n->refcount == REFCOUNT_LINK)
kono
parents:
diff changeset
682 {
kono
parents:
diff changeset
683 /* Replace target address of the pointer with target address
kono
parents:
diff changeset
684 of mapped object in the splay tree. */
kono
parents:
diff changeset
685 splay_tree_remove (mem_map, n);
kono
parents:
diff changeset
686 k->link_key = n;
kono
parents:
diff changeset
687 }
kono
parents:
diff changeset
688 size_t align = (size_t) 1 << (kind >> rshift);
kono
parents:
diff changeset
689 tgt->list[i].key = k;
kono
parents:
diff changeset
690 k->tgt = tgt;
kono
parents:
diff changeset
691 if (field_tgt_clear != ~(size_t) 0)
kono
parents:
diff changeset
692 {
kono
parents:
diff changeset
693 k->tgt_offset = k->host_start - field_tgt_base
kono
parents:
diff changeset
694 + field_tgt_offset;
kono
parents:
diff changeset
695 if (i == field_tgt_clear)
kono
parents:
diff changeset
696 field_tgt_clear = ~(size_t) 0;
kono
parents:
diff changeset
697 }
kono
parents:
diff changeset
698 else
kono
parents:
diff changeset
699 {
kono
parents:
diff changeset
700 tgt_size = (tgt_size + align - 1) & ~(align - 1);
kono
parents:
diff changeset
701 k->tgt_offset = tgt_size;
kono
parents:
diff changeset
702 tgt_size += k->host_end - k->host_start;
kono
parents:
diff changeset
703 }
kono
parents:
diff changeset
704 tgt->list[i].copy_from = GOMP_MAP_COPY_FROM_P (kind & typemask);
kono
parents:
diff changeset
705 tgt->list[i].always_copy_from
kono
parents:
diff changeset
706 = GOMP_MAP_ALWAYS_FROM_P (kind & typemask);
kono
parents:
diff changeset
707 tgt->list[i].offset = 0;
kono
parents:
diff changeset
708 tgt->list[i].length = k->host_end - k->host_start;
kono
parents:
diff changeset
709 k->refcount = 1;
kono
parents:
diff changeset
710 tgt->refcount++;
kono
parents:
diff changeset
711 array->left = NULL;
kono
parents:
diff changeset
712 array->right = NULL;
kono
parents:
diff changeset
713 splay_tree_insert (mem_map, array);
kono
parents:
diff changeset
714 switch (kind & typemask)
kono
parents:
diff changeset
715 {
kono
parents:
diff changeset
716 case GOMP_MAP_ALLOC:
kono
parents:
diff changeset
717 case GOMP_MAP_FROM:
kono
parents:
diff changeset
718 case GOMP_MAP_FORCE_ALLOC:
kono
parents:
diff changeset
719 case GOMP_MAP_FORCE_FROM:
kono
parents:
diff changeset
720 case GOMP_MAP_ALWAYS_FROM:
kono
parents:
diff changeset
721 break;
kono
parents:
diff changeset
722 case GOMP_MAP_TO:
kono
parents:
diff changeset
723 case GOMP_MAP_TOFROM:
kono
parents:
diff changeset
724 case GOMP_MAP_FORCE_TO:
kono
parents:
diff changeset
725 case GOMP_MAP_FORCE_TOFROM:
kono
parents:
diff changeset
726 case GOMP_MAP_ALWAYS_TO:
kono
parents:
diff changeset
727 case GOMP_MAP_ALWAYS_TOFROM:
kono
parents:
diff changeset
728 /* FIXME: Perhaps add some smarts, like if copying
kono
parents:
diff changeset
729 several adjacent fields from host to target, use some
kono
parents:
diff changeset
730 host buffer to avoid sending each var individually. */
kono
parents:
diff changeset
731 gomp_copy_host2dev (devicep,
kono
parents:
diff changeset
732 (void *) (tgt->tgt_start
kono
parents:
diff changeset
733 + k->tgt_offset),
kono
parents:
diff changeset
734 (void *) k->host_start,
kono
parents:
diff changeset
735 k->host_end - k->host_start);
kono
parents:
diff changeset
736 break;
kono
parents:
diff changeset
737 case GOMP_MAP_POINTER:
kono
parents:
diff changeset
738 gomp_map_pointer (tgt, (uintptr_t) *(void **) k->host_start,
kono
parents:
diff changeset
739 k->tgt_offset, sizes[i]);
kono
parents:
diff changeset
740 break;
kono
parents:
diff changeset
741 case GOMP_MAP_TO_PSET:
kono
parents:
diff changeset
742 /* FIXME: see above FIXME comment. */
kono
parents:
diff changeset
743 gomp_copy_host2dev (devicep,
kono
parents:
diff changeset
744 (void *) (tgt->tgt_start
kono
parents:
diff changeset
745 + k->tgt_offset),
kono
parents:
diff changeset
746 (void *) k->host_start,
kono
parents:
diff changeset
747 k->host_end - k->host_start);
kono
parents:
diff changeset
748
kono
parents:
diff changeset
749 for (j = i + 1; j < mapnum; j++)
kono
parents:
diff changeset
750 if (!GOMP_MAP_POINTER_P (get_kind (short_mapkind, kinds,
kono
parents:
diff changeset
751 j)
kono
parents:
diff changeset
752 & typemask))
kono
parents:
diff changeset
753 break;
kono
parents:
diff changeset
754 else if ((uintptr_t) hostaddrs[j] < k->host_start
kono
parents:
diff changeset
755 || ((uintptr_t) hostaddrs[j] + sizeof (void *)
kono
parents:
diff changeset
756 > k->host_end))
kono
parents:
diff changeset
757 break;
kono
parents:
diff changeset
758 else
kono
parents:
diff changeset
759 {
kono
parents:
diff changeset
760 tgt->list[j].key = k;
kono
parents:
diff changeset
761 tgt->list[j].copy_from = false;
kono
parents:
diff changeset
762 tgt->list[j].always_copy_from = false;
kono
parents:
diff changeset
763 if (k->refcount != REFCOUNT_INFINITY)
kono
parents:
diff changeset
764 k->refcount++;
kono
parents:
diff changeset
765 gomp_map_pointer (tgt,
kono
parents:
diff changeset
766 (uintptr_t) *(void **) hostaddrs[j],
kono
parents:
diff changeset
767 k->tgt_offset
kono
parents:
diff changeset
768 + ((uintptr_t) hostaddrs[j]
kono
parents:
diff changeset
769 - k->host_start),
kono
parents:
diff changeset
770 sizes[j]);
kono
parents:
diff changeset
771 i++;
kono
parents:
diff changeset
772 }
kono
parents:
diff changeset
773 break;
kono
parents:
diff changeset
774 case GOMP_MAP_FORCE_PRESENT:
kono
parents:
diff changeset
775 {
kono
parents:
diff changeset
776 /* We already looked up the memory region above and it
kono
parents:
diff changeset
777 was missing. */
kono
parents:
diff changeset
778 size_t size = k->host_end - k->host_start;
kono
parents:
diff changeset
779 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
780 #ifdef HAVE_INTTYPES_H
kono
parents:
diff changeset
781 gomp_fatal ("present clause: !acc_is_present (%p, "
kono
parents:
diff changeset
782 "%"PRIu64" (0x%"PRIx64"))",
kono
parents:
diff changeset
783 (void *) k->host_start,
kono
parents:
diff changeset
784 (uint64_t) size, (uint64_t) size);
kono
parents:
diff changeset
785 #else
kono
parents:
diff changeset
786 gomp_fatal ("present clause: !acc_is_present (%p, "
kono
parents:
diff changeset
787 "%lu (0x%lx))", (void *) k->host_start,
kono
parents:
diff changeset
788 (unsigned long) size, (unsigned long) size);
kono
parents:
diff changeset
789 #endif
kono
parents:
diff changeset
790 }
kono
parents:
diff changeset
791 break;
kono
parents:
diff changeset
792 case GOMP_MAP_FORCE_DEVICEPTR:
kono
parents:
diff changeset
793 assert (k->host_end - k->host_start == sizeof (void *));
kono
parents:
diff changeset
794 gomp_copy_host2dev (devicep,
kono
parents:
diff changeset
795 (void *) (tgt->tgt_start
kono
parents:
diff changeset
796 + k->tgt_offset),
kono
parents:
diff changeset
797 (void *) k->host_start,
kono
parents:
diff changeset
798 sizeof (void *));
kono
parents:
diff changeset
799 break;
kono
parents:
diff changeset
800 default:
kono
parents:
diff changeset
801 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
802 gomp_fatal ("%s: unhandled kind 0x%.2x", __FUNCTION__,
kono
parents:
diff changeset
803 kind);
kono
parents:
diff changeset
804 }
kono
parents:
diff changeset
805
kono
parents:
diff changeset
806 if (k->link_key)
kono
parents:
diff changeset
807 {
kono
parents:
diff changeset
808 /* Set link pointer on target to the device address of the
kono
parents:
diff changeset
809 mapped object. */
kono
parents:
diff changeset
810 void *tgt_addr = (void *) (tgt->tgt_start + k->tgt_offset);
kono
parents:
diff changeset
811 devicep->host2dev_func (devicep->target_id,
kono
parents:
diff changeset
812 (void *) n->tgt_offset,
kono
parents:
diff changeset
813 &tgt_addr, sizeof (void *));
kono
parents:
diff changeset
814 }
kono
parents:
diff changeset
815 array++;
kono
parents:
diff changeset
816 }
kono
parents:
diff changeset
817 }
kono
parents:
diff changeset
818 }
kono
parents:
diff changeset
819
kono
parents:
diff changeset
820 if (pragma_kind == GOMP_MAP_VARS_TARGET)
kono
parents:
diff changeset
821 {
kono
parents:
diff changeset
822 for (i = 0; i < mapnum; i++)
kono
parents:
diff changeset
823 {
kono
parents:
diff changeset
824 cur_node.tgt_offset = gomp_map_val (tgt, hostaddrs, i);
kono
parents:
diff changeset
825 /* FIXME: see above FIXME comment. */
kono
parents:
diff changeset
826 gomp_copy_host2dev (devicep,
kono
parents:
diff changeset
827 (void *) (tgt->tgt_start + i * sizeof (void *)),
kono
parents:
diff changeset
828 (void *) &cur_node.tgt_offset, sizeof (void *));
kono
parents:
diff changeset
829 }
kono
parents:
diff changeset
830 }
kono
parents:
diff changeset
831
kono
parents:
diff changeset
832 /* If the variable from "omp target enter data" map-list was already mapped,
kono
parents:
diff changeset
833 tgt is not needed. Otherwise tgt will be freed by gomp_unmap_vars or
kono
parents:
diff changeset
834 gomp_exit_data. */
kono
parents:
diff changeset
835 if (pragma_kind == GOMP_MAP_VARS_ENTER_DATA && tgt->refcount == 0)
kono
parents:
diff changeset
836 {
kono
parents:
diff changeset
837 free (tgt);
kono
parents:
diff changeset
838 tgt = NULL;
kono
parents:
diff changeset
839 }
kono
parents:
diff changeset
840
kono
parents:
diff changeset
841 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
842 return tgt;
kono
parents:
diff changeset
843 }
kono
parents:
diff changeset
844
kono
parents:
diff changeset
845 static void
kono
parents:
diff changeset
846 gomp_unmap_tgt (struct target_mem_desc *tgt)
kono
parents:
diff changeset
847 {
kono
parents:
diff changeset
848 /* Deallocate on target the tgt->tgt_start .. tgt->tgt_end region. */
kono
parents:
diff changeset
849 if (tgt->tgt_end)
kono
parents:
diff changeset
850 gomp_free_device_memory (tgt->device_descr, tgt->to_free);
kono
parents:
diff changeset
851
kono
parents:
diff changeset
852 free (tgt->array);
kono
parents:
diff changeset
853 free (tgt);
kono
parents:
diff changeset
854 }
kono
parents:
diff changeset
855
kono
parents:
diff changeset
856 /* Unmap variables described by TGT. If DO_COPYFROM is true, copy relevant
kono
parents:
diff changeset
857 variables back from device to host: if it is false, it is assumed that this
kono
parents:
diff changeset
858 has been done already. */
kono
parents:
diff changeset
859
kono
parents:
diff changeset
860 attribute_hidden void
kono
parents:
diff changeset
861 gomp_unmap_vars (struct target_mem_desc *tgt, bool do_copyfrom)
kono
parents:
diff changeset
862 {
kono
parents:
diff changeset
863 struct gomp_device_descr *devicep = tgt->device_descr;
kono
parents:
diff changeset
864
kono
parents:
diff changeset
865 if (tgt->list_count == 0)
kono
parents:
diff changeset
866 {
kono
parents:
diff changeset
867 free (tgt);
kono
parents:
diff changeset
868 return;
kono
parents:
diff changeset
869 }
kono
parents:
diff changeset
870
kono
parents:
diff changeset
871 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
872 if (devicep->state == GOMP_DEVICE_FINALIZED)
kono
parents:
diff changeset
873 {
kono
parents:
diff changeset
874 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
875 free (tgt->array);
kono
parents:
diff changeset
876 free (tgt);
kono
parents:
diff changeset
877 return;
kono
parents:
diff changeset
878 }
kono
parents:
diff changeset
879
kono
parents:
diff changeset
880 size_t i;
kono
parents:
diff changeset
881 for (i = 0; i < tgt->list_count; i++)
kono
parents:
diff changeset
882 {
kono
parents:
diff changeset
883 splay_tree_key k = tgt->list[i].key;
kono
parents:
diff changeset
884 if (k == NULL)
kono
parents:
diff changeset
885 continue;
kono
parents:
diff changeset
886
kono
parents:
diff changeset
887 bool do_unmap = false;
kono
parents:
diff changeset
888 if (k->refcount > 1 && k->refcount != REFCOUNT_INFINITY)
kono
parents:
diff changeset
889 k->refcount--;
kono
parents:
diff changeset
890 else if (k->refcount == 1)
kono
parents:
diff changeset
891 {
kono
parents:
diff changeset
892 k->refcount--;
kono
parents:
diff changeset
893 do_unmap = true;
kono
parents:
diff changeset
894 }
kono
parents:
diff changeset
895
kono
parents:
diff changeset
896 if ((do_unmap && do_copyfrom && tgt->list[i].copy_from)
kono
parents:
diff changeset
897 || tgt->list[i].always_copy_from)
kono
parents:
diff changeset
898 gomp_copy_dev2host (devicep,
kono
parents:
diff changeset
899 (void *) (k->host_start + tgt->list[i].offset),
kono
parents:
diff changeset
900 (void *) (k->tgt->tgt_start + k->tgt_offset
kono
parents:
diff changeset
901 + tgt->list[i].offset),
kono
parents:
diff changeset
902 tgt->list[i].length);
kono
parents:
diff changeset
903 if (do_unmap)
kono
parents:
diff changeset
904 {
kono
parents:
diff changeset
905 splay_tree_remove (&devicep->mem_map, k);
kono
parents:
diff changeset
906 if (k->link_key)
kono
parents:
diff changeset
907 splay_tree_insert (&devicep->mem_map,
kono
parents:
diff changeset
908 (splay_tree_node) k->link_key);
kono
parents:
diff changeset
909 if (k->tgt->refcount > 1)
kono
parents:
diff changeset
910 k->tgt->refcount--;
kono
parents:
diff changeset
911 else
kono
parents:
diff changeset
912 gomp_unmap_tgt (k->tgt);
kono
parents:
diff changeset
913 }
kono
parents:
diff changeset
914 }
kono
parents:
diff changeset
915
kono
parents:
diff changeset
916 if (tgt->refcount > 1)
kono
parents:
diff changeset
917 tgt->refcount--;
kono
parents:
diff changeset
918 else
kono
parents:
diff changeset
919 gomp_unmap_tgt (tgt);
kono
parents:
diff changeset
920
kono
parents:
diff changeset
921 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
922 }
kono
parents:
diff changeset
923
kono
parents:
diff changeset
924 static void
kono
parents:
diff changeset
925 gomp_update (struct gomp_device_descr *devicep, size_t mapnum, void **hostaddrs,
kono
parents:
diff changeset
926 size_t *sizes, void *kinds, bool short_mapkind)
kono
parents:
diff changeset
927 {
kono
parents:
diff changeset
928 size_t i;
kono
parents:
diff changeset
929 struct splay_tree_key_s cur_node;
kono
parents:
diff changeset
930 const int typemask = short_mapkind ? 0xff : 0x7;
kono
parents:
diff changeset
931
kono
parents:
diff changeset
932 if (!devicep)
kono
parents:
diff changeset
933 return;
kono
parents:
diff changeset
934
kono
parents:
diff changeset
935 if (mapnum == 0)
kono
parents:
diff changeset
936 return;
kono
parents:
diff changeset
937
kono
parents:
diff changeset
938 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
939 if (devicep->state == GOMP_DEVICE_FINALIZED)
kono
parents:
diff changeset
940 {
kono
parents:
diff changeset
941 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
942 return;
kono
parents:
diff changeset
943 }
kono
parents:
diff changeset
944
kono
parents:
diff changeset
945 for (i = 0; i < mapnum; i++)
kono
parents:
diff changeset
946 if (sizes[i])
kono
parents:
diff changeset
947 {
kono
parents:
diff changeset
948 cur_node.host_start = (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
949 cur_node.host_end = cur_node.host_start + sizes[i];
kono
parents:
diff changeset
950 splay_tree_key n = splay_tree_lookup (&devicep->mem_map, &cur_node);
kono
parents:
diff changeset
951 if (n)
kono
parents:
diff changeset
952 {
kono
parents:
diff changeset
953 int kind = get_kind (short_mapkind, kinds, i);
kono
parents:
diff changeset
954 if (n->host_start > cur_node.host_start
kono
parents:
diff changeset
955 || n->host_end < cur_node.host_end)
kono
parents:
diff changeset
956 {
kono
parents:
diff changeset
957 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
958 gomp_fatal ("Trying to update [%p..%p) object when "
kono
parents:
diff changeset
959 "only [%p..%p) is mapped",
kono
parents:
diff changeset
960 (void *) cur_node.host_start,
kono
parents:
diff changeset
961 (void *) cur_node.host_end,
kono
parents:
diff changeset
962 (void *) n->host_start,
kono
parents:
diff changeset
963 (void *) n->host_end);
kono
parents:
diff changeset
964 }
kono
parents:
diff changeset
965
kono
parents:
diff changeset
966
kono
parents:
diff changeset
967 void *hostaddr = (void *) cur_node.host_start;
kono
parents:
diff changeset
968 void *devaddr = (void *) (n->tgt->tgt_start + n->tgt_offset
kono
parents:
diff changeset
969 + cur_node.host_start - n->host_start);
kono
parents:
diff changeset
970 size_t size = cur_node.host_end - cur_node.host_start;
kono
parents:
diff changeset
971
kono
parents:
diff changeset
972 if (GOMP_MAP_COPY_TO_P (kind & typemask))
kono
parents:
diff changeset
973 gomp_copy_host2dev (devicep, devaddr, hostaddr, size);
kono
parents:
diff changeset
974 if (GOMP_MAP_COPY_FROM_P (kind & typemask))
kono
parents:
diff changeset
975 gomp_copy_dev2host (devicep, hostaddr, devaddr, size);
kono
parents:
diff changeset
976 }
kono
parents:
diff changeset
977 }
kono
parents:
diff changeset
978 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
979 }
kono
parents:
diff changeset
980
kono
parents:
diff changeset
981 /* Load image pointed by TARGET_DATA to the device, specified by DEVICEP.
kono
parents:
diff changeset
982 And insert to splay tree the mapping between addresses from HOST_TABLE and
kono
parents:
diff changeset
983 from loaded target image. We rely in the host and device compiler
kono
parents:
diff changeset
984 emitting variable and functions in the same order. */
kono
parents:
diff changeset
985
kono
parents:
diff changeset
986 static void
kono
parents:
diff changeset
987 gomp_load_image_to_device (struct gomp_device_descr *devicep, unsigned version,
kono
parents:
diff changeset
988 const void *host_table, const void *target_data,
kono
parents:
diff changeset
989 bool is_register_lock)
kono
parents:
diff changeset
990 {
kono
parents:
diff changeset
991 void **host_func_table = ((void ***) host_table)[0];
kono
parents:
diff changeset
992 void **host_funcs_end = ((void ***) host_table)[1];
kono
parents:
diff changeset
993 void **host_var_table = ((void ***) host_table)[2];
kono
parents:
diff changeset
994 void **host_vars_end = ((void ***) host_table)[3];
kono
parents:
diff changeset
995
kono
parents:
diff changeset
996 /* The func table contains only addresses, the var table contains addresses
kono
parents:
diff changeset
997 and corresponding sizes. */
kono
parents:
diff changeset
998 int num_funcs = host_funcs_end - host_func_table;
kono
parents:
diff changeset
999 int num_vars = (host_vars_end - host_var_table) / 2;
kono
parents:
diff changeset
1000
kono
parents:
diff changeset
1001 /* Load image to device and get target addresses for the image. */
kono
parents:
diff changeset
1002 struct addr_pair *target_table = NULL;
kono
parents:
diff changeset
1003 int i, num_target_entries;
kono
parents:
diff changeset
1004
kono
parents:
diff changeset
1005 num_target_entries
kono
parents:
diff changeset
1006 = devicep->load_image_func (devicep->target_id, version,
kono
parents:
diff changeset
1007 target_data, &target_table);
kono
parents:
diff changeset
1008
kono
parents:
diff changeset
1009 if (num_target_entries != num_funcs + num_vars)
kono
parents:
diff changeset
1010 {
kono
parents:
diff changeset
1011 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
1012 if (is_register_lock)
kono
parents:
diff changeset
1013 gomp_mutex_unlock (&register_lock);
kono
parents:
diff changeset
1014 gomp_fatal ("Cannot map target functions or variables"
kono
parents:
diff changeset
1015 " (expected %u, have %u)", num_funcs + num_vars,
kono
parents:
diff changeset
1016 num_target_entries);
kono
parents:
diff changeset
1017 }
kono
parents:
diff changeset
1018
kono
parents:
diff changeset
1019 /* Insert host-target address mapping into splay tree. */
kono
parents:
diff changeset
1020 struct target_mem_desc *tgt = gomp_malloc (sizeof (*tgt));
kono
parents:
diff changeset
1021 tgt->array = gomp_malloc ((num_funcs + num_vars) * sizeof (*tgt->array));
kono
parents:
diff changeset
1022 tgt->refcount = REFCOUNT_INFINITY;
kono
parents:
diff changeset
1023 tgt->tgt_start = 0;
kono
parents:
diff changeset
1024 tgt->tgt_end = 0;
kono
parents:
diff changeset
1025 tgt->to_free = NULL;
kono
parents:
diff changeset
1026 tgt->prev = NULL;
kono
parents:
diff changeset
1027 tgt->list_count = 0;
kono
parents:
diff changeset
1028 tgt->device_descr = devicep;
kono
parents:
diff changeset
1029 splay_tree_node array = tgt->array;
kono
parents:
diff changeset
1030
kono
parents:
diff changeset
1031 for (i = 0; i < num_funcs; i++)
kono
parents:
diff changeset
1032 {
kono
parents:
diff changeset
1033 splay_tree_key k = &array->key;
kono
parents:
diff changeset
1034 k->host_start = (uintptr_t) host_func_table[i];
kono
parents:
diff changeset
1035 k->host_end = k->host_start + 1;
kono
parents:
diff changeset
1036 k->tgt = tgt;
kono
parents:
diff changeset
1037 k->tgt_offset = target_table[i].start;
kono
parents:
diff changeset
1038 k->refcount = REFCOUNT_INFINITY;
kono
parents:
diff changeset
1039 k->link_key = NULL;
kono
parents:
diff changeset
1040 array->left = NULL;
kono
parents:
diff changeset
1041 array->right = NULL;
kono
parents:
diff changeset
1042 splay_tree_insert (&devicep->mem_map, array);
kono
parents:
diff changeset
1043 array++;
kono
parents:
diff changeset
1044 }
kono
parents:
diff changeset
1045
kono
parents:
diff changeset
1046 /* Most significant bit of the size in host and target tables marks
kono
parents:
diff changeset
1047 "omp declare target link" variables. */
kono
parents:
diff changeset
1048 const uintptr_t link_bit = 1ULL << (sizeof (uintptr_t) * __CHAR_BIT__ - 1);
kono
parents:
diff changeset
1049 const uintptr_t size_mask = ~link_bit;
kono
parents:
diff changeset
1050
kono
parents:
diff changeset
1051 for (i = 0; i < num_vars; i++)
kono
parents:
diff changeset
1052 {
kono
parents:
diff changeset
1053 struct addr_pair *target_var = &target_table[num_funcs + i];
kono
parents:
diff changeset
1054 uintptr_t target_size = target_var->end - target_var->start;
kono
parents:
diff changeset
1055
kono
parents:
diff changeset
1056 if ((uintptr_t) host_var_table[i * 2 + 1] != target_size)
kono
parents:
diff changeset
1057 {
kono
parents:
diff changeset
1058 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
1059 if (is_register_lock)
kono
parents:
diff changeset
1060 gomp_mutex_unlock (&register_lock);
kono
parents:
diff changeset
1061 gomp_fatal ("Cannot map target variables (size mismatch)");
kono
parents:
diff changeset
1062 }
kono
parents:
diff changeset
1063
kono
parents:
diff changeset
1064 splay_tree_key k = &array->key;
kono
parents:
diff changeset
1065 k->host_start = (uintptr_t) host_var_table[i * 2];
kono
parents:
diff changeset
1066 k->host_end
kono
parents:
diff changeset
1067 = k->host_start + (size_mask & (uintptr_t) host_var_table[i * 2 + 1]);
kono
parents:
diff changeset
1068 k->tgt = tgt;
kono
parents:
diff changeset
1069 k->tgt_offset = target_var->start;
kono
parents:
diff changeset
1070 k->refcount = target_size & link_bit ? REFCOUNT_LINK : REFCOUNT_INFINITY;
kono
parents:
diff changeset
1071 k->link_key = NULL;
kono
parents:
diff changeset
1072 array->left = NULL;
kono
parents:
diff changeset
1073 array->right = NULL;
kono
parents:
diff changeset
1074 splay_tree_insert (&devicep->mem_map, array);
kono
parents:
diff changeset
1075 array++;
kono
parents:
diff changeset
1076 }
kono
parents:
diff changeset
1077
kono
parents:
diff changeset
1078 free (target_table);
kono
parents:
diff changeset
1079 }
kono
parents:
diff changeset
1080
kono
parents:
diff changeset
1081 /* Unload the mappings described by target_data from device DEVICE_P.
kono
parents:
diff changeset
1082 The device must be locked. */
kono
parents:
diff changeset
1083
kono
parents:
diff changeset
1084 static void
kono
parents:
diff changeset
1085 gomp_unload_image_from_device (struct gomp_device_descr *devicep,
kono
parents:
diff changeset
1086 unsigned version,
kono
parents:
diff changeset
1087 const void *host_table, const void *target_data)
kono
parents:
diff changeset
1088 {
kono
parents:
diff changeset
1089 void **host_func_table = ((void ***) host_table)[0];
kono
parents:
diff changeset
1090 void **host_funcs_end = ((void ***) host_table)[1];
kono
parents:
diff changeset
1091 void **host_var_table = ((void ***) host_table)[2];
kono
parents:
diff changeset
1092 void **host_vars_end = ((void ***) host_table)[3];
kono
parents:
diff changeset
1093
kono
parents:
diff changeset
1094 /* The func table contains only addresses, the var table contains addresses
kono
parents:
diff changeset
1095 and corresponding sizes. */
kono
parents:
diff changeset
1096 int num_funcs = host_funcs_end - host_func_table;
kono
parents:
diff changeset
1097 int num_vars = (host_vars_end - host_var_table) / 2;
kono
parents:
diff changeset
1098
kono
parents:
diff changeset
1099 struct splay_tree_key_s k;
kono
parents:
diff changeset
1100 splay_tree_key node = NULL;
kono
parents:
diff changeset
1101
kono
parents:
diff changeset
1102 /* Find mapping at start of node array */
kono
parents:
diff changeset
1103 if (num_funcs || num_vars)
kono
parents:
diff changeset
1104 {
kono
parents:
diff changeset
1105 k.host_start = (num_funcs ? (uintptr_t) host_func_table[0]
kono
parents:
diff changeset
1106 : (uintptr_t) host_var_table[0]);
kono
parents:
diff changeset
1107 k.host_end = k.host_start + 1;
kono
parents:
diff changeset
1108 node = splay_tree_lookup (&devicep->mem_map, &k);
kono
parents:
diff changeset
1109 }
kono
parents:
diff changeset
1110
kono
parents:
diff changeset
1111 if (!devicep->unload_image_func (devicep->target_id, version, target_data))
kono
parents:
diff changeset
1112 {
kono
parents:
diff changeset
1113 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
1114 gomp_fatal ("image unload fail");
kono
parents:
diff changeset
1115 }
kono
parents:
diff changeset
1116
kono
parents:
diff changeset
1117 /* Remove mappings from splay tree. */
kono
parents:
diff changeset
1118 int i;
kono
parents:
diff changeset
1119 for (i = 0; i < num_funcs; i++)
kono
parents:
diff changeset
1120 {
kono
parents:
diff changeset
1121 k.host_start = (uintptr_t) host_func_table[i];
kono
parents:
diff changeset
1122 k.host_end = k.host_start + 1;
kono
parents:
diff changeset
1123 splay_tree_remove (&devicep->mem_map, &k);
kono
parents:
diff changeset
1124 }
kono
parents:
diff changeset
1125
kono
parents:
diff changeset
1126 /* Most significant bit of the size in host and target tables marks
kono
parents:
diff changeset
1127 "omp declare target link" variables. */
kono
parents:
diff changeset
1128 const uintptr_t link_bit = 1ULL << (sizeof (uintptr_t) * __CHAR_BIT__ - 1);
kono
parents:
diff changeset
1129 const uintptr_t size_mask = ~link_bit;
kono
parents:
diff changeset
1130 bool is_tgt_unmapped = false;
kono
parents:
diff changeset
1131
kono
parents:
diff changeset
1132 for (i = 0; i < num_vars; i++)
kono
parents:
diff changeset
1133 {
kono
parents:
diff changeset
1134 k.host_start = (uintptr_t) host_var_table[i * 2];
kono
parents:
diff changeset
1135 k.host_end
kono
parents:
diff changeset
1136 = k.host_start + (size_mask & (uintptr_t) host_var_table[i * 2 + 1]);
kono
parents:
diff changeset
1137
kono
parents:
diff changeset
1138 if (!(link_bit & (uintptr_t) host_var_table[i * 2 + 1]))
kono
parents:
diff changeset
1139 splay_tree_remove (&devicep->mem_map, &k);
kono
parents:
diff changeset
1140 else
kono
parents:
diff changeset
1141 {
kono
parents:
diff changeset
1142 splay_tree_key n = splay_tree_lookup (&devicep->mem_map, &k);
kono
parents:
diff changeset
1143 splay_tree_remove (&devicep->mem_map, n);
kono
parents:
diff changeset
1144 if (n->link_key)
kono
parents:
diff changeset
1145 {
kono
parents:
diff changeset
1146 if (n->tgt->refcount > 1)
kono
parents:
diff changeset
1147 n->tgt->refcount--;
kono
parents:
diff changeset
1148 else
kono
parents:
diff changeset
1149 {
kono
parents:
diff changeset
1150 is_tgt_unmapped = true;
kono
parents:
diff changeset
1151 gomp_unmap_tgt (n->tgt);
kono
parents:
diff changeset
1152 }
kono
parents:
diff changeset
1153 }
kono
parents:
diff changeset
1154 }
kono
parents:
diff changeset
1155 }
kono
parents:
diff changeset
1156
kono
parents:
diff changeset
1157 if (node && !is_tgt_unmapped)
kono
parents:
diff changeset
1158 {
kono
parents:
diff changeset
1159 free (node->tgt);
kono
parents:
diff changeset
1160 free (node);
kono
parents:
diff changeset
1161 }
kono
parents:
diff changeset
1162 }
kono
parents:
diff changeset
1163
kono
parents:
diff changeset
1164 /* This function should be called from every offload image while loading.
kono
parents:
diff changeset
1165 It gets the descriptor of the host func and var tables HOST_TABLE, TYPE of
kono
parents:
diff changeset
1166 the target, and TARGET_DATA needed by target plugin. */
kono
parents:
diff changeset
1167
kono
parents:
diff changeset
1168 void
kono
parents:
diff changeset
1169 GOMP_offload_register_ver (unsigned version, const void *host_table,
kono
parents:
diff changeset
1170 int target_type, const void *target_data)
kono
parents:
diff changeset
1171 {
kono
parents:
diff changeset
1172 int i;
kono
parents:
diff changeset
1173
kono
parents:
diff changeset
1174 if (GOMP_VERSION_LIB (version) > GOMP_VERSION)
kono
parents:
diff changeset
1175 gomp_fatal ("Library too old for offload (version %u < %u)",
kono
parents:
diff changeset
1176 GOMP_VERSION, GOMP_VERSION_LIB (version));
kono
parents:
diff changeset
1177
kono
parents:
diff changeset
1178 gomp_mutex_lock (&register_lock);
kono
parents:
diff changeset
1179
kono
parents:
diff changeset
1180 /* Load image to all initialized devices. */
kono
parents:
diff changeset
1181 for (i = 0; i < num_devices; i++)
kono
parents:
diff changeset
1182 {
kono
parents:
diff changeset
1183 struct gomp_device_descr *devicep = &devices[i];
kono
parents:
diff changeset
1184 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
1185 if (devicep->type == target_type
kono
parents:
diff changeset
1186 && devicep->state == GOMP_DEVICE_INITIALIZED)
kono
parents:
diff changeset
1187 gomp_load_image_to_device (devicep, version,
kono
parents:
diff changeset
1188 host_table, target_data, true);
kono
parents:
diff changeset
1189 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
1190 }
kono
parents:
diff changeset
1191
kono
parents:
diff changeset
1192 /* Insert image to array of pending images. */
kono
parents:
diff changeset
1193 offload_images
kono
parents:
diff changeset
1194 = gomp_realloc_unlock (offload_images,
kono
parents:
diff changeset
1195 (num_offload_images + 1)
kono
parents:
diff changeset
1196 * sizeof (struct offload_image_descr));
kono
parents:
diff changeset
1197 offload_images[num_offload_images].version = version;
kono
parents:
diff changeset
1198 offload_images[num_offload_images].type = target_type;
kono
parents:
diff changeset
1199 offload_images[num_offload_images].host_table = host_table;
kono
parents:
diff changeset
1200 offload_images[num_offload_images].target_data = target_data;
kono
parents:
diff changeset
1201
kono
parents:
diff changeset
1202 num_offload_images++;
kono
parents:
diff changeset
1203 gomp_mutex_unlock (&register_lock);
kono
parents:
diff changeset
1204 }
kono
parents:
diff changeset
1205
kono
parents:
diff changeset
1206 void
kono
parents:
diff changeset
1207 GOMP_offload_register (const void *host_table, int target_type,
kono
parents:
diff changeset
1208 const void *target_data)
kono
parents:
diff changeset
1209 {
kono
parents:
diff changeset
1210 GOMP_offload_register_ver (0, host_table, target_type, target_data);
kono
parents:
diff changeset
1211 }
kono
parents:
diff changeset
1212
kono
parents:
diff changeset
1213 /* This function should be called from every offload image while unloading.
kono
parents:
diff changeset
1214 It gets the descriptor of the host func and var tables HOST_TABLE, TYPE of
kono
parents:
diff changeset
1215 the target, and TARGET_DATA needed by target plugin. */
kono
parents:
diff changeset
1216
kono
parents:
diff changeset
1217 void
kono
parents:
diff changeset
1218 GOMP_offload_unregister_ver (unsigned version, const void *host_table,
kono
parents:
diff changeset
1219 int target_type, const void *target_data)
kono
parents:
diff changeset
1220 {
kono
parents:
diff changeset
1221 int i;
kono
parents:
diff changeset
1222
kono
parents:
diff changeset
1223 gomp_mutex_lock (&register_lock);
kono
parents:
diff changeset
1224
kono
parents:
diff changeset
1225 /* Unload image from all initialized devices. */
kono
parents:
diff changeset
1226 for (i = 0; i < num_devices; i++)
kono
parents:
diff changeset
1227 {
kono
parents:
diff changeset
1228 struct gomp_device_descr *devicep = &devices[i];
kono
parents:
diff changeset
1229 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
1230 if (devicep->type == target_type
kono
parents:
diff changeset
1231 && devicep->state == GOMP_DEVICE_INITIALIZED)
kono
parents:
diff changeset
1232 gomp_unload_image_from_device (devicep, version,
kono
parents:
diff changeset
1233 host_table, target_data);
kono
parents:
diff changeset
1234 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
1235 }
kono
parents:
diff changeset
1236
kono
parents:
diff changeset
1237 /* Remove image from array of pending images. */
kono
parents:
diff changeset
1238 for (i = 0; i < num_offload_images; i++)
kono
parents:
diff changeset
1239 if (offload_images[i].target_data == target_data)
kono
parents:
diff changeset
1240 {
kono
parents:
diff changeset
1241 offload_images[i] = offload_images[--num_offload_images];
kono
parents:
diff changeset
1242 break;
kono
parents:
diff changeset
1243 }
kono
parents:
diff changeset
1244
kono
parents:
diff changeset
1245 gomp_mutex_unlock (&register_lock);
kono
parents:
diff changeset
1246 }
kono
parents:
diff changeset
1247
kono
parents:
diff changeset
1248 void
kono
parents:
diff changeset
1249 GOMP_offload_unregister (const void *host_table, int target_type,
kono
parents:
diff changeset
1250 const void *target_data)
kono
parents:
diff changeset
1251 {
kono
parents:
diff changeset
1252 GOMP_offload_unregister_ver (0, host_table, target_type, target_data);
kono
parents:
diff changeset
1253 }
kono
parents:
diff changeset
1254
kono
parents:
diff changeset
1255 /* This function initializes the target device, specified by DEVICEP. DEVICEP
kono
parents:
diff changeset
1256 must be locked on entry, and remains locked on return. */
kono
parents:
diff changeset
1257
kono
parents:
diff changeset
1258 attribute_hidden void
kono
parents:
diff changeset
1259 gomp_init_device (struct gomp_device_descr *devicep)
kono
parents:
diff changeset
1260 {
kono
parents:
diff changeset
1261 int i;
kono
parents:
diff changeset
1262 if (!devicep->init_device_func (devicep->target_id))
kono
parents:
diff changeset
1263 {
kono
parents:
diff changeset
1264 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
1265 gomp_fatal ("device initialization failed");
kono
parents:
diff changeset
1266 }
kono
parents:
diff changeset
1267
kono
parents:
diff changeset
1268 /* Load to device all images registered by the moment. */
kono
parents:
diff changeset
1269 for (i = 0; i < num_offload_images; i++)
kono
parents:
diff changeset
1270 {
kono
parents:
diff changeset
1271 struct offload_image_descr *image = &offload_images[i];
kono
parents:
diff changeset
1272 if (image->type == devicep->type)
kono
parents:
diff changeset
1273 gomp_load_image_to_device (devicep, image->version,
kono
parents:
diff changeset
1274 image->host_table, image->target_data,
kono
parents:
diff changeset
1275 false);
kono
parents:
diff changeset
1276 }
kono
parents:
diff changeset
1277
kono
parents:
diff changeset
1278 devicep->state = GOMP_DEVICE_INITIALIZED;
kono
parents:
diff changeset
1279 }
kono
parents:
diff changeset
1280
kono
parents:
diff changeset
1281 attribute_hidden void
kono
parents:
diff changeset
1282 gomp_unload_device (struct gomp_device_descr *devicep)
kono
parents:
diff changeset
1283 {
kono
parents:
diff changeset
1284 if (devicep->state == GOMP_DEVICE_INITIALIZED)
kono
parents:
diff changeset
1285 {
kono
parents:
diff changeset
1286 unsigned i;
kono
parents:
diff changeset
1287
kono
parents:
diff changeset
1288 /* Unload from device all images registered at the moment. */
kono
parents:
diff changeset
1289 for (i = 0; i < num_offload_images; i++)
kono
parents:
diff changeset
1290 {
kono
parents:
diff changeset
1291 struct offload_image_descr *image = &offload_images[i];
kono
parents:
diff changeset
1292 if (image->type == devicep->type)
kono
parents:
diff changeset
1293 gomp_unload_image_from_device (devicep, image->version,
kono
parents:
diff changeset
1294 image->host_table,
kono
parents:
diff changeset
1295 image->target_data);
kono
parents:
diff changeset
1296 }
kono
parents:
diff changeset
1297 }
kono
parents:
diff changeset
1298 }
kono
parents:
diff changeset
1299
kono
parents:
diff changeset
1300 /* Free address mapping tables. MM must be locked on entry, and remains locked
kono
parents:
diff changeset
1301 on return. */
kono
parents:
diff changeset
1302
kono
parents:
diff changeset
1303 attribute_hidden void
kono
parents:
diff changeset
1304 gomp_free_memmap (struct splay_tree_s *mem_map)
kono
parents:
diff changeset
1305 {
kono
parents:
diff changeset
1306 while (mem_map->root)
kono
parents:
diff changeset
1307 {
kono
parents:
diff changeset
1308 struct target_mem_desc *tgt = mem_map->root->key.tgt;
kono
parents:
diff changeset
1309
kono
parents:
diff changeset
1310 splay_tree_remove (mem_map, &mem_map->root->key);
kono
parents:
diff changeset
1311 free (tgt->array);
kono
parents:
diff changeset
1312 free (tgt);
kono
parents:
diff changeset
1313 }
kono
parents:
diff changeset
1314 }
kono
parents:
diff changeset
1315
kono
parents:
diff changeset
1316 /* Host fallback for GOMP_target{,_ext} routines. */
kono
parents:
diff changeset
1317
kono
parents:
diff changeset
1318 static void
kono
parents:
diff changeset
1319 gomp_target_fallback (void (*fn) (void *), void **hostaddrs)
kono
parents:
diff changeset
1320 {
kono
parents:
diff changeset
1321 struct gomp_thread old_thr, *thr = gomp_thread ();
kono
parents:
diff changeset
1322 old_thr = *thr;
kono
parents:
diff changeset
1323 memset (thr, '\0', sizeof (*thr));
kono
parents:
diff changeset
1324 if (gomp_places_list)
kono
parents:
diff changeset
1325 {
kono
parents:
diff changeset
1326 thr->place = old_thr.place;
kono
parents:
diff changeset
1327 thr->ts.place_partition_len = gomp_places_list_len;
kono
parents:
diff changeset
1328 }
kono
parents:
diff changeset
1329 fn (hostaddrs);
kono
parents:
diff changeset
1330 gomp_free_thread (thr);
kono
parents:
diff changeset
1331 *thr = old_thr;
kono
parents:
diff changeset
1332 }
kono
parents:
diff changeset
1333
kono
parents:
diff changeset
1334 /* Calculate alignment and size requirements of a private copy of data shared
kono
parents:
diff changeset
1335 as GOMP_MAP_FIRSTPRIVATE and store them to TGT_ALIGN and TGT_SIZE. */
kono
parents:
diff changeset
1336
kono
parents:
diff changeset
1337 static inline void
kono
parents:
diff changeset
1338 calculate_firstprivate_requirements (size_t mapnum, size_t *sizes,
kono
parents:
diff changeset
1339 unsigned short *kinds, size_t *tgt_align,
kono
parents:
diff changeset
1340 size_t *tgt_size)
kono
parents:
diff changeset
1341 {
kono
parents:
diff changeset
1342 size_t i;
kono
parents:
diff changeset
1343 for (i = 0; i < mapnum; i++)
kono
parents:
diff changeset
1344 if ((kinds[i] & 0xff) == GOMP_MAP_FIRSTPRIVATE)
kono
parents:
diff changeset
1345 {
kono
parents:
diff changeset
1346 size_t align = (size_t) 1 << (kinds[i] >> 8);
kono
parents:
diff changeset
1347 if (*tgt_align < align)
kono
parents:
diff changeset
1348 *tgt_align = align;
kono
parents:
diff changeset
1349 *tgt_size = (*tgt_size + align - 1) & ~(align - 1);
kono
parents:
diff changeset
1350 *tgt_size += sizes[i];
kono
parents:
diff changeset
1351 }
kono
parents:
diff changeset
1352 }
kono
parents:
diff changeset
1353
kono
parents:
diff changeset
1354 /* Copy data shared as GOMP_MAP_FIRSTPRIVATE to DST. */
kono
parents:
diff changeset
1355
kono
parents:
diff changeset
1356 static inline void
kono
parents:
diff changeset
1357 copy_firstprivate_data (char *tgt, size_t mapnum, void **hostaddrs,
kono
parents:
diff changeset
1358 size_t *sizes, unsigned short *kinds, size_t tgt_align,
kono
parents:
diff changeset
1359 size_t tgt_size)
kono
parents:
diff changeset
1360 {
kono
parents:
diff changeset
1361 uintptr_t al = (uintptr_t) tgt & (tgt_align - 1);
kono
parents:
diff changeset
1362 if (al)
kono
parents:
diff changeset
1363 tgt += tgt_align - al;
kono
parents:
diff changeset
1364 tgt_size = 0;
kono
parents:
diff changeset
1365 size_t i;
kono
parents:
diff changeset
1366 for (i = 0; i < mapnum; i++)
kono
parents:
diff changeset
1367 if ((kinds[i] & 0xff) == GOMP_MAP_FIRSTPRIVATE)
kono
parents:
diff changeset
1368 {
kono
parents:
diff changeset
1369 size_t align = (size_t) 1 << (kinds[i] >> 8);
kono
parents:
diff changeset
1370 tgt_size = (tgt_size + align - 1) & ~(align - 1);
kono
parents:
diff changeset
1371 memcpy (tgt + tgt_size, hostaddrs[i], sizes[i]);
kono
parents:
diff changeset
1372 hostaddrs[i] = tgt + tgt_size;
kono
parents:
diff changeset
1373 tgt_size = tgt_size + sizes[i];
kono
parents:
diff changeset
1374 }
kono
parents:
diff changeset
1375 }
kono
parents:
diff changeset
1376
kono
parents:
diff changeset
1377 /* Helper function of GOMP_target{,_ext} routines. */
kono
parents:
diff changeset
1378
kono
parents:
diff changeset
1379 static void *
kono
parents:
diff changeset
1380 gomp_get_target_fn_addr (struct gomp_device_descr *devicep,
kono
parents:
diff changeset
1381 void (*host_fn) (void *))
kono
parents:
diff changeset
1382 {
kono
parents:
diff changeset
1383 if (devicep->capabilities & GOMP_OFFLOAD_CAP_NATIVE_EXEC)
kono
parents:
diff changeset
1384 return (void *) host_fn;
kono
parents:
diff changeset
1385 else
kono
parents:
diff changeset
1386 {
kono
parents:
diff changeset
1387 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
1388 if (devicep->state == GOMP_DEVICE_FINALIZED)
kono
parents:
diff changeset
1389 {
kono
parents:
diff changeset
1390 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
1391 return NULL;
kono
parents:
diff changeset
1392 }
kono
parents:
diff changeset
1393
kono
parents:
diff changeset
1394 struct splay_tree_key_s k;
kono
parents:
diff changeset
1395 k.host_start = (uintptr_t) host_fn;
kono
parents:
diff changeset
1396 k.host_end = k.host_start + 1;
kono
parents:
diff changeset
1397 splay_tree_key tgt_fn = splay_tree_lookup (&devicep->mem_map, &k);
kono
parents:
diff changeset
1398 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
1399 if (tgt_fn == NULL)
kono
parents:
diff changeset
1400 return NULL;
kono
parents:
diff changeset
1401
kono
parents:
diff changeset
1402 return (void *) tgt_fn->tgt_offset;
kono
parents:
diff changeset
1403 }
kono
parents:
diff changeset
1404 }
kono
parents:
diff changeset
1405
kono
parents:
diff changeset
1406 /* Called when encountering a target directive. If DEVICE
kono
parents:
diff changeset
1407 is GOMP_DEVICE_ICV, it means use device-var ICV. If it is
kono
parents:
diff changeset
1408 GOMP_DEVICE_HOST_FALLBACK (or any value
kono
parents:
diff changeset
1409 larger than last available hw device), use host fallback.
kono
parents:
diff changeset
1410 FN is address of host code, UNUSED is part of the current ABI, but
kono
parents:
diff changeset
1411 we're not actually using it. HOSTADDRS, SIZES and KINDS are arrays
kono
parents:
diff changeset
1412 with MAPNUM entries, with addresses of the host objects,
kono
parents:
diff changeset
1413 sizes of the host objects (resp. for pointer kind pointer bias
kono
parents:
diff changeset
1414 and assumed sizeof (void *) size) and kinds. */
kono
parents:
diff changeset
1415
kono
parents:
diff changeset
1416 void
kono
parents:
diff changeset
1417 GOMP_target (int device, void (*fn) (void *), const void *unused,
kono
parents:
diff changeset
1418 size_t mapnum, void **hostaddrs, size_t *sizes,
kono
parents:
diff changeset
1419 unsigned char *kinds)
kono
parents:
diff changeset
1420 {
kono
parents:
diff changeset
1421 struct gomp_device_descr *devicep = resolve_device (device);
kono
parents:
diff changeset
1422
kono
parents:
diff changeset
1423 void *fn_addr;
kono
parents:
diff changeset
1424 if (devicep == NULL
kono
parents:
diff changeset
1425 || !(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
1426 /* All shared memory devices should use the GOMP_target_ext function. */
kono
parents:
diff changeset
1427 || devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM
kono
parents:
diff changeset
1428 || !(fn_addr = gomp_get_target_fn_addr (devicep, fn)))
kono
parents:
diff changeset
1429 return gomp_target_fallback (fn, hostaddrs);
kono
parents:
diff changeset
1430
kono
parents:
diff changeset
1431 struct target_mem_desc *tgt_vars
kono
parents:
diff changeset
1432 = gomp_map_vars (devicep, mapnum, hostaddrs, NULL, sizes, kinds, false,
kono
parents:
diff changeset
1433 GOMP_MAP_VARS_TARGET);
kono
parents:
diff changeset
1434 devicep->run_func (devicep->target_id, fn_addr, (void *) tgt_vars->tgt_start,
kono
parents:
diff changeset
1435 NULL);
kono
parents:
diff changeset
1436 gomp_unmap_vars (tgt_vars, true);
kono
parents:
diff changeset
1437 }
kono
parents:
diff changeset
1438
kono
parents:
diff changeset
1439 /* Like GOMP_target, but KINDS is 16-bit, UNUSED is no longer present,
kono
parents:
diff changeset
1440 and several arguments have been added:
kono
parents:
diff changeset
1441 FLAGS is a bitmask, see GOMP_TARGET_FLAG_* in gomp-constants.h.
kono
parents:
diff changeset
1442 DEPEND is array of dependencies, see GOMP_task for details.
kono
parents:
diff changeset
1443
kono
parents:
diff changeset
1444 ARGS is a pointer to an array consisting of a variable number of both
kono
parents:
diff changeset
1445 device-independent and device-specific arguments, which can take one two
kono
parents:
diff changeset
1446 elements where the first specifies for which device it is intended, the type
kono
parents:
diff changeset
1447 and optionally also the value. If the value is not present in the first
kono
parents:
diff changeset
1448 one, the whole second element the actual value. The last element of the
kono
parents:
diff changeset
1449 array is a single NULL. Among the device independent can be for example
kono
parents:
diff changeset
1450 NUM_TEAMS and THREAD_LIMIT.
kono
parents:
diff changeset
1451
kono
parents:
diff changeset
1452 NUM_TEAMS is positive if GOMP_teams will be called in the body with
kono
parents:
diff changeset
1453 that value, or 1 if teams construct is not present, or 0, if
kono
parents:
diff changeset
1454 teams construct does not have num_teams clause and so the choice is
kono
parents:
diff changeset
1455 implementation defined, and -1 if it can't be determined on the host
kono
parents:
diff changeset
1456 what value will GOMP_teams have on the device.
kono
parents:
diff changeset
1457 THREAD_LIMIT similarly is positive if GOMP_teams will be called in the
kono
parents:
diff changeset
1458 body with that value, or 0, if teams construct does not have thread_limit
kono
parents:
diff changeset
1459 clause or the teams construct is not present, or -1 if it can't be
kono
parents:
diff changeset
1460 determined on the host what value will GOMP_teams have on the device. */
kono
parents:
diff changeset
1461
kono
parents:
diff changeset
1462 void
kono
parents:
diff changeset
1463 GOMP_target_ext (int device, void (*fn) (void *), size_t mapnum,
kono
parents:
diff changeset
1464 void **hostaddrs, size_t *sizes, unsigned short *kinds,
kono
parents:
diff changeset
1465 unsigned int flags, void **depend, void **args)
kono
parents:
diff changeset
1466 {
kono
parents:
diff changeset
1467 struct gomp_device_descr *devicep = resolve_device (device);
kono
parents:
diff changeset
1468 size_t tgt_align = 0, tgt_size = 0;
kono
parents:
diff changeset
1469 bool fpc_done = false;
kono
parents:
diff changeset
1470
kono
parents:
diff changeset
1471 if (flags & GOMP_TARGET_FLAG_NOWAIT)
kono
parents:
diff changeset
1472 {
kono
parents:
diff changeset
1473 struct gomp_thread *thr = gomp_thread ();
kono
parents:
diff changeset
1474 /* Create a team if we don't have any around, as nowait
kono
parents:
diff changeset
1475 target tasks make sense to run asynchronously even when
kono
parents:
diff changeset
1476 outside of any parallel. */
kono
parents:
diff changeset
1477 if (__builtin_expect (thr->ts.team == NULL, 0))
kono
parents:
diff changeset
1478 {
kono
parents:
diff changeset
1479 struct gomp_team *team = gomp_new_team (1);
kono
parents:
diff changeset
1480 struct gomp_task *task = thr->task;
kono
parents:
diff changeset
1481 struct gomp_task_icv *icv = task ? &task->icv : &gomp_global_icv;
kono
parents:
diff changeset
1482 team->prev_ts = thr->ts;
kono
parents:
diff changeset
1483 thr->ts.team = team;
kono
parents:
diff changeset
1484 thr->ts.team_id = 0;
kono
parents:
diff changeset
1485 thr->ts.work_share = &team->work_shares[0];
kono
parents:
diff changeset
1486 thr->ts.last_work_share = NULL;
kono
parents:
diff changeset
1487 #ifdef HAVE_SYNC_BUILTINS
kono
parents:
diff changeset
1488 thr->ts.single_count = 0;
kono
parents:
diff changeset
1489 #endif
kono
parents:
diff changeset
1490 thr->ts.static_trip = 0;
kono
parents:
diff changeset
1491 thr->task = &team->implicit_task[0];
kono
parents:
diff changeset
1492 gomp_init_task (thr->task, NULL, icv);
kono
parents:
diff changeset
1493 if (task)
kono
parents:
diff changeset
1494 {
kono
parents:
diff changeset
1495 thr->task = task;
kono
parents:
diff changeset
1496 gomp_end_task ();
kono
parents:
diff changeset
1497 free (task);
kono
parents:
diff changeset
1498 thr->task = &team->implicit_task[0];
kono
parents:
diff changeset
1499 }
kono
parents:
diff changeset
1500 else
kono
parents:
diff changeset
1501 pthread_setspecific (gomp_thread_destructor, thr);
kono
parents:
diff changeset
1502 }
kono
parents:
diff changeset
1503 if (thr->ts.team
kono
parents:
diff changeset
1504 && !thr->task->final_task)
kono
parents:
diff changeset
1505 {
kono
parents:
diff changeset
1506 gomp_create_target_task (devicep, fn, mapnum, hostaddrs,
kono
parents:
diff changeset
1507 sizes, kinds, flags, depend, args,
kono
parents:
diff changeset
1508 GOMP_TARGET_TASK_BEFORE_MAP);
kono
parents:
diff changeset
1509 return;
kono
parents:
diff changeset
1510 }
kono
parents:
diff changeset
1511 }
kono
parents:
diff changeset
1512
kono
parents:
diff changeset
1513 /* If there are depend clauses, but nowait is not present
kono
parents:
diff changeset
1514 (or we are in a final task), block the parent task until the
kono
parents:
diff changeset
1515 dependencies are resolved and then just continue with the rest
kono
parents:
diff changeset
1516 of the function as if it is a merged task. */
kono
parents:
diff changeset
1517 if (depend != NULL)
kono
parents:
diff changeset
1518 {
kono
parents:
diff changeset
1519 struct gomp_thread *thr = gomp_thread ();
kono
parents:
diff changeset
1520 if (thr->task && thr->task->depend_hash)
kono
parents:
diff changeset
1521 {
kono
parents:
diff changeset
1522 /* If we might need to wait, copy firstprivate now. */
kono
parents:
diff changeset
1523 calculate_firstprivate_requirements (mapnum, sizes, kinds,
kono
parents:
diff changeset
1524 &tgt_align, &tgt_size);
kono
parents:
diff changeset
1525 if (tgt_align)
kono
parents:
diff changeset
1526 {
kono
parents:
diff changeset
1527 char *tgt = gomp_alloca (tgt_size + tgt_align - 1);
kono
parents:
diff changeset
1528 copy_firstprivate_data (tgt, mapnum, hostaddrs, sizes, kinds,
kono
parents:
diff changeset
1529 tgt_align, tgt_size);
kono
parents:
diff changeset
1530 }
kono
parents:
diff changeset
1531 fpc_done = true;
kono
parents:
diff changeset
1532 gomp_task_maybe_wait_for_dependencies (depend);
kono
parents:
diff changeset
1533 }
kono
parents:
diff changeset
1534 }
kono
parents:
diff changeset
1535
kono
parents:
diff changeset
1536 void *fn_addr;
kono
parents:
diff changeset
1537 if (devicep == NULL
kono
parents:
diff changeset
1538 || !(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
1539 || !(fn_addr = gomp_get_target_fn_addr (devicep, fn))
kono
parents:
diff changeset
1540 || (devicep->can_run_func && !devicep->can_run_func (fn_addr)))
kono
parents:
diff changeset
1541 {
kono
parents:
diff changeset
1542 if (!fpc_done)
kono
parents:
diff changeset
1543 {
kono
parents:
diff changeset
1544 calculate_firstprivate_requirements (mapnum, sizes, kinds,
kono
parents:
diff changeset
1545 &tgt_align, &tgt_size);
kono
parents:
diff changeset
1546 if (tgt_align)
kono
parents:
diff changeset
1547 {
kono
parents:
diff changeset
1548 char *tgt = gomp_alloca (tgt_size + tgt_align - 1);
kono
parents:
diff changeset
1549 copy_firstprivate_data (tgt, mapnum, hostaddrs, sizes, kinds,
kono
parents:
diff changeset
1550 tgt_align, tgt_size);
kono
parents:
diff changeset
1551 }
kono
parents:
diff changeset
1552 }
kono
parents:
diff changeset
1553 gomp_target_fallback (fn, hostaddrs);
kono
parents:
diff changeset
1554 return;
kono
parents:
diff changeset
1555 }
kono
parents:
diff changeset
1556
kono
parents:
diff changeset
1557 struct target_mem_desc *tgt_vars;
kono
parents:
diff changeset
1558 if (devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
1559 {
kono
parents:
diff changeset
1560 if (!fpc_done)
kono
parents:
diff changeset
1561 {
kono
parents:
diff changeset
1562 calculate_firstprivate_requirements (mapnum, sizes, kinds,
kono
parents:
diff changeset
1563 &tgt_align, &tgt_size);
kono
parents:
diff changeset
1564 if (tgt_align)
kono
parents:
diff changeset
1565 {
kono
parents:
diff changeset
1566 char *tgt = gomp_alloca (tgt_size + tgt_align - 1);
kono
parents:
diff changeset
1567 copy_firstprivate_data (tgt, mapnum, hostaddrs, sizes, kinds,
kono
parents:
diff changeset
1568 tgt_align, tgt_size);
kono
parents:
diff changeset
1569 }
kono
parents:
diff changeset
1570 }
kono
parents:
diff changeset
1571 tgt_vars = NULL;
kono
parents:
diff changeset
1572 }
kono
parents:
diff changeset
1573 else
kono
parents:
diff changeset
1574 tgt_vars = gomp_map_vars (devicep, mapnum, hostaddrs, NULL, sizes, kinds,
kono
parents:
diff changeset
1575 true, GOMP_MAP_VARS_TARGET);
kono
parents:
diff changeset
1576 devicep->run_func (devicep->target_id, fn_addr,
kono
parents:
diff changeset
1577 tgt_vars ? (void *) tgt_vars->tgt_start : hostaddrs,
kono
parents:
diff changeset
1578 args);
kono
parents:
diff changeset
1579 if (tgt_vars)
kono
parents:
diff changeset
1580 gomp_unmap_vars (tgt_vars, true);
kono
parents:
diff changeset
1581 }
kono
parents:
diff changeset
1582
kono
parents:
diff changeset
1583 /* Host fallback for GOMP_target_data{,_ext} routines. */
kono
parents:
diff changeset
1584
kono
parents:
diff changeset
1585 static void
kono
parents:
diff changeset
1586 gomp_target_data_fallback (void)
kono
parents:
diff changeset
1587 {
kono
parents:
diff changeset
1588 struct gomp_task_icv *icv = gomp_icv (false);
kono
parents:
diff changeset
1589 if (icv->target_data)
kono
parents:
diff changeset
1590 {
kono
parents:
diff changeset
1591 /* Even when doing a host fallback, if there are any active
kono
parents:
diff changeset
1592 #pragma omp target data constructs, need to remember the
kono
parents:
diff changeset
1593 new #pragma omp target data, otherwise GOMP_target_end_data
kono
parents:
diff changeset
1594 would get out of sync. */
kono
parents:
diff changeset
1595 struct target_mem_desc *tgt
kono
parents:
diff changeset
1596 = gomp_map_vars (NULL, 0, NULL, NULL, NULL, NULL, false,
kono
parents:
diff changeset
1597 GOMP_MAP_VARS_DATA);
kono
parents:
diff changeset
1598 tgt->prev = icv->target_data;
kono
parents:
diff changeset
1599 icv->target_data = tgt;
kono
parents:
diff changeset
1600 }
kono
parents:
diff changeset
1601 }
kono
parents:
diff changeset
1602
kono
parents:
diff changeset
1603 void
kono
parents:
diff changeset
1604 GOMP_target_data (int device, const void *unused, size_t mapnum,
kono
parents:
diff changeset
1605 void **hostaddrs, size_t *sizes, unsigned char *kinds)
kono
parents:
diff changeset
1606 {
kono
parents:
diff changeset
1607 struct gomp_device_descr *devicep = resolve_device (device);
kono
parents:
diff changeset
1608
kono
parents:
diff changeset
1609 if (devicep == NULL
kono
parents:
diff changeset
1610 || !(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
1611 || (devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM))
kono
parents:
diff changeset
1612 return gomp_target_data_fallback ();
kono
parents:
diff changeset
1613
kono
parents:
diff changeset
1614 struct target_mem_desc *tgt
kono
parents:
diff changeset
1615 = gomp_map_vars (devicep, mapnum, hostaddrs, NULL, sizes, kinds, false,
kono
parents:
diff changeset
1616 GOMP_MAP_VARS_DATA);
kono
parents:
diff changeset
1617 struct gomp_task_icv *icv = gomp_icv (true);
kono
parents:
diff changeset
1618 tgt->prev = icv->target_data;
kono
parents:
diff changeset
1619 icv->target_data = tgt;
kono
parents:
diff changeset
1620 }
kono
parents:
diff changeset
1621
kono
parents:
diff changeset
1622 void
kono
parents:
diff changeset
1623 GOMP_target_data_ext (int device, size_t mapnum, void **hostaddrs,
kono
parents:
diff changeset
1624 size_t *sizes, unsigned short *kinds)
kono
parents:
diff changeset
1625 {
kono
parents:
diff changeset
1626 struct gomp_device_descr *devicep = resolve_device (device);
kono
parents:
diff changeset
1627
kono
parents:
diff changeset
1628 if (devicep == NULL
kono
parents:
diff changeset
1629 || !(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
1630 || devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
1631 return gomp_target_data_fallback ();
kono
parents:
diff changeset
1632
kono
parents:
diff changeset
1633 struct target_mem_desc *tgt
kono
parents:
diff changeset
1634 = gomp_map_vars (devicep, mapnum, hostaddrs, NULL, sizes, kinds, true,
kono
parents:
diff changeset
1635 GOMP_MAP_VARS_DATA);
kono
parents:
diff changeset
1636 struct gomp_task_icv *icv = gomp_icv (true);
kono
parents:
diff changeset
1637 tgt->prev = icv->target_data;
kono
parents:
diff changeset
1638 icv->target_data = tgt;
kono
parents:
diff changeset
1639 }
kono
parents:
diff changeset
1640
kono
parents:
diff changeset
1641 void
kono
parents:
diff changeset
1642 GOMP_target_end_data (void)
kono
parents:
diff changeset
1643 {
kono
parents:
diff changeset
1644 struct gomp_task_icv *icv = gomp_icv (false);
kono
parents:
diff changeset
1645 if (icv->target_data)
kono
parents:
diff changeset
1646 {
kono
parents:
diff changeset
1647 struct target_mem_desc *tgt = icv->target_data;
kono
parents:
diff changeset
1648 icv->target_data = tgt->prev;
kono
parents:
diff changeset
1649 gomp_unmap_vars (tgt, true);
kono
parents:
diff changeset
1650 }
kono
parents:
diff changeset
1651 }
kono
parents:
diff changeset
1652
kono
parents:
diff changeset
1653 void
kono
parents:
diff changeset
1654 GOMP_target_update (int device, const void *unused, size_t mapnum,
kono
parents:
diff changeset
1655 void **hostaddrs, size_t *sizes, unsigned char *kinds)
kono
parents:
diff changeset
1656 {
kono
parents:
diff changeset
1657 struct gomp_device_descr *devicep = resolve_device (device);
kono
parents:
diff changeset
1658
kono
parents:
diff changeset
1659 if (devicep == NULL
kono
parents:
diff changeset
1660 || !(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
1661 || devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
1662 return;
kono
parents:
diff changeset
1663
kono
parents:
diff changeset
1664 gomp_update (devicep, mapnum, hostaddrs, sizes, kinds, false);
kono
parents:
diff changeset
1665 }
kono
parents:
diff changeset
1666
kono
parents:
diff changeset
1667 void
kono
parents:
diff changeset
1668 GOMP_target_update_ext (int device, size_t mapnum, void **hostaddrs,
kono
parents:
diff changeset
1669 size_t *sizes, unsigned short *kinds,
kono
parents:
diff changeset
1670 unsigned int flags, void **depend)
kono
parents:
diff changeset
1671 {
kono
parents:
diff changeset
1672 struct gomp_device_descr *devicep = resolve_device (device);
kono
parents:
diff changeset
1673
kono
parents:
diff changeset
1674 /* If there are depend clauses, but nowait is not present,
kono
parents:
diff changeset
1675 block the parent task until the dependencies are resolved
kono
parents:
diff changeset
1676 and then just continue with the rest of the function as if it
kono
parents:
diff changeset
1677 is a merged task. Until we are able to schedule task during
kono
parents:
diff changeset
1678 variable mapping or unmapping, ignore nowait if depend clauses
kono
parents:
diff changeset
1679 are not present. */
kono
parents:
diff changeset
1680 if (depend != NULL)
kono
parents:
diff changeset
1681 {
kono
parents:
diff changeset
1682 struct gomp_thread *thr = gomp_thread ();
kono
parents:
diff changeset
1683 if (thr->task && thr->task->depend_hash)
kono
parents:
diff changeset
1684 {
kono
parents:
diff changeset
1685 if ((flags & GOMP_TARGET_FLAG_NOWAIT)
kono
parents:
diff changeset
1686 && thr->ts.team
kono
parents:
diff changeset
1687 && !thr->task->final_task)
kono
parents:
diff changeset
1688 {
kono
parents:
diff changeset
1689 if (gomp_create_target_task (devicep, (void (*) (void *)) NULL,
kono
parents:
diff changeset
1690 mapnum, hostaddrs, sizes, kinds,
kono
parents:
diff changeset
1691 flags | GOMP_TARGET_FLAG_UPDATE,
kono
parents:
diff changeset
1692 depend, NULL, GOMP_TARGET_TASK_DATA))
kono
parents:
diff changeset
1693 return;
kono
parents:
diff changeset
1694 }
kono
parents:
diff changeset
1695 else
kono
parents:
diff changeset
1696 {
kono
parents:
diff changeset
1697 struct gomp_team *team = thr->ts.team;
kono
parents:
diff changeset
1698 /* If parallel or taskgroup has been cancelled, don't start new
kono
parents:
diff changeset
1699 tasks. */
kono
parents:
diff changeset
1700 if (team
kono
parents:
diff changeset
1701 && (gomp_team_barrier_cancelled (&team->barrier)
kono
parents:
diff changeset
1702 || (thr->task->taskgroup
kono
parents:
diff changeset
1703 && thr->task->taskgroup->cancelled)))
kono
parents:
diff changeset
1704 return;
kono
parents:
diff changeset
1705
kono
parents:
diff changeset
1706 gomp_task_maybe_wait_for_dependencies (depend);
kono
parents:
diff changeset
1707 }
kono
parents:
diff changeset
1708 }
kono
parents:
diff changeset
1709 }
kono
parents:
diff changeset
1710
kono
parents:
diff changeset
1711 if (devicep == NULL
kono
parents:
diff changeset
1712 || !(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
1713 || devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
1714 return;
kono
parents:
diff changeset
1715
kono
parents:
diff changeset
1716 struct gomp_thread *thr = gomp_thread ();
kono
parents:
diff changeset
1717 struct gomp_team *team = thr->ts.team;
kono
parents:
diff changeset
1718 /* If parallel or taskgroup has been cancelled, don't start new tasks. */
kono
parents:
diff changeset
1719 if (team
kono
parents:
diff changeset
1720 && (gomp_team_barrier_cancelled (&team->barrier)
kono
parents:
diff changeset
1721 || (thr->task->taskgroup && thr->task->taskgroup->cancelled)))
kono
parents:
diff changeset
1722 return;
kono
parents:
diff changeset
1723
kono
parents:
diff changeset
1724 gomp_update (devicep, mapnum, hostaddrs, sizes, kinds, true);
kono
parents:
diff changeset
1725 }
kono
parents:
diff changeset
1726
kono
parents:
diff changeset
1727 static void
kono
parents:
diff changeset
1728 gomp_exit_data (struct gomp_device_descr *devicep, size_t mapnum,
kono
parents:
diff changeset
1729 void **hostaddrs, size_t *sizes, unsigned short *kinds)
kono
parents:
diff changeset
1730 {
kono
parents:
diff changeset
1731 const int typemask = 0xff;
kono
parents:
diff changeset
1732 size_t i;
kono
parents:
diff changeset
1733 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
1734 if (devicep->state == GOMP_DEVICE_FINALIZED)
kono
parents:
diff changeset
1735 {
kono
parents:
diff changeset
1736 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
1737 return;
kono
parents:
diff changeset
1738 }
kono
parents:
diff changeset
1739
kono
parents:
diff changeset
1740 for (i = 0; i < mapnum; i++)
kono
parents:
diff changeset
1741 {
kono
parents:
diff changeset
1742 struct splay_tree_key_s cur_node;
kono
parents:
diff changeset
1743 unsigned char kind = kinds[i] & typemask;
kono
parents:
diff changeset
1744 switch (kind)
kono
parents:
diff changeset
1745 {
kono
parents:
diff changeset
1746 case GOMP_MAP_FROM:
kono
parents:
diff changeset
1747 case GOMP_MAP_ALWAYS_FROM:
kono
parents:
diff changeset
1748 case GOMP_MAP_DELETE:
kono
parents:
diff changeset
1749 case GOMP_MAP_RELEASE:
kono
parents:
diff changeset
1750 case GOMP_MAP_ZERO_LEN_ARRAY_SECTION:
kono
parents:
diff changeset
1751 case GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION:
kono
parents:
diff changeset
1752 cur_node.host_start = (uintptr_t) hostaddrs[i];
kono
parents:
diff changeset
1753 cur_node.host_end = cur_node.host_start + sizes[i];
kono
parents:
diff changeset
1754 splay_tree_key k = (kind == GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION
kono
parents:
diff changeset
1755 || kind == GOMP_MAP_ZERO_LEN_ARRAY_SECTION)
kono
parents:
diff changeset
1756 ? gomp_map_0len_lookup (&devicep->mem_map, &cur_node)
kono
parents:
diff changeset
1757 : splay_tree_lookup (&devicep->mem_map, &cur_node);
kono
parents:
diff changeset
1758 if (!k)
kono
parents:
diff changeset
1759 continue;
kono
parents:
diff changeset
1760
kono
parents:
diff changeset
1761 if (k->refcount > 0 && k->refcount != REFCOUNT_INFINITY)
kono
parents:
diff changeset
1762 k->refcount--;
kono
parents:
diff changeset
1763 if ((kind == GOMP_MAP_DELETE
kono
parents:
diff changeset
1764 || kind == GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION)
kono
parents:
diff changeset
1765 && k->refcount != REFCOUNT_INFINITY)
kono
parents:
diff changeset
1766 k->refcount = 0;
kono
parents:
diff changeset
1767
kono
parents:
diff changeset
1768 if ((kind == GOMP_MAP_FROM && k->refcount == 0)
kono
parents:
diff changeset
1769 || kind == GOMP_MAP_ALWAYS_FROM)
kono
parents:
diff changeset
1770 gomp_copy_dev2host (devicep, (void *) cur_node.host_start,
kono
parents:
diff changeset
1771 (void *) (k->tgt->tgt_start + k->tgt_offset
kono
parents:
diff changeset
1772 + cur_node.host_start
kono
parents:
diff changeset
1773 - k->host_start),
kono
parents:
diff changeset
1774 cur_node.host_end - cur_node.host_start);
kono
parents:
diff changeset
1775 if (k->refcount == 0)
kono
parents:
diff changeset
1776 {
kono
parents:
diff changeset
1777 splay_tree_remove (&devicep->mem_map, k);
kono
parents:
diff changeset
1778 if (k->link_key)
kono
parents:
diff changeset
1779 splay_tree_insert (&devicep->mem_map,
kono
parents:
diff changeset
1780 (splay_tree_node) k->link_key);
kono
parents:
diff changeset
1781 if (k->tgt->refcount > 1)
kono
parents:
diff changeset
1782 k->tgt->refcount--;
kono
parents:
diff changeset
1783 else
kono
parents:
diff changeset
1784 gomp_unmap_tgt (k->tgt);
kono
parents:
diff changeset
1785 }
kono
parents:
diff changeset
1786
kono
parents:
diff changeset
1787 break;
kono
parents:
diff changeset
1788 default:
kono
parents:
diff changeset
1789 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
1790 gomp_fatal ("GOMP_target_enter_exit_data unhandled kind 0x%.2x",
kono
parents:
diff changeset
1791 kind);
kono
parents:
diff changeset
1792 }
kono
parents:
diff changeset
1793 }
kono
parents:
diff changeset
1794
kono
parents:
diff changeset
1795 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
1796 }
kono
parents:
diff changeset
1797
kono
parents:
diff changeset
1798 void
kono
parents:
diff changeset
1799 GOMP_target_enter_exit_data (int device, size_t mapnum, void **hostaddrs,
kono
parents:
diff changeset
1800 size_t *sizes, unsigned short *kinds,
kono
parents:
diff changeset
1801 unsigned int flags, void **depend)
kono
parents:
diff changeset
1802 {
kono
parents:
diff changeset
1803 struct gomp_device_descr *devicep = resolve_device (device);
kono
parents:
diff changeset
1804
kono
parents:
diff changeset
1805 /* If there are depend clauses, but nowait is not present,
kono
parents:
diff changeset
1806 block the parent task until the dependencies are resolved
kono
parents:
diff changeset
1807 and then just continue with the rest of the function as if it
kono
parents:
diff changeset
1808 is a merged task. Until we are able to schedule task during
kono
parents:
diff changeset
1809 variable mapping or unmapping, ignore nowait if depend clauses
kono
parents:
diff changeset
1810 are not present. */
kono
parents:
diff changeset
1811 if (depend != NULL)
kono
parents:
diff changeset
1812 {
kono
parents:
diff changeset
1813 struct gomp_thread *thr = gomp_thread ();
kono
parents:
diff changeset
1814 if (thr->task && thr->task->depend_hash)
kono
parents:
diff changeset
1815 {
kono
parents:
diff changeset
1816 if ((flags & GOMP_TARGET_FLAG_NOWAIT)
kono
parents:
diff changeset
1817 && thr->ts.team
kono
parents:
diff changeset
1818 && !thr->task->final_task)
kono
parents:
diff changeset
1819 {
kono
parents:
diff changeset
1820 if (gomp_create_target_task (devicep, (void (*) (void *)) NULL,
kono
parents:
diff changeset
1821 mapnum, hostaddrs, sizes, kinds,
kono
parents:
diff changeset
1822 flags, depend, NULL,
kono
parents:
diff changeset
1823 GOMP_TARGET_TASK_DATA))
kono
parents:
diff changeset
1824 return;
kono
parents:
diff changeset
1825 }
kono
parents:
diff changeset
1826 else
kono
parents:
diff changeset
1827 {
kono
parents:
diff changeset
1828 struct gomp_team *team = thr->ts.team;
kono
parents:
diff changeset
1829 /* If parallel or taskgroup has been cancelled, don't start new
kono
parents:
diff changeset
1830 tasks. */
kono
parents:
diff changeset
1831 if (team
kono
parents:
diff changeset
1832 && (gomp_team_barrier_cancelled (&team->barrier)
kono
parents:
diff changeset
1833 || (thr->task->taskgroup
kono
parents:
diff changeset
1834 && thr->task->taskgroup->cancelled)))
kono
parents:
diff changeset
1835 return;
kono
parents:
diff changeset
1836
kono
parents:
diff changeset
1837 gomp_task_maybe_wait_for_dependencies (depend);
kono
parents:
diff changeset
1838 }
kono
parents:
diff changeset
1839 }
kono
parents:
diff changeset
1840 }
kono
parents:
diff changeset
1841
kono
parents:
diff changeset
1842 if (devicep == NULL
kono
parents:
diff changeset
1843 || !(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
1844 || devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
1845 return;
kono
parents:
diff changeset
1846
kono
parents:
diff changeset
1847 struct gomp_thread *thr = gomp_thread ();
kono
parents:
diff changeset
1848 struct gomp_team *team = thr->ts.team;
kono
parents:
diff changeset
1849 /* If parallel or taskgroup has been cancelled, don't start new tasks. */
kono
parents:
diff changeset
1850 if (team
kono
parents:
diff changeset
1851 && (gomp_team_barrier_cancelled (&team->barrier)
kono
parents:
diff changeset
1852 || (thr->task->taskgroup && thr->task->taskgroup->cancelled)))
kono
parents:
diff changeset
1853 return;
kono
parents:
diff changeset
1854
kono
parents:
diff changeset
1855 size_t i;
kono
parents:
diff changeset
1856 if ((flags & GOMP_TARGET_FLAG_EXIT_DATA) == 0)
kono
parents:
diff changeset
1857 for (i = 0; i < mapnum; i++)
kono
parents:
diff changeset
1858 if ((kinds[i] & 0xff) == GOMP_MAP_STRUCT)
kono
parents:
diff changeset
1859 {
kono
parents:
diff changeset
1860 gomp_map_vars (devicep, sizes[i] + 1, &hostaddrs[i], NULL, &sizes[i],
kono
parents:
diff changeset
1861 &kinds[i], true, GOMP_MAP_VARS_ENTER_DATA);
kono
parents:
diff changeset
1862 i += sizes[i];
kono
parents:
diff changeset
1863 }
kono
parents:
diff changeset
1864 else
kono
parents:
diff changeset
1865 gomp_map_vars (devicep, 1, &hostaddrs[i], NULL, &sizes[i], &kinds[i],
kono
parents:
diff changeset
1866 true, GOMP_MAP_VARS_ENTER_DATA);
kono
parents:
diff changeset
1867 else
kono
parents:
diff changeset
1868 gomp_exit_data (devicep, mapnum, hostaddrs, sizes, kinds);
kono
parents:
diff changeset
1869 }
kono
parents:
diff changeset
1870
kono
parents:
diff changeset
1871 bool
kono
parents:
diff changeset
1872 gomp_target_task_fn (void *data)
kono
parents:
diff changeset
1873 {
kono
parents:
diff changeset
1874 struct gomp_target_task *ttask = (struct gomp_target_task *) data;
kono
parents:
diff changeset
1875 struct gomp_device_descr *devicep = ttask->devicep;
kono
parents:
diff changeset
1876
kono
parents:
diff changeset
1877 if (ttask->fn != NULL)
kono
parents:
diff changeset
1878 {
kono
parents:
diff changeset
1879 void *fn_addr;
kono
parents:
diff changeset
1880 if (devicep == NULL
kono
parents:
diff changeset
1881 || !(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
1882 || !(fn_addr = gomp_get_target_fn_addr (devicep, ttask->fn))
kono
parents:
diff changeset
1883 || (devicep->can_run_func && !devicep->can_run_func (fn_addr)))
kono
parents:
diff changeset
1884 {
kono
parents:
diff changeset
1885 ttask->state = GOMP_TARGET_TASK_FALLBACK;
kono
parents:
diff changeset
1886 gomp_target_fallback (ttask->fn, ttask->hostaddrs);
kono
parents:
diff changeset
1887 return false;
kono
parents:
diff changeset
1888 }
kono
parents:
diff changeset
1889
kono
parents:
diff changeset
1890 if (ttask->state == GOMP_TARGET_TASK_FINISHED)
kono
parents:
diff changeset
1891 {
kono
parents:
diff changeset
1892 if (ttask->tgt)
kono
parents:
diff changeset
1893 gomp_unmap_vars (ttask->tgt, true);
kono
parents:
diff changeset
1894 return false;
kono
parents:
diff changeset
1895 }
kono
parents:
diff changeset
1896
kono
parents:
diff changeset
1897 void *actual_arguments;
kono
parents:
diff changeset
1898 if (devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
1899 {
kono
parents:
diff changeset
1900 ttask->tgt = NULL;
kono
parents:
diff changeset
1901 actual_arguments = ttask->hostaddrs;
kono
parents:
diff changeset
1902 }
kono
parents:
diff changeset
1903 else
kono
parents:
diff changeset
1904 {
kono
parents:
diff changeset
1905 ttask->tgt = gomp_map_vars (devicep, ttask->mapnum, ttask->hostaddrs,
kono
parents:
diff changeset
1906 NULL, ttask->sizes, ttask->kinds, true,
kono
parents:
diff changeset
1907 GOMP_MAP_VARS_TARGET);
kono
parents:
diff changeset
1908 actual_arguments = (void *) ttask->tgt->tgt_start;
kono
parents:
diff changeset
1909 }
kono
parents:
diff changeset
1910 ttask->state = GOMP_TARGET_TASK_READY_TO_RUN;
kono
parents:
diff changeset
1911
kono
parents:
diff changeset
1912 devicep->async_run_func (devicep->target_id, fn_addr, actual_arguments,
kono
parents:
diff changeset
1913 ttask->args, (void *) ttask);
kono
parents:
diff changeset
1914 return true;
kono
parents:
diff changeset
1915 }
kono
parents:
diff changeset
1916 else if (devicep == NULL
kono
parents:
diff changeset
1917 || !(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
1918 || devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
1919 return false;
kono
parents:
diff changeset
1920
kono
parents:
diff changeset
1921 size_t i;
kono
parents:
diff changeset
1922 if (ttask->flags & GOMP_TARGET_FLAG_UPDATE)
kono
parents:
diff changeset
1923 gomp_update (devicep, ttask->mapnum, ttask->hostaddrs, ttask->sizes,
kono
parents:
diff changeset
1924 ttask->kinds, true);
kono
parents:
diff changeset
1925 else if ((ttask->flags & GOMP_TARGET_FLAG_EXIT_DATA) == 0)
kono
parents:
diff changeset
1926 for (i = 0; i < ttask->mapnum; i++)
kono
parents:
diff changeset
1927 if ((ttask->kinds[i] & 0xff) == GOMP_MAP_STRUCT)
kono
parents:
diff changeset
1928 {
kono
parents:
diff changeset
1929 gomp_map_vars (devicep, ttask->sizes[i] + 1, &ttask->hostaddrs[i],
kono
parents:
diff changeset
1930 NULL, &ttask->sizes[i], &ttask->kinds[i], true,
kono
parents:
diff changeset
1931 GOMP_MAP_VARS_ENTER_DATA);
kono
parents:
diff changeset
1932 i += ttask->sizes[i];
kono
parents:
diff changeset
1933 }
kono
parents:
diff changeset
1934 else
kono
parents:
diff changeset
1935 gomp_map_vars (devicep, 1, &ttask->hostaddrs[i], NULL, &ttask->sizes[i],
kono
parents:
diff changeset
1936 &ttask->kinds[i], true, GOMP_MAP_VARS_ENTER_DATA);
kono
parents:
diff changeset
1937 else
kono
parents:
diff changeset
1938 gomp_exit_data (devicep, ttask->mapnum, ttask->hostaddrs, ttask->sizes,
kono
parents:
diff changeset
1939 ttask->kinds);
kono
parents:
diff changeset
1940 return false;
kono
parents:
diff changeset
1941 }
kono
parents:
diff changeset
1942
kono
parents:
diff changeset
1943 void
kono
parents:
diff changeset
1944 GOMP_teams (unsigned int num_teams, unsigned int thread_limit)
kono
parents:
diff changeset
1945 {
kono
parents:
diff changeset
1946 if (thread_limit)
kono
parents:
diff changeset
1947 {
kono
parents:
diff changeset
1948 struct gomp_task_icv *icv = gomp_icv (true);
kono
parents:
diff changeset
1949 icv->thread_limit_var
kono
parents:
diff changeset
1950 = thread_limit > INT_MAX ? UINT_MAX : thread_limit;
kono
parents:
diff changeset
1951 }
kono
parents:
diff changeset
1952 (void) num_teams;
kono
parents:
diff changeset
1953 }
kono
parents:
diff changeset
1954
kono
parents:
diff changeset
1955 void *
kono
parents:
diff changeset
1956 omp_target_alloc (size_t size, int device_num)
kono
parents:
diff changeset
1957 {
kono
parents:
diff changeset
1958 if (device_num == GOMP_DEVICE_HOST_FALLBACK)
kono
parents:
diff changeset
1959 return malloc (size);
kono
parents:
diff changeset
1960
kono
parents:
diff changeset
1961 if (device_num < 0)
kono
parents:
diff changeset
1962 return NULL;
kono
parents:
diff changeset
1963
kono
parents:
diff changeset
1964 struct gomp_device_descr *devicep = resolve_device (device_num);
kono
parents:
diff changeset
1965 if (devicep == NULL)
kono
parents:
diff changeset
1966 return NULL;
kono
parents:
diff changeset
1967
kono
parents:
diff changeset
1968 if (!(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
1969 || devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
1970 return malloc (size);
kono
parents:
diff changeset
1971
kono
parents:
diff changeset
1972 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
1973 void *ret = devicep->alloc_func (devicep->target_id, size);
kono
parents:
diff changeset
1974 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
1975 return ret;
kono
parents:
diff changeset
1976 }
kono
parents:
diff changeset
1977
kono
parents:
diff changeset
1978 void
kono
parents:
diff changeset
1979 omp_target_free (void *device_ptr, int device_num)
kono
parents:
diff changeset
1980 {
kono
parents:
diff changeset
1981 if (device_ptr == NULL)
kono
parents:
diff changeset
1982 return;
kono
parents:
diff changeset
1983
kono
parents:
diff changeset
1984 if (device_num == GOMP_DEVICE_HOST_FALLBACK)
kono
parents:
diff changeset
1985 {
kono
parents:
diff changeset
1986 free (device_ptr);
kono
parents:
diff changeset
1987 return;
kono
parents:
diff changeset
1988 }
kono
parents:
diff changeset
1989
kono
parents:
diff changeset
1990 if (device_num < 0)
kono
parents:
diff changeset
1991 return;
kono
parents:
diff changeset
1992
kono
parents:
diff changeset
1993 struct gomp_device_descr *devicep = resolve_device (device_num);
kono
parents:
diff changeset
1994 if (devicep == NULL)
kono
parents:
diff changeset
1995 return;
kono
parents:
diff changeset
1996
kono
parents:
diff changeset
1997 if (!(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
1998 || devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
1999 {
kono
parents:
diff changeset
2000 free (device_ptr);
kono
parents:
diff changeset
2001 return;
kono
parents:
diff changeset
2002 }
kono
parents:
diff changeset
2003
kono
parents:
diff changeset
2004 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
2005 gomp_free_device_memory (devicep, device_ptr);
kono
parents:
diff changeset
2006 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
2007 }
kono
parents:
diff changeset
2008
kono
parents:
diff changeset
2009 int
kono
parents:
diff changeset
2010 omp_target_is_present (void *ptr, int device_num)
kono
parents:
diff changeset
2011 {
kono
parents:
diff changeset
2012 if (ptr == NULL)
kono
parents:
diff changeset
2013 return 1;
kono
parents:
diff changeset
2014
kono
parents:
diff changeset
2015 if (device_num == GOMP_DEVICE_HOST_FALLBACK)
kono
parents:
diff changeset
2016 return 1;
kono
parents:
diff changeset
2017
kono
parents:
diff changeset
2018 if (device_num < 0)
kono
parents:
diff changeset
2019 return 0;
kono
parents:
diff changeset
2020
kono
parents:
diff changeset
2021 struct gomp_device_descr *devicep = resolve_device (device_num);
kono
parents:
diff changeset
2022 if (devicep == NULL)
kono
parents:
diff changeset
2023 return 0;
kono
parents:
diff changeset
2024
kono
parents:
diff changeset
2025 if (!(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
2026 || devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
2027 return 1;
kono
parents:
diff changeset
2028
kono
parents:
diff changeset
2029 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
2030 struct splay_tree_s *mem_map = &devicep->mem_map;
kono
parents:
diff changeset
2031 struct splay_tree_key_s cur_node;
kono
parents:
diff changeset
2032
kono
parents:
diff changeset
2033 cur_node.host_start = (uintptr_t) ptr;
kono
parents:
diff changeset
2034 cur_node.host_end = cur_node.host_start;
kono
parents:
diff changeset
2035 splay_tree_key n = gomp_map_0len_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
2036 int ret = n != NULL;
kono
parents:
diff changeset
2037 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
2038 return ret;
kono
parents:
diff changeset
2039 }
kono
parents:
diff changeset
2040
kono
parents:
diff changeset
2041 int
kono
parents:
diff changeset
2042 omp_target_memcpy (void *dst, void *src, size_t length, size_t dst_offset,
kono
parents:
diff changeset
2043 size_t src_offset, int dst_device_num, int src_device_num)
kono
parents:
diff changeset
2044 {
kono
parents:
diff changeset
2045 struct gomp_device_descr *dst_devicep = NULL, *src_devicep = NULL;
kono
parents:
diff changeset
2046 bool ret;
kono
parents:
diff changeset
2047
kono
parents:
diff changeset
2048 if (dst_device_num != GOMP_DEVICE_HOST_FALLBACK)
kono
parents:
diff changeset
2049 {
kono
parents:
diff changeset
2050 if (dst_device_num < 0)
kono
parents:
diff changeset
2051 return EINVAL;
kono
parents:
diff changeset
2052
kono
parents:
diff changeset
2053 dst_devicep = resolve_device (dst_device_num);
kono
parents:
diff changeset
2054 if (dst_devicep == NULL)
kono
parents:
diff changeset
2055 return EINVAL;
kono
parents:
diff changeset
2056
kono
parents:
diff changeset
2057 if (!(dst_devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
2058 || dst_devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
2059 dst_devicep = NULL;
kono
parents:
diff changeset
2060 }
kono
parents:
diff changeset
2061 if (src_device_num != GOMP_DEVICE_HOST_FALLBACK)
kono
parents:
diff changeset
2062 {
kono
parents:
diff changeset
2063 if (src_device_num < 0)
kono
parents:
diff changeset
2064 return EINVAL;
kono
parents:
diff changeset
2065
kono
parents:
diff changeset
2066 src_devicep = resolve_device (src_device_num);
kono
parents:
diff changeset
2067 if (src_devicep == NULL)
kono
parents:
diff changeset
2068 return EINVAL;
kono
parents:
diff changeset
2069
kono
parents:
diff changeset
2070 if (!(src_devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
2071 || src_devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
2072 src_devicep = NULL;
kono
parents:
diff changeset
2073 }
kono
parents:
diff changeset
2074 if (src_devicep == NULL && dst_devicep == NULL)
kono
parents:
diff changeset
2075 {
kono
parents:
diff changeset
2076 memcpy ((char *) dst + dst_offset, (char *) src + src_offset, length);
kono
parents:
diff changeset
2077 return 0;
kono
parents:
diff changeset
2078 }
kono
parents:
diff changeset
2079 if (src_devicep == NULL)
kono
parents:
diff changeset
2080 {
kono
parents:
diff changeset
2081 gomp_mutex_lock (&dst_devicep->lock);
kono
parents:
diff changeset
2082 ret = dst_devicep->host2dev_func (dst_devicep->target_id,
kono
parents:
diff changeset
2083 (char *) dst + dst_offset,
kono
parents:
diff changeset
2084 (char *) src + src_offset, length);
kono
parents:
diff changeset
2085 gomp_mutex_unlock (&dst_devicep->lock);
kono
parents:
diff changeset
2086 return (ret ? 0 : EINVAL);
kono
parents:
diff changeset
2087 }
kono
parents:
diff changeset
2088 if (dst_devicep == NULL)
kono
parents:
diff changeset
2089 {
kono
parents:
diff changeset
2090 gomp_mutex_lock (&src_devicep->lock);
kono
parents:
diff changeset
2091 ret = src_devicep->dev2host_func (src_devicep->target_id,
kono
parents:
diff changeset
2092 (char *) dst + dst_offset,
kono
parents:
diff changeset
2093 (char *) src + src_offset, length);
kono
parents:
diff changeset
2094 gomp_mutex_unlock (&src_devicep->lock);
kono
parents:
diff changeset
2095 return (ret ? 0 : EINVAL);
kono
parents:
diff changeset
2096 }
kono
parents:
diff changeset
2097 if (src_devicep == dst_devicep)
kono
parents:
diff changeset
2098 {
kono
parents:
diff changeset
2099 gomp_mutex_lock (&src_devicep->lock);
kono
parents:
diff changeset
2100 ret = src_devicep->dev2dev_func (src_devicep->target_id,
kono
parents:
diff changeset
2101 (char *) dst + dst_offset,
kono
parents:
diff changeset
2102 (char *) src + src_offset, length);
kono
parents:
diff changeset
2103 gomp_mutex_unlock (&src_devicep->lock);
kono
parents:
diff changeset
2104 return (ret ? 0 : EINVAL);
kono
parents:
diff changeset
2105 }
kono
parents:
diff changeset
2106 return EINVAL;
kono
parents:
diff changeset
2107 }
kono
parents:
diff changeset
2108
kono
parents:
diff changeset
2109 static int
kono
parents:
diff changeset
2110 omp_target_memcpy_rect_worker (void *dst, void *src, size_t element_size,
kono
parents:
diff changeset
2111 int num_dims, const size_t *volume,
kono
parents:
diff changeset
2112 const size_t *dst_offsets,
kono
parents:
diff changeset
2113 const size_t *src_offsets,
kono
parents:
diff changeset
2114 const size_t *dst_dimensions,
kono
parents:
diff changeset
2115 const size_t *src_dimensions,
kono
parents:
diff changeset
2116 struct gomp_device_descr *dst_devicep,
kono
parents:
diff changeset
2117 struct gomp_device_descr *src_devicep)
kono
parents:
diff changeset
2118 {
kono
parents:
diff changeset
2119 size_t dst_slice = element_size;
kono
parents:
diff changeset
2120 size_t src_slice = element_size;
kono
parents:
diff changeset
2121 size_t j, dst_off, src_off, length;
kono
parents:
diff changeset
2122 int i, ret;
kono
parents:
diff changeset
2123
kono
parents:
diff changeset
2124 if (num_dims == 1)
kono
parents:
diff changeset
2125 {
kono
parents:
diff changeset
2126 if (__builtin_mul_overflow (element_size, volume[0], &length)
kono
parents:
diff changeset
2127 || __builtin_mul_overflow (element_size, dst_offsets[0], &dst_off)
kono
parents:
diff changeset
2128 || __builtin_mul_overflow (element_size, src_offsets[0], &src_off))
kono
parents:
diff changeset
2129 return EINVAL;
kono
parents:
diff changeset
2130 if (dst_devicep == NULL && src_devicep == NULL)
kono
parents:
diff changeset
2131 {
kono
parents:
diff changeset
2132 memcpy ((char *) dst + dst_off, (char *) src + src_off, length);
kono
parents:
diff changeset
2133 ret = 1;
kono
parents:
diff changeset
2134 }
kono
parents:
diff changeset
2135 else if (src_devicep == NULL)
kono
parents:
diff changeset
2136 ret = dst_devicep->host2dev_func (dst_devicep->target_id,
kono
parents:
diff changeset
2137 (char *) dst + dst_off,
kono
parents:
diff changeset
2138 (char *) src + src_off, length);
kono
parents:
diff changeset
2139 else if (dst_devicep == NULL)
kono
parents:
diff changeset
2140 ret = src_devicep->dev2host_func (src_devicep->target_id,
kono
parents:
diff changeset
2141 (char *) dst + dst_off,
kono
parents:
diff changeset
2142 (char *) src + src_off, length);
kono
parents:
diff changeset
2143 else if (src_devicep == dst_devicep)
kono
parents:
diff changeset
2144 ret = src_devicep->dev2dev_func (src_devicep->target_id,
kono
parents:
diff changeset
2145 (char *) dst + dst_off,
kono
parents:
diff changeset
2146 (char *) src + src_off, length);
kono
parents:
diff changeset
2147 else
kono
parents:
diff changeset
2148 ret = 0;
kono
parents:
diff changeset
2149 return ret ? 0 : EINVAL;
kono
parents:
diff changeset
2150 }
kono
parents:
diff changeset
2151
kono
parents:
diff changeset
2152 /* FIXME: it would be nice to have some plugin function to handle
kono
parents:
diff changeset
2153 num_dims == 2 and num_dims == 3 more efficiently. Larger ones can
kono
parents:
diff changeset
2154 be handled in the generic recursion below, and for host-host it
kono
parents:
diff changeset
2155 should be used even for any num_dims >= 2. */
kono
parents:
diff changeset
2156
kono
parents:
diff changeset
2157 for (i = 1; i < num_dims; i++)
kono
parents:
diff changeset
2158 if (__builtin_mul_overflow (dst_slice, dst_dimensions[i], &dst_slice)
kono
parents:
diff changeset
2159 || __builtin_mul_overflow (src_slice, src_dimensions[i], &src_slice))
kono
parents:
diff changeset
2160 return EINVAL;
kono
parents:
diff changeset
2161 if (__builtin_mul_overflow (dst_slice, dst_offsets[0], &dst_off)
kono
parents:
diff changeset
2162 || __builtin_mul_overflow (src_slice, src_offsets[0], &src_off))
kono
parents:
diff changeset
2163 return EINVAL;
kono
parents:
diff changeset
2164 for (j = 0; j < volume[0]; j++)
kono
parents:
diff changeset
2165 {
kono
parents:
diff changeset
2166 ret = omp_target_memcpy_rect_worker ((char *) dst + dst_off,
kono
parents:
diff changeset
2167 (char *) src + src_off,
kono
parents:
diff changeset
2168 element_size, num_dims - 1,
kono
parents:
diff changeset
2169 volume + 1, dst_offsets + 1,
kono
parents:
diff changeset
2170 src_offsets + 1, dst_dimensions + 1,
kono
parents:
diff changeset
2171 src_dimensions + 1, dst_devicep,
kono
parents:
diff changeset
2172 src_devicep);
kono
parents:
diff changeset
2173 if (ret)
kono
parents:
diff changeset
2174 return ret;
kono
parents:
diff changeset
2175 dst_off += dst_slice;
kono
parents:
diff changeset
2176 src_off += src_slice;
kono
parents:
diff changeset
2177 }
kono
parents:
diff changeset
2178 return 0;
kono
parents:
diff changeset
2179 }
kono
parents:
diff changeset
2180
kono
parents:
diff changeset
2181 int
kono
parents:
diff changeset
2182 omp_target_memcpy_rect (void *dst, void *src, size_t element_size,
kono
parents:
diff changeset
2183 int num_dims, const size_t *volume,
kono
parents:
diff changeset
2184 const size_t *dst_offsets,
kono
parents:
diff changeset
2185 const size_t *src_offsets,
kono
parents:
diff changeset
2186 const size_t *dst_dimensions,
kono
parents:
diff changeset
2187 const size_t *src_dimensions,
kono
parents:
diff changeset
2188 int dst_device_num, int src_device_num)
kono
parents:
diff changeset
2189 {
kono
parents:
diff changeset
2190 struct gomp_device_descr *dst_devicep = NULL, *src_devicep = NULL;
kono
parents:
diff changeset
2191
kono
parents:
diff changeset
2192 if (!dst && !src)
kono
parents:
diff changeset
2193 return INT_MAX;
kono
parents:
diff changeset
2194
kono
parents:
diff changeset
2195 if (dst_device_num != GOMP_DEVICE_HOST_FALLBACK)
kono
parents:
diff changeset
2196 {
kono
parents:
diff changeset
2197 if (dst_device_num < 0)
kono
parents:
diff changeset
2198 return EINVAL;
kono
parents:
diff changeset
2199
kono
parents:
diff changeset
2200 dst_devicep = resolve_device (dst_device_num);
kono
parents:
diff changeset
2201 if (dst_devicep == NULL)
kono
parents:
diff changeset
2202 return EINVAL;
kono
parents:
diff changeset
2203
kono
parents:
diff changeset
2204 if (!(dst_devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
2205 || dst_devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
2206 dst_devicep = NULL;
kono
parents:
diff changeset
2207 }
kono
parents:
diff changeset
2208 if (src_device_num != GOMP_DEVICE_HOST_FALLBACK)
kono
parents:
diff changeset
2209 {
kono
parents:
diff changeset
2210 if (src_device_num < 0)
kono
parents:
diff changeset
2211 return EINVAL;
kono
parents:
diff changeset
2212
kono
parents:
diff changeset
2213 src_devicep = resolve_device (src_device_num);
kono
parents:
diff changeset
2214 if (src_devicep == NULL)
kono
parents:
diff changeset
2215 return EINVAL;
kono
parents:
diff changeset
2216
kono
parents:
diff changeset
2217 if (!(src_devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
2218 || src_devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
2219 src_devicep = NULL;
kono
parents:
diff changeset
2220 }
kono
parents:
diff changeset
2221
kono
parents:
diff changeset
2222 if (src_devicep != NULL && dst_devicep != NULL && src_devicep != dst_devicep)
kono
parents:
diff changeset
2223 return EINVAL;
kono
parents:
diff changeset
2224
kono
parents:
diff changeset
2225 if (src_devicep)
kono
parents:
diff changeset
2226 gomp_mutex_lock (&src_devicep->lock);
kono
parents:
diff changeset
2227 else if (dst_devicep)
kono
parents:
diff changeset
2228 gomp_mutex_lock (&dst_devicep->lock);
kono
parents:
diff changeset
2229 int ret = omp_target_memcpy_rect_worker (dst, src, element_size, num_dims,
kono
parents:
diff changeset
2230 volume, dst_offsets, src_offsets,
kono
parents:
diff changeset
2231 dst_dimensions, src_dimensions,
kono
parents:
diff changeset
2232 dst_devicep, src_devicep);
kono
parents:
diff changeset
2233 if (src_devicep)
kono
parents:
diff changeset
2234 gomp_mutex_unlock (&src_devicep->lock);
kono
parents:
diff changeset
2235 else if (dst_devicep)
kono
parents:
diff changeset
2236 gomp_mutex_unlock (&dst_devicep->lock);
kono
parents:
diff changeset
2237 return ret;
kono
parents:
diff changeset
2238 }
kono
parents:
diff changeset
2239
kono
parents:
diff changeset
2240 int
kono
parents:
diff changeset
2241 omp_target_associate_ptr (void *host_ptr, void *device_ptr, size_t size,
kono
parents:
diff changeset
2242 size_t device_offset, int device_num)
kono
parents:
diff changeset
2243 {
kono
parents:
diff changeset
2244 if (device_num == GOMP_DEVICE_HOST_FALLBACK)
kono
parents:
diff changeset
2245 return EINVAL;
kono
parents:
diff changeset
2246
kono
parents:
diff changeset
2247 if (device_num < 0)
kono
parents:
diff changeset
2248 return EINVAL;
kono
parents:
diff changeset
2249
kono
parents:
diff changeset
2250 struct gomp_device_descr *devicep = resolve_device (device_num);
kono
parents:
diff changeset
2251 if (devicep == NULL)
kono
parents:
diff changeset
2252 return EINVAL;
kono
parents:
diff changeset
2253
kono
parents:
diff changeset
2254 if (!(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
2255 || devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
kono
parents:
diff changeset
2256 return EINVAL;
kono
parents:
diff changeset
2257
kono
parents:
diff changeset
2258 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
2259
kono
parents:
diff changeset
2260 struct splay_tree_s *mem_map = &devicep->mem_map;
kono
parents:
diff changeset
2261 struct splay_tree_key_s cur_node;
kono
parents:
diff changeset
2262 int ret = EINVAL;
kono
parents:
diff changeset
2263
kono
parents:
diff changeset
2264 cur_node.host_start = (uintptr_t) host_ptr;
kono
parents:
diff changeset
2265 cur_node.host_end = cur_node.host_start + size;
kono
parents:
diff changeset
2266 splay_tree_key n = gomp_map_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
2267 if (n)
kono
parents:
diff changeset
2268 {
kono
parents:
diff changeset
2269 if (n->tgt->tgt_start + n->tgt_offset
kono
parents:
diff changeset
2270 == (uintptr_t) device_ptr + device_offset
kono
parents:
diff changeset
2271 && n->host_start <= cur_node.host_start
kono
parents:
diff changeset
2272 && n->host_end >= cur_node.host_end)
kono
parents:
diff changeset
2273 ret = 0;
kono
parents:
diff changeset
2274 }
kono
parents:
diff changeset
2275 else
kono
parents:
diff changeset
2276 {
kono
parents:
diff changeset
2277 struct target_mem_desc *tgt = gomp_malloc (sizeof (*tgt));
kono
parents:
diff changeset
2278 tgt->array = gomp_malloc (sizeof (*tgt->array));
kono
parents:
diff changeset
2279 tgt->refcount = 1;
kono
parents:
diff changeset
2280 tgt->tgt_start = 0;
kono
parents:
diff changeset
2281 tgt->tgt_end = 0;
kono
parents:
diff changeset
2282 tgt->to_free = NULL;
kono
parents:
diff changeset
2283 tgt->prev = NULL;
kono
parents:
diff changeset
2284 tgt->list_count = 0;
kono
parents:
diff changeset
2285 tgt->device_descr = devicep;
kono
parents:
diff changeset
2286 splay_tree_node array = tgt->array;
kono
parents:
diff changeset
2287 splay_tree_key k = &array->key;
kono
parents:
diff changeset
2288 k->host_start = cur_node.host_start;
kono
parents:
diff changeset
2289 k->host_end = cur_node.host_end;
kono
parents:
diff changeset
2290 k->tgt = tgt;
kono
parents:
diff changeset
2291 k->tgt_offset = (uintptr_t) device_ptr + device_offset;
kono
parents:
diff changeset
2292 k->refcount = REFCOUNT_INFINITY;
kono
parents:
diff changeset
2293 array->left = NULL;
kono
parents:
diff changeset
2294 array->right = NULL;
kono
parents:
diff changeset
2295 splay_tree_insert (&devicep->mem_map, array);
kono
parents:
diff changeset
2296 ret = 0;
kono
parents:
diff changeset
2297 }
kono
parents:
diff changeset
2298 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
2299 return ret;
kono
parents:
diff changeset
2300 }
kono
parents:
diff changeset
2301
kono
parents:
diff changeset
2302 int
kono
parents:
diff changeset
2303 omp_target_disassociate_ptr (void *ptr, int device_num)
kono
parents:
diff changeset
2304 {
kono
parents:
diff changeset
2305 if (device_num == GOMP_DEVICE_HOST_FALLBACK)
kono
parents:
diff changeset
2306 return EINVAL;
kono
parents:
diff changeset
2307
kono
parents:
diff changeset
2308 if (device_num < 0)
kono
parents:
diff changeset
2309 return EINVAL;
kono
parents:
diff changeset
2310
kono
parents:
diff changeset
2311 struct gomp_device_descr *devicep = resolve_device (device_num);
kono
parents:
diff changeset
2312 if (devicep == NULL)
kono
parents:
diff changeset
2313 return EINVAL;
kono
parents:
diff changeset
2314
kono
parents:
diff changeset
2315 if (!(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400))
kono
parents:
diff changeset
2316 return EINVAL;
kono
parents:
diff changeset
2317
kono
parents:
diff changeset
2318 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
2319
kono
parents:
diff changeset
2320 struct splay_tree_s *mem_map = &devicep->mem_map;
kono
parents:
diff changeset
2321 struct splay_tree_key_s cur_node;
kono
parents:
diff changeset
2322 int ret = EINVAL;
kono
parents:
diff changeset
2323
kono
parents:
diff changeset
2324 cur_node.host_start = (uintptr_t) ptr;
kono
parents:
diff changeset
2325 cur_node.host_end = cur_node.host_start;
kono
parents:
diff changeset
2326 splay_tree_key n = gomp_map_lookup (mem_map, &cur_node);
kono
parents:
diff changeset
2327 if (n
kono
parents:
diff changeset
2328 && n->host_start == cur_node.host_start
kono
parents:
diff changeset
2329 && n->refcount == REFCOUNT_INFINITY
kono
parents:
diff changeset
2330 && n->tgt->tgt_start == 0
kono
parents:
diff changeset
2331 && n->tgt->to_free == NULL
kono
parents:
diff changeset
2332 && n->tgt->refcount == 1
kono
parents:
diff changeset
2333 && n->tgt->list_count == 0)
kono
parents:
diff changeset
2334 {
kono
parents:
diff changeset
2335 splay_tree_remove (&devicep->mem_map, n);
kono
parents:
diff changeset
2336 gomp_unmap_tgt (n->tgt);
kono
parents:
diff changeset
2337 ret = 0;
kono
parents:
diff changeset
2338 }
kono
parents:
diff changeset
2339
kono
parents:
diff changeset
2340 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
2341 return ret;
kono
parents:
diff changeset
2342 }
kono
parents:
diff changeset
2343
kono
parents:
diff changeset
2344 #ifdef PLUGIN_SUPPORT
kono
parents:
diff changeset
2345
kono
parents:
diff changeset
2346 /* This function tries to load a plugin for DEVICE. Name of plugin is passed
kono
parents:
diff changeset
2347 in PLUGIN_NAME.
kono
parents:
diff changeset
2348 The handles of the found functions are stored in the corresponding fields
kono
parents:
diff changeset
2349 of DEVICE. The function returns TRUE on success and FALSE otherwise. */
kono
parents:
diff changeset
2350
kono
parents:
diff changeset
2351 static bool
kono
parents:
diff changeset
2352 gomp_load_plugin_for_device (struct gomp_device_descr *device,
kono
parents:
diff changeset
2353 const char *plugin_name)
kono
parents:
diff changeset
2354 {
kono
parents:
diff changeset
2355 const char *err = NULL, *last_missing = NULL;
kono
parents:
diff changeset
2356
kono
parents:
diff changeset
2357 void *plugin_handle = dlopen (plugin_name, RTLD_LAZY);
kono
parents:
diff changeset
2358 if (!plugin_handle)
kono
parents:
diff changeset
2359 goto dl_fail;
kono
parents:
diff changeset
2360
kono
parents:
diff changeset
2361 /* Check if all required functions are available in the plugin and store
kono
parents:
diff changeset
2362 their handlers. None of the symbols can legitimately be NULL,
kono
parents:
diff changeset
2363 so we don't need to check dlerror all the time. */
kono
parents:
diff changeset
2364 #define DLSYM(f) \
kono
parents:
diff changeset
2365 if (!(device->f##_func = dlsym (plugin_handle, "GOMP_OFFLOAD_" #f))) \
kono
parents:
diff changeset
2366 goto dl_fail
kono
parents:
diff changeset
2367 /* Similar, but missing functions are not an error. Return false if
kono
parents:
diff changeset
2368 failed, true otherwise. */
kono
parents:
diff changeset
2369 #define DLSYM_OPT(f, n) \
kono
parents:
diff changeset
2370 ((device->f##_func = dlsym (plugin_handle, "GOMP_OFFLOAD_" #n)) \
kono
parents:
diff changeset
2371 || (last_missing = #n, 0))
kono
parents:
diff changeset
2372
kono
parents:
diff changeset
2373 DLSYM (version);
kono
parents:
diff changeset
2374 if (device->version_func () != GOMP_VERSION)
kono
parents:
diff changeset
2375 {
kono
parents:
diff changeset
2376 err = "plugin version mismatch";
kono
parents:
diff changeset
2377 goto fail;
kono
parents:
diff changeset
2378 }
kono
parents:
diff changeset
2379
kono
parents:
diff changeset
2380 DLSYM (get_name);
kono
parents:
diff changeset
2381 DLSYM (get_caps);
kono
parents:
diff changeset
2382 DLSYM (get_type);
kono
parents:
diff changeset
2383 DLSYM (get_num_devices);
kono
parents:
diff changeset
2384 DLSYM (init_device);
kono
parents:
diff changeset
2385 DLSYM (fini_device);
kono
parents:
diff changeset
2386 DLSYM (load_image);
kono
parents:
diff changeset
2387 DLSYM (unload_image);
kono
parents:
diff changeset
2388 DLSYM (alloc);
kono
parents:
diff changeset
2389 DLSYM (free);
kono
parents:
diff changeset
2390 DLSYM (dev2host);
kono
parents:
diff changeset
2391 DLSYM (host2dev);
kono
parents:
diff changeset
2392 device->capabilities = device->get_caps_func ();
kono
parents:
diff changeset
2393 if (device->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
2394 {
kono
parents:
diff changeset
2395 DLSYM (run);
kono
parents:
diff changeset
2396 DLSYM (async_run);
kono
parents:
diff changeset
2397 DLSYM_OPT (can_run, can_run);
kono
parents:
diff changeset
2398 DLSYM (dev2dev);
kono
parents:
diff changeset
2399 }
kono
parents:
diff changeset
2400 if (device->capabilities & GOMP_OFFLOAD_CAP_OPENACC_200)
kono
parents:
diff changeset
2401 {
kono
parents:
diff changeset
2402 if (!DLSYM_OPT (openacc.exec, openacc_exec)
kono
parents:
diff changeset
2403 || !DLSYM_OPT (openacc.register_async_cleanup,
kono
parents:
diff changeset
2404 openacc_register_async_cleanup)
kono
parents:
diff changeset
2405 || !DLSYM_OPT (openacc.async_test, openacc_async_test)
kono
parents:
diff changeset
2406 || !DLSYM_OPT (openacc.async_test_all, openacc_async_test_all)
kono
parents:
diff changeset
2407 || !DLSYM_OPT (openacc.async_wait, openacc_async_wait)
kono
parents:
diff changeset
2408 || !DLSYM_OPT (openacc.async_wait_async, openacc_async_wait_async)
kono
parents:
diff changeset
2409 || !DLSYM_OPT (openacc.async_wait_all, openacc_async_wait_all)
kono
parents:
diff changeset
2410 || !DLSYM_OPT (openacc.async_wait_all_async,
kono
parents:
diff changeset
2411 openacc_async_wait_all_async)
kono
parents:
diff changeset
2412 || !DLSYM_OPT (openacc.async_set_async, openacc_async_set_async)
kono
parents:
diff changeset
2413 || !DLSYM_OPT (openacc.create_thread_data,
kono
parents:
diff changeset
2414 openacc_create_thread_data)
kono
parents:
diff changeset
2415 || !DLSYM_OPT (openacc.destroy_thread_data,
kono
parents:
diff changeset
2416 openacc_destroy_thread_data))
kono
parents:
diff changeset
2417 {
kono
parents:
diff changeset
2418 /* Require all the OpenACC handlers if we have
kono
parents:
diff changeset
2419 GOMP_OFFLOAD_CAP_OPENACC_200. */
kono
parents:
diff changeset
2420 err = "plugin missing OpenACC handler function";
kono
parents:
diff changeset
2421 goto fail;
kono
parents:
diff changeset
2422 }
kono
parents:
diff changeset
2423
kono
parents:
diff changeset
2424 unsigned cuda = 0;
kono
parents:
diff changeset
2425 cuda += DLSYM_OPT (openacc.cuda.get_current_device,
kono
parents:
diff changeset
2426 openacc_cuda_get_current_device);
kono
parents:
diff changeset
2427 cuda += DLSYM_OPT (openacc.cuda.get_current_context,
kono
parents:
diff changeset
2428 openacc_cuda_get_current_context);
kono
parents:
diff changeset
2429 cuda += DLSYM_OPT (openacc.cuda.get_stream, openacc_cuda_get_stream);
kono
parents:
diff changeset
2430 cuda += DLSYM_OPT (openacc.cuda.set_stream, openacc_cuda_set_stream);
kono
parents:
diff changeset
2431 if (cuda && cuda != 4)
kono
parents:
diff changeset
2432 {
kono
parents:
diff changeset
2433 /* Make sure all the CUDA functions are there if any of them are. */
kono
parents:
diff changeset
2434 err = "plugin missing OpenACC CUDA handler function";
kono
parents:
diff changeset
2435 goto fail;
kono
parents:
diff changeset
2436 }
kono
parents:
diff changeset
2437 }
kono
parents:
diff changeset
2438 #undef DLSYM
kono
parents:
diff changeset
2439 #undef DLSYM_OPT
kono
parents:
diff changeset
2440
kono
parents:
diff changeset
2441 return 1;
kono
parents:
diff changeset
2442
kono
parents:
diff changeset
2443 dl_fail:
kono
parents:
diff changeset
2444 err = dlerror ();
kono
parents:
diff changeset
2445 fail:
kono
parents:
diff changeset
2446 gomp_error ("while loading %s: %s", plugin_name, err);
kono
parents:
diff changeset
2447 if (last_missing)
kono
parents:
diff changeset
2448 gomp_error ("missing function was %s", last_missing);
kono
parents:
diff changeset
2449 if (plugin_handle)
kono
parents:
diff changeset
2450 dlclose (plugin_handle);
kono
parents:
diff changeset
2451
kono
parents:
diff changeset
2452 return 0;
kono
parents:
diff changeset
2453 }
kono
parents:
diff changeset
2454
kono
parents:
diff changeset
2455 /* This function finalizes all initialized devices. */
kono
parents:
diff changeset
2456
kono
parents:
diff changeset
2457 static void
kono
parents:
diff changeset
2458 gomp_target_fini (void)
kono
parents:
diff changeset
2459 {
kono
parents:
diff changeset
2460 int i;
kono
parents:
diff changeset
2461 for (i = 0; i < num_devices; i++)
kono
parents:
diff changeset
2462 {
kono
parents:
diff changeset
2463 bool ret = true;
kono
parents:
diff changeset
2464 struct gomp_device_descr *devicep = &devices[i];
kono
parents:
diff changeset
2465 gomp_mutex_lock (&devicep->lock);
kono
parents:
diff changeset
2466 if (devicep->state == GOMP_DEVICE_INITIALIZED)
kono
parents:
diff changeset
2467 {
kono
parents:
diff changeset
2468 ret = devicep->fini_device_func (devicep->target_id);
kono
parents:
diff changeset
2469 devicep->state = GOMP_DEVICE_FINALIZED;
kono
parents:
diff changeset
2470 }
kono
parents:
diff changeset
2471 gomp_mutex_unlock (&devicep->lock);
kono
parents:
diff changeset
2472 if (!ret)
kono
parents:
diff changeset
2473 gomp_fatal ("device finalization failed");
kono
parents:
diff changeset
2474 }
kono
parents:
diff changeset
2475 }
kono
parents:
diff changeset
2476
kono
parents:
diff changeset
2477 /* This function initializes the runtime needed for offloading.
kono
parents:
diff changeset
2478 It parses the list of offload targets and tries to load the plugins for
kono
parents:
diff changeset
2479 these targets. On return, the variables NUM_DEVICES and NUM_DEVICES_OPENMP
kono
parents:
diff changeset
2480 will be set, and the array DEVICES initialized, containing descriptors for
kono
parents:
diff changeset
2481 corresponding devices, first the GOMP_OFFLOAD_CAP_OPENMP_400 ones, follows
kono
parents:
diff changeset
2482 by the others. */
kono
parents:
diff changeset
2483
kono
parents:
diff changeset
2484 static void
kono
parents:
diff changeset
2485 gomp_target_init (void)
kono
parents:
diff changeset
2486 {
kono
parents:
diff changeset
2487 const char *prefix ="libgomp-plugin-";
kono
parents:
diff changeset
2488 const char *suffix = SONAME_SUFFIX (1);
kono
parents:
diff changeset
2489 const char *cur, *next;
kono
parents:
diff changeset
2490 char *plugin_name;
kono
parents:
diff changeset
2491 int i, new_num_devices;
kono
parents:
diff changeset
2492
kono
parents:
diff changeset
2493 num_devices = 0;
kono
parents:
diff changeset
2494 devices = NULL;
kono
parents:
diff changeset
2495
kono
parents:
diff changeset
2496 cur = OFFLOAD_TARGETS;
kono
parents:
diff changeset
2497 if (*cur)
kono
parents:
diff changeset
2498 do
kono
parents:
diff changeset
2499 {
kono
parents:
diff changeset
2500 struct gomp_device_descr current_device;
kono
parents:
diff changeset
2501
kono
parents:
diff changeset
2502 next = strchr (cur, ',');
kono
parents:
diff changeset
2503
kono
parents:
diff changeset
2504 plugin_name = (char *) malloc (1 + (next ? next - cur : strlen (cur))
kono
parents:
diff changeset
2505 + strlen (prefix) + strlen (suffix));
kono
parents:
diff changeset
2506 if (!plugin_name)
kono
parents:
diff changeset
2507 {
kono
parents:
diff changeset
2508 num_devices = 0;
kono
parents:
diff changeset
2509 break;
kono
parents:
diff changeset
2510 }
kono
parents:
diff changeset
2511
kono
parents:
diff changeset
2512 strcpy (plugin_name, prefix);
kono
parents:
diff changeset
2513 strncat (plugin_name, cur, next ? next - cur : strlen (cur));
kono
parents:
diff changeset
2514 strcat (plugin_name, suffix);
kono
parents:
diff changeset
2515
kono
parents:
diff changeset
2516 if (gomp_load_plugin_for_device (&current_device, plugin_name))
kono
parents:
diff changeset
2517 {
kono
parents:
diff changeset
2518 new_num_devices = current_device.get_num_devices_func ();
kono
parents:
diff changeset
2519 if (new_num_devices >= 1)
kono
parents:
diff changeset
2520 {
kono
parents:
diff changeset
2521 /* Augment DEVICES and NUM_DEVICES. */
kono
parents:
diff changeset
2522
kono
parents:
diff changeset
2523 devices = realloc (devices, (num_devices + new_num_devices)
kono
parents:
diff changeset
2524 * sizeof (struct gomp_device_descr));
kono
parents:
diff changeset
2525 if (!devices)
kono
parents:
diff changeset
2526 {
kono
parents:
diff changeset
2527 num_devices = 0;
kono
parents:
diff changeset
2528 free (plugin_name);
kono
parents:
diff changeset
2529 break;
kono
parents:
diff changeset
2530 }
kono
parents:
diff changeset
2531
kono
parents:
diff changeset
2532 current_device.name = current_device.get_name_func ();
kono
parents:
diff changeset
2533 /* current_device.capabilities has already been set. */
kono
parents:
diff changeset
2534 current_device.type = current_device.get_type_func ();
kono
parents:
diff changeset
2535 current_device.mem_map.root = NULL;
kono
parents:
diff changeset
2536 current_device.state = GOMP_DEVICE_UNINITIALIZED;
kono
parents:
diff changeset
2537 current_device.openacc.data_environ = NULL;
kono
parents:
diff changeset
2538 for (i = 0; i < new_num_devices; i++)
kono
parents:
diff changeset
2539 {
kono
parents:
diff changeset
2540 current_device.target_id = i;
kono
parents:
diff changeset
2541 devices[num_devices] = current_device;
kono
parents:
diff changeset
2542 gomp_mutex_init (&devices[num_devices].lock);
kono
parents:
diff changeset
2543 num_devices++;
kono
parents:
diff changeset
2544 }
kono
parents:
diff changeset
2545 }
kono
parents:
diff changeset
2546 }
kono
parents:
diff changeset
2547
kono
parents:
diff changeset
2548 free (plugin_name);
kono
parents:
diff changeset
2549 cur = next + 1;
kono
parents:
diff changeset
2550 }
kono
parents:
diff changeset
2551 while (next);
kono
parents:
diff changeset
2552
kono
parents:
diff changeset
2553 /* In DEVICES, sort the GOMP_OFFLOAD_CAP_OPENMP_400 ones first, and set
kono
parents:
diff changeset
2554 NUM_DEVICES_OPENMP. */
kono
parents:
diff changeset
2555 struct gomp_device_descr *devices_s
kono
parents:
diff changeset
2556 = malloc (num_devices * sizeof (struct gomp_device_descr));
kono
parents:
diff changeset
2557 if (!devices_s)
kono
parents:
diff changeset
2558 {
kono
parents:
diff changeset
2559 num_devices = 0;
kono
parents:
diff changeset
2560 free (devices);
kono
parents:
diff changeset
2561 devices = NULL;
kono
parents:
diff changeset
2562 }
kono
parents:
diff changeset
2563 num_devices_openmp = 0;
kono
parents:
diff changeset
2564 for (i = 0; i < num_devices; i++)
kono
parents:
diff changeset
2565 if (devices[i].capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
kono
parents:
diff changeset
2566 devices_s[num_devices_openmp++] = devices[i];
kono
parents:
diff changeset
2567 int num_devices_after_openmp = num_devices_openmp;
kono
parents:
diff changeset
2568 for (i = 0; i < num_devices; i++)
kono
parents:
diff changeset
2569 if (!(devices[i].capabilities & GOMP_OFFLOAD_CAP_OPENMP_400))
kono
parents:
diff changeset
2570 devices_s[num_devices_after_openmp++] = devices[i];
kono
parents:
diff changeset
2571 free (devices);
kono
parents:
diff changeset
2572 devices = devices_s;
kono
parents:
diff changeset
2573
kono
parents:
diff changeset
2574 for (i = 0; i < num_devices; i++)
kono
parents:
diff changeset
2575 {
kono
parents:
diff changeset
2576 /* The 'devices' array can be moved (by the realloc call) until we have
kono
parents:
diff changeset
2577 found all the plugins, so registering with the OpenACC runtime (which
kono
parents:
diff changeset
2578 takes a copy of the pointer argument) must be delayed until now. */
kono
parents:
diff changeset
2579 if (devices[i].capabilities & GOMP_OFFLOAD_CAP_OPENACC_200)
kono
parents:
diff changeset
2580 goacc_register (&devices[i]);
kono
parents:
diff changeset
2581 }
kono
parents:
diff changeset
2582
kono
parents:
diff changeset
2583 if (atexit (gomp_target_fini) != 0)
kono
parents:
diff changeset
2584 gomp_fatal ("atexit failed");
kono
parents:
diff changeset
2585 }
kono
parents:
diff changeset
2586
kono
parents:
diff changeset
2587 #else /* PLUGIN_SUPPORT */
kono
parents:
diff changeset
2588 /* If dlfcn.h is unavailable we always fallback to host execution.
kono
parents:
diff changeset
2589 GOMP_target* routines are just stubs for this case. */
kono
parents:
diff changeset
2590 static void
kono
parents:
diff changeset
2591 gomp_target_init (void)
kono
parents:
diff changeset
2592 {
kono
parents:
diff changeset
2593 }
kono
parents:
diff changeset
2594 #endif /* PLUGIN_SUPPORT */