1 /* Copyright (C) 2005-2018 Free Software Foundation, Inc. 2 Contributed by Richard Henderson <rth@redhat.com>. 3 4 This file is part of the GNU Offloading and Multi Processing Library 5 (libgomp). 6 7 Libgomp is free software; you can redistribute it and/or modify it 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. 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 14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 more details. 16 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/>. */ 25 26 /* This file handles the LOOP (FOR/DO) construct. */ 27 28 #include <limits.h> 29 #include <stdlib.h> 30 #include "libgomp.h" 31 32 typedef unsigned long long gomp_ull; 33 34 /* Initialize the given work share construct from the given arguments. */ 35 36 static inline void 37 gomp_loop_ull_init (struct gomp_work_share *ws, bool up, gomp_ull start, 38 gomp_ull end, gomp_ull incr, enum gomp_schedule_type sched, 39 gomp_ull chunk_size) 40 { 41 ws->sched = sched; 42 ws->chunk_size_ull = chunk_size; 43 /* Canonicalize loops that have zero iterations to ->next == ->end. */ 44 ws->end_ull = ((up && start > end) || (!up && start < end)) 45 ? start : end; 46 ws->incr_ull = incr; 47 ws->next_ull = start; 48 ws->mode = 0; 49 if (sched == GFS_DYNAMIC) 50 { 51 ws->chunk_size_ull *= incr; 52 53 #if defined HAVE_SYNC_BUILTINS && defined __LP64__ 54 { 55 /* For dynamic scheduling prepare things to make each iteration 56 faster. */ 57 struct gomp_thread *thr = gomp_thread (); 58 struct gomp_team *team = thr->ts.team; 59 long nthreads = team ? team->nthreads : 1; 60 61 if (__builtin_expect (up, 1)) 62 { 63 /* Cheap overflow protection. */ 64 if (__builtin_expect ((nthreads | ws->chunk_size_ull) 65 < 1ULL << (sizeof (gomp_ull) 66 * __CHAR_BIT__ / 2 - 1), 1)) 67 ws->mode = ws->end_ull < (__LONG_LONG_MAX__ * 2ULL + 1 68 - (nthreads + 1) * ws->chunk_size_ull); 69 } 70 /* Cheap overflow protection. */ 71 else if (__builtin_expect ((nthreads | -ws->chunk_size_ull) 72 < 1ULL << (sizeof (gomp_ull) 73 * __CHAR_BIT__ / 2 - 1), 1)) 74 ws->mode = ws->end_ull > ((nthreads + 1) * -ws->chunk_size_ull 75 - (__LONG_LONG_MAX__ * 2ULL + 1)); 76 } 77 #endif 78 } 79 if (!up) 80 ws->mode |= 2; 81 } 82 83 /* The *_start routines are called when first encountering a loop construct 84 that is not bound directly to a parallel construct. The first thread 85 that arrives will create the work-share construct; subsequent threads 86 will see the construct exists and allocate work from it. 87 88 START, END, INCR are the bounds of the loop; due to the restrictions of 89 OpenMP, these values must be the same in every thread. This is not 90 verified (nor is it entirely verifiable, since START is not necessarily 91 retained intact in the work-share data structure). CHUNK_SIZE is the 92 scheduling parameter; again this must be identical in all threads. 93 94 Returns true if there's any work for this thread to perform. If so, 95 *ISTART and *IEND are filled with the bounds of the iteration block 96 allocated to this thread. Returns false if all work was assigned to 97 other threads prior to this thread's arrival. */ 98 99 static bool 100 gomp_loop_ull_static_start (bool up, gomp_ull start, gomp_ull end, 101 gomp_ull incr, gomp_ull chunk_size, 102 gomp_ull *istart, gomp_ull *iend) 103 { 104 struct gomp_thread *thr = gomp_thread (); 105 106 thr->ts.static_trip = 0; 107 if (gomp_work_share_start (false)) 108 { 109 gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, 110 GFS_STATIC, chunk_size); 111 gomp_work_share_init_done (); 112 } 113 114 return !gomp_iter_ull_static_next (istart, iend); 115 } 116 117 static bool 118 gomp_loop_ull_dynamic_start (bool up, gomp_ull start, gomp_ull end, 119 gomp_ull incr, gomp_ull chunk_size, 120 gomp_ull *istart, gomp_ull *iend) 121 { 122 struct gomp_thread *thr = gomp_thread (); 123 bool ret; 124 125 if (gomp_work_share_start (false)) 126 { 127 gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, 128 GFS_DYNAMIC, chunk_size); 129 gomp_work_share_init_done (); 130 } 131 132 #if defined HAVE_SYNC_BUILTINS && defined __LP64__ 133 ret = gomp_iter_ull_dynamic_next (istart, iend); 134 #else 135 gomp_mutex_lock (&thr->ts.work_share->lock); 136 ret = gomp_iter_ull_dynamic_next_locked (istart, iend); 137 gomp_mutex_unlock (&thr->ts.work_share->lock); 138 #endif 139 140 return ret; 141 } 142 143 static bool 144 gomp_loop_ull_guided_start (bool up, gomp_ull start, gomp_ull end, 145 gomp_ull incr, gomp_ull chunk_size, 146 gomp_ull *istart, gomp_ull *iend) 147 { 148 struct gomp_thread *thr = gomp_thread (); 149 bool ret; 150 151 if (gomp_work_share_start (false)) 152 { 153 gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, 154 GFS_GUIDED, chunk_size); 155 gomp_work_share_init_done (); 156 } 157 158 #if defined HAVE_SYNC_BUILTINS && defined __LP64__ 159 ret = gomp_iter_ull_guided_next (istart, iend); 160 #else 161 gomp_mutex_lock (&thr->ts.work_share->lock); 162 ret = gomp_iter_ull_guided_next_locked (istart, iend); 163 gomp_mutex_unlock (&thr->ts.work_share->lock); 164 #endif 165 166 return ret; 167 } 168 169 bool 170 GOMP_loop_ull_runtime_start (bool up, gomp_ull start, gomp_ull end, 171 gomp_ull incr, gomp_ull *istart, gomp_ull *iend) 172 { 173 struct gomp_task_icv *icv = gomp_icv (false); 174 switch (icv->run_sched_var) 175 { 176 case GFS_STATIC: 177 return gomp_loop_ull_static_start (up, start, end, incr, 178 icv->run_sched_chunk_size, 179 istart, iend); 180 case GFS_DYNAMIC: 181 return gomp_loop_ull_dynamic_start (up, start, end, incr, 182 icv->run_sched_chunk_size, 183 istart, iend); 184 case GFS_GUIDED: 185 return gomp_loop_ull_guided_start (up, start, end, incr, 186 icv->run_sched_chunk_size, 187 istart, iend); 188 case GFS_AUTO: 189 /* For now map to schedule(static), later on we could play with feedback 190 driven choice. */ 191 return gomp_loop_ull_static_start (up, start, end, incr, 192 0, istart, iend); 193 default: 194 abort (); 195 } 196 } 197 198 /* The *_ordered_*_start routines are similar. The only difference is that 199 this work-share construct is initialized to expect an ORDERED section. */ 200 201 static bool 202 gomp_loop_ull_ordered_static_start (bool up, gomp_ull start, gomp_ull end, 203 gomp_ull incr, gomp_ull chunk_size, 204 gomp_ull *istart, gomp_ull *iend) 205 { 206 struct gomp_thread *thr = gomp_thread (); 207 208 thr->ts.static_trip = 0; 209 if (gomp_work_share_start (true)) 210 { 211 gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, 212 GFS_STATIC, chunk_size); 213 gomp_ordered_static_init (); 214 gomp_work_share_init_done (); 215 } 216 217 return !gomp_iter_ull_static_next (istart, iend); 218 } 219 220 static bool 221 gomp_loop_ull_ordered_dynamic_start (bool up, gomp_ull start, gomp_ull end, 222 gomp_ull incr, gomp_ull chunk_size, 223 gomp_ull *istart, gomp_ull *iend) 224 { 225 struct gomp_thread *thr = gomp_thread (); 226 bool ret; 227 228 if (gomp_work_share_start (true)) 229 { 230 gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, 231 GFS_DYNAMIC, chunk_size); 232 gomp_mutex_lock (&thr->ts.work_share->lock); 233 gomp_work_share_init_done (); 234 } 235 else 236 gomp_mutex_lock (&thr->ts.work_share->lock); 237 238 ret = gomp_iter_ull_dynamic_next_locked (istart, iend); 239 if (ret) 240 gomp_ordered_first (); 241 gomp_mutex_unlock (&thr->ts.work_share->lock); 242 243 return ret; 244 } 245 246 static bool 247 gomp_loop_ull_ordered_guided_start (bool up, gomp_ull start, gomp_ull end, 248 gomp_ull incr, gomp_ull chunk_size, 249 gomp_ull *istart, gomp_ull *iend) 250 { 251 struct gomp_thread *thr = gomp_thread (); 252 bool ret; 253 254 if (gomp_work_share_start (true)) 255 { 256 gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr, 257 GFS_GUIDED, chunk_size); 258 gomp_mutex_lock (&thr->ts.work_share->lock); 259 gomp_work_share_init_done (); 260 } 261 else 262 gomp_mutex_lock (&thr->ts.work_share->lock); 263 264 ret = gomp_iter_ull_guided_next_locked (istart, iend); 265 if (ret) 266 gomp_ordered_first (); 267 gomp_mutex_unlock (&thr->ts.work_share->lock); 268 269 return ret; 270 } 271 272 bool 273 GOMP_loop_ull_ordered_runtime_start (bool up, gomp_ull start, gomp_ull end, 274 gomp_ull incr, gomp_ull *istart, 275 gomp_ull *iend) 276 { 277 struct gomp_task_icv *icv = gomp_icv (false); 278 switch (icv->run_sched_var) 279 { 280 case GFS_STATIC: 281 return gomp_loop_ull_ordered_static_start (up, start, end, incr, 282 icv->run_sched_chunk_size, 283 istart, iend); 284 case GFS_DYNAMIC: 285 return gomp_loop_ull_ordered_dynamic_start (up, start, end, incr, 286 icv->run_sched_chunk_size, 287 istart, iend); 288 case GFS_GUIDED: 289 return gomp_loop_ull_ordered_guided_start (up, start, end, incr, 290 icv->run_sched_chunk_size, 291 istart, iend); 292 case GFS_AUTO: 293 /* For now map to schedule(static), later on we could play with feedback 294 driven choice. */ 295 return gomp_loop_ull_ordered_static_start (up, start, end, incr, 296 0, istart, iend); 297 default: 298 abort (); 299 } 300 } 301 302 /* The *_doacross_*_start routines are similar. The only difference is that 303 this work-share construct is initialized to expect an ORDERED(N) - DOACROSS 304 section, and the worksharing loop iterates always from 0 to COUNTS[0] - 1 305 and other COUNTS array elements tell the library number of iterations 306 in the ordered inner loops. */ 307 308 static bool 309 gomp_loop_ull_doacross_static_start (unsigned ncounts, gomp_ull *counts, 310 gomp_ull chunk_size, gomp_ull *istart, 311 gomp_ull *iend) 312 { 313 struct gomp_thread *thr = gomp_thread (); 314 315 thr->ts.static_trip = 0; 316 if (gomp_work_share_start (false)) 317 { 318 gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1, 319 GFS_STATIC, chunk_size); 320 gomp_doacross_ull_init (ncounts, counts, chunk_size); 321 gomp_work_share_init_done (); 322 } 323 324 return !gomp_iter_ull_static_next (istart, iend); 325 } 326 327 static bool 328 gomp_loop_ull_doacross_dynamic_start (unsigned ncounts, gomp_ull *counts, 329 gomp_ull chunk_size, gomp_ull *istart, 330 gomp_ull *iend) 331 { 332 struct gomp_thread *thr = gomp_thread (); 333 bool ret; 334 335 if (gomp_work_share_start (false)) 336 { 337 gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1, 338 GFS_DYNAMIC, chunk_size); 339 gomp_doacross_ull_init (ncounts, counts, chunk_size); 340 gomp_work_share_init_done (); 341 } 342 343 #if defined HAVE_SYNC_BUILTINS && defined __LP64__ 344 ret = gomp_iter_ull_dynamic_next (istart, iend); 345 #else 346 gomp_mutex_lock (&thr->ts.work_share->lock); 347 ret = gomp_iter_ull_dynamic_next_locked (istart, iend); 348 gomp_mutex_unlock (&thr->ts.work_share->lock); 349 #endif 350 351 return ret; 352 } 353 354 static bool 355 gomp_loop_ull_doacross_guided_start (unsigned ncounts, gomp_ull *counts, 356 gomp_ull chunk_size, gomp_ull *istart, 357 gomp_ull *iend) 358 { 359 struct gomp_thread *thr = gomp_thread (); 360 bool ret; 361 362 if (gomp_work_share_start (false)) 363 { 364 gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1, 365 GFS_GUIDED, chunk_size); 366 gomp_doacross_ull_init (ncounts, counts, chunk_size); 367 gomp_work_share_init_done (); 368 } 369 370 #if defined HAVE_SYNC_BUILTINS && defined __LP64__ 371 ret = gomp_iter_ull_guided_next (istart, iend); 372 #else 373 gomp_mutex_lock (&thr->ts.work_share->lock); 374 ret = gomp_iter_ull_guided_next_locked (istart, iend); 375 gomp_mutex_unlock (&thr->ts.work_share->lock); 376 #endif 377 378 return ret; 379 } 380 381 bool 382 GOMP_loop_ull_doacross_runtime_start (unsigned ncounts, gomp_ull *counts, 383 gomp_ull *istart, gomp_ull *iend) 384 { 385 struct gomp_task_icv *icv = gomp_icv (false); 386 switch (icv->run_sched_var) 387 { 388 case GFS_STATIC: 389 return gomp_loop_ull_doacross_static_start (ncounts, counts, 390 icv->run_sched_chunk_size, 391 istart, iend); 392 case GFS_DYNAMIC: 393 return gomp_loop_ull_doacross_dynamic_start (ncounts, counts, 394 icv->run_sched_chunk_size, 395 istart, iend); 396 case GFS_GUIDED: 397 return gomp_loop_ull_doacross_guided_start (ncounts, counts, 398 icv->run_sched_chunk_size, 399 istart, iend); 400 case GFS_AUTO: 401 /* For now map to schedule(static), later on we could play with feedback 402 driven choice. */ 403 return gomp_loop_ull_doacross_static_start (ncounts, counts, 404 0, istart, iend); 405 default: 406 abort (); 407 } 408 } 409 410 /* The *_next routines are called when the thread completes processing of 411 the iteration block currently assigned to it. If the work-share 412 construct is bound directly to a parallel construct, then the iteration 413 bounds may have been set up before the parallel. In which case, this 414 may be the first iteration for the thread. 415 416 Returns true if there is work remaining to be performed; *ISTART and 417 *IEND are filled with a new iteration block. Returns false if all work 418 has been assigned. */ 419 420 static bool 421 gomp_loop_ull_static_next (gomp_ull *istart, gomp_ull *iend) 422 { 423 return !gomp_iter_ull_static_next (istart, iend); 424 } 425 426 static bool 427 gomp_loop_ull_dynamic_next (gomp_ull *istart, gomp_ull *iend) 428 { 429 bool ret; 430 431 #if defined HAVE_SYNC_BUILTINS && defined __LP64__ 432 ret = gomp_iter_ull_dynamic_next (istart, iend); 433 #else 434 struct gomp_thread *thr = gomp_thread (); 435 gomp_mutex_lock (&thr->ts.work_share->lock); 436 ret = gomp_iter_ull_dynamic_next_locked (istart, iend); 437 gomp_mutex_unlock (&thr->ts.work_share->lock); 438 #endif 439 440 return ret; 441 } 442 443 static bool 444 gomp_loop_ull_guided_next (gomp_ull *istart, gomp_ull *iend) 445 { 446 bool ret; 447 448 #if defined HAVE_SYNC_BUILTINS && defined __LP64__ 449 ret = gomp_iter_ull_guided_next (istart, iend); 450 #else 451 struct gomp_thread *thr = gomp_thread (); 452 gomp_mutex_lock (&thr->ts.work_share->lock); 453 ret = gomp_iter_ull_guided_next_locked (istart, iend); 454 gomp_mutex_unlock (&thr->ts.work_share->lock); 455 #endif 456 457 return ret; 458 } 459 460 bool 461 GOMP_loop_ull_runtime_next (gomp_ull *istart, gomp_ull *iend) 462 { 463 struct gomp_thread *thr = gomp_thread (); 464 465 switch (thr->ts.work_share->sched) 466 { 467 case GFS_STATIC: 468 case GFS_AUTO: 469 return gomp_loop_ull_static_next (istart, iend); 470 case GFS_DYNAMIC: 471 return gomp_loop_ull_dynamic_next (istart, iend); 472 case GFS_GUIDED: 473 return gomp_loop_ull_guided_next (istart, iend); 474 default: 475 abort (); 476 } 477 } 478 479 /* The *_ordered_*_next routines are called when the thread completes 480 processing of the iteration block currently assigned to it. 481 482 Returns true if there is work remaining to be performed; *ISTART and 483 *IEND are filled with a new iteration block. Returns false if all work 484 has been assigned. */ 485 486 static bool 487 gomp_loop_ull_ordered_static_next (gomp_ull *istart, gomp_ull *iend) 488 { 489 struct gomp_thread *thr = gomp_thread (); 490 int test; 491 492 gomp_ordered_sync (); 493 gomp_mutex_lock (&thr->ts.work_share->lock); 494 test = gomp_iter_ull_static_next (istart, iend); 495 if (test >= 0) 496 gomp_ordered_static_next (); 497 gomp_mutex_unlock (&thr->ts.work_share->lock); 498 499 return test == 0; 500 } 501 502 static bool 503 gomp_loop_ull_ordered_dynamic_next (gomp_ull *istart, gomp_ull *iend) 504 { 505 struct gomp_thread *thr = gomp_thread (); 506 bool ret; 507 508 gomp_ordered_sync (); 509 gomp_mutex_lock (&thr->ts.work_share->lock); 510 ret = gomp_iter_ull_dynamic_next_locked (istart, iend); 511 if (ret) 512 gomp_ordered_next (); 513 else 514 gomp_ordered_last (); 515 gomp_mutex_unlock (&thr->ts.work_share->lock); 516 517 return ret; 518 } 519 520 static bool 521 gomp_loop_ull_ordered_guided_next (gomp_ull *istart, gomp_ull *iend) 522 { 523 struct gomp_thread *thr = gomp_thread (); 524 bool ret; 525 526 gomp_ordered_sync (); 527 gomp_mutex_lock (&thr->ts.work_share->lock); 528 ret = gomp_iter_ull_guided_next_locked (istart, iend); 529 if (ret) 530 gomp_ordered_next (); 531 else 532 gomp_ordered_last (); 533 gomp_mutex_unlock (&thr->ts.work_share->lock); 534 535 return ret; 536 } 537 538 bool 539 GOMP_loop_ull_ordered_runtime_next (gomp_ull *istart, gomp_ull *iend) 540 { 541 struct gomp_thread *thr = gomp_thread (); 542 543 switch (thr->ts.work_share->sched) 544 { 545 case GFS_STATIC: 546 case GFS_AUTO: 547 return gomp_loop_ull_ordered_static_next (istart, iend); 548 case GFS_DYNAMIC: 549 return gomp_loop_ull_ordered_dynamic_next (istart, iend); 550 case GFS_GUIDED: 551 return gomp_loop_ull_ordered_guided_next (istart, iend); 552 default: 553 abort (); 554 } 555 } 556 557 /* We use static functions above so that we're sure that the "runtime" 558 function can defer to the proper routine without interposition. We 559 export the static function with a strong alias when possible, or with 560 a wrapper function otherwise. */ 561 562 #ifdef HAVE_ATTRIBUTE_ALIAS 563 extern __typeof(gomp_loop_ull_static_start) GOMP_loop_ull_static_start 564 __attribute__((alias ("gomp_loop_ull_static_start"))); 565 extern __typeof(gomp_loop_ull_dynamic_start) GOMP_loop_ull_dynamic_start 566 __attribute__((alias ("gomp_loop_ull_dynamic_start"))); 567 extern __typeof(gomp_loop_ull_guided_start) GOMP_loop_ull_guided_start 568 __attribute__((alias ("gomp_loop_ull_guided_start"))); 569 extern __typeof(gomp_loop_ull_dynamic_start) GOMP_loop_ull_nonmonotonic_dynamic_start 570 __attribute__((alias ("gomp_loop_ull_dynamic_start"))); 571 extern __typeof(gomp_loop_ull_guided_start) GOMP_loop_ull_nonmonotonic_guided_start 572 __attribute__((alias ("gomp_loop_ull_guided_start"))); 573 574 extern __typeof(gomp_loop_ull_ordered_static_start) GOMP_loop_ull_ordered_static_start 575 __attribute__((alias ("gomp_loop_ull_ordered_static_start"))); 576 extern __typeof(gomp_loop_ull_ordered_dynamic_start) GOMP_loop_ull_ordered_dynamic_start 577 __attribute__((alias ("gomp_loop_ull_ordered_dynamic_start"))); 578 extern __typeof(gomp_loop_ull_ordered_guided_start) GOMP_loop_ull_ordered_guided_start 579 __attribute__((alias ("gomp_loop_ull_ordered_guided_start"))); 580 581 extern __typeof(gomp_loop_ull_doacross_static_start) GOMP_loop_ull_doacross_static_start 582 __attribute__((alias ("gomp_loop_ull_doacross_static_start"))); 583 extern __typeof(gomp_loop_ull_doacross_dynamic_start) GOMP_loop_ull_doacross_dynamic_start 584 __attribute__((alias ("gomp_loop_ull_doacross_dynamic_start"))); 585 extern __typeof(gomp_loop_ull_doacross_guided_start) GOMP_loop_ull_doacross_guided_start 586 __attribute__((alias ("gomp_loop_ull_doacross_guided_start"))); 587 588 extern __typeof(gomp_loop_ull_static_next) GOMP_loop_ull_static_next 589 __attribute__((alias ("gomp_loop_ull_static_next"))); 590 extern __typeof(gomp_loop_ull_dynamic_next) GOMP_loop_ull_dynamic_next 591 __attribute__((alias ("gomp_loop_ull_dynamic_next"))); 592 extern __typeof(gomp_loop_ull_guided_next) GOMP_loop_ull_guided_next 593 __attribute__((alias ("gomp_loop_ull_guided_next"))); 594 extern __typeof(gomp_loop_ull_dynamic_next) GOMP_loop_ull_nonmonotonic_dynamic_next 595 __attribute__((alias ("gomp_loop_ull_dynamic_next"))); 596 extern __typeof(gomp_loop_ull_guided_next) GOMP_loop_ull_nonmonotonic_guided_next 597 __attribute__((alias ("gomp_loop_ull_guided_next"))); 598 599 extern __typeof(gomp_loop_ull_ordered_static_next) GOMP_loop_ull_ordered_static_next 600 __attribute__((alias ("gomp_loop_ull_ordered_static_next"))); 601 extern __typeof(gomp_loop_ull_ordered_dynamic_next) GOMP_loop_ull_ordered_dynamic_next 602 __attribute__((alias ("gomp_loop_ull_ordered_dynamic_next"))); 603 extern __typeof(gomp_loop_ull_ordered_guided_next) GOMP_loop_ull_ordered_guided_next 604 __attribute__((alias ("gomp_loop_ull_ordered_guided_next"))); 605 #else 606 bool 607 GOMP_loop_ull_static_start (bool up, gomp_ull start, gomp_ull end, 608 gomp_ull incr, gomp_ull chunk_size, 609 gomp_ull *istart, gomp_ull *iend) 610 { 611 return gomp_loop_ull_static_start (up, start, end, incr, chunk_size, istart, 612 iend); 613 } 614 615 bool 616 GOMP_loop_ull_dynamic_start (bool up, gomp_ull start, gomp_ull end, 617 gomp_ull incr, gomp_ull chunk_size, 618 gomp_ull *istart, gomp_ull *iend) 619 { 620 return gomp_loop_ull_dynamic_start (up, start, end, incr, chunk_size, istart, 621 iend); 622 } 623 624 bool 625 GOMP_loop_ull_guided_start (bool up, gomp_ull start, gomp_ull end, 626 gomp_ull incr, gomp_ull chunk_size, 627 gomp_ull *istart, gomp_ull *iend) 628 { 629 return gomp_loop_ull_guided_start (up, start, end, incr, chunk_size, istart, 630 iend); 631 } 632 633 bool 634 GOMP_loop_ull_nonmonotonic_dynamic_start (bool up, gomp_ull start, 635 gomp_ull end, gomp_ull incr, 636 gomp_ull chunk_size, 637 gomp_ull *istart, gomp_ull *iend) 638 { 639 return gomp_loop_ull_dynamic_start (up, start, end, incr, chunk_size, istart, 640 iend); 641 } 642 643 bool 644 GOMP_loop_ull_nonmonotonic_guided_start (bool up, gomp_ull start, gomp_ull end, 645 gomp_ull incr, gomp_ull chunk_size, 646 gomp_ull *istart, gomp_ull *iend) 647 { 648 return gomp_loop_ull_guided_start (up, start, end, incr, chunk_size, istart, 649 iend); 650 } 651 652 bool 653 GOMP_loop_ull_ordered_static_start (bool up, gomp_ull start, gomp_ull end, 654 gomp_ull incr, gomp_ull chunk_size, 655 gomp_ull *istart, gomp_ull *iend) 656 { 657 return gomp_loop_ull_ordered_static_start (up, start, end, incr, chunk_size, 658 istart, iend); 659 } 660 661 bool 662 GOMP_loop_ull_ordered_dynamic_start (bool up, gomp_ull start, gomp_ull end, 663 gomp_ull incr, gomp_ull chunk_size, 664 gomp_ull *istart, gomp_ull *iend) 665 { 666 return gomp_loop_ull_ordered_dynamic_start (up, start, end, incr, chunk_size, 667 istart, iend); 668 } 669 670 bool 671 GOMP_loop_ull_ordered_guided_start (bool up, gomp_ull start, gomp_ull end, 672 gomp_ull incr, gomp_ull chunk_size, 673 gomp_ull *istart, gomp_ull *iend) 674 { 675 return gomp_loop_ull_ordered_guided_start (up, start, end, incr, chunk_size, 676 istart, iend); 677 } 678 679 bool 680 GOMP_loop_ull_doacross_static_start (unsigned ncounts, gomp_ull *counts, 681 gomp_ull chunk_size, gomp_ull *istart, 682 gomp_ull *iend) 683 { 684 return gomp_loop_ull_doacross_static_start (ncounts, counts, chunk_size, 685 istart, iend); 686 } 687 688 bool 689 GOMP_loop_ull_doacross_dynamic_start (unsigned ncounts, gomp_ull *counts, 690 gomp_ull chunk_size, gomp_ull *istart, 691 gomp_ull *iend) 692 { 693 return gomp_loop_ull_doacross_dynamic_start (ncounts, counts, chunk_size, 694 istart, iend); 695 } 696 697 bool 698 GOMP_loop_ull_doacross_guided_start (unsigned ncounts, gomp_ull *counts, 699 gomp_ull chunk_size, gomp_ull *istart, 700 gomp_ull *iend) 701 { 702 return gomp_loop_ull_doacross_guided_start (ncounts, counts, chunk_size, 703 istart, iend); 704 } 705 706 bool 707 GOMP_loop_ull_static_next (gomp_ull *istart, gomp_ull *iend) 708 { 709 return gomp_loop_ull_static_next (istart, iend); 710 } 711 712 bool 713 GOMP_loop_ull_dynamic_next (gomp_ull *istart, gomp_ull *iend) 714 { 715 return gomp_loop_ull_dynamic_next (istart, iend); 716 } 717 718 bool 719 GOMP_loop_ull_guided_next (gomp_ull *istart, gomp_ull *iend) 720 { 721 return gomp_loop_ull_guided_next (istart, iend); 722 } 723 724 bool 725 GOMP_loop_ull_nonmonotonic_dynamic_next (gomp_ull *istart, gomp_ull *iend) 726 { 727 return gomp_loop_ull_dynamic_next (istart, iend); 728 } 729 730 bool 731 GOMP_loop_ull_nonmonotonic_guided_next (gomp_ull *istart, gomp_ull *iend) 732 { 733 return gomp_loop_ull_guided_next (istart, iend); 734 } 735 736 bool 737 GOMP_loop_ull_ordered_static_next (gomp_ull *istart, gomp_ull *iend) 738 { 739 return gomp_loop_ull_ordered_static_next (istart, iend); 740 } 741 742 bool 743 GOMP_loop_ull_ordered_dynamic_next (gomp_ull *istart, gomp_ull *iend) 744 { 745 return gomp_loop_ull_ordered_dynamic_next (istart, iend); 746 } 747 748 bool 749 GOMP_loop_ull_ordered_guided_next (gomp_ull *istart, gomp_ull *iend) 750 { 751 return gomp_loop_ull_ordered_guided_next (istart, iend); 752 } 753 #endif 754