11debfc3dSmrg /* OpenACC Runtime Library Definitions.
21debfc3dSmrg
3*8feb0f0bSmrg Copyright (C) 2013-2020 Free Software Foundation, Inc.
41debfc3dSmrg
51debfc3dSmrg Contributed by Mentor Embedded.
61debfc3dSmrg
71debfc3dSmrg This file is part of the GNU Offloading and Multi Processing Library
81debfc3dSmrg (libgomp).
91debfc3dSmrg
101debfc3dSmrg Libgomp is free software; you can redistribute it and/or modify it
111debfc3dSmrg under the terms of the GNU General Public License as published by
121debfc3dSmrg the Free Software Foundation; either version 3, or (at your option)
131debfc3dSmrg any later version.
141debfc3dSmrg
151debfc3dSmrg Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
161debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
171debfc3dSmrg FOR A PARTICULAR PURPOSE. See the GNU General Public License for
181debfc3dSmrg more details.
191debfc3dSmrg
201debfc3dSmrg Under Section 7 of GPL version 3, you are granted additional
211debfc3dSmrg permissions described in the GCC Runtime Library Exception, version
221debfc3dSmrg 3.1, as published by the Free Software Foundation.
231debfc3dSmrg
241debfc3dSmrg You should have received a copy of the GNU General Public License and
251debfc3dSmrg a copy of the GCC Runtime Library Exception along with this program;
261debfc3dSmrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
271debfc3dSmrg <http://www.gnu.org/licenses/>. */
281debfc3dSmrg
291debfc3dSmrg #include <assert.h>
30*8feb0f0bSmrg #include <string.h>
311debfc3dSmrg #include "openacc.h"
321debfc3dSmrg #include "libgomp.h"
331debfc3dSmrg #include "oacc-int.h"
341debfc3dSmrg
35*8feb0f0bSmrg static struct goacc_thread *
get_goacc_thread(void)36*8feb0f0bSmrg get_goacc_thread (void)
371debfc3dSmrg {
381debfc3dSmrg struct goacc_thread *thr = goacc_thread ();
391debfc3dSmrg
401debfc3dSmrg if (!thr || !thr->dev)
411debfc3dSmrg gomp_fatal ("no device active");
421debfc3dSmrg
43*8feb0f0bSmrg return thr;
44*8feb0f0bSmrg }
45*8feb0f0bSmrg
46*8feb0f0bSmrg static int
validate_async_val(int async)47*8feb0f0bSmrg validate_async_val (int async)
48*8feb0f0bSmrg {
49*8feb0f0bSmrg if (!async_valid_p (async))
50*8feb0f0bSmrg gomp_fatal ("invalid async-argument: %d", async);
51*8feb0f0bSmrg
52*8feb0f0bSmrg if (async == acc_async_sync)
53*8feb0f0bSmrg return -1;
54*8feb0f0bSmrg
55*8feb0f0bSmrg if (async == acc_async_noval)
56*8feb0f0bSmrg return 0;
57*8feb0f0bSmrg
58*8feb0f0bSmrg if (async >= 0)
59*8feb0f0bSmrg /* TODO: we reserve 0 for acc_async_noval before we can clarify the
60*8feb0f0bSmrg semantics of "default_async". */
61*8feb0f0bSmrg return 1 + async;
62*8feb0f0bSmrg else
63*8feb0f0bSmrg __builtin_unreachable ();
64*8feb0f0bSmrg }
65*8feb0f0bSmrg
66*8feb0f0bSmrg /* Return the asyncqueue to be used for OpenACC async-argument ASYNC. This
67*8feb0f0bSmrg might return NULL if no asyncqueue is to be used. Otherwise, if CREATE,
68*8feb0f0bSmrg create the asyncqueue if it doesn't exist yet.
69*8feb0f0bSmrg
70*8feb0f0bSmrg Unless CREATE, this will not generate any OpenACC Profiling Interface
71*8feb0f0bSmrg events. */
72*8feb0f0bSmrg
73*8feb0f0bSmrg attribute_hidden struct goacc_asyncqueue *
lookup_goacc_asyncqueue(struct goacc_thread * thr,bool create,int async)74*8feb0f0bSmrg lookup_goacc_asyncqueue (struct goacc_thread *thr, bool create, int async)
75*8feb0f0bSmrg {
76*8feb0f0bSmrg async = validate_async_val (async);
77*8feb0f0bSmrg if (async < 0)
78*8feb0f0bSmrg return NULL;
79*8feb0f0bSmrg
80*8feb0f0bSmrg struct goacc_asyncqueue *ret_aq = NULL;
81*8feb0f0bSmrg struct gomp_device_descr *dev = thr->dev;
82*8feb0f0bSmrg
83*8feb0f0bSmrg gomp_mutex_lock (&dev->openacc.async.lock);
84*8feb0f0bSmrg
85*8feb0f0bSmrg if (!create
86*8feb0f0bSmrg && (async >= dev->openacc.async.nasyncqueue
87*8feb0f0bSmrg || !dev->openacc.async.asyncqueue[async]))
88*8feb0f0bSmrg goto end;
89*8feb0f0bSmrg
90*8feb0f0bSmrg if (async >= dev->openacc.async.nasyncqueue)
91*8feb0f0bSmrg {
92*8feb0f0bSmrg int diff = async + 1 - dev->openacc.async.nasyncqueue;
93*8feb0f0bSmrg dev->openacc.async.asyncqueue
94*8feb0f0bSmrg = gomp_realloc (dev->openacc.async.asyncqueue,
95*8feb0f0bSmrg sizeof (goacc_aq) * (async + 1));
96*8feb0f0bSmrg memset (dev->openacc.async.asyncqueue + dev->openacc.async.nasyncqueue,
97*8feb0f0bSmrg 0, sizeof (goacc_aq) * diff);
98*8feb0f0bSmrg dev->openacc.async.nasyncqueue = async + 1;
99*8feb0f0bSmrg }
100*8feb0f0bSmrg
101*8feb0f0bSmrg if (!dev->openacc.async.asyncqueue[async])
102*8feb0f0bSmrg {
103*8feb0f0bSmrg dev->openacc.async.asyncqueue[async]
104*8feb0f0bSmrg = dev->openacc.async.construct_func (dev->target_id);
105*8feb0f0bSmrg
106*8feb0f0bSmrg if (!dev->openacc.async.asyncqueue[async])
107*8feb0f0bSmrg {
108*8feb0f0bSmrg gomp_mutex_unlock (&dev->openacc.async.lock);
109*8feb0f0bSmrg gomp_fatal ("async %d creation failed", async);
110*8feb0f0bSmrg }
111*8feb0f0bSmrg
112*8feb0f0bSmrg /* Link new async queue into active list. */
113*8feb0f0bSmrg goacc_aq_list n = gomp_malloc (sizeof (struct goacc_asyncqueue_list));
114*8feb0f0bSmrg n->aq = dev->openacc.async.asyncqueue[async];
115*8feb0f0bSmrg n->next = dev->openacc.async.active;
116*8feb0f0bSmrg dev->openacc.async.active = n;
117*8feb0f0bSmrg }
118*8feb0f0bSmrg
119*8feb0f0bSmrg ret_aq = dev->openacc.async.asyncqueue[async];
120*8feb0f0bSmrg
121*8feb0f0bSmrg end:
122*8feb0f0bSmrg gomp_mutex_unlock (&dev->openacc.async.lock);
123*8feb0f0bSmrg return ret_aq;
124*8feb0f0bSmrg }
125*8feb0f0bSmrg
126*8feb0f0bSmrg /* Return the asyncqueue to be used for OpenACC async-argument ASYNC. This
127*8feb0f0bSmrg might return NULL if no asyncqueue is to be used. Otherwise, create the
128*8feb0f0bSmrg asyncqueue if it doesn't exist yet. */
129*8feb0f0bSmrg
130*8feb0f0bSmrg attribute_hidden struct goacc_asyncqueue *
get_goacc_asyncqueue(int async)131*8feb0f0bSmrg get_goacc_asyncqueue (int async)
132*8feb0f0bSmrg {
133*8feb0f0bSmrg struct goacc_thread *thr = get_goacc_thread ();
134*8feb0f0bSmrg return lookup_goacc_asyncqueue (thr, true, async);
135*8feb0f0bSmrg }
136*8feb0f0bSmrg
137*8feb0f0bSmrg int
acc_async_test(int async)138*8feb0f0bSmrg acc_async_test (int async)
139*8feb0f0bSmrg {
140*8feb0f0bSmrg struct goacc_thread *thr = goacc_thread ();
141*8feb0f0bSmrg
142*8feb0f0bSmrg if (!thr || !thr->dev)
143*8feb0f0bSmrg gomp_fatal ("no device active");
144*8feb0f0bSmrg
145*8feb0f0bSmrg goacc_aq aq = lookup_goacc_asyncqueue (thr, false, async);
146*8feb0f0bSmrg if (!aq)
147*8feb0f0bSmrg return 1;
148*8feb0f0bSmrg
149*8feb0f0bSmrg acc_prof_info prof_info;
150*8feb0f0bSmrg acc_api_info api_info;
151*8feb0f0bSmrg bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
152*8feb0f0bSmrg if (profiling_p)
153*8feb0f0bSmrg {
154*8feb0f0bSmrg prof_info.async = async;
155*8feb0f0bSmrg prof_info.async_queue = prof_info.async;
156*8feb0f0bSmrg }
157*8feb0f0bSmrg
158*8feb0f0bSmrg int res = thr->dev->openacc.async.test_func (aq);
159*8feb0f0bSmrg
160*8feb0f0bSmrg if (profiling_p)
161*8feb0f0bSmrg {
162*8feb0f0bSmrg thr->prof_info = NULL;
163*8feb0f0bSmrg thr->api_info = NULL;
164*8feb0f0bSmrg }
165*8feb0f0bSmrg
166*8feb0f0bSmrg return res;
1671debfc3dSmrg }
1681debfc3dSmrg
1691debfc3dSmrg int
acc_async_test_all(void)1701debfc3dSmrg acc_async_test_all (void)
1711debfc3dSmrg {
172*8feb0f0bSmrg struct goacc_thread *thr = get_goacc_thread ();
1731debfc3dSmrg
174*8feb0f0bSmrg acc_prof_info prof_info;
175*8feb0f0bSmrg acc_api_info api_info;
176*8feb0f0bSmrg bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
1771debfc3dSmrg
178*8feb0f0bSmrg int ret = 1;
179*8feb0f0bSmrg gomp_mutex_lock (&thr->dev->openacc.async.lock);
180*8feb0f0bSmrg for (goacc_aq_list l = thr->dev->openacc.async.active; l; l = l->next)
181*8feb0f0bSmrg if (!thr->dev->openacc.async.test_func (l->aq))
182*8feb0f0bSmrg {
183*8feb0f0bSmrg ret = 0;
184*8feb0f0bSmrg break;
185*8feb0f0bSmrg }
186*8feb0f0bSmrg gomp_mutex_unlock (&thr->dev->openacc.async.lock);
187*8feb0f0bSmrg
188*8feb0f0bSmrg if (profiling_p)
189*8feb0f0bSmrg {
190*8feb0f0bSmrg thr->prof_info = NULL;
191*8feb0f0bSmrg thr->api_info = NULL;
192*8feb0f0bSmrg }
193*8feb0f0bSmrg
194*8feb0f0bSmrg return ret;
1951debfc3dSmrg }
1961debfc3dSmrg
1971debfc3dSmrg void
acc_wait(int async)1981debfc3dSmrg acc_wait (int async)
1991debfc3dSmrg {
200*8feb0f0bSmrg struct goacc_thread *thr = get_goacc_thread ();
2011debfc3dSmrg
202*8feb0f0bSmrg goacc_aq aq = lookup_goacc_asyncqueue (thr, false, async);
203*8feb0f0bSmrg if (!aq)
204*8feb0f0bSmrg return;
2051debfc3dSmrg
206*8feb0f0bSmrg acc_prof_info prof_info;
207*8feb0f0bSmrg acc_api_info api_info;
208*8feb0f0bSmrg bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
209*8feb0f0bSmrg if (profiling_p)
210*8feb0f0bSmrg {
211*8feb0f0bSmrg prof_info.async = async;
212*8feb0f0bSmrg prof_info.async_queue = prof_info.async;
213*8feb0f0bSmrg }
2141debfc3dSmrg
215*8feb0f0bSmrg if (!thr->dev->openacc.async.synchronize_func (aq))
216*8feb0f0bSmrg gomp_fatal ("wait on %d failed", async);
217*8feb0f0bSmrg
218*8feb0f0bSmrg if (profiling_p)
219*8feb0f0bSmrg {
220*8feb0f0bSmrg thr->prof_info = NULL;
221*8feb0f0bSmrg thr->api_info = NULL;
222*8feb0f0bSmrg }
2231debfc3dSmrg }
2241debfc3dSmrg
225a2dc1f3fSmrg /* acc_async_wait is an OpenACC 1.0 compatibility name for acc_wait. */
226a2dc1f3fSmrg #ifdef HAVE_ATTRIBUTE_ALIAS
strong_alias(acc_wait,acc_async_wait)227a2dc1f3fSmrg strong_alias (acc_wait, acc_async_wait)
228a2dc1f3fSmrg #else
229a2dc1f3fSmrg void
230a2dc1f3fSmrg acc_async_wait (int async)
231a2dc1f3fSmrg {
232a2dc1f3fSmrg acc_wait (async);
233a2dc1f3fSmrg }
234a2dc1f3fSmrg #endif
235a2dc1f3fSmrg
2361debfc3dSmrg void
2371debfc3dSmrg acc_wait_async (int async1, int async2)
2381debfc3dSmrg {
239*8feb0f0bSmrg struct goacc_thread *thr = get_goacc_thread ();
2401debfc3dSmrg
241*8feb0f0bSmrg goacc_aq aq1 = lookup_goacc_asyncqueue (thr, false, async1);
242*8feb0f0bSmrg /* TODO: Is this also correct for acc_async_sync, assuming that in this case,
243*8feb0f0bSmrg we'll always be synchronous anyways? */
244*8feb0f0bSmrg if (!aq1)
245*8feb0f0bSmrg return;
2461debfc3dSmrg
247*8feb0f0bSmrg acc_prof_info prof_info;
248*8feb0f0bSmrg acc_api_info api_info;
249*8feb0f0bSmrg bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
250*8feb0f0bSmrg if (profiling_p)
251*8feb0f0bSmrg {
252*8feb0f0bSmrg prof_info.async = async2;
253*8feb0f0bSmrg prof_info.async_queue = prof_info.async;
254*8feb0f0bSmrg }
255*8feb0f0bSmrg
256*8feb0f0bSmrg goacc_aq aq2 = lookup_goacc_asyncqueue (thr, true, async2);
257*8feb0f0bSmrg /* An async queue is always synchronized with itself. */
258*8feb0f0bSmrg if (aq1 == aq2)
259*8feb0f0bSmrg goto out_prof;
260*8feb0f0bSmrg
261*8feb0f0bSmrg if (aq2)
262*8feb0f0bSmrg {
263*8feb0f0bSmrg if (!thr->dev->openacc.async.serialize_func (aq1, aq2))
264*8feb0f0bSmrg gomp_fatal ("ordering of async ids %d and %d failed", async1, async2);
265*8feb0f0bSmrg }
266*8feb0f0bSmrg else
267*8feb0f0bSmrg {
268*8feb0f0bSmrg /* TODO: Local thread synchronization.
269*8feb0f0bSmrg Necessary for the "async2 == acc_async_sync" case, or can just skip? */
270*8feb0f0bSmrg if (!thr->dev->openacc.async.synchronize_func (aq1))
271*8feb0f0bSmrg gomp_fatal ("wait on %d failed", async1);
272*8feb0f0bSmrg }
273*8feb0f0bSmrg
274*8feb0f0bSmrg out_prof:
275*8feb0f0bSmrg if (profiling_p)
276*8feb0f0bSmrg {
277*8feb0f0bSmrg thr->prof_info = NULL;
278*8feb0f0bSmrg thr->api_info = NULL;
279*8feb0f0bSmrg }
2801debfc3dSmrg }
2811debfc3dSmrg
2821debfc3dSmrg void
acc_wait_all(void)2831debfc3dSmrg acc_wait_all (void)
2841debfc3dSmrg {
2851debfc3dSmrg struct goacc_thread *thr = goacc_thread ();
2861debfc3dSmrg
287*8feb0f0bSmrg acc_prof_info prof_info;
288*8feb0f0bSmrg acc_api_info api_info;
289*8feb0f0bSmrg bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
2901debfc3dSmrg
291*8feb0f0bSmrg bool ret = true;
292*8feb0f0bSmrg gomp_mutex_lock (&thr->dev->openacc.async.lock);
293*8feb0f0bSmrg for (goacc_aq_list l = thr->dev->openacc.async.active; l; l = l->next)
294*8feb0f0bSmrg ret &= thr->dev->openacc.async.synchronize_func (l->aq);
295*8feb0f0bSmrg gomp_mutex_unlock (&thr->dev->openacc.async.lock);
296*8feb0f0bSmrg
297*8feb0f0bSmrg if (profiling_p)
298*8feb0f0bSmrg {
299*8feb0f0bSmrg thr->prof_info = NULL;
300*8feb0f0bSmrg thr->api_info = NULL;
301*8feb0f0bSmrg }
302*8feb0f0bSmrg
303*8feb0f0bSmrg if (!ret)
304*8feb0f0bSmrg gomp_fatal ("wait all failed");
3051debfc3dSmrg }
3061debfc3dSmrg
307a2dc1f3fSmrg /* acc_async_wait_all is an OpenACC 1.0 compatibility name for acc_wait_all. */
308a2dc1f3fSmrg #ifdef HAVE_ATTRIBUTE_ALIAS
strong_alias(acc_wait_all,acc_async_wait_all)309a2dc1f3fSmrg strong_alias (acc_wait_all, acc_async_wait_all)
310a2dc1f3fSmrg #else
311a2dc1f3fSmrg void
312a2dc1f3fSmrg acc_async_wait_all (void)
313a2dc1f3fSmrg {
314a2dc1f3fSmrg acc_wait_all ();
315a2dc1f3fSmrg }
316a2dc1f3fSmrg #endif
317a2dc1f3fSmrg
3181debfc3dSmrg void
3191debfc3dSmrg acc_wait_all_async (int async)
3201debfc3dSmrg {
321*8feb0f0bSmrg struct goacc_thread *thr = get_goacc_thread ();
322*8feb0f0bSmrg
323*8feb0f0bSmrg acc_prof_info prof_info;
324*8feb0f0bSmrg acc_api_info api_info;
325*8feb0f0bSmrg bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
326*8feb0f0bSmrg if (profiling_p)
327*8feb0f0bSmrg {
328*8feb0f0bSmrg prof_info.async = async;
329*8feb0f0bSmrg prof_info.async_queue = prof_info.async;
330*8feb0f0bSmrg }
331*8feb0f0bSmrg
332*8feb0f0bSmrg goacc_aq waiting_queue = lookup_goacc_asyncqueue (thr, true, async);
333*8feb0f0bSmrg
334*8feb0f0bSmrg bool ret = true;
335*8feb0f0bSmrg gomp_mutex_lock (&thr->dev->openacc.async.lock);
336*8feb0f0bSmrg for (goacc_aq_list l = thr->dev->openacc.async.active; l; l = l->next)
337*8feb0f0bSmrg {
338*8feb0f0bSmrg if (waiting_queue)
339*8feb0f0bSmrg ret &= thr->dev->openacc.async.serialize_func (l->aq, waiting_queue);
340*8feb0f0bSmrg else
341*8feb0f0bSmrg /* TODO: Local thread synchronization.
342*8feb0f0bSmrg Necessary for the "async2 == acc_async_sync" case, or can just skip? */
343*8feb0f0bSmrg ret &= thr->dev->openacc.async.synchronize_func (l->aq);
344*8feb0f0bSmrg }
345*8feb0f0bSmrg gomp_mutex_unlock (&thr->dev->openacc.async.lock);
346*8feb0f0bSmrg
347*8feb0f0bSmrg if (profiling_p)
348*8feb0f0bSmrg {
349*8feb0f0bSmrg thr->prof_info = NULL;
350*8feb0f0bSmrg thr->api_info = NULL;
351*8feb0f0bSmrg }
352*8feb0f0bSmrg
353*8feb0f0bSmrg if (!ret)
354*8feb0f0bSmrg gomp_fatal ("wait all async(%d) failed", async);
355*8feb0f0bSmrg }
356*8feb0f0bSmrg
357*8feb0f0bSmrg void
GOACC_wait(int async,int num_waits,...)358*8feb0f0bSmrg GOACC_wait (int async, int num_waits, ...)
359*8feb0f0bSmrg {
360*8feb0f0bSmrg goacc_lazy_initialize ();
3611debfc3dSmrg
3621debfc3dSmrg struct goacc_thread *thr = goacc_thread ();
3631debfc3dSmrg
364*8feb0f0bSmrg /* No nesting. */
365*8feb0f0bSmrg assert (thr->prof_info == NULL);
366*8feb0f0bSmrg assert (thr->api_info == NULL);
367*8feb0f0bSmrg acc_prof_info prof_info;
368*8feb0f0bSmrg acc_api_info api_info;
369*8feb0f0bSmrg bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
370*8feb0f0bSmrg if (profiling_p)
371*8feb0f0bSmrg {
372*8feb0f0bSmrg prof_info.async = async;
373*8feb0f0bSmrg prof_info.async_queue = prof_info.async;
374*8feb0f0bSmrg }
3751debfc3dSmrg
376*8feb0f0bSmrg if (num_waits)
377*8feb0f0bSmrg {
378*8feb0f0bSmrg va_list ap;
379*8feb0f0bSmrg
380*8feb0f0bSmrg va_start (ap, num_waits);
381*8feb0f0bSmrg goacc_wait (async, num_waits, &ap);
382*8feb0f0bSmrg va_end (ap);
383*8feb0f0bSmrg }
384*8feb0f0bSmrg else if (async == acc_async_sync)
385*8feb0f0bSmrg acc_wait_all ();
386*8feb0f0bSmrg else
387*8feb0f0bSmrg acc_wait_all_async (async);
388*8feb0f0bSmrg
389*8feb0f0bSmrg if (profiling_p)
390*8feb0f0bSmrg {
391*8feb0f0bSmrg thr->prof_info = NULL;
392*8feb0f0bSmrg thr->api_info = NULL;
393*8feb0f0bSmrg }
394*8feb0f0bSmrg }
395*8feb0f0bSmrg
396*8feb0f0bSmrg attribute_hidden void
goacc_wait(int async,int num_waits,va_list * ap)397*8feb0f0bSmrg goacc_wait (int async, int num_waits, va_list *ap)
398*8feb0f0bSmrg {
399*8feb0f0bSmrg while (num_waits--)
400*8feb0f0bSmrg {
401*8feb0f0bSmrg int qid = va_arg (*ap, int);
402*8feb0f0bSmrg
403*8feb0f0bSmrg /* Waiting on ACC_ASYNC_NOVAL maps to 'wait all'. */
404*8feb0f0bSmrg if (qid == acc_async_noval)
405*8feb0f0bSmrg {
406*8feb0f0bSmrg if (async == acc_async_sync)
407*8feb0f0bSmrg acc_wait_all ();
408*8feb0f0bSmrg else
409*8feb0f0bSmrg acc_wait_all_async (async);
410*8feb0f0bSmrg break;
411*8feb0f0bSmrg }
412*8feb0f0bSmrg
413*8feb0f0bSmrg if (acc_async_test (qid))
414*8feb0f0bSmrg continue;
415*8feb0f0bSmrg
416*8feb0f0bSmrg if (async == acc_async_sync)
417*8feb0f0bSmrg acc_wait (qid);
418*8feb0f0bSmrg else if (qid == async)
419*8feb0f0bSmrg /* If we're waiting on the same asynchronous queue as we're
420*8feb0f0bSmrg launching on, the queue itself will order work as
421*8feb0f0bSmrg required, so there's no need to wait explicitly. */
422*8feb0f0bSmrg ;
423*8feb0f0bSmrg else
424*8feb0f0bSmrg acc_wait_async (qid, async);
425*8feb0f0bSmrg }
426*8feb0f0bSmrg }
427*8feb0f0bSmrg
428*8feb0f0bSmrg attribute_hidden void
goacc_async_free(struct gomp_device_descr * devicep,struct goacc_asyncqueue * aq,void * ptr)429*8feb0f0bSmrg goacc_async_free (struct gomp_device_descr *devicep,
430*8feb0f0bSmrg struct goacc_asyncqueue *aq, void *ptr)
431*8feb0f0bSmrg {
432*8feb0f0bSmrg if (!aq)
433*8feb0f0bSmrg free (ptr);
434*8feb0f0bSmrg else
435*8feb0f0bSmrg devicep->openacc.async.queue_callback_func (aq, free, ptr);
436*8feb0f0bSmrg }
437*8feb0f0bSmrg
438*8feb0f0bSmrg /* This function initializes the asyncqueues for the device specified by
439*8feb0f0bSmrg DEVICEP. TODO DEVICEP must be locked on entry, and remains locked on
440*8feb0f0bSmrg return. */
441*8feb0f0bSmrg
442*8feb0f0bSmrg attribute_hidden void
goacc_init_asyncqueues(struct gomp_device_descr * devicep)443*8feb0f0bSmrg goacc_init_asyncqueues (struct gomp_device_descr *devicep)
444*8feb0f0bSmrg {
445*8feb0f0bSmrg devicep->openacc.async.nasyncqueue = 0;
446*8feb0f0bSmrg devicep->openacc.async.asyncqueue = NULL;
447*8feb0f0bSmrg devicep->openacc.async.active = NULL;
448*8feb0f0bSmrg gomp_mutex_init (&devicep->openacc.async.lock);
449*8feb0f0bSmrg }
450*8feb0f0bSmrg
451*8feb0f0bSmrg /* This function finalizes the asyncqueues for the device specified by DEVICEP.
452*8feb0f0bSmrg TODO DEVICEP must be locked on entry, and remains locked on return. */
453*8feb0f0bSmrg
454*8feb0f0bSmrg attribute_hidden bool
goacc_fini_asyncqueues(struct gomp_device_descr * devicep)455*8feb0f0bSmrg goacc_fini_asyncqueues (struct gomp_device_descr *devicep)
456*8feb0f0bSmrg {
457*8feb0f0bSmrg bool ret = true;
458*8feb0f0bSmrg gomp_mutex_lock (&devicep->openacc.async.lock);
459*8feb0f0bSmrg if (devicep->openacc.async.nasyncqueue > 0)
460*8feb0f0bSmrg {
461*8feb0f0bSmrg goacc_aq_list next;
462*8feb0f0bSmrg for (goacc_aq_list l = devicep->openacc.async.active; l; l = next)
463*8feb0f0bSmrg {
464*8feb0f0bSmrg ret &= devicep->openacc.async.destruct_func (l->aq);
465*8feb0f0bSmrg next = l->next;
466*8feb0f0bSmrg free (l);
467*8feb0f0bSmrg }
468*8feb0f0bSmrg free (devicep->openacc.async.asyncqueue);
469*8feb0f0bSmrg devicep->openacc.async.nasyncqueue = 0;
470*8feb0f0bSmrg devicep->openacc.async.asyncqueue = NULL;
471*8feb0f0bSmrg devicep->openacc.async.active = NULL;
472*8feb0f0bSmrg }
473*8feb0f0bSmrg gomp_mutex_unlock (&devicep->openacc.async.lock);
474*8feb0f0bSmrg gomp_mutex_destroy (&devicep->openacc.async.lock);
475*8feb0f0bSmrg return ret;
4761debfc3dSmrg }
477