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