1 /* 2 * kmp_tasking.cpp -- OpenMP 3.0 tasking support. 3 */ 4 5 //===----------------------------------------------------------------------===// 6 // 7 // The LLVM Compiler Infrastructure 8 // 9 // This file is dual licensed under the MIT and the University of Illinois Open 10 // Source Licenses. See LICENSE.txt for details. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "kmp.h" 15 #include "kmp_i18n.h" 16 #include "kmp_itt.h" 17 #include "kmp_stats.h" 18 #include "kmp_wait_release.h" 19 20 #if OMPT_SUPPORT 21 #include "ompt-specific.h" 22 #endif 23 24 #include "tsan_annotations.h" 25 26 /* forward declaration */ 27 static void __kmp_enable_tasking(kmp_task_team_t *task_team, 28 kmp_info_t *this_thr); 29 static void __kmp_alloc_task_deque(kmp_info_t *thread, 30 kmp_thread_data_t *thread_data); 31 static int __kmp_realloc_task_threads_data(kmp_info_t *thread, 32 kmp_task_team_t *task_team); 33 34 #ifdef OMP_45_ENABLED 35 static void __kmp_bottom_half_finish_proxy(kmp_int32 gtid, kmp_task_t *ptask); 36 #endif 37 38 #ifdef BUILD_TIED_TASK_STACK 39 40 // __kmp_trace_task_stack: print the tied tasks from the task stack in order 41 // from top do bottom 42 // 43 // gtid: global thread identifier for thread containing stack 44 // thread_data: thread data for task team thread containing stack 45 // threshold: value above which the trace statement triggers 46 // location: string identifying call site of this function (for trace) 47 static void __kmp_trace_task_stack(kmp_int32 gtid, 48 kmp_thread_data_t *thread_data, 49 int threshold, char *location) { 50 kmp_task_stack_t *task_stack = &thread_data->td.td_susp_tied_tasks; 51 kmp_taskdata_t **stack_top = task_stack->ts_top; 52 kmp_int32 entries = task_stack->ts_entries; 53 kmp_taskdata_t *tied_task; 54 55 KA_TRACE( 56 threshold, 57 ("__kmp_trace_task_stack(start): location = %s, gtid = %d, entries = %d, " 58 "first_block = %p, stack_top = %p \n", 59 location, gtid, entries, task_stack->ts_first_block, stack_top)); 60 61 KMP_DEBUG_ASSERT(stack_top != NULL); 62 KMP_DEBUG_ASSERT(entries > 0); 63 64 while (entries != 0) { 65 KMP_DEBUG_ASSERT(stack_top != &task_stack->ts_first_block.sb_block[0]); 66 // fix up ts_top if we need to pop from previous block 67 if (entries & TASK_STACK_INDEX_MASK == 0) { 68 kmp_stack_block_t *stack_block = (kmp_stack_block_t *)(stack_top); 69 70 stack_block = stack_block->sb_prev; 71 stack_top = &stack_block->sb_block[TASK_STACK_BLOCK_SIZE]; 72 } 73 74 // finish bookkeeping 75 stack_top--; 76 entries--; 77 78 tied_task = *stack_top; 79 80 KMP_DEBUG_ASSERT(tied_task != NULL); 81 KMP_DEBUG_ASSERT(tied_task->td_flags.tasktype == TASK_TIED); 82 83 KA_TRACE(threshold, 84 ("__kmp_trace_task_stack(%s): gtid=%d, entry=%d, " 85 "stack_top=%p, tied_task=%p\n", 86 location, gtid, entries, stack_top, tied_task)); 87 } 88 KMP_DEBUG_ASSERT(stack_top == &task_stack->ts_first_block.sb_block[0]); 89 90 KA_TRACE(threshold, 91 ("__kmp_trace_task_stack(exit): location = %s, gtid = %d\n", 92 location, gtid)); 93 } 94 95 // __kmp_init_task_stack: initialize the task stack for the first time 96 // after a thread_data structure is created. 97 // It should not be necessary to do this again (assuming the stack works). 98 // 99 // gtid: global thread identifier of calling thread 100 // thread_data: thread data for task team thread containing stack 101 static void __kmp_init_task_stack(kmp_int32 gtid, 102 kmp_thread_data_t *thread_data) { 103 kmp_task_stack_t *task_stack = &thread_data->td.td_susp_tied_tasks; 104 kmp_stack_block_t *first_block; 105 106 // set up the first block of the stack 107 first_block = &task_stack->ts_first_block; 108 task_stack->ts_top = (kmp_taskdata_t **)first_block; 109 memset((void *)first_block, '\0', 110 TASK_STACK_BLOCK_SIZE * sizeof(kmp_taskdata_t *)); 111 112 // initialize the stack to be empty 113 task_stack->ts_entries = TASK_STACK_EMPTY; 114 first_block->sb_next = NULL; 115 first_block->sb_prev = NULL; 116 } 117 118 // __kmp_free_task_stack: free the task stack when thread_data is destroyed. 119 // 120 // gtid: global thread identifier for calling thread 121 // thread_data: thread info for thread containing stack 122 static void __kmp_free_task_stack(kmp_int32 gtid, 123 kmp_thread_data_t *thread_data) { 124 kmp_task_stack_t *task_stack = &thread_data->td.td_susp_tied_tasks; 125 kmp_stack_block_t *stack_block = &task_stack->ts_first_block; 126 127 KMP_DEBUG_ASSERT(task_stack->ts_entries == TASK_STACK_EMPTY); 128 // free from the second block of the stack 129 while (stack_block != NULL) { 130 kmp_stack_block_t *next_block = (stack_block) ? stack_block->sb_next : NULL; 131 132 stack_block->sb_next = NULL; 133 stack_block->sb_prev = NULL; 134 if (stack_block != &task_stack->ts_first_block) { 135 __kmp_thread_free(thread, 136 stack_block); // free the block, if not the first 137 } 138 stack_block = next_block; 139 } 140 // initialize the stack to be empty 141 task_stack->ts_entries = 0; 142 task_stack->ts_top = NULL; 143 } 144 145 // __kmp_push_task_stack: Push the tied task onto the task stack. 146 // Grow the stack if necessary by allocating another block. 147 // 148 // gtid: global thread identifier for calling thread 149 // thread: thread info for thread containing stack 150 // tied_task: the task to push on the stack 151 static void __kmp_push_task_stack(kmp_int32 gtid, kmp_info_t *thread, 152 kmp_taskdata_t *tied_task) { 153 // GEH - need to consider what to do if tt_threads_data not allocated yet 154 kmp_thread_data_t *thread_data = 155 &thread->th.th_task_team->tt.tt_threads_data[__kmp_tid_from_gtid(gtid)]; 156 kmp_task_stack_t *task_stack = &thread_data->td.td_susp_tied_tasks; 157 158 if (tied_task->td_flags.team_serial || tied_task->td_flags.tasking_ser) { 159 return; // Don't push anything on stack if team or team tasks are serialized 160 } 161 162 KMP_DEBUG_ASSERT(tied_task->td_flags.tasktype == TASK_TIED); 163 KMP_DEBUG_ASSERT(task_stack->ts_top != NULL); 164 165 KA_TRACE(20, 166 ("__kmp_push_task_stack(enter): GTID: %d; THREAD: %p; TASK: %p\n", 167 gtid, thread, tied_task)); 168 // Store entry 169 *(task_stack->ts_top) = tied_task; 170 171 // Do bookkeeping for next push 172 task_stack->ts_top++; 173 task_stack->ts_entries++; 174 175 if (task_stack->ts_entries & TASK_STACK_INDEX_MASK == 0) { 176 // Find beginning of this task block 177 kmp_stack_block_t *stack_block = 178 (kmp_stack_block_t *)(task_stack->ts_top - TASK_STACK_BLOCK_SIZE); 179 180 // Check if we already have a block 181 if (stack_block->sb_next != 182 NULL) { // reset ts_top to beginning of next block 183 task_stack->ts_top = &stack_block->sb_next->sb_block[0]; 184 } else { // Alloc new block and link it up 185 kmp_stack_block_t *new_block = (kmp_stack_block_t *)__kmp_thread_calloc( 186 thread, sizeof(kmp_stack_block_t)); 187 188 task_stack->ts_top = &new_block->sb_block[0]; 189 stack_block->sb_next = new_block; 190 new_block->sb_prev = stack_block; 191 new_block->sb_next = NULL; 192 193 KA_TRACE( 194 30, 195 ("__kmp_push_task_stack(): GTID: %d; TASK: %p; Alloc new block: %p\n", 196 gtid, tied_task, new_block)); 197 } 198 } 199 KA_TRACE(20, ("__kmp_push_task_stack(exit): GTID: %d; TASK: %p\n", gtid, 200 tied_task)); 201 } 202 203 // __kmp_pop_task_stack: Pop the tied task from the task stack. Don't return 204 // the task, just check to make sure it matches the ending task passed in. 205 // 206 // gtid: global thread identifier for the calling thread 207 // thread: thread info structure containing stack 208 // tied_task: the task popped off the stack 209 // ending_task: the task that is ending (should match popped task) 210 static void __kmp_pop_task_stack(kmp_int32 gtid, kmp_info_t *thread, 211 kmp_taskdata_t *ending_task) { 212 // GEH - need to consider what to do if tt_threads_data not allocated yet 213 kmp_thread_data_t *thread_data = 214 &thread->th.th_task_team->tt_threads_data[__kmp_tid_from_gtid(gtid)]; 215 kmp_task_stack_t *task_stack = &thread_data->td.td_susp_tied_tasks; 216 kmp_taskdata_t *tied_task; 217 218 if (ending_task->td_flags.team_serial || ending_task->td_flags.tasking_ser) { 219 // Don't pop anything from stack if team or team tasks are serialized 220 return; 221 } 222 223 KMP_DEBUG_ASSERT(task_stack->ts_top != NULL); 224 KMP_DEBUG_ASSERT(task_stack->ts_entries > 0); 225 226 KA_TRACE(20, ("__kmp_pop_task_stack(enter): GTID: %d; THREAD: %p\n", gtid, 227 thread)); 228 229 // fix up ts_top if we need to pop from previous block 230 if (task_stack->ts_entries & TASK_STACK_INDEX_MASK == 0) { 231 kmp_stack_block_t *stack_block = (kmp_stack_block_t *)(task_stack->ts_top); 232 233 stack_block = stack_block->sb_prev; 234 task_stack->ts_top = &stack_block->sb_block[TASK_STACK_BLOCK_SIZE]; 235 } 236 237 // finish bookkeeping 238 task_stack->ts_top--; 239 task_stack->ts_entries--; 240 241 tied_task = *(task_stack->ts_top); 242 243 KMP_DEBUG_ASSERT(tied_task != NULL); 244 KMP_DEBUG_ASSERT(tied_task->td_flags.tasktype == TASK_TIED); 245 KMP_DEBUG_ASSERT(tied_task == ending_task); // If we built the stack correctly 246 247 KA_TRACE(20, ("__kmp_pop_task_stack(exit): GTID: %d; TASK: %p\n", gtid, 248 tied_task)); 249 return; 250 } 251 #endif /* BUILD_TIED_TASK_STACK */ 252 253 // __kmp_push_task: Add a task to the thread's deque 254 static kmp_int32 __kmp_push_task(kmp_int32 gtid, kmp_task_t *task) { 255 kmp_info_t *thread = __kmp_threads[gtid]; 256 kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(task); 257 kmp_task_team_t *task_team = thread->th.th_task_team; 258 kmp_int32 tid = __kmp_tid_from_gtid(gtid); 259 kmp_thread_data_t *thread_data; 260 261 KA_TRACE(20, 262 ("__kmp_push_task: T#%d trying to push task %p.\n", gtid, taskdata)); 263 264 if (taskdata->td_flags.tiedness == TASK_UNTIED) { 265 // untied task needs to increment counter so that the task structure is not 266 // freed prematurely 267 kmp_int32 counter = 1 + KMP_TEST_THEN_INC32(&taskdata->td_untied_count); 268 KA_TRACE( 269 20, 270 ("__kmp_push_task: T#%d untied_count (%d) incremented for task %p\n", 271 gtid, counter, taskdata)); 272 } 273 274 // The first check avoids building task_team thread data if serialized 275 if (taskdata->td_flags.task_serial) { 276 KA_TRACE(20, ("__kmp_push_task: T#%d team serialized; returning " 277 "TASK_NOT_PUSHED for task %p\n", 278 gtid, taskdata)); 279 return TASK_NOT_PUSHED; 280 } 281 282 // Now that serialized tasks have returned, we can assume that we are not in 283 // immediate exec mode 284 KMP_DEBUG_ASSERT(__kmp_tasking_mode != tskm_immediate_exec); 285 if (!KMP_TASKING_ENABLED(task_team)) { 286 __kmp_enable_tasking(task_team, thread); 287 } 288 KMP_DEBUG_ASSERT(TCR_4(task_team->tt.tt_found_tasks) == TRUE); 289 KMP_DEBUG_ASSERT(TCR_PTR(task_team->tt.tt_threads_data) != NULL); 290 291 // Find tasking deque specific to encountering thread 292 thread_data = &task_team->tt.tt_threads_data[tid]; 293 294 // No lock needed since only owner can allocate 295 if (thread_data->td.td_deque == NULL) { 296 __kmp_alloc_task_deque(thread, thread_data); 297 } 298 299 // Check if deque is full 300 if (TCR_4(thread_data->td.td_deque_ntasks) >= 301 TASK_DEQUE_SIZE(thread_data->td)) { 302 KA_TRACE(20, ("__kmp_push_task: T#%d deque is full; returning " 303 "TASK_NOT_PUSHED for task %p\n", 304 gtid, taskdata)); 305 return TASK_NOT_PUSHED; 306 } 307 308 // Lock the deque for the task push operation 309 __kmp_acquire_bootstrap_lock(&thread_data->td.td_deque_lock); 310 311 #if OMP_45_ENABLED 312 // Need to recheck as we can get a proxy task from a thread outside of OpenMP 313 if (TCR_4(thread_data->td.td_deque_ntasks) >= 314 TASK_DEQUE_SIZE(thread_data->td)) { 315 __kmp_release_bootstrap_lock(&thread_data->td.td_deque_lock); 316 KA_TRACE(20, ("__kmp_push_task: T#%d deque is full on 2nd check; returning " 317 "TASK_NOT_PUSHED for task %p\n", 318 gtid, taskdata)); 319 return TASK_NOT_PUSHED; 320 } 321 #else 322 // Must have room since no thread can add tasks but calling thread 323 KMP_DEBUG_ASSERT(TCR_4(thread_data->td.td_deque_ntasks) < 324 TASK_DEQUE_SIZE(thread_data->td)); 325 #endif 326 327 thread_data->td.td_deque[thread_data->td.td_deque_tail] = 328 taskdata; // Push taskdata 329 // Wrap index. 330 thread_data->td.td_deque_tail = 331 (thread_data->td.td_deque_tail + 1) & TASK_DEQUE_MASK(thread_data->td); 332 TCW_4(thread_data->td.td_deque_ntasks, 333 TCR_4(thread_data->td.td_deque_ntasks) + 1); // Adjust task count 334 335 KA_TRACE(20, ("__kmp_push_task: T#%d returning TASK_SUCCESSFULLY_PUSHED: " 336 "task=%p ntasks=%d head=%u tail=%u\n", 337 gtid, taskdata, thread_data->td.td_deque_ntasks, 338 thread_data->td.td_deque_head, thread_data->td.td_deque_tail)); 339 340 __kmp_release_bootstrap_lock(&thread_data->td.td_deque_lock); 341 342 return TASK_SUCCESSFULLY_PUSHED; 343 } 344 345 // __kmp_pop_current_task_from_thread: set up current task from called thread 346 // when team ends 347 // 348 // this_thr: thread structure to set current_task in. 349 void __kmp_pop_current_task_from_thread(kmp_info_t *this_thr) { 350 KF_TRACE(10, ("__kmp_pop_current_task_from_thread(enter): T#%d " 351 "this_thread=%p, curtask=%p, " 352 "curtask_parent=%p\n", 353 0, this_thr, this_thr->th.th_current_task, 354 this_thr->th.th_current_task->td_parent)); 355 356 this_thr->th.th_current_task = this_thr->th.th_current_task->td_parent; 357 358 KF_TRACE(10, ("__kmp_pop_current_task_from_thread(exit): T#%d " 359 "this_thread=%p, curtask=%p, " 360 "curtask_parent=%p\n", 361 0, this_thr, this_thr->th.th_current_task, 362 this_thr->th.th_current_task->td_parent)); 363 } 364 365 // __kmp_push_current_task_to_thread: set up current task in called thread for a 366 // new team 367 // 368 // this_thr: thread structure to set up 369 // team: team for implicit task data 370 // tid: thread within team to set up 371 void __kmp_push_current_task_to_thread(kmp_info_t *this_thr, kmp_team_t *team, 372 int tid) { 373 // current task of the thread is a parent of the new just created implicit 374 // tasks of new team 375 KF_TRACE(10, ("__kmp_push_current_task_to_thread(enter): T#%d this_thread=%p " 376 "curtask=%p " 377 "parent_task=%p\n", 378 tid, this_thr, this_thr->th.th_current_task, 379 team->t.t_implicit_task_taskdata[tid].td_parent)); 380 381 KMP_DEBUG_ASSERT(this_thr != NULL); 382 383 if (tid == 0) { 384 if (this_thr->th.th_current_task != &team->t.t_implicit_task_taskdata[0]) { 385 team->t.t_implicit_task_taskdata[0].td_parent = 386 this_thr->th.th_current_task; 387 this_thr->th.th_current_task = &team->t.t_implicit_task_taskdata[0]; 388 } 389 } else { 390 team->t.t_implicit_task_taskdata[tid].td_parent = 391 team->t.t_implicit_task_taskdata[0].td_parent; 392 this_thr->th.th_current_task = &team->t.t_implicit_task_taskdata[tid]; 393 } 394 395 KF_TRACE(10, ("__kmp_push_current_task_to_thread(exit): T#%d this_thread=%p " 396 "curtask=%p " 397 "parent_task=%p\n", 398 tid, this_thr, this_thr->th.th_current_task, 399 team->t.t_implicit_task_taskdata[tid].td_parent)); 400 } 401 402 // __kmp_task_start: bookkeeping for a task starting execution 403 // 404 // GTID: global thread id of calling thread 405 // task: task starting execution 406 // current_task: task suspending 407 static void __kmp_task_start(kmp_int32 gtid, kmp_task_t *task, 408 kmp_taskdata_t *current_task) { 409 kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(task); 410 kmp_info_t *thread = __kmp_threads[gtid]; 411 412 KA_TRACE(10, 413 ("__kmp_task_start(enter): T#%d starting task %p: current_task=%p\n", 414 gtid, taskdata, current_task)); 415 416 KMP_DEBUG_ASSERT(taskdata->td_flags.tasktype == TASK_EXPLICIT); 417 418 // mark currently executing task as suspended 419 // TODO: GEH - make sure root team implicit task is initialized properly. 420 // KMP_DEBUG_ASSERT( current_task -> td_flags.executing == 1 ); 421 current_task->td_flags.executing = 0; 422 423 // Add task to stack if tied 424 #ifdef BUILD_TIED_TASK_STACK 425 if (taskdata->td_flags.tiedness == TASK_TIED) { 426 __kmp_push_task_stack(gtid, thread, taskdata); 427 } 428 #endif /* BUILD_TIED_TASK_STACK */ 429 430 // mark starting task as executing and as current task 431 thread->th.th_current_task = taskdata; 432 433 KMP_DEBUG_ASSERT(taskdata->td_flags.started == 0 || 434 taskdata->td_flags.tiedness == TASK_UNTIED); 435 KMP_DEBUG_ASSERT(taskdata->td_flags.executing == 0 || 436 taskdata->td_flags.tiedness == TASK_UNTIED); 437 taskdata->td_flags.started = 1; 438 taskdata->td_flags.executing = 1; 439 KMP_DEBUG_ASSERT(taskdata->td_flags.complete == 0); 440 KMP_DEBUG_ASSERT(taskdata->td_flags.freed == 0); 441 442 // GEH TODO: shouldn't we pass some sort of location identifier here? 443 // APT: yes, we will pass location here. 444 // need to store current thread state (in a thread or taskdata structure) 445 // before setting work_state, otherwise wrong state is set after end of task 446 447 KA_TRACE(10, ("__kmp_task_start(exit): T#%d task=%p\n", gtid, taskdata)); 448 449 #if OMPT_SUPPORT 450 if (ompt_enabled && ompt_callbacks.ompt_callback(ompt_event_task_begin)) { 451 kmp_taskdata_t *parent = taskdata->td_parent; 452 ompt_callbacks.ompt_callback(ompt_event_task_begin)( 453 parent ? parent->ompt_task_info.task_id : ompt_task_id_none, 454 parent ? &(parent->ompt_task_info.frame) : NULL, 455 taskdata->ompt_task_info.task_id, taskdata->ompt_task_info.function); 456 } 457 #endif 458 #if OMP_40_ENABLED && OMPT_SUPPORT && OMPT_TRACE 459 /* OMPT emit all dependences if requested by the tool */ 460 if (ompt_enabled && taskdata->ompt_task_info.ndeps > 0 && 461 ompt_callbacks.ompt_callback(ompt_event_task_dependences)) { 462 ompt_callbacks.ompt_callback(ompt_event_task_dependences)( 463 taskdata->ompt_task_info.task_id, taskdata->ompt_task_info.deps, 464 taskdata->ompt_task_info.ndeps); 465 /* We can now free the allocated memory for the dependencies */ 466 KMP_OMPT_DEPS_FREE(thread, taskdata->ompt_task_info.deps); 467 taskdata->ompt_task_info.deps = NULL; 468 taskdata->ompt_task_info.ndeps = 0; 469 } 470 #endif /* OMP_40_ENABLED && OMPT_SUPPORT && OMPT_TRACE */ 471 472 return; 473 } 474 475 // __kmpc_omp_task_begin_if0: report that a given serialized task has started 476 // execution 477 // 478 // loc_ref: source location information; points to beginning of task block. 479 // gtid: global thread number. 480 // task: task thunk for the started task. 481 void __kmpc_omp_task_begin_if0(ident_t *loc_ref, kmp_int32 gtid, 482 kmp_task_t *task) { 483 kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(task); 484 kmp_taskdata_t *current_task = __kmp_threads[gtid]->th.th_current_task; 485 486 KA_TRACE(10, ("__kmpc_omp_task_begin_if0(enter): T#%d loc=%p task=%p " 487 "current_task=%p\n", 488 gtid, loc_ref, taskdata, current_task)); 489 490 if (taskdata->td_flags.tiedness == TASK_UNTIED) { 491 // untied task needs to increment counter so that the task structure is not 492 // freed prematurely 493 kmp_int32 counter = 1 + KMP_TEST_THEN_INC32(&taskdata->td_untied_count); 494 KA_TRACE(20, ("__kmpc_omp_task_begin_if0: T#%d untied_count (%d) " 495 "incremented for task %p\n", 496 gtid, counter, taskdata)); 497 } 498 499 taskdata->td_flags.task_serial = 500 1; // Execute this task immediately, not deferred. 501 __kmp_task_start(gtid, task, current_task); 502 503 KA_TRACE(10, ("__kmpc_omp_task_begin_if0(exit): T#%d loc=%p task=%p,\n", gtid, 504 loc_ref, taskdata)); 505 506 return; 507 } 508 509 #ifdef TASK_UNUSED 510 // __kmpc_omp_task_begin: report that a given task has started execution 511 // NEVER GENERATED BY COMPILER, DEPRECATED!!! 512 void __kmpc_omp_task_begin(ident_t *loc_ref, kmp_int32 gtid, kmp_task_t *task) { 513 kmp_taskdata_t *current_task = __kmp_threads[gtid]->th.th_current_task; 514 515 KA_TRACE( 516 10, 517 ("__kmpc_omp_task_begin(enter): T#%d loc=%p task=%p current_task=%p\n", 518 gtid, loc_ref, KMP_TASK_TO_TASKDATA(task), current_task)); 519 520 __kmp_task_start(gtid, task, current_task); 521 522 KA_TRACE(10, ("__kmpc_omp_task_begin(exit): T#%d loc=%p task=%p,\n", gtid, 523 loc_ref, KMP_TASK_TO_TASKDATA(task))); 524 return; 525 } 526 #endif // TASK_UNUSED 527 528 // __kmp_free_task: free the current task space and the space for shareds 529 // 530 // gtid: Global thread ID of calling thread 531 // taskdata: task to free 532 // thread: thread data structure of caller 533 static void __kmp_free_task(kmp_int32 gtid, kmp_taskdata_t *taskdata, 534 kmp_info_t *thread) { 535 KA_TRACE(30, ("__kmp_free_task: T#%d freeing data from task %p\n", gtid, 536 taskdata)); 537 538 // Check to make sure all flags and counters have the correct values 539 KMP_DEBUG_ASSERT(taskdata->td_flags.tasktype == TASK_EXPLICIT); 540 KMP_DEBUG_ASSERT(taskdata->td_flags.executing == 0); 541 KMP_DEBUG_ASSERT(taskdata->td_flags.complete == 1); 542 KMP_DEBUG_ASSERT(taskdata->td_flags.freed == 0); 543 KMP_DEBUG_ASSERT(TCR_4(taskdata->td_allocated_child_tasks) == 0 || 544 taskdata->td_flags.task_serial == 1); 545 KMP_DEBUG_ASSERT(TCR_4(taskdata->td_incomplete_child_tasks) == 0); 546 547 taskdata->td_flags.freed = 1; 548 ANNOTATE_HAPPENS_BEFORE(taskdata); 549 // deallocate the taskdata and shared variable blocks associated with this task 550 #if USE_FAST_MEMORY 551 __kmp_fast_free(thread, taskdata); 552 #else /* ! USE_FAST_MEMORY */ 553 __kmp_thread_free(thread, taskdata); 554 #endif 555 556 KA_TRACE(20, ("__kmp_free_task: T#%d freed task %p\n", gtid, taskdata)); 557 } 558 559 // __kmp_free_task_and_ancestors: free the current task and ancestors without 560 // children 561 // 562 // gtid: Global thread ID of calling thread 563 // taskdata: task to free 564 // thread: thread data structure of caller 565 static void __kmp_free_task_and_ancestors(kmp_int32 gtid, 566 kmp_taskdata_t *taskdata, 567 kmp_info_t *thread) { 568 #if OMP_45_ENABLED 569 // Proxy tasks must always be allowed to free their parents 570 // because they can be run in background even in serial mode. 571 kmp_int32 team_serial = 572 (taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser) && 573 !taskdata->td_flags.proxy; 574 #else 575 kmp_int32 team_serial = 576 taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser; 577 #endif 578 KMP_DEBUG_ASSERT(taskdata->td_flags.tasktype == TASK_EXPLICIT); 579 580 kmp_int32 children = 581 KMP_TEST_THEN_DEC32(&taskdata->td_allocated_child_tasks) - 1; 582 KMP_DEBUG_ASSERT(children >= 0); 583 584 // Now, go up the ancestor tree to see if any ancestors can now be freed. 585 while (children == 0) { 586 kmp_taskdata_t *parent_taskdata = taskdata->td_parent; 587 588 KA_TRACE(20, ("__kmp_free_task_and_ancestors(enter): T#%d task %p complete " 589 "and freeing itself\n", 590 gtid, taskdata)); 591 592 // --- Deallocate my ancestor task --- 593 __kmp_free_task(gtid, taskdata, thread); 594 595 taskdata = parent_taskdata; 596 597 // Stop checking ancestors at implicit task instead of walking up ancestor 598 // tree to avoid premature deallocation of ancestors. 599 if (team_serial || taskdata->td_flags.tasktype == TASK_IMPLICIT) 600 return; 601 602 // Predecrement simulated by "- 1" calculation 603 children = KMP_TEST_THEN_DEC32(&taskdata->td_allocated_child_tasks) - 1; 604 KMP_DEBUG_ASSERT(children >= 0); 605 } 606 607 KA_TRACE( 608 20, ("__kmp_free_task_and_ancestors(exit): T#%d task %p has %d children; " 609 "not freeing it yet\n", 610 gtid, taskdata, children)); 611 } 612 613 // __kmp_task_finish: bookkeeping to do when a task finishes execution 614 // 615 // gtid: global thread ID for calling thread 616 // task: task to be finished 617 // resumed_task: task to be resumed. (may be NULL if task is serialized) 618 static void __kmp_task_finish(kmp_int32 gtid, kmp_task_t *task, 619 kmp_taskdata_t *resumed_task) { 620 kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(task); 621 kmp_info_t *thread = __kmp_threads[gtid]; 622 kmp_task_team_t *task_team = 623 thread->th.th_task_team; // might be NULL for serial teams... 624 kmp_int32 children = 0; 625 626 #if OMPT_SUPPORT 627 if (ompt_enabled && ompt_callbacks.ompt_callback(ompt_event_task_end)) { 628 kmp_taskdata_t *parent = taskdata->td_parent; 629 ompt_callbacks.ompt_callback(ompt_event_task_end)( 630 taskdata->ompt_task_info.task_id); 631 } 632 #endif 633 634 KA_TRACE(10, ("__kmp_task_finish(enter): T#%d finishing task %p and resuming " 635 "task %p\n", 636 gtid, taskdata, resumed_task)); 637 638 KMP_DEBUG_ASSERT(taskdata->td_flags.tasktype == TASK_EXPLICIT); 639 640 // Pop task from stack if tied 641 #ifdef BUILD_TIED_TASK_STACK 642 if (taskdata->td_flags.tiedness == TASK_TIED) { 643 __kmp_pop_task_stack(gtid, thread, taskdata); 644 } 645 #endif /* BUILD_TIED_TASK_STACK */ 646 647 if (taskdata->td_flags.tiedness == TASK_UNTIED) { 648 // untied task needs to check the counter so that the task structure is not 649 // freed prematurely 650 kmp_int32 counter = KMP_TEST_THEN_DEC32(&taskdata->td_untied_count) - 1; 651 KA_TRACE( 652 20, 653 ("__kmp_task_finish: T#%d untied_count (%d) decremented for task %p\n", 654 gtid, counter, taskdata)); 655 if (counter > 0) { 656 // untied task is not done, to be continued possibly by other thread, do 657 // not free it now 658 if (resumed_task == NULL) { 659 KMP_DEBUG_ASSERT(taskdata->td_flags.task_serial); 660 resumed_task = taskdata->td_parent; // In a serialized task, the resumed 661 // task is the parent 662 } 663 thread->th.th_current_task = resumed_task; // restore current_task 664 resumed_task->td_flags.executing = 1; // resume previous task 665 KA_TRACE(10, ("__kmp_task_finish(exit): T#%d partially done task %p, " 666 "resuming task %p\n", 667 gtid, taskdata, resumed_task)); 668 return; 669 } 670 } 671 672 KMP_DEBUG_ASSERT(taskdata->td_flags.complete == 0); 673 taskdata->td_flags.complete = 1; // mark the task as completed 674 KMP_DEBUG_ASSERT(taskdata->td_flags.started == 1); 675 KMP_DEBUG_ASSERT(taskdata->td_flags.freed == 0); 676 677 // Only need to keep track of count if team parallel and tasking not 678 // serialized 679 if (!(taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser)) { 680 // Predecrement simulated by "- 1" calculation 681 children = 682 KMP_TEST_THEN_DEC32(&taskdata->td_parent->td_incomplete_child_tasks) - 683 1; 684 KMP_DEBUG_ASSERT(children >= 0); 685 #if OMP_40_ENABLED 686 if (taskdata->td_taskgroup) 687 KMP_TEST_THEN_DEC32((kmp_int32 *)(&taskdata->td_taskgroup->count)); 688 #if OMP_45_ENABLED 689 } 690 // if we found proxy tasks there could exist a dependency chain 691 // with the proxy task as origin 692 if (!(taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser) || 693 (task_team && task_team->tt.tt_found_proxy_tasks)) { 694 #endif 695 __kmp_release_deps(gtid, taskdata); 696 #endif 697 } 698 699 // td_flags.executing must be marked as 0 after __kmp_release_deps has been 700 // called. Othertwise, if a task is executed immediately from the release_deps 701 // code, the flag will be reset to 1 again by this same function 702 KMP_DEBUG_ASSERT(taskdata->td_flags.executing == 1); 703 taskdata->td_flags.executing = 0; // suspend the finishing task 704 705 KA_TRACE( 706 20, ("__kmp_task_finish: T#%d finished task %p, %d incomplete children\n", 707 gtid, taskdata, children)); 708 709 #if OMP_40_ENABLED 710 /* If the tasks' destructor thunk flag has been set, we need to invoke the 711 destructor thunk that has been generated by the compiler. The code is 712 placed here, since at this point other tasks might have been released 713 hence overlapping the destructor invokations with some other work in the 714 released tasks. The OpenMP spec is not specific on when the destructors 715 are invoked, so we should be free to choose. */ 716 if (taskdata->td_flags.destructors_thunk) { 717 kmp_routine_entry_t destr_thunk = task->data1.destructors; 718 KMP_ASSERT(destr_thunk); 719 destr_thunk(gtid, task); 720 } 721 #endif // OMP_40_ENABLED 722 723 // bookkeeping for resuming task: 724 // GEH - note tasking_ser => task_serial 725 KMP_DEBUG_ASSERT( 726 (taskdata->td_flags.tasking_ser || taskdata->td_flags.task_serial) == 727 taskdata->td_flags.task_serial); 728 if (taskdata->td_flags.task_serial) { 729 if (resumed_task == NULL) { 730 resumed_task = taskdata->td_parent; // In a serialized task, the resumed 731 // task is the parent 732 } else 733 #if OMP_45_ENABLED 734 if (!(task_team && task_team->tt.tt_found_proxy_tasks)) 735 #endif 736 { 737 // verify resumed task passed in points to parent 738 KMP_DEBUG_ASSERT(resumed_task == taskdata->td_parent); 739 } 740 } else { 741 KMP_DEBUG_ASSERT(resumed_task != 742 NULL); // verify that resumed task is passed as arguemnt 743 } 744 745 // Free this task and then ancestor tasks if they have no children. 746 // Restore th_current_task first as suggested by John: 747 // johnmc: if an asynchronous inquiry peers into the runtime system 748 // it doesn't see the freed task as the current task. 749 thread->th.th_current_task = resumed_task; 750 __kmp_free_task_and_ancestors(gtid, taskdata, thread); 751 752 // TODO: GEH - make sure root team implicit task is initialized properly. 753 // KMP_DEBUG_ASSERT( resumed_task->td_flags.executing == 0 ); 754 resumed_task->td_flags.executing = 1; // resume previous task 755 756 KA_TRACE( 757 10, ("__kmp_task_finish(exit): T#%d finished task %p, resuming task %p\n", 758 gtid, taskdata, resumed_task)); 759 760 return; 761 } 762 763 // __kmpc_omp_task_complete_if0: report that a task has completed execution 764 // 765 // loc_ref: source location information; points to end of task block. 766 // gtid: global thread number. 767 // task: task thunk for the completed task. 768 void __kmpc_omp_task_complete_if0(ident_t *loc_ref, kmp_int32 gtid, 769 kmp_task_t *task) { 770 KA_TRACE(10, ("__kmpc_omp_task_complete_if0(enter): T#%d loc=%p task=%p\n", 771 gtid, loc_ref, KMP_TASK_TO_TASKDATA(task))); 772 // this routine will provide task to resume 773 __kmp_task_finish(gtid, task, NULL); 774 775 KA_TRACE(10, ("__kmpc_omp_task_complete_if0(exit): T#%d loc=%p task=%p\n", 776 gtid, loc_ref, KMP_TASK_TO_TASKDATA(task))); 777 return; 778 } 779 780 #ifdef TASK_UNUSED 781 // __kmpc_omp_task_complete: report that a task has completed execution 782 // NEVER GENERATED BY COMPILER, DEPRECATED!!! 783 void __kmpc_omp_task_complete(ident_t *loc_ref, kmp_int32 gtid, 784 kmp_task_t *task) { 785 KA_TRACE(10, ("__kmpc_omp_task_complete(enter): T#%d loc=%p task=%p\n", gtid, 786 loc_ref, KMP_TASK_TO_TASKDATA(task))); 787 788 __kmp_task_finish(gtid, task, NULL); // Not sure how to find task to resume 789 790 KA_TRACE(10, ("__kmpc_omp_task_complete(exit): T#%d loc=%p task=%p\n", gtid, 791 loc_ref, KMP_TASK_TO_TASKDATA(task))); 792 return; 793 } 794 #endif // TASK_UNUSED 795 796 #if OMPT_SUPPORT 797 // __kmp_task_init_ompt: Initialize OMPT fields maintained by a task. This will 798 // only be called after ompt_tool, so we already know whether ompt is enabled 799 // or not. 800 static inline void __kmp_task_init_ompt(kmp_taskdata_t *task, int tid, 801 void *function) { 802 if (ompt_enabled) { 803 task->ompt_task_info.task_id = __ompt_task_id_new(tid); 804 task->ompt_task_info.function = function; 805 task->ompt_task_info.frame.exit_runtime_frame = NULL; 806 task->ompt_task_info.frame.reenter_runtime_frame = NULL; 807 #if OMP_40_ENABLED 808 task->ompt_task_info.ndeps = 0; 809 task->ompt_task_info.deps = NULL; 810 #endif /* OMP_40_ENABLED */ 811 } 812 } 813 #endif 814 815 // __kmp_init_implicit_task: Initialize the appropriate fields in the implicit 816 // task for a given thread 817 // 818 // loc_ref: reference to source location of parallel region 819 // this_thr: thread data structure corresponding to implicit task 820 // team: team for this_thr 821 // tid: thread id of given thread within team 822 // set_curr_task: TRUE if need to push current task to thread 823 // NOTE: Routine does not set up the implicit task ICVS. This is assumed to 824 // have already been done elsewhere. 825 // TODO: Get better loc_ref. Value passed in may be NULL 826 void __kmp_init_implicit_task(ident_t *loc_ref, kmp_info_t *this_thr, 827 kmp_team_t *team, int tid, int set_curr_task) { 828 kmp_taskdata_t *task = &team->t.t_implicit_task_taskdata[tid]; 829 830 KF_TRACE( 831 10, 832 ("__kmp_init_implicit_task(enter): T#:%d team=%p task=%p, reinit=%s\n", 833 tid, team, task, set_curr_task ? "TRUE" : "FALSE")); 834 835 task->td_task_id = KMP_GEN_TASK_ID(); 836 task->td_team = team; 837 // task->td_parent = NULL; // fix for CQ230101 (broken parent task info 838 // in debugger) 839 task->td_ident = loc_ref; 840 task->td_taskwait_ident = NULL; 841 task->td_taskwait_counter = 0; 842 task->td_taskwait_thread = 0; 843 844 task->td_flags.tiedness = TASK_TIED; 845 task->td_flags.tasktype = TASK_IMPLICIT; 846 #if OMP_45_ENABLED 847 task->td_flags.proxy = TASK_FULL; 848 #endif 849 850 // All implicit tasks are executed immediately, not deferred 851 task->td_flags.task_serial = 1; 852 task->td_flags.tasking_ser = (__kmp_tasking_mode == tskm_immediate_exec); 853 task->td_flags.team_serial = (team->t.t_serialized) ? 1 : 0; 854 855 task->td_flags.started = 1; 856 task->td_flags.executing = 1; 857 task->td_flags.complete = 0; 858 task->td_flags.freed = 0; 859 860 #if OMP_40_ENABLED 861 task->td_depnode = NULL; 862 #endif 863 864 if (set_curr_task) { // only do this init first time thread is created 865 task->td_incomplete_child_tasks = 0; 866 // Not used: don't need to deallocate implicit task 867 task->td_allocated_child_tasks = 0; 868 #if OMP_40_ENABLED 869 task->td_taskgroup = NULL; // An implicit task does not have taskgroup 870 task->td_dephash = NULL; 871 #endif 872 __kmp_push_current_task_to_thread(this_thr, team, tid); 873 } else { 874 KMP_DEBUG_ASSERT(task->td_incomplete_child_tasks == 0); 875 KMP_DEBUG_ASSERT(task->td_allocated_child_tasks == 0); 876 } 877 878 #if OMPT_SUPPORT 879 __kmp_task_init_ompt(task, tid, NULL); 880 #endif 881 882 KF_TRACE(10, ("__kmp_init_implicit_task(exit): T#:%d team=%p task=%p\n", tid, 883 team, task)); 884 } 885 886 // __kmp_finish_implicit_task: Release resources associated to implicit tasks 887 // at the end of parallel regions. Some resources are kept for reuse in the next 888 // parallel region. 889 // 890 // thread: thread data structure corresponding to implicit task 891 void __kmp_finish_implicit_task(kmp_info_t *thread) { 892 kmp_taskdata_t *task = thread->th.th_current_task; 893 if (task->td_dephash) 894 __kmp_dephash_free_entries(thread, task->td_dephash); 895 } 896 897 // __kmp_free_implicit_task: Release resources associated to implicit tasks 898 // when these are destroyed regions 899 // 900 // thread: thread data structure corresponding to implicit task 901 void __kmp_free_implicit_task(kmp_info_t *thread) { 902 kmp_taskdata_t *task = thread->th.th_current_task; 903 if (task->td_dephash) 904 __kmp_dephash_free(thread, task->td_dephash); 905 task->td_dephash = NULL; 906 } 907 908 // Round up a size to a power of two specified by val: Used to insert padding 909 // between structures co-allocated using a single malloc() call 910 static size_t __kmp_round_up_to_val(size_t size, size_t val) { 911 if (size & (val - 1)) { 912 size &= ~(val - 1); 913 if (size <= KMP_SIZE_T_MAX - val) { 914 size += val; // Round up if there is no overflow. 915 } 916 } 917 return size; 918 } // __kmp_round_up_to_va 919 920 // __kmp_task_alloc: Allocate the taskdata and task data structures for a task 921 // 922 // loc_ref: source location information 923 // gtid: global thread number. 924 // flags: include tiedness & task type (explicit vs. implicit) of the ''new'' 925 // task encountered. Converted from kmp_int32 to kmp_tasking_flags_t in routine. 926 // sizeof_kmp_task_t: Size in bytes of kmp_task_t data structure including 927 // private vars accessed in task. 928 // sizeof_shareds: Size in bytes of array of pointers to shared vars accessed 929 // in task. 930 // task_entry: Pointer to task code entry point generated by compiler. 931 // returns: a pointer to the allocated kmp_task_t structure (task). 932 kmp_task_t *__kmp_task_alloc(ident_t *loc_ref, kmp_int32 gtid, 933 kmp_tasking_flags_t *flags, 934 size_t sizeof_kmp_task_t, size_t sizeof_shareds, 935 kmp_routine_entry_t task_entry) { 936 kmp_task_t *task; 937 kmp_taskdata_t *taskdata; 938 kmp_info_t *thread = __kmp_threads[gtid]; 939 kmp_team_t *team = thread->th.th_team; 940 kmp_taskdata_t *parent_task = thread->th.th_current_task; 941 size_t shareds_offset; 942 943 KA_TRACE(10, ("__kmp_task_alloc(enter): T#%d loc=%p, flags=(0x%x) " 944 "sizeof_task=%ld sizeof_shared=%ld entry=%p\n", 945 gtid, loc_ref, *((kmp_int32 *)flags), sizeof_kmp_task_t, 946 sizeof_shareds, task_entry)); 947 948 if (parent_task->td_flags.final) { 949 if (flags->merged_if0) { 950 } 951 flags->final = 1; 952 } 953 954 #if OMP_45_ENABLED 955 if (flags->proxy == TASK_PROXY) { 956 flags->tiedness = TASK_UNTIED; 957 flags->merged_if0 = 1; 958 959 /* are we running in a sequential parallel or tskm_immediate_exec... we need 960 tasking support enabled */ 961 if ((thread->th.th_task_team) == NULL) { 962 /* This should only happen if the team is serialized 963 setup a task team and propagate it to the thread */ 964 KMP_DEBUG_ASSERT(team->t.t_serialized); 965 KA_TRACE(30, 966 ("T#%d creating task team in __kmp_task_alloc for proxy task\n", 967 gtid)); 968 __kmp_task_team_setup( 969 thread, team, 970 1); // 1 indicates setup the current team regardless of nthreads 971 thread->th.th_task_team = team->t.t_task_team[thread->th.th_task_state]; 972 } 973 kmp_task_team_t *task_team = thread->th.th_task_team; 974 975 /* tasking must be enabled now as the task might not be pushed */ 976 if (!KMP_TASKING_ENABLED(task_team)) { 977 KA_TRACE( 978 30, 979 ("T#%d enabling tasking in __kmp_task_alloc for proxy task\n", gtid)); 980 __kmp_enable_tasking(task_team, thread); 981 kmp_int32 tid = thread->th.th_info.ds.ds_tid; 982 kmp_thread_data_t *thread_data = &task_team->tt.tt_threads_data[tid]; 983 // No lock needed since only owner can allocate 984 if (thread_data->td.td_deque == NULL) { 985 __kmp_alloc_task_deque(thread, thread_data); 986 } 987 } 988 989 if (task_team->tt.tt_found_proxy_tasks == FALSE) 990 TCW_4(task_team->tt.tt_found_proxy_tasks, TRUE); 991 } 992 #endif 993 994 // Calculate shared structure offset including padding after kmp_task_t struct 995 // to align pointers in shared struct 996 shareds_offset = sizeof(kmp_taskdata_t) + sizeof_kmp_task_t; 997 shareds_offset = __kmp_round_up_to_val(shareds_offset, sizeof(void *)); 998 999 // Allocate a kmp_taskdata_t block and a kmp_task_t block. 1000 KA_TRACE(30, ("__kmp_task_alloc: T#%d First malloc size: %ld\n", gtid, 1001 shareds_offset)); 1002 KA_TRACE(30, ("__kmp_task_alloc: T#%d Second malloc size: %ld\n", gtid, 1003 sizeof_shareds)); 1004 1005 // Avoid double allocation here by combining shareds with taskdata 1006 #if USE_FAST_MEMORY 1007 taskdata = (kmp_taskdata_t *)__kmp_fast_allocate(thread, shareds_offset + 1008 sizeof_shareds); 1009 #else /* ! USE_FAST_MEMORY */ 1010 taskdata = (kmp_taskdata_t *)__kmp_thread_malloc(thread, shareds_offset + 1011 sizeof_shareds); 1012 #endif /* USE_FAST_MEMORY */ 1013 ANNOTATE_HAPPENS_AFTER(taskdata); 1014 1015 task = KMP_TASKDATA_TO_TASK(taskdata); 1016 1017 // Make sure task & taskdata are aligned appropriately 1018 #if KMP_ARCH_X86 || KMP_ARCH_PPC64 || !KMP_HAVE_QUAD 1019 KMP_DEBUG_ASSERT((((kmp_uintptr_t)taskdata) & (sizeof(double) - 1)) == 0); 1020 KMP_DEBUG_ASSERT((((kmp_uintptr_t)task) & (sizeof(double) - 1)) == 0); 1021 #else 1022 KMP_DEBUG_ASSERT((((kmp_uintptr_t)taskdata) & (sizeof(_Quad) - 1)) == 0); 1023 KMP_DEBUG_ASSERT((((kmp_uintptr_t)task) & (sizeof(_Quad) - 1)) == 0); 1024 #endif 1025 if (sizeof_shareds > 0) { 1026 // Avoid double allocation here by combining shareds with taskdata 1027 task->shareds = &((char *)taskdata)[shareds_offset]; 1028 // Make sure shareds struct is aligned to pointer size 1029 KMP_DEBUG_ASSERT((((kmp_uintptr_t)task->shareds) & (sizeof(void *) - 1)) == 1030 0); 1031 } else { 1032 task->shareds = NULL; 1033 } 1034 task->routine = task_entry; 1035 task->part_id = 0; // AC: Always start with 0 part id 1036 1037 taskdata->td_task_id = KMP_GEN_TASK_ID(); 1038 taskdata->td_team = team; 1039 taskdata->td_alloc_thread = thread; 1040 taskdata->td_parent = parent_task; 1041 taskdata->td_level = parent_task->td_level + 1; // increment nesting level 1042 taskdata->td_untied_count = 0; 1043 taskdata->td_ident = loc_ref; 1044 taskdata->td_taskwait_ident = NULL; 1045 taskdata->td_taskwait_counter = 0; 1046 taskdata->td_taskwait_thread = 0; 1047 KMP_DEBUG_ASSERT(taskdata->td_parent != NULL); 1048 #if OMP_45_ENABLED 1049 // avoid copying icvs for proxy tasks 1050 if (flags->proxy == TASK_FULL) 1051 #endif 1052 copy_icvs(&taskdata->td_icvs, &taskdata->td_parent->td_icvs); 1053 1054 taskdata->td_flags.tiedness = flags->tiedness; 1055 taskdata->td_flags.final = flags->final; 1056 taskdata->td_flags.merged_if0 = flags->merged_if0; 1057 #if OMP_40_ENABLED 1058 taskdata->td_flags.destructors_thunk = flags->destructors_thunk; 1059 #endif // OMP_40_ENABLED 1060 #if OMP_45_ENABLED 1061 taskdata->td_flags.proxy = flags->proxy; 1062 taskdata->td_task_team = thread->th.th_task_team; 1063 taskdata->td_size_alloc = shareds_offset + sizeof_shareds; 1064 #endif 1065 taskdata->td_flags.tasktype = TASK_EXPLICIT; 1066 1067 // GEH - TODO: fix this to copy parent task's value of tasking_ser flag 1068 taskdata->td_flags.tasking_ser = (__kmp_tasking_mode == tskm_immediate_exec); 1069 1070 // GEH - TODO: fix this to copy parent task's value of team_serial flag 1071 taskdata->td_flags.team_serial = (team->t.t_serialized) ? 1 : 0; 1072 1073 // GEH - Note we serialize the task if the team is serialized to make sure 1074 // implicit parallel region tasks are not left until program termination to 1075 // execute. Also, it helps locality to execute immediately. 1076 1077 taskdata->td_flags.task_serial = 1078 (parent_task->td_flags.final || taskdata->td_flags.team_serial || 1079 taskdata->td_flags.tasking_ser); 1080 1081 taskdata->td_flags.started = 0; 1082 taskdata->td_flags.executing = 0; 1083 taskdata->td_flags.complete = 0; 1084 taskdata->td_flags.freed = 0; 1085 1086 taskdata->td_flags.native = flags->native; 1087 1088 taskdata->td_incomplete_child_tasks = 0; 1089 taskdata->td_allocated_child_tasks = 1; // start at one because counts current 1090 // task and children 1091 #if OMP_40_ENABLED 1092 taskdata->td_taskgroup = 1093 parent_task->td_taskgroup; // task inherits taskgroup from the parent task 1094 taskdata->td_dephash = NULL; 1095 taskdata->td_depnode = NULL; 1096 #endif 1097 1098 // Only need to keep track of child task counts if team parallel and tasking not 1099 // serialized or if it is a proxy task 1100 #if OMP_45_ENABLED 1101 if (flags->proxy == TASK_PROXY || 1102 !(taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser)) 1103 #else 1104 if (!(taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser)) 1105 #endif 1106 { 1107 KMP_TEST_THEN_INC32(&parent_task->td_incomplete_child_tasks); 1108 #if OMP_40_ENABLED 1109 if (parent_task->td_taskgroup) 1110 KMP_TEST_THEN_INC32((kmp_int32 *)(&parent_task->td_taskgroup->count)); 1111 #endif 1112 // Only need to keep track of allocated child tasks for explicit tasks since 1113 // implicit not deallocated 1114 if (taskdata->td_parent->td_flags.tasktype == TASK_EXPLICIT) { 1115 KMP_TEST_THEN_INC32(&taskdata->td_parent->td_allocated_child_tasks); 1116 } 1117 } 1118 1119 KA_TRACE(20, ("__kmp_task_alloc(exit): T#%d created task %p parent=%p\n", 1120 gtid, taskdata, taskdata->td_parent)); 1121 ANNOTATE_HAPPENS_BEFORE(task); 1122 1123 #if OMPT_SUPPORT 1124 __kmp_task_init_ompt(taskdata, gtid, (void *)task_entry); 1125 #endif 1126 1127 return task; 1128 } 1129 1130 kmp_task_t *__kmpc_omp_task_alloc(ident_t *loc_ref, kmp_int32 gtid, 1131 kmp_int32 flags, size_t sizeof_kmp_task_t, 1132 size_t sizeof_shareds, 1133 kmp_routine_entry_t task_entry) { 1134 kmp_task_t *retval; 1135 kmp_tasking_flags_t *input_flags = (kmp_tasking_flags_t *)&flags; 1136 1137 input_flags->native = FALSE; 1138 // __kmp_task_alloc() sets up all other runtime flags 1139 1140 #if OMP_45_ENABLED 1141 KA_TRACE(10, ("__kmpc_omp_task_alloc(enter): T#%d loc=%p, flags=(%s %s) " 1142 "sizeof_task=%ld sizeof_shared=%ld entry=%p\n", 1143 gtid, loc_ref, input_flags->tiedness ? "tied " : "untied", 1144 input_flags->proxy ? "proxy" : "", sizeof_kmp_task_t, 1145 sizeof_shareds, task_entry)); 1146 #else 1147 KA_TRACE(10, ("__kmpc_omp_task_alloc(enter): T#%d loc=%p, flags=(%s) " 1148 "sizeof_task=%ld sizeof_shared=%ld entry=%p\n", 1149 gtid, loc_ref, input_flags->tiedness ? "tied " : "untied", 1150 sizeof_kmp_task_t, sizeof_shareds, task_entry)); 1151 #endif 1152 1153 retval = __kmp_task_alloc(loc_ref, gtid, input_flags, sizeof_kmp_task_t, 1154 sizeof_shareds, task_entry); 1155 1156 KA_TRACE(20, ("__kmpc_omp_task_alloc(exit): T#%d retval %p\n", gtid, retval)); 1157 1158 return retval; 1159 } 1160 1161 // __kmp_invoke_task: invoke the specified task 1162 // 1163 // gtid: global thread ID of caller 1164 // task: the task to invoke 1165 // current_task: the task to resume after task invokation 1166 static void __kmp_invoke_task(kmp_int32 gtid, kmp_task_t *task, 1167 kmp_taskdata_t *current_task) { 1168 kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(task); 1169 kmp_uint64 cur_time; 1170 #if OMP_40_ENABLED 1171 int discard = 0 /* false */; 1172 #endif 1173 KA_TRACE( 1174 30, ("__kmp_invoke_task(enter): T#%d invoking task %p, current_task=%p\n", 1175 gtid, taskdata, current_task)); 1176 KMP_DEBUG_ASSERT(task); 1177 #if OMP_45_ENABLED 1178 if (taskdata->td_flags.proxy == TASK_PROXY && 1179 taskdata->td_flags.complete == 1) { 1180 // This is a proxy task that was already completed but it needs to run 1181 // its bottom-half finish 1182 KA_TRACE( 1183 30, 1184 ("__kmp_invoke_task: T#%d running bottom finish for proxy task %p\n", 1185 gtid, taskdata)); 1186 1187 __kmp_bottom_half_finish_proxy(gtid, task); 1188 1189 KA_TRACE(30, ("__kmp_invoke_task(exit): T#%d completed bottom finish for " 1190 "proxy task %p, resuming task %p\n", 1191 gtid, taskdata, current_task)); 1192 1193 return; 1194 } 1195 #endif 1196 1197 #if USE_ITT_BUILD && USE_ITT_NOTIFY 1198 if (__kmp_forkjoin_frames_mode == 3) { 1199 // Get the current time stamp to measure task execution time to correct 1200 // barrier imbalance time 1201 cur_time = __itt_get_timestamp(); 1202 } 1203 #endif 1204 1205 #if OMP_45_ENABLED 1206 // Proxy tasks are not handled by the runtime 1207 if (taskdata->td_flags.proxy != TASK_PROXY) { 1208 #endif 1209 ANNOTATE_HAPPENS_AFTER(task); 1210 __kmp_task_start(gtid, task, current_task); 1211 #if OMP_45_ENABLED 1212 } 1213 #endif 1214 1215 #if OMPT_SUPPORT 1216 ompt_thread_info_t oldInfo; 1217 kmp_info_t *thread; 1218 if (ompt_enabled) { 1219 // Store the threads states and restore them after the task 1220 thread = __kmp_threads[gtid]; 1221 oldInfo = thread->th.ompt_thread_info; 1222 thread->th.ompt_thread_info.wait_id = 0; 1223 thread->th.ompt_thread_info.state = ompt_state_work_parallel; 1224 taskdata->ompt_task_info.frame.exit_runtime_frame = 1225 __builtin_frame_address(0); 1226 } 1227 #endif 1228 1229 #if OMP_40_ENABLED 1230 // TODO: cancel tasks if the parallel region has also been cancelled 1231 // TODO: check if this sequence can be hoisted above __kmp_task_start 1232 // if cancellation has been enabled for this run ... 1233 if (__kmp_omp_cancellation) { 1234 kmp_info_t *this_thr = __kmp_threads[gtid]; 1235 kmp_team_t *this_team = this_thr->th.th_team; 1236 kmp_taskgroup_t *taskgroup = taskdata->td_taskgroup; 1237 if ((taskgroup && taskgroup->cancel_request) || 1238 (this_team->t.t_cancel_request == cancel_parallel)) { 1239 KMP_COUNT_BLOCK(TASK_cancelled); 1240 // this task belongs to a task group and we need to cancel it 1241 discard = 1 /* true */; 1242 } 1243 } 1244 1245 // Invoke the task routine and pass in relevant data. 1246 // Thunks generated by gcc take a different argument list. 1247 if (!discard) { 1248 #if KMP_STATS_ENABLED 1249 KMP_COUNT_BLOCK(TASK_executed); 1250 switch (KMP_GET_THREAD_STATE()) { 1251 case FORK_JOIN_BARRIER: 1252 KMP_PUSH_PARTITIONED_TIMER(OMP_task_join_bar); 1253 break; 1254 case PLAIN_BARRIER: 1255 KMP_PUSH_PARTITIONED_TIMER(OMP_task_plain_bar); 1256 break; 1257 case TASKYIELD: 1258 KMP_PUSH_PARTITIONED_TIMER(OMP_task_taskyield); 1259 break; 1260 case TASKWAIT: 1261 KMP_PUSH_PARTITIONED_TIMER(OMP_task_taskwait); 1262 break; 1263 case TASKGROUP: 1264 KMP_PUSH_PARTITIONED_TIMER(OMP_task_taskgroup); 1265 break; 1266 default: 1267 KMP_PUSH_PARTITIONED_TIMER(OMP_task_immediate); 1268 break; 1269 } 1270 #endif // KMP_STATS_ENABLED 1271 #endif // OMP_40_ENABLED 1272 1273 #if OMPT_SUPPORT && OMPT_TRACE 1274 /* let OMPT know that we're about to run this task */ 1275 if (ompt_enabled && ompt_callbacks.ompt_callback(ompt_event_task_switch)) { 1276 ompt_callbacks.ompt_callback(ompt_event_task_switch)( 1277 current_task->ompt_task_info.task_id, 1278 taskdata->ompt_task_info.task_id); 1279 } 1280 #endif 1281 1282 #ifdef KMP_GOMP_COMPAT 1283 if (taskdata->td_flags.native) { 1284 ((void (*)(void *))(*(task->routine)))(task->shareds); 1285 } else 1286 #endif /* KMP_GOMP_COMPAT */ 1287 { 1288 (*(task->routine))(gtid, task); 1289 } 1290 KMP_POP_PARTITIONED_TIMER(); 1291 1292 #if OMPT_SUPPORT && OMPT_TRACE 1293 /* let OMPT know that we're returning to the callee task */ 1294 if (ompt_enabled && ompt_callbacks.ompt_callback(ompt_event_task_switch)) { 1295 ompt_callbacks.ompt_callback(ompt_event_task_switch)( 1296 taskdata->ompt_task_info.task_id, 1297 current_task->ompt_task_info.task_id); 1298 } 1299 #endif 1300 1301 #if OMP_40_ENABLED 1302 } 1303 #endif // OMP_40_ENABLED 1304 1305 #if OMPT_SUPPORT 1306 if (ompt_enabled) { 1307 thread->th.ompt_thread_info = oldInfo; 1308 taskdata->ompt_task_info.frame.exit_runtime_frame = NULL; 1309 } 1310 #endif 1311 1312 #if OMP_45_ENABLED 1313 // Proxy tasks are not handled by the runtime 1314 if (taskdata->td_flags.proxy != TASK_PROXY) { 1315 #endif 1316 ANNOTATE_HAPPENS_BEFORE(taskdata->td_parent); 1317 __kmp_task_finish(gtid, task, current_task); 1318 #if OMP_45_ENABLED 1319 } 1320 #endif 1321 1322 #if USE_ITT_BUILD && USE_ITT_NOTIFY 1323 // Barrier imbalance - correct arrive time after the task finished 1324 if (__kmp_forkjoin_frames_mode == 3) { 1325 kmp_info_t *this_thr = __kmp_threads[gtid]; 1326 if (this_thr->th.th_bar_arrive_time) { 1327 this_thr->th.th_bar_arrive_time += (__itt_get_timestamp() - cur_time); 1328 } 1329 } 1330 #endif 1331 KA_TRACE( 1332 30, 1333 ("__kmp_invoke_task(exit): T#%d completed task %p, resuming task %p\n", 1334 gtid, taskdata, current_task)); 1335 return; 1336 } 1337 1338 // __kmpc_omp_task_parts: Schedule a thread-switchable task for execution 1339 // 1340 // loc_ref: location of original task pragma (ignored) 1341 // gtid: Global Thread ID of encountering thread 1342 // new_task: task thunk allocated by __kmp_omp_task_alloc() for the ''new task'' 1343 // Returns: 1344 // TASK_CURRENT_NOT_QUEUED (0) if did not suspend and queue current task to 1345 // be resumed later. 1346 // TASK_CURRENT_QUEUED (1) if suspended and queued the current task to be 1347 // resumed later. 1348 kmp_int32 __kmpc_omp_task_parts(ident_t *loc_ref, kmp_int32 gtid, 1349 kmp_task_t *new_task) { 1350 kmp_taskdata_t *new_taskdata = KMP_TASK_TO_TASKDATA(new_task); 1351 1352 KA_TRACE(10, ("__kmpc_omp_task_parts(enter): T#%d loc=%p task=%p\n", gtid, 1353 loc_ref, new_taskdata)); 1354 1355 /* Should we execute the new task or queue it? For now, let's just always try 1356 to queue it. If the queue fills up, then we'll execute it. */ 1357 1358 if (__kmp_push_task(gtid, new_task) == TASK_NOT_PUSHED) // if cannot defer 1359 { // Execute this task immediately 1360 kmp_taskdata_t *current_task = __kmp_threads[gtid]->th.th_current_task; 1361 new_taskdata->td_flags.task_serial = 1; 1362 __kmp_invoke_task(gtid, new_task, current_task); 1363 } 1364 1365 KA_TRACE( 1366 10, 1367 ("__kmpc_omp_task_parts(exit): T#%d returning TASK_CURRENT_NOT_QUEUED: " 1368 "loc=%p task=%p, return: TASK_CURRENT_NOT_QUEUED\n", 1369 gtid, loc_ref, new_taskdata)); 1370 1371 ANNOTATE_HAPPENS_BEFORE(new_task); 1372 return TASK_CURRENT_NOT_QUEUED; 1373 } 1374 1375 // __kmp_omp_task: Schedule a non-thread-switchable task for execution 1376 // 1377 // gtid: Global Thread ID of encountering thread 1378 // new_task:non-thread-switchable task thunk allocated by __kmp_omp_task_alloc() 1379 // serialize_immediate: if TRUE then if the task is executed immediately its 1380 // execution will be serialized 1381 // Returns: 1382 // TASK_CURRENT_NOT_QUEUED (0) if did not suspend and queue current task to 1383 // be resumed later. 1384 // TASK_CURRENT_QUEUED (1) if suspended and queued the current task to be 1385 // resumed later. 1386 kmp_int32 __kmp_omp_task(kmp_int32 gtid, kmp_task_t *new_task, 1387 bool serialize_immediate) { 1388 kmp_taskdata_t *new_taskdata = KMP_TASK_TO_TASKDATA(new_task); 1389 1390 #if OMPT_SUPPORT 1391 if (ompt_enabled) { 1392 new_taskdata->ompt_task_info.frame.reenter_runtime_frame = 1393 __builtin_frame_address(1); 1394 } 1395 #endif 1396 1397 /* Should we execute the new task or queue it? For now, let's just always try to 1398 queue it. If the queue fills up, then we'll execute it. */ 1399 #if OMP_45_ENABLED 1400 if (new_taskdata->td_flags.proxy == TASK_PROXY || 1401 __kmp_push_task(gtid, new_task) == TASK_NOT_PUSHED) // if cannot defer 1402 #else 1403 if (__kmp_push_task(gtid, new_task) == TASK_NOT_PUSHED) // if cannot defer 1404 #endif 1405 { // Execute this task immediately 1406 kmp_taskdata_t *current_task = __kmp_threads[gtid]->th.th_current_task; 1407 if (serialize_immediate) 1408 new_taskdata->td_flags.task_serial = 1; 1409 __kmp_invoke_task(gtid, new_task, current_task); 1410 } 1411 1412 #if OMPT_SUPPORT 1413 if (ompt_enabled) { 1414 new_taskdata->ompt_task_info.frame.reenter_runtime_frame = NULL; 1415 } 1416 #endif 1417 1418 ANNOTATE_HAPPENS_BEFORE(new_task); 1419 return TASK_CURRENT_NOT_QUEUED; 1420 } 1421 1422 // __kmpc_omp_task: Wrapper around __kmp_omp_task to schedule a 1423 // non-thread-switchable task from the parent thread only! 1424 // 1425 // loc_ref: location of original task pragma (ignored) 1426 // gtid: Global Thread ID of encountering thread 1427 // new_task: non-thread-switchable task thunk allocated by 1428 // __kmp_omp_task_alloc() 1429 // Returns: 1430 // TASK_CURRENT_NOT_QUEUED (0) if did not suspend and queue current task to 1431 // be resumed later. 1432 // TASK_CURRENT_QUEUED (1) if suspended and queued the current task to be 1433 // resumed later. 1434 kmp_int32 __kmpc_omp_task(ident_t *loc_ref, kmp_int32 gtid, 1435 kmp_task_t *new_task) { 1436 kmp_int32 res; 1437 KMP_SET_THREAD_STATE_BLOCK(EXPLICIT_TASK); 1438 1439 #if KMP_DEBUG 1440 kmp_taskdata_t *new_taskdata = KMP_TASK_TO_TASKDATA(new_task); 1441 #endif 1442 KA_TRACE(10, ("__kmpc_omp_task(enter): T#%d loc=%p task=%p\n", gtid, loc_ref, 1443 new_taskdata)); 1444 1445 res = __kmp_omp_task(gtid, new_task, true); 1446 1447 KA_TRACE(10, ("__kmpc_omp_task(exit): T#%d returning " 1448 "TASK_CURRENT_NOT_QUEUED: loc=%p task=%p\n", 1449 gtid, loc_ref, new_taskdata)); 1450 return res; 1451 } 1452 1453 // __kmpc_omp_taskwait: Wait until all tasks generated by the current task are 1454 // complete 1455 kmp_int32 __kmpc_omp_taskwait(ident_t *loc_ref, kmp_int32 gtid) { 1456 kmp_taskdata_t *taskdata; 1457 kmp_info_t *thread; 1458 int thread_finished = FALSE; 1459 KMP_SET_THREAD_STATE_BLOCK(TASKWAIT); 1460 1461 KA_TRACE(10, ("__kmpc_omp_taskwait(enter): T#%d loc=%p\n", gtid, loc_ref)); 1462 1463 if (__kmp_tasking_mode != tskm_immediate_exec) { 1464 thread = __kmp_threads[gtid]; 1465 taskdata = thread->th.th_current_task; 1466 #if OMPT_SUPPORT && OMPT_TRACE 1467 ompt_task_id_t my_task_id; 1468 ompt_parallel_id_t my_parallel_id; 1469 1470 if (ompt_enabled) { 1471 kmp_team_t *team = thread->th.th_team; 1472 my_task_id = taskdata->ompt_task_info.task_id; 1473 my_parallel_id = team->t.ompt_team_info.parallel_id; 1474 1475 taskdata->ompt_task_info.frame.reenter_runtime_frame = 1476 __builtin_frame_address(1); 1477 if (ompt_callbacks.ompt_callback(ompt_event_taskwait_begin)) { 1478 ompt_callbacks.ompt_callback(ompt_event_taskwait_begin)(my_parallel_id, 1479 my_task_id); 1480 } 1481 } 1482 #endif 1483 1484 // Debugger: The taskwait is active. Store location and thread encountered the 1485 // taskwait. 1486 #if USE_ITT_BUILD 1487 // Note: These values are used by ITT events as well. 1488 #endif /* USE_ITT_BUILD */ 1489 taskdata->td_taskwait_counter += 1; 1490 taskdata->td_taskwait_ident = loc_ref; 1491 taskdata->td_taskwait_thread = gtid + 1; 1492 1493 #if USE_ITT_BUILD 1494 void *itt_sync_obj = __kmp_itt_taskwait_object(gtid); 1495 if (itt_sync_obj != NULL) 1496 __kmp_itt_taskwait_starting(gtid, itt_sync_obj); 1497 #endif /* USE_ITT_BUILD */ 1498 1499 bool must_wait = 1500 !taskdata->td_flags.team_serial && !taskdata->td_flags.final; 1501 1502 #if OMP_45_ENABLED 1503 must_wait = must_wait || (thread->th.th_task_team != NULL && 1504 thread->th.th_task_team->tt.tt_found_proxy_tasks); 1505 #endif 1506 if (must_wait) { 1507 kmp_flag_32 flag( 1508 RCAST(volatile kmp_uint32 *, &taskdata->td_incomplete_child_tasks), 1509 0U); 1510 while (TCR_4(taskdata->td_incomplete_child_tasks) != 0) { 1511 flag.execute_tasks(thread, gtid, FALSE, 1512 &thread_finished USE_ITT_BUILD_ARG(itt_sync_obj), 1513 __kmp_task_stealing_constraint); 1514 } 1515 } 1516 #if USE_ITT_BUILD 1517 if (itt_sync_obj != NULL) 1518 __kmp_itt_taskwait_finished(gtid, itt_sync_obj); 1519 #endif /* USE_ITT_BUILD */ 1520 1521 // Debugger: The taskwait is completed. Location remains, but thread is 1522 // negated. 1523 taskdata->td_taskwait_thread = -taskdata->td_taskwait_thread; 1524 1525 #if OMPT_SUPPORT && OMPT_TRACE 1526 if (ompt_enabled) { 1527 if (ompt_callbacks.ompt_callback(ompt_event_taskwait_end)) { 1528 ompt_callbacks.ompt_callback(ompt_event_taskwait_end)(my_parallel_id, 1529 my_task_id); 1530 } 1531 taskdata->ompt_task_info.frame.reenter_runtime_frame = NULL; 1532 } 1533 #endif 1534 ANNOTATE_HAPPENS_AFTER(taskdata); 1535 } 1536 1537 KA_TRACE(10, ("__kmpc_omp_taskwait(exit): T#%d task %p finished waiting, " 1538 "returning TASK_CURRENT_NOT_QUEUED\n", 1539 gtid, taskdata)); 1540 1541 return TASK_CURRENT_NOT_QUEUED; 1542 } 1543 1544 // __kmpc_omp_taskyield: switch to a different task 1545 kmp_int32 __kmpc_omp_taskyield(ident_t *loc_ref, kmp_int32 gtid, int end_part) { 1546 kmp_taskdata_t *taskdata; 1547 kmp_info_t *thread; 1548 int thread_finished = FALSE; 1549 1550 KMP_COUNT_BLOCK(OMP_TASKYIELD); 1551 KMP_SET_THREAD_STATE_BLOCK(TASKYIELD); 1552 1553 KA_TRACE(10, ("__kmpc_omp_taskyield(enter): T#%d loc=%p end_part = %d\n", 1554 gtid, loc_ref, end_part)); 1555 1556 if (__kmp_tasking_mode != tskm_immediate_exec && __kmp_init_parallel) { 1557 thread = __kmp_threads[gtid]; 1558 taskdata = thread->th.th_current_task; 1559 // Should we model this as a task wait or not? 1560 // Debugger: The taskwait is active. Store location and thread encountered the 1561 // taskwait. 1562 #if USE_ITT_BUILD 1563 // Note: These values are used by ITT events as well. 1564 #endif /* USE_ITT_BUILD */ 1565 taskdata->td_taskwait_counter += 1; 1566 taskdata->td_taskwait_ident = loc_ref; 1567 taskdata->td_taskwait_thread = gtid + 1; 1568 1569 #if USE_ITT_BUILD 1570 void *itt_sync_obj = __kmp_itt_taskwait_object(gtid); 1571 if (itt_sync_obj != NULL) 1572 __kmp_itt_taskwait_starting(gtid, itt_sync_obj); 1573 #endif /* USE_ITT_BUILD */ 1574 if (!taskdata->td_flags.team_serial) { 1575 kmp_task_team_t *task_team = thread->th.th_task_team; 1576 if (task_team != NULL) { 1577 if (KMP_TASKING_ENABLED(task_team)) { 1578 __kmp_execute_tasks_32( 1579 thread, gtid, NULL, FALSE, 1580 &thread_finished USE_ITT_BUILD_ARG(itt_sync_obj), 1581 __kmp_task_stealing_constraint); 1582 } 1583 } 1584 } 1585 #if USE_ITT_BUILD 1586 if (itt_sync_obj != NULL) 1587 __kmp_itt_taskwait_finished(gtid, itt_sync_obj); 1588 #endif /* USE_ITT_BUILD */ 1589 1590 // Debugger: The taskwait is completed. Location remains, but thread is 1591 // negated. 1592 taskdata->td_taskwait_thread = -taskdata->td_taskwait_thread; 1593 } 1594 1595 KA_TRACE(10, ("__kmpc_omp_taskyield(exit): T#%d task %p resuming, " 1596 "returning TASK_CURRENT_NOT_QUEUED\n", 1597 gtid, taskdata)); 1598 1599 return TASK_CURRENT_NOT_QUEUED; 1600 } 1601 1602 // TODO: change to OMP_50_ENABLED, need to change build tools for this to work 1603 #if OMP_45_ENABLED 1604 // Task Reduction implementation 1605 1606 typedef struct kmp_task_red_flags { 1607 unsigned lazy_priv : 1; // hint: (1) use lazy allocation (big objects) 1608 unsigned reserved31 : 31; 1609 } kmp_task_red_flags_t; 1610 1611 // internal structure for reduction data item related info 1612 typedef struct kmp_task_red_data { 1613 void *reduce_shar; // shared reduction item 1614 size_t reduce_size; // size of data item 1615 void *reduce_priv; // thread specific data 1616 void *reduce_pend; // end of private data for comparison op 1617 void *reduce_init; // data initialization routine 1618 void *reduce_fini; // data finalization routine 1619 void *reduce_comb; // data combiner routine 1620 kmp_task_red_flags_t flags; // flags for additional info from compiler 1621 } kmp_task_red_data_t; 1622 1623 // structure sent us by compiler - one per reduction item 1624 typedef struct kmp_task_red_input { 1625 void *reduce_shar; // shared reduction item 1626 size_t reduce_size; // size of data item 1627 void *reduce_init; // data initialization routine 1628 void *reduce_fini; // data finalization routine 1629 void *reduce_comb; // data combiner routine 1630 kmp_task_red_flags_t flags; // flags for additional info from compiler 1631 } kmp_task_red_input_t; 1632 1633 /*! 1634 @ingroup TASKING 1635 @param gtid Global thread ID 1636 @param num Number of data items to reduce 1637 @param data Array of data for reduction 1638 @return The taskgroup identifier 1639 1640 Initialize task reduction for the taskgroup. 1641 */ 1642 void *__kmpc_task_reduction_init(int gtid, int num, void *data) { 1643 kmp_info_t *thread = __kmp_threads[gtid]; 1644 kmp_taskgroup_t *tg = thread->th.th_current_task->td_taskgroup; 1645 kmp_int32 nth = thread->th.th_team_nproc; 1646 kmp_task_red_input_t *input = (kmp_task_red_input_t *)data; 1647 kmp_task_red_data_t *arr; 1648 1649 // check input data just in case 1650 KMP_ASSERT(tg != NULL); 1651 KMP_ASSERT(data != NULL); 1652 KMP_ASSERT(num > 0); 1653 if (nth == 1) { 1654 KA_TRACE(10, ("__kmpc_task_reduction_init: T#%d, tg %p, exiting nth=1\n", 1655 gtid, tg)); 1656 return (void *)tg; 1657 } 1658 KA_TRACE(10, ("__kmpc_task_reduction_init: T#%d, taskgroup %p, #items %d\n", 1659 gtid, tg, num)); 1660 arr = (kmp_task_red_data_t *)__kmp_thread_malloc( 1661 thread, num * sizeof(kmp_task_red_data_t)); 1662 for (int i = 0; i < num; ++i) { 1663 void (*f_init)(void *) = (void (*)(void *))(input[i].reduce_init); 1664 size_t size = input[i].reduce_size - 1; 1665 // round the size up to cache line per thread-specific item 1666 size += CACHE_LINE - size % CACHE_LINE; 1667 KMP_ASSERT(input[i].reduce_comb != NULL); // combiner is mandatory 1668 arr[i].reduce_shar = input[i].reduce_shar; 1669 arr[i].reduce_size = size; 1670 arr[i].reduce_init = input[i].reduce_init; 1671 arr[i].reduce_fini = input[i].reduce_fini; 1672 arr[i].reduce_comb = input[i].reduce_comb; 1673 arr[i].flags = input[i].flags; 1674 if (!input[i].flags.lazy_priv) { 1675 // allocate cache-line aligned block and fill it with zeros 1676 arr[i].reduce_priv = __kmp_allocate(nth * size); 1677 arr[i].reduce_pend = (char *)(arr[i].reduce_priv) + nth * size; 1678 if (f_init != NULL) { 1679 // initialize thread-specific items 1680 for (int j = 0; j < nth; ++j) { 1681 f_init((char *)(arr[i].reduce_priv) + j * size); 1682 } 1683 } 1684 } else { 1685 // only allocate space for pointers now, 1686 // objects will be lazily allocated/initialized once requested 1687 arr[i].reduce_priv = __kmp_allocate(nth * sizeof(void *)); 1688 } 1689 } 1690 tg->reduce_data = (void *)arr; 1691 tg->reduce_num_data = num; 1692 return (void *)tg; 1693 } 1694 1695 /*! 1696 @ingroup TASKING 1697 @param gtid Global thread ID 1698 @param tskgrp The taskgroup ID (optional) 1699 @param data Shared location of the item 1700 @return The pointer to per-thread data 1701 1702 Get thread-specific location of data item 1703 */ 1704 void *__kmpc_task_reduction_get_th_data(int gtid, void *tskgrp, void *data) { 1705 kmp_info_t *thread = __kmp_threads[gtid]; 1706 kmp_int32 nth = thread->th.th_team_nproc; 1707 if (nth == 1) 1708 return data; // nothing to do 1709 1710 kmp_taskgroup_t *tg = (kmp_taskgroup_t *)tskgrp; 1711 if (tg == NULL) 1712 tg = thread->th.th_current_task->td_taskgroup; 1713 KMP_ASSERT(tg != NULL); 1714 kmp_task_red_data_t *arr = (kmp_task_red_data_t *)(tg->reduce_data); 1715 kmp_int32 num = tg->reduce_num_data; 1716 kmp_int32 tid = thread->th.th_info.ds.ds_tid; 1717 1718 KMP_ASSERT(data != NULL); 1719 while (tg != NULL) { 1720 for (int i = 0; i < num; ++i) { 1721 if (!arr[i].flags.lazy_priv) { 1722 if (data == arr[i].reduce_shar || 1723 (data >= arr[i].reduce_priv && data < arr[i].reduce_pend)) 1724 return (char *)(arr[i].reduce_priv) + tid * arr[i].reduce_size; 1725 } else { 1726 // check shared location first 1727 void **p_priv = (void **)(arr[i].reduce_priv); 1728 if (data == arr[i].reduce_shar) 1729 goto found; 1730 // check if we get some thread specific location as parameter 1731 for (int j = 0; j < nth; ++j) 1732 if (data == p_priv[j]) 1733 goto found; 1734 continue; // not found, continue search 1735 found: 1736 if (p_priv[tid] == NULL) { 1737 // allocate thread specific object lazily 1738 void (*f_init)(void *) = (void (*)(void *))(arr[i].reduce_init); 1739 p_priv[tid] = __kmp_allocate(arr[i].reduce_size); 1740 if (f_init != NULL) { 1741 f_init(p_priv[tid]); 1742 } 1743 } 1744 return p_priv[tid]; 1745 } 1746 } 1747 tg = tg->parent; 1748 arr = (kmp_task_red_data_t *)(tg->reduce_data); 1749 num = tg->reduce_num_data; 1750 } 1751 KMP_ASSERT2(0, "Unknown task reduction item"); 1752 return NULL; // ERROR, this line never executed 1753 } 1754 1755 // Finalize task reduction. 1756 // Called from __kmpc_end_taskgroup() 1757 static void __kmp_task_reduction_fini(kmp_info_t *th, kmp_taskgroup_t *tg) { 1758 kmp_int32 nth = th->th.th_team_nproc; 1759 KMP_DEBUG_ASSERT(nth > 1); // should not be called if nth == 1 1760 kmp_task_red_data_t *arr = (kmp_task_red_data_t *)tg->reduce_data; 1761 kmp_int32 num = tg->reduce_num_data; 1762 for (int i = 0; i < num; ++i) { 1763 void *sh_data = arr[i].reduce_shar; 1764 void (*f_fini)(void *) = (void (*)(void *))(arr[i].reduce_fini); 1765 void (*f_comb)(void *, void *) = 1766 (void (*)(void *, void *))(arr[i].reduce_comb); 1767 if (!arr[i].flags.lazy_priv) { 1768 void *pr_data = arr[i].reduce_priv; 1769 size_t size = arr[i].reduce_size; 1770 for (int j = 0; j < nth; ++j) { 1771 void *priv_data = (char *)pr_data + j * size; 1772 f_comb(sh_data, priv_data); // combine results 1773 if (f_fini) 1774 f_fini(priv_data); // finalize if needed 1775 } 1776 } else { 1777 void **pr_data = (void **)(arr[i].reduce_priv); 1778 for (int j = 0; j < nth; ++j) { 1779 if (pr_data[j] != NULL) { 1780 f_comb(sh_data, pr_data[j]); // combine results 1781 if (f_fini) 1782 f_fini(pr_data[j]); // finalize if needed 1783 __kmp_free(pr_data[j]); 1784 } 1785 } 1786 } 1787 __kmp_free(arr[i].reduce_priv); 1788 } 1789 __kmp_thread_free(th, arr); 1790 tg->reduce_data = NULL; 1791 tg->reduce_num_data = 0; 1792 } 1793 #endif 1794 1795 #if OMP_40_ENABLED 1796 // __kmpc_taskgroup: Start a new taskgroup 1797 void __kmpc_taskgroup(ident_t *loc, int gtid) { 1798 kmp_info_t *thread = __kmp_threads[gtid]; 1799 kmp_taskdata_t *taskdata = thread->th.th_current_task; 1800 kmp_taskgroup_t *tg_new = 1801 (kmp_taskgroup_t *)__kmp_thread_malloc(thread, sizeof(kmp_taskgroup_t)); 1802 KA_TRACE(10, ("__kmpc_taskgroup: T#%d loc=%p group=%p\n", gtid, loc, tg_new)); 1803 tg_new->count = 0; 1804 tg_new->cancel_request = cancel_noreq; 1805 tg_new->parent = taskdata->td_taskgroup; 1806 // TODO: change to OMP_50_ENABLED, need to change build tools for this to work 1807 #if OMP_45_ENABLED 1808 tg_new->reduce_data = NULL; 1809 tg_new->reduce_num_data = 0; 1810 #endif 1811 taskdata->td_taskgroup = tg_new; 1812 } 1813 1814 // __kmpc_end_taskgroup: Wait until all tasks generated by the current task 1815 // and its descendants are complete 1816 void __kmpc_end_taskgroup(ident_t *loc, int gtid) { 1817 kmp_info_t *thread = __kmp_threads[gtid]; 1818 kmp_taskdata_t *taskdata = thread->th.th_current_task; 1819 kmp_taskgroup_t *taskgroup = taskdata->td_taskgroup; 1820 int thread_finished = FALSE; 1821 1822 KA_TRACE(10, ("__kmpc_end_taskgroup(enter): T#%d loc=%p\n", gtid, loc)); 1823 KMP_DEBUG_ASSERT(taskgroup != NULL); 1824 KMP_SET_THREAD_STATE_BLOCK(TASKGROUP); 1825 1826 if (__kmp_tasking_mode != tskm_immediate_exec) { 1827 #if USE_ITT_BUILD 1828 // For ITT the taskgroup wait is similar to taskwait until we need to 1829 // distinguish them 1830 void *itt_sync_obj = __kmp_itt_taskwait_object(gtid); 1831 if (itt_sync_obj != NULL) 1832 __kmp_itt_taskwait_starting(gtid, itt_sync_obj); 1833 #endif /* USE_ITT_BUILD */ 1834 1835 #if OMP_45_ENABLED 1836 if (!taskdata->td_flags.team_serial || 1837 (thread->th.th_task_team != NULL && 1838 thread->th.th_task_team->tt.tt_found_proxy_tasks)) 1839 #else 1840 if (!taskdata->td_flags.team_serial) 1841 #endif 1842 { 1843 kmp_flag_32 flag(RCAST(kmp_uint32 *, &taskgroup->count), 0U); 1844 while (TCR_4(taskgroup->count) != 0) { 1845 flag.execute_tasks(thread, gtid, FALSE, 1846 &thread_finished USE_ITT_BUILD_ARG(itt_sync_obj), 1847 __kmp_task_stealing_constraint); 1848 } 1849 } 1850 1851 #if USE_ITT_BUILD 1852 if (itt_sync_obj != NULL) 1853 __kmp_itt_taskwait_finished(gtid, itt_sync_obj); 1854 #endif /* USE_ITT_BUILD */ 1855 } 1856 KMP_DEBUG_ASSERT(taskgroup->count == 0); 1857 1858 // TODO: change to OMP_50_ENABLED, need to change build tools for this to work 1859 #if OMP_45_ENABLED 1860 if (taskgroup->reduce_data != NULL) // need to reduce? 1861 __kmp_task_reduction_fini(thread, taskgroup); 1862 #endif 1863 // Restore parent taskgroup for the current task 1864 taskdata->td_taskgroup = taskgroup->parent; 1865 __kmp_thread_free(thread, taskgroup); 1866 1867 KA_TRACE(10, ("__kmpc_end_taskgroup(exit): T#%d task %p finished waiting\n", 1868 gtid, taskdata)); 1869 ANNOTATE_HAPPENS_AFTER(taskdata); 1870 } 1871 #endif 1872 1873 // __kmp_remove_my_task: remove a task from my own deque 1874 static kmp_task_t *__kmp_remove_my_task(kmp_info_t *thread, kmp_int32 gtid, 1875 kmp_task_team_t *task_team, 1876 kmp_int32 is_constrained) { 1877 kmp_task_t *task; 1878 kmp_taskdata_t *taskdata; 1879 kmp_thread_data_t *thread_data; 1880 kmp_uint32 tail; 1881 1882 KMP_DEBUG_ASSERT(__kmp_tasking_mode != tskm_immediate_exec); 1883 KMP_DEBUG_ASSERT(task_team->tt.tt_threads_data != 1884 NULL); // Caller should check this condition 1885 1886 thread_data = &task_team->tt.tt_threads_data[__kmp_tid_from_gtid(gtid)]; 1887 1888 KA_TRACE(10, ("__kmp_remove_my_task(enter): T#%d ntasks=%d head=%u tail=%u\n", 1889 gtid, thread_data->td.td_deque_ntasks, 1890 thread_data->td.td_deque_head, thread_data->td.td_deque_tail)); 1891 1892 if (TCR_4(thread_data->td.td_deque_ntasks) == 0) { 1893 KA_TRACE(10, 1894 ("__kmp_remove_my_task(exit #1): T#%d No tasks to remove: " 1895 "ntasks=%d head=%u tail=%u\n", 1896 gtid, thread_data->td.td_deque_ntasks, 1897 thread_data->td.td_deque_head, thread_data->td.td_deque_tail)); 1898 return NULL; 1899 } 1900 1901 __kmp_acquire_bootstrap_lock(&thread_data->td.td_deque_lock); 1902 1903 if (TCR_4(thread_data->td.td_deque_ntasks) == 0) { 1904 __kmp_release_bootstrap_lock(&thread_data->td.td_deque_lock); 1905 KA_TRACE(10, 1906 ("__kmp_remove_my_task(exit #2): T#%d No tasks to remove: " 1907 "ntasks=%d head=%u tail=%u\n", 1908 gtid, thread_data->td.td_deque_ntasks, 1909 thread_data->td.td_deque_head, thread_data->td.td_deque_tail)); 1910 return NULL; 1911 } 1912 1913 tail = (thread_data->td.td_deque_tail - 1) & 1914 TASK_DEQUE_MASK(thread_data->td); // Wrap index. 1915 taskdata = thread_data->td.td_deque[tail]; 1916 1917 if (is_constrained && (taskdata->td_flags.tiedness == TASK_TIED)) { 1918 // we need to check if the candidate obeys task scheduling constraint: 1919 // only child of current task can be scheduled 1920 kmp_taskdata_t *current = thread->th.th_current_task; 1921 kmp_int32 level = current->td_level; 1922 kmp_taskdata_t *parent = taskdata->td_parent; 1923 while (parent != current && parent->td_level > level) { 1924 parent = parent->td_parent; // check generation up to the level of the 1925 // current task 1926 KMP_DEBUG_ASSERT(parent != NULL); 1927 } 1928 if (parent != current) { 1929 // If the tail task is not a child, then no other child can appear in the 1930 // deque. 1931 __kmp_release_bootstrap_lock(&thread_data->td.td_deque_lock); 1932 KA_TRACE(10, 1933 ("__kmp_remove_my_task(exit #2): T#%d No tasks to remove: " 1934 "ntasks=%d head=%u tail=%u\n", 1935 gtid, thread_data->td.td_deque_ntasks, 1936 thread_data->td.td_deque_head, thread_data->td.td_deque_tail)); 1937 return NULL; 1938 } 1939 } 1940 1941 thread_data->td.td_deque_tail = tail; 1942 TCW_4(thread_data->td.td_deque_ntasks, thread_data->td.td_deque_ntasks - 1); 1943 1944 __kmp_release_bootstrap_lock(&thread_data->td.td_deque_lock); 1945 1946 KA_TRACE(10, ("__kmp_remove_my_task(exit #2): T#%d task %p removed: " 1947 "ntasks=%d head=%u tail=%u\n", 1948 gtid, taskdata, thread_data->td.td_deque_ntasks, 1949 thread_data->td.td_deque_head, thread_data->td.td_deque_tail)); 1950 1951 task = KMP_TASKDATA_TO_TASK(taskdata); 1952 return task; 1953 } 1954 1955 // __kmp_steal_task: remove a task from another thread's deque 1956 // Assume that calling thread has already checked existence of 1957 // task_team thread_data before calling this routine. 1958 static kmp_task_t *__kmp_steal_task(kmp_info_t *victim, kmp_int32 gtid, 1959 kmp_task_team_t *task_team, 1960 volatile kmp_int32 *unfinished_threads, 1961 int *thread_finished, 1962 kmp_int32 is_constrained) { 1963 kmp_task_t *task; 1964 kmp_taskdata_t *taskdata; 1965 kmp_thread_data_t *victim_td, *threads_data; 1966 kmp_int32 victim_tid; 1967 1968 KMP_DEBUG_ASSERT(__kmp_tasking_mode != tskm_immediate_exec); 1969 1970 threads_data = task_team->tt.tt_threads_data; 1971 KMP_DEBUG_ASSERT(threads_data != NULL); // Caller should check this condition 1972 1973 victim_tid = victim->th.th_info.ds.ds_tid; 1974 victim_td = &threads_data[victim_tid]; 1975 1976 KA_TRACE(10, ("__kmp_steal_task(enter): T#%d try to steal from T#%d: " 1977 "task_team=%p ntasks=%d " 1978 "head=%u tail=%u\n", 1979 gtid, __kmp_gtid_from_thread(victim), task_team, 1980 victim_td->td.td_deque_ntasks, victim_td->td.td_deque_head, 1981 victim_td->td.td_deque_tail)); 1982 1983 if ((TCR_4(victim_td->td.td_deque_ntasks) == 1984 0) || // Caller should not check this condition 1985 (TCR_PTR(victim->th.th_task_team) != 1986 task_team)) // GEH: why would this happen? 1987 { 1988 KA_TRACE(10, ("__kmp_steal_task(exit #1): T#%d could not steal from T#%d: " 1989 "task_team=%p " 1990 "ntasks=%d head=%u tail=%u\n", 1991 gtid, __kmp_gtid_from_thread(victim), task_team, 1992 victim_td->td.td_deque_ntasks, victim_td->td.td_deque_head, 1993 victim_td->td.td_deque_tail)); 1994 return NULL; 1995 } 1996 1997 __kmp_acquire_bootstrap_lock(&victim_td->td.td_deque_lock); 1998 1999 // Check again after we acquire the lock 2000 if ((TCR_4(victim_td->td.td_deque_ntasks) == 0) || 2001 (TCR_PTR(victim->th.th_task_team) != 2002 task_team)) // GEH: why would this happen? 2003 { 2004 __kmp_release_bootstrap_lock(&victim_td->td.td_deque_lock); 2005 KA_TRACE(10, ("__kmp_steal_task(exit #2): T#%d could not steal from T#%d: " 2006 "task_team=%p " 2007 "ntasks=%d head=%u tail=%u\n", 2008 gtid, __kmp_gtid_from_thread(victim), task_team, 2009 victim_td->td.td_deque_ntasks, victim_td->td.td_deque_head, 2010 victim_td->td.td_deque_tail)); 2011 return NULL; 2012 } 2013 2014 KMP_DEBUG_ASSERT(victim_td->td.td_deque != NULL); 2015 2016 taskdata = victim_td->td.td_deque[victim_td->td.td_deque_head]; 2017 if (is_constrained) { 2018 // we need to check if the candidate obeys task scheduling constraint: 2019 // only descendant of current task can be scheduled 2020 kmp_taskdata_t *current = __kmp_threads[gtid]->th.th_current_task; 2021 kmp_int32 level = current->td_level; 2022 kmp_taskdata_t *parent = taskdata->td_parent; 2023 while (parent != current && parent->td_level > level) { 2024 parent = parent->td_parent; // check generation up to the level of the 2025 // current task 2026 KMP_DEBUG_ASSERT(parent != NULL); 2027 } 2028 if (parent != current) { 2029 // If the head task is not a descendant of the current task then do not 2030 // steal it. No other task in victim's deque can be a descendant of the 2031 // current task. 2032 __kmp_release_bootstrap_lock(&victim_td->td.td_deque_lock); 2033 KA_TRACE(10, ("__kmp_steal_task(exit #2): T#%d could not steal from " 2034 "T#%d: task_team=%p " 2035 "ntasks=%d head=%u tail=%u\n", 2036 gtid, 2037 __kmp_gtid_from_thread(threads_data[victim_tid].td.td_thr), 2038 task_team, victim_td->td.td_deque_ntasks, 2039 victim_td->td.td_deque_head, victim_td->td.td_deque_tail)); 2040 return NULL; 2041 } 2042 } 2043 // Bump head pointer and Wrap. 2044 victim_td->td.td_deque_head = 2045 (victim_td->td.td_deque_head + 1) & TASK_DEQUE_MASK(victim_td->td); 2046 if (*thread_finished) { 2047 // We need to un-mark this victim as a finished victim. This must be done 2048 // before releasing the lock, or else other threads (starting with the 2049 // master victim) might be prematurely released from the barrier!!! 2050 kmp_int32 count; 2051 2052 count = KMP_TEST_THEN_INC32(unfinished_threads); 2053 2054 KA_TRACE( 2055 20, 2056 ("__kmp_steal_task: T#%d inc unfinished_threads to %d: task_team=%p\n", 2057 gtid, count + 1, task_team)); 2058 2059 *thread_finished = FALSE; 2060 } 2061 TCW_4(victim_td->td.td_deque_ntasks, 2062 TCR_4(victim_td->td.td_deque_ntasks) - 1); 2063 2064 __kmp_release_bootstrap_lock(&victim_td->td.td_deque_lock); 2065 2066 KMP_COUNT_BLOCK(TASK_stolen); 2067 KA_TRACE( 2068 10, 2069 ("__kmp_steal_task(exit #3): T#%d stole task %p from T#%d: task_team=%p " 2070 "ntasks=%d head=%u tail=%u\n", 2071 gtid, taskdata, __kmp_gtid_from_thread(victim), task_team, 2072 victim_td->td.td_deque_ntasks, victim_td->td.td_deque_head, 2073 victim_td->td.td_deque_tail)); 2074 2075 task = KMP_TASKDATA_TO_TASK(taskdata); 2076 return task; 2077 } 2078 2079 // __kmp_execute_tasks_template: Choose and execute tasks until either the 2080 // condition is statisfied (return true) or there are none left (return false). 2081 // 2082 // final_spin is TRUE if this is the spin at the release barrier. 2083 // thread_finished indicates whether the thread is finished executing all 2084 // the tasks it has on its deque, and is at the release barrier. 2085 // spinner is the location on which to spin. 2086 // spinner == NULL means only execute a single task and return. 2087 // checker is the value to check to terminate the spin. 2088 template <class C> 2089 static inline int __kmp_execute_tasks_template( 2090 kmp_info_t *thread, kmp_int32 gtid, C *flag, int final_spin, 2091 int *thread_finished USE_ITT_BUILD_ARG(void *itt_sync_obj), 2092 kmp_int32 is_constrained) { 2093 kmp_task_team_t *task_team = thread->th.th_task_team; 2094 kmp_thread_data_t *threads_data; 2095 kmp_task_t *task; 2096 kmp_info_t *other_thread; 2097 kmp_taskdata_t *current_task = thread->th.th_current_task; 2098 volatile kmp_int32 *unfinished_threads; 2099 kmp_int32 nthreads, victim = -2, use_own_tasks = 1, new_victim = 0, 2100 tid = thread->th.th_info.ds.ds_tid; 2101 2102 KMP_DEBUG_ASSERT(__kmp_tasking_mode != tskm_immediate_exec); 2103 KMP_DEBUG_ASSERT(thread == __kmp_threads[gtid]); 2104 2105 if (task_team == NULL) 2106 return FALSE; 2107 2108 KA_TRACE(15, ("__kmp_execute_tasks_template(enter): T#%d final_spin=%d " 2109 "*thread_finished=%d\n", 2110 gtid, final_spin, *thread_finished)); 2111 2112 thread->th.th_reap_state = KMP_NOT_SAFE_TO_REAP; 2113 threads_data = (kmp_thread_data_t *)TCR_PTR(task_team->tt.tt_threads_data); 2114 KMP_DEBUG_ASSERT(threads_data != NULL); 2115 2116 nthreads = task_team->tt.tt_nproc; 2117 unfinished_threads = &(task_team->tt.tt_unfinished_threads); 2118 #if OMP_45_ENABLED 2119 KMP_DEBUG_ASSERT(nthreads > 1 || task_team->tt.tt_found_proxy_tasks); 2120 #else 2121 KMP_DEBUG_ASSERT(nthreads > 1); 2122 #endif 2123 KMP_DEBUG_ASSERT(TCR_4(*unfinished_threads) >= 0); 2124 2125 while (1) { // Outer loop keeps trying to find tasks in case of single thread 2126 // getting tasks from target constructs 2127 while (1) { // Inner loop to find a task and execute it 2128 task = NULL; 2129 if (use_own_tasks) { // check on own queue first 2130 task = __kmp_remove_my_task(thread, gtid, task_team, is_constrained); 2131 } 2132 if ((task == NULL) && (nthreads > 1)) { // Steal a task 2133 int asleep = 1; 2134 use_own_tasks = 0; 2135 // Try to steal from the last place I stole from successfully. 2136 if (victim == -2) { // haven't stolen anything yet 2137 victim = threads_data[tid].td.td_deque_last_stolen; 2138 if (victim != 2139 -1) // if we have a last stolen from victim, get the thread 2140 other_thread = threads_data[victim].td.td_thr; 2141 } 2142 if (victim != -1) { // found last victim 2143 asleep = 0; 2144 } else if (!new_victim) { // no recent steals and we haven't already 2145 // used a new victim; select a random thread 2146 do { // Find a different thread to steal work from. 2147 // Pick a random thread. Initial plan was to cycle through all the 2148 // threads, and only return if we tried to steal from every thread, 2149 // and failed. Arch says that's not such a great idea. 2150 victim = __kmp_get_random(thread) % (nthreads - 1); 2151 if (victim >= tid) { 2152 ++victim; // Adjusts random distribution to exclude self 2153 } 2154 // Found a potential victim 2155 other_thread = threads_data[victim].td.td_thr; 2156 // There is a slight chance that __kmp_enable_tasking() did not wake 2157 // up all threads waiting at the barrier. If victim is sleeping, 2158 // then wake it up. Since we were going to pay the cache miss 2159 // penalty for referencing another thread's kmp_info_t struct 2160 // anyway, 2161 // the check shouldn't cost too much performance at this point. In 2162 // extra barrier mode, tasks do not sleep at the separate tasking 2163 // barrier, so this isn't a problem. 2164 asleep = 0; 2165 if ((__kmp_tasking_mode == tskm_task_teams) && 2166 (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) && 2167 (TCR_PTR(CCAST(void *, other_thread->th.th_sleep_loc)) != 2168 NULL)) { 2169 asleep = 1; 2170 __kmp_null_resume_wrapper(__kmp_gtid_from_thread(other_thread), 2171 other_thread->th.th_sleep_loc); 2172 // A sleeping thread should not have any tasks on it's queue. 2173 // There is a slight possibility that it resumes, steals a task 2174 // from another thread, which spawns more tasks, all in the time 2175 // that it takes this thread to check => don't write an assertion 2176 // that the victim's queue is empty. Try stealing from a 2177 // different thread. 2178 } 2179 } while (asleep); 2180 } 2181 2182 if (!asleep) { 2183 // We have a victim to try to steal from 2184 task = __kmp_steal_task(other_thread, gtid, task_team, 2185 unfinished_threads, thread_finished, 2186 is_constrained); 2187 } 2188 if (task != NULL) { // set last stolen to victim 2189 if (threads_data[tid].td.td_deque_last_stolen != victim) { 2190 threads_data[tid].td.td_deque_last_stolen = victim; 2191 // The pre-refactored code did not try more than 1 successful new 2192 // vicitm, unless the last one generated more local tasks; 2193 // new_victim keeps track of this 2194 new_victim = 1; 2195 } 2196 } else { // No tasks found; unset last_stolen 2197 KMP_CHECK_UPDATE(threads_data[tid].td.td_deque_last_stolen, -1); 2198 victim = -2; // no successful victim found 2199 } 2200 } 2201 2202 if (task == NULL) // break out of tasking loop 2203 break; 2204 2205 // Found a task; execute it 2206 #if USE_ITT_BUILD && USE_ITT_NOTIFY 2207 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) { 2208 if (itt_sync_obj == NULL) { // we are at fork barrier where we could not 2209 // get the object reliably 2210 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier); 2211 } 2212 __kmp_itt_task_starting(itt_sync_obj); 2213 } 2214 #endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */ 2215 __kmp_invoke_task(gtid, task, current_task); 2216 #if USE_ITT_BUILD 2217 if (itt_sync_obj != NULL) 2218 __kmp_itt_task_finished(itt_sync_obj); 2219 #endif /* USE_ITT_BUILD */ 2220 // If this thread is only partway through the barrier and the condition is 2221 // met, then return now, so that the barrier gather/release pattern can 2222 // proceed. If this thread is in the last spin loop in the barrier, 2223 // waiting to be released, we know that the termination condition will not 2224 // be satisified, so don't waste any cycles checking it. 2225 if (flag == NULL || (!final_spin && flag->done_check())) { 2226 KA_TRACE( 2227 15, 2228 ("__kmp_execute_tasks_template: T#%d spin condition satisfied\n", 2229 gtid)); 2230 return TRUE; 2231 } 2232 if (thread->th.th_task_team == NULL) { 2233 break; 2234 } 2235 // Yield before executing next task 2236 KMP_YIELD(__kmp_library == library_throughput); 2237 // If execution of a stolen task results in more tasks being placed on our 2238 // run queue, reset use_own_tasks 2239 if (!use_own_tasks && TCR_4(threads_data[tid].td.td_deque_ntasks) != 0) { 2240 KA_TRACE(20, ("__kmp_execute_tasks_template: T#%d stolen task spawned " 2241 "other tasks, restart\n", 2242 gtid)); 2243 use_own_tasks = 1; 2244 new_victim = 0; 2245 } 2246 } 2247 2248 // The task source has been exhausted. If in final spin loop of barrier, check 2249 // if termination condition is satisfied. 2250 #if OMP_45_ENABLED 2251 // The work queue may be empty but there might be proxy tasks still 2252 // executing 2253 if (final_spin && TCR_4(current_task->td_incomplete_child_tasks) == 0) 2254 #else 2255 if (final_spin) 2256 #endif 2257 { 2258 // First, decrement the #unfinished threads, if that has not already been 2259 // done. This decrement might be to the spin location, and result in the 2260 // termination condition being satisfied. 2261 if (!*thread_finished) { 2262 kmp_int32 count; 2263 2264 count = KMP_TEST_THEN_DEC32(unfinished_threads) - 1; 2265 KA_TRACE(20, ("__kmp_execute_tasks_template: T#%d dec " 2266 "unfinished_threads to %d task_team=%p\n", 2267 gtid, count, task_team)); 2268 *thread_finished = TRUE; 2269 } 2270 2271 // It is now unsafe to reference thread->th.th_team !!! 2272 // Decrementing task_team->tt.tt_unfinished_threads can allow the master 2273 // thread to pass through the barrier, where it might reset each thread's 2274 // th.th_team field for the next parallel region. If we can steal more 2275 // work, we know that this has not happened yet. 2276 if (flag != NULL && flag->done_check()) { 2277 KA_TRACE( 2278 15, 2279 ("__kmp_execute_tasks_template: T#%d spin condition satisfied\n", 2280 gtid)); 2281 return TRUE; 2282 } 2283 } 2284 2285 // If this thread's task team is NULL, master has recognized that there are 2286 // no more tasks; bail out 2287 if (thread->th.th_task_team == NULL) { 2288 KA_TRACE(15, 2289 ("__kmp_execute_tasks_template: T#%d no more tasks\n", gtid)); 2290 return FALSE; 2291 } 2292 2293 #if OMP_45_ENABLED 2294 // We could be getting tasks from target constructs; if this is the only 2295 // thread, keep trying to execute tasks from own queue 2296 if (nthreads == 1) 2297 use_own_tasks = 1; 2298 else 2299 #endif 2300 { 2301 KA_TRACE(15, 2302 ("__kmp_execute_tasks_template: T#%d can't find work\n", gtid)); 2303 return FALSE; 2304 } 2305 } 2306 } 2307 2308 int __kmp_execute_tasks_32( 2309 kmp_info_t *thread, kmp_int32 gtid, kmp_flag_32 *flag, int final_spin, 2310 int *thread_finished USE_ITT_BUILD_ARG(void *itt_sync_obj), 2311 kmp_int32 is_constrained) { 2312 return __kmp_execute_tasks_template( 2313 thread, gtid, flag, final_spin, 2314 thread_finished USE_ITT_BUILD_ARG(itt_sync_obj), is_constrained); 2315 } 2316 2317 int __kmp_execute_tasks_64( 2318 kmp_info_t *thread, kmp_int32 gtid, kmp_flag_64 *flag, int final_spin, 2319 int *thread_finished USE_ITT_BUILD_ARG(void *itt_sync_obj), 2320 kmp_int32 is_constrained) { 2321 return __kmp_execute_tasks_template( 2322 thread, gtid, flag, final_spin, 2323 thread_finished USE_ITT_BUILD_ARG(itt_sync_obj), is_constrained); 2324 } 2325 2326 int __kmp_execute_tasks_oncore( 2327 kmp_info_t *thread, kmp_int32 gtid, kmp_flag_oncore *flag, int final_spin, 2328 int *thread_finished USE_ITT_BUILD_ARG(void *itt_sync_obj), 2329 kmp_int32 is_constrained) { 2330 return __kmp_execute_tasks_template( 2331 thread, gtid, flag, final_spin, 2332 thread_finished USE_ITT_BUILD_ARG(itt_sync_obj), is_constrained); 2333 } 2334 2335 // __kmp_enable_tasking: Allocate task team and resume threads sleeping at the 2336 // next barrier so they can assist in executing enqueued tasks. 2337 // First thread in allocates the task team atomically. 2338 static void __kmp_enable_tasking(kmp_task_team_t *task_team, 2339 kmp_info_t *this_thr) { 2340 kmp_thread_data_t *threads_data; 2341 int nthreads, i, is_init_thread; 2342 2343 KA_TRACE(10, ("__kmp_enable_tasking(enter): T#%d\n", 2344 __kmp_gtid_from_thread(this_thr))); 2345 2346 KMP_DEBUG_ASSERT(task_team != NULL); 2347 KMP_DEBUG_ASSERT(this_thr->th.th_team != NULL); 2348 2349 nthreads = task_team->tt.tt_nproc; 2350 KMP_DEBUG_ASSERT(nthreads > 0); 2351 KMP_DEBUG_ASSERT(nthreads == this_thr->th.th_team->t.t_nproc); 2352 2353 // Allocate or increase the size of threads_data if necessary 2354 is_init_thread = __kmp_realloc_task_threads_data(this_thr, task_team); 2355 2356 if (!is_init_thread) { 2357 // Some other thread already set up the array. 2358 KA_TRACE( 2359 20, 2360 ("__kmp_enable_tasking(exit): T#%d: threads array already set up.\n", 2361 __kmp_gtid_from_thread(this_thr))); 2362 return; 2363 } 2364 threads_data = (kmp_thread_data_t *)TCR_PTR(task_team->tt.tt_threads_data); 2365 KMP_DEBUG_ASSERT(threads_data != NULL); 2366 2367 if ((__kmp_tasking_mode == tskm_task_teams) && 2368 (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME)) { 2369 // Release any threads sleeping at the barrier, so that they can steal 2370 // tasks and execute them. In extra barrier mode, tasks do not sleep 2371 // at the separate tasking barrier, so this isn't a problem. 2372 for (i = 0; i < nthreads; i++) { 2373 volatile void *sleep_loc; 2374 kmp_info_t *thread = threads_data[i].td.td_thr; 2375 2376 if (i == this_thr->th.th_info.ds.ds_tid) { 2377 continue; 2378 } 2379 // Since we haven't locked the thread's suspend mutex lock at this 2380 // point, there is a small window where a thread might be putting 2381 // itself to sleep, but hasn't set the th_sleep_loc field yet. 2382 // To work around this, __kmp_execute_tasks_template() periodically checks 2383 // see if other threads are sleeping (using the same random mechanism that 2384 // is used for task stealing) and awakens them if they are. 2385 if ((sleep_loc = TCR_PTR(CCAST(void *, thread->th.th_sleep_loc))) != 2386 NULL) { 2387 KF_TRACE(50, ("__kmp_enable_tasking: T#%d waking up thread T#%d\n", 2388 __kmp_gtid_from_thread(this_thr), 2389 __kmp_gtid_from_thread(thread))); 2390 __kmp_null_resume_wrapper(__kmp_gtid_from_thread(thread), sleep_loc); 2391 } else { 2392 KF_TRACE(50, ("__kmp_enable_tasking: T#%d don't wake up thread T#%d\n", 2393 __kmp_gtid_from_thread(this_thr), 2394 __kmp_gtid_from_thread(thread))); 2395 } 2396 } 2397 } 2398 2399 KA_TRACE(10, ("__kmp_enable_tasking(exit): T#%d\n", 2400 __kmp_gtid_from_thread(this_thr))); 2401 } 2402 2403 /* // TODO: Check the comment consistency 2404 * Utility routines for "task teams". A task team (kmp_task_t) is kind of 2405 * like a shadow of the kmp_team_t data struct, with a different lifetime. 2406 * After a child * thread checks into a barrier and calls __kmp_release() from 2407 * the particular variant of __kmp_<barrier_kind>_barrier_gather(), it can no 2408 * longer assume that the kmp_team_t structure is intact (at any moment, the 2409 * master thread may exit the barrier code and free the team data structure, 2410 * and return the threads to the thread pool). 2411 * 2412 * This does not work with the the tasking code, as the thread is still 2413 * expected to participate in the execution of any tasks that may have been 2414 * spawned my a member of the team, and the thread still needs access to all 2415 * to each thread in the team, so that it can steal work from it. 2416 * 2417 * Enter the existence of the kmp_task_team_t struct. It employs a reference 2418 * counting mechanims, and is allocated by the master thread before calling 2419 * __kmp_<barrier_kind>_release, and then is release by the last thread to 2420 * exit __kmp_<barrier_kind>_release at the next barrier. I.e. the lifetimes 2421 * of the kmp_task_team_t structs for consecutive barriers can overlap 2422 * (and will, unless the master thread is the last thread to exit the barrier 2423 * release phase, which is not typical). 2424 * 2425 * The existence of such a struct is useful outside the context of tasking, 2426 * but for now, I'm trying to keep it specific to the OMP_30_ENABLED macro, 2427 * so that any performance differences show up when comparing the 2.5 vs. 3.0 2428 * libraries. 2429 * 2430 * We currently use the existence of the threads array as an indicator that 2431 * tasks were spawned since the last barrier. If the structure is to be 2432 * useful outside the context of tasking, then this will have to change, but 2433 * not settting the field minimizes the performance impact of tasking on 2434 * barriers, when no explicit tasks were spawned (pushed, actually). 2435 */ 2436 2437 static kmp_task_team_t *__kmp_free_task_teams = 2438 NULL; // Free list for task_team data structures 2439 // Lock for task team data structures 2440 static kmp_bootstrap_lock_t __kmp_task_team_lock = 2441 KMP_BOOTSTRAP_LOCK_INITIALIZER(__kmp_task_team_lock); 2442 2443 // __kmp_alloc_task_deque: 2444 // Allocates a task deque for a particular thread, and initialize the necessary 2445 // data structures relating to the deque. This only happens once per thread 2446 // per task team since task teams are recycled. No lock is needed during 2447 // allocation since each thread allocates its own deque. 2448 static void __kmp_alloc_task_deque(kmp_info_t *thread, 2449 kmp_thread_data_t *thread_data) { 2450 __kmp_init_bootstrap_lock(&thread_data->td.td_deque_lock); 2451 KMP_DEBUG_ASSERT(thread_data->td.td_deque == NULL); 2452 2453 // Initialize last stolen task field to "none" 2454 thread_data->td.td_deque_last_stolen = -1; 2455 2456 KMP_DEBUG_ASSERT(TCR_4(thread_data->td.td_deque_ntasks) == 0); 2457 KMP_DEBUG_ASSERT(thread_data->td.td_deque_head == 0); 2458 KMP_DEBUG_ASSERT(thread_data->td.td_deque_tail == 0); 2459 2460 KE_TRACE( 2461 10, 2462 ("__kmp_alloc_task_deque: T#%d allocating deque[%d] for thread_data %p\n", 2463 __kmp_gtid_from_thread(thread), INITIAL_TASK_DEQUE_SIZE, thread_data)); 2464 // Allocate space for task deque, and zero the deque 2465 // Cannot use __kmp_thread_calloc() because threads not around for 2466 // kmp_reap_task_team( ). 2467 thread_data->td.td_deque = (kmp_taskdata_t **)__kmp_allocate( 2468 INITIAL_TASK_DEQUE_SIZE * sizeof(kmp_taskdata_t *)); 2469 thread_data->td.td_deque_size = INITIAL_TASK_DEQUE_SIZE; 2470 } 2471 2472 // __kmp_realloc_task_deque: 2473 // Re-allocates a task deque for a particular thread, copies the content from 2474 // the old deque and adjusts the necessary data structures relating to the 2475 // deque. This operation must be done with a the deque_lock being held 2476 static void __kmp_realloc_task_deque(kmp_info_t *thread, 2477 kmp_thread_data_t *thread_data) { 2478 kmp_int32 size = TASK_DEQUE_SIZE(thread_data->td); 2479 kmp_int32 new_size = 2 * size; 2480 2481 KE_TRACE(10, ("__kmp_realloc_task_deque: T#%d reallocating deque[from %d to " 2482 "%d] for thread_data %p\n", 2483 __kmp_gtid_from_thread(thread), size, new_size, thread_data)); 2484 2485 kmp_taskdata_t **new_deque = 2486 (kmp_taskdata_t **)__kmp_allocate(new_size * sizeof(kmp_taskdata_t *)); 2487 2488 int i, j; 2489 for (i = thread_data->td.td_deque_head, j = 0; j < size; 2490 i = (i + 1) & TASK_DEQUE_MASK(thread_data->td), j++) 2491 new_deque[j] = thread_data->td.td_deque[i]; 2492 2493 __kmp_free(thread_data->td.td_deque); 2494 2495 thread_data->td.td_deque_head = 0; 2496 thread_data->td.td_deque_tail = size; 2497 thread_data->td.td_deque = new_deque; 2498 thread_data->td.td_deque_size = new_size; 2499 } 2500 2501 // __kmp_free_task_deque: 2502 // Deallocates a task deque for a particular thread. Happens at library 2503 // deallocation so don't need to reset all thread data fields. 2504 static void __kmp_free_task_deque(kmp_thread_data_t *thread_data) { 2505 if (thread_data->td.td_deque != NULL) { 2506 __kmp_acquire_bootstrap_lock(&thread_data->td.td_deque_lock); 2507 TCW_4(thread_data->td.td_deque_ntasks, 0); 2508 __kmp_free(thread_data->td.td_deque); 2509 thread_data->td.td_deque = NULL; 2510 __kmp_release_bootstrap_lock(&thread_data->td.td_deque_lock); 2511 } 2512 2513 #ifdef BUILD_TIED_TASK_STACK 2514 // GEH: Figure out what to do here for td_susp_tied_tasks 2515 if (thread_data->td.td_susp_tied_tasks.ts_entries != TASK_STACK_EMPTY) { 2516 __kmp_free_task_stack(__kmp_thread_from_gtid(gtid), thread_data); 2517 } 2518 #endif // BUILD_TIED_TASK_STACK 2519 } 2520 2521 // __kmp_realloc_task_threads_data: 2522 // Allocates a threads_data array for a task team, either by allocating an 2523 // initial array or enlarging an existing array. Only the first thread to get 2524 // the lock allocs or enlarges the array and re-initializes the array eleemnts. 2525 // That thread returns "TRUE", the rest return "FALSE". 2526 // Assumes that the new array size is given by task_team -> tt.tt_nproc. 2527 // The current size is given by task_team -> tt.tt_max_threads. 2528 static int __kmp_realloc_task_threads_data(kmp_info_t *thread, 2529 kmp_task_team_t *task_team) { 2530 kmp_thread_data_t **threads_data_p; 2531 kmp_int32 nthreads, maxthreads; 2532 int is_init_thread = FALSE; 2533 2534 if (TCR_4(task_team->tt.tt_found_tasks)) { 2535 // Already reallocated and initialized. 2536 return FALSE; 2537 } 2538 2539 threads_data_p = &task_team->tt.tt_threads_data; 2540 nthreads = task_team->tt.tt_nproc; 2541 maxthreads = task_team->tt.tt_max_threads; 2542 2543 // All threads must lock when they encounter the first task of the implicit 2544 // task region to make sure threads_data fields are (re)initialized before 2545 // used. 2546 __kmp_acquire_bootstrap_lock(&task_team->tt.tt_threads_lock); 2547 2548 if (!TCR_4(task_team->tt.tt_found_tasks)) { 2549 // first thread to enable tasking 2550 kmp_team_t *team = thread->th.th_team; 2551 int i; 2552 2553 is_init_thread = TRUE; 2554 if (maxthreads < nthreads) { 2555 2556 if (*threads_data_p != NULL) { 2557 kmp_thread_data_t *old_data = *threads_data_p; 2558 kmp_thread_data_t *new_data = NULL; 2559 2560 KE_TRACE( 2561 10, 2562 ("__kmp_realloc_task_threads_data: T#%d reallocating " 2563 "threads data for task_team %p, new_size = %d, old_size = %d\n", 2564 __kmp_gtid_from_thread(thread), task_team, nthreads, maxthreads)); 2565 // Reallocate threads_data to have more elements than current array 2566 // Cannot use __kmp_thread_realloc() because threads not around for 2567 // kmp_reap_task_team( ). Note all new array entries are initialized 2568 // to zero by __kmp_allocate(). 2569 new_data = (kmp_thread_data_t *)__kmp_allocate( 2570 nthreads * sizeof(kmp_thread_data_t)); 2571 // copy old data to new data 2572 KMP_MEMCPY_S((void *)new_data, nthreads * sizeof(kmp_thread_data_t), 2573 (void *)old_data, maxthreads * sizeof(kmp_thread_data_t)); 2574 2575 #ifdef BUILD_TIED_TASK_STACK 2576 // GEH: Figure out if this is the right thing to do 2577 for (i = maxthreads; i < nthreads; i++) { 2578 kmp_thread_data_t *thread_data = &(*threads_data_p)[i]; 2579 __kmp_init_task_stack(__kmp_gtid_from_thread(thread), thread_data); 2580 } 2581 #endif // BUILD_TIED_TASK_STACK 2582 // Install the new data and free the old data 2583 (*threads_data_p) = new_data; 2584 __kmp_free(old_data); 2585 } else { 2586 KE_TRACE(10, ("__kmp_realloc_task_threads_data: T#%d allocating " 2587 "threads data for task_team %p, size = %d\n", 2588 __kmp_gtid_from_thread(thread), task_team, nthreads)); 2589 // Make the initial allocate for threads_data array, and zero entries 2590 // Cannot use __kmp_thread_calloc() because threads not around for 2591 // kmp_reap_task_team( ). 2592 ANNOTATE_IGNORE_WRITES_BEGIN(); 2593 *threads_data_p = (kmp_thread_data_t *)__kmp_allocate( 2594 nthreads * sizeof(kmp_thread_data_t)); 2595 ANNOTATE_IGNORE_WRITES_END(); 2596 #ifdef BUILD_TIED_TASK_STACK 2597 // GEH: Figure out if this is the right thing to do 2598 for (i = 0; i < nthreads; i++) { 2599 kmp_thread_data_t *thread_data = &(*threads_data_p)[i]; 2600 __kmp_init_task_stack(__kmp_gtid_from_thread(thread), thread_data); 2601 } 2602 #endif // BUILD_TIED_TASK_STACK 2603 } 2604 task_team->tt.tt_max_threads = nthreads; 2605 } else { 2606 // If array has (more than) enough elements, go ahead and use it 2607 KMP_DEBUG_ASSERT(*threads_data_p != NULL); 2608 } 2609 2610 // initialize threads_data pointers back to thread_info structures 2611 for (i = 0; i < nthreads; i++) { 2612 kmp_thread_data_t *thread_data = &(*threads_data_p)[i]; 2613 thread_data->td.td_thr = team->t.t_threads[i]; 2614 2615 if (thread_data->td.td_deque_last_stolen >= nthreads) { 2616 // The last stolen field survives across teams / barrier, and the number 2617 // of threads may have changed. It's possible (likely?) that a new 2618 // parallel region will exhibit the same behavior as previous region. 2619 thread_data->td.td_deque_last_stolen = -1; 2620 } 2621 } 2622 2623 KMP_MB(); 2624 TCW_SYNC_4(task_team->tt.tt_found_tasks, TRUE); 2625 } 2626 2627 __kmp_release_bootstrap_lock(&task_team->tt.tt_threads_lock); 2628 return is_init_thread; 2629 } 2630 2631 // __kmp_free_task_threads_data: 2632 // Deallocates a threads_data array for a task team, including any attached 2633 // tasking deques. Only occurs at library shutdown. 2634 static void __kmp_free_task_threads_data(kmp_task_team_t *task_team) { 2635 __kmp_acquire_bootstrap_lock(&task_team->tt.tt_threads_lock); 2636 if (task_team->tt.tt_threads_data != NULL) { 2637 int i; 2638 for (i = 0; i < task_team->tt.tt_max_threads; i++) { 2639 __kmp_free_task_deque(&task_team->tt.tt_threads_data[i]); 2640 } 2641 __kmp_free(task_team->tt.tt_threads_data); 2642 task_team->tt.tt_threads_data = NULL; 2643 } 2644 __kmp_release_bootstrap_lock(&task_team->tt.tt_threads_lock); 2645 } 2646 2647 // __kmp_allocate_task_team: 2648 // Allocates a task team associated with a specific team, taking it from 2649 // the global task team free list if possible. Also initializes data 2650 // structures. 2651 static kmp_task_team_t *__kmp_allocate_task_team(kmp_info_t *thread, 2652 kmp_team_t *team) { 2653 kmp_task_team_t *task_team = NULL; 2654 int nthreads; 2655 2656 KA_TRACE(20, ("__kmp_allocate_task_team: T#%d entering; team = %p\n", 2657 (thread ? __kmp_gtid_from_thread(thread) : -1), team)); 2658 2659 if (TCR_PTR(__kmp_free_task_teams) != NULL) { 2660 // Take a task team from the task team pool 2661 __kmp_acquire_bootstrap_lock(&__kmp_task_team_lock); 2662 if (__kmp_free_task_teams != NULL) { 2663 task_team = __kmp_free_task_teams; 2664 TCW_PTR(__kmp_free_task_teams, task_team->tt.tt_next); 2665 task_team->tt.tt_next = NULL; 2666 } 2667 __kmp_release_bootstrap_lock(&__kmp_task_team_lock); 2668 } 2669 2670 if (task_team == NULL) { 2671 KE_TRACE(10, ("__kmp_allocate_task_team: T#%d allocating " 2672 "task team for team %p\n", 2673 __kmp_gtid_from_thread(thread), team)); 2674 // Allocate a new task team if one is not available. 2675 // Cannot use __kmp_thread_malloc() because threads not around for 2676 // kmp_reap_task_team( ). 2677 task_team = (kmp_task_team_t *)__kmp_allocate(sizeof(kmp_task_team_t)); 2678 __kmp_init_bootstrap_lock(&task_team->tt.tt_threads_lock); 2679 // AC: __kmp_allocate zeroes returned memory 2680 // task_team -> tt.tt_threads_data = NULL; 2681 // task_team -> tt.tt_max_threads = 0; 2682 // task_team -> tt.tt_next = NULL; 2683 } 2684 2685 TCW_4(task_team->tt.tt_found_tasks, FALSE); 2686 #if OMP_45_ENABLED 2687 TCW_4(task_team->tt.tt_found_proxy_tasks, FALSE); 2688 #endif 2689 task_team->tt.tt_nproc = nthreads = team->t.t_nproc; 2690 2691 TCW_4(task_team->tt.tt_unfinished_threads, nthreads); 2692 TCW_4(task_team->tt.tt_active, TRUE); 2693 2694 KA_TRACE(20, ("__kmp_allocate_task_team: T#%d exiting; task_team = %p " 2695 "unfinished_threads init'd to %d\n", 2696 (thread ? __kmp_gtid_from_thread(thread) : -1), task_team, 2697 task_team->tt.tt_unfinished_threads)); 2698 return task_team; 2699 } 2700 2701 // __kmp_free_task_team: 2702 // Frees the task team associated with a specific thread, and adds it 2703 // to the global task team free list. 2704 void __kmp_free_task_team(kmp_info_t *thread, kmp_task_team_t *task_team) { 2705 KA_TRACE(20, ("__kmp_free_task_team: T#%d task_team = %p\n", 2706 thread ? __kmp_gtid_from_thread(thread) : -1, task_team)); 2707 2708 // Put task team back on free list 2709 __kmp_acquire_bootstrap_lock(&__kmp_task_team_lock); 2710 2711 KMP_DEBUG_ASSERT(task_team->tt.tt_next == NULL); 2712 task_team->tt.tt_next = __kmp_free_task_teams; 2713 TCW_PTR(__kmp_free_task_teams, task_team); 2714 2715 __kmp_release_bootstrap_lock(&__kmp_task_team_lock); 2716 } 2717 2718 // __kmp_reap_task_teams: 2719 // Free all the task teams on the task team free list. 2720 // Should only be done during library shutdown. 2721 // Cannot do anything that needs a thread structure or gtid since they are 2722 // already gone. 2723 void __kmp_reap_task_teams(void) { 2724 kmp_task_team_t *task_team; 2725 2726 if (TCR_PTR(__kmp_free_task_teams) != NULL) { 2727 // Free all task_teams on the free list 2728 __kmp_acquire_bootstrap_lock(&__kmp_task_team_lock); 2729 while ((task_team = __kmp_free_task_teams) != NULL) { 2730 __kmp_free_task_teams = task_team->tt.tt_next; 2731 task_team->tt.tt_next = NULL; 2732 2733 // Free threads_data if necessary 2734 if (task_team->tt.tt_threads_data != NULL) { 2735 __kmp_free_task_threads_data(task_team); 2736 } 2737 __kmp_free(task_team); 2738 } 2739 __kmp_release_bootstrap_lock(&__kmp_task_team_lock); 2740 } 2741 } 2742 2743 // __kmp_wait_to_unref_task_teams: 2744 // Some threads could still be in the fork barrier release code, possibly 2745 // trying to steal tasks. Wait for each thread to unreference its task team. 2746 void __kmp_wait_to_unref_task_teams(void) { 2747 kmp_info_t *thread; 2748 kmp_uint32 spins; 2749 int done; 2750 2751 KMP_INIT_YIELD(spins); 2752 2753 for (;;) { 2754 done = TRUE; 2755 2756 // TODO: GEH - this may be is wrong because some sync would be necessary 2757 // in case threads are added to the pool during the traversal. Need to 2758 // verify that lock for thread pool is held when calling this routine. 2759 for (thread = CCAST(kmp_info_t *, __kmp_thread_pool); thread != NULL; 2760 thread = thread->th.th_next_pool) { 2761 #if KMP_OS_WINDOWS 2762 DWORD exit_val; 2763 #endif 2764 if (TCR_PTR(thread->th.th_task_team) == NULL) { 2765 KA_TRACE(10, ("__kmp_wait_to_unref_task_team: T#%d task_team == NULL\n", 2766 __kmp_gtid_from_thread(thread))); 2767 continue; 2768 } 2769 #if KMP_OS_WINDOWS 2770 // TODO: GEH - add this check for Linux* OS / OS X* as well? 2771 if (!__kmp_is_thread_alive(thread, &exit_val)) { 2772 thread->th.th_task_team = NULL; 2773 continue; 2774 } 2775 #endif 2776 2777 done = FALSE; // Because th_task_team pointer is not NULL for this thread 2778 2779 KA_TRACE(10, ("__kmp_wait_to_unref_task_team: Waiting for T#%d to " 2780 "unreference task_team\n", 2781 __kmp_gtid_from_thread(thread))); 2782 2783 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) { 2784 volatile void *sleep_loc; 2785 // If the thread is sleeping, awaken it. 2786 if ((sleep_loc = TCR_PTR(CCAST(void *, thread->th.th_sleep_loc))) != 2787 NULL) { 2788 KA_TRACE( 2789 10, 2790 ("__kmp_wait_to_unref_task_team: T#%d waking up thread T#%d\n", 2791 __kmp_gtid_from_thread(thread), __kmp_gtid_from_thread(thread))); 2792 __kmp_null_resume_wrapper(__kmp_gtid_from_thread(thread), sleep_loc); 2793 } 2794 } 2795 } 2796 if (done) { 2797 break; 2798 } 2799 2800 // If we are oversubscribed, or have waited a bit (and library mode is 2801 // throughput), yield. Pause is in the following code. 2802 KMP_YIELD(TCR_4(__kmp_nth) > __kmp_avail_proc); 2803 KMP_YIELD_SPIN(spins); // Yields only if KMP_LIBRARY=throughput 2804 } 2805 } 2806 2807 // __kmp_task_team_setup: Create a task_team for the current team, but use 2808 // an already created, unused one if it already exists. 2809 void __kmp_task_team_setup(kmp_info_t *this_thr, kmp_team_t *team, int always) { 2810 KMP_DEBUG_ASSERT(__kmp_tasking_mode != tskm_immediate_exec); 2811 2812 // If this task_team hasn't been created yet, allocate it. It will be used in 2813 // the region after the next. 2814 // If it exists, it is the current task team and shouldn't be touched yet as 2815 // it may still be in use. 2816 if (team->t.t_task_team[this_thr->th.th_task_state] == NULL && 2817 (always || team->t.t_nproc > 1)) { 2818 team->t.t_task_team[this_thr->th.th_task_state] = 2819 __kmp_allocate_task_team(this_thr, team); 2820 KA_TRACE(20, ("__kmp_task_team_setup: Master T#%d created new task_team %p " 2821 "for team %d at parity=%d\n", 2822 __kmp_gtid_from_thread(this_thr), 2823 team->t.t_task_team[this_thr->th.th_task_state], 2824 ((team != NULL) ? team->t.t_id : -1), 2825 this_thr->th.th_task_state)); 2826 } 2827 2828 // After threads exit the release, they will call sync, and then point to this 2829 // other task_team; make sure it is allocated and properly initialized. As 2830 // threads spin in the barrier release phase, they will continue to use the 2831 // previous task_team struct(above), until they receive the signal to stop 2832 // checking for tasks (they can't safely reference the kmp_team_t struct, 2833 // which could be reallocated by the master thread). No task teams are formed 2834 // for serialized teams. 2835 if (team->t.t_nproc > 1) { 2836 int other_team = 1 - this_thr->th.th_task_state; 2837 if (team->t.t_task_team[other_team] == NULL) { // setup other team as well 2838 team->t.t_task_team[other_team] = 2839 __kmp_allocate_task_team(this_thr, team); 2840 KA_TRACE(20, ("__kmp_task_team_setup: Master T#%d created second new " 2841 "task_team %p for team %d at parity=%d\n", 2842 __kmp_gtid_from_thread(this_thr), 2843 team->t.t_task_team[other_team], 2844 ((team != NULL) ? team->t.t_id : -1), other_team)); 2845 } else { // Leave the old task team struct in place for the upcoming region; 2846 // adjust as needed 2847 kmp_task_team_t *task_team = team->t.t_task_team[other_team]; 2848 if (!task_team->tt.tt_active || 2849 team->t.t_nproc != task_team->tt.tt_nproc) { 2850 TCW_4(task_team->tt.tt_nproc, team->t.t_nproc); 2851 TCW_4(task_team->tt.tt_found_tasks, FALSE); 2852 #if OMP_45_ENABLED 2853 TCW_4(task_team->tt.tt_found_proxy_tasks, FALSE); 2854 #endif 2855 TCW_4(task_team->tt.tt_unfinished_threads, team->t.t_nproc); 2856 TCW_4(task_team->tt.tt_active, TRUE); 2857 } 2858 // if team size has changed, the first thread to enable tasking will 2859 // realloc threads_data if necessary 2860 KA_TRACE(20, ("__kmp_task_team_setup: Master T#%d reset next task_team " 2861 "%p for team %d at parity=%d\n", 2862 __kmp_gtid_from_thread(this_thr), 2863 team->t.t_task_team[other_team], 2864 ((team != NULL) ? team->t.t_id : -1), other_team)); 2865 } 2866 } 2867 } 2868 2869 // __kmp_task_team_sync: Propagation of task team data from team to threads 2870 // which happens just after the release phase of a team barrier. This may be 2871 // called by any thread, but only for teams with # threads > 1. 2872 void __kmp_task_team_sync(kmp_info_t *this_thr, kmp_team_t *team) { 2873 KMP_DEBUG_ASSERT(__kmp_tasking_mode != tskm_immediate_exec); 2874 2875 // Toggle the th_task_state field, to switch which task_team this thread 2876 // refers to 2877 this_thr->th.th_task_state = 1 - this_thr->th.th_task_state; 2878 // It is now safe to propagate the task team pointer from the team struct to 2879 // the current thread. 2880 TCW_PTR(this_thr->th.th_task_team, 2881 team->t.t_task_team[this_thr->th.th_task_state]); 2882 KA_TRACE(20, 2883 ("__kmp_task_team_sync: Thread T#%d task team switched to task_team " 2884 "%p from Team #%d (parity=%d)\n", 2885 __kmp_gtid_from_thread(this_thr), this_thr->th.th_task_team, 2886 ((team != NULL) ? team->t.t_id : -1), this_thr->th.th_task_state)); 2887 } 2888 2889 // __kmp_task_team_wait: Master thread waits for outstanding tasks after the 2890 // barrier gather phase. Only called by master thread if #threads in team > 1 or 2891 // if proxy tasks were created. 2892 // 2893 // wait is a flag that defaults to 1 (see kmp.h), but waiting can be turned off 2894 // by passing in 0 optionally as the last argument. When wait is zero, master 2895 // thread does not wait for unfinished_threads to reach 0. 2896 void __kmp_task_team_wait( 2897 kmp_info_t *this_thr, 2898 kmp_team_t *team USE_ITT_BUILD_ARG(void *itt_sync_obj), int wait) { 2899 kmp_task_team_t *task_team = team->t.t_task_team[this_thr->th.th_task_state]; 2900 2901 KMP_DEBUG_ASSERT(__kmp_tasking_mode != tskm_immediate_exec); 2902 KMP_DEBUG_ASSERT(task_team == this_thr->th.th_task_team); 2903 2904 if ((task_team != NULL) && KMP_TASKING_ENABLED(task_team)) { 2905 if (wait) { 2906 KA_TRACE(20, ("__kmp_task_team_wait: Master T#%d waiting for all tasks " 2907 "(for unfinished_threads to reach 0) on task_team = %p\n", 2908 __kmp_gtid_from_thread(this_thr), task_team)); 2909 // Worker threads may have dropped through to release phase, but could 2910 // still be executing tasks. Wait here for tasks to complete. To avoid 2911 // memory contention, only master thread checks termination condition. 2912 kmp_flag_32 flag( 2913 RCAST(volatile kmp_uint32 *, &task_team->tt.tt_unfinished_threads), 2914 0U); 2915 flag.wait(this_thr, TRUE USE_ITT_BUILD_ARG(itt_sync_obj)); 2916 } 2917 // Deactivate the old task team, so that the worker threads will stop 2918 // referencing it while spinning. 2919 KA_TRACE( 2920 20, 2921 ("__kmp_task_team_wait: Master T#%d deactivating task_team %p: " 2922 "setting active to false, setting local and team's pointer to NULL\n", 2923 __kmp_gtid_from_thread(this_thr), task_team)); 2924 #if OMP_45_ENABLED 2925 KMP_DEBUG_ASSERT(task_team->tt.tt_nproc > 1 || 2926 task_team->tt.tt_found_proxy_tasks == TRUE); 2927 TCW_SYNC_4(task_team->tt.tt_found_proxy_tasks, FALSE); 2928 #else 2929 KMP_DEBUG_ASSERT(task_team->tt.tt_nproc > 1); 2930 #endif 2931 TCW_SYNC_4(task_team->tt.tt_active, FALSE); 2932 KMP_MB(); 2933 2934 TCW_PTR(this_thr->th.th_task_team, NULL); 2935 } 2936 } 2937 2938 // __kmp_tasking_barrier: 2939 // This routine may only called when __kmp_tasking_mode == tskm_extra_barrier. 2940 // Internal function to execute all tasks prior to a regular barrier or a join 2941 // barrier. It is a full barrier itself, which unfortunately turns regular 2942 // barriers into double barriers and join barriers into 1 1/2 barriers. 2943 void __kmp_tasking_barrier(kmp_team_t *team, kmp_info_t *thread, int gtid) { 2944 volatile kmp_uint32 *spin = RCAST( 2945 volatile kmp_uint32 *, 2946 &team->t.t_task_team[thread->th.th_task_state]->tt.tt_unfinished_threads); 2947 int flag = FALSE; 2948 KMP_DEBUG_ASSERT(__kmp_tasking_mode == tskm_extra_barrier); 2949 2950 #if USE_ITT_BUILD 2951 KMP_FSYNC_SPIN_INIT(spin, (kmp_uint32 *)NULL); 2952 #endif /* USE_ITT_BUILD */ 2953 kmp_flag_32 spin_flag(spin, 0U); 2954 while (!spin_flag.execute_tasks(thread, gtid, TRUE, 2955 &flag USE_ITT_BUILD_ARG(NULL), 0)) { 2956 #if USE_ITT_BUILD 2957 // TODO: What about itt_sync_obj?? 2958 KMP_FSYNC_SPIN_PREPARE(CCAST(kmp_uint32 *, spin)); 2959 #endif /* USE_ITT_BUILD */ 2960 2961 if (TCR_4(__kmp_global.g.g_done)) { 2962 if (__kmp_global.g.g_abort) 2963 __kmp_abort_thread(); 2964 break; 2965 } 2966 KMP_YIELD(TRUE); // GH: We always yield here 2967 } 2968 #if USE_ITT_BUILD 2969 KMP_FSYNC_SPIN_ACQUIRED(CCAST(kmp_uint32 *, spin)); 2970 #endif /* USE_ITT_BUILD */ 2971 } 2972 2973 #if OMP_45_ENABLED 2974 2975 // __kmp_give_task puts a task into a given thread queue if: 2976 // - the queue for that thread was created 2977 // - there's space in that queue 2978 // Because of this, __kmp_push_task needs to check if there's space after 2979 // getting the lock 2980 static bool __kmp_give_task(kmp_info_t *thread, kmp_int32 tid, kmp_task_t *task, 2981 kmp_int32 pass) { 2982 kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(task); 2983 kmp_task_team_t *task_team = taskdata->td_task_team; 2984 2985 KA_TRACE(20, ("__kmp_give_task: trying to give task %p to thread %d.\n", 2986 taskdata, tid)); 2987 2988 // If task_team is NULL something went really bad... 2989 KMP_DEBUG_ASSERT(task_team != NULL); 2990 2991 bool result = false; 2992 kmp_thread_data_t *thread_data = &task_team->tt.tt_threads_data[tid]; 2993 2994 if (thread_data->td.td_deque == NULL) { 2995 // There's no queue in this thread, go find another one 2996 // We're guaranteed that at least one thread has a queue 2997 KA_TRACE(30, 2998 ("__kmp_give_task: thread %d has no queue while giving task %p.\n", 2999 tid, taskdata)); 3000 return result; 3001 } 3002 3003 if (TCR_4(thread_data->td.td_deque_ntasks) >= 3004 TASK_DEQUE_SIZE(thread_data->td)) { 3005 KA_TRACE( 3006 30, 3007 ("__kmp_give_task: queue is full while giving task %p to thread %d.\n", 3008 taskdata, tid)); 3009 3010 // if this deque is bigger than the pass ratio give a chance to another 3011 // thread 3012 if (TASK_DEQUE_SIZE(thread_data->td) / INITIAL_TASK_DEQUE_SIZE >= pass) 3013 return result; 3014 3015 __kmp_acquire_bootstrap_lock(&thread_data->td.td_deque_lock); 3016 __kmp_realloc_task_deque(thread, thread_data); 3017 3018 } else { 3019 3020 __kmp_acquire_bootstrap_lock(&thread_data->td.td_deque_lock); 3021 3022 if (TCR_4(thread_data->td.td_deque_ntasks) >= 3023 TASK_DEQUE_SIZE(thread_data->td)) { 3024 KA_TRACE(30, ("__kmp_give_task: queue is full while giving task %p to " 3025 "thread %d.\n", 3026 taskdata, tid)); 3027 3028 // if this deque is bigger than the pass ratio give a chance to another 3029 // thread 3030 if (TASK_DEQUE_SIZE(thread_data->td) / INITIAL_TASK_DEQUE_SIZE >= pass) 3031 goto release_and_exit; 3032 3033 __kmp_realloc_task_deque(thread, thread_data); 3034 } 3035 } 3036 3037 // lock is held here, and there is space in the deque 3038 3039 thread_data->td.td_deque[thread_data->td.td_deque_tail] = taskdata; 3040 // Wrap index. 3041 thread_data->td.td_deque_tail = 3042 (thread_data->td.td_deque_tail + 1) & TASK_DEQUE_MASK(thread_data->td); 3043 TCW_4(thread_data->td.td_deque_ntasks, 3044 TCR_4(thread_data->td.td_deque_ntasks) + 1); 3045 3046 result = true; 3047 KA_TRACE(30, ("__kmp_give_task: successfully gave task %p to thread %d.\n", 3048 taskdata, tid)); 3049 3050 release_and_exit: 3051 __kmp_release_bootstrap_lock(&thread_data->td.td_deque_lock); 3052 3053 return result; 3054 } 3055 3056 /* The finish of the proxy tasks is divided in two pieces: 3057 - the top half is the one that can be done from a thread outside the team 3058 - the bottom half must be run from a them within the team 3059 3060 In order to run the bottom half the task gets queued back into one of the 3061 threads of the team. Once the td_incomplete_child_task counter of the parent 3062 is decremented the threads can leave the barriers. So, the bottom half needs 3063 to be queued before the counter is decremented. The top half is therefore 3064 divided in two parts: 3065 - things that can be run before queuing the bottom half 3066 - things that must be run after queuing the bottom half 3067 3068 This creates a second race as the bottom half can free the task before the 3069 second top half is executed. To avoid this we use the 3070 td_incomplete_child_task of the proxy task to synchronize the top and bottom 3071 half. */ 3072 static void __kmp_first_top_half_finish_proxy(kmp_taskdata_t *taskdata) { 3073 KMP_DEBUG_ASSERT(taskdata->td_flags.tasktype == TASK_EXPLICIT); 3074 KMP_DEBUG_ASSERT(taskdata->td_flags.proxy == TASK_PROXY); 3075 KMP_DEBUG_ASSERT(taskdata->td_flags.complete == 0); 3076 KMP_DEBUG_ASSERT(taskdata->td_flags.freed == 0); 3077 3078 taskdata->td_flags.complete = 1; // mark the task as completed 3079 3080 if (taskdata->td_taskgroup) 3081 KMP_TEST_THEN_DEC32(&taskdata->td_taskgroup->count); 3082 3083 // Create an imaginary children for this task so the bottom half cannot 3084 // release the task before we have completed the second top half 3085 TCI_4(taskdata->td_incomplete_child_tasks); 3086 } 3087 3088 static void __kmp_second_top_half_finish_proxy(kmp_taskdata_t *taskdata) { 3089 kmp_int32 children = 0; 3090 3091 // Predecrement simulated by "- 1" calculation 3092 children = 3093 KMP_TEST_THEN_DEC32(&taskdata->td_parent->td_incomplete_child_tasks) - 1; 3094 KMP_DEBUG_ASSERT(children >= 0); 3095 3096 // Remove the imaginary children 3097 TCD_4(taskdata->td_incomplete_child_tasks); 3098 } 3099 3100 static void __kmp_bottom_half_finish_proxy(kmp_int32 gtid, kmp_task_t *ptask) { 3101 kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(ptask); 3102 kmp_info_t *thread = __kmp_threads[gtid]; 3103 3104 KMP_DEBUG_ASSERT(taskdata->td_flags.proxy == TASK_PROXY); 3105 KMP_DEBUG_ASSERT(taskdata->td_flags.complete == 3106 1); // top half must run before bottom half 3107 3108 // We need to wait to make sure the top half is finished 3109 // Spinning here should be ok as this should happen quickly 3110 while (TCR_4(taskdata->td_incomplete_child_tasks) > 0) 3111 ; 3112 3113 __kmp_release_deps(gtid, taskdata); 3114 __kmp_free_task_and_ancestors(gtid, taskdata, thread); 3115 } 3116 3117 /*! 3118 @ingroup TASKING 3119 @param gtid Global Thread ID of encountering thread 3120 @param ptask Task which execution is completed 3121 3122 Execute the completation of a proxy task from a thread of that is part of the 3123 team. Run first and bottom halves directly. 3124 */ 3125 void __kmpc_proxy_task_completed(kmp_int32 gtid, kmp_task_t *ptask) { 3126 KMP_DEBUG_ASSERT(ptask != NULL); 3127 kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(ptask); 3128 KA_TRACE( 3129 10, ("__kmp_proxy_task_completed(enter): T#%d proxy task %p completing\n", 3130 gtid, taskdata)); 3131 3132 KMP_DEBUG_ASSERT(taskdata->td_flags.proxy == TASK_PROXY); 3133 3134 __kmp_first_top_half_finish_proxy(taskdata); 3135 __kmp_second_top_half_finish_proxy(taskdata); 3136 __kmp_bottom_half_finish_proxy(gtid, ptask); 3137 3138 KA_TRACE(10, 3139 ("__kmp_proxy_task_completed(exit): T#%d proxy task %p completing\n", 3140 gtid, taskdata)); 3141 } 3142 3143 /*! 3144 @ingroup TASKING 3145 @param ptask Task which execution is completed 3146 3147 Execute the completation of a proxy task from a thread that could not belong to 3148 the team. 3149 */ 3150 void __kmpc_proxy_task_completed_ooo(kmp_task_t *ptask) { 3151 KMP_DEBUG_ASSERT(ptask != NULL); 3152 kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(ptask); 3153 3154 KA_TRACE( 3155 10, 3156 ("__kmp_proxy_task_completed_ooo(enter): proxy task completing ooo %p\n", 3157 taskdata)); 3158 3159 KMP_DEBUG_ASSERT(taskdata->td_flags.proxy == TASK_PROXY); 3160 3161 __kmp_first_top_half_finish_proxy(taskdata); 3162 3163 // Enqueue task to complete bottom half completion from a thread within the 3164 // corresponding team 3165 kmp_team_t *team = taskdata->td_team; 3166 kmp_int32 nthreads = team->t.t_nproc; 3167 kmp_info_t *thread; 3168 3169 // This should be similar to start_k = __kmp_get_random( thread ) % nthreads 3170 // but we cannot use __kmp_get_random here 3171 kmp_int32 start_k = 0; 3172 kmp_int32 pass = 1; 3173 kmp_int32 k = start_k; 3174 3175 do { 3176 // For now we're just linearly trying to find a thread 3177 thread = team->t.t_threads[k]; 3178 k = (k + 1) % nthreads; 3179 3180 // we did a full pass through all the threads 3181 if (k == start_k) 3182 pass = pass << 1; 3183 3184 } while (!__kmp_give_task(thread, k, ptask, pass)); 3185 3186 __kmp_second_top_half_finish_proxy(taskdata); 3187 3188 KA_TRACE( 3189 10, 3190 ("__kmp_proxy_task_completed_ooo(exit): proxy task completing ooo %p\n", 3191 taskdata)); 3192 } 3193 3194 // __kmp_task_dup_alloc: Allocate the taskdata and make a copy of source task 3195 // for taskloop 3196 // 3197 // thread: allocating thread 3198 // task_src: pointer to source task to be duplicated 3199 // returns: a pointer to the allocated kmp_task_t structure (task). 3200 kmp_task_t *__kmp_task_dup_alloc(kmp_info_t *thread, kmp_task_t *task_src) { 3201 kmp_task_t *task; 3202 kmp_taskdata_t *taskdata; 3203 kmp_taskdata_t *taskdata_src; 3204 kmp_taskdata_t *parent_task = thread->th.th_current_task; 3205 size_t shareds_offset; 3206 size_t task_size; 3207 3208 KA_TRACE(10, ("__kmp_task_dup_alloc(enter): Th %p, source task %p\n", thread, 3209 task_src)); 3210 taskdata_src = KMP_TASK_TO_TASKDATA(task_src); 3211 KMP_DEBUG_ASSERT(taskdata_src->td_flags.proxy == 3212 TASK_FULL); // it should not be proxy task 3213 KMP_DEBUG_ASSERT(taskdata_src->td_flags.tasktype == TASK_EXPLICIT); 3214 task_size = taskdata_src->td_size_alloc; 3215 3216 // Allocate a kmp_taskdata_t block and a kmp_task_t block. 3217 KA_TRACE(30, ("__kmp_task_dup_alloc: Th %p, malloc size %ld\n", thread, 3218 task_size)); 3219 #if USE_FAST_MEMORY 3220 taskdata = (kmp_taskdata_t *)__kmp_fast_allocate(thread, task_size); 3221 #else 3222 taskdata = (kmp_taskdata_t *)__kmp_thread_malloc(thread, task_size); 3223 #endif /* USE_FAST_MEMORY */ 3224 KMP_MEMCPY(taskdata, taskdata_src, task_size); 3225 3226 task = KMP_TASKDATA_TO_TASK(taskdata); 3227 3228 // Initialize new task (only specific fields not affected by memcpy) 3229 taskdata->td_task_id = KMP_GEN_TASK_ID(); 3230 if (task->shareds != NULL) { // need setup shareds pointer 3231 shareds_offset = (char *)task_src->shareds - (char *)taskdata_src; 3232 task->shareds = &((char *)taskdata)[shareds_offset]; 3233 KMP_DEBUG_ASSERT((((kmp_uintptr_t)task->shareds) & (sizeof(void *) - 1)) == 3234 0); 3235 } 3236 taskdata->td_alloc_thread = thread; 3237 taskdata->td_parent = parent_task; 3238 taskdata->td_taskgroup = 3239 parent_task 3240 ->td_taskgroup; // task inherits the taskgroup from the parent task 3241 3242 // Only need to keep track of child task counts if team parallel and tasking 3243 // not serialized 3244 if (!(taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser)) { 3245 KMP_TEST_THEN_INC32(&parent_task->td_incomplete_child_tasks); 3246 if (parent_task->td_taskgroup) 3247 KMP_TEST_THEN_INC32(&parent_task->td_taskgroup->count); 3248 // Only need to keep track of allocated child tasks for explicit tasks since 3249 // implicit not deallocated 3250 if (taskdata->td_parent->td_flags.tasktype == TASK_EXPLICIT) 3251 KMP_TEST_THEN_INC32(&taskdata->td_parent->td_allocated_child_tasks); 3252 } 3253 3254 KA_TRACE(20, 3255 ("__kmp_task_dup_alloc(exit): Th %p, created task %p, parent=%p\n", 3256 thread, taskdata, taskdata->td_parent)); 3257 #if OMPT_SUPPORT 3258 __kmp_task_init_ompt(taskdata, thread->th.th_info.ds.ds_gtid, 3259 (void *)task->routine); 3260 #endif 3261 return task; 3262 } 3263 3264 // Routine optionally generated by the compiler for setting the lastprivate flag 3265 // and calling needed constructors for private/firstprivate objects 3266 // (used to form taskloop tasks from pattern task) 3267 // Parameters: dest task, src task, lastprivate flag. 3268 typedef void (*p_task_dup_t)(kmp_task_t *, kmp_task_t *, kmp_int32); 3269 3270 // __kmp_taskloop_linear: Start tasks of the taskloop linearly 3271 // 3272 // loc Source location information 3273 // gtid Global thread ID 3274 // task Pattern task, exposes the loop iteration range 3275 // lb Pointer to loop lower bound in task structure 3276 // ub Pointer to loop upper bound in task structure 3277 // st Loop stride 3278 // ub_glob Global upper bound (used for lastprivate check) 3279 // num_tasks Number of tasks to execute 3280 // grainsize Number of loop iterations per task 3281 // extras Number of chunks with grainsize+1 iterations 3282 // tc Iterations count 3283 // task_dup Tasks duplication routine 3284 void __kmp_taskloop_linear(ident_t *loc, int gtid, kmp_task_t *task, 3285 kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, 3286 kmp_uint64 ub_glob, kmp_uint64 num_tasks, 3287 kmp_uint64 grainsize, kmp_uint64 extras, 3288 kmp_uint64 tc, void *task_dup) { 3289 KMP_COUNT_BLOCK(OMP_TASKLOOP); 3290 KMP_TIME_PARTITIONED_BLOCK(OMP_taskloop_scheduling); 3291 p_task_dup_t ptask_dup = (p_task_dup_t)task_dup; 3292 kmp_uint64 lower = *lb; // compiler provides global bounds here 3293 kmp_uint64 upper = *ub; 3294 kmp_uint64 i; 3295 kmp_info_t *thread = __kmp_threads[gtid]; 3296 kmp_taskdata_t *current_task = thread->th.th_current_task; 3297 kmp_task_t *next_task; 3298 kmp_int32 lastpriv = 0; 3299 size_t lower_offset = 3300 (char *)lb - (char *)task; // remember offset of lb in the task structure 3301 size_t upper_offset = 3302 (char *)ub - (char *)task; // remember offset of ub in the task structure 3303 3304 KMP_DEBUG_ASSERT(tc == num_tasks * grainsize + extras); 3305 KMP_DEBUG_ASSERT(num_tasks > extras); 3306 KMP_DEBUG_ASSERT(num_tasks > 0); 3307 KA_TRACE(20, ("__kmp_taskloop_linear: T#%d: %lld tasks, grainsize %lld, " 3308 "extras %lld, i=%lld,%lld(%d)%lld, dup %p\n", 3309 gtid, num_tasks, grainsize, extras, lower, upper, ub_glob, st, 3310 task_dup)); 3311 3312 // Launch num_tasks tasks, assign grainsize iterations each task 3313 for (i = 0; i < num_tasks; ++i) { 3314 kmp_uint64 chunk_minus_1; 3315 if (extras == 0) { 3316 chunk_minus_1 = grainsize - 1; 3317 } else { 3318 chunk_minus_1 = grainsize; 3319 --extras; // first extras iterations get bigger chunk (grainsize+1) 3320 } 3321 upper = lower + st * chunk_minus_1; 3322 if (i == num_tasks - 1) { 3323 // schedule the last task, set lastprivate flag if needed 3324 if (st == 1) { // most common case 3325 KMP_DEBUG_ASSERT(upper == *ub); 3326 if (upper == ub_glob) 3327 lastpriv = 1; 3328 } else if (st > 0) { // positive loop stride 3329 KMP_DEBUG_ASSERT((kmp_uint64)st > *ub - upper); 3330 if ((kmp_uint64)st > ub_glob - upper) 3331 lastpriv = 1; 3332 } else { // negative loop stride 3333 KMP_DEBUG_ASSERT(upper + st < *ub); 3334 if (upper - ub_glob < (kmp_uint64)(-st)) 3335 lastpriv = 1; 3336 } 3337 } 3338 next_task = __kmp_task_dup_alloc(thread, task); // allocate new task 3339 // adjust task-specific bounds 3340 *(kmp_uint64 *)((char *)next_task + lower_offset) = lower; 3341 *(kmp_uint64 *)((char *)next_task + upper_offset) = upper; 3342 if (ptask_dup != NULL) // set lastprivate flag, construct fistprivates, etc. 3343 ptask_dup(next_task, task, lastpriv); 3344 KA_TRACE(40, ("__kmp_taskloop_linear: T#%d; task %p: lower %lld, " 3345 "upper %lld (offsets %p %p)\n", 3346 gtid, next_task, lower, upper, lower_offset, upper_offset)); 3347 __kmp_omp_task(gtid, next_task, true); // schedule new task 3348 lower = upper + st; // adjust lower bound for the next iteration 3349 } 3350 // free the pattern task and exit 3351 __kmp_task_start(gtid, task, current_task); // make internal bookkeeping 3352 // do not execute the pattern task, just do internal bookkeeping 3353 __kmp_task_finish(gtid, task, current_task); 3354 } 3355 3356 // Structure to keep taskloop parameters for auxiliary task 3357 // kept in the shareds of the task structure. 3358 typedef struct __taskloop_params { 3359 kmp_task_t *task; 3360 kmp_uint64 *lb; 3361 kmp_uint64 *ub; 3362 void *task_dup; 3363 kmp_int64 st; 3364 kmp_uint64 ub_glob; 3365 kmp_uint64 num_tasks; 3366 kmp_uint64 grainsize; 3367 kmp_uint64 extras; 3368 kmp_uint64 tc; 3369 kmp_uint64 num_t_min; 3370 } __taskloop_params_t; 3371 3372 void __kmp_taskloop_recur(ident_t *, int, kmp_task_t *, kmp_uint64 *, 3373 kmp_uint64 *, kmp_int64, kmp_uint64, kmp_uint64, 3374 kmp_uint64, kmp_uint64, kmp_uint64, kmp_uint64, 3375 void *); 3376 3377 // Execute part of the the taskloop submitted as a task. 3378 int __kmp_taskloop_task(int gtid, void *ptask) { 3379 __taskloop_params_t *p = 3380 (__taskloop_params_t *)((kmp_task_t *)ptask)->shareds; 3381 kmp_task_t *task = p->task; 3382 kmp_uint64 *lb = p->lb; 3383 kmp_uint64 *ub = p->ub; 3384 void *task_dup = p->task_dup; 3385 // p_task_dup_t ptask_dup = (p_task_dup_t)task_dup; 3386 kmp_int64 st = p->st; 3387 kmp_uint64 ub_glob = p->ub_glob; 3388 kmp_uint64 num_tasks = p->num_tasks; 3389 kmp_uint64 grainsize = p->grainsize; 3390 kmp_uint64 extras = p->extras; 3391 kmp_uint64 tc = p->tc; 3392 kmp_uint64 num_t_min = p->num_t_min; 3393 #if KMP_DEBUG 3394 kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(task); 3395 KMP_DEBUG_ASSERT(task != NULL); 3396 KA_TRACE(20, ("__kmp_taskloop_task: T#%d, task %p: %lld tasks, grainsize" 3397 " %lld, extras %lld, i=%lld,%lld(%d), dup %p\n", 3398 gtid, taskdata, num_tasks, grainsize, extras, *lb, *ub, st, 3399 task_dup)); 3400 #endif 3401 KMP_DEBUG_ASSERT(num_tasks * 2 + 1 > num_t_min); 3402 if (num_tasks > num_t_min) 3403 __kmp_taskloop_recur(NULL, gtid, task, lb, ub, st, ub_glob, num_tasks, 3404 grainsize, extras, tc, num_t_min, task_dup); 3405 else 3406 __kmp_taskloop_linear(NULL, gtid, task, lb, ub, st, ub_glob, num_tasks, 3407 grainsize, extras, tc, task_dup); 3408 3409 KA_TRACE(40, ("__kmp_taskloop_task(exit): T#%d\n", gtid)); 3410 return 0; 3411 } 3412 3413 // Schedule part of the the taskloop as a task, 3414 // execute the rest of the the taskloop. 3415 // 3416 // loc Source location information 3417 // gtid Global thread ID 3418 // task Pattern task, exposes the loop iteration range 3419 // lb Pointer to loop lower bound in task structure 3420 // ub Pointer to loop upper bound in task structure 3421 // st Loop stride 3422 // ub_glob Global upper bound (used for lastprivate check) 3423 // num_tasks Number of tasks to execute 3424 // grainsize Number of loop iterations per task 3425 // extras Number of chunks with grainsize+1 iterations 3426 // tc Iterations count 3427 // num_t_min Threashold to launch tasks recursively 3428 // task_dup Tasks duplication routine 3429 void __kmp_taskloop_recur(ident_t *loc, int gtid, kmp_task_t *task, 3430 kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, 3431 kmp_uint64 ub_glob, kmp_uint64 num_tasks, 3432 kmp_uint64 grainsize, kmp_uint64 extras, 3433 kmp_uint64 tc, kmp_uint64 num_t_min, void *task_dup) { 3434 #if KMP_DEBUG 3435 kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(task); 3436 KMP_DEBUG_ASSERT(task != NULL); 3437 KMP_DEBUG_ASSERT(num_tasks > num_t_min); 3438 KA_TRACE(20, ("__kmp_taskloop_recur: T#%d, task %p: %lld tasks, grainsize" 3439 " %lld, extras %lld, i=%lld,%lld(%d), dup %p\n", 3440 gtid, taskdata, num_tasks, grainsize, extras, *lb, *ub, st, 3441 task_dup)); 3442 #endif 3443 p_task_dup_t ptask_dup = (p_task_dup_t)task_dup; 3444 kmp_uint64 lower = *lb; 3445 kmp_uint64 upper = *ub; 3446 kmp_info_t *thread = __kmp_threads[gtid]; 3447 // kmp_taskdata_t *current_task = thread->th.th_current_task; 3448 kmp_task_t *next_task; 3449 kmp_int32 lastpriv = 0; 3450 size_t lower_offset = 3451 (char *)lb - (char *)task; // remember offset of lb in the task structure 3452 size_t upper_offset = 3453 (char *)ub - (char *)task; // remember offset of ub in the task structure 3454 3455 KMP_DEBUG_ASSERT(tc == num_tasks * grainsize + extras); 3456 KMP_DEBUG_ASSERT(num_tasks > extras); 3457 KMP_DEBUG_ASSERT(num_tasks > 0); 3458 3459 // split the loop in two halves 3460 kmp_uint64 lb1, ub0, tc0, tc1, ext0, ext1; 3461 kmp_uint64 gr_size0 = grainsize; 3462 kmp_uint64 n_tsk0 = num_tasks >> 1; // num_tasks/2 to execute 3463 kmp_uint64 n_tsk1 = num_tasks - n_tsk0; // to schedule as a task 3464 if (n_tsk0 <= extras) { 3465 gr_size0++; // integrate extras into grainsize 3466 ext0 = 0; // no extra iters in 1st half 3467 ext1 = extras - n_tsk0; // remaining extras 3468 tc0 = gr_size0 * n_tsk0; 3469 tc1 = tc - tc0; 3470 } else { // n_tsk0 > extras 3471 ext1 = 0; // no extra iters in 2nd half 3472 ext0 = extras; 3473 tc1 = grainsize * n_tsk1; 3474 tc0 = tc - tc1; 3475 } 3476 ub0 = lower + st * (tc0 - 1); 3477 lb1 = ub0 + st; 3478 3479 // create pattern task for 2nd half of the loop 3480 next_task = __kmp_task_dup_alloc(thread, task); // duplicate the task 3481 // adjust lower bound (upper bound is not changed) for the 2nd half 3482 *(kmp_uint64 *)((char *)next_task + lower_offset) = lb1; 3483 if (ptask_dup != NULL) // construct fistprivates, etc. 3484 ptask_dup(next_task, task, 0); 3485 *ub = ub0; // adjust upper bound for the 1st half 3486 3487 // create auxiliary task for 2nd half of the loop 3488 kmp_task_t *new_task = 3489 __kmpc_omp_task_alloc(loc, gtid, 1, 3 * sizeof(void *), 3490 sizeof(__taskloop_params_t), &__kmp_taskloop_task); 3491 __taskloop_params_t *p = (__taskloop_params_t *)new_task->shareds; 3492 p->task = next_task; 3493 p->lb = (kmp_uint64 *)((char *)next_task + lower_offset); 3494 p->ub = (kmp_uint64 *)((char *)next_task + upper_offset); 3495 p->task_dup = task_dup; 3496 p->st = st; 3497 p->ub_glob = ub_glob; 3498 p->num_tasks = n_tsk1; 3499 p->grainsize = grainsize; 3500 p->extras = ext1; 3501 p->tc = tc1; 3502 p->num_t_min = num_t_min; 3503 __kmp_omp_task(gtid, new_task, true); // schedule new task 3504 3505 // execute the 1st half of current subrange 3506 if (n_tsk0 > num_t_min) 3507 __kmp_taskloop_recur(loc, gtid, task, lb, ub, st, ub_glob, n_tsk0, gr_size0, 3508 ext0, tc0, num_t_min, task_dup); 3509 else 3510 __kmp_taskloop_linear(loc, gtid, task, lb, ub, st, ub_glob, n_tsk0, 3511 gr_size0, ext0, tc0, task_dup); 3512 3513 KA_TRACE(40, ("__kmpc_taskloop_recur(exit): T#%d\n", gtid)); 3514 } 3515 3516 /*! 3517 @ingroup TASKING 3518 @param loc Source location information 3519 @param gtid Global thread ID 3520 @param task Task structure 3521 @param if_val Value of the if clause 3522 @param lb Pointer to loop lower bound in task structure 3523 @param ub Pointer to loop upper bound in task structure 3524 @param st Loop stride 3525 @param nogroup Flag, 1 if nogroup clause specified, 0 otherwise 3526 @param sched Schedule specified 0/1/2 for none/grainsize/num_tasks 3527 @param grainsize Schedule value if specified 3528 @param task_dup Tasks duplication routine 3529 3530 Execute the taskloop construct. 3531 */ 3532 void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int if_val, 3533 kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, 3534 int sched, kmp_uint64 grainsize, void *task_dup) { 3535 kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(task); 3536 KMP_DEBUG_ASSERT(task != NULL); 3537 3538 KA_TRACE(20, ("__kmpc_taskloop: T#%d, task %p, lb %lld, ub %lld, st %lld, " 3539 "grain %llu(%d), dup %p\n", 3540 gtid, taskdata, *lb, *ub, st, grainsize, sched, task_dup)); 3541 3542 if (nogroup == 0) 3543 __kmpc_taskgroup(loc, gtid); 3544 3545 // ========================================================================= 3546 // calculate loop parameters 3547 kmp_uint64 tc; 3548 kmp_uint64 lower = *lb; // compiler provides global bounds here 3549 kmp_uint64 upper = *ub; 3550 kmp_uint64 ub_glob = upper; // global upper used to calc lastprivate flag 3551 kmp_uint64 num_tasks = 0, extras = 0; 3552 kmp_uint64 num_tasks_min = __kmp_taskloop_min_tasks; 3553 kmp_info_t *thread = __kmp_threads[gtid]; 3554 kmp_taskdata_t *current_task = thread->th.th_current_task; 3555 3556 // compute trip count 3557 if (st == 1) { // most common case 3558 tc = upper - lower + 1; 3559 } else if (st < 0) { 3560 tc = (lower - upper) / (-st) + 1; 3561 } else { // st > 0 3562 tc = (upper - lower) / st + 1; 3563 } 3564 if (tc == 0) { 3565 KA_TRACE(20, ("__kmpc_taskloop(exit): T#%d zero-trip loop\n", gtid)); 3566 // free the pattern task and exit 3567 __kmp_task_start(gtid, task, current_task); 3568 // do not execute anything for zero-trip loop 3569 __kmp_task_finish(gtid, task, current_task); 3570 return; 3571 } 3572 if (num_tasks_min == 0) 3573 // TODO: can we choose better default heuristic? 3574 num_tasks_min = 3575 KMP_MIN(thread->th.th_team_nproc * 10, INITIAL_TASK_DEQUE_SIZE); 3576 3577 // compute num_tasks/grainsize based on the input provided 3578 switch (sched) { 3579 case 0: // no schedule clause specified, we can choose the default 3580 // let's try to schedule (team_size*10) tasks 3581 grainsize = thread->th.th_team_nproc * 10; 3582 case 2: // num_tasks provided 3583 if (grainsize > tc) { 3584 num_tasks = tc; // too big num_tasks requested, adjust values 3585 grainsize = 1; 3586 extras = 0; 3587 } else { 3588 num_tasks = grainsize; 3589 grainsize = tc / num_tasks; 3590 extras = tc % num_tasks; 3591 } 3592 break; 3593 case 1: // grainsize provided 3594 if (grainsize > tc) { 3595 num_tasks = 1; // too big grainsize requested, adjust values 3596 grainsize = tc; 3597 extras = 0; 3598 } else { 3599 num_tasks = tc / grainsize; 3600 // adjust grainsize for balanced distribution of iterations 3601 grainsize = tc / num_tasks; 3602 extras = tc % num_tasks; 3603 } 3604 break; 3605 default: 3606 KMP_ASSERT2(0, "unknown scheduling of taskloop"); 3607 } 3608 KMP_DEBUG_ASSERT(tc == num_tasks * grainsize + extras); 3609 KMP_DEBUG_ASSERT(num_tasks > extras); 3610 KMP_DEBUG_ASSERT(num_tasks > 0); 3611 // ========================================================================= 3612 3613 // check if clause value first 3614 if (if_val == 0) { // if(0) specified, mark task as serial 3615 taskdata->td_flags.task_serial = 1; 3616 taskdata->td_flags.tiedness = TASK_TIED; // AC: serial task cannot be untied 3617 // always start serial tasks linearly 3618 __kmp_taskloop_linear(loc, gtid, task, lb, ub, st, ub_glob, num_tasks, 3619 grainsize, extras, tc, task_dup); 3620 } else if (num_tasks > num_tasks_min) { 3621 KA_TRACE(20, ("__kmpc_taskloop: T#%d, go recursive: tc %llu, #tasks %llu" 3622 "(%lld), grain %llu, extras %llu\n", 3623 gtid, tc, num_tasks, num_tasks_min, grainsize, extras)); 3624 __kmp_taskloop_recur(loc, gtid, task, lb, ub, st, ub_glob, num_tasks, 3625 grainsize, extras, tc, num_tasks_min, task_dup); 3626 } else { 3627 KA_TRACE(20, ("__kmpc_taskloop: T#%d, go linear: tc %llu, #tasks %llu" 3628 "(%lld), grain %llu, extras %llu\n", 3629 gtid, tc, num_tasks, num_tasks_min, grainsize, extras)); 3630 __kmp_taskloop_linear(loc, gtid, task, lb, ub, st, ub_glob, num_tasks, 3631 grainsize, extras, tc, task_dup); 3632 } 3633 3634 if (nogroup == 0) 3635 __kmpc_end_taskgroup(loc, gtid); 3636 KA_TRACE(20, ("__kmpc_taskloop(exit): T#%d\n", gtid)); 3637 } 3638 3639 #endif 3640