xref: /openbsd-src/gnu/gcc/libgomp/loop.c (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
1*404b540aSrobert /* Copyright (C) 2005 Free Software Foundation, Inc.
2*404b540aSrobert    Contributed by Richard Henderson <rth@redhat.com>.
3*404b540aSrobert 
4*404b540aSrobert    This file is part of the GNU OpenMP Library (libgomp).
5*404b540aSrobert 
6*404b540aSrobert    Libgomp is free software; you can redistribute it and/or modify it
7*404b540aSrobert    under the terms of the GNU Lesser General Public License as published by
8*404b540aSrobert    the Free Software Foundation; either version 2.1 of the License, or
9*404b540aSrobert    (at your option) any later version.
10*404b540aSrobert 
11*404b540aSrobert    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
12*404b540aSrobert    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13*404b540aSrobert    FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
14*404b540aSrobert    more details.
15*404b540aSrobert 
16*404b540aSrobert    You should have received a copy of the GNU Lesser General Public License
17*404b540aSrobert    along with libgomp; see the file COPYING.LIB.  If not, write to the
18*404b540aSrobert    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19*404b540aSrobert    MA 02110-1301, USA.  */
20*404b540aSrobert 
21*404b540aSrobert /* As a special exception, if you link this library with other files, some
22*404b540aSrobert    of which are compiled with GCC, to produce an executable, this library
23*404b540aSrobert    does not by itself cause the resulting executable to be covered by the
24*404b540aSrobert    GNU General Public License.  This exception does not however invalidate
25*404b540aSrobert    any other reasons why the executable file might be covered by the GNU
26*404b540aSrobert    General Public License.  */
27*404b540aSrobert 
28*404b540aSrobert /* This file handles the LOOP (FOR/DO) construct.  */
29*404b540aSrobert 
30*404b540aSrobert #include "libgomp.h"
31*404b540aSrobert #include <stdlib.h>
32*404b540aSrobert 
33*404b540aSrobert 
34*404b540aSrobert /* Initialize the given work share construct from the given arguments.  */
35*404b540aSrobert 
36*404b540aSrobert static inline void
gomp_loop_init(struct gomp_work_share * ws,long start,long end,long incr,enum gomp_schedule_type sched,long chunk_size)37*404b540aSrobert gomp_loop_init (struct gomp_work_share *ws, long start, long end, long incr,
38*404b540aSrobert 		enum gomp_schedule_type sched, long chunk_size)
39*404b540aSrobert {
40*404b540aSrobert   ws->sched = sched;
41*404b540aSrobert   ws->chunk_size = chunk_size;
42*404b540aSrobert   /* Canonicalize loops that have zero iterations to ->next == ->end.  */
43*404b540aSrobert   ws->end = ((incr > 0 && start > end) || (incr < 0 && start < end))
44*404b540aSrobert 	    ? start : end;
45*404b540aSrobert   ws->incr = incr;
46*404b540aSrobert   ws->next = start;
47*404b540aSrobert }
48*404b540aSrobert 
49*404b540aSrobert /* The *_start routines are called when first encountering a loop construct
50*404b540aSrobert    that is not bound directly to a parallel construct.  The first thread
51*404b540aSrobert    that arrives will create the work-share construct; subsequent threads
52*404b540aSrobert    will see the construct exists and allocate work from it.
53*404b540aSrobert 
54*404b540aSrobert    START, END, INCR are the bounds of the loop; due to the restrictions of
55*404b540aSrobert    OpenMP, these values must be the same in every thread.  This is not
56*404b540aSrobert    verified (nor is it entirely verifiable, since START is not necessarily
57*404b540aSrobert    retained intact in the work-share data structure).  CHUNK_SIZE is the
58*404b540aSrobert    scheduling parameter; again this must be identical in all threads.
59*404b540aSrobert 
60*404b540aSrobert    Returns true if there's any work for this thread to perform.  If so,
61*404b540aSrobert    *ISTART and *IEND are filled with the bounds of the iteration block
62*404b540aSrobert    allocated to this thread.  Returns false if all work was assigned to
63*404b540aSrobert    other threads prior to this thread's arrival.  */
64*404b540aSrobert 
65*404b540aSrobert static bool
gomp_loop_static_start(long start,long end,long incr,long chunk_size,long * istart,long * iend)66*404b540aSrobert gomp_loop_static_start (long start, long end, long incr, long chunk_size,
67*404b540aSrobert 			long *istart, long *iend)
68*404b540aSrobert {
69*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
70*404b540aSrobert 
71*404b540aSrobert   if (gomp_work_share_start (false))
72*404b540aSrobert     gomp_loop_init (thr->ts.work_share, start, end, incr,
73*404b540aSrobert 		    GFS_STATIC, chunk_size);
74*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
75*404b540aSrobert 
76*404b540aSrobert   return !gomp_iter_static_next (istart, iend);
77*404b540aSrobert }
78*404b540aSrobert 
79*404b540aSrobert static bool
gomp_loop_dynamic_start(long start,long end,long incr,long chunk_size,long * istart,long * iend)80*404b540aSrobert gomp_loop_dynamic_start (long start, long end, long incr, long chunk_size,
81*404b540aSrobert 			 long *istart, long *iend)
82*404b540aSrobert {
83*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
84*404b540aSrobert   bool ret;
85*404b540aSrobert 
86*404b540aSrobert   if (gomp_work_share_start (false))
87*404b540aSrobert     gomp_loop_init (thr->ts.work_share, start, end, incr,
88*404b540aSrobert 		    GFS_DYNAMIC, chunk_size);
89*404b540aSrobert 
90*404b540aSrobert #ifdef HAVE_SYNC_BUILTINS
91*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
92*404b540aSrobert   ret = gomp_iter_dynamic_next (istart, iend);
93*404b540aSrobert #else
94*404b540aSrobert   ret = gomp_iter_dynamic_next_locked (istart, iend);
95*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
96*404b540aSrobert #endif
97*404b540aSrobert 
98*404b540aSrobert   return ret;
99*404b540aSrobert }
100*404b540aSrobert 
101*404b540aSrobert static bool
gomp_loop_guided_start(long start,long end,long incr,long chunk_size,long * istart,long * iend)102*404b540aSrobert gomp_loop_guided_start (long start, long end, long incr, long chunk_size,
103*404b540aSrobert 			long *istart, long *iend)
104*404b540aSrobert {
105*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
106*404b540aSrobert   bool ret;
107*404b540aSrobert 
108*404b540aSrobert   if (gomp_work_share_start (false))
109*404b540aSrobert     gomp_loop_init (thr->ts.work_share, start, end, incr,
110*404b540aSrobert 		    GFS_GUIDED, chunk_size);
111*404b540aSrobert 
112*404b540aSrobert #ifdef HAVE_SYNC_BUILTINS
113*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
114*404b540aSrobert   ret = gomp_iter_guided_next (istart, iend);
115*404b540aSrobert #else
116*404b540aSrobert   ret = gomp_iter_guided_next_locked (istart, iend);
117*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
118*404b540aSrobert #endif
119*404b540aSrobert 
120*404b540aSrobert   return ret;
121*404b540aSrobert }
122*404b540aSrobert 
123*404b540aSrobert bool
GOMP_loop_runtime_start(long start,long end,long incr,long * istart,long * iend)124*404b540aSrobert GOMP_loop_runtime_start (long start, long end, long incr,
125*404b540aSrobert 			 long *istart, long *iend)
126*404b540aSrobert {
127*404b540aSrobert   switch (gomp_run_sched_var)
128*404b540aSrobert     {
129*404b540aSrobert     case GFS_STATIC:
130*404b540aSrobert       return gomp_loop_static_start (start, end, incr, gomp_run_sched_chunk,
131*404b540aSrobert 				     istart, iend);
132*404b540aSrobert     case GFS_DYNAMIC:
133*404b540aSrobert       return gomp_loop_dynamic_start (start, end, incr, gomp_run_sched_chunk,
134*404b540aSrobert 				      istart, iend);
135*404b540aSrobert     case GFS_GUIDED:
136*404b540aSrobert       return gomp_loop_guided_start (start, end, incr, gomp_run_sched_chunk,
137*404b540aSrobert 				     istart, iend);
138*404b540aSrobert     default:
139*404b540aSrobert       abort ();
140*404b540aSrobert     }
141*404b540aSrobert }
142*404b540aSrobert 
143*404b540aSrobert /* The *_ordered_*_start routines are similar.  The only difference is that
144*404b540aSrobert    this work-share construct is initialized to expect an ORDERED section.  */
145*404b540aSrobert 
146*404b540aSrobert static bool
gomp_loop_ordered_static_start(long start,long end,long incr,long chunk_size,long * istart,long * iend)147*404b540aSrobert gomp_loop_ordered_static_start (long start, long end, long incr,
148*404b540aSrobert 				long chunk_size, long *istart, long *iend)
149*404b540aSrobert {
150*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
151*404b540aSrobert 
152*404b540aSrobert   if (gomp_work_share_start (true))
153*404b540aSrobert     {
154*404b540aSrobert       gomp_loop_init (thr->ts.work_share, start, end, incr,
155*404b540aSrobert 		      GFS_STATIC, chunk_size);
156*404b540aSrobert       gomp_ordered_static_init ();
157*404b540aSrobert     }
158*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
159*404b540aSrobert 
160*404b540aSrobert   return !gomp_iter_static_next (istart, iend);
161*404b540aSrobert }
162*404b540aSrobert 
163*404b540aSrobert static bool
gomp_loop_ordered_dynamic_start(long start,long end,long incr,long chunk_size,long * istart,long * iend)164*404b540aSrobert gomp_loop_ordered_dynamic_start (long start, long end, long incr,
165*404b540aSrobert 				 long chunk_size, long *istart, long *iend)
166*404b540aSrobert {
167*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
168*404b540aSrobert   bool ret;
169*404b540aSrobert 
170*404b540aSrobert   if (gomp_work_share_start (true))
171*404b540aSrobert     gomp_loop_init (thr->ts.work_share, start, end, incr,
172*404b540aSrobert 		    GFS_DYNAMIC, chunk_size);
173*404b540aSrobert 
174*404b540aSrobert   ret = gomp_iter_dynamic_next_locked (istart, iend);
175*404b540aSrobert   if (ret)
176*404b540aSrobert     gomp_ordered_first ();
177*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
178*404b540aSrobert 
179*404b540aSrobert   return ret;
180*404b540aSrobert }
181*404b540aSrobert 
182*404b540aSrobert static bool
gomp_loop_ordered_guided_start(long start,long end,long incr,long chunk_size,long * istart,long * iend)183*404b540aSrobert gomp_loop_ordered_guided_start (long start, long end, long incr,
184*404b540aSrobert 				long chunk_size, long *istart, long *iend)
185*404b540aSrobert {
186*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
187*404b540aSrobert   bool ret;
188*404b540aSrobert 
189*404b540aSrobert   if (gomp_work_share_start (true))
190*404b540aSrobert     gomp_loop_init (thr->ts.work_share, start, end, incr,
191*404b540aSrobert 		    GFS_GUIDED, chunk_size);
192*404b540aSrobert 
193*404b540aSrobert   ret = gomp_iter_guided_next_locked (istart, iend);
194*404b540aSrobert   if (ret)
195*404b540aSrobert     gomp_ordered_first ();
196*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
197*404b540aSrobert 
198*404b540aSrobert   return ret;
199*404b540aSrobert }
200*404b540aSrobert 
201*404b540aSrobert bool
GOMP_loop_ordered_runtime_start(long start,long end,long incr,long * istart,long * iend)202*404b540aSrobert GOMP_loop_ordered_runtime_start (long start, long end, long incr,
203*404b540aSrobert 				 long *istart, long *iend)
204*404b540aSrobert {
205*404b540aSrobert   switch (gomp_run_sched_var)
206*404b540aSrobert     {
207*404b540aSrobert     case GFS_STATIC:
208*404b540aSrobert       return gomp_loop_ordered_static_start (start, end, incr,
209*404b540aSrobert 					     gomp_run_sched_chunk,
210*404b540aSrobert 					     istart, iend);
211*404b540aSrobert     case GFS_DYNAMIC:
212*404b540aSrobert       return gomp_loop_ordered_dynamic_start (start, end, incr,
213*404b540aSrobert 					      gomp_run_sched_chunk,
214*404b540aSrobert 					      istart, iend);
215*404b540aSrobert     case GFS_GUIDED:
216*404b540aSrobert       return gomp_loop_ordered_guided_start (start, end, incr,
217*404b540aSrobert 					     gomp_run_sched_chunk,
218*404b540aSrobert 					     istart, iend);
219*404b540aSrobert     default:
220*404b540aSrobert       abort ();
221*404b540aSrobert     }
222*404b540aSrobert }
223*404b540aSrobert 
224*404b540aSrobert /* The *_next routines are called when the thread completes processing of
225*404b540aSrobert    the iteration block currently assigned to it.  If the work-share
226*404b540aSrobert    construct is bound directly to a parallel construct, then the iteration
227*404b540aSrobert    bounds may have been set up before the parallel.  In which case, this
228*404b540aSrobert    may be the first iteration for the thread.
229*404b540aSrobert 
230*404b540aSrobert    Returns true if there is work remaining to be performed; *ISTART and
231*404b540aSrobert    *IEND are filled with a new iteration block.  Returns false if all work
232*404b540aSrobert    has been assigned.  */
233*404b540aSrobert 
234*404b540aSrobert static bool
gomp_loop_static_next(long * istart,long * iend)235*404b540aSrobert gomp_loop_static_next (long *istart, long *iend)
236*404b540aSrobert {
237*404b540aSrobert   return !gomp_iter_static_next (istart, iend);
238*404b540aSrobert }
239*404b540aSrobert 
240*404b540aSrobert static bool
gomp_loop_dynamic_next(long * istart,long * iend)241*404b540aSrobert gomp_loop_dynamic_next (long *istart, long *iend)
242*404b540aSrobert {
243*404b540aSrobert   bool ret;
244*404b540aSrobert 
245*404b540aSrobert #ifdef HAVE_SYNC_BUILTINS
246*404b540aSrobert   ret = gomp_iter_dynamic_next (istart, iend);
247*404b540aSrobert #else
248*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
249*404b540aSrobert   gomp_mutex_lock (&thr->ts.work_share->lock);
250*404b540aSrobert   ret = gomp_iter_dynamic_next_locked (istart, iend);
251*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
252*404b540aSrobert #endif
253*404b540aSrobert 
254*404b540aSrobert   return ret;
255*404b540aSrobert }
256*404b540aSrobert 
257*404b540aSrobert static bool
gomp_loop_guided_next(long * istart,long * iend)258*404b540aSrobert gomp_loop_guided_next (long *istart, long *iend)
259*404b540aSrobert {
260*404b540aSrobert   bool ret;
261*404b540aSrobert 
262*404b540aSrobert #ifdef HAVE_SYNC_BUILTINS
263*404b540aSrobert   ret = gomp_iter_guided_next (istart, iend);
264*404b540aSrobert #else
265*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
266*404b540aSrobert   gomp_mutex_lock (&thr->ts.work_share->lock);
267*404b540aSrobert   ret = gomp_iter_guided_next_locked (istart, iend);
268*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
269*404b540aSrobert #endif
270*404b540aSrobert 
271*404b540aSrobert   return ret;
272*404b540aSrobert }
273*404b540aSrobert 
274*404b540aSrobert bool
GOMP_loop_runtime_next(long * istart,long * iend)275*404b540aSrobert GOMP_loop_runtime_next (long *istart, long *iend)
276*404b540aSrobert {
277*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
278*404b540aSrobert 
279*404b540aSrobert   switch (thr->ts.work_share->sched)
280*404b540aSrobert     {
281*404b540aSrobert     case GFS_STATIC:
282*404b540aSrobert       return gomp_loop_static_next (istart, iend);
283*404b540aSrobert     case GFS_DYNAMIC:
284*404b540aSrobert       return gomp_loop_dynamic_next (istart, iend);
285*404b540aSrobert     case GFS_GUIDED:
286*404b540aSrobert       return gomp_loop_guided_next (istart, iend);
287*404b540aSrobert     default:
288*404b540aSrobert       abort ();
289*404b540aSrobert     }
290*404b540aSrobert }
291*404b540aSrobert 
292*404b540aSrobert /* The *_ordered_*_next routines are called when the thread completes
293*404b540aSrobert    processing of the iteration block currently assigned to it.
294*404b540aSrobert 
295*404b540aSrobert    Returns true if there is work remaining to be performed; *ISTART and
296*404b540aSrobert    *IEND are filled with a new iteration block.  Returns false if all work
297*404b540aSrobert    has been assigned.  */
298*404b540aSrobert 
299*404b540aSrobert static bool
gomp_loop_ordered_static_next(long * istart,long * iend)300*404b540aSrobert gomp_loop_ordered_static_next (long *istart, long *iend)
301*404b540aSrobert {
302*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
303*404b540aSrobert   int test;
304*404b540aSrobert 
305*404b540aSrobert   gomp_ordered_sync ();
306*404b540aSrobert   gomp_mutex_lock (&thr->ts.work_share->lock);
307*404b540aSrobert   test = gomp_iter_static_next (istart, iend);
308*404b540aSrobert   if (test >= 0)
309*404b540aSrobert     gomp_ordered_static_next ();
310*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
311*404b540aSrobert 
312*404b540aSrobert   return test == 0;
313*404b540aSrobert }
314*404b540aSrobert 
315*404b540aSrobert static bool
gomp_loop_ordered_dynamic_next(long * istart,long * iend)316*404b540aSrobert gomp_loop_ordered_dynamic_next (long *istart, long *iend)
317*404b540aSrobert {
318*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
319*404b540aSrobert   bool ret;
320*404b540aSrobert 
321*404b540aSrobert   gomp_ordered_sync ();
322*404b540aSrobert   gomp_mutex_lock (&thr->ts.work_share->lock);
323*404b540aSrobert   ret = gomp_iter_dynamic_next_locked (istart, iend);
324*404b540aSrobert   if (ret)
325*404b540aSrobert     gomp_ordered_next ();
326*404b540aSrobert   else
327*404b540aSrobert     gomp_ordered_last ();
328*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
329*404b540aSrobert 
330*404b540aSrobert   return ret;
331*404b540aSrobert }
332*404b540aSrobert 
333*404b540aSrobert static bool
gomp_loop_ordered_guided_next(long * istart,long * iend)334*404b540aSrobert gomp_loop_ordered_guided_next (long *istart, long *iend)
335*404b540aSrobert {
336*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
337*404b540aSrobert   bool ret;
338*404b540aSrobert 
339*404b540aSrobert   gomp_ordered_sync ();
340*404b540aSrobert   gomp_mutex_lock (&thr->ts.work_share->lock);
341*404b540aSrobert   ret = gomp_iter_guided_next_locked (istart, iend);
342*404b540aSrobert   if (ret)
343*404b540aSrobert     gomp_ordered_next ();
344*404b540aSrobert   else
345*404b540aSrobert     gomp_ordered_last ();
346*404b540aSrobert   gomp_mutex_unlock (&thr->ts.work_share->lock);
347*404b540aSrobert 
348*404b540aSrobert   return ret;
349*404b540aSrobert }
350*404b540aSrobert 
351*404b540aSrobert bool
GOMP_loop_ordered_runtime_next(long * istart,long * iend)352*404b540aSrobert GOMP_loop_ordered_runtime_next (long *istart, long *iend)
353*404b540aSrobert {
354*404b540aSrobert   struct gomp_thread *thr = gomp_thread ();
355*404b540aSrobert 
356*404b540aSrobert   switch (thr->ts.work_share->sched)
357*404b540aSrobert     {
358*404b540aSrobert     case GFS_STATIC:
359*404b540aSrobert       return gomp_loop_ordered_static_next (istart, iend);
360*404b540aSrobert     case GFS_DYNAMIC:
361*404b540aSrobert       return gomp_loop_ordered_dynamic_next (istart, iend);
362*404b540aSrobert     case GFS_GUIDED:
363*404b540aSrobert       return gomp_loop_ordered_guided_next (istart, iend);
364*404b540aSrobert     default:
365*404b540aSrobert       abort ();
366*404b540aSrobert     }
367*404b540aSrobert }
368*404b540aSrobert 
369*404b540aSrobert /* The GOMP_parallel_loop_* routines pre-initialize a work-share construct
370*404b540aSrobert    to avoid one synchronization once we get into the loop.  */
371*404b540aSrobert 
372*404b540aSrobert static void
gomp_parallel_loop_start(void (* fn)(void *),void * data,unsigned num_threads,long start,long end,long incr,enum gomp_schedule_type sched,long chunk_size)373*404b540aSrobert gomp_parallel_loop_start (void (*fn) (void *), void *data,
374*404b540aSrobert 			  unsigned num_threads, long start, long end,
375*404b540aSrobert 			  long incr, enum gomp_schedule_type sched,
376*404b540aSrobert 			  long chunk_size)
377*404b540aSrobert {
378*404b540aSrobert   struct gomp_work_share *ws;
379*404b540aSrobert 
380*404b540aSrobert   num_threads = gomp_resolve_num_threads (num_threads);
381*404b540aSrobert   ws = gomp_new_work_share (false, num_threads);
382*404b540aSrobert   gomp_loop_init (ws, start, end, incr, sched, chunk_size);
383*404b540aSrobert   gomp_team_start (fn, data, num_threads, ws);
384*404b540aSrobert }
385*404b540aSrobert 
386*404b540aSrobert void
GOMP_parallel_loop_static_start(void (* fn)(void *),void * data,unsigned num_threads,long start,long end,long incr,long chunk_size)387*404b540aSrobert GOMP_parallel_loop_static_start (void (*fn) (void *), void *data,
388*404b540aSrobert 				 unsigned num_threads, long start, long end,
389*404b540aSrobert 				 long incr, long chunk_size)
390*404b540aSrobert {
391*404b540aSrobert   gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
392*404b540aSrobert 			    GFS_STATIC, chunk_size);
393*404b540aSrobert }
394*404b540aSrobert 
395*404b540aSrobert void
GOMP_parallel_loop_dynamic_start(void (* fn)(void *),void * data,unsigned num_threads,long start,long end,long incr,long chunk_size)396*404b540aSrobert GOMP_parallel_loop_dynamic_start (void (*fn) (void *), void *data,
397*404b540aSrobert 				  unsigned num_threads, long start, long end,
398*404b540aSrobert 				  long incr, long chunk_size)
399*404b540aSrobert {
400*404b540aSrobert   gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
401*404b540aSrobert 			    GFS_DYNAMIC, chunk_size);
402*404b540aSrobert }
403*404b540aSrobert 
404*404b540aSrobert void
GOMP_parallel_loop_guided_start(void (* fn)(void *),void * data,unsigned num_threads,long start,long end,long incr,long chunk_size)405*404b540aSrobert GOMP_parallel_loop_guided_start (void (*fn) (void *), void *data,
406*404b540aSrobert 				 unsigned num_threads, long start, long end,
407*404b540aSrobert 				 long incr, long chunk_size)
408*404b540aSrobert {
409*404b540aSrobert   gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
410*404b540aSrobert 			    GFS_GUIDED, chunk_size);
411*404b540aSrobert }
412*404b540aSrobert 
413*404b540aSrobert void
GOMP_parallel_loop_runtime_start(void (* fn)(void *),void * data,unsigned num_threads,long start,long end,long incr)414*404b540aSrobert GOMP_parallel_loop_runtime_start (void (*fn) (void *), void *data,
415*404b540aSrobert 				  unsigned num_threads, long start, long end,
416*404b540aSrobert 				  long incr)
417*404b540aSrobert {
418*404b540aSrobert   gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
419*404b540aSrobert 			    gomp_run_sched_var, gomp_run_sched_chunk);
420*404b540aSrobert }
421*404b540aSrobert 
422*404b540aSrobert /* The GOMP_loop_end* routines are called after the thread is told that
423*404b540aSrobert    all loop iterations are complete.  This first version synchronizes
424*404b540aSrobert    all threads; the nowait version does not.  */
425*404b540aSrobert 
426*404b540aSrobert void
GOMP_loop_end(void)427*404b540aSrobert GOMP_loop_end (void)
428*404b540aSrobert {
429*404b540aSrobert   gomp_work_share_end ();
430*404b540aSrobert }
431*404b540aSrobert 
432*404b540aSrobert void
GOMP_loop_end_nowait(void)433*404b540aSrobert GOMP_loop_end_nowait (void)
434*404b540aSrobert {
435*404b540aSrobert   gomp_work_share_end_nowait ();
436*404b540aSrobert }
437*404b540aSrobert 
438*404b540aSrobert 
439*404b540aSrobert /* We use static functions above so that we're sure that the "runtime"
440*404b540aSrobert    function can defer to the proper routine without interposition.  We
441*404b540aSrobert    export the static function with a strong alias when possible, or with
442*404b540aSrobert    a wrapper function otherwise.  */
443*404b540aSrobert 
444*404b540aSrobert #ifdef HAVE_ATTRIBUTE_ALIAS
445*404b540aSrobert extern __typeof(gomp_loop_static_start) GOMP_loop_static_start
446*404b540aSrobert 	__attribute__((alias ("gomp_loop_static_start")));
447*404b540aSrobert extern __typeof(gomp_loop_dynamic_start) GOMP_loop_dynamic_start
448*404b540aSrobert 	__attribute__((alias ("gomp_loop_dynamic_start")));
449*404b540aSrobert extern __typeof(gomp_loop_guided_start) GOMP_loop_guided_start
450*404b540aSrobert 	__attribute__((alias ("gomp_loop_guided_start")));
451*404b540aSrobert 
452*404b540aSrobert extern __typeof(gomp_loop_ordered_static_start) GOMP_loop_ordered_static_start
453*404b540aSrobert 	__attribute__((alias ("gomp_loop_ordered_static_start")));
454*404b540aSrobert extern __typeof(gomp_loop_ordered_dynamic_start) GOMP_loop_ordered_dynamic_start
455*404b540aSrobert 	__attribute__((alias ("gomp_loop_ordered_dynamic_start")));
456*404b540aSrobert extern __typeof(gomp_loop_ordered_guided_start) GOMP_loop_ordered_guided_start
457*404b540aSrobert 	__attribute__((alias ("gomp_loop_ordered_guided_start")));
458*404b540aSrobert 
459*404b540aSrobert extern __typeof(gomp_loop_static_next) GOMP_loop_static_next
460*404b540aSrobert 	__attribute__((alias ("gomp_loop_static_next")));
461*404b540aSrobert extern __typeof(gomp_loop_dynamic_next) GOMP_loop_dynamic_next
462*404b540aSrobert 	__attribute__((alias ("gomp_loop_dynamic_next")));
463*404b540aSrobert extern __typeof(gomp_loop_guided_next) GOMP_loop_guided_next
464*404b540aSrobert 	__attribute__((alias ("gomp_loop_guided_next")));
465*404b540aSrobert 
466*404b540aSrobert extern __typeof(gomp_loop_ordered_static_next) GOMP_loop_ordered_static_next
467*404b540aSrobert 	__attribute__((alias ("gomp_loop_ordered_static_next")));
468*404b540aSrobert extern __typeof(gomp_loop_ordered_dynamic_next) GOMP_loop_ordered_dynamic_next
469*404b540aSrobert 	__attribute__((alias ("gomp_loop_ordered_dynamic_next")));
470*404b540aSrobert extern __typeof(gomp_loop_ordered_guided_next) GOMP_loop_ordered_guided_next
471*404b540aSrobert 	__attribute__((alias ("gomp_loop_ordered_guided_next")));
472*404b540aSrobert #else
473*404b540aSrobert bool
GOMP_loop_static_start(long start,long end,long incr,long chunk_size,long * istart,long * iend)474*404b540aSrobert GOMP_loop_static_start (long start, long end, long incr, long chunk_size,
475*404b540aSrobert 			long *istart, long *iend)
476*404b540aSrobert {
477*404b540aSrobert   return gomp_loop_static_start (start, end, incr, chunk_size, istart, iend);
478*404b540aSrobert }
479*404b540aSrobert 
480*404b540aSrobert bool
GOMP_loop_dynamic_start(long start,long end,long incr,long chunk_size,long * istart,long * iend)481*404b540aSrobert GOMP_loop_dynamic_start (long start, long end, long incr, long chunk_size,
482*404b540aSrobert 			 long *istart, long *iend)
483*404b540aSrobert {
484*404b540aSrobert   return gomp_loop_dynamic_start (start, end, incr, chunk_size, istart, iend);
485*404b540aSrobert }
486*404b540aSrobert 
487*404b540aSrobert bool
GOMP_loop_guided_start(long start,long end,long incr,long chunk_size,long * istart,long * iend)488*404b540aSrobert GOMP_loop_guided_start (long start, long end, long incr, long chunk_size,
489*404b540aSrobert 			long *istart, long *iend)
490*404b540aSrobert {
491*404b540aSrobert   return gomp_loop_guided_start (start, end, incr, chunk_size, istart, iend);
492*404b540aSrobert }
493*404b540aSrobert 
494*404b540aSrobert bool
GOMP_loop_ordered_static_start(long start,long end,long incr,long chunk_size,long * istart,long * iend)495*404b540aSrobert GOMP_loop_ordered_static_start (long start, long end, long incr,
496*404b540aSrobert 				long chunk_size, long *istart, long *iend)
497*404b540aSrobert {
498*404b540aSrobert   return gomp_loop_ordered_static_start (start, end, incr, chunk_size,
499*404b540aSrobert 					 istart, iend);
500*404b540aSrobert }
501*404b540aSrobert 
502*404b540aSrobert bool
GOMP_loop_ordered_dynamic_start(long start,long end,long incr,long chunk_size,long * istart,long * iend)503*404b540aSrobert GOMP_loop_ordered_dynamic_start (long start, long end, long incr,
504*404b540aSrobert 				 long chunk_size, long *istart, long *iend)
505*404b540aSrobert {
506*404b540aSrobert   return gomp_loop_ordered_dynamic_start (start, end, incr, chunk_size,
507*404b540aSrobert 					  istart, iend);
508*404b540aSrobert }
509*404b540aSrobert 
510*404b540aSrobert bool
GOMP_loop_ordered_guided_start(long start,long end,long incr,long chunk_size,long * istart,long * iend)511*404b540aSrobert GOMP_loop_ordered_guided_start (long start, long end, long incr,
512*404b540aSrobert 				long chunk_size, long *istart, long *iend)
513*404b540aSrobert {
514*404b540aSrobert   return gomp_loop_ordered_guided_start (start, end, incr, chunk_size,
515*404b540aSrobert 					 istart, iend);
516*404b540aSrobert }
517*404b540aSrobert 
518*404b540aSrobert bool
GOMP_loop_static_next(long * istart,long * iend)519*404b540aSrobert GOMP_loop_static_next (long *istart, long *iend)
520*404b540aSrobert {
521*404b540aSrobert   return gomp_loop_static_next (istart, iend);
522*404b540aSrobert }
523*404b540aSrobert 
524*404b540aSrobert bool
GOMP_loop_dynamic_next(long * istart,long * iend)525*404b540aSrobert GOMP_loop_dynamic_next (long *istart, long *iend)
526*404b540aSrobert {
527*404b540aSrobert   return gomp_loop_dynamic_next (istart, iend);
528*404b540aSrobert }
529*404b540aSrobert 
530*404b540aSrobert bool
GOMP_loop_guided_next(long * istart,long * iend)531*404b540aSrobert GOMP_loop_guided_next (long *istart, long *iend)
532*404b540aSrobert {
533*404b540aSrobert   return gomp_loop_guided_next (istart, iend);
534*404b540aSrobert }
535*404b540aSrobert 
536*404b540aSrobert bool
GOMP_loop_ordered_static_next(long * istart,long * iend)537*404b540aSrobert GOMP_loop_ordered_static_next (long *istart, long *iend)
538*404b540aSrobert {
539*404b540aSrobert   return gomp_loop_ordered_static_next (istart, iend);
540*404b540aSrobert }
541*404b540aSrobert 
542*404b540aSrobert bool
GOMP_loop_ordered_dynamic_next(long * istart,long * iend)543*404b540aSrobert GOMP_loop_ordered_dynamic_next (long *istart, long *iend)
544*404b540aSrobert {
545*404b540aSrobert   return gomp_loop_ordered_dynamic_next (istart, iend);
546*404b540aSrobert }
547*404b540aSrobert 
548*404b540aSrobert bool
GOMP_loop_ordered_guided_next(long * istart,long * iend)549*404b540aSrobert GOMP_loop_ordered_guided_next (long *istart, long *iend)
550*404b540aSrobert {
551*404b540aSrobert   return gomp_loop_ordered_guided_next (istart, iend);
552*404b540aSrobert }
553*404b540aSrobert #endif
554