Mercurial > hg > CbC > CbC_gcc
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 |