xref: /netbsd-src/external/gpl3/gcc.old/dist/libgomp/oacc-async.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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