00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <limits.h>
00028 #include <stdlib.h>
00029 #include "libgomp.h"
00030
00031 typedef unsigned long long gomp_ull;
00032
00033
00034
00035 static inline void
00036 gomp_loop_ull_init (struct gomp_work_share *ws, bool up, gomp_ull start,
00037 gomp_ull end, gomp_ull incr, enum gomp_schedule_type sched,
00038 gomp_ull chunk_size)
00039 {
00040 ws->sched = sched;
00041 ws->chunk_size_ull = chunk_size;
00042
00043 ws->end_ull = ((up && start > end) || (!up && start < end))
00044 ? start : end;
00045 ws->incr_ull = incr;
00046 ws->next_ull = start;
00047 ws->mode = 0;
00048 if (sched == GFS_DYNAMIC)
00049 {
00050 ws->chunk_size_ull *= incr;
00051
00052 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
00053 {
00054
00055
00056 struct gomp_thread *thr = gomp_thread ();
00057 struct gomp_team *team = thr->ts.team;
00058 long nthreads = team ? team->nthreads : 1;
00059
00060 if (__builtin_expect (up, 1))
00061 {
00062
00063 if (__builtin_expect ((nthreads | ws->chunk_size_ull)
00064 < 1ULL << (sizeof (gomp_ull)
00065 * __CHAR_BIT__ / 2 - 1), 1))
00066 ws->mode = ws->end_ull < (__LONG_LONG_MAX__ * 2ULL + 1
00067 - (nthreads + 1) * ws->chunk_size_ull);
00068 }
00069
00070 else if (__builtin_expect ((nthreads | -ws->chunk_size_ull)
00071 < 1ULL << (sizeof (gomp_ull)
00072 * __CHAR_BIT__ / 2 - 1), 1))
00073 ws->mode = ws->end_ull > ((nthreads + 1) * -ws->chunk_size_ull
00074 - (__LONG_LONG_MAX__ * 2ULL + 1));
00075 }
00076 #endif
00077 }
00078 if (!up)
00079 ws->mode |= 2;
00080 }
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 static bool
00099 gomp_loop_ull_static_start (bool up, gomp_ull start, gomp_ull end,
00100 gomp_ull incr, gomp_ull chunk_size,
00101 gomp_ull *istart, gomp_ull *iend)
00102 {
00103 struct gomp_thread *thr = gomp_thread ();
00104
00105 thr->ts.static_trip = 0;
00106 if (gomp_work_share_start (false))
00107 {
00108 gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
00109 GFS_STATIC, chunk_size);
00110 gomp_work_share_init_done ();
00111 }
00112
00113 return !gomp_iter_ull_static_next (istart, iend);
00114 }
00115
00116 static bool
00117 gomp_loop_ull_dynamic_start (bool up, gomp_ull start, gomp_ull end,
00118 gomp_ull incr, gomp_ull chunk_size,
00119 gomp_ull *istart, gomp_ull *iend)
00120 {
00121 struct gomp_thread *thr = gomp_thread ();
00122 bool ret;
00123
00124 if (gomp_work_share_start (false))
00125 {
00126 gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
00127 GFS_DYNAMIC, chunk_size);
00128 gomp_work_share_init_done ();
00129 }
00130
00131 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
00132 ret = gomp_iter_ull_dynamic_next (istart, iend);
00133 #else
00134 gomp_mutex_lock (&thr->ts.work_share->lock);
00135 ret = gomp_iter_ull_dynamic_next_locked (istart, iend);
00136 gomp_mutex_unlock (&thr->ts.work_share->lock);
00137 #endif
00138
00139 return ret;
00140 }
00141
00142 static bool
00143 gomp_loop_ull_guided_start (bool up, gomp_ull start, gomp_ull end,
00144 gomp_ull incr, gomp_ull chunk_size,
00145 gomp_ull *istart, gomp_ull *iend)
00146 {
00147 struct gomp_thread *thr = gomp_thread ();
00148 bool ret;
00149
00150 if (gomp_work_share_start (false))
00151 {
00152 gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
00153 GFS_GUIDED, chunk_size);
00154 gomp_work_share_init_done ();
00155 }
00156
00157 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
00158 ret = gomp_iter_ull_guided_next (istart, iend);
00159 #else
00160 gomp_mutex_lock (&thr->ts.work_share->lock);
00161 ret = gomp_iter_ull_guided_next_locked (istart, iend);
00162 gomp_mutex_unlock (&thr->ts.work_share->lock);
00163 #endif
00164
00165 return ret;
00166 }
00167
00168 bool
00169 GOMP_loop_ull_runtime_start (bool up, gomp_ull start, gomp_ull end,
00170 gomp_ull incr, gomp_ull *istart, gomp_ull *iend)
00171 {
00172 struct gomp_task_icv *icv = gomp_icv (false);
00173 switch (icv->run_sched_var)
00174 {
00175 case GFS_STATIC:
00176 return gomp_loop_ull_static_start (up, start, end, incr,
00177 icv->run_sched_modifier,
00178 istart, iend);
00179 case GFS_DYNAMIC:
00180 return gomp_loop_ull_dynamic_start (up, start, end, incr,
00181 icv->run_sched_modifier,
00182 istart, iend);
00183 case GFS_GUIDED:
00184 return gomp_loop_ull_guided_start (up, start, end, incr,
00185 icv->run_sched_modifier,
00186 istart, iend);
00187 case GFS_AUTO:
00188
00189
00190 return gomp_loop_ull_static_start (up, start, end, incr,
00191 0, istart, iend);
00192 default:
00193 abort ();
00194 }
00195 }
00196
00197
00198
00199
00200 static bool
00201 gomp_loop_ull_ordered_static_start (bool up, gomp_ull start, gomp_ull end,
00202 gomp_ull incr, gomp_ull chunk_size,
00203 gomp_ull *istart, gomp_ull *iend)
00204 {
00205 struct gomp_thread *thr = gomp_thread ();
00206
00207 thr->ts.static_trip = 0;
00208 if (gomp_work_share_start (true))
00209 {
00210 gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
00211 GFS_STATIC, chunk_size);
00212 gomp_ordered_static_init ();
00213 gomp_work_share_init_done ();
00214 }
00215
00216 return !gomp_iter_ull_static_next (istart, iend);
00217 }
00218
00219 static bool
00220 gomp_loop_ull_ordered_dynamic_start (bool up, gomp_ull start, gomp_ull end,
00221 gomp_ull incr, gomp_ull chunk_size,
00222 gomp_ull *istart, gomp_ull *iend)
00223 {
00224 struct gomp_thread *thr = gomp_thread ();
00225 bool ret;
00226
00227 if (gomp_work_share_start (true))
00228 {
00229 gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
00230 GFS_DYNAMIC, chunk_size);
00231 gomp_mutex_lock (&thr->ts.work_share->lock);
00232 gomp_work_share_init_done ();
00233 }
00234 else
00235 gomp_mutex_lock (&thr->ts.work_share->lock);
00236
00237 ret = gomp_iter_ull_dynamic_next_locked (istart, iend);
00238 if (ret)
00239 gomp_ordered_first ();
00240 gomp_mutex_unlock (&thr->ts.work_share->lock);
00241
00242 return ret;
00243 }
00244
00245 static bool
00246 gomp_loop_ull_ordered_guided_start (bool up, gomp_ull start, gomp_ull end,
00247 gomp_ull incr, gomp_ull chunk_size,
00248 gomp_ull *istart, gomp_ull *iend)
00249 {
00250 struct gomp_thread *thr = gomp_thread ();
00251 bool ret;
00252
00253 if (gomp_work_share_start (true))
00254 {
00255 gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
00256 GFS_GUIDED, chunk_size);
00257 gomp_mutex_lock (&thr->ts.work_share->lock);
00258 gomp_work_share_init_done ();
00259 }
00260 else
00261 gomp_mutex_lock (&thr->ts.work_share->lock);
00262
00263 ret = gomp_iter_ull_guided_next_locked (istart, iend);
00264 if (ret)
00265 gomp_ordered_first ();
00266 gomp_mutex_unlock (&thr->ts.work_share->lock);
00267
00268 return ret;
00269 }
00270
00271 bool
00272 GOMP_loop_ull_ordered_runtime_start (bool up, gomp_ull start, gomp_ull end,
00273 gomp_ull incr, gomp_ull *istart,
00274 gomp_ull *iend)
00275 {
00276 struct gomp_task_icv *icv = gomp_icv (false);
00277 switch (icv->run_sched_var)
00278 {
00279 case GFS_STATIC:
00280 return gomp_loop_ull_ordered_static_start (up, start, end, incr,
00281 icv->run_sched_modifier,
00282 istart, iend);
00283 case GFS_DYNAMIC:
00284 return gomp_loop_ull_ordered_dynamic_start (up, start, end, incr,
00285 icv->run_sched_modifier,
00286 istart, iend);
00287 case GFS_GUIDED:
00288 return gomp_loop_ull_ordered_guided_start (up, start, end, incr,
00289 icv->run_sched_modifier,
00290 istart, iend);
00291 case GFS_AUTO:
00292
00293
00294 return gomp_loop_ull_ordered_static_start (up, start, end, incr,
00295 0, istart, iend);
00296 default:
00297 abort ();
00298 }
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 static bool
00312 gomp_loop_ull_static_next (gomp_ull *istart, gomp_ull *iend)
00313 {
00314 return !gomp_iter_ull_static_next (istart, iend);
00315 }
00316
00317 static bool
00318 gomp_loop_ull_dynamic_next (gomp_ull *istart, gomp_ull *iend)
00319 {
00320 bool ret;
00321
00322 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
00323 ret = gomp_iter_ull_dynamic_next (istart, iend);
00324 #else
00325 struct gomp_thread *thr = gomp_thread ();
00326 gomp_mutex_lock (&thr->ts.work_share->lock);
00327 ret = gomp_iter_ull_dynamic_next_locked (istart, iend);
00328 gomp_mutex_unlock (&thr->ts.work_share->lock);
00329 #endif
00330
00331 return ret;
00332 }
00333
00334 static bool
00335 gomp_loop_ull_guided_next (gomp_ull *istart, gomp_ull *iend)
00336 {
00337 bool ret;
00338
00339 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
00340 ret = gomp_iter_ull_guided_next (istart, iend);
00341 #else
00342 struct gomp_thread *thr = gomp_thread ();
00343 gomp_mutex_lock (&thr->ts.work_share->lock);
00344 ret = gomp_iter_ull_guided_next_locked (istart, iend);
00345 gomp_mutex_unlock (&thr->ts.work_share->lock);
00346 #endif
00347
00348 return ret;
00349 }
00350
00351 bool
00352 GOMP_loop_ull_runtime_next (gomp_ull *istart, gomp_ull *iend)
00353 {
00354 struct gomp_thread *thr = gomp_thread ();
00355
00356 switch (thr->ts.work_share->sched)
00357 {
00358 case GFS_STATIC:
00359 case GFS_AUTO:
00360 return gomp_loop_ull_static_next (istart, iend);
00361 case GFS_DYNAMIC:
00362 return gomp_loop_ull_dynamic_next (istart, iend);
00363 case GFS_GUIDED:
00364 return gomp_loop_ull_guided_next (istart, iend);
00365 default:
00366 abort ();
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377 static bool
00378 gomp_loop_ull_ordered_static_next (gomp_ull *istart, gomp_ull *iend)
00379 {
00380 struct gomp_thread *thr = gomp_thread ();
00381 int test;
00382
00383 gomp_ordered_sync ();
00384 gomp_mutex_lock (&thr->ts.work_share->lock);
00385 test = gomp_iter_ull_static_next (istart, iend);
00386 if (test >= 0)
00387 gomp_ordered_static_next ();
00388 gomp_mutex_unlock (&thr->ts.work_share->lock);
00389
00390 return test == 0;
00391 }
00392
00393 static bool
00394 gomp_loop_ull_ordered_dynamic_next (gomp_ull *istart, gomp_ull *iend)
00395 {
00396 struct gomp_thread *thr = gomp_thread ();
00397 bool ret;
00398
00399 gomp_ordered_sync ();
00400 gomp_mutex_lock (&thr->ts.work_share->lock);
00401 ret = gomp_iter_ull_dynamic_next_locked (istart, iend);
00402 if (ret)
00403 gomp_ordered_next ();
00404 else
00405 gomp_ordered_last ();
00406 gomp_mutex_unlock (&thr->ts.work_share->lock);
00407
00408 return ret;
00409 }
00410
00411 static bool
00412 gomp_loop_ull_ordered_guided_next (gomp_ull *istart, gomp_ull *iend)
00413 {
00414 struct gomp_thread *thr = gomp_thread ();
00415 bool ret;
00416
00417 gomp_ordered_sync ();
00418 gomp_mutex_lock (&thr->ts.work_share->lock);
00419 ret = gomp_iter_ull_guided_next_locked (istart, iend);
00420 if (ret)
00421 gomp_ordered_next ();
00422 else
00423 gomp_ordered_last ();
00424 gomp_mutex_unlock (&thr->ts.work_share->lock);
00425
00426 return ret;
00427 }
00428
00429 bool
00430 GOMP_loop_ull_ordered_runtime_next (gomp_ull *istart, gomp_ull *iend)
00431 {
00432 struct gomp_thread *thr = gomp_thread ();
00433
00434 switch (thr->ts.work_share->sched)
00435 {
00436 case GFS_STATIC:
00437 case GFS_AUTO:
00438 return gomp_loop_ull_ordered_static_next (istart, iend);
00439 case GFS_DYNAMIC:
00440 return gomp_loop_ull_ordered_dynamic_next (istart, iend);
00441 case GFS_GUIDED:
00442 return gomp_loop_ull_ordered_guided_next (istart, iend);
00443 default:
00444 abort ();
00445 }
00446 }
00447
00448
00449
00450
00451
00452
00453 #ifdef HAVE_ATTRIBUTE_ALIAS
00454 extern __typeof(gomp_loop_ull_static_start) GOMP_loop_ull_static_start
00455 __attribute__((alias ("gomp_loop_ull_static_start")));
00456 extern __typeof(gomp_loop_ull_dynamic_start) GOMP_loop_ull_dynamic_start
00457 __attribute__((alias ("gomp_loop_ull_dynamic_start")));
00458 extern __typeof(gomp_loop_ull_guided_start) GOMP_loop_ull_guided_start
00459 __attribute__((alias ("gomp_loop_ull_guided_start")));
00460
00461 extern __typeof(gomp_loop_ull_ordered_static_start) GOMP_loop_ull_ordered_static_start
00462 __attribute__((alias ("gomp_loop_ull_ordered_static_start")));
00463 extern __typeof(gomp_loop_ull_ordered_dynamic_start) GOMP_loop_ull_ordered_dynamic_start
00464 __attribute__((alias ("gomp_loop_ull_ordered_dynamic_start")));
00465 extern __typeof(gomp_loop_ull_ordered_guided_start) GOMP_loop_ull_ordered_guided_start
00466 __attribute__((alias ("gomp_loop_ull_ordered_guided_start")));
00467
00468 extern __typeof(gomp_loop_ull_static_next) GOMP_loop_ull_static_next
00469 __attribute__((alias ("gomp_loop_ull_static_next")));
00470 extern __typeof(gomp_loop_ull_dynamic_next) GOMP_loop_ull_dynamic_next
00471 __attribute__((alias ("gomp_loop_ull_dynamic_next")));
00472 extern __typeof(gomp_loop_ull_guided_next) GOMP_loop_ull_guided_next
00473 __attribute__((alias ("gomp_loop_ull_guided_next")));
00474
00475 extern __typeof(gomp_loop_ull_ordered_static_next) GOMP_loop_ull_ordered_static_next
00476 __attribute__((alias ("gomp_loop_ull_ordered_static_next")));
00477 extern __typeof(gomp_loop_ull_ordered_dynamic_next) GOMP_loop_ull_ordered_dynamic_next
00478 __attribute__((alias ("gomp_loop_ull_ordered_dynamic_next")));
00479 extern __typeof(gomp_loop_ull_ordered_guided_next) GOMP_loop_ull_ordered_guided_next
00480 __attribute__((alias ("gomp_loop_ull_ordered_guided_next")));
00481 #else
00482 bool
00483 GOMP_loop_ull_static_start (bool up, gomp_ull start, gomp_ull end,
00484 gomp_ull incr, gomp_ull chunk_size,
00485 gomp_ull *istart, gomp_ull *iend)
00486 {
00487 return gomp_loop_ull_static_start (up, start, end, incr, chunk_size, istart,
00488 iend);
00489 }
00490
00491 bool
00492 GOMP_loop_ull_dynamic_start (bool up, gomp_ull start, gomp_ull end,
00493 gomp_ull incr, gomp_ull chunk_size,
00494 gomp_ull *istart, gomp_ull *iend)
00495 {
00496 return gomp_loop_ull_dynamic_start (up, start, end, incr, chunk_size, istart,
00497 iend);
00498 }
00499
00500 bool
00501 GOMP_loop_ull_guided_start (bool up, gomp_ull start, gomp_ull end,
00502 gomp_ull incr, gomp_ull chunk_size,
00503 gomp_ull *istart, gomp_ull *iend)
00504 {
00505 return gomp_loop_ull_guided_start (up, start, end, incr, chunk_size, istart,
00506 iend);
00507 }
00508
00509 bool
00510 GOMP_loop_ull_ordered_static_start (bool up, gomp_ull start, gomp_ull end,
00511 gomp_ull incr, gomp_ull chunk_size,
00512 gomp_ull *istart, gomp_ull *iend)
00513 {
00514 return gomp_loop_ull_ordered_static_start (up, start, end, incr, chunk_size,
00515 istart, iend);
00516 }
00517
00518 bool
00519 GOMP_loop_ull_ordered_dynamic_start (bool up, gomp_ull start, gomp_ull end,
00520 gomp_ull incr, gomp_ull chunk_size,
00521 gomp_ull *istart, gomp_ull *iend)
00522 {
00523 return gomp_loop_ull_ordered_dynamic_start (up, start, end, incr, chunk_size,
00524 istart, iend);
00525 }
00526
00527 bool
00528 GOMP_loop_ull_ordered_guided_start (bool up, gomp_ull start, gomp_ull end,
00529 gomp_ull incr, gomp_ull chunk_size,
00530 gomp_ull *istart, gomp_ull *iend)
00531 {
00532 return gomp_loop_ull_ordered_guided_start (up, start, end, incr, chunk_size,
00533 istart, iend);
00534 }
00535
00536 bool
00537 GOMP_loop_ull_static_next (gomp_ull *istart, gomp_ull *iend)
00538 {
00539 return gomp_loop_ull_static_next (istart, iend);
00540 }
00541
00542 bool
00543 GOMP_loop_ull_dynamic_next (gomp_ull *istart, gomp_ull *iend)
00544 {
00545 return gomp_loop_ull_dynamic_next (istart, iend);
00546 }
00547
00548 bool
00549 GOMP_loop_ull_guided_next (gomp_ull *istart, gomp_ull *iend)
00550 {
00551 return gomp_loop_ull_guided_next (istart, iend);
00552 }
00553
00554 bool
00555 GOMP_loop_ull_ordered_static_next (gomp_ull *istart, gomp_ull *iend)
00556 {
00557 return gomp_loop_ull_ordered_static_next (istart, iend);
00558 }
00559
00560 bool
00561 GOMP_loop_ull_ordered_dynamic_next (gomp_ull *istart, gomp_ull *iend)
00562 {
00563 return gomp_loop_ull_ordered_dynamic_next (istart, iend);
00564 }
00565
00566 bool
00567 GOMP_loop_ull_ordered_guided_next (gomp_ull *istart, gomp_ull *iend)
00568 {
00569 return gomp_loop_ull_ordered_guided_next (istart, iend);
00570 }
00571 #endif