comparison libgomp/loop.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
1 /* Copyright (C) 2005-2018 Free Software Foundation, Inc. 1 /* Copyright (C) 2005-2020 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>. 2 Contributed by Richard Henderson <rth@redhat.com>.
3 3
4 This file is part of the GNU Offloading and Multi Processing Library 4 This file is part of the GNU Offloading and Multi Processing Library
5 (libgomp). 5 (libgomp).
6 6
25 25
26 /* This file handles the LOOP (FOR/DO) construct. */ 26 /* This file handles the LOOP (FOR/DO) construct. */
27 27
28 #include <limits.h> 28 #include <limits.h>
29 #include <stdlib.h> 29 #include <stdlib.h>
30 #include <string.h>
30 #include "libgomp.h" 31 #include "libgomp.h"
31 32
33
34 ialias (GOMP_loop_runtime_next)
35 ialias_redirect (GOMP_taskgroup_reduction_register)
32 36
33 /* Initialize the given work share construct from the given arguments. */ 37 /* Initialize the given work share construct from the given arguments. */
34 38
35 static inline void 39 static inline void
36 gomp_loop_init (struct gomp_work_share *ws, long start, long end, long incr, 40 gomp_loop_init (struct gomp_work_share *ws, long start, long end, long incr,
77 #endif 81 #endif
78 } 82 }
79 } 83 }
80 84
81 /* The *_start routines are called when first encountering a loop construct 85 /* The *_start routines are called when first encountering a loop construct
82 that is not bound directly to a parallel construct. The first thread 86 that is not bound directly to a parallel construct. The first thread
83 that arrives will create the work-share construct; subsequent threads 87 that arrives will create the work-share construct; subsequent threads
84 will see the construct exists and allocate work from it. 88 will see the construct exists and allocate work from it.
85 89
86 START, END, INCR are the bounds of the loop; due to the restrictions of 90 START, END, INCR are the bounds of the loop; due to the restrictions of
87 OpenMP, these values must be the same in every thread. This is not 91 OpenMP, these values must be the same in every thread. This is not
88 verified (nor is it entirely verifiable, since START is not necessarily 92 verified (nor is it entirely verifiable, since START is not necessarily
89 retained intact in the work-share data structure). CHUNK_SIZE is the 93 retained intact in the work-share data structure). CHUNK_SIZE is the
90 scheduling parameter; again this must be identical in all threads. 94 scheduling parameter; again this must be identical in all threads.
91 95
92 Returns true if there's any work for this thread to perform. If so, 96 Returns true if there's any work for this thread to perform. If so,
99 long *istart, long *iend) 103 long *istart, long *iend)
100 { 104 {
101 struct gomp_thread *thr = gomp_thread (); 105 struct gomp_thread *thr = gomp_thread ();
102 106
103 thr->ts.static_trip = 0; 107 thr->ts.static_trip = 0;
104 if (gomp_work_share_start (false)) 108 if (gomp_work_share_start (0))
105 { 109 {
106 gomp_loop_init (thr->ts.work_share, start, end, incr, 110 gomp_loop_init (thr->ts.work_share, start, end, incr,
107 GFS_STATIC, chunk_size); 111 GFS_STATIC, chunk_size);
108 gomp_work_share_init_done (); 112 gomp_work_share_init_done ();
109 } 113 }
121 long *istart, long *iend) 125 long *istart, long *iend)
122 { 126 {
123 struct gomp_thread *thr = gomp_thread (); 127 struct gomp_thread *thr = gomp_thread ();
124 bool ret; 128 bool ret;
125 129
126 if (gomp_work_share_start (false)) 130 if (gomp_work_share_start (0))
127 { 131 {
128 gomp_loop_init (thr->ts.work_share, start, end, incr, 132 gomp_loop_init (thr->ts.work_share, start, end, incr,
129 GFS_DYNAMIC, chunk_size); 133 GFS_DYNAMIC, chunk_size);
130 gomp_work_share_init_done (); 134 gomp_work_share_init_done ();
131 } 135 }
149 long *istart, long *iend) 153 long *istart, long *iend)
150 { 154 {
151 struct gomp_thread *thr = gomp_thread (); 155 struct gomp_thread *thr = gomp_thread ();
152 bool ret; 156 bool ret;
153 157
154 if (gomp_work_share_start (false)) 158 if (gomp_work_share_start (0))
155 { 159 {
156 gomp_loop_init (thr->ts.work_share, start, end, incr, 160 gomp_loop_init (thr->ts.work_share, start, end, incr,
157 GFS_GUIDED, chunk_size); 161 GFS_GUIDED, chunk_size);
158 gomp_work_share_init_done (); 162 gomp_work_share_init_done ();
159 } 163 }
172 bool 176 bool
173 GOMP_loop_runtime_start (long start, long end, long incr, 177 GOMP_loop_runtime_start (long start, long end, long incr,
174 long *istart, long *iend) 178 long *istart, long *iend)
175 { 179 {
176 struct gomp_task_icv *icv = gomp_icv (false); 180 struct gomp_task_icv *icv = gomp_icv (false);
177 switch (icv->run_sched_var) 181 switch (icv->run_sched_var & ~GFS_MONOTONIC)
178 { 182 {
179 case GFS_STATIC: 183 case GFS_STATIC:
180 return gomp_loop_static_start (start, end, incr, 184 return gomp_loop_static_start (start, end, incr,
181 icv->run_sched_chunk_size, 185 icv->run_sched_chunk_size,
182 istart, iend); 186 istart, iend);
195 default: 199 default:
196 abort (); 200 abort ();
197 } 201 }
198 } 202 }
199 203
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;
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))
273 if (size > (sizeof (struct gomp_work_share)
274 - INLINE_ORDERED_TEAM_IDS_OFF))
275 *mem
276 = (void *) (thr->ts.work_share->ordered_team_ids
277 = gomp_malloc_cleared (size));
278 else
279 *mem = memset (((char *) thr->ts.work_share)
280 + INLINE_ORDERED_TEAM_IDS_OFF, '\0', size);
281 }
282 gomp_work_share_init_done ();
283 }
284 else
285 {
286 if (reductions)
287 {
288 uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
289 gomp_workshare_task_reduction_register (reductions,
290 first_reductions);
291 }
292 if (mem)
293 {
294 if ((offsetof (struct gomp_work_share, inline_ordered_team_ids)
295 & (__alignof__ (long long) - 1)) == 0)
296 *mem = (void *) thr->ts.work_share->ordered_team_ids;
297 else
298 {
299 uintptr_t p = (uintptr_t) thr->ts.work_share->ordered_team_ids;
300 p += __alignof__ (long long) - 1;
301 p &= ~(__alignof__ (long long) - 1);
302 *mem = (void *) p;
303 }
304 }
305 }
306
307 if (!istart)
308 return true;
309 return ialias_call (GOMP_loop_runtime_next) (istart, iend);
310 }
311
200 /* The *_ordered_*_start routines are similar. The only difference is that 312 /* The *_ordered_*_start routines are similar. The only difference is that
201 this work-share construct is initialized to expect an ORDERED section. */ 313 this work-share construct is initialized to expect an ORDERED section. */
202 314
203 static bool 315 static bool
204 gomp_loop_ordered_static_start (long start, long end, long incr, 316 gomp_loop_ordered_static_start (long start, long end, long incr,
205 long chunk_size, long *istart, long *iend) 317 long chunk_size, long *istart, long *iend)
206 { 318 {
207 struct gomp_thread *thr = gomp_thread (); 319 struct gomp_thread *thr = gomp_thread ();
208 320
209 thr->ts.static_trip = 0; 321 thr->ts.static_trip = 0;
210 if (gomp_work_share_start (true)) 322 if (gomp_work_share_start (1))
211 { 323 {
212 gomp_loop_init (thr->ts.work_share, start, end, incr, 324 gomp_loop_init (thr->ts.work_share, start, end, incr,
213 GFS_STATIC, chunk_size); 325 GFS_STATIC, chunk_size);
214 gomp_ordered_static_init (); 326 gomp_ordered_static_init ();
215 gomp_work_share_init_done (); 327 gomp_work_share_init_done ();
223 long chunk_size, long *istart, long *iend) 335 long chunk_size, long *istart, long *iend)
224 { 336 {
225 struct gomp_thread *thr = gomp_thread (); 337 struct gomp_thread *thr = gomp_thread ();
226 bool ret; 338 bool ret;
227 339
228 if (gomp_work_share_start (true)) 340 if (gomp_work_share_start (1))
229 { 341 {
230 gomp_loop_init (thr->ts.work_share, start, end, incr, 342 gomp_loop_init (thr->ts.work_share, start, end, incr,
231 GFS_DYNAMIC, chunk_size); 343 GFS_DYNAMIC, chunk_size);
232 gomp_mutex_lock (&thr->ts.work_share->lock); 344 gomp_mutex_lock (&thr->ts.work_share->lock);
233 gomp_work_share_init_done (); 345 gomp_work_share_init_done ();
248 long chunk_size, long *istart, long *iend) 360 long chunk_size, long *istart, long *iend)
249 { 361 {
250 struct gomp_thread *thr = gomp_thread (); 362 struct gomp_thread *thr = gomp_thread ();
251 bool ret; 363 bool ret;
252 364
253 if (gomp_work_share_start (true)) 365 if (gomp_work_share_start (1))
254 { 366 {
255 gomp_loop_init (thr->ts.work_share, start, end, incr, 367 gomp_loop_init (thr->ts.work_share, start, end, incr,
256 GFS_GUIDED, chunk_size); 368 GFS_GUIDED, chunk_size);
257 gomp_mutex_lock (&thr->ts.work_share->lock); 369 gomp_mutex_lock (&thr->ts.work_share->lock);
258 gomp_work_share_init_done (); 370 gomp_work_share_init_done ();
271 bool 383 bool
272 GOMP_loop_ordered_runtime_start (long start, long end, long incr, 384 GOMP_loop_ordered_runtime_start (long start, long end, long incr,
273 long *istart, long *iend) 385 long *istart, long *iend)
274 { 386 {
275 struct gomp_task_icv *icv = gomp_icv (false); 387 struct gomp_task_icv *icv = gomp_icv (false);
276 switch (icv->run_sched_var) 388 switch (icv->run_sched_var & ~GFS_MONOTONIC)
277 { 389 {
278 case GFS_STATIC: 390 case GFS_STATIC:
279 return gomp_loop_ordered_static_start (start, end, incr, 391 return gomp_loop_ordered_static_start (start, end, incr,
280 icv->run_sched_chunk_size, 392 icv->run_sched_chunk_size,
281 istart, iend); 393 istart, iend);
295 default: 407 default:
296 abort (); 408 abort ();
297 } 409 }
298 } 410 }
299 411
412 bool
413 GOMP_loop_ordered_start (long start, long end, long incr, long sched,
414 long chunk_size, long *istart, long *iend,
415 uintptr_t *reductions, void **mem)
416 {
417 struct gomp_thread *thr = gomp_thread ();
418 size_t ordered = 1;
419 bool ret;
420
421 thr->ts.static_trip = 0;
422 if (reductions)
423 gomp_workshare_taskgroup_start ();
424 if (mem)
425 ordered += (uintptr_t) *mem;
426 if (gomp_work_share_start (ordered))
427 {
428 sched = gomp_adjust_sched (sched, &chunk_size);
429 gomp_loop_init (thr->ts.work_share, start, end, incr,
430 sched, chunk_size);
431 if (reductions)
432 {
433 GOMP_taskgroup_reduction_register (reductions);
434 thr->task->taskgroup->workshare = true;
435 thr->ts.work_share->task_reductions = reductions;
436 }
437 if (sched == GFS_STATIC)
438 gomp_ordered_static_init ();
439 else
440 gomp_mutex_lock (&thr->ts.work_share->lock);
441 gomp_work_share_init_done ();
442 }
443 else
444 {
445 if (reductions)
446 {
447 uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
448 gomp_workshare_task_reduction_register (reductions,
449 first_reductions);
450 }
451 sched = thr->ts.work_share->sched;
452 if (sched != GFS_STATIC)
453 gomp_mutex_lock (&thr->ts.work_share->lock);
454 }
455
456 if (mem)
457 {
458 uintptr_t p
459 = (uintptr_t) (thr->ts.work_share->ordered_team_ids
460 + (thr->ts.team ? thr->ts.team->nthreads : 1));
461 p += __alignof__ (long long) - 1;
462 p &= ~(__alignof__ (long long) - 1);
463 *mem = (void *) p;
464 }
465
466 switch (sched)
467 {
468 case GFS_STATIC:
469 case GFS_AUTO:
470 return !gomp_iter_static_next (istart, iend);
471 case GFS_DYNAMIC:
472 ret = gomp_iter_dynamic_next_locked (istart, iend);
473 break;
474 case GFS_GUIDED:
475 ret = gomp_iter_guided_next_locked (istart, iend);
476 break;
477 default:
478 abort ();
479 }
480
481 if (ret)
482 gomp_ordered_first ();
483 gomp_mutex_unlock (&thr->ts.work_share->lock);
484 return ret;
485 }
486
300 /* The *_doacross_*_start routines are similar. The only difference is that 487 /* The *_doacross_*_start routines are similar. The only difference is that
301 this work-share construct is initialized to expect an ORDERED(N) - DOACROSS 488 this work-share construct is initialized to expect an ORDERED(N) - DOACROSS
302 section, and the worksharing loop iterates always from 0 to COUNTS[0] - 1 489 section, and the worksharing loop iterates always from 0 to COUNTS[0] - 1
303 and other COUNTS array elements tell the library number of iterations 490 and other COUNTS array elements tell the library number of iterations
304 in the ordered inner loops. */ 491 in the ordered inner loops. */
308 long chunk_size, long *istart, long *iend) 495 long chunk_size, long *istart, long *iend)
309 { 496 {
310 struct gomp_thread *thr = gomp_thread (); 497 struct gomp_thread *thr = gomp_thread ();
311 498
312 thr->ts.static_trip = 0; 499 thr->ts.static_trip = 0;
313 if (gomp_work_share_start (false)) 500 if (gomp_work_share_start (0))
314 { 501 {
315 gomp_loop_init (thr->ts.work_share, 0, counts[0], 1, 502 gomp_loop_init (thr->ts.work_share, 0, counts[0], 1,
316 GFS_STATIC, chunk_size); 503 GFS_STATIC, chunk_size);
317 gomp_doacross_init (ncounts, counts, chunk_size); 504 gomp_doacross_init (ncounts, counts, chunk_size, 0);
318 gomp_work_share_init_done (); 505 gomp_work_share_init_done ();
319 } 506 }
320 507
321 return !gomp_iter_static_next (istart, iend); 508 return !gomp_iter_static_next (istart, iend);
322 } 509 }
326 long chunk_size, long *istart, long *iend) 513 long chunk_size, long *istart, long *iend)
327 { 514 {
328 struct gomp_thread *thr = gomp_thread (); 515 struct gomp_thread *thr = gomp_thread ();
329 bool ret; 516 bool ret;
330 517
331 if (gomp_work_share_start (false)) 518 if (gomp_work_share_start (0))
332 { 519 {
333 gomp_loop_init (thr->ts.work_share, 0, counts[0], 1, 520 gomp_loop_init (thr->ts.work_share, 0, counts[0], 1,
334 GFS_DYNAMIC, chunk_size); 521 GFS_DYNAMIC, chunk_size);
335 gomp_doacross_init (ncounts, counts, chunk_size); 522 gomp_doacross_init (ncounts, counts, chunk_size, 0);
336 gomp_work_share_init_done (); 523 gomp_work_share_init_done ();
337 } 524 }
338 525
339 #ifdef HAVE_SYNC_BUILTINS 526 #ifdef HAVE_SYNC_BUILTINS
340 ret = gomp_iter_dynamic_next (istart, iend); 527 ret = gomp_iter_dynamic_next (istart, iend);
352 long chunk_size, long *istart, long *iend) 539 long chunk_size, long *istart, long *iend)
353 { 540 {
354 struct gomp_thread *thr = gomp_thread (); 541 struct gomp_thread *thr = gomp_thread ();
355 bool ret; 542 bool ret;
356 543
357 if (gomp_work_share_start (false)) 544 if (gomp_work_share_start (0))
358 { 545 {
359 gomp_loop_init (thr->ts.work_share, 0, counts[0], 1, 546 gomp_loop_init (thr->ts.work_share, 0, counts[0], 1,
360 GFS_GUIDED, chunk_size); 547 GFS_GUIDED, chunk_size);
361 gomp_doacross_init (ncounts, counts, chunk_size); 548 gomp_doacross_init (ncounts, counts, chunk_size, 0);
362 gomp_work_share_init_done (); 549 gomp_work_share_init_done ();
363 } 550 }
364 551
365 #ifdef HAVE_SYNC_BUILTINS 552 #ifdef HAVE_SYNC_BUILTINS
366 ret = gomp_iter_guided_next (istart, iend); 553 ret = gomp_iter_guided_next (istart, iend);
376 bool 563 bool
377 GOMP_loop_doacross_runtime_start (unsigned ncounts, long *counts, 564 GOMP_loop_doacross_runtime_start (unsigned ncounts, long *counts,
378 long *istart, long *iend) 565 long *istart, long *iend)
379 { 566 {
380 struct gomp_task_icv *icv = gomp_icv (false); 567 struct gomp_task_icv *icv = gomp_icv (false);
381 switch (icv->run_sched_var) 568 switch (icv->run_sched_var & ~GFS_MONOTONIC)
382 { 569 {
383 case GFS_STATIC: 570 case GFS_STATIC:
384 return gomp_loop_doacross_static_start (ncounts, counts, 571 return gomp_loop_doacross_static_start (ncounts, counts,
385 icv->run_sched_chunk_size, 572 icv->run_sched_chunk_size,
386 istart, iend); 573 istart, iend);
400 default: 587 default:
401 abort (); 588 abort ();
402 } 589 }
403 } 590 }
404 591
405 /* The *_next routines are called when the thread completes processing of 592 bool
406 the iteration block currently assigned to it. If the work-share 593 GOMP_loop_doacross_start (unsigned ncounts, long *counts, long sched,
594 long chunk_size, long *istart, long *iend,
595 uintptr_t *reductions, void **mem)
596 {
597 struct gomp_thread *thr = gomp_thread ();
598
599 thr->ts.static_trip = 0;
600 if (reductions)
601 gomp_workshare_taskgroup_start ();
602 if (gomp_work_share_start (0))
603 {
604 size_t extra = 0;
605 if (mem)
606 extra = (uintptr_t) *mem;
607 sched = gomp_adjust_sched (sched, &chunk_size);
608 gomp_loop_init (thr->ts.work_share, 0, counts[0], 1,
609 sched, chunk_size);
610 gomp_doacross_init (ncounts, counts, chunk_size, extra);
611 if (reductions)
612 {
613 GOMP_taskgroup_reduction_register (reductions);
614 thr->task->taskgroup->workshare = true;
615 thr->ts.work_share->task_reductions = reductions;
616 }
617 gomp_work_share_init_done ();
618 }
619 else
620 {
621 if (reductions)
622 {
623 uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
624 gomp_workshare_task_reduction_register (reductions,
625 first_reductions);
626 }
627 sched = thr->ts.work_share->sched;
628 }
629
630 if (mem)
631 *mem = thr->ts.work_share->doacross->extra;
632
633 return ialias_call (GOMP_loop_runtime_next) (istart, iend);
634 }
635
636 /* The *_next routines are called when the thread completes processing of
637 the iteration block currently assigned to it. If the work-share
407 construct is bound directly to a parallel construct, then the iteration 638 construct is bound directly to a parallel construct, then the iteration
408 bounds may have been set up before the parallel. In which case, this 639 bounds may have been set up before the parallel. In which case, this
409 may be the first iteration for the thread. 640 may be the first iteration for the thread.
410 641
411 Returns true if there is work remaining to be performed; *ISTART and 642 Returns true if there is work remaining to be performed; *ISTART and
454 685
455 bool 686 bool
456 GOMP_loop_runtime_next (long *istart, long *iend) 687 GOMP_loop_runtime_next (long *istart, long *iend)
457 { 688 {
458 struct gomp_thread *thr = gomp_thread (); 689 struct gomp_thread *thr = gomp_thread ();
459 690
460 switch (thr->ts.work_share->sched) 691 switch (thr->ts.work_share->sched)
461 { 692 {
462 case GFS_STATIC: 693 case GFS_STATIC:
463 case GFS_AUTO: 694 case GFS_AUTO:
464 return gomp_loop_static_next (istart, iend); 695 return gomp_loop_static_next (istart, iend);
532 763
533 bool 764 bool
534 GOMP_loop_ordered_runtime_next (long *istart, long *iend) 765 GOMP_loop_ordered_runtime_next (long *istart, long *iend)
535 { 766 {
536 struct gomp_thread *thr = gomp_thread (); 767 struct gomp_thread *thr = gomp_thread ();
537 768
538 switch (thr->ts.work_share->sched) 769 switch (thr->ts.work_share->sched)
539 { 770 {
540 case GFS_STATIC: 771 case GFS_STATIC:
541 case GFS_AUTO: 772 case GFS_AUTO:
542 return gomp_loop_ordered_static_next (istart, iend); 773 return gomp_loop_ordered_static_next (istart, iend);
561 struct gomp_team *team; 792 struct gomp_team *team;
562 793
563 num_threads = gomp_resolve_num_threads (num_threads, 0); 794 num_threads = gomp_resolve_num_threads (num_threads, 0);
564 team = gomp_new_team (num_threads); 795 team = gomp_new_team (num_threads);
565 gomp_loop_init (&team->work_shares[0], start, end, incr, sched, chunk_size); 796 gomp_loop_init (&team->work_shares[0], start, end, incr, sched, chunk_size);
566 gomp_team_start (fn, data, num_threads, flags, team); 797 gomp_team_start (fn, data, num_threads, flags, team, NULL);
567 } 798 }
568 799
569 void 800 void
570 GOMP_parallel_loop_static_start (void (*fn) (void *), void *data, 801 GOMP_parallel_loop_static_start (void (*fn) (void *), void *data,
571 unsigned num_threads, long start, long end, 802 unsigned num_threads, long start, long end,
598 unsigned num_threads, long start, long end, 829 unsigned num_threads, long start, long end,
599 long incr) 830 long incr)
600 { 831 {
601 struct gomp_task_icv *icv = gomp_icv (false); 832 struct gomp_task_icv *icv = gomp_icv (false);
602 gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, 833 gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
603 icv->run_sched_var, icv->run_sched_chunk_size, 0); 834 icv->run_sched_var & ~GFS_MONOTONIC,
835 icv->run_sched_chunk_size, 0);
604 } 836 }
605 837
606 ialias_redirect (GOMP_parallel_end) 838 ialias_redirect (GOMP_parallel_end)
607 839
608 void 840 void
632 unsigned num_threads, long start, long end, 864 unsigned num_threads, long start, long end,
633 long incr, long chunk_size, unsigned flags) 865 long incr, long chunk_size, unsigned flags)
634 { 866 {
635 gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, 867 gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
636 GFS_GUIDED, chunk_size, flags); 868 GFS_GUIDED, chunk_size, flags);
869 fn (data);
870 GOMP_parallel_end ();
871 }
872
873 void
874 GOMP_parallel_loop_runtime (void (*fn) (void *), void *data,
875 unsigned num_threads, long start, long end,
876 long incr, unsigned flags)
877 {
878 struct gomp_task_icv *icv = gomp_icv (false);
879 gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
880 icv->run_sched_var & ~GFS_MONOTONIC,
881 icv->run_sched_chunk_size, flags);
637 fn (data); 882 fn (data);
638 GOMP_parallel_end (); 883 GOMP_parallel_end ();
639 } 884 }
640 885
641 #ifdef HAVE_ATTRIBUTE_ALIAS 886 #ifdef HAVE_ATTRIBUTE_ALIAS
642 extern __typeof(GOMP_parallel_loop_dynamic) GOMP_parallel_loop_nonmonotonic_dynamic 887 extern __typeof(GOMP_parallel_loop_dynamic) GOMP_parallel_loop_nonmonotonic_dynamic
643 __attribute__((alias ("GOMP_parallel_loop_dynamic"))); 888 __attribute__((alias ("GOMP_parallel_loop_dynamic")));
644 extern __typeof(GOMP_parallel_loop_guided) GOMP_parallel_loop_nonmonotonic_guided 889 extern __typeof(GOMP_parallel_loop_guided) GOMP_parallel_loop_nonmonotonic_guided
645 __attribute__((alias ("GOMP_parallel_loop_guided"))); 890 __attribute__((alias ("GOMP_parallel_loop_guided")));
891 extern __typeof(GOMP_parallel_loop_runtime) GOMP_parallel_loop_nonmonotonic_runtime
892 __attribute__((alias ("GOMP_parallel_loop_runtime")));
893 extern __typeof(GOMP_parallel_loop_runtime) GOMP_parallel_loop_maybe_nonmonotonic_runtime
894 __attribute__((alias ("GOMP_parallel_loop_runtime")));
646 #else 895 #else
647 void 896 void
648 GOMP_parallel_loop_nonmonotonic_dynamic (void (*fn) (void *), void *data, 897 GOMP_parallel_loop_nonmonotonic_dynamic (void (*fn) (void *), void *data,
649 unsigned num_threads, long start, 898 unsigned num_threads, long start,
650 long end, long incr, long chunk_size, 899 long end, long incr, long chunk_size,
665 gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, 914 gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
666 GFS_GUIDED, chunk_size, flags); 915 GFS_GUIDED, chunk_size, flags);
667 fn (data); 916 fn (data);
668 GOMP_parallel_end (); 917 GOMP_parallel_end ();
669 } 918 }
670 #endif 919
671 920 void
672 void 921 GOMP_parallel_loop_nonmonotonic_runtime (void (*fn) (void *), void *data,
673 GOMP_parallel_loop_runtime (void (*fn) (void *), void *data, 922 unsigned num_threads, long start,
674 unsigned num_threads, long start, long end, 923 long end, long incr, unsigned flags)
675 long incr, unsigned flags)
676 { 924 {
677 struct gomp_task_icv *icv = gomp_icv (false); 925 struct gomp_task_icv *icv = gomp_icv (false);
678 gomp_parallel_loop_start (fn, data, num_threads, start, end, incr, 926 gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
679 icv->run_sched_var, icv->run_sched_chunk_size, 927 icv->run_sched_var & ~GFS_MONOTONIC,
680 flags); 928 icv->run_sched_chunk_size, flags);
681 fn (data); 929 fn (data);
682 GOMP_parallel_end (); 930 GOMP_parallel_end ();
683 } 931 }
932
933 void
934 GOMP_parallel_loop_maybe_nonmonotonic_runtime (void (*fn) (void *), void *data,
935 unsigned num_threads, long start,
936 long end, long incr,
937 unsigned flags)
938 {
939 struct gomp_task_icv *icv = gomp_icv (false);
940 gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
941 icv->run_sched_var & ~GFS_MONOTONIC,
942 icv->run_sched_chunk_size, flags);
943 fn (data);
944 GOMP_parallel_end ();
945 }
946 #endif
684 947
685 /* The GOMP_loop_end* routines are called after the thread is told that 948 /* The GOMP_loop_end* routines are called after the thread is told that
686 all loop iterations are complete. The first two versions synchronize 949 all loop iterations are complete. The first two versions synchronize
687 all threads; the nowait version does not. */ 950 all threads; the nowait version does not. */
688 951
719 __attribute__((alias ("gomp_loop_guided_start"))); 982 __attribute__((alias ("gomp_loop_guided_start")));
720 extern __typeof(gomp_loop_dynamic_start) GOMP_loop_nonmonotonic_dynamic_start 983 extern __typeof(gomp_loop_dynamic_start) GOMP_loop_nonmonotonic_dynamic_start
721 __attribute__((alias ("gomp_loop_dynamic_start"))); 984 __attribute__((alias ("gomp_loop_dynamic_start")));
722 extern __typeof(gomp_loop_guided_start) GOMP_loop_nonmonotonic_guided_start 985 extern __typeof(gomp_loop_guided_start) GOMP_loop_nonmonotonic_guided_start
723 __attribute__((alias ("gomp_loop_guided_start"))); 986 __attribute__((alias ("gomp_loop_guided_start")));
987 extern __typeof(GOMP_loop_runtime_start) GOMP_loop_nonmonotonic_runtime_start
988 __attribute__((alias ("GOMP_loop_runtime_start")));
989 extern __typeof(GOMP_loop_runtime_start) GOMP_loop_maybe_nonmonotonic_runtime_start
990 __attribute__((alias ("GOMP_loop_runtime_start")));
724 991
725 extern __typeof(gomp_loop_ordered_static_start) GOMP_loop_ordered_static_start 992 extern __typeof(gomp_loop_ordered_static_start) GOMP_loop_ordered_static_start
726 __attribute__((alias ("gomp_loop_ordered_static_start"))); 993 __attribute__((alias ("gomp_loop_ordered_static_start")));
727 extern __typeof(gomp_loop_ordered_dynamic_start) GOMP_loop_ordered_dynamic_start 994 extern __typeof(gomp_loop_ordered_dynamic_start) GOMP_loop_ordered_dynamic_start
728 __attribute__((alias ("gomp_loop_ordered_dynamic_start"))); 995 __attribute__((alias ("gomp_loop_ordered_dynamic_start")));
744 __attribute__((alias ("gomp_loop_guided_next"))); 1011 __attribute__((alias ("gomp_loop_guided_next")));
745 extern __typeof(gomp_loop_dynamic_next) GOMP_loop_nonmonotonic_dynamic_next 1012 extern __typeof(gomp_loop_dynamic_next) GOMP_loop_nonmonotonic_dynamic_next
746 __attribute__((alias ("gomp_loop_dynamic_next"))); 1013 __attribute__((alias ("gomp_loop_dynamic_next")));
747 extern __typeof(gomp_loop_guided_next) GOMP_loop_nonmonotonic_guided_next 1014 extern __typeof(gomp_loop_guided_next) GOMP_loop_nonmonotonic_guided_next
748 __attribute__((alias ("gomp_loop_guided_next"))); 1015 __attribute__((alias ("gomp_loop_guided_next")));
1016 extern __typeof(GOMP_loop_runtime_next) GOMP_loop_nonmonotonic_runtime_next
1017 __attribute__((alias ("GOMP_loop_runtime_next")));
1018 extern __typeof(GOMP_loop_runtime_next) GOMP_loop_maybe_nonmonotonic_runtime_next
1019 __attribute__((alias ("GOMP_loop_runtime_next")));
749 1020
750 extern __typeof(gomp_loop_ordered_static_next) GOMP_loop_ordered_static_next 1021 extern __typeof(gomp_loop_ordered_static_next) GOMP_loop_ordered_static_next
751 __attribute__((alias ("gomp_loop_ordered_static_next"))); 1022 __attribute__((alias ("gomp_loop_ordered_static_next")));
752 extern __typeof(gomp_loop_ordered_dynamic_next) GOMP_loop_ordered_dynamic_next 1023 extern __typeof(gomp_loop_ordered_dynamic_next) GOMP_loop_ordered_dynamic_next
753 __attribute__((alias ("gomp_loop_ordered_dynamic_next"))); 1024 __attribute__((alias ("gomp_loop_ordered_dynamic_next")));
789 { 1060 {
790 return gomp_loop_guided_start (start, end, incr, chunk_size, istart, iend); 1061 return gomp_loop_guided_start (start, end, incr, chunk_size, istart, iend);
791 } 1062 }
792 1063
793 bool 1064 bool
1065 GOMP_loop_nonmonotonic_runtime_start (long start, long end, long incr,
1066 long *istart, long *iend)
1067 {
1068 return GOMP_loop_runtime_start (start, end, incr, istart, iend);
1069 }
1070
1071 bool
1072 GOMP_loop_maybe_nonmonotonic_runtime_start (long start, long end, long incr,
1073 long *istart, long *iend)
1074 {
1075 return GOMP_loop_runtime_start (start, end, incr, istart, iend);
1076 }
1077
1078 bool
794 GOMP_loop_ordered_static_start (long start, long end, long incr, 1079 GOMP_loop_ordered_static_start (long start, long end, long incr,
795 long chunk_size, long *istart, long *iend) 1080 long chunk_size, long *istart, long *iend)
796 { 1081 {
797 return gomp_loop_ordered_static_start (start, end, incr, chunk_size, 1082 return gomp_loop_ordered_static_start (start, end, incr, chunk_size,
798 istart, iend); 1083 istart, iend);
867 { 1152 {
868 return gomp_loop_guided_next (istart, iend); 1153 return gomp_loop_guided_next (istart, iend);
869 } 1154 }
870 1155
871 bool 1156 bool
1157 GOMP_loop_nonmonotonic_runtime_next (long *istart, long *iend)
1158 {
1159 return GOMP_loop_runtime_next (istart, iend);
1160 }
1161
1162 bool
1163 GOMP_loop_maybe_nonmonotonic_runtime_next (long *istart, long *iend)
1164 {
1165 return GOMP_loop_runtime_next (istart, iend);
1166 }
1167
1168 bool
872 GOMP_loop_ordered_static_next (long *istart, long *iend) 1169 GOMP_loop_ordered_static_next (long *istart, long *iend)
873 { 1170 {
874 return gomp_loop_ordered_static_next (istart, iend); 1171 return gomp_loop_ordered_static_next (istart, iend);
875 } 1172 }
876 1173