]>
Commit | Line | Data |
---|---|---|
a945c346 | 1 | /* Copyright (C) 2005-2024 Free Software Foundation, Inc. |
953ff289 DN |
2 | Contributed by Richard Henderson <rth@redhat.com>. |
3 | ||
f1f3453e TS |
4 | This file is part of the GNU Offloading and Multi Processing Library |
5 | (libgomp). | |
953ff289 DN |
6 | |
7 | Libgomp is free software; you can redistribute it and/or modify it | |
748086b7 JJ |
8 | under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 3, or (at your option) | |
10 | any later version. | |
953ff289 DN |
11 | |
12 | Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
748086b7 | 14 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
953ff289 DN |
15 | more details. |
16 | ||
748086b7 JJ |
17 | Under Section 7 of GPL version 3, you are granted additional |
18 | permissions described in the GCC Runtime Library Exception, version | |
19 | 3.1, as published by the Free Software Foundation. | |
20 | ||
21 | You should have received a copy of the GNU General Public License and | |
22 | a copy of the GCC Runtime Library Exception along with this program; | |
23 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
24 | <http://www.gnu.org/licenses/>. */ | |
953ff289 DN |
25 | |
26 | /* This file handles the LOOP (FOR/DO) construct. */ | |
27 | ||
a68ab351 | 28 | #include <limits.h> |
953ff289 | 29 | #include <stdlib.h> |
28567c40 | 30 | #include <string.h> |
a68ab351 | 31 | #include "libgomp.h" |
953ff289 DN |
32 | |
33 | ||
28567c40 JJ |
34 | ialias (GOMP_loop_runtime_next) |
35 | ialias_redirect (GOMP_taskgroup_reduction_register) | |
36 | ||
953ff289 DN |
37 | /* Initialize the given work share construct from the given arguments. */ |
38 | ||
39 | static inline void | |
22568cc6 JJ |
40 | gomp_loop_init (struct gomp_work_share *ws, long start, long end, long incr, |
41 | enum gomp_schedule_type sched, long chunk_size) | |
953ff289 DN |
42 | { |
43 | ws->sched = sched; | |
44 | ws->chunk_size = chunk_size; | |
22568cc6 JJ |
45 | /* Canonicalize loops that have zero iterations to ->next == ->end. */ |
46 | ws->end = ((incr > 0 && start > end) || (incr < 0 && start < end)) | |
47 | ? start : end; | |
953ff289 DN |
48 | ws->incr = incr; |
49 | ws->next = start; | |
a68ab351 JJ |
50 | if (sched == GFS_DYNAMIC) |
51 | { | |
52 | ws->chunk_size *= incr; | |
53 | ||
54 | #ifdef HAVE_SYNC_BUILTINS | |
55 | { | |
56 | /* For dynamic scheduling prepare things to make each iteration | |
57 | faster. */ | |
58 | struct gomp_thread *thr = gomp_thread (); | |
59 | struct gomp_team *team = thr->ts.team; | |
60 | long nthreads = team ? team->nthreads : 1; | |
61 | ||
62 | if (__builtin_expect (incr > 0, 1)) | |
63 | { | |
64 | /* Cheap overflow protection. */ | |
65 | if (__builtin_expect ((nthreads | ws->chunk_size) | |
66 | >= 1UL << (sizeof (long) | |
67 | * __CHAR_BIT__ / 2 - 1), 0)) | |
68 | ws->mode = 0; | |
69 | else | |
70 | ws->mode = ws->end < (LONG_MAX | |
71 | - (nthreads + 1) * ws->chunk_size); | |
72 | } | |
73 | /* Cheap overflow protection. */ | |
74 | else if (__builtin_expect ((nthreads | -ws->chunk_size) | |
75 | >= 1UL << (sizeof (long) | |
76 | * __CHAR_BIT__ / 2 - 1), 0)) | |
77 | ws->mode = 0; | |
78 | else | |
79 | ws->mode = ws->end > (nthreads + 1) * -ws->chunk_size - LONG_MAX; | |
80 | } | |
81 | #endif | |
82 | } | |
953ff289 DN |
83 | } |
84 | ||
85 | /* The *_start routines are called when first encountering a loop construct | |
28567c40 | 86 | that is not bound directly to a parallel construct. The first thread |
953ff289 DN |
87 | that arrives will create the work-share construct; subsequent threads |
88 | will see the construct exists and allocate work from it. | |
89 | ||
90 | START, END, INCR are the bounds of the loop; due to the restrictions of | |
28567c40 | 91 | OpenMP, these values must be the same in every thread. This is not |
953ff289 DN |
92 | verified (nor is it entirely verifiable, since START is not necessarily |
93 | retained intact in the work-share data structure). CHUNK_SIZE is the | |
94 | scheduling parameter; again this must be identical in all threads. | |
95 | ||
96 | Returns true if there's any work for this thread to perform. If so, | |
97 | *ISTART and *IEND are filled with the bounds of the iteration block | |
98 | allocated to this thread. Returns false if all work was assigned to | |
99 | other threads prior to this thread's arrival. */ | |
100 | ||
101 | static bool | |
102 | gomp_loop_static_start (long start, long end, long incr, long chunk_size, | |
103 | long *istart, long *iend) | |
104 | { | |
105 | struct gomp_thread *thr = gomp_thread (); | |
106 | ||
a68ab351 | 107 | thr->ts.static_trip = 0; |
28567c40 | 108 | if (gomp_work_share_start (0)) |
a68ab351 JJ |
109 | { |
110 | gomp_loop_init (thr->ts.work_share, start, end, incr, | |
111 | GFS_STATIC, chunk_size); | |
112 | gomp_work_share_init_done (); | |
113 | } | |
953ff289 DN |
114 | |
115 | return !gomp_iter_static_next (istart, iend); | |
116 | } | |
117 | ||
e01d41e5 JJ |
118 | /* The current dynamic implementation is always monotonic. The |
119 | entrypoints without nonmonotonic in them have to be always monotonic, | |
120 | but the nonmonotonic ones could be changed to use work-stealing for | |
121 | improved scalability. */ | |
122 | ||
953ff289 DN |
123 | static bool |
124 | gomp_loop_dynamic_start (long start, long end, long incr, long chunk_size, | |
125 | long *istart, long *iend) | |
126 | { | |
127 | struct gomp_thread *thr = gomp_thread (); | |
128 | bool ret; | |
129 | ||
28567c40 | 130 | if (gomp_work_share_start (0)) |
a68ab351 JJ |
131 | { |
132 | gomp_loop_init (thr->ts.work_share, start, end, incr, | |
133 | GFS_DYNAMIC, chunk_size); | |
134 | gomp_work_share_init_done (); | |
135 | } | |
953ff289 DN |
136 | |
137 | #ifdef HAVE_SYNC_BUILTINS | |
953ff289 DN |
138 | ret = gomp_iter_dynamic_next (istart, iend); |
139 | #else | |
a68ab351 | 140 | gomp_mutex_lock (&thr->ts.work_share->lock); |
953ff289 DN |
141 | ret = gomp_iter_dynamic_next_locked (istart, iend); |
142 | gomp_mutex_unlock (&thr->ts.work_share->lock); | |
143 | #endif | |
144 | ||
145 | return ret; | |
146 | } | |
147 | ||
e01d41e5 JJ |
148 | /* Similarly as for dynamic, though the question is how can the chunk sizes |
149 | be decreased without a central locking or atomics. */ | |
150 | ||
953ff289 DN |
151 | static bool |
152 | gomp_loop_guided_start (long start, long end, long incr, long chunk_size, | |
153 | long *istart, long *iend) | |
154 | { | |
155 | struct gomp_thread *thr = gomp_thread (); | |
156 | bool ret; | |
157 | ||
28567c40 | 158 | if (gomp_work_share_start (0)) |
a68ab351 JJ |
159 | { |
160 | gomp_loop_init (thr->ts.work_share, start, end, incr, | |
161 | GFS_GUIDED, chunk_size); | |
162 | gomp_work_share_init_done (); | |
163 | } | |
953ff289 DN |
164 | |
165 | #ifdef HAVE_SYNC_BUILTINS | |
953ff289 DN |
166 | ret = gomp_iter_guided_next (istart, iend); |
167 | #else | |
a68ab351 | 168 | gomp_mutex_lock (&thr->ts.work_share->lock); |
953ff289 DN |
169 | ret = gomp_iter_guided_next_locked (istart, iend); |
170 | gomp_mutex_unlock (&thr->ts.work_share->lock); | |
171 | #endif | |
172 | ||
173 | return ret; | |
174 | } | |
175 | ||
176 | bool | |
177 | GOMP_loop_runtime_start (long start, long end, long incr, | |
178 | long *istart, long *iend) | |
179 | { | |
a68ab351 | 180 | struct gomp_task_icv *icv = gomp_icv (false); |
28567c40 | 181 | switch (icv->run_sched_var & ~GFS_MONOTONIC) |
953ff289 DN |
182 | { |
183 | case GFS_STATIC: | |
d9a6bd32 JJ |
184 | return gomp_loop_static_start (start, end, incr, |
185 | icv->run_sched_chunk_size, | |
953ff289 DN |
186 | istart, iend); |
187 | case GFS_DYNAMIC: | |
d9a6bd32 JJ |
188 | return gomp_loop_dynamic_start (start, end, incr, |
189 | icv->run_sched_chunk_size, | |
953ff289 DN |
190 | istart, iend); |
191 | case GFS_GUIDED: | |
d9a6bd32 JJ |
192 | return gomp_loop_guided_start (start, end, incr, |
193 | icv->run_sched_chunk_size, | |
953ff289 | 194 | istart, iend); |
a68ab351 JJ |
195 | case GFS_AUTO: |
196 | /* For now map to schedule(static), later on we could play with feedback | |
197 | driven choice. */ | |
198 | return gomp_loop_static_start (start, end, incr, 0, istart, iend); | |
953ff289 DN |
199 | default: |
200 | abort (); | |
201 | } | |
202 | } | |
203 | ||
28567c40 JJ |
204 | static long |
205 | gomp_adjust_sched (long sched, long *chunk_size) | |
206 | { | |
207 | sched &= ~GFS_MONOTONIC; | |
208 | switch (sched) | |
209 | { | |
210 | case GFS_STATIC: | |
211 | case GFS_DYNAMIC: | |
212 | case GFS_GUIDED: | |
213 | return sched; | |
214 | /* GFS_RUNTIME is used for runtime schedule without monotonic | |
215 | or nonmonotonic modifiers on the clause. | |
216 | GFS_RUNTIME|GFS_MONOTONIC for runtime schedule with monotonic | |
217 | modifier. */ | |
218 | case GFS_RUNTIME: | |
219 | /* GFS_AUTO is used for runtime schedule with nonmonotonic | |
220 | modifier. */ | |
221 | case GFS_AUTO: | |
222 | { | |
223 | struct gomp_task_icv *icv = gomp_icv (false); | |
224 | sched = icv->run_sched_var & ~GFS_MONOTONIC; | |
225 | switch (sched) | |
226 | { | |
227 | case GFS_STATIC: | |
228 | case GFS_DYNAMIC: | |
229 | case GFS_GUIDED: | |
230 | *chunk_size = icv->run_sched_chunk_size; | |
231 | break; | |
232 | case GFS_AUTO: | |
233 | sched = GFS_STATIC; | |
234 | *chunk_size = 0; | |
235 | break; | |
236 | default: | |
237 | abort (); | |
238 | } | |
239 | return sched; | |
240 | } | |
241 | default: | |
242 | abort (); | |
243 | } | |
244 | } | |
245 | ||
246 | bool | |
247 | GOMP_loop_start (long start, long end, long incr, long sched, | |
248 | long chunk_size, long *istart, long *iend, | |
249 | uintptr_t *reductions, void **mem) | |
250 | { | |
251 | struct gomp_thread *thr = gomp_thread (); | |
252 | ||
253 | thr->ts.static_trip = 0; | |
254 | if (reductions) | |
255 | gomp_workshare_taskgroup_start (); | |
256 | if (gomp_work_share_start (0)) | |
257 | { | |
258 | sched = gomp_adjust_sched (sched, &chunk_size); | |
259 | gomp_loop_init (thr->ts.work_share, start, end, incr, | |
260 | sched, chunk_size); | |
261 | if (reductions) | |
262 | { | |
263 | GOMP_taskgroup_reduction_register (reductions); | |
264 | thr->task->taskgroup->workshare = true; | |
265 | thr->ts.work_share->task_reductions = reductions; | |
266 | } | |
267 | if (mem) | |
268 | { | |
269 | uintptr_t size = (uintptr_t) *mem; | |
fcfb8032 JJ |
270 | #define INLINE_ORDERED_TEAM_IDS_OFF \ |
271 | ((offsetof (struct gomp_work_share, inline_ordered_team_ids) \ | |
272 | + __alignof__ (long long) - 1) & ~(__alignof__ (long long) - 1)) | |
57a957cb JJ |
273 | if (sizeof (struct gomp_work_share) |
274 | <= INLINE_ORDERED_TEAM_IDS_OFF | |
275 | || __alignof__ (struct gomp_work_share) < __alignof__ (long long) | |
276 | || size > (sizeof (struct gomp_work_share) | |
277 | - INLINE_ORDERED_TEAM_IDS_OFF)) | |
fcfb8032 JJ |
278 | *mem |
279 | = (void *) (thr->ts.work_share->ordered_team_ids | |
280 | = gomp_malloc_cleared (size)); | |
28567c40 | 281 | else |
fcfb8032 JJ |
282 | *mem = memset (((char *) thr->ts.work_share) |
283 | + INLINE_ORDERED_TEAM_IDS_OFF, '\0', size); | |
28567c40 JJ |
284 | } |
285 | gomp_work_share_init_done (); | |
286 | } | |
287 | else | |
288 | { | |
289 | if (reductions) | |
290 | { | |
291 | uintptr_t *first_reductions = thr->ts.work_share->task_reductions; | |
292 | gomp_workshare_task_reduction_register (reductions, | |
293 | first_reductions); | |
294 | } | |
295 | if (mem) | |
fcfb8032 JJ |
296 | { |
297 | if ((offsetof (struct gomp_work_share, inline_ordered_team_ids) | |
298 | & (__alignof__ (long long) - 1)) == 0) | |
299 | *mem = (void *) thr->ts.work_share->ordered_team_ids; | |
300 | else | |
301 | { | |
302 | uintptr_t p = (uintptr_t) thr->ts.work_share->ordered_team_ids; | |
303 | p += __alignof__ (long long) - 1; | |
304 | p &= ~(__alignof__ (long long) - 1); | |
305 | *mem = (void *) p; | |
306 | } | |
307 | } | |
28567c40 JJ |
308 | } |
309 | ||
310 | if (!istart) | |
311 | return true; | |
312 | return ialias_call (GOMP_loop_runtime_next) (istart, iend); | |
313 | } | |
314 | ||
953ff289 DN |
315 | /* The *_ordered_*_start routines are similar. The only difference is that |
316 | this work-share construct is initialized to expect an ORDERED section. */ | |
317 | ||
318 | static bool | |
319 | gomp_loop_ordered_static_start (long start, long end, long incr, | |
320 | long chunk_size, long *istart, long *iend) | |
321 | { | |
322 | struct gomp_thread *thr = gomp_thread (); | |
323 | ||
a68ab351 | 324 | thr->ts.static_trip = 0; |
28567c40 | 325 | if (gomp_work_share_start (1)) |
953ff289 DN |
326 | { |
327 | gomp_loop_init (thr->ts.work_share, start, end, incr, | |
328 | GFS_STATIC, chunk_size); | |
329 | gomp_ordered_static_init (); | |
a68ab351 | 330 | gomp_work_share_init_done (); |
953ff289 | 331 | } |
953ff289 DN |
332 | |
333 | return !gomp_iter_static_next (istart, iend); | |
334 | } | |
335 | ||
336 | static bool | |
337 | gomp_loop_ordered_dynamic_start (long start, long end, long incr, | |
338 | long chunk_size, long *istart, long *iend) | |
339 | { | |
340 | struct gomp_thread *thr = gomp_thread (); | |
341 | bool ret; | |
342 | ||
28567c40 | 343 | if (gomp_work_share_start (1)) |
a68ab351 JJ |
344 | { |
345 | gomp_loop_init (thr->ts.work_share, start, end, incr, | |
346 | GFS_DYNAMIC, chunk_size); | |
347 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
348 | gomp_work_share_init_done (); | |
349 | } | |
350 | else | |
351 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
953ff289 DN |
352 | |
353 | ret = gomp_iter_dynamic_next_locked (istart, iend); | |
354 | if (ret) | |
355 | gomp_ordered_first (); | |
356 | gomp_mutex_unlock (&thr->ts.work_share->lock); | |
357 | ||
358 | return ret; | |
359 | } | |
360 | ||
361 | static bool | |
362 | gomp_loop_ordered_guided_start (long start, long end, long incr, | |
363 | long chunk_size, long *istart, long *iend) | |
364 | { | |
365 | struct gomp_thread *thr = gomp_thread (); | |
366 | bool ret; | |
367 | ||
28567c40 | 368 | if (gomp_work_share_start (1)) |
a68ab351 JJ |
369 | { |
370 | gomp_loop_init (thr->ts.work_share, start, end, incr, | |
371 | GFS_GUIDED, chunk_size); | |
372 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
373 | gomp_work_share_init_done (); | |
374 | } | |
375 | else | |
376 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
953ff289 DN |
377 | |
378 | ret = gomp_iter_guided_next_locked (istart, iend); | |
379 | if (ret) | |
380 | gomp_ordered_first (); | |
381 | gomp_mutex_unlock (&thr->ts.work_share->lock); | |
382 | ||
383 | return ret; | |
384 | } | |
385 | ||
386 | bool | |
387 | GOMP_loop_ordered_runtime_start (long start, long end, long incr, | |
388 | long *istart, long *iend) | |
389 | { | |
a68ab351 | 390 | struct gomp_task_icv *icv = gomp_icv (false); |
28567c40 | 391 | switch (icv->run_sched_var & ~GFS_MONOTONIC) |
953ff289 DN |
392 | { |
393 | case GFS_STATIC: | |
394 | return gomp_loop_ordered_static_start (start, end, incr, | |
d9a6bd32 | 395 | icv->run_sched_chunk_size, |
953ff289 DN |
396 | istart, iend); |
397 | case GFS_DYNAMIC: | |
398 | return gomp_loop_ordered_dynamic_start (start, end, incr, | |
d9a6bd32 | 399 | icv->run_sched_chunk_size, |
953ff289 DN |
400 | istart, iend); |
401 | case GFS_GUIDED: | |
402 | return gomp_loop_ordered_guided_start (start, end, incr, | |
d9a6bd32 | 403 | icv->run_sched_chunk_size, |
953ff289 | 404 | istart, iend); |
a68ab351 JJ |
405 | case GFS_AUTO: |
406 | /* For now map to schedule(static), later on we could play with feedback | |
407 | driven choice. */ | |
408 | return gomp_loop_ordered_static_start (start, end, incr, | |
409 | 0, istart, iend); | |
953ff289 DN |
410 | default: |
411 | abort (); | |
412 | } | |
413 | } | |
414 | ||
28567c40 JJ |
415 | bool |
416 | GOMP_loop_ordered_start (long start, long end, long incr, long sched, | |
417 | long chunk_size, long *istart, long *iend, | |
418 | uintptr_t *reductions, void **mem) | |
419 | { | |
420 | struct gomp_thread *thr = gomp_thread (); | |
421 | size_t ordered = 1; | |
422 | bool ret; | |
423 | ||
424 | thr->ts.static_trip = 0; | |
425 | if (reductions) | |
426 | gomp_workshare_taskgroup_start (); | |
427 | if (mem) | |
428 | ordered += (uintptr_t) *mem; | |
429 | if (gomp_work_share_start (ordered)) | |
430 | { | |
431 | sched = gomp_adjust_sched (sched, &chunk_size); | |
432 | gomp_loop_init (thr->ts.work_share, start, end, incr, | |
433 | sched, chunk_size); | |
434 | if (reductions) | |
435 | { | |
436 | GOMP_taskgroup_reduction_register (reductions); | |
437 | thr->task->taskgroup->workshare = true; | |
438 | thr->ts.work_share->task_reductions = reductions; | |
439 | } | |
440 | if (sched == GFS_STATIC) | |
441 | gomp_ordered_static_init (); | |
442 | else | |
443 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
444 | gomp_work_share_init_done (); | |
445 | } | |
446 | else | |
447 | { | |
448 | if (reductions) | |
449 | { | |
450 | uintptr_t *first_reductions = thr->ts.work_share->task_reductions; | |
451 | gomp_workshare_task_reduction_register (reductions, | |
452 | first_reductions); | |
453 | } | |
454 | sched = thr->ts.work_share->sched; | |
455 | if (sched != GFS_STATIC) | |
456 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
457 | } | |
458 | ||
459 | if (mem) | |
460 | { | |
461 | uintptr_t p | |
462 | = (uintptr_t) (thr->ts.work_share->ordered_team_ids | |
463 | + (thr->ts.team ? thr->ts.team->nthreads : 1)); | |
464 | p += __alignof__ (long long) - 1; | |
465 | p &= ~(__alignof__ (long long) - 1); | |
466 | *mem = (void *) p; | |
467 | } | |
468 | ||
469 | switch (sched) | |
470 | { | |
471 | case GFS_STATIC: | |
472 | case GFS_AUTO: | |
473 | return !gomp_iter_static_next (istart, iend); | |
474 | case GFS_DYNAMIC: | |
475 | ret = gomp_iter_dynamic_next_locked (istart, iend); | |
476 | break; | |
477 | case GFS_GUIDED: | |
478 | ret = gomp_iter_guided_next_locked (istart, iend); | |
479 | break; | |
480 | default: | |
481 | abort (); | |
482 | } | |
483 | ||
484 | if (ret) | |
485 | gomp_ordered_first (); | |
486 | gomp_mutex_unlock (&thr->ts.work_share->lock); | |
487 | return ret; | |
488 | } | |
489 | ||
d9a6bd32 JJ |
490 | /* The *_doacross_*_start routines are similar. The only difference is that |
491 | this work-share construct is initialized to expect an ORDERED(N) - DOACROSS | |
492 | section, and the worksharing loop iterates always from 0 to COUNTS[0] - 1 | |
493 | and other COUNTS array elements tell the library number of iterations | |
494 | in the ordered inner loops. */ | |
495 | ||
496 | static bool | |
497 | gomp_loop_doacross_static_start (unsigned ncounts, long *counts, | |
498 | long chunk_size, long *istart, long *iend) | |
499 | { | |
500 | struct gomp_thread *thr = gomp_thread (); | |
501 | ||
502 | thr->ts.static_trip = 0; | |
28567c40 | 503 | if (gomp_work_share_start (0)) |
d9a6bd32 JJ |
504 | { |
505 | gomp_loop_init (thr->ts.work_share, 0, counts[0], 1, | |
506 | GFS_STATIC, chunk_size); | |
28567c40 | 507 | gomp_doacross_init (ncounts, counts, chunk_size, 0); |
d9a6bd32 JJ |
508 | gomp_work_share_init_done (); |
509 | } | |
510 | ||
511 | return !gomp_iter_static_next (istart, iend); | |
512 | } | |
513 | ||
514 | static bool | |
515 | gomp_loop_doacross_dynamic_start (unsigned ncounts, long *counts, | |
516 | long chunk_size, long *istart, long *iend) | |
517 | { | |
518 | struct gomp_thread *thr = gomp_thread (); | |
519 | bool ret; | |
520 | ||
28567c40 | 521 | if (gomp_work_share_start (0)) |
d9a6bd32 JJ |
522 | { |
523 | gomp_loop_init (thr->ts.work_share, 0, counts[0], 1, | |
524 | GFS_DYNAMIC, chunk_size); | |
28567c40 | 525 | gomp_doacross_init (ncounts, counts, chunk_size, 0); |
d9a6bd32 JJ |
526 | gomp_work_share_init_done (); |
527 | } | |
528 | ||
529 | #ifdef HAVE_SYNC_BUILTINS | |
530 | ret = gomp_iter_dynamic_next (istart, iend); | |
531 | #else | |
532 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
533 | ret = gomp_iter_dynamic_next_locked (istart, iend); | |
534 | gomp_mutex_unlock (&thr->ts.work_share->lock); | |
535 | #endif | |
536 | ||
537 | return ret; | |
538 | } | |
539 | ||
540 | static bool | |
541 | gomp_loop_doacross_guided_start (unsigned ncounts, long *counts, | |
542 | long chunk_size, long *istart, long *iend) | |
543 | { | |
544 | struct gomp_thread *thr = gomp_thread (); | |
545 | bool ret; | |
546 | ||
28567c40 | 547 | if (gomp_work_share_start (0)) |
d9a6bd32 JJ |
548 | { |
549 | gomp_loop_init (thr->ts.work_share, 0, counts[0], 1, | |
550 | GFS_GUIDED, chunk_size); | |
28567c40 | 551 | gomp_doacross_init (ncounts, counts, chunk_size, 0); |
d9a6bd32 JJ |
552 | gomp_work_share_init_done (); |
553 | } | |
554 | ||
555 | #ifdef HAVE_SYNC_BUILTINS | |
556 | ret = gomp_iter_guided_next (istart, iend); | |
557 | #else | |
558 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
559 | ret = gomp_iter_guided_next_locked (istart, iend); | |
560 | gomp_mutex_unlock (&thr->ts.work_share->lock); | |
561 | #endif | |
562 | ||
563 | return ret; | |
564 | } | |
565 | ||
566 | bool | |
567 | GOMP_loop_doacross_runtime_start (unsigned ncounts, long *counts, | |
568 | long *istart, long *iend) | |
569 | { | |
570 | struct gomp_task_icv *icv = gomp_icv (false); | |
28567c40 | 571 | switch (icv->run_sched_var & ~GFS_MONOTONIC) |
d9a6bd32 JJ |
572 | { |
573 | case GFS_STATIC: | |
574 | return gomp_loop_doacross_static_start (ncounts, counts, | |
575 | icv->run_sched_chunk_size, | |
576 | istart, iend); | |
577 | case GFS_DYNAMIC: | |
578 | return gomp_loop_doacross_dynamic_start (ncounts, counts, | |
579 | icv->run_sched_chunk_size, | |
580 | istart, iend); | |
581 | case GFS_GUIDED: | |
582 | return gomp_loop_doacross_guided_start (ncounts, counts, | |
583 | icv->run_sched_chunk_size, | |
584 | istart, iend); | |
585 | case GFS_AUTO: | |
586 | /* For now map to schedule(static), later on we could play with feedback | |
587 | driven choice. */ | |
588 | return gomp_loop_doacross_static_start (ncounts, counts, | |
589 | 0, istart, iend); | |
590 | default: | |
591 | abort (); | |
592 | } | |
593 | } | |
594 | ||
28567c40 JJ |
595 | bool |
596 | GOMP_loop_doacross_start (unsigned ncounts, long *counts, long sched, | |
597 | long chunk_size, long *istart, long *iend, | |
598 | uintptr_t *reductions, void **mem) | |
599 | { | |
600 | struct gomp_thread *thr = gomp_thread (); | |
601 | ||
602 | thr->ts.static_trip = 0; | |
603 | if (reductions) | |
604 | gomp_workshare_taskgroup_start (); | |
605 | if (gomp_work_share_start (0)) | |
606 | { | |
607 | size_t extra = 0; | |
608 | if (mem) | |
609 | extra = (uintptr_t) *mem; | |
610 | sched = gomp_adjust_sched (sched, &chunk_size); | |
611 | gomp_loop_init (thr->ts.work_share, 0, counts[0], 1, | |
612 | sched, chunk_size); | |
613 | gomp_doacross_init (ncounts, counts, chunk_size, extra); | |
614 | if (reductions) | |
615 | { | |
616 | GOMP_taskgroup_reduction_register (reductions); | |
617 | thr->task->taskgroup->workshare = true; | |
618 | thr->ts.work_share->task_reductions = reductions; | |
619 | } | |
620 | gomp_work_share_init_done (); | |
621 | } | |
622 | else | |
623 | { | |
624 | if (reductions) | |
625 | { | |
626 | uintptr_t *first_reductions = thr->ts.work_share->task_reductions; | |
627 | gomp_workshare_task_reduction_register (reductions, | |
628 | first_reductions); | |
629 | } | |
630 | sched = thr->ts.work_share->sched; | |
631 | } | |
632 | ||
633 | if (mem) | |
634 | *mem = thr->ts.work_share->doacross->extra; | |
635 | ||
636 | return ialias_call (GOMP_loop_runtime_next) (istart, iend); | |
637 | } | |
638 | ||
639 | /* The *_next routines are called when the thread completes processing of | |
640 | the iteration block currently assigned to it. If the work-share | |
953ff289 DN |
641 | construct is bound directly to a parallel construct, then the iteration |
642 | bounds may have been set up before the parallel. In which case, this | |
643 | may be the first iteration for the thread. | |
644 | ||
645 | Returns true if there is work remaining to be performed; *ISTART and | |
646 | *IEND are filled with a new iteration block. Returns false if all work | |
647 | has been assigned. */ | |
648 | ||
649 | static bool | |
650 | gomp_loop_static_next (long *istart, long *iend) | |
651 | { | |
652 | return !gomp_iter_static_next (istart, iend); | |
653 | } | |
654 | ||
655 | static bool | |
656 | gomp_loop_dynamic_next (long *istart, long *iend) | |
657 | { | |
658 | bool ret; | |
659 | ||
660 | #ifdef HAVE_SYNC_BUILTINS | |
661 | ret = gomp_iter_dynamic_next (istart, iend); | |
662 | #else | |
663 | struct gomp_thread *thr = gomp_thread (); | |
664 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
665 | ret = gomp_iter_dynamic_next_locked (istart, iend); | |
666 | gomp_mutex_unlock (&thr->ts.work_share->lock); | |
667 | #endif | |
668 | ||
669 | return ret; | |
670 | } | |
671 | ||
672 | static bool | |
673 | gomp_loop_guided_next (long *istart, long *iend) | |
674 | { | |
675 | bool ret; | |
676 | ||
677 | #ifdef HAVE_SYNC_BUILTINS | |
678 | ret = gomp_iter_guided_next (istart, iend); | |
679 | #else | |
680 | struct gomp_thread *thr = gomp_thread (); | |
681 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
682 | ret = gomp_iter_guided_next_locked (istart, iend); | |
683 | gomp_mutex_unlock (&thr->ts.work_share->lock); | |
684 | #endif | |
685 | ||
686 | return ret; | |
687 | } | |
688 | ||
689 | bool | |
690 | GOMP_loop_runtime_next (long *istart, long *iend) | |
691 | { | |
692 | struct gomp_thread *thr = gomp_thread (); | |
28567c40 | 693 | |
953ff289 DN |
694 | switch (thr->ts.work_share->sched) |
695 | { | |
696 | case GFS_STATIC: | |
a68ab351 | 697 | case GFS_AUTO: |
953ff289 DN |
698 | return gomp_loop_static_next (istart, iend); |
699 | case GFS_DYNAMIC: | |
700 | return gomp_loop_dynamic_next (istart, iend); | |
701 | case GFS_GUIDED: | |
702 | return gomp_loop_guided_next (istart, iend); | |
703 | default: | |
704 | abort (); | |
705 | } | |
706 | } | |
707 | ||
708 | /* The *_ordered_*_next routines are called when the thread completes | |
709 | processing of the iteration block currently assigned to it. | |
710 | ||
711 | Returns true if there is work remaining to be performed; *ISTART and | |
712 | *IEND are filled with a new iteration block. Returns false if all work | |
713 | has been assigned. */ | |
714 | ||
715 | static bool | |
716 | gomp_loop_ordered_static_next (long *istart, long *iend) | |
717 | { | |
718 | struct gomp_thread *thr = gomp_thread (); | |
719 | int test; | |
720 | ||
721 | gomp_ordered_sync (); | |
722 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
723 | test = gomp_iter_static_next (istart, iend); | |
724 | if (test >= 0) | |
725 | gomp_ordered_static_next (); | |
726 | gomp_mutex_unlock (&thr->ts.work_share->lock); | |
727 | ||
728 | return test == 0; | |
729 | } | |
730 | ||
731 | static bool | |
732 | gomp_loop_ordered_dynamic_next (long *istart, long *iend) | |
733 | { | |
734 | struct gomp_thread *thr = gomp_thread (); | |
735 | bool ret; | |
736 | ||
737 | gomp_ordered_sync (); | |
738 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
739 | ret = gomp_iter_dynamic_next_locked (istart, iend); | |
740 | if (ret) | |
741 | gomp_ordered_next (); | |
742 | else | |
743 | gomp_ordered_last (); | |
744 | gomp_mutex_unlock (&thr->ts.work_share->lock); | |
745 | ||
746 | return ret; | |
747 | } | |
748 | ||
749 | static bool | |
750 | gomp_loop_ordered_guided_next (long *istart, long *iend) | |
751 | { | |
752 | struct gomp_thread *thr = gomp_thread (); | |
753 | bool ret; | |
754 | ||
755 | gomp_ordered_sync (); | |
756 | gomp_mutex_lock (&thr->ts.work_share->lock); | |
757 | ret = gomp_iter_guided_next_locked (istart, iend); | |
758 | if (ret) | |
759 | gomp_ordered_next (); | |
760 | else | |
761 | gomp_ordered_last (); | |
762 | gomp_mutex_unlock (&thr->ts.work_share->lock); | |
763 | ||
764 | return ret; | |
765 | } | |
766 | ||
767 | bool | |
768 | GOMP_loop_ordered_runtime_next (long *istart, long *iend) | |
769 | { | |
770 | struct gomp_thread *thr = gomp_thread (); | |
28567c40 | 771 | |
953ff289 DN |
772 | switch (thr->ts.work_share->sched) |
773 | { | |
774 | case GFS_STATIC: | |
a68ab351 | 775 | case GFS_AUTO: |
953ff289 DN |
776 | return gomp_loop_ordered_static_next (istart, iend); |
777 | case GFS_DYNAMIC: | |
778 | return gomp_loop_ordered_dynamic_next (istart, iend); | |
779 | case GFS_GUIDED: | |
780 | return gomp_loop_ordered_guided_next (istart, iend); | |
781 | default: | |
782 | abort (); | |
783 | } | |
784 | } | |
785 | ||
786 | /* The GOMP_parallel_loop_* routines pre-initialize a work-share construct | |
787 | to avoid one synchronization once we get into the loop. */ | |
788 | ||
789 | static void | |
790 | gomp_parallel_loop_start (void (*fn) (void *), void *data, | |
791 | unsigned num_threads, long start, long end, | |
792 | long incr, enum gomp_schedule_type sched, | |
acf0174b | 793 | long chunk_size, unsigned int flags) |
953ff289 | 794 | { |
a68ab351 | 795 | struct gomp_team *team; |
953ff289 | 796 | |
a68ab351 JJ |
797 | num_threads = gomp_resolve_num_threads (num_threads, 0); |
798 | team = gomp_new_team (num_threads); | |
799 | gomp_loop_init (&team->work_shares[0], start, end, incr, sched, chunk_size); | |
28567c40 | 800 | gomp_team_start (fn, data, num_threads, flags, team, NULL); |
953ff289 DN |
801 | } |
802 | ||
803 | void | |
804 | GOMP_parallel_loop_static_start (void (*fn) (void *), void *data, | |
805 | unsigned num_threads, long start, long end, | |
806 | long incr, long chunk_size) | |
807 | { | |
808 | gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, | |
acf0174b | 809 | GFS_STATIC, chunk_size, 0); |
953ff289 DN |
810 | } |
811 | ||
812 | void | |
813 | GOMP_parallel_loop_dynamic_start (void (*fn) (void *), void *data, | |
814 | unsigned num_threads, long start, long end, | |
815 | long incr, long chunk_size) | |
816 | { | |
817 | gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, | |
acf0174b | 818 | GFS_DYNAMIC, chunk_size, 0); |
953ff289 DN |
819 | } |
820 | ||
821 | void | |
822 | GOMP_parallel_loop_guided_start (void (*fn) (void *), void *data, | |
823 | unsigned num_threads, long start, long end, | |
824 | long incr, long chunk_size) | |
825 | { | |
826 | gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, | |
acf0174b | 827 | GFS_GUIDED, chunk_size, 0); |
953ff289 DN |
828 | } |
829 | ||
830 | void | |
831 | GOMP_parallel_loop_runtime_start (void (*fn) (void *), void *data, | |
832 | unsigned num_threads, long start, long end, | |
833 | long incr) | |
834 | { | |
a68ab351 | 835 | struct gomp_task_icv *icv = gomp_icv (false); |
953ff289 | 836 | gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, |
28567c40 JJ |
837 | icv->run_sched_var & ~GFS_MONOTONIC, |
838 | icv->run_sched_chunk_size, 0); | |
acf0174b JJ |
839 | } |
840 | ||
841 | ialias_redirect (GOMP_parallel_end) | |
842 | ||
843 | void | |
844 | GOMP_parallel_loop_static (void (*fn) (void *), void *data, | |
845 | unsigned num_threads, long start, long end, | |
846 | long incr, long chunk_size, unsigned flags) | |
847 | { | |
848 | gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, | |
849 | GFS_STATIC, chunk_size, flags); | |
850 | fn (data); | |
851 | GOMP_parallel_end (); | |
852 | } | |
853 | ||
854 | void | |
855 | GOMP_parallel_loop_dynamic (void (*fn) (void *), void *data, | |
856 | unsigned num_threads, long start, long end, | |
857 | long incr, long chunk_size, unsigned flags) | |
858 | { | |
859 | gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, | |
860 | GFS_DYNAMIC, chunk_size, flags); | |
861 | fn (data); | |
862 | GOMP_parallel_end (); | |
863 | } | |
864 | ||
865 | void | |
866 | GOMP_parallel_loop_guided (void (*fn) (void *), void *data, | |
867 | unsigned num_threads, long start, long end, | |
868 | long incr, long chunk_size, unsigned flags) | |
869 | { | |
870 | gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, | |
871 | GFS_GUIDED, chunk_size, flags); | |
872 | fn (data); | |
873 | GOMP_parallel_end (); | |
874 | } | |
875 | ||
28567c40 JJ |
876 | void |
877 | GOMP_parallel_loop_runtime (void (*fn) (void *), void *data, | |
878 | unsigned num_threads, long start, long end, | |
879 | long incr, unsigned flags) | |
880 | { | |
881 | struct gomp_task_icv *icv = gomp_icv (false); | |
882 | gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, | |
883 | icv->run_sched_var & ~GFS_MONOTONIC, | |
884 | icv->run_sched_chunk_size, flags); | |
885 | fn (data); | |
886 | GOMP_parallel_end (); | |
887 | } | |
888 | ||
e01d41e5 JJ |
889 | #ifdef HAVE_ATTRIBUTE_ALIAS |
890 | extern __typeof(GOMP_parallel_loop_dynamic) GOMP_parallel_loop_nonmonotonic_dynamic | |
891 | __attribute__((alias ("GOMP_parallel_loop_dynamic"))); | |
892 | extern __typeof(GOMP_parallel_loop_guided) GOMP_parallel_loop_nonmonotonic_guided | |
893 | __attribute__((alias ("GOMP_parallel_loop_guided"))); | |
28567c40 JJ |
894 | extern __typeof(GOMP_parallel_loop_runtime) GOMP_parallel_loop_nonmonotonic_runtime |
895 | __attribute__((alias ("GOMP_parallel_loop_runtime"))); | |
896 | extern __typeof(GOMP_parallel_loop_runtime) GOMP_parallel_loop_maybe_nonmonotonic_runtime | |
897 | __attribute__((alias ("GOMP_parallel_loop_runtime"))); | |
e01d41e5 JJ |
898 | #else |
899 | void | |
900 | GOMP_parallel_loop_nonmonotonic_dynamic (void (*fn) (void *), void *data, | |
901 | unsigned num_threads, long start, | |
902 | long end, long incr, long chunk_size, | |
903 | unsigned flags) | |
904 | { | |
905 | gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, | |
906 | GFS_DYNAMIC, chunk_size, flags); | |
907 | fn (data); | |
908 | GOMP_parallel_end (); | |
909 | } | |
910 | ||
911 | void | |
912 | GOMP_parallel_loop_nonmonotonic_guided (void (*fn) (void *), void *data, | |
913 | unsigned num_threads, long start, | |
914 | long end, long incr, long chunk_size, | |
915 | unsigned flags) | |
916 | { | |
917 | gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, | |
918 | GFS_GUIDED, chunk_size, flags); | |
919 | fn (data); | |
920 | GOMP_parallel_end (); | |
921 | } | |
e01d41e5 | 922 | |
acf0174b | 923 | void |
28567c40 JJ |
924 | GOMP_parallel_loop_nonmonotonic_runtime (void (*fn) (void *), void *data, |
925 | unsigned num_threads, long start, | |
926 | long end, long incr, unsigned flags) | |
acf0174b JJ |
927 | { |
928 | struct gomp_task_icv *icv = gomp_icv (false); | |
929 | gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, | |
28567c40 JJ |
930 | icv->run_sched_var & ~GFS_MONOTONIC, |
931 | icv->run_sched_chunk_size, flags); | |
acf0174b JJ |
932 | fn (data); |
933 | GOMP_parallel_end (); | |
953ff289 DN |
934 | } |
935 | ||
28567c40 JJ |
936 | void |
937 | GOMP_parallel_loop_maybe_nonmonotonic_runtime (void (*fn) (void *), void *data, | |
938 | unsigned num_threads, long start, | |
939 | long end, long incr, | |
940 | unsigned flags) | |
941 | { | |
942 | struct gomp_task_icv *icv = gomp_icv (false); | |
943 | gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, | |
944 | icv->run_sched_var & ~GFS_MONOTONIC, | |
945 | icv->run_sched_chunk_size, flags); | |
946 | fn (data); | |
947 | GOMP_parallel_end (); | |
948 | } | |
949 | #endif | |
950 | ||
953ff289 | 951 | /* The GOMP_loop_end* routines are called after the thread is told that |
acf0174b | 952 | all loop iterations are complete. The first two versions synchronize |
953ff289 DN |
953 | all threads; the nowait version does not. */ |
954 | ||
955 | void | |
956 | GOMP_loop_end (void) | |
957 | { | |
958 | gomp_work_share_end (); | |
959 | } | |
960 | ||
acf0174b JJ |
961 | bool |
962 | GOMP_loop_end_cancel (void) | |
963 | { | |
964 | return gomp_work_share_end_cancel (); | |
965 | } | |
966 | ||
953ff289 DN |
967 | void |
968 | GOMP_loop_end_nowait (void) | |
969 | { | |
970 | gomp_work_share_end_nowait (); | |
971 | } | |
972 | ||
973 | ||
974 | /* We use static functions above so that we're sure that the "runtime" | |
975 | function can defer to the proper routine without interposition. We | |
976 | export the static function with a strong alias when possible, or with | |
977 | a wrapper function otherwise. */ | |
978 | ||
979 | #ifdef HAVE_ATTRIBUTE_ALIAS | |
980 | extern __typeof(gomp_loop_static_start) GOMP_loop_static_start | |
981 | __attribute__((alias ("gomp_loop_static_start"))); | |
982 | extern __typeof(gomp_loop_dynamic_start) GOMP_loop_dynamic_start | |
983 | __attribute__((alias ("gomp_loop_dynamic_start"))); | |
984 | extern __typeof(gomp_loop_guided_start) GOMP_loop_guided_start | |
985 | __attribute__((alias ("gomp_loop_guided_start"))); | |
e01d41e5 JJ |
986 | extern __typeof(gomp_loop_dynamic_start) GOMP_loop_nonmonotonic_dynamic_start |
987 | __attribute__((alias ("gomp_loop_dynamic_start"))); | |
988 | extern __typeof(gomp_loop_guided_start) GOMP_loop_nonmonotonic_guided_start | |
989 | __attribute__((alias ("gomp_loop_guided_start"))); | |
28567c40 JJ |
990 | extern __typeof(GOMP_loop_runtime_start) GOMP_loop_nonmonotonic_runtime_start |
991 | __attribute__((alias ("GOMP_loop_runtime_start"))); | |
992 | extern __typeof(GOMP_loop_runtime_start) GOMP_loop_maybe_nonmonotonic_runtime_start | |
993 | __attribute__((alias ("GOMP_loop_runtime_start"))); | |
953ff289 DN |
994 | |
995 | extern __typeof(gomp_loop_ordered_static_start) GOMP_loop_ordered_static_start | |
996 | __attribute__((alias ("gomp_loop_ordered_static_start"))); | |
997 | extern __typeof(gomp_loop_ordered_dynamic_start) GOMP_loop_ordered_dynamic_start | |
998 | __attribute__((alias ("gomp_loop_ordered_dynamic_start"))); | |
999 | extern __typeof(gomp_loop_ordered_guided_start) GOMP_loop_ordered_guided_start | |
1000 | __attribute__((alias ("gomp_loop_ordered_guided_start"))); | |
1001 | ||
d9a6bd32 JJ |
1002 | extern __typeof(gomp_loop_doacross_static_start) GOMP_loop_doacross_static_start |
1003 | __attribute__((alias ("gomp_loop_doacross_static_start"))); | |
1004 | extern __typeof(gomp_loop_doacross_dynamic_start) GOMP_loop_doacross_dynamic_start | |
1005 | __attribute__((alias ("gomp_loop_doacross_dynamic_start"))); | |
1006 | extern __typeof(gomp_loop_doacross_guided_start) GOMP_loop_doacross_guided_start | |
1007 | __attribute__((alias ("gomp_loop_doacross_guided_start"))); | |
1008 | ||
953ff289 DN |
1009 | extern __typeof(gomp_loop_static_next) GOMP_loop_static_next |
1010 | __attribute__((alias ("gomp_loop_static_next"))); | |
1011 | extern __typeof(gomp_loop_dynamic_next) GOMP_loop_dynamic_next | |
1012 | __attribute__((alias ("gomp_loop_dynamic_next"))); | |
1013 | extern __typeof(gomp_loop_guided_next) GOMP_loop_guided_next | |
1014 | __attribute__((alias ("gomp_loop_guided_next"))); | |
e01d41e5 JJ |
1015 | extern __typeof(gomp_loop_dynamic_next) GOMP_loop_nonmonotonic_dynamic_next |
1016 | __attribute__((alias ("gomp_loop_dynamic_next"))); | |
1017 | extern __typeof(gomp_loop_guided_next) GOMP_loop_nonmonotonic_guided_next | |
1018 | __attribute__((alias ("gomp_loop_guided_next"))); | |
28567c40 JJ |
1019 | extern __typeof(GOMP_loop_runtime_next) GOMP_loop_nonmonotonic_runtime_next |
1020 | __attribute__((alias ("GOMP_loop_runtime_next"))); | |
1021 | extern __typeof(GOMP_loop_runtime_next) GOMP_loop_maybe_nonmonotonic_runtime_next | |
1022 | __attribute__((alias ("GOMP_loop_runtime_next"))); | |
953ff289 DN |
1023 | |
1024 | extern __typeof(gomp_loop_ordered_static_next) GOMP_loop_ordered_static_next | |
1025 | __attribute__((alias ("gomp_loop_ordered_static_next"))); | |
1026 | extern __typeof(gomp_loop_ordered_dynamic_next) GOMP_loop_ordered_dynamic_next | |
1027 | __attribute__((alias ("gomp_loop_ordered_dynamic_next"))); | |
1028 | extern __typeof(gomp_loop_ordered_guided_next) GOMP_loop_ordered_guided_next | |
1029 | __attribute__((alias ("gomp_loop_ordered_guided_next"))); | |
1030 | #else | |
1031 | bool | |
1032 | GOMP_loop_static_start (long start, long end, long incr, long chunk_size, | |
1033 | long *istart, long *iend) | |
1034 | { | |
1035 | return gomp_loop_static_start (start, end, incr, chunk_size, istart, iend); | |
1036 | } | |
1037 | ||
1038 | bool | |
1039 | GOMP_loop_dynamic_start (long start, long end, long incr, long chunk_size, | |
1040 | long *istart, long *iend) | |
1041 | { | |
1042 | return gomp_loop_dynamic_start (start, end, incr, chunk_size, istart, iend); | |
1043 | } | |
1044 | ||
1045 | bool | |
1046 | GOMP_loop_guided_start (long start, long end, long incr, long chunk_size, | |
1047 | long *istart, long *iend) | |
1048 | { | |
1049 | return gomp_loop_guided_start (start, end, incr, chunk_size, istart, iend); | |
1050 | } | |
1051 | ||
e01d41e5 JJ |
1052 | bool |
1053 | GOMP_loop_nonmonotonic_dynamic_start (long start, long end, long incr, | |
1054 | long chunk_size, long *istart, | |
1055 | long *iend) | |
1056 | { | |
1057 | return gomp_loop_dynamic_start (start, end, incr, chunk_size, istart, iend); | |
1058 | } | |
1059 | ||
1060 | bool | |
1061 | GOMP_loop_nonmonotonic_guided_start (long start, long end, long incr, | |
1062 | long chunk_size, long *istart, long *iend) | |
1063 | { | |
1064 | return gomp_loop_guided_start (start, end, incr, chunk_size, istart, iend); | |
1065 | } | |
1066 | ||
28567c40 JJ |
1067 | bool |
1068 | GOMP_loop_nonmonotonic_runtime_start (long start, long end, long incr, | |
1069 | long *istart, long *iend) | |
1070 | { | |
1071 | return GOMP_loop_runtime_start (start, end, incr, istart, iend); | |
1072 | } | |
1073 | ||
1074 | bool | |
1075 | GOMP_loop_maybe_nonmonotonic_runtime_start (long start, long end, long incr, | |
1076 | long *istart, long *iend) | |
1077 | { | |
1078 | return GOMP_loop_runtime_start (start, end, incr, istart, iend); | |
1079 | } | |
1080 | ||
953ff289 DN |
1081 | bool |
1082 | GOMP_loop_ordered_static_start (long start, long end, long incr, | |
1083 | long chunk_size, long *istart, long *iend) | |
1084 | { | |
1085 | return gomp_loop_ordered_static_start (start, end, incr, chunk_size, | |
1086 | istart, iend); | |
1087 | } | |
1088 | ||
1089 | bool | |
1090 | GOMP_loop_ordered_dynamic_start (long start, long end, long incr, | |
1091 | long chunk_size, long *istart, long *iend) | |
1092 | { | |
1093 | return gomp_loop_ordered_dynamic_start (start, end, incr, chunk_size, | |
1094 | istart, iend); | |
1095 | } | |
1096 | ||
1097 | bool | |
1098 | GOMP_loop_ordered_guided_start (long start, long end, long incr, | |
1099 | long chunk_size, long *istart, long *iend) | |
1100 | { | |
1101 | return gomp_loop_ordered_guided_start (start, end, incr, chunk_size, | |
1102 | istart, iend); | |
1103 | } | |
1104 | ||
d9a6bd32 JJ |
1105 | bool |
1106 | GOMP_loop_doacross_static_start (unsigned ncounts, long *counts, | |
1107 | long chunk_size, long *istart, long *iend) | |
1108 | { | |
1109 | return gomp_loop_doacross_static_start (ncounts, counts, chunk_size, | |
1110 | istart, iend); | |
1111 | } | |
1112 | ||
1113 | bool | |
1114 | GOMP_loop_doacross_dynamic_start (unsigned ncounts, long *counts, | |
1115 | long chunk_size, long *istart, long *iend) | |
1116 | { | |
1117 | return gomp_loop_doacross_dynamic_start (ncounts, counts, chunk_size, | |
1118 | istart, iend); | |
1119 | } | |
1120 | ||
1121 | bool | |
1122 | GOMP_loop_doacross_guided_start (unsigned ncounts, long *counts, | |
1123 | long chunk_size, long *istart, long *iend) | |
1124 | { | |
1125 | return gomp_loop_doacross_guided_start (ncounts, counts, chunk_size, | |
1126 | istart, iend); | |
1127 | } | |
1128 | ||
953ff289 DN |
1129 | bool |
1130 | GOMP_loop_static_next (long *istart, long *iend) | |
1131 | { | |
1132 | return gomp_loop_static_next (istart, iend); | |
1133 | } | |
1134 | ||
1135 | bool | |
1136 | GOMP_loop_dynamic_next (long *istart, long *iend) | |
1137 | { | |
1138 | return gomp_loop_dynamic_next (istart, iend); | |
1139 | } | |
1140 | ||
1141 | bool | |
1142 | GOMP_loop_guided_next (long *istart, long *iend) | |
1143 | { | |
1144 | return gomp_loop_guided_next (istart, iend); | |
1145 | } | |
1146 | ||
e01d41e5 JJ |
1147 | bool |
1148 | GOMP_loop_nonmonotonic_dynamic_next (long *istart, long *iend) | |
1149 | { | |
1150 | return gomp_loop_dynamic_next (istart, iend); | |
1151 | } | |
1152 | ||
1153 | bool | |
1154 | GOMP_loop_nonmonotonic_guided_next (long *istart, long *iend) | |
1155 | { | |
1156 | return gomp_loop_guided_next (istart, iend); | |
1157 | } | |
1158 | ||
28567c40 JJ |
1159 | bool |
1160 | GOMP_loop_nonmonotonic_runtime_next (long *istart, long *iend) | |
1161 | { | |
1162 | return GOMP_loop_runtime_next (istart, iend); | |
1163 | } | |
1164 | ||
1165 | bool | |
1166 | GOMP_loop_maybe_nonmonotonic_runtime_next (long *istart, long *iend) | |
1167 | { | |
1168 | return GOMP_loop_runtime_next (istart, iend); | |
1169 | } | |
1170 | ||
953ff289 DN |
1171 | bool |
1172 | GOMP_loop_ordered_static_next (long *istart, long *iend) | |
1173 | { | |
1174 | return gomp_loop_ordered_static_next (istart, iend); | |
1175 | } | |
1176 | ||
1177 | bool | |
1178 | GOMP_loop_ordered_dynamic_next (long *istart, long *iend) | |
1179 | { | |
1180 | return gomp_loop_ordered_dynamic_next (istart, iend); | |
1181 | } | |
1182 | ||
1183 | bool | |
1184 | GOMP_loop_ordered_guided_next (long *istart, long *iend) | |
1185 | { | |
1186 | return gomp_loop_ordered_guided_next (istart, iend); | |
1187 | } | |
1188 | #endif |