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