LLVM OpenMP* Runtime Library
kmp_runtime.cpp
1/*
2 * kmp_runtime.cpp -- KPTS runtime support library
3 */
4
5//===----------------------------------------------------------------------===//
6//
7// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8// See https://llvm.org/LICENSE.txt for license information.
9// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10//
11//===----------------------------------------------------------------------===//
12
13#include "kmp.h"
14#include "kmp_affinity.h"
15#include "kmp_atomic.h"
16#include "kmp_environment.h"
17#include "kmp_error.h"
18#include "kmp_i18n.h"
19#include "kmp_io.h"
20#include "kmp_itt.h"
21#include "kmp_settings.h"
22#include "kmp_stats.h"
23#include "kmp_str.h"
24#include "kmp_wait_release.h"
25#include "kmp_wrapper_getpid.h"
26#include "kmp_dispatch.h"
27#include "kmp_utils.h"
28#if KMP_USE_HIER_SCHED
29#include "kmp_dispatch_hier.h"
30#endif
31
32#if OMPT_SUPPORT
33#include "ompt-specific.h"
34#endif
35#if OMPD_SUPPORT
36#include "ompd-specific.h"
37#endif
38
39#if OMP_PROFILING_SUPPORT
40#include "llvm/Support/TimeProfiler.h"
41static char *ProfileTraceFile = nullptr;
42#endif
43
44/* these are temporary issues to be dealt with */
45#define KMP_USE_PRCTL 0
46
47#if KMP_OS_WINDOWS
48#include <process.h>
49#endif
50
51#ifndef KMP_USE_SHM
52// Windows and WASI do not need these include files as they don't use shared
53// memory.
54#else
55#include <sys/mman.h>
56#include <sys/stat.h>
57#include <fcntl.h>
58#define SHM_SIZE 1024
59#endif
60
61#if defined(KMP_GOMP_COMPAT)
62char const __kmp_version_alt_comp[] =
63 KMP_VERSION_PREFIX "alternative compiler support: yes";
64#endif /* defined(KMP_GOMP_COMPAT) */
65
66char const __kmp_version_omp_api[] =
67 KMP_VERSION_PREFIX "API version: 5.0 (201611)";
68
69#ifdef KMP_DEBUG
70char const __kmp_version_lock[] =
71 KMP_VERSION_PREFIX "lock type: run time selectable";
72#endif /* KMP_DEBUG */
73
74#define KMP_MIN(x, y) ((x) < (y) ? (x) : (y))
75
76/* ------------------------------------------------------------------------ */
77
78#if KMP_USE_MONITOR
79kmp_info_t __kmp_monitor;
80#endif
81
82/* Forward declarations */
83
84void __kmp_cleanup(void);
85
86static void __kmp_initialize_info(kmp_info_t *, kmp_team_t *, int tid,
87 int gtid);
88static void __kmp_initialize_team(kmp_team_t *team, int new_nproc,
89 kmp_internal_control_t *new_icvs,
90 ident_t *loc);
91#if KMP_AFFINITY_SUPPORTED
92static void __kmp_partition_places(kmp_team_t *team,
93 int update_master_only = 0);
94#endif
95static void __kmp_do_serial_initialize(void);
96#if ENABLE_LIBOMPTARGET
97static void __kmp_target_init(void);
98#endif // ENABLE_LIBOMPTARGET
99void __kmp_fork_barrier(int gtid, int tid);
100void __kmp_join_barrier(int gtid);
101void __kmp_setup_icv_copy(kmp_team_t *team, int new_nproc,
102 kmp_internal_control_t *new_icvs, ident_t *loc);
103
104#ifdef USE_LOAD_BALANCE
105static int __kmp_load_balance_nproc(kmp_root_t *root, int set_nproc);
106#endif
107
108static int __kmp_expand_threads(int nNeed);
109#if KMP_OS_WINDOWS
110static int __kmp_unregister_root_other_thread(int gtid);
111#endif
112static void __kmp_reap_thread(kmp_info_t *thread, int is_root);
113kmp_info_t *__kmp_thread_pool_insert_pt = NULL;
114
115void __kmp_resize_dist_barrier(kmp_team_t *team, int old_nthreads,
116 int new_nthreads);
117void __kmp_add_threads_to_team(kmp_team_t *team, int new_nthreads);
118
119static kmp_nested_nthreads_t *__kmp_override_nested_nth(kmp_info_t *thr,
120 int level) {
121 kmp_nested_nthreads_t *new_nested_nth =
122 (kmp_nested_nthreads_t *)KMP_INTERNAL_MALLOC(
123 sizeof(kmp_nested_nthreads_t));
124 int new_size = level + thr->th.th_set_nested_nth_sz;
125 new_nested_nth->nth = (int *)KMP_INTERNAL_MALLOC(new_size * sizeof(int));
126 for (int i = 0; i < level + 1; ++i)
127 new_nested_nth->nth[i] = 0;
128 for (int i = level + 1, j = 1; i < new_size; ++i, ++j)
129 new_nested_nth->nth[i] = thr->th.th_set_nested_nth[j];
130 new_nested_nth->size = new_nested_nth->used = new_size;
131 return new_nested_nth;
132}
133
134/* Calculate the identifier of the current thread */
135/* fast (and somewhat portable) way to get unique identifier of executing
136 thread. Returns KMP_GTID_DNE if we haven't been assigned a gtid. */
137int __kmp_get_global_thread_id() {
138 int i;
139 kmp_info_t **other_threads;
140 size_t stack_data;
141 char *stack_addr;
142 size_t stack_size;
143 char *stack_base;
144
145 KA_TRACE(
146 1000,
147 ("*** __kmp_get_global_thread_id: entering, nproc=%d all_nproc=%d\n",
148 __kmp_nth, __kmp_all_nth));
149
150 /* JPH - to handle the case where __kmpc_end(0) is called immediately prior to
151 a parallel region, made it return KMP_GTID_DNE to force serial_initialize
152 by caller. Had to handle KMP_GTID_DNE at all call-sites, or else guarantee
153 __kmp_init_gtid for this to work. */
154
155 if (!TCR_4(__kmp_init_gtid))
156 return KMP_GTID_DNE;
157
158#ifdef KMP_TDATA_GTID
159 if (TCR_4(__kmp_gtid_mode) >= 3) {
160 KA_TRACE(1000, ("*** __kmp_get_global_thread_id: using TDATA\n"));
161 return __kmp_gtid;
162 }
163#endif
164 if (TCR_4(__kmp_gtid_mode) >= 2) {
165 KA_TRACE(1000, ("*** __kmp_get_global_thread_id: using keyed TLS\n"));
166 return __kmp_gtid_get_specific();
167 }
168 KA_TRACE(1000, ("*** __kmp_get_global_thread_id: using internal alg.\n"));
169
170 stack_addr = (char *)&stack_data;
171 other_threads = __kmp_threads;
172
173 /* ATT: The code below is a source of potential bugs due to unsynchronized
174 access to __kmp_threads array. For example:
175 1. Current thread loads other_threads[i] to thr and checks it, it is
176 non-NULL.
177 2. Current thread is suspended by OS.
178 3. Another thread unregisters and finishes (debug versions of free()
179 may fill memory with something like 0xEF).
180 4. Current thread is resumed.
181 5. Current thread reads junk from *thr.
182 TODO: Fix it. --ln */
183
184 for (i = 0; i < __kmp_threads_capacity; i++) {
185
186 kmp_info_t *thr = (kmp_info_t *)TCR_SYNC_PTR(other_threads[i]);
187 if (!thr)
188 continue;
189
190 stack_size = (size_t)TCR_PTR(thr->th.th_info.ds.ds_stacksize);
191 stack_base = (char *)TCR_PTR(thr->th.th_info.ds.ds_stackbase);
192
193 /* stack grows down -- search through all of the active threads */
194
195 if (stack_addr <= stack_base) {
196 size_t stack_diff = stack_base - stack_addr;
197
198 if (stack_diff <= stack_size) {
199 /* The only way we can be closer than the allocated */
200 /* stack size is if we are running on this thread. */
201 // __kmp_gtid_get_specific can return negative value because this
202 // function can be called by thread destructor. However, before the
203 // thread destructor is called, the value of the corresponding
204 // thread-specific data will be reset to NULL.
205 KMP_DEBUG_ASSERT(__kmp_gtid_get_specific() < 0 ||
206 __kmp_gtid_get_specific() == i);
207 return i;
208 }
209 }
210 }
211
212 /* get specific to try and determine our gtid */
213 KA_TRACE(1000,
214 ("*** __kmp_get_global_thread_id: internal alg. failed to find "
215 "thread, using TLS\n"));
216 i = __kmp_gtid_get_specific();
217
218 /*fprintf( stderr, "=== %d\n", i ); */ /* GROO */
219
220 /* if we havn't been assigned a gtid, then return code */
221 if (i < 0)
222 return i;
223
224 // other_threads[i] can be nullptr at this point because the corresponding
225 // thread could have already been destructed. It can happen when this function
226 // is called in end library routine.
227 if (!TCR_SYNC_PTR(other_threads[i]))
228 return i;
229
230 /* dynamically updated stack window for uber threads to avoid get_specific
231 call */
232 if (!TCR_4(other_threads[i]->th.th_info.ds.ds_stackgrow)) {
233 KMP_FATAL(StackOverflow, i);
234 }
235
236 stack_base = (char *)other_threads[i]->th.th_info.ds.ds_stackbase;
237 if (stack_addr > stack_base) {
238 TCW_PTR(other_threads[i]->th.th_info.ds.ds_stackbase, stack_addr);
239 TCW_PTR(other_threads[i]->th.th_info.ds.ds_stacksize,
240 other_threads[i]->th.th_info.ds.ds_stacksize + stack_addr -
241 stack_base);
242 } else {
243 TCW_PTR(other_threads[i]->th.th_info.ds.ds_stacksize,
244 stack_base - stack_addr);
245 }
246
247 /* Reprint stack bounds for ubermaster since they have been refined */
248 if (__kmp_storage_map) {
249 char *stack_end = (char *)other_threads[i]->th.th_info.ds.ds_stackbase;
250 char *stack_beg = stack_end - other_threads[i]->th.th_info.ds.ds_stacksize;
251 __kmp_print_storage_map_gtid(i, stack_beg, stack_end,
252 other_threads[i]->th.th_info.ds.ds_stacksize,
253 "th_%d stack (refinement)", i);
254 }
255 return i;
256}
257
258int __kmp_get_global_thread_id_reg() {
259 int gtid;
260
261 if (!__kmp_init_serial) {
262 gtid = KMP_GTID_DNE;
263 } else
264#ifdef KMP_TDATA_GTID
265 if (TCR_4(__kmp_gtid_mode) >= 3) {
266 KA_TRACE(1000, ("*** __kmp_get_global_thread_id_reg: using TDATA\n"));
267 gtid = __kmp_gtid;
268 } else
269#endif
270 if (TCR_4(__kmp_gtid_mode) >= 2) {
271 KA_TRACE(1000, ("*** __kmp_get_global_thread_id_reg: using keyed TLS\n"));
272 gtid = __kmp_gtid_get_specific();
273 } else {
274 KA_TRACE(1000,
275 ("*** __kmp_get_global_thread_id_reg: using internal alg.\n"));
276 gtid = __kmp_get_global_thread_id();
277 }
278
279 /* we must be a new uber master sibling thread */
280 if (gtid == KMP_GTID_DNE) {
281 KA_TRACE(10,
282 ("__kmp_get_global_thread_id_reg: Encountered new root thread. "
283 "Registering a new gtid.\n"));
284 __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
285 if (!__kmp_init_serial) {
286 __kmp_do_serial_initialize();
287 gtid = __kmp_gtid_get_specific();
288 } else {
289 gtid = __kmp_register_root(FALSE);
290 }
291 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
292 /*__kmp_printf( "+++ %d\n", gtid ); */ /* GROO */
293 }
294
295 KMP_DEBUG_ASSERT(gtid >= 0);
296
297 return gtid;
298}
299
300/* caller must hold forkjoin_lock */
301void __kmp_check_stack_overlap(kmp_info_t *th) {
302 int f;
303 char *stack_beg = NULL;
304 char *stack_end = NULL;
305 int gtid;
306
307 KA_TRACE(10, ("__kmp_check_stack_overlap: called\n"));
308 if (__kmp_storage_map) {
309 stack_end = (char *)th->th.th_info.ds.ds_stackbase;
310 stack_beg = stack_end - th->th.th_info.ds.ds_stacksize;
311
312 gtid = __kmp_gtid_from_thread(th);
313
314 if (gtid == KMP_GTID_MONITOR) {
315 __kmp_print_storage_map_gtid(
316 gtid, stack_beg, stack_end, th->th.th_info.ds.ds_stacksize,
317 "th_%s stack (%s)", "mon",
318 (th->th.th_info.ds.ds_stackgrow) ? "initial" : "actual");
319 } else {
320 __kmp_print_storage_map_gtid(
321 gtid, stack_beg, stack_end, th->th.th_info.ds.ds_stacksize,
322 "th_%d stack (%s)", gtid,
323 (th->th.th_info.ds.ds_stackgrow) ? "initial" : "actual");
324 }
325 }
326
327 /* No point in checking ubermaster threads since they use refinement and
328 * cannot overlap */
329 gtid = __kmp_gtid_from_thread(th);
330 if (__kmp_env_checks == TRUE && !KMP_UBER_GTID(gtid)) {
331 KA_TRACE(10,
332 ("__kmp_check_stack_overlap: performing extensive checking\n"));
333 if (stack_beg == NULL) {
334 stack_end = (char *)th->th.th_info.ds.ds_stackbase;
335 stack_beg = stack_end - th->th.th_info.ds.ds_stacksize;
336 }
337
338 for (f = 0; f < __kmp_threads_capacity; f++) {
339 kmp_info_t *f_th = (kmp_info_t *)TCR_SYNC_PTR(__kmp_threads[f]);
340
341 if (f_th && f_th != th) {
342 char *other_stack_end =
343 (char *)TCR_PTR(f_th->th.th_info.ds.ds_stackbase);
344 char *other_stack_beg =
345 other_stack_end - (size_t)TCR_PTR(f_th->th.th_info.ds.ds_stacksize);
346 if ((stack_beg > other_stack_beg && stack_beg < other_stack_end) ||
347 (stack_end > other_stack_beg && stack_end < other_stack_end)) {
348
349 /* Print the other stack values before the abort */
350 if (__kmp_storage_map)
351 __kmp_print_storage_map_gtid(
352 -1, other_stack_beg, other_stack_end,
353 (size_t)TCR_PTR(f_th->th.th_info.ds.ds_stacksize),
354 "th_%d stack (overlapped)", __kmp_gtid_from_thread(f_th));
355
356 __kmp_fatal(KMP_MSG(StackOverlap), KMP_HNT(ChangeStackLimit),
357 __kmp_msg_null);
358 }
359 }
360 }
361 }
362 KA_TRACE(10, ("__kmp_check_stack_overlap: returning\n"));
363}
364
365/* ------------------------------------------------------------------------ */
366
367void __kmp_infinite_loop(void) {
368 static int done = FALSE;
369
370 while (!done) {
371 KMP_YIELD(TRUE);
372 }
373}
374
375#define MAX_MESSAGE 512
376
377void __kmp_print_storage_map_gtid(int gtid, void *p1, void *p2, size_t size,
378 char const *format, ...) {
379 char buffer[MAX_MESSAGE];
380 va_list ap;
381
382 va_start(ap, format);
383 KMP_SNPRINTF(buffer, sizeof(buffer), "OMP storage map: %p %p%8lu %s\n", p1,
384 p2, (unsigned long)size, format);
385 __kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
386 __kmp_vprintf(kmp_err, buffer, ap);
387#if KMP_PRINT_DATA_PLACEMENT
388 int node;
389 if (gtid >= 0) {
390 if (p1 <= p2 && (char *)p2 - (char *)p1 == size) {
391 if (__kmp_storage_map_verbose) {
392 node = __kmp_get_host_node(p1);
393 if (node < 0) /* doesn't work, so don't try this next time */
394 __kmp_storage_map_verbose = FALSE;
395 else {
396 char *last;
397 int lastNode;
398 int localProc = __kmp_get_cpu_from_gtid(gtid);
399
400 const int page_size = KMP_GET_PAGE_SIZE();
401
402 p1 = (void *)((size_t)p1 & ~((size_t)page_size - 1));
403 p2 = (void *)(((size_t)p2 - 1) & ~((size_t)page_size - 1));
404 if (localProc >= 0)
405 __kmp_printf_no_lock(" GTID %d localNode %d\n", gtid,
406 localProc >> 1);
407 else
408 __kmp_printf_no_lock(" GTID %d\n", gtid);
409#if KMP_USE_PRCTL
410 /* The more elaborate format is disabled for now because of the prctl
411 * hanging bug. */
412 do {
413 last = p1;
414 lastNode = node;
415 /* This loop collates adjacent pages with the same host node. */
416 do {
417 (char *)p1 += page_size;
418 } while (p1 <= p2 && (node = __kmp_get_host_node(p1)) == lastNode);
419 __kmp_printf_no_lock(" %p-%p memNode %d\n", last, (char *)p1 - 1,
420 lastNode);
421 } while (p1 <= p2);
422#else
423 __kmp_printf_no_lock(" %p-%p memNode %d\n", p1,
424 (char *)p1 + (page_size - 1),
425 __kmp_get_host_node(p1));
426 if (p1 < p2) {
427 __kmp_printf_no_lock(" %p-%p memNode %d\n", p2,
428 (char *)p2 + (page_size - 1),
429 __kmp_get_host_node(p2));
430 }
431#endif
432 }
433 }
434 } else
435 __kmp_printf_no_lock(" %s\n", KMP_I18N_STR(StorageMapWarning));
436 }
437#endif /* KMP_PRINT_DATA_PLACEMENT */
438 __kmp_release_bootstrap_lock(&__kmp_stdio_lock);
439
440 va_end(ap);
441}
442
443void __kmp_warn(char const *format, ...) {
444 char buffer[MAX_MESSAGE];
445 va_list ap;
446
447 if (__kmp_generate_warnings == kmp_warnings_off) {
448 return;
449 }
450
451 va_start(ap, format);
452
453 KMP_SNPRINTF(buffer, sizeof(buffer), "OMP warning: %s\n", format);
454 __kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
455 __kmp_vprintf(kmp_err, buffer, ap);
456 __kmp_release_bootstrap_lock(&__kmp_stdio_lock);
457
458 va_end(ap);
459}
460
461void __kmp_abort_process() {
462 // A failed assertion or fatal error raised from inside the abort path itself
463 // re-enters this function on the same thread. __kmp_exit_lock is not
464 // recursive, so re-acquiring it below would hang the process instead of
465 // terminating it. Terminate directly on re-entry.
466 static KMP_THREAD_LOCAL bool aborting = false;
467 if (aborting)
468 abort();
469 aborting = true;
470
471 // Later threads may stall here, but that's ok because abort() will kill them.
472 __kmp_acquire_bootstrap_lock(&__kmp_exit_lock);
473
474 if (__kmp_debug_buf) {
475 __kmp_dump_debug_buffer();
476 }
477
478#if KMP_OS_WINDOWS
479 // Let other threads know of abnormal termination and prevent deadlock
480 // if abort happened during library initialization or shutdown
481 __kmp_global.g.g_abort = SIGABRT;
482
483 /* On Windows* OS by default abort() causes pop-up error box, which stalls
484 nightly testing. Unfortunately, we cannot reliably suppress pop-up error
485 boxes. _set_abort_behavior() works well, but this function is not
486 available in VS7 (this is not problem for DLL, but it is a problem for
487 static OpenMP RTL). SetErrorMode (and so, timelimit utility) does not
488 help, at least in some versions of MS C RTL.
489
490 It seems following sequence is the only way to simulate abort() and
491 avoid pop-up error box. */
492 raise(SIGABRT);
493 _exit(3); // Just in case, if signal ignored, exit anyway.
494#else
495 __kmp_unregister_library();
496 abort();
497#endif
498
499 __kmp_infinite_loop();
500 __kmp_release_bootstrap_lock(&__kmp_exit_lock);
501
502} // __kmp_abort_process
503
504void __kmp_abort_thread(void) {
505 // TODO: Eliminate g_abort global variable and this function.
506 // In case of abort just call abort(), it will kill all the threads.
507 __kmp_infinite_loop();
508} // __kmp_abort_thread
509
510/* Print out the storage map for the major kmp_info_t thread data structures
511 that are allocated together. */
512
513static void __kmp_print_thread_storage_map(kmp_info_t *thr, int gtid) {
514 __kmp_print_storage_map_gtid(gtid, thr, thr + 1, sizeof(kmp_info_t), "th_%d",
515 gtid);
516
517 __kmp_print_storage_map_gtid(gtid, &thr->th.th_info, &thr->th.th_team,
518 sizeof(kmp_desc_t), "th_%d.th_info", gtid);
519
520 __kmp_print_storage_map_gtid(gtid, &thr->th.th_local, &thr->th.th_pri_head,
521 sizeof(kmp_local_t), "th_%d.th_local", gtid);
522
523 __kmp_print_storage_map_gtid(
524 gtid, &thr->th.th_bar[0], &thr->th.th_bar[bs_last_barrier],
525 sizeof(kmp_balign_t) * bs_last_barrier, "th_%d.th_bar", gtid);
526
527 __kmp_print_storage_map_gtid(gtid, &thr->th.th_bar[bs_plain_barrier],
528 &thr->th.th_bar[bs_plain_barrier + 1],
529 sizeof(kmp_balign_t), "th_%d.th_bar[plain]",
530 gtid);
531
532 __kmp_print_storage_map_gtid(gtid, &thr->th.th_bar[bs_forkjoin_barrier],
533 &thr->th.th_bar[bs_forkjoin_barrier + 1],
534 sizeof(kmp_balign_t), "th_%d.th_bar[forkjoin]",
535 gtid);
536
537#if KMP_FAST_REDUCTION_BARRIER
538 __kmp_print_storage_map_gtid(gtid, &thr->th.th_bar[bs_reduction_barrier],
539 &thr->th.th_bar[bs_reduction_barrier + 1],
540 sizeof(kmp_balign_t), "th_%d.th_bar[reduction]",
541 gtid);
542#endif // KMP_FAST_REDUCTION_BARRIER
543}
544
545/* Print out the storage map for the major kmp_team_t team data structures
546 that are allocated together. */
547
548static void __kmp_print_team_storage_map(const char *header, kmp_team_t *team,
549 int team_id, int num_thr) {
550 int num_disp_buff = team->t.t_max_nproc > 1 ? __kmp_dispatch_num_buffers : 2;
551 __kmp_print_storage_map_gtid(-1, team, team + 1, sizeof(kmp_team_t), "%s_%d",
552 header, team_id);
553
554 __kmp_print_storage_map_gtid(-1, &team->t.t_bar[0],
555 &team->t.t_bar[bs_last_barrier],
556 sizeof(kmp_balign_team_t) * bs_last_barrier,
557 "%s_%d.t_bar", header, team_id);
558
559 __kmp_print_storage_map_gtid(-1, &team->t.t_bar[bs_plain_barrier],
560 &team->t.t_bar[bs_plain_barrier + 1],
561 sizeof(kmp_balign_team_t), "%s_%d.t_bar[plain]",
562 header, team_id);
563
564 __kmp_print_storage_map_gtid(-1, &team->t.t_bar[bs_forkjoin_barrier],
565 &team->t.t_bar[bs_forkjoin_barrier + 1],
566 sizeof(kmp_balign_team_t),
567 "%s_%d.t_bar[forkjoin]", header, team_id);
568
569#if KMP_FAST_REDUCTION_BARRIER
570 __kmp_print_storage_map_gtid(-1, &team->t.t_bar[bs_reduction_barrier],
571 &team->t.t_bar[bs_reduction_barrier + 1],
572 sizeof(kmp_balign_team_t),
573 "%s_%d.t_bar[reduction]", header, team_id);
574#endif // KMP_FAST_REDUCTION_BARRIER
575
576 __kmp_print_storage_map_gtid(
577 -1, &team->t.t_dispatch[0], &team->t.t_dispatch[num_thr],
578 sizeof(kmp_disp_t) * num_thr, "%s_%d.t_dispatch", header, team_id);
579
580 __kmp_print_storage_map_gtid(
581 -1, &team->t.t_threads[0], &team->t.t_threads[num_thr],
582 sizeof(kmp_info_t *) * num_thr, "%s_%d.t_threads", header, team_id);
583
584 __kmp_print_storage_map_gtid(-1, &team->t.t_disp_buffer[0],
585 &team->t.t_disp_buffer[num_disp_buff],
586 sizeof(dispatch_shared_info_t) * num_disp_buff,
587 "%s_%d.t_disp_buffer", header, team_id);
588}
589
590static void __kmp_init_allocator() {
591 __kmp_init_memkind();
592 __kmp_init_target_mem();
593}
594static void __kmp_fini_allocator() {
595 __kmp_fini_target_mem();
596 __kmp_fini_memkind();
597}
598
599/* ------------------------------------------------------------------------ */
600
601#if ENABLE_LIBOMPTARGET
602static void __kmp_init_omptarget() {
603 __kmp_init_target_task();
604}
605#endif
606
607/* ------------------------------------------------------------------------ */
608
609#if KMP_DYNAMIC_LIB
610#if KMP_OS_WINDOWS
611
612BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) {
613 //__kmp_acquire_bootstrap_lock( &__kmp_initz_lock );
614
615 switch (fdwReason) {
616
617 case DLL_PROCESS_ATTACH:
618 KA_TRACE(10, ("DllMain: PROCESS_ATTACH\n"));
619
620 return TRUE;
621
622 case DLL_PROCESS_DETACH:
623 KA_TRACE(10, ("DllMain: PROCESS_DETACH T#%d\n", __kmp_gtid_get_specific()));
624
625 // According to Windows* documentation for DllMain entry point:
626 // for DLL_PROCESS_DETACH, lpReserved is used for telling the difference:
627 // lpReserved == NULL when FreeLibrary() is called,
628 // lpReserved != NULL when the process is terminated.
629 // When FreeLibrary() is called, worker threads remain alive. So the
630 // runtime's state is consistent and executing proper shutdown is OK.
631 // When the process is terminated, worker threads have exited or been
632 // forcefully terminated by the OS and only the shutdown thread remains.
633 // This can leave the runtime in an inconsistent state.
634 // Hence, only attempt proper cleanup when FreeLibrary() is called.
635 // Otherwise, rely on OS to reclaim resources.
636 if (lpReserved == NULL)
637 __kmp_internal_end_library(__kmp_gtid_get_specific());
638
639 return TRUE;
640
641 case DLL_THREAD_ATTACH:
642 KA_TRACE(10, ("DllMain: THREAD_ATTACH\n"));
643
644 /* if we want to register new siblings all the time here call
645 * __kmp_get_gtid(); */
646 return TRUE;
647
648 case DLL_THREAD_DETACH:
649 KA_TRACE(10, ("DllMain: THREAD_DETACH T#%d\n", __kmp_gtid_get_specific()));
650
651 __kmp_internal_end_thread(__kmp_gtid_get_specific());
652 return TRUE;
653 }
654
655 return TRUE;
656}
657
658#endif /* KMP_OS_WINDOWS */
659#endif /* KMP_DYNAMIC_LIB */
660
661/* __kmp_parallel_deo -- Wait until it's our turn. */
662void __kmp_parallel_deo(int *gtid_ref, int *cid_ref, ident_t *loc_ref) {
663 int gtid = *gtid_ref;
664#ifdef BUILD_PARALLEL_ORDERED
665 kmp_team_t *team = __kmp_team_from_gtid(gtid);
666#endif /* BUILD_PARALLEL_ORDERED */
667
668 if (__kmp_env_consistency_check) {
669 if (__kmp_threads[gtid]->th.th_root->r.r_active)
670#if KMP_USE_DYNAMIC_LOCK
671 __kmp_push_sync(gtid, ct_ordered_in_parallel, loc_ref, NULL, 0);
672#else
673 __kmp_push_sync(gtid, ct_ordered_in_parallel, loc_ref, NULL);
674#endif
675 }
676#ifdef BUILD_PARALLEL_ORDERED
677 if (!team->t.t_serialized) {
678 KMP_MB();
679 KMP_WAIT(&team->t.t_ordered.dt.t_value, __kmp_tid_from_gtid(gtid), KMP_EQ,
680 NULL);
681 KMP_MB();
682 }
683#endif /* BUILD_PARALLEL_ORDERED */
684}
685
686/* __kmp_parallel_dxo -- Signal the next task. */
687void __kmp_parallel_dxo(int *gtid_ref, int *cid_ref, ident_t *loc_ref) {
688 int gtid = *gtid_ref;
689#ifdef BUILD_PARALLEL_ORDERED
690 int tid = __kmp_tid_from_gtid(gtid);
691 kmp_team_t *team = __kmp_team_from_gtid(gtid);
692#endif /* BUILD_PARALLEL_ORDERED */
693
694 if (__kmp_env_consistency_check) {
695 if (__kmp_threads[gtid]->th.th_root->r.r_active)
696 __kmp_pop_sync(gtid, ct_ordered_in_parallel, loc_ref);
697 }
698#ifdef BUILD_PARALLEL_ORDERED
699 if (!team->t.t_serialized) {
700 KMP_MB(); /* Flush all pending memory write invalidates. */
701
702 /* use the tid of the next thread in this team */
703 /* TODO replace with general release procedure */
704 team->t.t_ordered.dt.t_value = ((tid + 1) % team->t.t_nproc);
705
706 KMP_MB(); /* Flush all pending memory write invalidates. */
707 }
708#endif /* BUILD_PARALLEL_ORDERED */
709}
710
711/* ------------------------------------------------------------------------ */
712/* The BARRIER for a SINGLE process section is always explicit */
713
714int __kmp_enter_single(int gtid, ident_t *id_ref, int push_ws) {
715 int status;
716 kmp_info_t *th;
717 kmp_team_t *team;
718
719 if (!TCR_4(__kmp_init_parallel))
720 __kmp_parallel_initialize();
721 __kmp_resume_if_soft_paused();
722
723 th = __kmp_threads[gtid];
724 team = th->th.th_team;
725 status = 0;
726
727 th->th.th_ident = id_ref;
728
729 if (team->t.t_serialized) {
730 status = 1;
731 } else {
732 kmp_int32 old_this = th->th.th_local.this_construct;
733
734 ++th->th.th_local.this_construct;
735 /* try to set team count to thread count--success means thread got the
736 single block */
737 /* TODO: Should this be acquire or release? */
738 if (team->t.t_construct == old_this) {
739 status = __kmp_atomic_compare_store_acq(&team->t.t_construct, old_this,
740 th->th.th_local.this_construct);
741 }
742#if USE_ITT_BUILD
743 if (__itt_metadata_add_ptr && __kmp_forkjoin_frames_mode == 3 &&
744 KMP_MASTER_GTID(gtid) && th->th.th_teams_microtask == NULL &&
745 team->t.t_active_level == 1) {
746 // Only report metadata by primary thread of active team at level 1
747 __kmp_itt_metadata_single(id_ref);
748 }
749#endif /* USE_ITT_BUILD */
750 }
751
752 if (__kmp_env_consistency_check) {
753 if (status && push_ws) {
754 __kmp_push_workshare(gtid, ct_psingle, id_ref);
755 } else {
756 __kmp_check_workshare(gtid, ct_psingle, id_ref);
757 }
758 }
759#if USE_ITT_BUILD
760 if (status) {
761 __kmp_itt_single_start(gtid);
762 }
763#endif /* USE_ITT_BUILD */
764 return status;
765}
766
767void __kmp_exit_single(int gtid) {
768#if USE_ITT_BUILD
769 __kmp_itt_single_end(gtid);
770#endif /* USE_ITT_BUILD */
771 if (__kmp_env_consistency_check)
772 __kmp_pop_workshare(gtid, ct_psingle, NULL);
773}
774
775/* determine if we can go parallel or must use a serialized parallel region and
776 * how many threads we can use
777 * set_nproc is the number of threads requested for the team
778 * returns 0 if we should serialize or only use one thread,
779 * otherwise the number of threads to use
780 * The forkjoin lock is held by the caller. */
781static int __kmp_reserve_threads(kmp_root_t *root, kmp_team_t *parent_team,
782 int master_tid, int set_nthreads,
783 int enter_teams) {
784 int capacity;
785 int new_nthreads;
786 KMP_DEBUG_ASSERT(__kmp_init_serial);
787 KMP_DEBUG_ASSERT(root && parent_team);
788 kmp_info_t *this_thr = parent_team->t.t_threads[master_tid];
789
790 // If dyn-var is set, dynamically adjust the number of desired threads,
791 // according to the method specified by dynamic_mode.
792 new_nthreads = set_nthreads;
793 if (!get__dynamic_2(parent_team, master_tid)) {
794 ;
795 }
796#ifdef USE_LOAD_BALANCE
797 else if (__kmp_global.g.g_dynamic_mode == dynamic_load_balance) {
798 new_nthreads = __kmp_load_balance_nproc(root, set_nthreads);
799 if (new_nthreads == 1) {
800 KC_TRACE(10, ("__kmp_reserve_threads: T#%d load balance reduced "
801 "reservation to 1 thread\n",
802 master_tid));
803 return 1;
804 }
805 if (new_nthreads < set_nthreads) {
806 KC_TRACE(10, ("__kmp_reserve_threads: T#%d load balance reduced "
807 "reservation to %d threads\n",
808 master_tid, new_nthreads));
809 }
810 }
811#endif /* USE_LOAD_BALANCE */
812 else if (__kmp_global.g.g_dynamic_mode == dynamic_thread_limit) {
813 new_nthreads = __kmp_avail_proc - __kmp_nth +
814 (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc);
815 if (new_nthreads <= 1) {
816 KC_TRACE(10, ("__kmp_reserve_threads: T#%d thread limit reduced "
817 "reservation to 1 thread\n",
818 master_tid));
819 return 1;
820 }
821 if (new_nthreads < set_nthreads) {
822 KC_TRACE(10, ("__kmp_reserve_threads: T#%d thread limit reduced "
823 "reservation to %d threads\n",
824 master_tid, new_nthreads));
825 } else {
826 new_nthreads = set_nthreads;
827 }
828 } else if (__kmp_global.g.g_dynamic_mode == dynamic_random) {
829 if (set_nthreads > 2) {
830 new_nthreads = __kmp_get_random(parent_team->t.t_threads[master_tid]);
831 new_nthreads = (new_nthreads % set_nthreads) + 1;
832 if (new_nthreads == 1) {
833 KC_TRACE(10, ("__kmp_reserve_threads: T#%d dynamic random reduced "
834 "reservation to 1 thread\n",
835 master_tid));
836 return 1;
837 }
838 if (new_nthreads < set_nthreads) {
839 KC_TRACE(10, ("__kmp_reserve_threads: T#%d dynamic random reduced "
840 "reservation to %d threads\n",
841 master_tid, new_nthreads));
842 }
843 }
844 } else {
845 KMP_ASSERT(0);
846 }
847
848 // Respect KMP_ALL_THREADS/KMP_DEVICE_THREAD_LIMIT.
849 if (__kmp_nth + new_nthreads -
850 (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc) >
851 __kmp_max_nth) {
852 int tl_nthreads = __kmp_max_nth - __kmp_nth +
853 (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc);
854 if (tl_nthreads <= 0) {
855 tl_nthreads = 1;
856 }
857
858 // If dyn-var is false, emit a 1-time warning.
859 if (!get__dynamic_2(parent_team, master_tid) && (!__kmp_reserve_warn)) {
860 __kmp_reserve_warn = 1;
861 __kmp_msg(kmp_ms_warning,
862 KMP_MSG(CantFormThrTeam, set_nthreads, tl_nthreads),
863 KMP_HNT(Unset_ALL_THREADS), __kmp_msg_null);
864 }
865 if (tl_nthreads == 1) {
866 KC_TRACE(10, ("__kmp_reserve_threads: T#%d KMP_DEVICE_THREAD_LIMIT "
867 "reduced reservation to 1 thread\n",
868 master_tid));
869 return 1;
870 }
871 KC_TRACE(10, ("__kmp_reserve_threads: T#%d KMP_DEVICE_THREAD_LIMIT reduced "
872 "reservation to %d threads\n",
873 master_tid, tl_nthreads));
874 new_nthreads = tl_nthreads;
875 }
876
877 // Respect OMP_THREAD_LIMIT
878 int cg_nthreads = this_thr->th.th_cg_roots->cg_nthreads;
879 int max_cg_threads = this_thr->th.th_cg_roots->cg_thread_limit;
880 if (cg_nthreads + new_nthreads -
881 (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc) >
882 max_cg_threads) {
883 int tl_nthreads = max_cg_threads - cg_nthreads +
884 (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc);
885 if (tl_nthreads <= 0) {
886 tl_nthreads = 1;
887 }
888
889 // If dyn-var is false, emit a 1-time warning.
890 if (!get__dynamic_2(parent_team, master_tid) && (!__kmp_reserve_warn)) {
891 __kmp_reserve_warn = 1;
892 __kmp_msg(kmp_ms_warning,
893 KMP_MSG(CantFormThrTeam, set_nthreads, tl_nthreads),
894 KMP_HNT(Unset_ALL_THREADS), __kmp_msg_null);
895 }
896 if (tl_nthreads == 1) {
897 KC_TRACE(10, ("__kmp_reserve_threads: T#%d OMP_THREAD_LIMIT "
898 "reduced reservation to 1 thread\n",
899 master_tid));
900 return 1;
901 }
902 KC_TRACE(10, ("__kmp_reserve_threads: T#%d OMP_THREAD_LIMIT reduced "
903 "reservation to %d threads\n",
904 master_tid, tl_nthreads));
905 new_nthreads = tl_nthreads;
906 }
907
908 // Check if the threads array is large enough, or needs expanding.
909 // See comment in __kmp_register_root() about the adjustment if
910 // __kmp_threads[0] == NULL.
911 capacity = __kmp_threads_capacity;
912 if (TCR_PTR(__kmp_threads[0]) == NULL) {
913 --capacity;
914 }
915 // If it is not for initializing the hidden helper team, we need to take
916 // __kmp_hidden_helper_threads_num out of the capacity because it is included
917 // in __kmp_threads_capacity.
918 if (__kmp_enable_hidden_helper && !TCR_4(__kmp_init_hidden_helper_threads)) {
919 capacity -= __kmp_hidden_helper_threads_num;
920 }
921 if (__kmp_nth + new_nthreads -
922 (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc) >
923 capacity) {
924 // Expand the threads array.
925 int slotsRequired = __kmp_nth + new_nthreads -
926 (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc) -
927 capacity;
928 int slotsAdded = __kmp_expand_threads(slotsRequired);
929 if (slotsAdded < slotsRequired) {
930 // The threads array was not expanded enough.
931 new_nthreads -= (slotsRequired - slotsAdded);
932 KMP_ASSERT(new_nthreads >= 1);
933
934 // If dyn-var is false, emit a 1-time warning.
935 if (!get__dynamic_2(parent_team, master_tid) && (!__kmp_reserve_warn)) {
936 __kmp_reserve_warn = 1;
937 if (__kmp_tp_cached) {
938 __kmp_msg(kmp_ms_warning,
939 KMP_MSG(CantFormThrTeam, set_nthreads, new_nthreads),
940 KMP_HNT(Set_ALL_THREADPRIVATE, __kmp_tp_capacity),
941 KMP_HNT(PossibleSystemLimitOnThreads), __kmp_msg_null);
942 } else {
943 __kmp_msg(kmp_ms_warning,
944 KMP_MSG(CantFormThrTeam, set_nthreads, new_nthreads),
945 KMP_HNT(SystemLimitOnThreads), __kmp_msg_null);
946 }
947 }
948 }
949 }
950
951#ifdef KMP_DEBUG
952 if (new_nthreads == 1) {
953 KC_TRACE(10,
954 ("__kmp_reserve_threads: T#%d serializing team after reclaiming "
955 "dead roots and rechecking; requested %d threads\n",
956 __kmp_get_gtid(), set_nthreads));
957 } else {
958 KC_TRACE(10, ("__kmp_reserve_threads: T#%d allocating %d threads; requested"
959 " %d threads\n",
960 __kmp_get_gtid(), new_nthreads, set_nthreads));
961 }
962#endif // KMP_DEBUG
963
964 if (this_thr->th.th_nt_strict && new_nthreads < set_nthreads) {
965 __kmpc_error(this_thr->th.th_nt_loc, this_thr->th.th_nt_sev,
966 this_thr->th.th_nt_msg);
967 }
968 return new_nthreads;
969}
970
971/* Allocate threads from the thread pool and assign them to the new team. We are
972 assured that there are enough threads available, because we checked on that
973 earlier within critical section forkjoin */
974static void __kmp_fork_team_threads(kmp_root_t *root, kmp_team_t *team,
975 kmp_info_t *master_th, int master_gtid,
976 int fork_teams_workers) {
977 int i;
978 int use_hot_team;
979
980 KA_TRACE(10, ("__kmp_fork_team_threads: new_nprocs = %d\n", team->t.t_nproc));
981 KMP_DEBUG_ASSERT(master_gtid == __kmp_get_gtid());
982 KMP_MB();
983
984 /* first, let's setup the primary thread */
985 master_th->th.th_info.ds.ds_tid = 0;
986 master_th->th.th_team = team;
987 master_th->th.th_team_nproc = team->t.t_nproc;
988 master_th->th.th_team_master = master_th;
989 master_th->th.th_team_serialized = FALSE;
990 master_th->th.th_dispatch = &team->t.t_dispatch[0];
991
992 /* make sure we are not the optimized hot team */
993 use_hot_team = 0;
994 kmp_hot_team_ptr_t *hot_teams = master_th->th.th_hot_teams;
995 if (hot_teams) { // hot teams array is not allocated if
996 // KMP_HOT_TEAMS_MAX_LEVEL=0
997 int level = team->t.t_active_level - 1; // index in array of hot teams
998 if (master_th->th.th_teams_microtask) { // are we inside the teams?
999 if (master_th->th.th_teams_size.nteams > 1) {
1000 ++level; // level was not increased in teams construct for
1001 // team_of_masters
1002 }
1003 if (team->t.t_pkfn != (microtask_t)__kmp_teams_master &&
1004 master_th->th.th_teams_level == team->t.t_level) {
1005 ++level; // level was not increased in teams construct for
1006 // team_of_workers before the parallel
1007 } // team->t.t_level will be increased inside parallel
1008 }
1009 if (level < __kmp_hot_teams_max_level) {
1010 if (hot_teams[level].hot_team) {
1011 // hot team has already been allocated for given level
1012 KMP_DEBUG_ASSERT(hot_teams[level].hot_team == team);
1013 use_hot_team = 1; // the team is ready to use
1014 } else {
1015 use_hot_team = 0; // AC: threads are not allocated yet
1016 hot_teams[level].hot_team = team; // remember new hot team
1017 hot_teams[level].hot_team_nth = team->t.t_nproc;
1018 }
1019 } else {
1020 use_hot_team = 0;
1021 }
1022 }
1023 if (!use_hot_team) {
1024
1025 /* install the primary thread */
1026 team->t.t_threads[0] = master_th;
1027 __kmp_initialize_info(master_th, team, 0, master_gtid);
1028
1029 /* now, install the worker threads */
1030 for (i = 1; i < team->t.t_nproc; i++) {
1031
1032 /* fork or reallocate a new thread and install it in team */
1033 kmp_info_t *thr = __kmp_allocate_thread(root, team, i);
1034 team->t.t_threads[i] = thr;
1035 KMP_DEBUG_ASSERT(thr);
1036 KMP_DEBUG_ASSERT(thr->th.th_team == team);
1037 /* align team and thread arrived states */
1038 KA_TRACE(20, ("__kmp_fork_team_threads: T#%d(%d:%d) init arrived "
1039 "T#%d(%d:%d) join =%llu, plain=%llu\n",
1040 __kmp_gtid_from_tid(0, team), team->t.t_id, 0,
1041 __kmp_gtid_from_tid(i, team), team->t.t_id, i,
1042 team->t.t_bar[bs_forkjoin_barrier].b_arrived,
1043 team->t.t_bar[bs_plain_barrier].b_arrived));
1044 thr->th.th_teams_microtask = master_th->th.th_teams_microtask;
1045 thr->th.th_teams_level = master_th->th.th_teams_level;
1046 thr->th.th_teams_size = master_th->th.th_teams_size;
1047 { // Initialize threads' barrier data.
1048 int b;
1049 kmp_balign_t *balign = team->t.t_threads[i]->th.th_bar;
1050 for (b = 0; b < bs_last_barrier; ++b) {
1051 balign[b].bb.b_arrived = team->t.t_bar[b].b_arrived;
1052 KMP_DEBUG_ASSERT(balign[b].bb.wait_flag != KMP_BARRIER_PARENT_FLAG);
1053#if USE_DEBUGGER
1054 balign[b].bb.b_worker_arrived = team->t.t_bar[b].b_team_arrived;
1055#endif
1056 }
1057 }
1058 }
1059
1060#if KMP_AFFINITY_SUPPORTED
1061 // Do not partition the places list for teams construct workers who
1062 // haven't actually been forked to do real work yet. This partitioning
1063 // will take place in the parallel region nested within the teams construct.
1064 if (!fork_teams_workers) {
1065 __kmp_partition_places(team);
1066 }
1067#endif
1068
1069 if (team->t.t_nproc > 1 &&
1070 __kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
1071 team->t.b->update_num_threads(team->t.t_nproc);
1072 __kmp_add_threads_to_team(team, team->t.t_nproc);
1073 }
1074 }
1075
1076 // Take care of primary thread's task state
1077 if (__kmp_tasking_mode != tskm_immediate_exec) {
1078 if (use_hot_team) {
1079 KMP_DEBUG_ASSERT_TASKTEAM_INVARIANT(team->t.t_parent, master_th);
1080 KA_TRACE(
1081 20,
1082 ("__kmp_fork_team_threads: Primary T#%d pushing task_team %p / team "
1083 "%p, new task_team %p / team %p\n",
1084 __kmp_gtid_from_thread(master_th), master_th->th.th_task_team,
1085 team->t.t_parent, team->t.t_task_team[master_th->th.th_task_state],
1086 team));
1087
1088 // Store primary thread's current task state on new team
1089 KMP_CHECK_UPDATE(team->t.t_primary_task_state,
1090 master_th->th.th_task_state);
1091
1092 // Restore primary thread's task state to hot team's state
1093 // by using thread 1's task state
1094 if (team->t.t_nproc > 1) {
1095 KMP_DEBUG_ASSERT(team->t.t_threads[1]->th.th_task_state == 0 ||
1096 team->t.t_threads[1]->th.th_task_state == 1);
1097 KMP_CHECK_UPDATE(master_th->th.th_task_state,
1098 team->t.t_threads[1]->th.th_task_state);
1099 } else {
1100 master_th->th.th_task_state = 0;
1101 }
1102 } else {
1103 // Store primary thread's current task_state on new team
1104 KMP_CHECK_UPDATE(team->t.t_primary_task_state,
1105 master_th->th.th_task_state);
1106 // Are not using hot team, so set task state to 0.
1107 master_th->th.th_task_state = 0;
1108 }
1109 }
1110
1111 if (__kmp_display_affinity && team->t.t_display_affinity != 1) {
1112 for (i = 0; i < team->t.t_nproc; i++) {
1113 kmp_info_t *thr = team->t.t_threads[i];
1114 if (thr->th.th_prev_num_threads != team->t.t_nproc ||
1115 thr->th.th_prev_level != team->t.t_level) {
1116 team->t.t_display_affinity = 1;
1117 break;
1118 }
1119 }
1120 }
1121
1122 KMP_MB();
1123}
1124
1125#if KMP_ARCH_X86 || KMP_ARCH_X86_64
1126// Propagate any changes to the floating point control registers out to the team
1127// We try to avoid unnecessary writes to the relevant cache line in the team
1128// structure, so we don't make changes unless they are needed.
1129inline static void propagateFPControl(kmp_team_t *team) {
1130 if (__kmp_inherit_fp_control) {
1131 kmp_int16 x87_fpu_control_word;
1132 kmp_uint32 mxcsr;
1133
1134 // Get primary thread's values of FPU control flags (both X87 and vector)
1135 __kmp_store_x87_fpu_control_word(&x87_fpu_control_word);
1136 __kmp_store_mxcsr(&mxcsr);
1137 mxcsr &= KMP_X86_MXCSR_MASK;
1138
1139 // There is no point looking at t_fp_control_saved here.
1140 // If it is TRUE, we still have to update the values if they are different
1141 // from those we now have. If it is FALSE we didn't save anything yet, but
1142 // our objective is the same. We have to ensure that the values in the team
1143 // are the same as those we have.
1144 // So, this code achieves what we need whether or not t_fp_control_saved is
1145 // true. By checking whether the value needs updating we avoid unnecessary
1146 // writes that would put the cache-line into a written state, causing all
1147 // threads in the team to have to read it again.
1148 KMP_CHECK_UPDATE(team->t.t_x87_fpu_control_word, x87_fpu_control_word);
1149 KMP_CHECK_UPDATE(team->t.t_mxcsr, mxcsr);
1150 // Although we don't use this value, other code in the runtime wants to know
1151 // whether it should restore them. So we must ensure it is correct.
1152 KMP_CHECK_UPDATE(team->t.t_fp_control_saved, TRUE);
1153 } else {
1154 // Similarly here. Don't write to this cache-line in the team structure
1155 // unless we have to.
1156 KMP_CHECK_UPDATE(team->t.t_fp_control_saved, FALSE);
1157 }
1158}
1159
1160// Do the opposite, setting the hardware registers to the updated values from
1161// the team.
1162inline static void updateHWFPControl(kmp_team_t *team) {
1163 if (__kmp_inherit_fp_control && team->t.t_fp_control_saved) {
1164 // Only reset the fp control regs if they have been changed in the team.
1165 // the parallel region that we are exiting.
1166 kmp_int16 x87_fpu_control_word;
1167 kmp_uint32 mxcsr;
1168 __kmp_store_x87_fpu_control_word(&x87_fpu_control_word);
1169 __kmp_store_mxcsr(&mxcsr);
1170 mxcsr &= KMP_X86_MXCSR_MASK;
1171
1172 if (team->t.t_x87_fpu_control_word != x87_fpu_control_word) {
1173 __kmp_clear_x87_fpu_status_word();
1174 __kmp_load_x87_fpu_control_word(&team->t.t_x87_fpu_control_word);
1175 }
1176
1177 if (team->t.t_mxcsr != mxcsr) {
1178 __kmp_load_mxcsr(&team->t.t_mxcsr);
1179 }
1180 }
1181}
1182#else
1183#define propagateFPControl(x) ((void)0)
1184#define updateHWFPControl(x) ((void)0)
1185#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
1186
1187static void __kmp_alloc_argv_entries(int argc, kmp_team_t *team,
1188 int realloc); // forward declaration
1189
1190/* Run a parallel region that has been serialized, so runs only in a team of the
1191 single primary thread. */
1192void __kmp_serialized_parallel(ident_t *loc, kmp_int32 global_tid) {
1193 kmp_info_t *this_thr;
1194 kmp_team_t *serial_team;
1195
1196 KC_TRACE(10, ("__kmpc_serialized_parallel: called by T#%d\n", global_tid));
1197
1198 /* Skip all this code for autopar serialized loops since it results in
1199 unacceptable overhead */
1200 if (loc != NULL && (loc->flags & KMP_IDENT_AUTOPAR))
1201 return;
1202
1203 if (!TCR_4(__kmp_init_parallel))
1204 __kmp_parallel_initialize();
1205 __kmp_resume_if_soft_paused();
1206
1207 this_thr = __kmp_threads[global_tid];
1208 serial_team = this_thr->th.th_serial_team;
1209
1210 /* utilize the serialized team held by this thread */
1211 KMP_DEBUG_ASSERT(serial_team);
1212 KMP_MB();
1213
1214 kmp_proc_bind_t proc_bind = this_thr->th.th_set_proc_bind;
1215 if (this_thr->th.th_current_task->td_icvs.proc_bind == proc_bind_false) {
1216 proc_bind = proc_bind_false;
1217 } else if (proc_bind == proc_bind_default) {
1218 // No proc_bind clause was specified, so use the current value
1219 // of proc-bind-var for this parallel region.
1220 proc_bind = this_thr->th.th_current_task->td_icvs.proc_bind;
1221 }
1222 // Reset for next parallel region
1223 this_thr->th.th_set_proc_bind = proc_bind_default;
1224
1225 // OpenMP 6.0 12.1.2 requires the num_threads 'strict' modifier to also have
1226 // effect when parallel execution is disabled by a corresponding if clause
1227 // attached to the parallel directive.
1228 if (this_thr->th.th_nt_strict && this_thr->th.th_set_nproc > 1)
1229 __kmpc_error(this_thr->th.th_nt_loc, this_thr->th.th_nt_sev,
1230 this_thr->th.th_nt_msg);
1231 // Reset num_threads for next parallel region
1232 this_thr->th.th_set_nproc = 0;
1233
1234#if OMPT_SUPPORT
1235 ompt_data_t ompt_parallel_data = ompt_data_none;
1236 void *codeptr = OMPT_LOAD_RETURN_ADDRESS(global_tid);
1237 if (ompt_enabled.enabled &&
1238 this_thr->th.ompt_thread_info.state != ompt_state_overhead) {
1239
1240 ompt_task_info_t *parent_task_info;
1241 parent_task_info = OMPT_CUR_TASK_INFO(this_thr);
1242
1243 parent_task_info->frame.enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
1244 if (ompt_enabled.ompt_callback_parallel_begin) {
1245 int team_size = 1;
1246
1247 ompt_callbacks.ompt_callback(ompt_callback_parallel_begin)(
1248 &(parent_task_info->task_data), &(parent_task_info->frame),
1249 &ompt_parallel_data, team_size,
1250 ompt_parallel_invoker_program | ompt_parallel_team, codeptr);
1251 }
1252 }
1253#endif // OMPT_SUPPORT
1254
1255 if (this_thr->th.th_team != serial_team) {
1256 // Nested level will be an index in the nested nthreads array
1257 int level = this_thr->th.th_team->t.t_level;
1258
1259 if (serial_team->t.t_serialized) {
1260 /* this serial team was already used
1261 TODO increase performance by making this locks more specific */
1262 kmp_team_t *new_team;
1263
1264 __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
1265
1266 new_team = __kmp_allocate_team(
1267 this_thr->th.th_root, 1, 1,
1268#if OMPT_SUPPORT
1269 ompt_parallel_data,
1270#endif
1271 proc_bind, &this_thr->th.th_current_task->td_icvs, 0, NULL);
1272 __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
1273 KMP_ASSERT(new_team);
1274
1275 /* setup new serialized team and install it */
1276 new_team->t.t_threads[0] = this_thr;
1277 new_team->t.t_parent = this_thr->th.th_team;
1278 serial_team = new_team;
1279 this_thr->th.th_serial_team = serial_team;
1280
1281 KF_TRACE(
1282 10,
1283 ("__kmpc_serialized_parallel: T#%d allocated new serial team %p\n",
1284 global_tid, serial_team));
1285
1286 /* TODO the above breaks the requirement that if we run out of resources,
1287 then we can still guarantee that serialized teams are ok, since we may
1288 need to allocate a new one */
1289 } else {
1290 KF_TRACE(
1291 10,
1292 ("__kmpc_serialized_parallel: T#%d reusing cached serial team %p\n",
1293 global_tid, serial_team));
1294 }
1295
1296 /* we have to initialize this serial team */
1297 KMP_DEBUG_ASSERT(serial_team->t.t_threads);
1298 KMP_DEBUG_ASSERT(serial_team->t.t_threads[0] == this_thr);
1299 KMP_DEBUG_ASSERT(this_thr->th.th_team != serial_team);
1300 serial_team->t.t_ident = loc;
1301 serial_team->t.t_serialized = 1;
1302 serial_team->t.t_nproc = 1;
1303 serial_team->t.t_parent = this_thr->th.th_team;
1304 if (this_thr->th.th_team->t.t_nested_nth)
1305 serial_team->t.t_nested_nth = this_thr->th.th_team->t.t_nested_nth;
1306 else
1307 serial_team->t.t_nested_nth = &__kmp_nested_nth;
1308 // Save previous team's task state on serial team structure
1309 serial_team->t.t_primary_task_state = this_thr->th.th_task_state;
1310 serial_team->t.t_sched.sched = this_thr->th.th_team->t.t_sched.sched;
1311 this_thr->th.th_team = serial_team;
1312 serial_team->t.t_master_tid = this_thr->th.th_info.ds.ds_tid;
1313
1314 KF_TRACE(10, ("__kmpc_serialized_parallel: T#%d curtask=%p\n", global_tid,
1315 this_thr->th.th_current_task));
1316 KMP_ASSERT(this_thr->th.th_current_task->td_flags.executing == 1);
1317 this_thr->th.th_current_task->td_flags.executing = 0;
1318
1319 __kmp_push_current_task_to_thread(this_thr, serial_team, 0);
1320
1321 /* TODO: GEH: do ICVs work for nested serialized teams? Don't we need an
1322 implicit task for each serialized task represented by
1323 team->t.t_serialized? */
1324 copy_icvs(&this_thr->th.th_current_task->td_icvs,
1325 &this_thr->th.th_current_task->td_parent->td_icvs);
1326
1327 // Thread value exists in the nested nthreads array for the next nested
1328 // level
1329 kmp_nested_nthreads_t *nested_nth = &__kmp_nested_nth;
1330 if (this_thr->th.th_team->t.t_nested_nth)
1331 nested_nth = this_thr->th.th_team->t.t_nested_nth;
1332 if (nested_nth->used && (level + 1 < nested_nth->used)) {
1333 this_thr->th.th_current_task->td_icvs.nproc = nested_nth->nth[level + 1];
1334 }
1335
1336 if (__kmp_nested_proc_bind.used &&
1337 (level + 1 < __kmp_nested_proc_bind.used)) {
1338 this_thr->th.th_current_task->td_icvs.proc_bind =
1339 __kmp_nested_proc_bind.bind_types[level + 1];
1340 }
1341
1342#if USE_DEBUGGER
1343 serial_team->t.t_pkfn = (microtask_t)(~0); // For the debugger.
1344#endif
1345 this_thr->th.th_info.ds.ds_tid = 0;
1346
1347 /* set thread cache values */
1348 this_thr->th.th_team_nproc = 1;
1349 this_thr->th.th_team_master = this_thr;
1350 this_thr->th.th_team_serialized = 1;
1351 this_thr->th.th_task_team = NULL;
1352 this_thr->th.th_task_state = 0;
1353
1354 serial_team->t.t_level = serial_team->t.t_parent->t.t_level + 1;
1355 serial_team->t.t_active_level = serial_team->t.t_parent->t.t_active_level;
1356 serial_team->t.t_def_allocator = this_thr->th.th_def_allocator; // save
1357
1358 propagateFPControl(serial_team);
1359
1360 /* check if we need to allocate dispatch buffers stack */
1361 KMP_DEBUG_ASSERT(serial_team->t.t_dispatch);
1362 if (!serial_team->t.t_dispatch->th_disp_buffer) {
1363 serial_team->t.t_dispatch->th_disp_buffer =
1364 (dispatch_private_info_t *)__kmp_allocate(
1365 sizeof(dispatch_private_info_t));
1366 }
1367 this_thr->th.th_dispatch = serial_team->t.t_dispatch;
1368
1369 KMP_MB();
1370
1371 } else {
1372 /* this serialized team is already being used,
1373 * that's fine, just add another nested level */
1374 KMP_DEBUG_ASSERT(this_thr->th.th_team == serial_team);
1375 KMP_DEBUG_ASSERT(serial_team->t.t_threads);
1376 KMP_DEBUG_ASSERT(serial_team->t.t_threads[0] == this_thr);
1377 ++serial_team->t.t_serialized;
1378 this_thr->th.th_team_serialized = serial_team->t.t_serialized;
1379
1380 // Nested level will be an index in the nested nthreads array
1381 int level = this_thr->th.th_team->t.t_level;
1382 // Thread value exists in the nested nthreads array for the next nested
1383 // level
1384
1385 kmp_nested_nthreads_t *nested_nth = &__kmp_nested_nth;
1386 if (serial_team->t.t_nested_nth)
1387 nested_nth = serial_team->t.t_nested_nth;
1388 if (nested_nth->used && (level + 1 < nested_nth->used)) {
1389 this_thr->th.th_current_task->td_icvs.nproc = nested_nth->nth[level + 1];
1390 }
1391
1392 serial_team->t.t_level++;
1393 KF_TRACE(10, ("__kmpc_serialized_parallel: T#%d increasing nesting level "
1394 "of serial team %p to %d\n",
1395 global_tid, serial_team, serial_team->t.t_level));
1396
1397 /* allocate/push dispatch buffers stack */
1398 KMP_DEBUG_ASSERT(serial_team->t.t_dispatch);
1399 {
1400 dispatch_private_info_t *disp_buffer =
1401 (dispatch_private_info_t *)__kmp_allocate(
1402 sizeof(dispatch_private_info_t));
1403 disp_buffer->next = serial_team->t.t_dispatch->th_disp_buffer;
1404 serial_team->t.t_dispatch->th_disp_buffer = disp_buffer;
1405 }
1406 this_thr->th.th_dispatch = serial_team->t.t_dispatch;
1407
1408 /* allocate/push task team stack */
1409 __kmp_push_task_team_node(this_thr, serial_team);
1410
1411 KMP_MB();
1412 }
1413 KMP_CHECK_UPDATE(serial_team->t.t_cancel_request, cancel_noreq);
1414
1415 // Perform the display affinity functionality for
1416 // serialized parallel regions
1417 if (__kmp_display_affinity) {
1418 if (this_thr->th.th_prev_level != serial_team->t.t_level ||
1419 this_thr->th.th_prev_num_threads != 1) {
1420 // NULL means use the affinity-format-var ICV
1421 __kmp_aux_display_affinity(global_tid, NULL);
1422 this_thr->th.th_prev_level = serial_team->t.t_level;
1423 this_thr->th.th_prev_num_threads = 1;
1424 }
1425 }
1426
1427 if (__kmp_env_consistency_check)
1428 __kmp_push_parallel(global_tid, NULL);
1429#if OMPT_SUPPORT
1430 serial_team->t.ompt_team_info.master_return_address = codeptr;
1431 if (ompt_enabled.enabled &&
1432 this_thr->th.ompt_thread_info.state != ompt_state_overhead) {
1433 OMPT_CUR_TASK_INFO(this_thr)->frame.exit_frame.ptr =
1434 OMPT_GET_FRAME_ADDRESS(0);
1435
1436 ompt_lw_taskteam_t lw_taskteam;
1437 __ompt_lw_taskteam_init(&lw_taskteam, this_thr, global_tid,
1438 &ompt_parallel_data, codeptr);
1439
1440 __ompt_lw_taskteam_link(&lw_taskteam, this_thr, 1);
1441 // don't use lw_taskteam after linking. content was swaped
1442
1443 /* OMPT implicit task begin */
1444 if (ompt_enabled.ompt_callback_implicit_task) {
1445 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1446 ompt_scope_begin, OMPT_CUR_TEAM_DATA(this_thr),
1447 OMPT_CUR_TASK_DATA(this_thr), 1, __kmp_tid_from_gtid(global_tid),
1448 ompt_task_implicit); // TODO: Can this be ompt_task_initial?
1449 OMPT_CUR_TASK_INFO(this_thr)->thread_num =
1450 __kmp_tid_from_gtid(global_tid);
1451 }
1452
1453 /* OMPT state */
1454 this_thr->th.ompt_thread_info.state = ompt_state_work_parallel;
1455 OMPT_CUR_TASK_INFO(this_thr)->frame.exit_frame.ptr =
1456 OMPT_GET_FRAME_ADDRESS(0);
1457 }
1458#endif
1459}
1460
1461// Test if this fork is for a team closely nested in a teams construct
1462static inline bool __kmp_is_fork_in_teams(kmp_info_t *master_th,
1463 microtask_t microtask, int level,
1464 int teams_level, kmp_va_list ap) {
1465 return (master_th->th.th_teams_microtask && ap &&
1466 microtask != (microtask_t)__kmp_teams_master && level == teams_level);
1467}
1468
1469// Test if this fork is for the teams construct, i.e. to form the outer league
1470// of teams
1471static inline bool __kmp_is_entering_teams(int active_level, int level,
1472 int teams_level, kmp_va_list ap) {
1473 return ((ap == NULL && active_level == 0) ||
1474 (ap && teams_level > 0 && teams_level == level));
1475}
1476
1477// AC: This is start of parallel that is nested inside teams construct.
1478// The team is actual (hot), all workers are ready at the fork barrier.
1479// No lock needed to initialize the team a bit, then free workers.
1480static inline int
1481__kmp_fork_in_teams(ident_t *loc, int gtid, kmp_team_t *parent_team,
1482 kmp_int32 argc, kmp_info_t *master_th, kmp_root_t *root,
1483 enum fork_context_e call_context, microtask_t microtask,
1484 launch_t invoker, int master_set_numthreads, int level,
1485#if OMPT_SUPPORT
1486 ompt_data_t ompt_parallel_data, void *return_address,
1487#endif
1488 kmp_va_list ap) {
1489 void **argv;
1490 int i;
1491
1492 parent_team->t.t_ident = loc;
1493 __kmp_alloc_argv_entries(argc, parent_team, TRUE);
1494 parent_team->t.t_argc = argc;
1495 argv = (void **)parent_team->t.t_argv;
1496 for (i = argc - 1; i >= 0; --i) {
1497 *argv++ = va_arg(kmp_va_deref(ap), void *);
1498 }
1499 // Increment our nested depth levels, but not increase the serialization
1500 if (parent_team == master_th->th.th_serial_team) {
1501 // AC: we are in serialized parallel
1502 __kmpc_serialized_parallel(loc, gtid);
1503 KMP_DEBUG_ASSERT(parent_team->t.t_serialized > 1);
1504
1505 if (call_context == fork_context_gnu) {
1506 // AC: need to decrement t_serialized for enquiry functions to work
1507 // correctly, will restore at join time
1508 parent_team->t.t_serialized--;
1509 return TRUE;
1510 }
1511
1512#if OMPD_SUPPORT
1513 parent_team->t.t_pkfn = microtask;
1514#endif
1515
1516#if OMPT_SUPPORT
1517 void *dummy;
1518 void **exit_frame_p;
1519 ompt_data_t *implicit_task_data;
1520 ompt_lw_taskteam_t lw_taskteam;
1521
1522 if (ompt_enabled.enabled) {
1523 __ompt_lw_taskteam_init(&lw_taskteam, master_th, gtid,
1524 &ompt_parallel_data, return_address);
1525 exit_frame_p = &(lw_taskteam.ompt_task_info.frame.exit_frame.ptr);
1526
1527 __ompt_lw_taskteam_link(&lw_taskteam, master_th, 0);
1528 // Don't use lw_taskteam after linking. Content was swapped.
1529
1530 /* OMPT implicit task begin */
1531 implicit_task_data = OMPT_CUR_TASK_DATA(master_th);
1532 if (ompt_enabled.ompt_callback_implicit_task) {
1533 OMPT_CUR_TASK_INFO(master_th)->thread_num = __kmp_tid_from_gtid(gtid);
1534 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1535 ompt_scope_begin, OMPT_CUR_TEAM_DATA(master_th), implicit_task_data,
1536 1, OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_implicit);
1537 }
1538
1539 /* OMPT state */
1540 master_th->th.ompt_thread_info.state = ompt_state_work_parallel;
1541 } else {
1542 exit_frame_p = &dummy;
1543 }
1544#endif
1545
1546 // AC: need to decrement t_serialized for enquiry functions to work
1547 // correctly, will restore at join time
1548 parent_team->t.t_serialized--;
1549
1550 {
1551 KMP_TIME_PARTITIONED_BLOCK(OMP_parallel);
1552 KMP_SET_THREAD_STATE_BLOCK(IMPLICIT_TASK);
1553 __kmp_invoke_microtask(microtask, gtid, 0, argc, parent_team->t.t_argv
1554#if OMPT_SUPPORT
1555 ,
1556 exit_frame_p
1557#endif
1558 );
1559 }
1560
1561#if OMPT_SUPPORT
1562 if (ompt_enabled.enabled) {
1563 *exit_frame_p = NULL;
1564 OMPT_CUR_TASK_INFO(master_th)->frame.exit_frame = ompt_data_none;
1565 if (ompt_enabled.ompt_callback_implicit_task) {
1566 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1567 ompt_scope_end, NULL, implicit_task_data, 1,
1568 OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_implicit);
1569 }
1570 ompt_parallel_data = *OMPT_CUR_TEAM_DATA(master_th);
1571 __ompt_lw_taskteam_unlink(master_th);
1572 if (ompt_enabled.ompt_callback_parallel_end) {
1573 ompt_callbacks.ompt_callback(ompt_callback_parallel_end)(
1574 &ompt_parallel_data, OMPT_CUR_TASK_DATA(master_th),
1575 OMPT_INVOKER(call_context) | ompt_parallel_team, return_address);
1576 }
1577 master_th->th.ompt_thread_info.state = ompt_state_overhead;
1578 }
1579#endif
1580 return TRUE;
1581 }
1582
1583 parent_team->t.t_pkfn = microtask;
1584 parent_team->t.t_invoke = invoker;
1585 KMP_ATOMIC_INC(&root->r.r_in_parallel);
1586 parent_team->t.t_active_level++;
1587 parent_team->t.t_level++;
1588 parent_team->t.t_def_allocator = master_th->th.th_def_allocator; // save
1589
1590 // If the threads allocated to the team are less than the thread limit, update
1591 // the thread limit here. th_teams_size.nth is specific to this team nested
1592 // in a teams construct, the team is fully created, and we're about to do
1593 // the actual fork. Best to do this here so that the subsequent uses below
1594 // and in the join have the correct value.
1595 master_th->th.th_teams_size.nth = parent_team->t.t_nproc;
1596
1597#if OMPT_SUPPORT
1598 if (ompt_enabled.enabled) {
1599 ompt_lw_taskteam_t lw_taskteam;
1600 __ompt_lw_taskteam_init(&lw_taskteam, master_th, gtid, &ompt_parallel_data,
1601 return_address);
1602 __ompt_lw_taskteam_link(&lw_taskteam, master_th, 1, true);
1603 }
1604#endif
1605
1606 /* Change number of threads in the team if requested */
1607 if (master_set_numthreads) { // The parallel has num_threads clause
1608 if (master_set_numthreads <= master_th->th.th_teams_size.nth) {
1609 // AC: only can reduce number of threads dynamically, can't increase
1610 kmp_info_t **other_threads = parent_team->t.t_threads;
1611 // NOTE: if using distributed barrier, we need to run this code block
1612 // even when the team size appears not to have changed from the max.
1613 int old_proc = master_th->th.th_teams_size.nth;
1614 if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
1615 __kmp_resize_dist_barrier(parent_team, old_proc, master_set_numthreads);
1616 __kmp_add_threads_to_team(parent_team, master_set_numthreads);
1617 }
1618 parent_team->t.t_nproc = master_set_numthreads;
1619 for (i = 0; i < master_set_numthreads; ++i) {
1620 other_threads[i]->th.th_team_nproc = master_set_numthreads;
1621 }
1622 }
1623 // Keep extra threads hot in the team for possible next parallels
1624 master_th->th.th_set_nproc = 0;
1625 }
1626
1627#if USE_DEBUGGER
1628 if (__kmp_debugging) { // Let debugger override number of threads.
1629 int nth = __kmp_omp_num_threads(loc);
1630 if (nth > 0) { // 0 means debugger doesn't want to change num threads
1631 master_set_numthreads = nth;
1632 }
1633 }
1634#endif
1635
1636 // Figure out the proc_bind policy for the nested parallel within teams
1637 kmp_proc_bind_t proc_bind = master_th->th.th_set_proc_bind;
1638 // proc_bind_default means don't update
1639 kmp_proc_bind_t proc_bind_icv = proc_bind_default;
1640 if (master_th->th.th_current_task->td_icvs.proc_bind == proc_bind_false) {
1641 proc_bind = proc_bind_false;
1642 } else {
1643 // No proc_bind clause specified; use current proc-bind-var
1644 if (proc_bind == proc_bind_default) {
1645 proc_bind = master_th->th.th_current_task->td_icvs.proc_bind;
1646 }
1647 /* else: The proc_bind policy was specified explicitly on parallel clause.
1648 This overrides proc-bind-var for this parallel region, but does not
1649 change proc-bind-var. */
1650 // Figure the value of proc-bind-var for the child threads.
1651 if ((level + 1 < __kmp_nested_proc_bind.used) &&
1652 (__kmp_nested_proc_bind.bind_types[level + 1] !=
1653 master_th->th.th_current_task->td_icvs.proc_bind)) {
1654 proc_bind_icv = __kmp_nested_proc_bind.bind_types[level + 1];
1655 }
1656 }
1657 KMP_CHECK_UPDATE(parent_team->t.t_proc_bind, proc_bind);
1658 // Need to change the bind-var ICV to correct value for each implicit task
1659 if (proc_bind_icv != proc_bind_default &&
1660 master_th->th.th_current_task->td_icvs.proc_bind != proc_bind_icv) {
1661 kmp_info_t **other_threads = parent_team->t.t_threads;
1662 for (i = 0; i < master_th->th.th_team_nproc; ++i) {
1663 other_threads[i]->th.th_current_task->td_icvs.proc_bind = proc_bind_icv;
1664 }
1665 }
1666 // Reset for next parallel region
1667 master_th->th.th_set_proc_bind = proc_bind_default;
1668
1669#if USE_ITT_BUILD && USE_ITT_NOTIFY
1670 if (((__itt_frame_submit_v3_ptr && __itt_get_timestamp_ptr) ||
1671 KMP_ITT_DEBUG) &&
1672 __kmp_forkjoin_frames_mode == 3 &&
1673 parent_team->t.t_active_level == 1 // only report frames at level 1
1674 && master_th->th.th_teams_size.nteams == 1) {
1675 kmp_uint64 tmp_time = __itt_get_timestamp();
1676 master_th->th.th_frame_time = tmp_time;
1677 parent_team->t.t_region_time = tmp_time;
1678 }
1679 if (__itt_stack_caller_create_ptr) {
1680 KMP_DEBUG_ASSERT(parent_team->t.t_stack_id == NULL);
1681 // create new stack stitching id before entering fork barrier
1682 parent_team->t.t_stack_id = __kmp_itt_stack_caller_create();
1683 }
1684#endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */
1685#if KMP_AFFINITY_SUPPORTED
1686 __kmp_partition_places(parent_team);
1687#endif
1688
1689 KF_TRACE(10, ("__kmp_fork_in_teams: before internal fork: root=%p, team=%p, "
1690 "master_th=%p, gtid=%d\n",
1691 root, parent_team, master_th, gtid));
1692 __kmp_internal_fork(loc, gtid, parent_team);
1693 KF_TRACE(10, ("__kmp_fork_in_teams: after internal fork: root=%p, team=%p, "
1694 "master_th=%p, gtid=%d\n",
1695 root, parent_team, master_th, gtid));
1696
1697 if (call_context == fork_context_gnu)
1698 return TRUE;
1699
1700 /* Invoke microtask for PRIMARY thread */
1701 KA_TRACE(20, ("__kmp_fork_in_teams: T#%d(%d:0) invoke microtask = %p\n", gtid,
1702 parent_team->t.t_id, parent_team->t.t_pkfn));
1703
1704 if (!parent_team->t.t_invoke(gtid)) {
1705 KMP_ASSERT2(0, "cannot invoke microtask for PRIMARY thread");
1706 }
1707 KA_TRACE(20, ("__kmp_fork_in_teams: T#%d(%d:0) done microtask = %p\n", gtid,
1708 parent_team->t.t_id, parent_team->t.t_pkfn));
1709 KMP_MB(); /* Flush all pending memory write invalidates. */
1710
1711 KA_TRACE(20, ("__kmp_fork_in_teams: parallel exit T#%d\n", gtid));
1712
1713 return TRUE;
1714}
1715
1716// Create a serialized parallel region
1717static inline int
1718__kmp_serial_fork_call(ident_t *loc, int gtid, enum fork_context_e call_context,
1719 kmp_int32 argc, microtask_t microtask, launch_t invoker,
1720 kmp_info_t *master_th, kmp_team_t *parent_team,
1721#if OMPT_SUPPORT
1722 ompt_data_t *ompt_parallel_data, void **return_address,
1723 ompt_data_t **parent_task_data,
1724#endif
1725 kmp_va_list ap) {
1726 kmp_team_t *team;
1727 int i;
1728 void **argv;
1729
1730/* josh todo: hypothetical question: what do we do for OS X*? */
1731#if KMP_OS_LINUX && \
1732 (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_ARM || KMP_ARCH_AARCH64)
1733 SimpleVLA<void *> args(argc);
1734#else
1735 void **args = (void **)KMP_ALLOCA(argc * sizeof(void *));
1736#endif /* KMP_OS_LINUX && ( KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_ARM || \
1737 KMP_ARCH_AARCH64) */
1738
1739 KA_TRACE(
1740 20, ("__kmp_serial_fork_call: T#%d serializing parallel region\n", gtid));
1741
1742 __kmpc_serialized_parallel(loc, gtid);
1743
1744#if OMPD_SUPPORT
1745 master_th->th.th_serial_team->t.t_pkfn = microtask;
1746#endif
1747
1748 if (call_context == fork_context_intel) {
1749 /* TODO this sucks, use the compiler itself to pass args! :) */
1750 master_th->th.th_serial_team->t.t_ident = loc;
1751 if (!ap) {
1752 // revert change made in __kmpc_serialized_parallel()
1753 master_th->th.th_serial_team->t.t_level--;
1754// Get args from parent team for teams construct
1755
1756#if OMPT_SUPPORT
1757 void *dummy;
1758 void **exit_frame_p;
1759 ompt_task_info_t *task_info;
1760 ompt_lw_taskteam_t lw_taskteam;
1761
1762 if (ompt_enabled.enabled) {
1763 __ompt_lw_taskteam_init(&lw_taskteam, master_th, gtid,
1764 ompt_parallel_data, *return_address);
1765
1766 __ompt_lw_taskteam_link(&lw_taskteam, master_th, 0);
1767 // don't use lw_taskteam after linking. content was swaped
1768 task_info = OMPT_CUR_TASK_INFO(master_th);
1769 exit_frame_p = &(task_info->frame.exit_frame.ptr);
1770 if (ompt_enabled.ompt_callback_implicit_task) {
1771 OMPT_CUR_TASK_INFO(master_th)->thread_num = __kmp_tid_from_gtid(gtid);
1772 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1773 ompt_scope_begin, OMPT_CUR_TEAM_DATA(master_th),
1774 &(task_info->task_data), 1,
1775 OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_implicit);
1776 }
1777
1778 /* OMPT state */
1779 master_th->th.ompt_thread_info.state = ompt_state_work_parallel;
1780 } else {
1781 exit_frame_p = &dummy;
1782 }
1783#endif
1784
1785 {
1786 KMP_TIME_PARTITIONED_BLOCK(OMP_parallel);
1787 KMP_SET_THREAD_STATE_BLOCK(IMPLICIT_TASK);
1788 __kmp_invoke_microtask(microtask, gtid, 0, argc, parent_team->t.t_argv
1789#if OMPT_SUPPORT
1790 ,
1791 exit_frame_p
1792#endif
1793 );
1794 }
1795
1796#if OMPT_SUPPORT
1797 if (ompt_enabled.enabled) {
1798 *exit_frame_p = NULL;
1799 if (ompt_enabled.ompt_callback_implicit_task) {
1800 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1801 ompt_scope_end, NULL, &(task_info->task_data), 1,
1802 OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_implicit);
1803 }
1804 *ompt_parallel_data = *OMPT_CUR_TEAM_DATA(master_th);
1805 __ompt_lw_taskteam_unlink(master_th);
1806 if (ompt_enabled.ompt_callback_parallel_end) {
1807 ompt_callbacks.ompt_callback(ompt_callback_parallel_end)(
1808 ompt_parallel_data, *parent_task_data,
1809 OMPT_INVOKER(call_context) | ompt_parallel_team, *return_address);
1810 }
1811 master_th->th.ompt_thread_info.state = ompt_state_overhead;
1812 }
1813#endif
1814 } else if (microtask == (microtask_t)__kmp_teams_master) {
1815 KMP_DEBUG_ASSERT(master_th->th.th_team == master_th->th.th_serial_team);
1816 team = master_th->th.th_team;
1817 // team->t.t_pkfn = microtask;
1818 team->t.t_invoke = invoker;
1819 __kmp_alloc_argv_entries(argc, team, TRUE);
1820 team->t.t_argc = argc;
1821 argv = (void **)team->t.t_argv;
1822 for (i = argc - 1; i >= 0; --i)
1823 *argv++ = va_arg(kmp_va_deref(ap), void *);
1824 // AC: revert change made in __kmpc_serialized_parallel()
1825 // because initial code in teams should have level=0
1826 team->t.t_level--;
1827 // AC: call special invoker for outer "parallel" of teams construct
1828 invoker(gtid);
1829#if OMPT_SUPPORT
1830 if (ompt_enabled.enabled) {
1831 ompt_task_info_t *task_info = OMPT_CUR_TASK_INFO(master_th);
1832 if (ompt_enabled.ompt_callback_implicit_task) {
1833 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1834 ompt_scope_end, NULL, &(task_info->task_data), 0,
1835 OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_initial);
1836 }
1837 if (ompt_enabled.ompt_callback_parallel_end) {
1838 ompt_callbacks.ompt_callback(ompt_callback_parallel_end)(
1839 ompt_parallel_data, *parent_task_data,
1840 OMPT_INVOKER(call_context) | ompt_parallel_league,
1841 *return_address);
1842 }
1843 master_th->th.ompt_thread_info.state = ompt_state_overhead;
1844 }
1845#endif
1846 } else {
1847 argv = args;
1848 for (i = argc - 1; i >= 0; --i)
1849 *argv++ = va_arg(kmp_va_deref(ap), void *);
1850 KMP_MB();
1851
1852#if OMPT_SUPPORT
1853 void *dummy;
1854 void **exit_frame_p;
1855 ompt_task_info_t *task_info;
1856 ompt_lw_taskteam_t lw_taskteam;
1857 ompt_data_t *implicit_task_data;
1858
1859 if (ompt_enabled.enabled) {
1860 __ompt_lw_taskteam_init(&lw_taskteam, master_th, gtid,
1861 ompt_parallel_data, *return_address);
1862 __ompt_lw_taskteam_link(&lw_taskteam, master_th, 0);
1863 // don't use lw_taskteam after linking. content was swaped
1864 task_info = OMPT_CUR_TASK_INFO(master_th);
1865 exit_frame_p = &(task_info->frame.exit_frame.ptr);
1866
1867 /* OMPT implicit task begin */
1868 implicit_task_data = OMPT_CUR_TASK_DATA(master_th);
1869 if (ompt_enabled.ompt_callback_implicit_task) {
1870 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1871 ompt_scope_begin, OMPT_CUR_TEAM_DATA(master_th),
1872 implicit_task_data, 1, __kmp_tid_from_gtid(gtid),
1873 ompt_task_implicit);
1874 OMPT_CUR_TASK_INFO(master_th)->thread_num = __kmp_tid_from_gtid(gtid);
1875 }
1876
1877 /* OMPT state */
1878 master_th->th.ompt_thread_info.state = ompt_state_work_parallel;
1879 } else {
1880 exit_frame_p = &dummy;
1881 }
1882#endif
1883
1884 {
1885 KMP_TIME_PARTITIONED_BLOCK(OMP_parallel);
1886 KMP_SET_THREAD_STATE_BLOCK(IMPLICIT_TASK);
1887 __kmp_invoke_microtask(microtask, gtid, 0, argc, args
1888#if OMPT_SUPPORT
1889 ,
1890 exit_frame_p
1891#endif
1892 );
1893 }
1894
1895#if OMPT_SUPPORT
1896 if (ompt_enabled.enabled) {
1897 *exit_frame_p = NULL;
1898 if (ompt_enabled.ompt_callback_implicit_task) {
1899 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1900 ompt_scope_end, NULL, &(task_info->task_data), 1,
1901 OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_implicit);
1902 }
1903
1904 *ompt_parallel_data = *OMPT_CUR_TEAM_DATA(master_th);
1905 __ompt_lw_taskteam_unlink(master_th);
1906 if (ompt_enabled.ompt_callback_parallel_end) {
1907 ompt_callbacks.ompt_callback(ompt_callback_parallel_end)(
1908 ompt_parallel_data, *parent_task_data,
1909 OMPT_INVOKER(call_context) | ompt_parallel_team, *return_address);
1910 }
1911 master_th->th.ompt_thread_info.state = ompt_state_overhead;
1912 }
1913#endif
1914 }
1915 } else if (call_context == fork_context_gnu) {
1916#if OMPT_SUPPORT
1917 if (ompt_enabled.enabled) {
1918 ompt_lw_taskteam_t lwt;
1919 __ompt_lw_taskteam_init(&lwt, master_th, gtid, ompt_parallel_data,
1920 *return_address);
1921
1922 lwt.ompt_task_info.frame.exit_frame = ompt_data_none;
1923 __ompt_lw_taskteam_link(&lwt, master_th, 1);
1924 }
1925// don't use lw_taskteam after linking. content was swaped
1926#endif
1927
1928 // we were called from GNU native code
1929 KA_TRACE(20, ("__kmp_serial_fork_call: T#%d serial exit\n", gtid));
1930 return FALSE;
1931 } else {
1932 KMP_ASSERT2(call_context < fork_context_last,
1933 "__kmp_serial_fork_call: unknown fork_context parameter");
1934 }
1935
1936 KA_TRACE(20, ("__kmp_serial_fork_call: T#%d serial exit\n", gtid));
1937 KMP_MB();
1938 return FALSE;
1939}
1940
1941/* most of the work for a fork */
1942/* return true if we really went parallel, false if serialized */
1943int __kmp_fork_call(ident_t *loc, int gtid,
1944 enum fork_context_e call_context, // Intel, GNU, ...
1945 kmp_int32 argc, microtask_t microtask, launch_t invoker,
1946 kmp_va_list ap) {
1947 void **argv;
1948 int i;
1949 int master_tid;
1950 int master_this_cons;
1951 kmp_team_t *team;
1952 kmp_team_t *parent_team;
1953 kmp_info_t *master_th;
1954 kmp_root_t *root;
1955 int nthreads;
1956 int master_active;
1957 int master_set_numthreads;
1958 int task_thread_limit = 0;
1959 int level;
1960 int active_level;
1961 int teams_level;
1962 kmp_hot_team_ptr_t **p_hot_teams;
1963 { // KMP_TIME_BLOCK
1964 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_fork_call);
1965 KMP_COUNT_VALUE(OMP_PARALLEL_args, argc);
1966
1967 KA_TRACE(20, ("__kmp_fork_call: enter T#%d\n", gtid));
1968 if (__kmp_stkpadding > 0 && __kmp_root[gtid] != NULL) {
1969 /* Some systems prefer the stack for the root thread(s) to start with */
1970 /* some gap from the parent stack to prevent false sharing. */
1971 void *dummy = KMP_ALLOCA(__kmp_stkpadding);
1972 /* These 2 lines below are so this does not get optimized out */
1973 if (__kmp_stkpadding > KMP_MAX_STKPADDING)
1974 __kmp_stkpadding += (short)((kmp_int64)dummy);
1975 }
1976
1977 /* initialize if needed */
1978 KMP_DEBUG_ASSERT(
1979 __kmp_init_serial); // AC: potentially unsafe, not in sync with shutdown
1980 if (!TCR_4(__kmp_init_parallel))
1981 __kmp_parallel_initialize();
1982 __kmp_resume_if_soft_paused();
1983
1984 /* setup current data */
1985 // AC: potentially unsafe, not in sync with library shutdown,
1986 // __kmp_threads can be freed
1987 master_th = __kmp_threads[gtid];
1988
1989 parent_team = master_th->th.th_team;
1990 master_tid = master_th->th.th_info.ds.ds_tid;
1991 master_this_cons = master_th->th.th_local.this_construct;
1992 root = master_th->th.th_root;
1993 master_active = root->r.r_active;
1994 master_set_numthreads = master_th->th.th_set_nproc;
1995 task_thread_limit =
1996 master_th->th.th_current_task->td_icvs.task_thread_limit;
1997
1998#if OMPT_SUPPORT
1999 ompt_data_t ompt_parallel_data = ompt_data_none;
2000 ompt_data_t *parent_task_data = NULL;
2001 ompt_frame_t *ompt_frame = NULL;
2002 void *return_address = NULL;
2003
2004 if (ompt_enabled.enabled) {
2005 __ompt_get_task_info_internal(0, NULL, &parent_task_data, &ompt_frame,
2006 NULL, NULL);
2007 return_address = OMPT_LOAD_RETURN_ADDRESS(gtid);
2008 }
2009#endif
2010
2011 // Assign affinity to root thread if it hasn't happened yet
2012 __kmp_assign_root_init_mask();
2013
2014 // Nested level will be an index in the nested nthreads array
2015 level = parent_team->t.t_level;
2016 // used to launch non-serial teams even if nested is not allowed
2017 active_level = parent_team->t.t_active_level;
2018 // needed to check nesting inside the teams
2019 teams_level = master_th->th.th_teams_level;
2020 p_hot_teams = &master_th->th.th_hot_teams;
2021 if (*p_hot_teams == NULL && __kmp_hot_teams_max_level > 0) {
2022 *p_hot_teams = (kmp_hot_team_ptr_t *)__kmp_allocate(
2023 sizeof(kmp_hot_team_ptr_t) * __kmp_hot_teams_max_level);
2024 (*p_hot_teams)[0].hot_team = root->r.r_hot_team;
2025 // it is either actual or not needed (when active_level > 0)
2026 (*p_hot_teams)[0].hot_team_nth = 1;
2027 }
2028
2029#if OMPT_SUPPORT
2030 if (ompt_enabled.enabled) {
2031 if (ompt_enabled.ompt_callback_parallel_begin) {
2032 int team_size = master_set_numthreads
2033 ? master_set_numthreads
2034 : get__nproc_2(parent_team, master_tid);
2035 int flags = OMPT_INVOKER(call_context) |
2036 ((microtask == (microtask_t)__kmp_teams_master)
2037 ? ompt_parallel_league
2038 : ompt_parallel_team);
2039 ompt_callbacks.ompt_callback(ompt_callback_parallel_begin)(
2040 parent_task_data, ompt_frame, &ompt_parallel_data, team_size, flags,
2041 return_address);
2042 }
2043 master_th->th.ompt_thread_info.state = ompt_state_overhead;
2044 }
2045#endif
2046
2047 master_th->th.th_ident = loc;
2048
2049 // Parallel closely nested in teams construct:
2050 if (__kmp_is_fork_in_teams(master_th, microtask, level, teams_level, ap)) {
2051 return __kmp_fork_in_teams(loc, gtid, parent_team, argc, master_th, root,
2052 call_context, microtask, invoker,
2053 master_set_numthreads, level,
2054#if OMPT_SUPPORT
2055 ompt_parallel_data, return_address,
2056#endif
2057 ap);
2058 } // End parallel closely nested in teams construct
2059
2060 // Need this to happen before we determine the number of threads, not while
2061 // we are allocating the team
2062 //__kmp_push_current_task_to_thread(master_th, parent_team, 0);
2063
2064 KMP_DEBUG_ASSERT_TASKTEAM_INVARIANT(parent_team, master_th);
2065
2066 // Determine the number of threads
2067 int enter_teams =
2068 __kmp_is_entering_teams(active_level, level, teams_level, ap);
2069 if ((!enter_teams &&
2070 (parent_team->t.t_active_level >=
2071 master_th->th.th_current_task->td_icvs.max_active_levels)) ||
2072 (__kmp_library == library_serial)) {
2073 KC_TRACE(10, ("__kmp_fork_call: T#%d serializing team\n", gtid));
2074 nthreads = 1;
2075 } else {
2076 nthreads = master_set_numthreads
2077 ? master_set_numthreads
2078 // TODO: get nproc directly from current task
2079 : get__nproc_2(parent_team, master_tid);
2080 // Use the thread_limit set for the current target task if exists, else go
2081 // with the deduced nthreads
2082 nthreads = task_thread_limit > 0 && task_thread_limit < nthreads
2083 ? task_thread_limit
2084 : nthreads;
2085 // Check if we need to take forkjoin lock? (no need for serialized
2086 // parallel out of teams construct).
2087 if (nthreads > 1) {
2088 /* determine how many new threads we can use */
2089 __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
2090 /* AC: If we execute teams from parallel region (on host), then teams
2091 should be created but each can only have 1 thread if nesting is
2092 disabled. If teams called from serial region, then teams and their
2093 threads should be created regardless of the nesting setting. */
2094 nthreads = __kmp_reserve_threads(root, parent_team, master_tid,
2095 nthreads, enter_teams);
2096 if (nthreads == 1) {
2097 // Free lock for single thread execution here; for multi-thread
2098 // execution it will be freed later after team of threads created
2099 // and initialized
2100 __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
2101 }
2102 }
2103 }
2104 KMP_DEBUG_ASSERT(nthreads > 0);
2105
2106 // If we temporarily changed the set number of threads then restore it now
2107 master_th->th.th_set_nproc = 0;
2108
2109 if (nthreads == 1) {
2110 return __kmp_serial_fork_call(loc, gtid, call_context, argc, microtask,
2111 invoker, master_th, parent_team,
2112#if OMPT_SUPPORT
2113 &ompt_parallel_data, &return_address,
2114 &parent_task_data,
2115#endif
2116 ap);
2117 } // if (nthreads == 1)
2118
2119 // GEH: only modify the executing flag in the case when not serialized
2120 // serialized case is handled in kmpc_serialized_parallel
2121 KF_TRACE(10, ("__kmp_fork_call: parent_team_aclevel=%d, master_th=%p, "
2122 "curtask=%p, curtask_max_aclevel=%d\n",
2123 parent_team->t.t_active_level, master_th,
2124 master_th->th.th_current_task,
2125 master_th->th.th_current_task->td_icvs.max_active_levels));
2126 // TODO: GEH - cannot do this assertion because root thread not set up as
2127 // executing
2128 // KMP_ASSERT( master_th->th.th_current_task->td_flags.executing == 1 );
2129 master_th->th.th_current_task->td_flags.executing = 0;
2130
2131 if (!master_th->th.th_teams_microtask || level > teams_level) {
2132 /* Increment our nested depth level */
2133 KMP_ATOMIC_INC(&root->r.r_in_parallel);
2134 }
2135
2136 // See if we need to make a copy of the ICVs.
2137 int nthreads_icv = master_th->th.th_current_task->td_icvs.nproc;
2138 kmp_nested_nthreads_t *nested_nth = NULL;
2139 if (!master_th->th.th_set_nested_nth &&
2140 (level + 1 < parent_team->t.t_nested_nth->used) &&
2141 (parent_team->t.t_nested_nth->nth[level + 1] != nthreads_icv)) {
2142 nthreads_icv = parent_team->t.t_nested_nth->nth[level + 1];
2143 } else if (master_th->th.th_set_nested_nth) {
2144 nested_nth = __kmp_override_nested_nth(master_th, level);
2145 if ((level + 1 < nested_nth->used) &&
2146 (nested_nth->nth[level + 1] != nthreads_icv))
2147 nthreads_icv = nested_nth->nth[level + 1];
2148 else
2149 nthreads_icv = 0; // don't update
2150 } else {
2151 nthreads_icv = 0; // don't update
2152 }
2153
2154 // Figure out the proc_bind_policy for the new team.
2155 kmp_proc_bind_t proc_bind = master_th->th.th_set_proc_bind;
2156 // proc_bind_default means don't update
2157 kmp_proc_bind_t proc_bind_icv = proc_bind_default;
2158 if (master_th->th.th_current_task->td_icvs.proc_bind == proc_bind_false) {
2159 proc_bind = proc_bind_false;
2160 } else {
2161 // No proc_bind clause specified; use current proc-bind-var for this
2162 // parallel region
2163 if (proc_bind == proc_bind_default) {
2164 proc_bind = master_th->th.th_current_task->td_icvs.proc_bind;
2165 }
2166 // Have teams construct take proc_bind value from KMP_TEAMS_PROC_BIND
2167 if (master_th->th.th_teams_microtask &&
2168 microtask == (microtask_t)__kmp_teams_master) {
2169 proc_bind = __kmp_teams_proc_bind;
2170 }
2171 /* else: The proc_bind policy was specified explicitly on parallel clause.
2172 This overrides proc-bind-var for this parallel region, but does not
2173 change proc-bind-var. */
2174 // Figure the value of proc-bind-var for the child threads.
2175 if ((level + 1 < __kmp_nested_proc_bind.used) &&
2176 (__kmp_nested_proc_bind.bind_types[level + 1] !=
2177 master_th->th.th_current_task->td_icvs.proc_bind)) {
2178 // Do not modify the proc bind icv for the two teams construct forks
2179 // They just let the proc bind icv pass through
2180 if (!master_th->th.th_teams_microtask ||
2181 !(microtask == (microtask_t)__kmp_teams_master || ap == NULL))
2182 proc_bind_icv = __kmp_nested_proc_bind.bind_types[level + 1];
2183 }
2184 }
2185
2186 // Reset for next parallel region
2187 master_th->th.th_set_proc_bind = proc_bind_default;
2188
2189 if ((nthreads_icv > 0) || (proc_bind_icv != proc_bind_default)) {
2190 kmp_internal_control_t new_icvs;
2191 copy_icvs(&new_icvs, &master_th->th.th_current_task->td_icvs);
2192 new_icvs.next = NULL;
2193 if (nthreads_icv > 0) {
2194 new_icvs.nproc = nthreads_icv;
2195 }
2196 if (proc_bind_icv != proc_bind_default) {
2197 new_icvs.proc_bind = proc_bind_icv;
2198 }
2199
2200 /* allocate a new parallel team */
2201 KF_TRACE(10, ("__kmp_fork_call: before __kmp_allocate_team\n"));
2202 team = __kmp_allocate_team(root, nthreads, nthreads,
2203#if OMPT_SUPPORT
2204 ompt_parallel_data,
2205#endif
2206 proc_bind, &new_icvs, argc, master_th);
2207 if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar)
2208 copy_icvs((kmp_internal_control_t *)team->t.b->team_icvs, &new_icvs);
2209 } else {
2210 /* allocate a new parallel team */
2211 KF_TRACE(10, ("__kmp_fork_call: before __kmp_allocate_team\n"));
2212 team = __kmp_allocate_team(
2213 root, nthreads, nthreads,
2214#if OMPT_SUPPORT
2215 ompt_parallel_data,
2216#endif
2217 proc_bind, &master_th->th.th_current_task->td_icvs, argc, master_th);
2218 if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar)
2219 copy_icvs((kmp_internal_control_t *)team->t.b->team_icvs,
2220 &master_th->th.th_current_task->td_icvs);
2221 }
2222 KF_TRACE(
2223 10, ("__kmp_fork_call: after __kmp_allocate_team - team = %p\n", team));
2224
2225 /* setup the new team */
2226 KMP_CHECK_UPDATE(team->t.t_master_tid, master_tid);
2227 KMP_CHECK_UPDATE(team->t.t_master_this_cons, master_this_cons);
2228 KMP_CHECK_UPDATE(team->t.t_ident, loc);
2229 KMP_CHECK_UPDATE(team->t.t_parent, parent_team);
2230 KMP_CHECK_UPDATE_SYNC(team->t.t_pkfn, microtask);
2231#if OMPT_SUPPORT
2232 KMP_CHECK_UPDATE_SYNC(team->t.ompt_team_info.master_return_address,
2233 return_address);
2234#endif
2235 KMP_CHECK_UPDATE(team->t.t_invoke, invoker); // TODO move to root, maybe
2236 // TODO: parent_team->t.t_level == INT_MAX ???
2237 if (!master_th->th.th_teams_microtask || level > teams_level) {
2238 int new_level = parent_team->t.t_level + 1;
2239 KMP_CHECK_UPDATE(team->t.t_level, new_level);
2240 new_level = parent_team->t.t_active_level + 1;
2241 KMP_CHECK_UPDATE(team->t.t_active_level, new_level);
2242 } else {
2243 // AC: Do not increase parallel level at start of the teams construct
2244 int new_level = parent_team->t.t_level;
2245 KMP_CHECK_UPDATE(team->t.t_level, new_level);
2246 new_level = parent_team->t.t_active_level;
2247 KMP_CHECK_UPDATE(team->t.t_active_level, new_level);
2248 }
2249 kmp_r_sched_t new_sched = get__sched_2(parent_team, master_tid);
2250 // set primary thread's schedule as new run-time schedule
2251 KMP_CHECK_UPDATE(team->t.t_sched.sched, new_sched.sched);
2252
2253 KMP_CHECK_UPDATE(team->t.t_cancel_request, cancel_noreq);
2254 KMP_CHECK_UPDATE(team->t.t_def_allocator, master_th->th.th_def_allocator);
2255
2256 // Check if hot team has potentially outdated list, and if so, free it
2257 if (team->t.t_nested_nth &&
2258 team->t.t_nested_nth != parent_team->t.t_nested_nth) {
2259 KMP_INTERNAL_FREE(team->t.t_nested_nth->nth);
2260 KMP_INTERNAL_FREE(team->t.t_nested_nth);
2261 team->t.t_nested_nth = NULL;
2262 }
2263 team->t.t_nested_nth = parent_team->t.t_nested_nth;
2264 if (master_th->th.th_set_nested_nth) {
2265 if (!nested_nth)
2266 nested_nth = __kmp_override_nested_nth(master_th, level);
2267 team->t.t_nested_nth = nested_nth;
2268 KMP_INTERNAL_FREE(master_th->th.th_set_nested_nth);
2269 master_th->th.th_set_nested_nth = NULL;
2270 master_th->th.th_set_nested_nth_sz = 0;
2271 master_th->th.th_nt_strict = false;
2272 }
2273
2274 // Update the floating point rounding in the team if required.
2275 propagateFPControl(team);
2276#if OMPD_SUPPORT
2277 if (ompd_state & OMPD_ENABLE_BP)
2278 ompd_bp_parallel_begin();
2279#endif
2280
2281 KA_TRACE(
2282 20,
2283 ("__kmp_fork_call: T#%d(%d:%d)->(%d:0) created a team of %d threads\n",
2284 gtid, parent_team->t.t_id, team->t.t_master_tid, team->t.t_id,
2285 team->t.t_nproc));
2286 KMP_DEBUG_ASSERT(team != root->r.r_hot_team ||
2287 (team->t.t_master_tid == 0 &&
2288 (team->t.t_parent == root->r.r_root_team ||
2289 team->t.t_parent->t.t_serialized)));
2290 KMP_MB();
2291
2292 /* now, setup the arguments */
2293 argv = (void **)team->t.t_argv;
2294 if (ap) {
2295 for (i = argc - 1; i >= 0; --i) {
2296 void *new_argv = va_arg(kmp_va_deref(ap), void *);
2297 KMP_CHECK_UPDATE(*argv, new_argv);
2298 argv++;
2299 }
2300 } else {
2301 for (i = 0; i < argc; ++i) {
2302 // Get args from parent team for teams construct
2303 KMP_CHECK_UPDATE(argv[i], team->t.t_parent->t.t_argv[i]);
2304 }
2305 }
2306
2307 /* now actually fork the threads */
2308 KMP_CHECK_UPDATE(team->t.t_master_active, master_active);
2309 if (!root->r.r_active) // Only do assignment if it prevents cache ping-pong
2310 root->r.r_active = TRUE;
2311
2312 __kmp_fork_team_threads(root, team, master_th, gtid, !ap);
2313 __kmp_setup_icv_copy(team, nthreads,
2314 &master_th->th.th_current_task->td_icvs, loc);
2315
2316#if OMPT_SUPPORT
2317 master_th->th.ompt_thread_info.state = ompt_state_work_parallel;
2318#endif
2319
2320 __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
2321
2322#if USE_ITT_BUILD
2323 if (team->t.t_active_level == 1 // only report frames at level 1
2324 && !master_th->th.th_teams_microtask) { // not in teams construct
2325#if USE_ITT_NOTIFY
2326 if ((__itt_frame_submit_v3_ptr || KMP_ITT_DEBUG) &&
2327 (__kmp_forkjoin_frames_mode == 3 ||
2328 __kmp_forkjoin_frames_mode == 1)) {
2329 kmp_uint64 tmp_time = 0;
2330 if (__itt_get_timestamp_ptr)
2331 tmp_time = __itt_get_timestamp();
2332 // Internal fork - report frame begin
2333 master_th->th.th_frame_time = tmp_time;
2334 if (__kmp_forkjoin_frames_mode == 3)
2335 team->t.t_region_time = tmp_time;
2336 } else
2337// only one notification scheme (either "submit" or "forking/joined", not both)
2338#endif /* USE_ITT_NOTIFY */
2339 if ((__itt_frame_begin_v3_ptr || KMP_ITT_DEBUG) &&
2340 __kmp_forkjoin_frames && !__kmp_forkjoin_frames_mode) {
2341 // Mark start of "parallel" region for Intel(R) VTune(TM) analyzer.
2342 __kmp_itt_region_forking(gtid, team->t.t_nproc, 0);
2343 }
2344 }
2345#endif /* USE_ITT_BUILD */
2346
2347 /* now go on and do the work */
2348 KMP_DEBUG_ASSERT(team == __kmp_threads[gtid]->th.th_team);
2349 KMP_MB();
2350 KF_TRACE(10,
2351 ("__kmp_internal_fork : root=%p, team=%p, master_th=%p, gtid=%d\n",
2352 root, team, master_th, gtid));
2353
2354#if USE_ITT_BUILD
2355 if (__itt_stack_caller_create_ptr) {
2356 // create new stack stitching id before entering fork barrier
2357 if (!enter_teams) {
2358 KMP_DEBUG_ASSERT(team->t.t_stack_id == NULL);
2359 team->t.t_stack_id = __kmp_itt_stack_caller_create();
2360 } else if (parent_team->t.t_serialized) {
2361 // keep stack stitching id in the serialized parent_team;
2362 // current team will be used for parallel inside the teams;
2363 // if parent_team is active, then it already keeps stack stitching id
2364 // for the league of teams
2365 KMP_DEBUG_ASSERT(parent_team->t.t_stack_id == NULL);
2366 parent_team->t.t_stack_id = __kmp_itt_stack_caller_create();
2367 }
2368 }
2369#endif /* USE_ITT_BUILD */
2370
2371 // AC: skip __kmp_internal_fork at teams construct, let only primary
2372 // threads execute
2373 if (ap) {
2374 __kmp_internal_fork(loc, gtid, team);
2375 KF_TRACE(10, ("__kmp_internal_fork : after : root=%p, team=%p, "
2376 "master_th=%p, gtid=%d\n",
2377 root, team, master_th, gtid));
2378 }
2379
2380 if (call_context == fork_context_gnu) {
2381 KA_TRACE(20, ("__kmp_fork_call: parallel exit T#%d\n", gtid));
2382 return TRUE;
2383 }
2384
2385 /* Invoke microtask for PRIMARY thread */
2386 KA_TRACE(20, ("__kmp_fork_call: T#%d(%d:0) invoke microtask = %p\n", gtid,
2387 team->t.t_id, team->t.t_pkfn));
2388 } // END of timer KMP_fork_call block
2389
2390#if KMP_STATS_ENABLED
2391 // If beginning a teams construct, then change thread state
2392 stats_state_e previous_state = KMP_GET_THREAD_STATE();
2393 if (!ap) {
2394 KMP_SET_THREAD_STATE(stats_state_e::TEAMS_REGION);
2395 }
2396#endif
2397
2398 if (!team->t.t_invoke(gtid)) {
2399 KMP_ASSERT2(0, "cannot invoke microtask for PRIMARY thread");
2400 }
2401
2402#if KMP_STATS_ENABLED
2403 // If was beginning of a teams construct, then reset thread state
2404 if (!ap) {
2405 KMP_SET_THREAD_STATE(previous_state);
2406 }
2407#endif
2408
2409 KA_TRACE(20, ("__kmp_fork_call: T#%d(%d:0) done microtask = %p\n", gtid,
2410 team->t.t_id, team->t.t_pkfn));
2411 KMP_MB(); /* Flush all pending memory write invalidates. */
2412
2413 KA_TRACE(20, ("__kmp_fork_call: parallel exit T#%d\n", gtid));
2414#if OMPT_SUPPORT
2415 if (ompt_enabled.enabled) {
2416 master_th->th.ompt_thread_info.state = ompt_state_overhead;
2417 }
2418#endif
2419
2420 return TRUE;
2421}
2422
2423#if OMPT_SUPPORT
2424static inline void __kmp_join_restore_state(kmp_info_t *thread,
2425 kmp_team_t *team) {
2426 // restore state outside the region
2427 thread->th.ompt_thread_info.state =
2428 ((team->t.t_serialized) ? ompt_state_work_serial
2429 : ompt_state_work_parallel);
2430}
2431
2432static inline void __kmp_join_ompt(int gtid, kmp_info_t *thread,
2433 kmp_team_t *team, ompt_data_t *parallel_data,
2434 int flags, void *codeptr) {
2435 ompt_task_info_t *task_info = __ompt_get_task_info_object(0);
2436 if (ompt_enabled.ompt_callback_parallel_end) {
2437 ompt_callbacks.ompt_callback(ompt_callback_parallel_end)(
2438 parallel_data, &(task_info->task_data), flags, codeptr);
2439 }
2440
2441 task_info->frame.enter_frame = ompt_data_none;
2442 __kmp_join_restore_state(thread, team);
2443}
2444#endif
2445
2446void __kmp_join_call(ident_t *loc, int gtid
2447#if OMPT_SUPPORT
2448 ,
2449 enum fork_context_e fork_context
2450#endif
2451 ,
2452 int exit_teams) {
2453 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_join_call);
2454 kmp_team_t *team;
2455 kmp_team_t *parent_team;
2456 kmp_info_t *master_th;
2457 kmp_root_t *root;
2458 int master_active;
2459
2460 KA_TRACE(20, ("__kmp_join_call: enter T#%d\n", gtid));
2461
2462 /* setup current data */
2463 master_th = __kmp_threads[gtid];
2464 root = master_th->th.th_root;
2465 team = master_th->th.th_team;
2466 parent_team = team->t.t_parent;
2467
2468 master_th->th.th_ident = loc;
2469
2470#if OMPT_SUPPORT
2471 void *team_microtask = (void *)team->t.t_pkfn;
2472 // For GOMP interface with serialized parallel, need the
2473 // __kmpc_end_serialized_parallel to call hooks for OMPT end-implicit-task
2474 // and end-parallel events.
2475 if (ompt_enabled.enabled &&
2476 !(team->t.t_serialized && fork_context == fork_context_gnu)) {
2477 master_th->th.ompt_thread_info.state = ompt_state_overhead;
2478 }
2479#endif
2480
2481#if KMP_DEBUG
2482 if (__kmp_tasking_mode != tskm_immediate_exec && !exit_teams) {
2483 KA_TRACE(20, ("__kmp_join_call: T#%d, old team = %p old task_team = %p, "
2484 "th_task_team = %p\n",
2485 __kmp_gtid_from_thread(master_th), team,
2486 team->t.t_task_team[master_th->th.th_task_state],
2487 master_th->th.th_task_team));
2488 KMP_DEBUG_ASSERT_TASKTEAM_INVARIANT(team, master_th);
2489 }
2490#endif
2491
2492 if (team->t.t_serialized) {
2493 if (master_th->th.th_teams_microtask) {
2494 // We are in teams construct
2495 int level = team->t.t_level;
2496 int tlevel = master_th->th.th_teams_level;
2497 if (level == tlevel) {
2498 // AC: we haven't incremented it earlier at start of teams construct,
2499 // so do it here - at the end of teams construct
2500 team->t.t_level++;
2501 } else if (level == tlevel + 1) {
2502 // AC: we are exiting parallel inside teams, need to increment
2503 // serialization in order to restore it in the next call to
2504 // __kmpc_end_serialized_parallel
2505 team->t.t_serialized++;
2506 }
2507 }
2509
2510#if OMPT_SUPPORT
2511 if (ompt_enabled.enabled) {
2512 if (fork_context == fork_context_gnu) {
2513 __ompt_lw_taskteam_unlink(master_th);
2514 }
2515 __kmp_join_restore_state(master_th, parent_team);
2516 }
2517#endif
2518
2519 return;
2520 }
2521
2522 master_active = team->t.t_master_active;
2523
2524 if (!exit_teams) {
2525 // AC: No barrier for internal teams at exit from teams construct.
2526 // But there is barrier for external team (league).
2527 __kmp_internal_join(loc, gtid, team);
2528#if USE_ITT_BUILD
2529 if (__itt_stack_caller_create_ptr) {
2530 KMP_DEBUG_ASSERT(team->t.t_stack_id != NULL);
2531 // destroy the stack stitching id after join barrier
2532 __kmp_itt_stack_caller_destroy((__itt_caller)team->t.t_stack_id);
2533 team->t.t_stack_id = NULL;
2534 }
2535#endif
2536 } else {
2537 master_th->th.th_task_state =
2538 0; // AC: no tasking in teams (out of any parallel)
2539#if USE_ITT_BUILD
2540 if (__itt_stack_caller_create_ptr && parent_team->t.t_serialized) {
2541 KMP_DEBUG_ASSERT(parent_team->t.t_stack_id != NULL);
2542 // destroy the stack stitching id on exit from the teams construct
2543 // if parent_team is active, then the id will be destroyed later on
2544 // by master of the league of teams
2545 __kmp_itt_stack_caller_destroy((__itt_caller)parent_team->t.t_stack_id);
2546 parent_team->t.t_stack_id = NULL;
2547 }
2548#endif
2549 }
2550
2551 KMP_MB();
2552
2553#if OMPT_SUPPORT
2554 ompt_data_t *parallel_data = &(team->t.ompt_team_info.parallel_data);
2555 void *codeptr = team->t.ompt_team_info.master_return_address;
2556#endif
2557
2558#if USE_ITT_BUILD
2559 // Mark end of "parallel" region for Intel(R) VTune(TM) analyzer.
2560 if (team->t.t_active_level == 1 &&
2561 (!master_th->th.th_teams_microtask || /* not in teams construct */
2562 master_th->th.th_teams_size.nteams == 1)) {
2563 master_th->th.th_ident = loc;
2564 // only one notification scheme (either "submit" or "forking/joined", not
2565 // both)
2566 if ((__itt_frame_submit_v3_ptr || KMP_ITT_DEBUG) &&
2567 __kmp_forkjoin_frames_mode == 3)
2568 __kmp_itt_frame_submit(gtid, team->t.t_region_time,
2569 master_th->th.th_frame_time, 0, loc,
2570 master_th->th.th_team_nproc, 1);
2571 else if ((__itt_frame_end_v3_ptr || KMP_ITT_DEBUG) &&
2572 !__kmp_forkjoin_frames_mode && __kmp_forkjoin_frames)
2573 __kmp_itt_region_joined(gtid);
2574 } // active_level == 1
2575#endif /* USE_ITT_BUILD */
2576
2577#if KMP_AFFINITY_SUPPORTED
2578 if (!exit_teams) {
2579 // Restore master thread's partition.
2580 master_th->th.th_first_place = team->t.t_first_place;
2581 master_th->th.th_last_place = team->t.t_last_place;
2582 }
2583#endif // KMP_AFFINITY_SUPPORTED
2584
2585 if (master_th->th.th_teams_microtask && !exit_teams &&
2586 team->t.t_pkfn != (microtask_t)__kmp_teams_master &&
2587 team->t.t_level == master_th->th.th_teams_level + 1) {
2588// AC: We need to leave the team structure intact at the end of parallel
2589// inside the teams construct, so that at the next parallel same (hot) team
2590// works, only adjust nesting levels
2591#if OMPT_SUPPORT
2592 ompt_data_t ompt_parallel_data = ompt_data_none;
2593 if (ompt_enabled.enabled) {
2594 ompt_task_info_t *task_info = __ompt_get_task_info_object(0);
2595 if (ompt_enabled.ompt_callback_implicit_task) {
2596 int ompt_team_size = team->t.t_nproc;
2597 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
2598 ompt_scope_end, NULL, &(task_info->task_data), ompt_team_size,
2599 OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_implicit);
2600 }
2601 task_info->frame.exit_frame = ompt_data_none;
2602 task_info->task_data = ompt_data_none;
2603 ompt_parallel_data = *OMPT_CUR_TEAM_DATA(master_th);
2604 __ompt_lw_taskteam_unlink(master_th);
2605 }
2606#endif
2607 /* Decrement our nested depth level */
2608 team->t.t_level--;
2609 team->t.t_active_level--;
2610 KMP_ATOMIC_DEC(&root->r.r_in_parallel);
2611
2612 // Restore number of threads in the team if needed. This code relies on
2613 // the proper adjustment of th_teams_size.nth after the fork in
2614 // __kmp_teams_master on each teams primary thread in the case that
2615 // __kmp_reserve_threads reduced it.
2616 if (master_th->th.th_team_nproc < master_th->th.th_teams_size.nth) {
2617 int old_num = master_th->th.th_team_nproc;
2618 int new_num = master_th->th.th_teams_size.nth;
2619 kmp_info_t **other_threads = team->t.t_threads;
2620 team->t.t_nproc = new_num;
2621 for (int i = 0; i < old_num; ++i) {
2622 other_threads[i]->th.th_team_nproc = new_num;
2623 }
2624 // Adjust states of non-used threads of the team
2625 for (int i = old_num; i < new_num; ++i) {
2626 // Re-initialize thread's barrier data.
2627 KMP_DEBUG_ASSERT(other_threads[i]);
2628 kmp_balign_t *balign = other_threads[i]->th.th_bar;
2629 for (int b = 0; b < bs_last_barrier; ++b) {
2630 balign[b].bb.b_arrived = team->t.t_bar[b].b_arrived;
2631 KMP_DEBUG_ASSERT(balign[b].bb.wait_flag != KMP_BARRIER_PARENT_FLAG);
2632#if USE_DEBUGGER
2633 balign[b].bb.b_worker_arrived = team->t.t_bar[b].b_team_arrived;
2634#endif
2635 }
2636 if (__kmp_tasking_mode != tskm_immediate_exec) {
2637 // Synchronize thread's task state
2638 other_threads[i]->th.th_task_state = master_th->th.th_task_state;
2639 }
2640 }
2641 }
2642
2643#if OMPT_SUPPORT
2644 if (ompt_enabled.enabled) {
2645 __kmp_join_ompt(gtid, master_th, parent_team, &ompt_parallel_data,
2646 OMPT_INVOKER(fork_context) | ompt_parallel_team, codeptr);
2647 }
2648#endif
2649
2650 return;
2651 }
2652
2653 /* do cleanup and restore the parent team */
2654 master_th->th.th_info.ds.ds_tid = team->t.t_master_tid;
2655 master_th->th.th_local.this_construct = team->t.t_master_this_cons;
2656
2657 master_th->th.th_dispatch = &parent_team->t.t_dispatch[team->t.t_master_tid];
2658
2659 /* jc: The following lock has instructions with REL and ACQ semantics,
2660 separating the parallel user code called in this parallel region
2661 from the serial user code called after this function returns. */
2662 __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
2663
2664 if (!master_th->th.th_teams_microtask ||
2665 team->t.t_level > master_th->th.th_teams_level) {
2666 /* Decrement our nested depth level */
2667 KMP_ATOMIC_DEC(&root->r.r_in_parallel);
2668 }
2669 KMP_DEBUG_ASSERT(root->r.r_in_parallel >= 0);
2670
2671#if OMPT_SUPPORT
2672 if (ompt_enabled.enabled) {
2673 ompt_task_info_t *task_info = __ompt_get_task_info_object(0);
2674 if (ompt_enabled.ompt_callback_implicit_task) {
2675 int flags = (team_microtask == (void *)__kmp_teams_master)
2676 ? ompt_task_initial
2677 : ompt_task_implicit;
2678 int ompt_team_size = (flags == ompt_task_initial) ? 0 : team->t.t_nproc;
2679 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
2680 ompt_scope_end, NULL, &(task_info->task_data), ompt_team_size,
2681 OMPT_CUR_TASK_INFO(master_th)->thread_num, flags);
2682 }
2683 task_info->frame.exit_frame = ompt_data_none;
2684 task_info->task_data = ompt_data_none;
2685 }
2686#endif
2687
2688 KF_TRACE(10, ("__kmp_join_call1: T#%d, this_thread=%p team=%p\n", 0,
2689 master_th, team));
2690 __kmp_pop_current_task_from_thread(master_th);
2691
2692 master_th->th.th_def_allocator = team->t.t_def_allocator;
2693
2694#if OMPD_SUPPORT
2695 if (ompd_state & OMPD_ENABLE_BP)
2696 ompd_bp_parallel_end();
2697#endif
2698 updateHWFPControl(team);
2699
2700 if (root->r.r_active != master_active)
2701 root->r.r_active = master_active;
2702
2703 __kmp_free_team(root, team, master_th); // this will free worker threads
2704
2705 /* this race was fun to find. make sure the following is in the critical
2706 region otherwise assertions may fail occasionally since the old team may be
2707 reallocated and the hierarchy appears inconsistent. it is actually safe to
2708 run and won't cause any bugs, but will cause those assertion failures. it's
2709 only one deref&assign so might as well put this in the critical region */
2710 master_th->th.th_team = parent_team;
2711 master_th->th.th_team_nproc = parent_team->t.t_nproc;
2712 master_th->th.th_team_master = parent_team->t.t_threads[0];
2713 master_th->th.th_team_serialized = parent_team->t.t_serialized;
2714
2715 /* restore serialized team, if need be */
2716 if (parent_team->t.t_serialized &&
2717 parent_team != master_th->th.th_serial_team &&
2718 parent_team != root->r.r_root_team) {
2719 __kmp_free_team(root, master_th->th.th_serial_team, NULL);
2720 master_th->th.th_serial_team = parent_team;
2721 }
2722
2723 if (__kmp_tasking_mode != tskm_immediate_exec) {
2724 // Restore primary thread's task state from team structure
2725 KMP_DEBUG_ASSERT(team->t.t_primary_task_state == 0 ||
2726 team->t.t_primary_task_state == 1);
2727 master_th->th.th_task_state = (kmp_uint8)team->t.t_primary_task_state;
2728
2729 // Copy the task team from the parent team to the primary thread
2730 master_th->th.th_task_team =
2731 parent_team->t.t_task_team[master_th->th.th_task_state];
2732 KA_TRACE(20,
2733 ("__kmp_join_call: Primary T#%d restoring task_team %p, team %p\n",
2734 __kmp_gtid_from_thread(master_th), master_th->th.th_task_team,
2735 parent_team));
2736 }
2737
2738 // TODO: GEH - cannot do this assertion because root thread not set up as
2739 // executing
2740 // KMP_ASSERT( master_th->th.th_current_task->td_flags.executing == 0 );
2741 master_th->th.th_current_task->td_flags.executing = 1;
2742
2743 __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
2744
2745#if KMP_AFFINITY_SUPPORTED
2746 if (master_th->th.th_team->t.t_level == 0 && __kmp_affinity.flags.reset) {
2747 __kmp_reset_root_init_mask(gtid);
2748 }
2749#endif
2750#if OMPT_SUPPORT
2751 int flags =
2752 OMPT_INVOKER(fork_context) |
2753 ((team_microtask == (void *)__kmp_teams_master) ? ompt_parallel_league
2754 : ompt_parallel_team);
2755 if (ompt_enabled.enabled) {
2756 __kmp_join_ompt(gtid, master_th, parent_team, parallel_data, flags,
2757 codeptr);
2758 }
2759#endif
2760
2761 KMP_MB();
2762 KA_TRACE(20, ("__kmp_join_call: exit T#%d\n", gtid));
2763}
2764
2765/* Check whether we should push an internal control record onto the
2766 serial team stack. If so, do it. */
2767void __kmp_save_internal_controls(kmp_info_t *thread) {
2768
2769 if (thread->th.th_team != thread->th.th_serial_team) {
2770 return;
2771 }
2772 if (thread->th.th_team->t.t_serialized > 1) {
2773 int push = 0;
2774
2775 if (thread->th.th_team->t.t_control_stack_top == NULL) {
2776 push = 1;
2777 } else {
2778 if (thread->th.th_team->t.t_control_stack_top->serial_nesting_level !=
2779 thread->th.th_team->t.t_serialized) {
2780 push = 1;
2781 }
2782 }
2783 if (push) { /* push a record on the serial team's stack */
2784 kmp_internal_control_t *control =
2785 (kmp_internal_control_t *)__kmp_allocate(
2786 sizeof(kmp_internal_control_t));
2787
2788 copy_icvs(control, &thread->th.th_current_task->td_icvs);
2789
2790 control->serial_nesting_level = thread->th.th_team->t.t_serialized;
2791
2792 control->next = thread->th.th_team->t.t_control_stack_top;
2793 thread->th.th_team->t.t_control_stack_top = control;
2794 }
2795 }
2796}
2797
2798/* Changes set_nproc */
2799void __kmp_set_num_threads(int new_nth, int gtid) {
2800 kmp_info_t *thread;
2801 kmp_root_t *root;
2802
2803 KF_TRACE(10, ("__kmp_set_num_threads: new __kmp_nth = %d\n", new_nth));
2804 KMP_DEBUG_ASSERT(__kmp_init_serial);
2805
2806 if (new_nth < 1)
2807 new_nth = 1;
2808 else if (new_nth > __kmp_max_nth)
2809 new_nth = __kmp_max_nth;
2810
2811 KMP_COUNT_VALUE(OMP_set_numthreads, new_nth);
2812 thread = __kmp_threads[gtid];
2813 if (thread->th.th_current_task->td_icvs.nproc == new_nth)
2814 return; // nothing to do
2815
2816 __kmp_save_internal_controls(thread);
2817
2818 set__nproc(thread, new_nth);
2819
2820 // If this omp_set_num_threads() call will cause the hot team size to be
2821 // reduced (in the absence of a num_threads clause), then reduce it now,
2822 // rather than waiting for the next parallel region.
2823 root = thread->th.th_root;
2824 if (__kmp_init_parallel && (!root->r.r_active) &&
2825 (root->r.r_hot_team->t.t_nproc > new_nth) && __kmp_hot_teams_max_level &&
2826 !__kmp_hot_teams_mode) {
2827 kmp_team_t *hot_team = root->r.r_hot_team;
2828 int f;
2829
2830 __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
2831
2832 if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
2833 __kmp_resize_dist_barrier(hot_team, hot_team->t.t_nproc, new_nth);
2834 }
2835 // Release the extra threads we don't need any more.
2836 for (f = new_nth; f < hot_team->t.t_nproc; f++) {
2837 KMP_DEBUG_ASSERT(hot_team->t.t_threads[f] != NULL);
2838 if (__kmp_tasking_mode != tskm_immediate_exec) {
2839 // When decreasing team size, threads no longer in the team should unref
2840 // task team.
2841 hot_team->t.t_threads[f]->th.th_task_team = NULL;
2842 }
2843 __kmp_free_thread(hot_team->t.t_threads[f]);
2844 hot_team->t.t_threads[f] = NULL;
2845 }
2846 hot_team->t.t_nproc = new_nth;
2847 if (thread->th.th_hot_teams) {
2848 KMP_DEBUG_ASSERT(hot_team == thread->th.th_hot_teams[0].hot_team);
2849 thread->th.th_hot_teams[0].hot_team_nth = new_nth;
2850 }
2851
2852 if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
2853 hot_team->t.b->update_num_threads(new_nth);
2854 __kmp_add_threads_to_team(hot_team, new_nth);
2855 }
2856
2857 __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
2858
2859 // Update the t_nproc field in the threads that are still active.
2860 for (f = 0; f < new_nth; f++) {
2861 KMP_DEBUG_ASSERT(hot_team->t.t_threads[f] != NULL);
2862 hot_team->t.t_threads[f]->th.th_team_nproc = new_nth;
2863 }
2864 // Special flag in case omp_set_num_threads() call
2865 hot_team->t.t_size_changed = -1;
2866 }
2867}
2868
2869/* Changes max_active_levels */
2870void __kmp_set_max_active_levels(int gtid, int max_active_levels) {
2871 kmp_info_t *thread;
2872
2873 KF_TRACE(10, ("__kmp_set_max_active_levels: new max_active_levels for thread "
2874 "%d = (%d)\n",
2875 gtid, max_active_levels));
2876 KMP_DEBUG_ASSERT(__kmp_init_serial);
2877
2878 // validate max_active_levels
2879 if (max_active_levels < 0) {
2880 KMP_WARNING(ActiveLevelsNegative, max_active_levels);
2881 // We ignore this call if the user has specified a negative value.
2882 // The current setting won't be changed. The last valid setting will be
2883 // used. A warning will be issued (if warnings are allowed as controlled by
2884 // the KMP_WARNINGS env var).
2885 KF_TRACE(10, ("__kmp_set_max_active_levels: the call is ignored: new "
2886 "max_active_levels for thread %d = (%d)\n",
2887 gtid, max_active_levels));
2888 return;
2889 }
2890 if (max_active_levels <= KMP_MAX_ACTIVE_LEVELS_LIMIT) {
2891 // it's OK, the max_active_levels is within the valid range: [ 0;
2892 // KMP_MAX_ACTIVE_LEVELS_LIMIT ]
2893 // We allow a zero value. (implementation defined behavior)
2894 } else {
2895 KMP_WARNING(ActiveLevelsExceedLimit, max_active_levels,
2896 KMP_MAX_ACTIVE_LEVELS_LIMIT);
2897 max_active_levels = KMP_MAX_ACTIVE_LEVELS_LIMIT;
2898 // Current upper limit is MAX_INT. (implementation defined behavior)
2899 // If the input exceeds the upper limit, we correct the input to be the
2900 // upper limit. (implementation defined behavior)
2901 // Actually, the flow should never get here until we use MAX_INT limit.
2902 }
2903 KF_TRACE(10, ("__kmp_set_max_active_levels: after validation: new "
2904 "max_active_levels for thread %d = (%d)\n",
2905 gtid, max_active_levels));
2906
2907 thread = __kmp_threads[gtid];
2908
2909 __kmp_save_internal_controls(thread);
2910
2911 set__max_active_levels(thread, max_active_levels);
2912}
2913
2914/* Gets max_active_levels */
2915int __kmp_get_max_active_levels(int gtid) {
2916 kmp_info_t *thread;
2917
2918 KF_TRACE(10, ("__kmp_get_max_active_levels: thread %d\n", gtid));
2919 KMP_DEBUG_ASSERT(__kmp_init_serial);
2920
2921 thread = __kmp_threads[gtid];
2922 KMP_DEBUG_ASSERT(thread->th.th_current_task);
2923 KF_TRACE(10, ("__kmp_get_max_active_levels: thread %d, curtask=%p, "
2924 "curtask_maxaclevel=%d\n",
2925 gtid, thread->th.th_current_task,
2926 thread->th.th_current_task->td_icvs.max_active_levels));
2927 return thread->th.th_current_task->td_icvs.max_active_levels;
2928}
2929
2930// nteams-var per-device ICV
2931void __kmp_set_num_teams(int num_teams) {
2932 if (num_teams > 0)
2933 __kmp_nteams = num_teams;
2934}
2935int __kmp_get_max_teams(void) { return __kmp_nteams; }
2936// teams-thread-limit-var per-device ICV
2937void __kmp_set_teams_thread_limit(int limit) {
2938 if (limit > 0)
2939 __kmp_teams_thread_limit = limit;
2940}
2941int __kmp_get_teams_thread_limit(void) { return __kmp_teams_thread_limit; }
2942
2943KMP_BUILD_ASSERT(sizeof(kmp_sched_t) == sizeof(int));
2944KMP_BUILD_ASSERT(sizeof(enum sched_type) == sizeof(int));
2945
2946/* Changes def_sched_var ICV values (run-time schedule kind and chunk) */
2947void __kmp_set_schedule(int gtid, kmp_sched_t kind, int chunk) {
2948 kmp_info_t *thread;
2949 kmp_sched_t orig_kind;
2950 // kmp_team_t *team;
2951
2952 KF_TRACE(10, ("__kmp_set_schedule: new schedule for thread %d = (%d, %d)\n",
2953 gtid, (int)kind, chunk));
2954 KMP_DEBUG_ASSERT(__kmp_init_serial);
2955
2956 // Check if the kind parameter is valid, correct if needed.
2957 // Valid parameters should fit in one of two intervals - standard or extended:
2958 // <lower>, <valid>, <upper_std>, <lower_ext>, <valid>, <upper>
2959 // 2008-01-25: 0, 1 - 4, 5, 100, 101 - 102, 103
2960 orig_kind = kind;
2961 kind = __kmp_sched_without_mods(kind);
2962
2963 if (kind <= kmp_sched_lower || kind >= kmp_sched_upper ||
2964 (kind <= kmp_sched_lower_ext && kind >= kmp_sched_upper_std)) {
2965 // TODO: Hint needs attention in case we change the default schedule.
2966 __kmp_msg(kmp_ms_warning, KMP_MSG(ScheduleKindOutOfRange, kind),
2967 KMP_HNT(DefaultScheduleKindUsed, "static, no chunk"),
2968 __kmp_msg_null);
2969 kind = kmp_sched_default;
2970 chunk = 0; // ignore chunk value in case of bad kind
2971 }
2972
2973 thread = __kmp_threads[gtid];
2974
2975 __kmp_save_internal_controls(thread);
2976
2977 if (kind < kmp_sched_upper_std) {
2978 if (kind == kmp_sched_static && chunk < KMP_DEFAULT_CHUNK) {
2979 // differ static chunked vs. unchunked: chunk should be invalid to
2980 // indicate unchunked schedule (which is the default)
2981 thread->th.th_current_task->td_icvs.sched.r_sched_type = kmp_sch_static;
2982 } else {
2983 thread->th.th_current_task->td_icvs.sched.r_sched_type =
2984 __kmp_sch_map[kind - kmp_sched_lower - 1];
2985 }
2986 } else {
2987 // __kmp_sch_map[ kind - kmp_sched_lower_ext + kmp_sched_upper_std -
2988 // kmp_sched_lower - 2 ];
2989 thread->th.th_current_task->td_icvs.sched.r_sched_type =
2990 __kmp_sch_map[kind - kmp_sched_lower_ext + kmp_sched_upper_std -
2991 kmp_sched_lower - 2];
2992 }
2993 __kmp_sched_apply_mods_intkind(
2994 orig_kind, &(thread->th.th_current_task->td_icvs.sched.r_sched_type));
2995 if (kind == kmp_sched_auto || chunk < 1) {
2996 // ignore parameter chunk for schedule auto
2997 thread->th.th_current_task->td_icvs.sched.chunk = KMP_DEFAULT_CHUNK;
2998 } else {
2999 thread->th.th_current_task->td_icvs.sched.chunk = chunk;
3000 }
3001}
3002
3003/* Gets def_sched_var ICV values */
3004void __kmp_get_schedule(int gtid, kmp_sched_t *kind, int *chunk) {
3005 kmp_info_t *thread;
3006 enum sched_type th_type;
3007
3008 KF_TRACE(10, ("__kmp_get_schedule: thread %d\n", gtid));
3009 KMP_DEBUG_ASSERT(__kmp_init_serial);
3010
3011 thread = __kmp_threads[gtid];
3012
3013 th_type = thread->th.th_current_task->td_icvs.sched.r_sched_type;
3014 switch (SCHEDULE_WITHOUT_MODIFIERS(th_type)) {
3015 case kmp_sch_static:
3016 case kmp_sch_static_greedy:
3017 case kmp_sch_static_balanced:
3018 *kind = kmp_sched_static;
3019 __kmp_sched_apply_mods_stdkind(kind, th_type);
3020 *chunk = 0; // chunk was not set, try to show this fact via zero value
3021 return;
3022 case kmp_sch_static_chunked:
3023 *kind = kmp_sched_static;
3024 break;
3025 case kmp_sch_dynamic_chunked:
3026 *kind = kmp_sched_dynamic;
3027 break;
3029 case kmp_sch_guided_iterative_chunked:
3030 case kmp_sch_guided_analytical_chunked:
3031 *kind = kmp_sched_guided;
3032 break;
3033 case kmp_sch_auto:
3034 *kind = kmp_sched_auto;
3035 break;
3036 case kmp_sch_trapezoidal:
3037 *kind = kmp_sched_trapezoidal;
3038 break;
3039#if KMP_STATIC_STEAL_ENABLED
3040 case kmp_sch_static_steal:
3041 *kind = kmp_sched_static_steal;
3042 break;
3043#endif
3044 default:
3045 KMP_FATAL(UnknownSchedulingType, th_type);
3046 }
3047
3048 __kmp_sched_apply_mods_stdkind(kind, th_type);
3049 *chunk = thread->th.th_current_task->td_icvs.sched.chunk;
3050}
3051
3052int __kmp_get_ancestor_thread_num(int gtid, int level) {
3053
3054 int ii, dd;
3055 kmp_team_t *team;
3056 kmp_info_t *thr;
3057
3058 KF_TRACE(10, ("__kmp_get_ancestor_thread_num: thread %d %d\n", gtid, level));
3059 KMP_DEBUG_ASSERT(__kmp_init_serial);
3060
3061 // validate level
3062 if (level == 0)
3063 return 0;
3064 if (level < 0)
3065 return -1;
3066 thr = __kmp_threads[gtid];
3067 team = thr->th.th_team;
3068 ii = team->t.t_level;
3069 if (level > ii)
3070 return -1;
3071
3072 if (thr->th.th_teams_microtask) {
3073 // AC: we are in teams region where multiple nested teams have same level
3074 int tlevel = thr->th.th_teams_level; // the level of the teams construct
3075 if (level <=
3076 tlevel) { // otherwise usual algorithm works (will not touch the teams)
3077 KMP_DEBUG_ASSERT(ii >= tlevel);
3078 // AC: As we need to pass by the teams league, we need to artificially
3079 // increase ii
3080 if (ii == tlevel) {
3081 ii += 2; // three teams have same level
3082 } else {
3083 ii++; // two teams have same level
3084 }
3085 }
3086 }
3087
3088 if (ii == level)
3089 return __kmp_tid_from_gtid(gtid);
3090
3091 dd = team->t.t_serialized;
3092 level++;
3093 while (ii > level) {
3094 for (dd = team->t.t_serialized; (dd > 0) && (ii > level); dd--, ii--) {
3095 }
3096 if ((team->t.t_serialized) && (!dd)) {
3097 team = team->t.t_parent;
3098 continue;
3099 }
3100 if (ii > level) {
3101 team = team->t.t_parent;
3102 dd = team->t.t_serialized;
3103 ii--;
3104 }
3105 }
3106
3107 return (dd > 1) ? (0) : (team->t.t_master_tid);
3108}
3109
3110int __kmp_get_team_size(int gtid, int level) {
3111
3112 int ii, dd;
3113 kmp_team_t *team;
3114 kmp_info_t *thr;
3115
3116 KF_TRACE(10, ("__kmp_get_team_size: thread %d %d\n", gtid, level));
3117 KMP_DEBUG_ASSERT(__kmp_init_serial);
3118
3119 // validate level
3120 if (level == 0)
3121 return 1;
3122 if (level < 0)
3123 return -1;
3124 thr = __kmp_threads[gtid];
3125 team = thr->th.th_team;
3126 ii = team->t.t_level;
3127 if (level > ii)
3128 return -1;
3129
3130 if (thr->th.th_teams_microtask) {
3131 // AC: we are in teams region where multiple nested teams have same level
3132 int tlevel = thr->th.th_teams_level; // the level of the teams construct
3133 if (level <=
3134 tlevel) { // otherwise usual algorithm works (will not touch the teams)
3135 KMP_DEBUG_ASSERT(ii >= tlevel);
3136 // AC: As we need to pass by the teams league, we need to artificially
3137 // increase ii
3138 if (ii == tlevel) {
3139 ii += 2; // three teams have same level
3140 } else {
3141 ii++; // two teams have same level
3142 }
3143 }
3144 }
3145
3146 while (ii > level) {
3147 for (dd = team->t.t_serialized; (dd > 0) && (ii > level); dd--, ii--) {
3148 }
3149 if (team->t.t_serialized && (!dd)) {
3150 team = team->t.t_parent;
3151 continue;
3152 }
3153 if (ii > level) {
3154 team = team->t.t_parent;
3155 ii--;
3156 }
3157 }
3158
3159 return team->t.t_nproc;
3160}
3161
3162kmp_r_sched_t __kmp_get_schedule_global() {
3163 // This routine created because pairs (__kmp_sched, __kmp_chunk) and
3164 // (__kmp_static, __kmp_guided) may be changed by kmp_set_defaults
3165 // independently. So one can get the updated schedule here.
3166
3167 kmp_r_sched_t r_sched;
3168
3169 // create schedule from 4 globals: __kmp_sched, __kmp_chunk, __kmp_static,
3170 // __kmp_guided. __kmp_sched should keep original value, so that user can set
3171 // KMP_SCHEDULE multiple times, and thus have different run-time schedules in
3172 // different roots (even in OMP 2.5)
3173 enum sched_type s = SCHEDULE_WITHOUT_MODIFIERS(__kmp_sched);
3174 enum sched_type sched_modifiers = SCHEDULE_GET_MODIFIERS(__kmp_sched);
3175 if (s == kmp_sch_static) {
3176 // replace STATIC with more detailed schedule (balanced or greedy)
3177 r_sched.r_sched_type = __kmp_static;
3178 } else if (s == kmp_sch_guided_chunked) {
3179 // replace GUIDED with more detailed schedule (iterative or analytical)
3180 r_sched.r_sched_type = __kmp_guided;
3181 } else { // (STATIC_CHUNKED), or (DYNAMIC_CHUNKED), or other
3182 r_sched.r_sched_type = __kmp_sched;
3183 }
3184 SCHEDULE_SET_MODIFIERS(r_sched.r_sched_type, sched_modifiers);
3185
3186 if (__kmp_chunk < KMP_DEFAULT_CHUNK) {
3187 // __kmp_chunk may be wrong here (if it was not ever set)
3188 r_sched.chunk = KMP_DEFAULT_CHUNK;
3189 } else {
3190 r_sched.chunk = __kmp_chunk;
3191 }
3192
3193 return r_sched;
3194}
3195
3196/* Allocate (realloc == FALSE) * or reallocate (realloc == TRUE)
3197 at least argc number of *t_argv entries for the requested team. */
3198static void __kmp_alloc_argv_entries(int argc, kmp_team_t *team, int realloc) {
3199
3200 KMP_DEBUG_ASSERT(team);
3201 if (!realloc || argc > team->t.t_max_argc) {
3202
3203 KA_TRACE(100, ("__kmp_alloc_argv_entries: team %d: needed entries=%d, "
3204 "current entries=%d\n",
3205 team->t.t_id, argc, (realloc) ? team->t.t_max_argc : 0));
3206 /* if previously allocated heap space for args, free them */
3207 if (realloc && team->t.t_argv != &team->t.t_inline_argv[0])
3208 __kmp_free((void *)team->t.t_argv);
3209
3210 if (argc <= KMP_INLINE_ARGV_ENTRIES) {
3211 /* use unused space in the cache line for arguments */
3212 team->t.t_max_argc = KMP_INLINE_ARGV_ENTRIES;
3213 KA_TRACE(100, ("__kmp_alloc_argv_entries: team %d: inline allocate %d "
3214 "argv entries\n",
3215 team->t.t_id, team->t.t_max_argc));
3216 team->t.t_argv = &team->t.t_inline_argv[0];
3217 if (__kmp_storage_map) {
3218 __kmp_print_storage_map_gtid(
3219 -1, &team->t.t_inline_argv[0],
3220 &team->t.t_inline_argv[KMP_INLINE_ARGV_ENTRIES],
3221 (sizeof(void *) * KMP_INLINE_ARGV_ENTRIES), "team_%d.t_inline_argv",
3222 team->t.t_id);
3223 }
3224 } else {
3225 /* allocate space for arguments in the heap */
3226 team->t.t_max_argc = (argc <= (KMP_MIN_MALLOC_ARGV_ENTRIES >> 1))
3227 ? KMP_MIN_MALLOC_ARGV_ENTRIES
3228 : 2 * argc;
3229 KA_TRACE(100, ("__kmp_alloc_argv_entries: team %d: dynamic allocate %d "
3230 "argv entries\n",
3231 team->t.t_id, team->t.t_max_argc));
3232 team->t.t_argv =
3233 (void **)__kmp_page_allocate(sizeof(void *) * team->t.t_max_argc);
3234 if (__kmp_storage_map) {
3235 __kmp_print_storage_map_gtid(-1, &team->t.t_argv[0],
3236 &team->t.t_argv[team->t.t_max_argc],
3237 sizeof(void *) * team->t.t_max_argc,
3238 "team_%d.t_argv", team->t.t_id);
3239 }
3240 }
3241 }
3242}
3243
3244static void __kmp_allocate_team_arrays(kmp_team_t *team, int max_nth) {
3245 int i;
3246 int num_disp_buff = max_nth > 1 ? __kmp_dispatch_num_buffers : 2;
3247 team->t.t_threads =
3248 (kmp_info_t **)__kmp_allocate(sizeof(kmp_info_t *) * max_nth);
3249 team->t.t_disp_buffer = (dispatch_shared_info_t *)__kmp_allocate(
3250 sizeof(dispatch_shared_info_t) * num_disp_buff);
3251 team->t.t_dispatch =
3252 (kmp_disp_t *)__kmp_allocate(sizeof(kmp_disp_t) * max_nth);
3253 team->t.t_implicit_task_taskdata =
3254 (kmp_taskdata_t *)__kmp_allocate(sizeof(kmp_taskdata_t) * max_nth);
3255 team->t.t_max_nproc = max_nth;
3256
3257 /* setup dispatch buffers */
3258 for (i = 0; i < num_disp_buff; ++i) {
3259 team->t.t_disp_buffer[i].buffer_index = i;
3260 team->t.t_disp_buffer[i].doacross_buf_idx = i;
3261 }
3262}
3263
3264static void __kmp_free_team_arrays(kmp_team_t *team) {
3265 /* Note: this does not free the threads in t_threads (__kmp_free_threads) */
3266 int i;
3267 for (i = 0; i < team->t.t_max_nproc; ++i) {
3268 if (team->t.t_dispatch[i].th_disp_buffer != NULL) {
3269 __kmp_free(team->t.t_dispatch[i].th_disp_buffer);
3270 team->t.t_dispatch[i].th_disp_buffer = NULL;
3271 }
3272 }
3273#if KMP_USE_HIER_SCHED
3274 __kmp_dispatch_free_hierarchies(team);
3275#endif
3276 __kmp_free(team->t.t_threads);
3277 __kmp_free(team->t.t_disp_buffer);
3278 __kmp_free(team->t.t_dispatch);
3279 __kmp_free(team->t.t_implicit_task_taskdata);
3280 team->t.t_threads = NULL;
3281 team->t.t_disp_buffer = NULL;
3282 team->t.t_dispatch = NULL;
3283 team->t.t_implicit_task_taskdata = 0;
3284}
3285
3286static void __kmp_reallocate_team_arrays(kmp_team_t *team, int max_nth) {
3287 kmp_info_t **oldThreads = team->t.t_threads;
3288
3289 __kmp_free(team->t.t_disp_buffer);
3290 __kmp_free(team->t.t_dispatch);
3291 __kmp_free(team->t.t_implicit_task_taskdata);
3292 __kmp_allocate_team_arrays(team, max_nth);
3293
3294 KMP_MEMCPY(team->t.t_threads, oldThreads,
3295 team->t.t_nproc * sizeof(kmp_info_t *));
3296
3297 __kmp_free(oldThreads);
3298}
3299
3300static kmp_internal_control_t __kmp_get_global_icvs(void) {
3301
3302 kmp_r_sched_t r_sched =
3303 __kmp_get_schedule_global(); // get current state of scheduling globals
3304
3305 KMP_DEBUG_ASSERT(__kmp_nested_proc_bind.used > 0);
3306
3307 kmp_internal_control_t g_icvs = {
3308 0, // int serial_nesting_level; //corresponds to value of th_team_serialized
3309 (kmp_int8)__kmp_global.g.g_dynamic, // internal control for dynamic
3310 // adjustment of threads (per thread)
3311 (kmp_int8)__kmp_env_blocktime, // int bt_set; //internal control for
3312 // whether blocktime is explicitly set
3313 __kmp_dflt_blocktime, // int blocktime; //internal control for blocktime
3314#if KMP_USE_MONITOR
3315 __kmp_bt_intervals, // int bt_intervals; //internal control for blocktime
3316// intervals
3317#endif
3318 __kmp_dflt_team_nth, // int nproc; //internal control for # of threads for
3319 // next parallel region (per thread)
3320 // (use a max ub on value if __kmp_parallel_initialize not called yet)
3321 __kmp_cg_max_nth, // int thread_limit;
3322 __kmp_task_max_nth, // int task_thread_limit; // to set the thread_limit
3323 // on task. This is used in the case of target thread_limit
3324 __kmp_dflt_max_active_levels, // int max_active_levels; //internal control
3325 // for max_active_levels
3326 r_sched, // kmp_r_sched_t sched; //internal control for runtime schedule
3327 // {sched,chunk} pair
3328 __kmp_nested_proc_bind.bind_types[0],
3329 __kmp_default_device,
3330 NULL // struct kmp_internal_control *next;
3331 };
3332
3333 return g_icvs;
3334}
3335
3336static kmp_internal_control_t __kmp_get_x_global_icvs(const kmp_team_t *team) {
3337
3338 kmp_internal_control_t gx_icvs;
3339 gx_icvs.serial_nesting_level =
3340 0; // probably =team->t.t_serial like in save_inter_controls
3341 copy_icvs(&gx_icvs, &team->t.t_threads[0]->th.th_current_task->td_icvs);
3342 gx_icvs.next = NULL;
3343
3344 return gx_icvs;
3345}
3346
3347static void __kmp_initialize_root(kmp_root_t *root) {
3348 int f;
3349 kmp_team_t *root_team;
3350 kmp_team_t *hot_team;
3351 int hot_team_max_nth;
3352 kmp_r_sched_t r_sched =
3353 __kmp_get_schedule_global(); // get current state of scheduling globals
3354 kmp_internal_control_t r_icvs = __kmp_get_global_icvs();
3355 KMP_DEBUG_ASSERT(root);
3356 KMP_ASSERT(!root->r.r_begin);
3357
3358 /* setup the root state structure */
3359 __kmp_init_lock(&root->r.r_begin_lock);
3360 root->r.r_begin = FALSE;
3361 root->r.r_active = FALSE;
3362 root->r.r_in_parallel = 0;
3363 root->r.r_blocktime = __kmp_dflt_blocktime;
3364#if KMP_AFFINITY_SUPPORTED
3365 root->r.r_affinity_assigned = FALSE;
3366#endif
3367
3368 /* setup the root team for this task */
3369 /* allocate the root team structure */
3370 KF_TRACE(10, ("__kmp_initialize_root: before root_team\n"));
3371
3372 root_team = __kmp_allocate_team(root,
3373 1, // new_nproc
3374 1, // max_nproc
3375#if OMPT_SUPPORT
3376 ompt_data_none, // root parallel id
3377#endif
3378 __kmp_nested_proc_bind.bind_types[0], &r_icvs,
3379 0, // argc
3380 NULL // primary thread is unknown
3381 );
3382#if USE_DEBUGGER
3383 // Non-NULL value should be assigned to make the debugger display the root
3384 // team.
3385 TCW_SYNC_PTR(root_team->t.t_pkfn, (microtask_t)(~0));
3386#endif
3387
3388 KF_TRACE(10, ("__kmp_initialize_root: after root_team = %p\n", root_team));
3389
3390 root->r.r_root_team = root_team;
3391 root_team->t.t_control_stack_top = NULL;
3392
3393 /* initialize root team */
3394 root_team->t.t_threads[0] = NULL;
3395 root_team->t.t_nproc = 1;
3396 root_team->t.t_serialized = 1;
3397 // TODO???: root_team->t.t_max_active_levels = __kmp_dflt_max_active_levels;
3398 root_team->t.t_sched.sched = r_sched.sched;
3399 root_team->t.t_nested_nth = &__kmp_nested_nth;
3400 KA_TRACE(
3401 20,
3402 ("__kmp_initialize_root: init root team %d arrived: join=%u, plain=%u\n",
3403 root_team->t.t_id, KMP_INIT_BARRIER_STATE, KMP_INIT_BARRIER_STATE));
3404
3405 /* setup the hot team for this task */
3406 /* allocate the hot team structure */
3407 KF_TRACE(10, ("__kmp_initialize_root: before hot_team\n"));
3408
3409 hot_team = __kmp_allocate_team(root,
3410 1, // new_nproc
3411 __kmp_dflt_team_nth_ub * 2, // max_nproc
3412#if OMPT_SUPPORT
3413 ompt_data_none, // root parallel id
3414#endif
3415 __kmp_nested_proc_bind.bind_types[0], &r_icvs,
3416 0, // argc
3417 NULL // primary thread is unknown
3418 );
3419 KF_TRACE(10, ("__kmp_initialize_root: after hot_team = %p\n", hot_team));
3420
3421 root->r.r_hot_team = hot_team;
3422 root_team->t.t_control_stack_top = NULL;
3423
3424 /* first-time initialization */
3425 hot_team->t.t_parent = root_team;
3426
3427 /* initialize hot team */
3428 hot_team_max_nth = hot_team->t.t_max_nproc;
3429 for (f = 0; f < hot_team_max_nth; ++f) {
3430 hot_team->t.t_threads[f] = NULL;
3431 }
3432 hot_team->t.t_nproc = 1;
3433 // TODO???: hot_team->t.t_max_active_levels = __kmp_dflt_max_active_levels;
3434 hot_team->t.t_sched.sched = r_sched.sched;
3435 hot_team->t.t_size_changed = 0;
3436 hot_team->t.t_nested_nth = &__kmp_nested_nth;
3437}
3438
3439#ifdef KMP_DEBUG
3440
3441typedef struct kmp_team_list_item {
3442 kmp_team_p const *entry;
3443 struct kmp_team_list_item *next;
3444} kmp_team_list_item_t;
3445typedef kmp_team_list_item_t *kmp_team_list_t;
3446
3447static void __kmp_print_structure_team_accum( // Add team to list of teams.
3448 kmp_team_list_t list, // List of teams.
3449 kmp_team_p const *team // Team to add.
3450) {
3451
3452 // List must terminate with item where both entry and next are NULL.
3453 // Team is added to the list only once.
3454 // List is sorted in ascending order by team id.
3455 // Team id is *not* a key.
3456
3457 kmp_team_list_t l;
3458
3459 KMP_DEBUG_ASSERT(list != NULL);
3460 if (team == NULL) {
3461 return;
3462 }
3463
3464 __kmp_print_structure_team_accum(list, team->t.t_parent);
3465 __kmp_print_structure_team_accum(list, team->t.t_next_pool);
3466
3467 // Search list for the team.
3468 l = list;
3469 while (l->next != NULL && l->entry != team) {
3470 l = l->next;
3471 }
3472 if (l->next != NULL) {
3473 return; // Team has been added before, exit.
3474 }
3475
3476 // Team is not found. Search list again for insertion point.
3477 l = list;
3478 while (l->next != NULL && l->entry->t.t_id <= team->t.t_id) {
3479 l = l->next;
3480 }
3481
3482 // Insert team.
3483 {
3484 kmp_team_list_item_t *item = (kmp_team_list_item_t *)KMP_INTERNAL_MALLOC(
3485 sizeof(kmp_team_list_item_t));
3486 *item = *l;
3487 l->entry = team;
3488 l->next = item;
3489 }
3490}
3491
3492static void __kmp_print_structure_team(char const *title, kmp_team_p const *team
3493
3494) {
3495 __kmp_printf("%s", title);
3496 if (team != NULL) {
3497 __kmp_printf("%2x %p\n", team->t.t_id, team);
3498 } else {
3499 __kmp_printf(" - (nil)\n");
3500 }
3501}
3502
3503static void __kmp_print_structure_thread(char const *title,
3504 kmp_info_p const *thread) {
3505 __kmp_printf("%s", title);
3506 if (thread != NULL) {
3507 __kmp_printf("%2d %p\n", thread->th.th_info.ds.ds_gtid, thread);
3508 } else {
3509 __kmp_printf(" - (nil)\n");
3510 }
3511}
3512
3513void __kmp_print_structure(void) {
3514
3515 kmp_team_list_t list;
3516
3517 // Initialize list of teams.
3518 list =
3519 (kmp_team_list_item_t *)KMP_INTERNAL_MALLOC(sizeof(kmp_team_list_item_t));
3520 list->entry = NULL;
3521 list->next = NULL;
3522
3523 __kmp_printf("\n------------------------------\nGlobal Thread "
3524 "Table\n------------------------------\n");
3525 {
3526 int gtid;
3527 for (gtid = 0; gtid < __kmp_threads_capacity; ++gtid) {
3528 __kmp_printf("%2d", gtid);
3529 if (__kmp_threads != NULL) {
3530 __kmp_printf(" %p", __kmp_threads[gtid]);
3531 }
3532 if (__kmp_root != NULL) {
3533 __kmp_printf(" %p", __kmp_root[gtid]);
3534 }
3535 __kmp_printf("\n");
3536 }
3537 }
3538
3539 // Print out __kmp_threads array.
3540 __kmp_printf("\n------------------------------\nThreads\n--------------------"
3541 "----------\n");
3542 if (__kmp_threads != NULL) {
3543 int gtid;
3544 for (gtid = 0; gtid < __kmp_threads_capacity; ++gtid) {
3545 kmp_info_t const *thread = __kmp_threads[gtid];
3546 if (thread != NULL) {
3547 __kmp_printf("GTID %2d %p:\n", gtid, thread);
3548 __kmp_printf(" Our Root: %p\n", thread->th.th_root);
3549 __kmp_print_structure_team(" Our Team: ", thread->th.th_team);
3550 __kmp_print_structure_team(" Serial Team: ",
3551 thread->th.th_serial_team);
3552 __kmp_printf(" Threads: %2d\n", thread->th.th_team_nproc);
3553 __kmp_print_structure_thread(" Primary: ",
3554 thread->th.th_team_master);
3555 __kmp_printf(" Serialized?: %2d\n", thread->th.th_team_serialized);
3556 __kmp_printf(" Set NProc: %2d\n", thread->th.th_set_nproc);
3557 __kmp_printf(" Set Proc Bind: %2d\n", thread->th.th_set_proc_bind);
3558 __kmp_print_structure_thread(" Next in pool: ",
3559 thread->th.th_next_pool);
3560 __kmp_printf("\n");
3561 __kmp_print_structure_team_accum(list, thread->th.th_team);
3562 __kmp_print_structure_team_accum(list, thread->th.th_serial_team);
3563 }
3564 }
3565 } else {
3566 __kmp_printf("Threads array is not allocated.\n");
3567 }
3568
3569 // Print out __kmp_root array.
3570 __kmp_printf("\n------------------------------\nUbers\n----------------------"
3571 "--------\n");
3572 if (__kmp_root != NULL) {
3573 int gtid;
3574 for (gtid = 0; gtid < __kmp_threads_capacity; ++gtid) {
3575 kmp_root_t const *root = __kmp_root[gtid];
3576 if (root != NULL) {
3577 __kmp_printf("GTID %2d %p:\n", gtid, root);
3578 __kmp_print_structure_team(" Root Team: ", root->r.r_root_team);
3579 __kmp_print_structure_team(" Hot Team: ", root->r.r_hot_team);
3580 __kmp_print_structure_thread(" Uber Thread: ",
3581 root->r.r_uber_thread);
3582 __kmp_printf(" Active?: %2d\n", root->r.r_active);
3583 __kmp_printf(" In Parallel: %2d\n",
3584 KMP_ATOMIC_LD_RLX(&root->r.r_in_parallel));
3585 __kmp_printf("\n");
3586 __kmp_print_structure_team_accum(list, root->r.r_root_team);
3587 __kmp_print_structure_team_accum(list, root->r.r_hot_team);
3588 }
3589 }
3590 } else {
3591 __kmp_printf("Ubers array is not allocated.\n");
3592 }
3593
3594 __kmp_printf("\n------------------------------\nTeams\n----------------------"
3595 "--------\n");
3596 while (list->next != NULL) {
3597 kmp_team_p const *team = list->entry;
3598 int i;
3599 __kmp_printf("Team %2x %p:\n", team->t.t_id, team);
3600 __kmp_print_structure_team(" Parent Team: ", team->t.t_parent);
3601 __kmp_printf(" Primary TID: %2d\n", team->t.t_master_tid);
3602 __kmp_printf(" Max threads: %2d\n", team->t.t_max_nproc);
3603 __kmp_printf(" Levels of serial: %2d\n", team->t.t_serialized);
3604 __kmp_printf(" Number threads: %2d\n", team->t.t_nproc);
3605 for (i = 0; i < team->t.t_nproc; ++i) {
3606 __kmp_printf(" Thread %2d: ", i);
3607 __kmp_print_structure_thread("", team->t.t_threads[i]);
3608 }
3609 __kmp_print_structure_team(" Next in pool: ", team->t.t_next_pool);
3610 __kmp_printf("\n");
3611 list = list->next;
3612 }
3613
3614 // Print out __kmp_thread_pool and __kmp_team_pool.
3615 __kmp_printf("\n------------------------------\nPools\n----------------------"
3616 "--------\n");
3617 __kmp_print_structure_thread("Thread pool: ",
3618 CCAST(kmp_info_t *, __kmp_thread_pool));
3619 __kmp_print_structure_team("Team pool: ",
3620 CCAST(kmp_team_t *, __kmp_team_pool));
3621 __kmp_printf("\n");
3622
3623 // Free team list.
3624 while (list != NULL) {
3625 kmp_team_list_item_t *item = list;
3626 list = list->next;
3627 KMP_INTERNAL_FREE(item);
3628 }
3629}
3630
3631#endif
3632
3633//---------------------------------------------------------------------------
3634// Stuff for per-thread fast random number generator
3635// Table of primes
3636static const unsigned __kmp_primes[] = {
3637 0x9e3779b1, 0xffe6cc59, 0x2109f6dd, 0x43977ab5, 0xba5703f5, 0xb495a877,
3638 0xe1626741, 0x79695e6b, 0xbc98c09f, 0xd5bee2b3, 0x287488f9, 0x3af18231,
3639 0x9677cd4d, 0xbe3a6929, 0xadc6a877, 0xdcf0674b, 0xbe4d6fe9, 0x5f15e201,
3640 0x99afc3fd, 0xf3f16801, 0xe222cfff, 0x24ba5fdb, 0x0620452d, 0x79f149e3,
3641 0xc8b93f49, 0x972702cd, 0xb07dd827, 0x6c97d5ed, 0x085a3d61, 0x46eb5ea7,
3642 0x3d9910ed, 0x2e687b5b, 0x29609227, 0x6eb081f1, 0x0954c4e1, 0x9d114db9,
3643 0x542acfa9, 0xb3e6bd7b, 0x0742d917, 0xe9f3ffa7, 0x54581edb, 0xf2480f45,
3644 0x0bb9288f, 0xef1affc7, 0x85fa0ca7, 0x3ccc14db, 0xe6baf34b, 0x343377f7,
3645 0x5ca19031, 0xe6d9293b, 0xf0a9f391, 0x5d2e980b, 0xfc411073, 0xc3749363,
3646 0xb892d829, 0x3549366b, 0x629750ad, 0xb98294e5, 0x892d9483, 0xc235baf3,
3647 0x3d2402a3, 0x6bdef3c9, 0xbec333cd, 0x40c9520f};
3648
3649//---------------------------------------------------------------------------
3650// __kmp_get_random: Get a random number using a linear congruential method.
3651unsigned short __kmp_get_random(kmp_info_t *thread) {
3652 unsigned x = thread->th.th_x;
3653 unsigned short r = (unsigned short)(x >> 16);
3654
3655 thread->th.th_x = x * thread->th.th_a + 1;
3656
3657 KA_TRACE(30, ("__kmp_get_random: THREAD: %d, RETURN: %u\n",
3658 thread->th.th_info.ds.ds_tid, r));
3659
3660 return r;
3661}
3662//--------------------------------------------------------
3663// __kmp_init_random: Initialize a random number generator
3664void __kmp_init_random(kmp_info_t *thread) {
3665 unsigned seed = thread->th.th_info.ds.ds_tid;
3666
3667 thread->th.th_a =
3668 __kmp_primes[seed % (sizeof(__kmp_primes) / sizeof(__kmp_primes[0]))];
3669 thread->th.th_x = (seed + 1) * thread->th.th_a + 1;
3670 KA_TRACE(30,
3671 ("__kmp_init_random: THREAD: %u; A: %u\n", seed, thread->th.th_a));
3672}
3673
3674#if KMP_OS_WINDOWS
3675/* reclaim array entries for root threads that are already dead, returns number
3676 * reclaimed */
3677static int __kmp_reclaim_dead_roots(void) {
3678 int i, r = 0;
3679
3680 for (i = 0; i < __kmp_threads_capacity; ++i) {
3681 if (KMP_UBER_GTID(i) &&
3682 !__kmp_still_running((kmp_info_t *)TCR_SYNC_PTR(__kmp_threads[i])) &&
3683 !__kmp_root[i]
3684 ->r.r_active) { // AC: reclaim only roots died in non-active state
3685 r += __kmp_unregister_root_other_thread(i);
3686 }
3687 }
3688 return r;
3689}
3690#endif
3691
3692/* This function attempts to create free entries in __kmp_threads and
3693 __kmp_root, and returns the number of free entries generated.
3694
3695 For Windows* OS static library, the first mechanism used is to reclaim array
3696 entries for root threads that are already dead.
3697
3698 On all platforms, expansion is attempted on the arrays __kmp_threads_ and
3699 __kmp_root, with appropriate update to __kmp_threads_capacity. Array
3700 capacity is increased by doubling with clipping to __kmp_tp_capacity, if
3701 threadprivate cache array has been created. Synchronization with
3702 __kmpc_threadprivate_cached is done using __kmp_tp_cached_lock.
3703
3704 After any dead root reclamation, if the clipping value allows array expansion
3705 to result in the generation of a total of nNeed free slots, the function does
3706 that expansion. If not, nothing is done beyond the possible initial root
3707 thread reclamation.
3708
3709 If any argument is negative, the behavior is undefined. */
3710static int __kmp_expand_threads(int nNeed) {
3711 int added = 0;
3712 int minimumRequiredCapacity;
3713 int newCapacity;
3714 kmp_info_t **newThreads;
3715 kmp_root_t **newRoot;
3716
3717 // All calls to __kmp_expand_threads should be under __kmp_forkjoin_lock, so
3718 // resizing __kmp_threads does not need additional protection if foreign
3719 // threads are present
3720
3721#if KMP_OS_WINDOWS && !KMP_DYNAMIC_LIB
3722 /* only for Windows static library */
3723 /* reclaim array entries for root threads that are already dead */
3724 added = __kmp_reclaim_dead_roots();
3725
3726 if (nNeed) {
3727 nNeed -= added;
3728 if (nNeed < 0)
3729 nNeed = 0;
3730 }
3731#endif
3732 if (nNeed <= 0)
3733 return added;
3734
3735 // Note that __kmp_threads_capacity is not bounded by __kmp_max_nth. If
3736 // __kmp_max_nth is set to some value less than __kmp_sys_max_nth by the
3737 // user via KMP_DEVICE_THREAD_LIMIT, then __kmp_threads_capacity may become
3738 // > __kmp_max_nth in one of two ways:
3739 //
3740 // 1) The initialization thread (gtid = 0) exits. __kmp_threads[0]
3741 // may not be reused by another thread, so we may need to increase
3742 // __kmp_threads_capacity to __kmp_max_nth + 1.
3743 //
3744 // 2) New foreign root(s) are encountered. We always register new foreign
3745 // roots. This may cause a smaller # of threads to be allocated at
3746 // subsequent parallel regions, but the worker threads hang around (and
3747 // eventually go to sleep) and need slots in the __kmp_threads[] array.
3748 //
3749 // Anyway, that is the reason for moving the check to see if
3750 // __kmp_max_nth was exceeded into __kmp_reserve_threads()
3751 // instead of having it performed here. -BB
3752
3753 KMP_DEBUG_ASSERT(__kmp_sys_max_nth >= __kmp_threads_capacity);
3754
3755 /* compute expansion headroom to check if we can expand */
3756 if (__kmp_sys_max_nth - __kmp_threads_capacity < nNeed) {
3757 /* possible expansion too small -- give up */
3758 return added;
3759 }
3760 minimumRequiredCapacity = __kmp_threads_capacity + nNeed;
3761
3762 newCapacity = __kmp_threads_capacity;
3763 do {
3764 newCapacity = newCapacity <= (__kmp_sys_max_nth >> 1) ? (newCapacity << 1)
3765 : __kmp_sys_max_nth;
3766 } while (newCapacity < minimumRequiredCapacity);
3767 newThreads = (kmp_info_t **)__kmp_allocate(
3768 (sizeof(kmp_info_t *) + sizeof(kmp_root_t *)) * newCapacity + CACHE_LINE);
3769 newRoot =
3770 (kmp_root_t **)((char *)newThreads + sizeof(kmp_info_t *) * newCapacity);
3771 KMP_MEMCPY(newThreads, __kmp_threads,
3772 __kmp_threads_capacity * sizeof(kmp_info_t *));
3773 KMP_MEMCPY(newRoot, __kmp_root,
3774 __kmp_threads_capacity * sizeof(kmp_root_t *));
3775 // Put old __kmp_threads array on a list. Any ongoing references to the old
3776 // list will be valid. This list is cleaned up at library shutdown.
3777 kmp_old_threads_list_t *node =
3778 (kmp_old_threads_list_t *)__kmp_allocate(sizeof(kmp_old_threads_list_t));
3779 node->threads = __kmp_threads;
3780 node->next = __kmp_old_threads_list;
3781 __kmp_old_threads_list = node;
3782
3783 *(kmp_info_t * *volatile *)&__kmp_threads = newThreads;
3784 *(kmp_root_t * *volatile *)&__kmp_root = newRoot;
3785 added += newCapacity - __kmp_threads_capacity;
3786 *(volatile int *)&__kmp_threads_capacity = newCapacity;
3787
3788 if (newCapacity > __kmp_tp_capacity) {
3789 __kmp_acquire_bootstrap_lock(&__kmp_tp_cached_lock);
3790 if (__kmp_tp_cached && newCapacity > __kmp_tp_capacity) {
3791 __kmp_threadprivate_resize_cache(newCapacity);
3792 } else { // increase __kmp_tp_capacity to correspond with kmp_threads size
3793 *(volatile int *)&__kmp_tp_capacity = newCapacity;
3794 }
3795 __kmp_release_bootstrap_lock(&__kmp_tp_cached_lock);
3796 }
3797
3798 return added;
3799}
3800
3801/* Register the current thread as a root thread and obtain our gtid. We must
3802 have the __kmp_initz_lock held at this point. Argument TRUE only if are the
3803 thread that calls from __kmp_do_serial_initialize() */
3804int __kmp_register_root(int initial_thread) {
3805 kmp_info_t *root_thread;
3806 kmp_root_t *root;
3807 int gtid;
3808 int capacity;
3809 __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
3810 KA_TRACE(20, ("__kmp_register_root: entered\n"));
3811 KMP_MB();
3812
3813 /* 2007-03-02:
3814 If initial thread did not invoke OpenMP RTL yet, and this thread is not an
3815 initial one, "__kmp_all_nth >= __kmp_threads_capacity" condition does not
3816 work as expected -- it may return false (that means there is at least one
3817 empty slot in __kmp_threads array), but it is possible the only free slot
3818 is #0, which is reserved for initial thread and so cannot be used for this
3819 one. Following code workarounds this bug.
3820
3821 However, right solution seems to be not reserving slot #0 for initial
3822 thread because:
3823 (1) there is no magic in slot #0,
3824 (2) we cannot detect initial thread reliably (the first thread which does
3825 serial initialization may be not a real initial thread).
3826 */
3827 capacity = __kmp_threads_capacity;
3828 if (!initial_thread && TCR_PTR(__kmp_threads[0]) == NULL) {
3829 --capacity;
3830 }
3831
3832 // If it is not for initializing the hidden helper team, we need to take
3833 // __kmp_hidden_helper_threads_num out of the capacity because it is included
3834 // in __kmp_threads_capacity.
3835 if (__kmp_enable_hidden_helper && !TCR_4(__kmp_init_hidden_helper_threads)) {
3836 capacity -= __kmp_hidden_helper_threads_num;
3837 }
3838
3839 /* see if there are too many threads */
3840 if (__kmp_all_nth >= capacity && !__kmp_expand_threads(1)) {
3841 if (__kmp_tp_cached) {
3842 __kmp_fatal(KMP_MSG(CantRegisterNewThread),
3843 KMP_HNT(Set_ALL_THREADPRIVATE, __kmp_tp_capacity),
3844 KMP_HNT(PossibleSystemLimitOnThreads), __kmp_msg_null);
3845 } else {
3846 __kmp_fatal(KMP_MSG(CantRegisterNewThread), KMP_HNT(SystemLimitOnThreads),
3847 __kmp_msg_null);
3848 }
3849 }
3850
3851 // When hidden helper task is enabled, __kmp_threads is organized as follows:
3852 // 0: initial thread, also a regular OpenMP thread.
3853 // [1, __kmp_hidden_helper_threads_num]: slots for hidden helper threads.
3854 // [__kmp_hidden_helper_threads_num + 1, __kmp_threads_capacity): slots for
3855 // regular OpenMP threads.
3856 if (TCR_4(__kmp_init_hidden_helper_threads)) {
3857 // Find an available thread slot for hidden helper thread. Slots for hidden
3858 // helper threads start from 1 to __kmp_hidden_helper_threads_num.
3859 for (gtid = 1; TCR_PTR(__kmp_threads[gtid]) != NULL &&
3860 gtid <= __kmp_hidden_helper_threads_num;
3861 gtid++)
3862 ;
3863 KMP_ASSERT(gtid <= __kmp_hidden_helper_threads_num);
3864 KA_TRACE(1, ("__kmp_register_root: found slot in threads array for "
3865 "hidden helper thread: T#%d\n",
3866 gtid));
3867 } else {
3868 /* find an available thread slot */
3869 // Don't reassign the zero slot since we need that to only be used by
3870 // initial thread. Slots for hidden helper threads should also be skipped.
3871 if (initial_thread && TCR_PTR(__kmp_threads[0]) == NULL) {
3872 gtid = 0;
3873 } else {
3874 for (gtid = __kmp_hidden_helper_threads_num + 1;
3875 TCR_PTR(__kmp_threads[gtid]) != NULL; gtid++)
3876 ;
3877 }
3878 KA_TRACE(
3879 1, ("__kmp_register_root: found slot in threads array: T#%d\n", gtid));
3880 KMP_ASSERT(gtid < __kmp_threads_capacity);
3881 }
3882
3883 /* update global accounting */
3884 __kmp_all_nth++;
3885 TCW_4(__kmp_nth, __kmp_nth + 1);
3886
3887 // if __kmp_adjust_gtid_mode is set, then we use method #1 (sp search) for low
3888 // numbers of procs, and method #2 (keyed API call) for higher numbers.
3889 if (__kmp_adjust_gtid_mode) {
3890 if (__kmp_all_nth >= __kmp_tls_gtid_min) {
3891 if (TCR_4(__kmp_gtid_mode) != 2) {
3892 TCW_4(__kmp_gtid_mode, 2);
3893 }
3894 } else {
3895 if (TCR_4(__kmp_gtid_mode) != 1) {
3896 TCW_4(__kmp_gtid_mode, 1);
3897 }
3898 }
3899 }
3900
3901#ifdef KMP_ADJUST_BLOCKTIME
3902 /* Adjust blocktime to zero if necessary */
3903 /* Middle initialization might not have occurred yet */
3904 if (!__kmp_env_blocktime && (__kmp_avail_proc > 0)) {
3905 if (__kmp_nth > __kmp_avail_proc) {
3906 __kmp_zero_bt = TRUE;
3907 }
3908 }
3909#endif /* KMP_ADJUST_BLOCKTIME */
3910
3911 /* setup this new hierarchy */
3912 if (!(root = __kmp_root[gtid])) {
3913 root = __kmp_root[gtid] = (kmp_root_t *)__kmp_allocate(sizeof(kmp_root_t));
3914 KMP_DEBUG_ASSERT(!root->r.r_root_team);
3915 }
3916
3917#if KMP_STATS_ENABLED
3918 // Initialize stats as soon as possible (right after gtid assignment).
3919 __kmp_stats_thread_ptr = __kmp_stats_list->push_back(gtid);
3920 __kmp_stats_thread_ptr->startLife();
3921 KMP_SET_THREAD_STATE(SERIAL_REGION);
3922 KMP_INIT_PARTITIONED_TIMERS(OMP_serial);
3923#endif
3924 __kmp_initialize_root(root);
3925
3926 /* setup new root thread structure */
3927 if (root->r.r_uber_thread) {
3928 root_thread = root->r.r_uber_thread;
3929 } else {
3930 root_thread = (kmp_info_t *)__kmp_allocate(sizeof(kmp_info_t));
3931 if (__kmp_storage_map) {
3932 __kmp_print_thread_storage_map(root_thread, gtid);
3933 }
3934 root_thread->th.th_info.ds.ds_gtid = gtid;
3935#if OMPT_SUPPORT
3936 root_thread->th.ompt_thread_info.thread_data = ompt_data_none;
3937#endif
3938 root_thread->th.th_root = root;
3939 if (__kmp_env_consistency_check) {
3940 root_thread->th.th_cons = __kmp_allocate_cons_stack(gtid);
3941 }
3942#if USE_FAST_MEMORY
3943 __kmp_initialize_fast_memory(root_thread);
3944#endif /* USE_FAST_MEMORY */
3945
3946#if KMP_USE_BGET
3947 KMP_DEBUG_ASSERT(root_thread->th.th_local.bget_data == NULL);
3948 __kmp_initialize_bget(root_thread);
3949#endif
3950 __kmp_init_random(root_thread); // Initialize random number generator
3951 }
3952
3953 /* setup the serial team held in reserve by the root thread */
3954 if (!root_thread->th.th_serial_team) {
3955 kmp_internal_control_t r_icvs = __kmp_get_global_icvs();
3956 KF_TRACE(10, ("__kmp_register_root: before serial_team\n"));
3957 root_thread->th.th_serial_team =
3958 __kmp_allocate_team(root, 1, 1,
3959#if OMPT_SUPPORT
3960 ompt_data_none, // root parallel id
3961#endif
3962 proc_bind_default, &r_icvs, 0, NULL);
3963 }
3964 KMP_ASSERT(root_thread->th.th_serial_team);
3965 KF_TRACE(10, ("__kmp_register_root: after serial_team = %p\n",
3966 root_thread->th.th_serial_team));
3967
3968 /* drop root_thread into place */
3969 TCW_SYNC_PTR(__kmp_threads[gtid], root_thread);
3970
3971 root->r.r_root_team->t.t_threads[0] = root_thread;
3972 root->r.r_hot_team->t.t_threads[0] = root_thread;
3973 root_thread->th.th_serial_team->t.t_threads[0] = root_thread;
3974 // AC: the team created in reserve, not for execution (it is unused for now).
3975 root_thread->th.th_serial_team->t.t_serialized = 0;
3976 root->r.r_uber_thread = root_thread;
3977
3978 /* initialize the thread, get it ready to go */
3979 __kmp_initialize_info(root_thread, root->r.r_root_team, 0, gtid);
3980 TCW_4(__kmp_init_gtid, TRUE);
3981
3982 /* prepare the primary thread for get_gtid() */
3983 __kmp_gtid_set_specific(gtid);
3984
3985#if USE_ITT_BUILD
3986 __kmp_itt_thread_name(gtid);
3987#endif /* USE_ITT_BUILD */
3988
3989#ifdef KMP_TDATA_GTID
3990 __kmp_gtid = gtid;
3991#endif
3992 __kmp_create_worker(gtid, root_thread, __kmp_stksize);
3993 KMP_DEBUG_ASSERT(__kmp_gtid_get_specific() == gtid);
3994
3995 KA_TRACE(20, ("__kmp_register_root: T#%d init T#%d(%d:%d) arrived: join=%u, "
3996 "plain=%u\n",
3997 gtid, __kmp_gtid_from_tid(0, root->r.r_hot_team),
3998 root->r.r_hot_team->t.t_id, 0, KMP_INIT_BARRIER_STATE,
3999 KMP_INIT_BARRIER_STATE));
4000 { // Initialize barrier data.
4001 int b;
4002 for (b = 0; b < bs_last_barrier; ++b) {
4003 root_thread->th.th_bar[b].bb.b_arrived = KMP_INIT_BARRIER_STATE;
4004#if USE_DEBUGGER
4005 root_thread->th.th_bar[b].bb.b_worker_arrived = 0;
4006#endif
4007 }
4008 }
4009 KMP_DEBUG_ASSERT(root->r.r_hot_team->t.t_bar[bs_forkjoin_barrier].b_arrived ==
4010 KMP_INIT_BARRIER_STATE);
4011
4012#if KMP_AFFINITY_SUPPORTED
4013 root_thread->th.th_current_place = KMP_PLACE_UNDEFINED;
4014 root_thread->th.th_new_place = KMP_PLACE_UNDEFINED;
4015 root_thread->th.th_first_place = KMP_PLACE_UNDEFINED;
4016 root_thread->th.th_last_place = KMP_PLACE_UNDEFINED;
4017#endif /* KMP_AFFINITY_SUPPORTED */
4018 root_thread->th.th_def_allocator = __kmp_def_allocator;
4019 root_thread->th.th_prev_level = 0;
4020 root_thread->th.th_prev_num_threads = 1;
4021
4022 kmp_cg_root_t *tmp = (kmp_cg_root_t *)__kmp_allocate(sizeof(kmp_cg_root_t));
4023 tmp->cg_root = root_thread;
4024 tmp->cg_thread_limit = __kmp_cg_max_nth;
4025 tmp->cg_nthreads = 1;
4026 KA_TRACE(100, ("__kmp_register_root: Thread %p created node %p with"
4027 " cg_nthreads init to 1\n",
4028 root_thread, tmp));
4029 tmp->up = NULL;
4030 root_thread->th.th_cg_roots = tmp;
4031
4032 __kmp_root_counter++;
4033
4034#if OMPT_SUPPORT
4035 if (ompt_enabled.enabled) {
4036
4037 kmp_info_t *root_thread = ompt_get_thread();
4038
4039 ompt_set_thread_state(root_thread, ompt_state_overhead);
4040
4041 if (ompt_enabled.ompt_callback_thread_begin) {
4042 ompt_callbacks.ompt_callback(ompt_callback_thread_begin)(
4043 ompt_thread_initial, __ompt_get_thread_data_internal());
4044 }
4045 ompt_data_t *task_data;
4046 ompt_data_t *parallel_data;
4047 __ompt_get_task_info_internal(0, NULL, &task_data, NULL, &parallel_data,
4048 NULL);
4049 if (ompt_enabled.ompt_callback_implicit_task) {
4050 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
4051 ompt_scope_begin, parallel_data, task_data, 1, 1, ompt_task_initial);
4052 }
4053
4054 ompt_set_thread_state(root_thread, ompt_state_work_serial);
4055 }
4056#endif
4057#if OMPD_SUPPORT
4058 if (ompd_state & OMPD_ENABLE_BP)
4059 ompd_bp_thread_begin();
4060#endif
4061
4062 KMP_MB();
4063 __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
4064
4065 return gtid;
4066}
4067
4068static int __kmp_free_hot_teams(kmp_root_t *root, kmp_info_t *thr, int level,
4069 const int max_level) {
4070 int i, n, nth;
4071 kmp_hot_team_ptr_t *hot_teams = thr->th.th_hot_teams;
4072 if (!hot_teams || !hot_teams[level].hot_team) {
4073 return 0;
4074 }
4075 KMP_DEBUG_ASSERT(level < max_level);
4076 kmp_team_t *team = hot_teams[level].hot_team;
4077 nth = hot_teams[level].hot_team_nth;
4078 n = nth - 1; // primary thread is not freed
4079 if (level < max_level - 1) {
4080 for (i = 0; i < nth; ++i) {
4081 kmp_info_t *th = team->t.t_threads[i];
4082 n += __kmp_free_hot_teams(root, th, level + 1, max_level);
4083 if (i > 0 && th->th.th_hot_teams) {
4084 __kmp_free(th->th.th_hot_teams);
4085 th->th.th_hot_teams = NULL;
4086 }
4087 }
4088 }
4089 __kmp_free_team(root, team, NULL);
4090 return n;
4091}
4092
4093// Resets a root thread and clear its root and hot teams.
4094// Returns the number of __kmp_threads entries directly and indirectly freed.
4095static int __kmp_reset_root(int gtid, kmp_root_t *root) {
4096 kmp_team_t *root_team = root->r.r_root_team;
4097 kmp_team_t *hot_team = root->r.r_hot_team;
4098 int n = hot_team->t.t_nproc;
4099 int i;
4100
4101 KMP_DEBUG_ASSERT(!root->r.r_active);
4102
4103 root->r.r_root_team = NULL;
4104 root->r.r_hot_team = NULL;
4105 // __kmp_free_team() does not free hot teams, so we have to clear r_hot_team
4106 // before call to __kmp_free_team().
4107 __kmp_free_team(root, root_team, NULL);
4108 if (__kmp_hot_teams_max_level >
4109 0) { // need to free nested hot teams and their threads if any
4110 for (i = 0; i < hot_team->t.t_nproc; ++i) {
4111 kmp_info_t *th = hot_team->t.t_threads[i];
4112 if (__kmp_hot_teams_max_level > 1) {
4113 n += __kmp_free_hot_teams(root, th, 1, __kmp_hot_teams_max_level);
4114 }
4115 if (th->th.th_hot_teams) {
4116 __kmp_free(th->th.th_hot_teams);
4117 th->th.th_hot_teams = NULL;
4118 }
4119 }
4120 }
4121 __kmp_free_team(root, hot_team, NULL);
4122
4123 // Before we can reap the thread, we need to make certain that all other
4124 // threads in the teams that had this root as ancestor have stopped trying to
4125 // steal tasks.
4126 if (__kmp_tasking_mode != tskm_immediate_exec) {
4127 __kmp_wait_to_unref_task_teams();
4128 }
4129
4130#if KMP_OS_WINDOWS
4131 /* Close Handle of root duplicated in __kmp_create_worker (tr #62919) */
4132 KA_TRACE(
4133 10, ("__kmp_reset_root: free handle, th = %p, handle = %" KMP_UINTPTR_SPEC
4134 "\n",
4135 (LPVOID) & (root->r.r_uber_thread->th),
4136 root->r.r_uber_thread->th.th_info.ds.ds_thread));
4137 __kmp_free_handle(root->r.r_uber_thread->th.th_info.ds.ds_thread);
4138#endif /* KMP_OS_WINDOWS */
4139
4140#if OMPD_SUPPORT
4141 if (ompd_state & OMPD_ENABLE_BP)
4142 ompd_bp_thread_end();
4143#endif
4144
4145#if OMPT_SUPPORT
4146 ompt_data_t *task_data;
4147 ompt_data_t *parallel_data;
4148 __ompt_get_task_info_internal(0, NULL, &task_data, NULL, &parallel_data,
4149 NULL);
4150 if (ompt_enabled.ompt_callback_implicit_task) {
4151 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
4152 ompt_scope_end, parallel_data, task_data, 0, 1, ompt_task_initial);
4153 }
4154 if (ompt_enabled.ompt_callback_thread_end) {
4155 ompt_callbacks.ompt_callback(ompt_callback_thread_end)(
4156 &(root->r.r_uber_thread->th.ompt_thread_info.thread_data));
4157 }
4158#endif
4159
4160 TCW_4(__kmp_nth,
4161 __kmp_nth - 1); // __kmp_reap_thread will decrement __kmp_all_nth.
4162 i = root->r.r_uber_thread->th.th_cg_roots->cg_nthreads--;
4163 KA_TRACE(100, ("__kmp_reset_root: Thread %p decrement cg_nthreads on node %p"
4164 " to %d\n",
4165 root->r.r_uber_thread, root->r.r_uber_thread->th.th_cg_roots,
4166 root->r.r_uber_thread->th.th_cg_roots->cg_nthreads));
4167 if (i == 1) {
4168 // need to free contention group structure
4169 KMP_DEBUG_ASSERT(root->r.r_uber_thread ==
4170 root->r.r_uber_thread->th.th_cg_roots->cg_root);
4171 KMP_DEBUG_ASSERT(root->r.r_uber_thread->th.th_cg_roots->up == NULL);
4172 __kmp_free(root->r.r_uber_thread->th.th_cg_roots);
4173 root->r.r_uber_thread->th.th_cg_roots = NULL;
4174 }
4175 __kmp_reap_thread(root->r.r_uber_thread, 1);
4176
4177 // We canot put root thread to __kmp_thread_pool, so we have to reap it
4178 // instead of freeing.
4179 root->r.r_uber_thread = NULL;
4180 /* mark root as no longer in use */
4181 root->r.r_begin = FALSE;
4182
4183 return n;
4184}
4185
4186void __kmp_unregister_root_current_thread(int gtid) {
4187 KA_TRACE(1, ("__kmp_unregister_root_current_thread: enter T#%d\n", gtid));
4188 /* this lock should be ok, since unregister_root_current_thread is never
4189 called during an abort, only during a normal close. furthermore, if you
4190 have the forkjoin lock, you should never try to get the initz lock */
4191 __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
4192 if (TCR_4(__kmp_global.g.g_done) || !__kmp_init_serial) {
4193 KC_TRACE(10, ("__kmp_unregister_root_current_thread: already finished, "
4194 "exiting T#%d\n",
4195 gtid));
4196 __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
4197 return;
4198 }
4199 kmp_root_t *root = __kmp_root[gtid];
4200
4201 KMP_DEBUG_ASSERT(__kmp_threads && __kmp_threads[gtid]);
4202 KMP_ASSERT(KMP_UBER_GTID(gtid));
4203 KMP_ASSERT(root == __kmp_threads[gtid]->th.th_root);
4204 KMP_ASSERT(root->r.r_active == FALSE);
4205
4206 KMP_MB();
4207
4208 kmp_info_t *thread = __kmp_threads[gtid];
4209 kmp_team_t *team = thread->th.th_team;
4210 kmp_task_team_t *task_team = thread->th.th_task_team;
4211
4212 // we need to wait for the proxy tasks before finishing the thread
4213 if (task_team != NULL && (task_team->tt.tt_found_proxy_tasks ||
4214 task_team->tt.tt_hidden_helper_task_encountered)) {
4215#if OMPT_SUPPORT
4216 // the runtime is shutting down so we won't report any events
4217 thread->th.ompt_thread_info.state = ompt_state_undefined;
4218#endif
4219 __kmp_task_team_wait(thread, team USE_ITT_BUILD_ARG(NULL));
4220 }
4221
4222 __kmp_reset_root(gtid, root);
4223
4224 KMP_MB();
4225 KC_TRACE(10,
4226 ("__kmp_unregister_root_current_thread: T#%d unregistered\n", gtid));
4227
4228 __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
4229}
4230
4231#if KMP_OS_WINDOWS
4232/* __kmp_forkjoin_lock must be already held
4233 Unregisters a root thread that is not the current thread. Returns the number
4234 of __kmp_threads entries freed as a result. */
4235static int __kmp_unregister_root_other_thread(int gtid) {
4236 kmp_root_t *root = __kmp_root[gtid];
4237 int r;
4238
4239 KA_TRACE(1, ("__kmp_unregister_root_other_thread: enter T#%d\n", gtid));
4240 KMP_DEBUG_ASSERT(__kmp_threads && __kmp_threads[gtid]);
4241 KMP_ASSERT(KMP_UBER_GTID(gtid));
4242 KMP_ASSERT(root == __kmp_threads[gtid]->th.th_root);
4243 KMP_ASSERT(root->r.r_active == FALSE);
4244
4245 r = __kmp_reset_root(gtid, root);
4246 KC_TRACE(10,
4247 ("__kmp_unregister_root_other_thread: T#%d unregistered\n", gtid));
4248 return r;
4249}
4250#endif
4251
4252#if KMP_DEBUG
4253void __kmp_task_info() {
4254
4255 kmp_int32 gtid = __kmp_entry_gtid();
4256 kmp_int32 tid = __kmp_tid_from_gtid(gtid);
4257 kmp_info_t *this_thr = __kmp_threads[gtid];
4258 kmp_team_t *steam = this_thr->th.th_serial_team;
4259 kmp_team_t *team = this_thr->th.th_team;
4260
4261 __kmp_printf(
4262 "__kmp_task_info: gtid=%d tid=%d t_thread=%p team=%p steam=%p curtask=%p "
4263 "ptask=%p\n",
4264 gtid, tid, this_thr, team, steam, this_thr->th.th_current_task,
4265 team->t.t_implicit_task_taskdata[tid].td_parent);
4266}
4267#endif // KMP_DEBUG
4268
4269/* TODO optimize with one big memclr, take out what isn't needed, split
4270 responsibility to workers as much as possible, and delay initialization of
4271 features as much as possible */
4272static void __kmp_initialize_info(kmp_info_t *this_thr, kmp_team_t *team,
4273 int tid, int gtid) {
4274 /* this_thr->th.th_info.ds.ds_gtid is setup in
4275 kmp_allocate_thread/create_worker.
4276 this_thr->th.th_serial_team is setup in __kmp_allocate_thread */
4277 KMP_DEBUG_ASSERT(this_thr != NULL);
4278 KMP_DEBUG_ASSERT(this_thr->th.th_serial_team);
4279 KMP_DEBUG_ASSERT(team);
4280 KMP_DEBUG_ASSERT(team->t.t_threads);
4281 KMP_DEBUG_ASSERT(team->t.t_dispatch);
4282 kmp_info_t *master = team->t.t_threads[0];
4283 KMP_DEBUG_ASSERT(master);
4284 KMP_DEBUG_ASSERT(master->th.th_root);
4285
4286 KMP_MB();
4287
4288 TCW_SYNC_PTR(this_thr->th.th_team, team);
4289
4290 this_thr->th.th_info.ds.ds_tid = tid;
4291 this_thr->th.th_set_nproc = 0;
4292 if (__kmp_tasking_mode != tskm_immediate_exec)
4293 // When tasking is possible, threads are not safe to reap until they are
4294 // done tasking; this will be set when tasking code is exited in wait
4295 this_thr->th.th_reap_state = KMP_NOT_SAFE_TO_REAP;
4296 else // no tasking --> always safe to reap
4297 this_thr->th.th_reap_state = KMP_SAFE_TO_REAP;
4298 this_thr->th.th_set_proc_bind = proc_bind_default;
4299
4300#if KMP_AFFINITY_SUPPORTED
4301 this_thr->th.th_new_place = this_thr->th.th_current_place;
4302#endif
4303 this_thr->th.th_root = master->th.th_root;
4304
4305 /* setup the thread's cache of the team structure */
4306 this_thr->th.th_team_nproc = team->t.t_nproc;
4307 this_thr->th.th_team_master = master;
4308 this_thr->th.th_team_serialized = team->t.t_serialized;
4309
4310 KMP_DEBUG_ASSERT(team->t.t_implicit_task_taskdata);
4311
4312 KF_TRACE(10, ("__kmp_initialize_info1: T#%d:%d this_thread=%p curtask=%p\n",
4313 tid, gtid, this_thr, this_thr->th.th_current_task));
4314
4315 __kmp_init_implicit_task(this_thr->th.th_team_master->th.th_ident, this_thr,
4316 team, tid, TRUE);
4317
4318 KF_TRACE(10, ("__kmp_initialize_info2: T#%d:%d this_thread=%p curtask=%p\n",
4319 tid, gtid, this_thr, this_thr->th.th_current_task));
4320 // TODO: Initialize ICVs from parent; GEH - isn't that already done in
4321 // __kmp_initialize_team()?
4322
4323 /* TODO no worksharing in speculative threads */
4324 this_thr->th.th_dispatch = &team->t.t_dispatch[tid];
4325
4326 this_thr->th.th_local.this_construct = 0;
4327
4328 if (!this_thr->th.th_pri_common) {
4329 this_thr->th.th_pri_common =
4330 (struct common_table *)__kmp_allocate(sizeof(struct common_table));
4331 if (__kmp_storage_map) {
4332 __kmp_print_storage_map_gtid(
4333 gtid, this_thr->th.th_pri_common, this_thr->th.th_pri_common + 1,
4334 sizeof(struct common_table), "th_%d.th_pri_common\n", gtid);
4335 }
4336 this_thr->th.th_pri_head = NULL;
4337 }
4338
4339 if (this_thr != master && // Primary thread's CG root is initialized elsewhere
4340 this_thr->th.th_cg_roots != master->th.th_cg_roots) { // CG root not set
4341 // Make new thread's CG root same as primary thread's
4342 KMP_DEBUG_ASSERT(master->th.th_cg_roots);
4343 kmp_cg_root_t *tmp = this_thr->th.th_cg_roots;
4344 if (tmp) {
4345 // worker changes CG, need to check if old CG should be freed
4346 int i = tmp->cg_nthreads--;
4347 KA_TRACE(100, ("__kmp_initialize_info: Thread %p decrement cg_nthreads"
4348 " on node %p of thread %p to %d\n",
4349 this_thr, tmp, tmp->cg_root, tmp->cg_nthreads));
4350 if (i == 1) {
4351 __kmp_free(tmp); // last thread left CG --> free it
4352 }
4353 }
4354 this_thr->th.th_cg_roots = master->th.th_cg_roots;
4355 // Increment new thread's CG root's counter to add the new thread
4356 this_thr->th.th_cg_roots->cg_nthreads++;
4357 KA_TRACE(100, ("__kmp_initialize_info: Thread %p increment cg_nthreads on"
4358 " node %p of thread %p to %d\n",
4359 this_thr, this_thr->th.th_cg_roots,
4360 this_thr->th.th_cg_roots->cg_root,
4361 this_thr->th.th_cg_roots->cg_nthreads));
4362 this_thr->th.th_current_task->td_icvs.thread_limit =
4363 this_thr->th.th_cg_roots->cg_thread_limit;
4364 }
4365
4366 /* Initialize dynamic dispatch */
4367 {
4368 volatile kmp_disp_t *dispatch = this_thr->th.th_dispatch;
4369 // Use team max_nproc since this will never change for the team.
4370 size_t disp_size =
4371 sizeof(dispatch_private_info_t) *
4372 (team->t.t_max_nproc == 1 ? 1 : __kmp_dispatch_num_buffers);
4373 KD_TRACE(10, ("__kmp_initialize_info: T#%d max_nproc: %d\n", gtid,
4374 team->t.t_max_nproc));
4375 KMP_ASSERT(dispatch);
4376 KMP_DEBUG_ASSERT(team->t.t_dispatch);
4377 KMP_DEBUG_ASSERT(dispatch == &team->t.t_dispatch[tid]);
4378
4379 dispatch->th_disp_index = 0;
4380 dispatch->th_doacross_buf_idx = 0;
4381 if (!dispatch->th_disp_buffer) {
4382 dispatch->th_disp_buffer =
4383 (dispatch_private_info_t *)__kmp_allocate(disp_size);
4384
4385 if (__kmp_storage_map) {
4386 __kmp_print_storage_map_gtid(
4387 gtid, &dispatch->th_disp_buffer[0],
4388 &dispatch->th_disp_buffer[team->t.t_max_nproc == 1
4389 ? 1
4390 : __kmp_dispatch_num_buffers],
4391 disp_size,
4392 "th_%d.th_dispatch.th_disp_buffer "
4393 "(team_%d.t_dispatch[%d].th_disp_buffer)",
4394 gtid, team->t.t_id, gtid);
4395 }
4396 } else {
4397 memset(&dispatch->th_disp_buffer[0], '\0', disp_size);
4398 }
4399
4400 dispatch->th_dispatch_pr_current = 0;
4401 dispatch->th_dispatch_sh_current = 0;
4402
4403 dispatch->th_deo_fcn = 0; /* ORDERED */
4404 dispatch->th_dxo_fcn = 0; /* END ORDERED */
4405 }
4406
4407 this_thr->th.th_next_pool = NULL;
4408
4409 KMP_DEBUG_ASSERT(!this_thr->th.th_spin_here);
4410 KMP_DEBUG_ASSERT(this_thr->th.th_next_waiting == 0);
4411
4412 KMP_MB();
4413}
4414
4415/* allocate a new thread for the requesting team. this is only called from
4416 within a forkjoin critical section. we will first try to get an available
4417 thread from the thread pool. if none is available, we will fork a new one
4418 assuming we are able to create a new one. this should be assured, as the
4419 caller should check on this first. */
4420kmp_info_t *__kmp_allocate_thread(kmp_root_t *root, kmp_team_t *team,
4421 int new_tid) {
4422 kmp_team_t *serial_team;
4423 kmp_info_t *new_thr;
4424 int new_gtid;
4425
4426 KA_TRACE(20, ("__kmp_allocate_thread: T#%d\n", __kmp_get_gtid()));
4427 KMP_DEBUG_ASSERT(root && team);
4428 KMP_MB();
4429
4430 /* first, try to get one from the thread pool unless allocating thread is
4431 * the main hidden helper thread. The hidden helper team should always
4432 * allocate new OS threads. */
4433 if (__kmp_thread_pool && !KMP_HIDDEN_HELPER_TEAM(team)) {
4434 new_thr = CCAST(kmp_info_t *, __kmp_thread_pool);
4435 __kmp_thread_pool = (volatile kmp_info_t *)new_thr->th.th_next_pool;
4436 if (new_thr == __kmp_thread_pool_insert_pt) {
4437 __kmp_thread_pool_insert_pt = NULL;
4438 }
4439 TCW_4(new_thr->th.th_in_pool, FALSE);
4440 __kmp_suspend_initialize_thread(new_thr);
4441 __kmp_lock_suspend_mx(new_thr);
4442 if (new_thr->th.th_active_in_pool == TRUE) {
4443 KMP_DEBUG_ASSERT(new_thr->th.th_active == TRUE);
4444 KMP_ATOMIC_DEC(&__kmp_thread_pool_active_nth);
4445 new_thr->th.th_active_in_pool = FALSE;
4446 }
4447 __kmp_unlock_suspend_mx(new_thr);
4448
4449 KA_TRACE(20, ("__kmp_allocate_thread: T#%d using thread T#%d\n",
4450 __kmp_get_gtid(), new_thr->th.th_info.ds.ds_gtid));
4451 KMP_ASSERT(!new_thr->th.th_team);
4452 KMP_DEBUG_ASSERT(__kmp_nth < __kmp_threads_capacity);
4453
4454 /* setup the thread structure */
4455 __kmp_initialize_info(new_thr, team, new_tid,
4456 new_thr->th.th_info.ds.ds_gtid);
4457 KMP_DEBUG_ASSERT(new_thr->th.th_serial_team);
4458
4459 TCW_4(__kmp_nth, __kmp_nth + 1);
4460
4461 new_thr->th.th_task_state = 0;
4462
4463 if (__kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
4464 // Make sure pool thread has transitioned to waiting on own thread struct
4465 KMP_DEBUG_ASSERT(new_thr->th.th_used_in_team.load() == 0);
4466 // Thread activated in __kmp_allocate_team when increasing team size
4467 }
4468
4469#ifdef KMP_ADJUST_BLOCKTIME
4470 /* Adjust blocktime back to zero if necessary */
4471 /* Middle initialization might not have occurred yet */
4472 if (!__kmp_env_blocktime && (__kmp_avail_proc > 0)) {
4473 if (__kmp_nth > __kmp_avail_proc) {
4474 __kmp_zero_bt = TRUE;
4475 }
4476 }
4477#endif /* KMP_ADJUST_BLOCKTIME */
4478
4479#if KMP_DEBUG
4480 // If thread entered pool via __kmp_free_thread, wait_flag should !=
4481 // KMP_BARRIER_PARENT_FLAG.
4482 int b;
4483 kmp_balign_t *balign = new_thr->th.th_bar;
4484 for (b = 0; b < bs_last_barrier; ++b)
4485 KMP_DEBUG_ASSERT(balign[b].bb.wait_flag != KMP_BARRIER_PARENT_FLAG);
4486#endif
4487
4488 KF_TRACE(10, ("__kmp_allocate_thread: T#%d using thread %p T#%d\n",
4489 __kmp_get_gtid(), new_thr, new_thr->th.th_info.ds.ds_gtid));
4490
4491 KMP_MB();
4492 return new_thr;
4493 }
4494
4495 /* no, well fork a new one */
4496 KMP_ASSERT(KMP_HIDDEN_HELPER_TEAM(team) || __kmp_nth == __kmp_all_nth);
4497 KMP_ASSERT(__kmp_all_nth < __kmp_threads_capacity);
4498
4499#if KMP_USE_MONITOR
4500 // If this is the first worker thread the RTL is creating, then also
4501 // launch the monitor thread. We try to do this as early as possible.
4502 if (!TCR_4(__kmp_init_monitor)) {
4503 __kmp_acquire_bootstrap_lock(&__kmp_monitor_lock);
4504 if (!TCR_4(__kmp_init_monitor)) {
4505 KF_TRACE(10, ("before __kmp_create_monitor\n"));
4506 TCW_4(__kmp_init_monitor, 1);
4507 __kmp_create_monitor(&__kmp_monitor);
4508 KF_TRACE(10, ("after __kmp_create_monitor\n"));
4509#if KMP_OS_WINDOWS
4510 // AC: wait until monitor has started. This is a fix for CQ232808.
4511 // The reason is that if the library is loaded/unloaded in a loop with
4512 // small (parallel) work in between, then there is high probability that
4513 // monitor thread started after the library shutdown. At shutdown it is
4514 // too late to cope with the problem, because when the primary thread is
4515 // in DllMain (process detach) the monitor has no chances to start (it is
4516 // blocked), and primary thread has no means to inform the monitor that
4517 // the library has gone, because all the memory which the monitor can
4518 // access is going to be released/reset.
4519 while (TCR_4(__kmp_init_monitor) < 2) {
4520 KMP_YIELD(TRUE);
4521 }
4522 KF_TRACE(10, ("after monitor thread has started\n"));
4523#endif
4524 }
4525 __kmp_release_bootstrap_lock(&__kmp_monitor_lock);
4526 }
4527#endif
4528
4529 KMP_MB();
4530
4531 {
4532 int new_start_gtid = TCR_4(__kmp_init_hidden_helper_threads)
4533 ? 1
4534 : __kmp_hidden_helper_threads_num + 1;
4535
4536 for (new_gtid = new_start_gtid; TCR_PTR(__kmp_threads[new_gtid]) != NULL;
4537 ++new_gtid) {
4538 KMP_DEBUG_ASSERT(new_gtid < __kmp_threads_capacity);
4539 }
4540
4541 if (TCR_4(__kmp_init_hidden_helper_threads)) {
4542 KMP_DEBUG_ASSERT(new_gtid <= __kmp_hidden_helper_threads_num);
4543 }
4544 }
4545
4546 /* allocate space for it. */
4547 new_thr = (kmp_info_t *)__kmp_allocate(sizeof(kmp_info_t));
4548
4549 new_thr->th.th_nt_strict = false;
4550 new_thr->th.th_nt_loc = NULL;
4551 new_thr->th.th_nt_sev = severity_fatal;
4552 new_thr->th.th_nt_msg = NULL;
4553
4554 TCW_SYNC_PTR(__kmp_threads[new_gtid], new_thr);
4555
4556#if USE_ITT_BUILD && USE_ITT_NOTIFY && KMP_DEBUG
4557 // suppress race conditions detection on synchronization flags in debug mode
4558 // this helps to analyze library internals eliminating false positives
4559 __itt_suppress_mark_range(
4560 __itt_suppress_range, __itt_suppress_threading_errors,
4561 &new_thr->th.th_sleep_loc, sizeof(new_thr->th.th_sleep_loc));
4562 __itt_suppress_mark_range(
4563 __itt_suppress_range, __itt_suppress_threading_errors,
4564 &new_thr->th.th_reap_state, sizeof(new_thr->th.th_reap_state));
4565#if KMP_OS_WINDOWS
4566 __itt_suppress_mark_range(
4567 __itt_suppress_range, __itt_suppress_threading_errors,
4568 &new_thr->th.th_suspend_init, sizeof(new_thr->th.th_suspend_init));
4569#else
4570 __itt_suppress_mark_range(__itt_suppress_range,
4571 __itt_suppress_threading_errors,
4572 &new_thr->th.th_suspend_init_count,
4573 sizeof(new_thr->th.th_suspend_init_count));
4574#endif
4575 // TODO: check if we need to also suppress b_arrived flags
4576 __itt_suppress_mark_range(__itt_suppress_range,
4577 __itt_suppress_threading_errors,
4578 CCAST(kmp_uint64 *, &new_thr->th.th_bar[0].bb.b_go),
4579 sizeof(new_thr->th.th_bar[0].bb.b_go));
4580 __itt_suppress_mark_range(__itt_suppress_range,
4581 __itt_suppress_threading_errors,
4582 CCAST(kmp_uint64 *, &new_thr->th.th_bar[1].bb.b_go),
4583 sizeof(new_thr->th.th_bar[1].bb.b_go));
4584 __itt_suppress_mark_range(__itt_suppress_range,
4585 __itt_suppress_threading_errors,
4586 CCAST(kmp_uint64 *, &new_thr->th.th_bar[2].bb.b_go),
4587 sizeof(new_thr->th.th_bar[2].bb.b_go));
4588#endif /* USE_ITT_BUILD && USE_ITT_NOTIFY && KMP_DEBUG */
4589 if (__kmp_storage_map) {
4590 __kmp_print_thread_storage_map(new_thr, new_gtid);
4591 }
4592
4593 // add the reserve serialized team, initialized from the team's primary thread
4594 {
4595 kmp_internal_control_t r_icvs = __kmp_get_x_global_icvs(team);
4596 KF_TRACE(10, ("__kmp_allocate_thread: before th_serial/serial_team\n"));
4597 new_thr->th.th_serial_team = serial_team =
4598 (kmp_team_t *)__kmp_allocate_team(root, 1, 1,
4599#if OMPT_SUPPORT
4600 ompt_data_none, // root parallel id
4601#endif
4602 proc_bind_default, &r_icvs, 0, NULL);
4603 }
4604 KMP_ASSERT(serial_team);
4605 serial_team->t.t_serialized = 0; // AC: the team created in reserve, not for
4606 // execution (it is unused for now).
4607 serial_team->t.t_threads[0] = new_thr;
4608 KF_TRACE(10,
4609 ("__kmp_allocate_thread: after th_serial/serial_team : new_thr=%p\n",
4610 new_thr));
4611
4612 /* setup the thread structures */
4613 __kmp_initialize_info(new_thr, team, new_tid, new_gtid);
4614
4615#if USE_FAST_MEMORY
4616 __kmp_initialize_fast_memory(new_thr);
4617#endif /* USE_FAST_MEMORY */
4618
4619#if KMP_USE_BGET
4620 KMP_DEBUG_ASSERT(new_thr->th.th_local.bget_data == NULL);
4621 __kmp_initialize_bget(new_thr);
4622#endif
4623
4624 __kmp_init_random(new_thr); // Initialize random number generator
4625
4626 /* Initialize these only once when thread is grabbed for a team allocation */
4627 KA_TRACE(20,
4628 ("__kmp_allocate_thread: T#%d init go fork=%u, plain=%u\n",
4629 __kmp_get_gtid(), KMP_INIT_BARRIER_STATE, KMP_INIT_BARRIER_STATE));
4630
4631 int b;
4632 kmp_balign_t *balign = new_thr->th.th_bar;
4633 for (b = 0; b < bs_last_barrier; ++b) {
4634 balign[b].bb.b_go = KMP_INIT_BARRIER_STATE;
4635 balign[b].bb.team = NULL;
4636 balign[b].bb.wait_flag = KMP_BARRIER_NOT_WAITING;
4637 balign[b].bb.use_oncore_barrier = 0;
4638 }
4639
4640 TCW_PTR(new_thr->th.th_sleep_loc, NULL);
4641 new_thr->th.th_sleep_loc_type = flag_unset;
4642
4643 new_thr->th.th_spin_here = FALSE;
4644 new_thr->th.th_next_waiting = 0;
4645#if KMP_OS_UNIX
4646 new_thr->th.th_blocking = false;
4647#endif
4648
4649#if KMP_AFFINITY_SUPPORTED
4650 new_thr->th.th_current_place = KMP_PLACE_UNDEFINED;
4651 new_thr->th.th_new_place = KMP_PLACE_UNDEFINED;
4652 new_thr->th.th_first_place = KMP_PLACE_UNDEFINED;
4653 new_thr->th.th_last_place = KMP_PLACE_UNDEFINED;
4654#endif
4655 new_thr->th.th_def_allocator = __kmp_def_allocator;
4656 new_thr->th.th_prev_level = 0;
4657 new_thr->th.th_prev_num_threads = 1;
4658
4659 TCW_4(new_thr->th.th_in_pool, FALSE);
4660 new_thr->th.th_active_in_pool = FALSE;
4661 TCW_4(new_thr->th.th_active, TRUE);
4662
4663 new_thr->th.th_set_nested_nth = NULL;
4664 new_thr->th.th_set_nested_nth_sz = 0;
4665
4666 /* adjust the global counters */
4667 __kmp_all_nth++;
4668 __kmp_nth++;
4669
4670 // if __kmp_adjust_gtid_mode is set, then we use method #1 (sp search) for low
4671 // numbers of procs, and method #2 (keyed API call) for higher numbers.
4672 if (__kmp_adjust_gtid_mode) {
4673 if (__kmp_all_nth >= __kmp_tls_gtid_min) {
4674 if (TCR_4(__kmp_gtid_mode) != 2) {
4675 TCW_4(__kmp_gtid_mode, 2);
4676 }
4677 } else {
4678 if (TCR_4(__kmp_gtid_mode) != 1) {
4679 TCW_4(__kmp_gtid_mode, 1);
4680 }
4681 }
4682 }
4683
4684#ifdef KMP_ADJUST_BLOCKTIME
4685 /* Adjust blocktime back to zero if necessary */
4686 /* Middle initialization might not have occurred yet */
4687 if (!__kmp_env_blocktime && (__kmp_avail_proc > 0)) {
4688 if (__kmp_nth > __kmp_avail_proc) {
4689 __kmp_zero_bt = TRUE;
4690 }
4691 }
4692#endif /* KMP_ADJUST_BLOCKTIME */
4693
4694#if KMP_AFFINITY_SUPPORTED
4695 // Set the affinity and topology information for new thread
4696 __kmp_affinity_set_init_mask(new_gtid, /*isa_root=*/FALSE);
4697#endif
4698
4699 /* actually fork it and create the new worker thread */
4700 KF_TRACE(
4701 10, ("__kmp_allocate_thread: before __kmp_create_worker: %p\n", new_thr));
4702 __kmp_create_worker(new_gtid, new_thr, __kmp_stksize);
4703 KF_TRACE(10,
4704 ("__kmp_allocate_thread: after __kmp_create_worker: %p\n", new_thr));
4705
4706 KA_TRACE(20, ("__kmp_allocate_thread: T#%d forked T#%d\n", __kmp_get_gtid(),
4707 new_gtid));
4708 KMP_MB();
4709 return new_thr;
4710}
4711
4712/* Reinitialize team for reuse.
4713 The hot team code calls this case at every fork barrier, so EPCC barrier
4714 test are extremely sensitive to changes in it, esp. writes to the team
4715 struct, which cause a cache invalidation in all threads.
4716 IF YOU TOUCH THIS ROUTINE, RUN EPCC C SYNCBENCH ON A BIG-IRON MACHINE!!! */
4717static void __kmp_reinitialize_team(kmp_team_t *team,
4718 kmp_internal_control_t *new_icvs,
4719 ident_t *loc) {
4720 KF_TRACE(10, ("__kmp_reinitialize_team: enter this_thread=%p team=%p\n",
4721 team->t.t_threads[0], team));
4722 KMP_DEBUG_ASSERT(team && new_icvs);
4723 KMP_DEBUG_ASSERT((!TCR_4(__kmp_init_parallel)) || new_icvs->nproc);
4724 KMP_CHECK_UPDATE(team->t.t_ident, loc);
4725
4726 KMP_CHECK_UPDATE(team->t.t_id, KMP_GEN_TEAM_ID());
4727 // Copy ICVs to the primary thread's implicit taskdata
4728 __kmp_init_implicit_task(loc, team->t.t_threads[0], team, 0, FALSE);
4729 copy_icvs(&team->t.t_implicit_task_taskdata[0].td_icvs, new_icvs);
4730
4731 KF_TRACE(10, ("__kmp_reinitialize_team: exit this_thread=%p team=%p\n",
4732 team->t.t_threads[0], team));
4733}
4734
4735/* Initialize the team data structure.
4736 This assumes the t_threads and t_max_nproc are already set.
4737 Also, we don't touch the arguments */
4738static void __kmp_initialize_team(kmp_team_t *team, int new_nproc,
4739 kmp_internal_control_t *new_icvs,
4740 ident_t *loc) {
4741 KF_TRACE(10, ("__kmp_initialize_team: enter: team=%p\n", team));
4742
4743 /* verify */
4744 KMP_DEBUG_ASSERT(team);
4745 KMP_DEBUG_ASSERT(new_nproc <= team->t.t_max_nproc);
4746 KMP_DEBUG_ASSERT(team->t.t_threads);
4747 KMP_MB();
4748
4749 team->t.t_master_tid = 0; /* not needed */
4750 /* team->t.t_master_bar; not needed */
4751 team->t.t_serialized = new_nproc > 1 ? 0 : 1;
4752 team->t.t_nproc = new_nproc;
4753
4754 /* team->t.t_parent = NULL; TODO not needed & would mess up hot team */
4755 team->t.t_next_pool = NULL;
4756 /* memset( team->t.t_threads, 0, sizeof(kmp_info_t*)*new_nproc ); would mess
4757 * up hot team */
4758
4759 TCW_SYNC_PTR(team->t.t_pkfn, NULL); /* not needed */
4760 team->t.t_invoke = NULL; /* not needed */
4761
4762 // TODO???: team->t.t_max_active_levels = new_max_active_levels;
4763 team->t.t_sched.sched = new_icvs->sched.sched;
4764
4765#if KMP_ARCH_X86 || KMP_ARCH_X86_64
4766 team->t.t_fp_control_saved = FALSE; /* not needed */
4767 team->t.t_x87_fpu_control_word = 0; /* not needed */
4768 team->t.t_mxcsr = 0; /* not needed */
4769#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
4770
4771 team->t.t_construct = 0;
4772
4773 team->t.t_ordered.dt.t_value = 0;
4774 team->t.t_master_active = FALSE;
4775
4776#ifdef KMP_DEBUG
4777 team->t.t_copypriv_data = NULL; /* not necessary, but nice for debugging */
4778#endif
4779#if KMP_OS_WINDOWS
4780 team->t.t_copyin_counter = 0; /* for barrier-free copyin implementation */
4781#endif
4782
4783 team->t.t_control_stack_top = NULL;
4784
4785 __kmp_reinitialize_team(team, new_icvs, loc);
4786
4787 KMP_MB();
4788 KF_TRACE(10, ("__kmp_initialize_team: exit: team=%p\n", team));
4789}
4790
4791#if KMP_AFFINITY_SUPPORTED
4792static inline void __kmp_set_thread_place(kmp_team_t *team, kmp_info_t *th,
4793 int first, int last, int newp) {
4794 th->th.th_first_place = first;
4795 th->th.th_last_place = last;
4796 th->th.th_new_place = newp;
4797 if (newp != th->th.th_current_place) {
4798 if (__kmp_display_affinity && team->t.t_display_affinity != 1)
4799 team->t.t_display_affinity = 1;
4800 // Copy topology information associated with the new place
4801 th->th.th_topology_ids = __kmp_affinity.ids[th->th.th_new_place];
4802 th->th.th_topology_attrs = __kmp_affinity.attrs[th->th.th_new_place];
4803 }
4804}
4805
4806// __kmp_partition_places() is the heart of the OpenMP 4.0 affinity mechanism.
4807// It calculates the worker + primary thread's partition based upon the parent
4808// thread's partition, and binds each worker to a thread in their partition.
4809// The primary thread's partition should already include its current binding.
4810static void __kmp_partition_places(kmp_team_t *team, int update_master_only) {
4811 // Do not partition places for the hidden helper team
4812 if (KMP_HIDDEN_HELPER_TEAM(team))
4813 return;
4814 // Copy the primary thread's place partition to the team struct
4815 kmp_info_t *master_th = team->t.t_threads[0];
4816 KMP_DEBUG_ASSERT(master_th != NULL);
4817 kmp_proc_bind_t proc_bind = team->t.t_proc_bind;
4818 int first_place = master_th->th.th_first_place;
4819 int last_place = master_th->th.th_last_place;
4820 int masters_place = master_th->th.th_current_place;
4821 int num_masks = __kmp_affinity.num_masks;
4822 team->t.t_first_place = first_place;
4823 team->t.t_last_place = last_place;
4824
4825 KA_TRACE(20, ("__kmp_partition_places: enter: proc_bind = %d T#%d(%d:0) "
4826 "bound to place %d partition = [%d,%d]\n",
4827 proc_bind, __kmp_gtid_from_thread(team->t.t_threads[0]),
4828 team->t.t_id, masters_place, first_place, last_place));
4829
4830 switch (proc_bind) {
4831
4832 case proc_bind_default:
4833 // Serial teams might have the proc_bind policy set to proc_bind_default.
4834 // Not an issue -- we don't rebind primary thread for any proc_bind policy.
4835 KMP_DEBUG_ASSERT(team->t.t_nproc == 1);
4836 break;
4837
4838 case proc_bind_primary: {
4839 int f;
4840 int n_th = team->t.t_nproc;
4841 for (f = 1; f < n_th; f++) {
4842 kmp_info_t *th = team->t.t_threads[f];
4843 KMP_DEBUG_ASSERT(th != NULL);
4844 __kmp_set_thread_place(team, th, first_place, last_place, masters_place);
4845
4846 KA_TRACE(100, ("__kmp_partition_places: primary: T#%d(%d:%d) place %d "
4847 "partition = [%d,%d]\n",
4848 __kmp_gtid_from_thread(team->t.t_threads[f]), team->t.t_id,
4849 f, masters_place, first_place, last_place));
4850 }
4851 } break;
4852
4853 case proc_bind_close: {
4854 int f;
4855 int n_th = team->t.t_nproc;
4856 int n_places;
4857 if (first_place <= last_place) {
4858 n_places = last_place - first_place + 1;
4859 } else {
4860 n_places = num_masks - first_place + last_place + 1;
4861 }
4862 if (n_th <= n_places) {
4863 int place = masters_place;
4864 for (f = 1; f < n_th; f++) {
4865 kmp_info_t *th = team->t.t_threads[f];
4866 KMP_DEBUG_ASSERT(th != NULL);
4867
4868 if (place == last_place) {
4869 place = first_place;
4870 } else if (place == (num_masks - 1)) {
4871 place = 0;
4872 } else {
4873 place++;
4874 }
4875 __kmp_set_thread_place(team, th, first_place, last_place, place);
4876
4877 KA_TRACE(100, ("__kmp_partition_places: close: T#%d(%d:%d) place %d "
4878 "partition = [%d,%d]\n",
4879 __kmp_gtid_from_thread(team->t.t_threads[f]),
4880 team->t.t_id, f, place, first_place, last_place));
4881 }
4882 } else {
4883 int S, rem, gap, s_count;
4884 S = n_th / n_places;
4885 s_count = 0;
4886 rem = n_th - (S * n_places);
4887 gap = rem > 0 ? n_places / rem : n_places;
4888 int place = masters_place;
4889 int gap_ct = gap;
4890 for (f = 0; f < n_th; f++) {
4891 kmp_info_t *th = team->t.t_threads[f];
4892 KMP_DEBUG_ASSERT(th != NULL);
4893
4894 __kmp_set_thread_place(team, th, first_place, last_place, place);
4895 s_count++;
4896
4897 if ((s_count == S) && rem && (gap_ct == gap)) {
4898 // do nothing, add an extra thread to place on next iteration
4899 } else if ((s_count == S + 1) && rem && (gap_ct == gap)) {
4900 // we added an extra thread to this place; move to next place
4901 if (place == last_place) {
4902 place = first_place;
4903 } else if (place == (num_masks - 1)) {
4904 place = 0;
4905 } else {
4906 place++;
4907 }
4908 s_count = 0;
4909 gap_ct = 1;
4910 rem--;
4911 } else if (s_count == S) { // place full; don't add extra
4912 if (place == last_place) {
4913 place = first_place;
4914 } else if (place == (num_masks - 1)) {
4915 place = 0;
4916 } else {
4917 place++;
4918 }
4919 gap_ct++;
4920 s_count = 0;
4921 }
4922
4923 KA_TRACE(100,
4924 ("__kmp_partition_places: close: T#%d(%d:%d) place %d "
4925 "partition = [%d,%d]\n",
4926 __kmp_gtid_from_thread(team->t.t_threads[f]), team->t.t_id, f,
4927 th->th.th_new_place, first_place, last_place));
4928 }
4929 KMP_DEBUG_ASSERT(place == masters_place);
4930 }
4931 } break;
4932
4933 case proc_bind_spread: {
4934 int f;
4935 int n_th = team->t.t_nproc;
4936 int n_places;
4937 int thidx;
4938 if (first_place <= last_place) {
4939 n_places = last_place - first_place + 1;
4940 } else {
4941 n_places = num_masks - first_place + last_place + 1;
4942 }
4943 if (n_th <= n_places) {
4944 int place = -1;
4945
4946 if (n_places != num_masks) {
4947 int S = n_places / n_th;
4948 int s_count, rem, gap, gap_ct;
4949
4950 place = masters_place;
4951 rem = n_places - n_th * S;
4952 gap = rem ? n_th / rem : 1;
4953 gap_ct = gap;
4954 thidx = n_th;
4955 if (update_master_only == 1)
4956 thidx = 1;
4957 for (f = 0; f < thidx; f++) {
4958 kmp_info_t *th = team->t.t_threads[f];
4959 KMP_DEBUG_ASSERT(th != NULL);
4960
4961 int fplace = place, nplace = place;
4962 s_count = 1;
4963 while (s_count < S) {
4964 if (place == last_place) {
4965 place = first_place;
4966 } else if (place == (num_masks - 1)) {
4967 place = 0;
4968 } else {
4969 place++;
4970 }
4971 s_count++;
4972 }
4973 if (rem && (gap_ct == gap)) {
4974 if (place == last_place) {
4975 place = first_place;
4976 } else if (place == (num_masks - 1)) {
4977 place = 0;
4978 } else {
4979 place++;
4980 }
4981 rem--;
4982 gap_ct = 0;
4983 }
4984 __kmp_set_thread_place(team, th, fplace, place, nplace);
4985 gap_ct++;
4986
4987 if (place == last_place) {
4988 place = first_place;
4989 } else if (place == (num_masks - 1)) {
4990 place = 0;
4991 } else {
4992 place++;
4993 }
4994
4995 KA_TRACE(100,
4996 ("__kmp_partition_places: spread: T#%d(%d:%d) place %d "
4997 "partition = [%d,%d], num_masks: %u\n",
4998 __kmp_gtid_from_thread(team->t.t_threads[f]), team->t.t_id,
4999 f, th->th.th_new_place, th->th.th_first_place,
5000 th->th.th_last_place, num_masks));
5001 }
5002 } else {
5003 /* Having uniform space of available computation places I can create
5004 T partitions of round(P/T) size and put threads into the first
5005 place of each partition. */
5006 double current = static_cast<double>(masters_place);
5007 double spacing =
5008 (static_cast<double>(n_places + 1) / static_cast<double>(n_th));
5009 int first, last;
5010 kmp_info_t *th;
5011
5012 thidx = n_th + 1;
5013 if (update_master_only == 1)
5014 thidx = 1;
5015 for (f = 0; f < thidx; f++) {
5016 first = static_cast<int>(current);
5017 last = static_cast<int>(current + spacing) - 1;
5018 KMP_DEBUG_ASSERT(last >= first);
5019 if (first >= n_places) {
5020 if (masters_place) {
5021 first -= n_places;
5022 last -= n_places;
5023 if (first == (masters_place + 1)) {
5024 KMP_DEBUG_ASSERT(f == n_th);
5025 first--;
5026 }
5027 if (last == masters_place) {
5028 KMP_DEBUG_ASSERT(f == (n_th - 1));
5029 last--;
5030 }
5031 } else {
5032 KMP_DEBUG_ASSERT(f == n_th);
5033 first = 0;
5034 last = 0;
5035 }
5036 }
5037 if (last >= n_places) {
5038 last = (n_places - 1);
5039 }
5040 place = first;
5041 current += spacing;
5042 if (f < n_th) {
5043 KMP_DEBUG_ASSERT(0 <= first);
5044 KMP_DEBUG_ASSERT(n_places > first);
5045 KMP_DEBUG_ASSERT(0 <= last);
5046 KMP_DEBUG_ASSERT(n_places > last);
5047 KMP_DEBUG_ASSERT(last_place >= first_place);
5048 th = team->t.t_threads[f];
5049 KMP_DEBUG_ASSERT(th);
5050 __kmp_set_thread_place(team, th, first, last, place);
5051 KA_TRACE(100,
5052 ("__kmp_partition_places: spread: T#%d(%d:%d) place %d "
5053 "partition = [%d,%d], spacing = %.4f\n",
5054 __kmp_gtid_from_thread(team->t.t_threads[f]),
5055 team->t.t_id, f, th->th.th_new_place,
5056 th->th.th_first_place, th->th.th_last_place, spacing));
5057 }
5058 }
5059 }
5060 KMP_DEBUG_ASSERT(update_master_only || place == masters_place);
5061 } else {
5062 int S, rem, gap, s_count;
5063 S = n_th / n_places;
5064 s_count = 0;
5065 rem = n_th - (S * n_places);
5066 gap = rem > 0 ? n_places / rem : n_places;
5067 int place = masters_place;
5068 int gap_ct = gap;
5069 thidx = n_th;
5070 if (update_master_only == 1)
5071 thidx = 1;
5072 for (f = 0; f < thidx; f++) {
5073 kmp_info_t *th = team->t.t_threads[f];
5074 KMP_DEBUG_ASSERT(th != NULL);
5075
5076 __kmp_set_thread_place(team, th, place, place, place);
5077 s_count++;
5078
5079 if ((s_count == S) && rem && (gap_ct == gap)) {
5080 // do nothing, add an extra thread to place on next iteration
5081 } else if ((s_count == S + 1) && rem && (gap_ct == gap)) {
5082 // we added an extra thread to this place; move on to next place
5083 if (place == last_place) {
5084 place = first_place;
5085 } else if (place == (num_masks - 1)) {
5086 place = 0;
5087 } else {
5088 place++;
5089 }
5090 s_count = 0;
5091 gap_ct = 1;
5092 rem--;
5093 } else if (s_count == S) { // place is full; don't add extra thread
5094 if (place == last_place) {
5095 place = first_place;
5096 } else if (place == (num_masks - 1)) {
5097 place = 0;
5098 } else {
5099 place++;
5100 }
5101 gap_ct++;
5102 s_count = 0;
5103 }
5104
5105 KA_TRACE(100, ("__kmp_partition_places: spread: T#%d(%d:%d) place %d "
5106 "partition = [%d,%d]\n",
5107 __kmp_gtid_from_thread(team->t.t_threads[f]),
5108 team->t.t_id, f, th->th.th_new_place,
5109 th->th.th_first_place, th->th.th_last_place));
5110 }
5111 KMP_DEBUG_ASSERT(update_master_only || place == masters_place);
5112 }
5113 } break;
5114
5115 default:
5116 break;
5117 }
5118
5119 KA_TRACE(20, ("__kmp_partition_places: exit T#%d\n", team->t.t_id));
5120}
5121
5122#endif // KMP_AFFINITY_SUPPORTED
5123
5124/* allocate a new team data structure to use. take one off of the free pool if
5125 available */
5126kmp_team_t *__kmp_allocate_team(kmp_root_t *root, int new_nproc, int max_nproc,
5127#if OMPT_SUPPORT
5128 ompt_data_t ompt_parallel_data,
5129#endif
5130 kmp_proc_bind_t new_proc_bind,
5131 kmp_internal_control_t *new_icvs, int argc,
5132 kmp_info_t *master) {
5133 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_allocate_team);
5134 int f;
5135 kmp_team_t *team;
5136 int use_hot_team = !root->r.r_active;
5137 int level = 0;
5138 int do_place_partition = 1;
5139
5140 KA_TRACE(20, ("__kmp_allocate_team: called\n"));
5141 KMP_DEBUG_ASSERT(new_nproc >= 1 && argc >= 0);
5142 KMP_DEBUG_ASSERT(max_nproc >= new_nproc);
5143 KMP_MB();
5144
5145 kmp_hot_team_ptr_t *hot_teams;
5146 if (master) {
5147 team = master->th.th_team;
5148 level = team->t.t_active_level;
5149 if (master->th.th_teams_microtask) { // in teams construct?
5150 if (master->th.th_teams_size.nteams > 1 &&
5151 ( // #teams > 1
5152 team->t.t_pkfn ==
5153 (microtask_t)__kmp_teams_master || // inner fork of the teams
5154 master->th.th_teams_level <
5155 team->t.t_level)) { // or nested parallel inside the teams
5156 ++level; // not increment if #teams==1, or for outer fork of the teams;
5157 // increment otherwise
5158 }
5159 // Do not perform the place partition if inner fork of the teams
5160 // Wait until nested parallel region encountered inside teams construct
5161 if ((master->th.th_teams_size.nteams == 1 &&
5162 master->th.th_teams_level >= team->t.t_level) ||
5163 (team->t.t_pkfn == (microtask_t)__kmp_teams_master))
5164 do_place_partition = 0;
5165 }
5166 hot_teams = master->th.th_hot_teams;
5167 if (level < __kmp_hot_teams_max_level && hot_teams &&
5168 hot_teams[level].hot_team) {
5169 // hot team has already been allocated for given level
5170 use_hot_team = 1;
5171 } else {
5172 use_hot_team = 0;
5173 }
5174 } else {
5175 // check we won't access uninitialized hot_teams, just in case
5176 KMP_DEBUG_ASSERT(new_nproc == 1);
5177 }
5178 // Optimization to use a "hot" team
5179 if (use_hot_team && new_nproc > 1) {
5180 KMP_DEBUG_ASSERT(new_nproc <= max_nproc);
5181 team = hot_teams[level].hot_team;
5182#if KMP_DEBUG
5183 if (__kmp_tasking_mode != tskm_immediate_exec) {
5184 KA_TRACE(20, ("__kmp_allocate_team: hot team task_team[0] = %p "
5185 "task_team[1] = %p before reinit\n",
5186 team->t.t_task_team[0], team->t.t_task_team[1]));
5187 }
5188#endif
5189
5190 if (team->t.t_nproc != new_nproc &&
5191 __kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5192 // Distributed barrier may need a resize
5193 int old_nthr = team->t.t_nproc;
5194 __kmp_resize_dist_barrier(team, old_nthr, new_nproc);
5195 }
5196
5197 // If not doing the place partition, then reset the team's proc bind
5198 // to indicate that partitioning of all threads still needs to take place
5199 if (do_place_partition == 0)
5200 team->t.t_proc_bind = proc_bind_default;
5201 // Has the number of threads changed?
5202 /* Let's assume the most common case is that the number of threads is
5203 unchanged, and put that case first. */
5204 if (team->t.t_nproc == new_nproc) { // Check changes in number of threads
5205 KA_TRACE(20, ("__kmp_allocate_team: reusing hot team\n"));
5206 // This case can mean that omp_set_num_threads() was called and the hot
5207 // team size was already reduced, so we check the special flag
5208 if (team->t.t_size_changed == -1) {
5209 team->t.t_size_changed = 1;
5210 } else {
5211 KMP_CHECK_UPDATE(team->t.t_size_changed, 0);
5212 }
5213
5214 // TODO???: team->t.t_max_active_levels = new_max_active_levels;
5215 kmp_r_sched_t new_sched = new_icvs->sched;
5216 // set primary thread's schedule as new run-time schedule
5217 KMP_CHECK_UPDATE(team->t.t_sched.sched, new_sched.sched);
5218
5219 __kmp_reinitialize_team(team, new_icvs,
5220 root->r.r_uber_thread->th.th_ident);
5221
5222 KF_TRACE(10, ("__kmp_allocate_team2: T#%d, this_thread=%p team=%p\n", 0,
5223 team->t.t_threads[0], team));
5224 __kmp_push_current_task_to_thread(team->t.t_threads[0], team, 0);
5225
5226#if KMP_AFFINITY_SUPPORTED
5227 if ((team->t.t_size_changed == 0) &&
5228 (team->t.t_proc_bind == new_proc_bind)) {
5229 if (new_proc_bind == proc_bind_spread) {
5230 if (do_place_partition) {
5231 // add flag to update only master for spread
5232 __kmp_partition_places(team, 1);
5233 }
5234 }
5235 KA_TRACE(200, ("__kmp_allocate_team: reusing hot team #%d bindings: "
5236 "proc_bind = %d, partition = [%d,%d]\n",
5237 team->t.t_id, new_proc_bind, team->t.t_first_place,
5238 team->t.t_last_place));
5239 } else {
5240 if (do_place_partition) {
5241 KMP_CHECK_UPDATE(team->t.t_proc_bind, new_proc_bind);
5242 __kmp_partition_places(team);
5243 }
5244 }
5245#else
5246 KMP_CHECK_UPDATE(team->t.t_proc_bind, new_proc_bind);
5247#endif /* KMP_AFFINITY_SUPPORTED */
5248 } else if (team->t.t_nproc > new_nproc) {
5249 KA_TRACE(20,
5250 ("__kmp_allocate_team: decreasing hot team thread count to %d\n",
5251 new_nproc));
5252
5253 team->t.t_size_changed = 1;
5254 if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5255 // Barrier size already reduced earlier in this function
5256 // Activate team threads via th_used_in_team
5257 __kmp_add_threads_to_team(team, new_nproc);
5258 }
5259 // When decreasing team size, threads no longer in the team should
5260 // unref task team.
5261 if (__kmp_tasking_mode != tskm_immediate_exec) {
5262 for (f = new_nproc; f < team->t.t_nproc; f++) {
5263 kmp_info_t *th = team->t.t_threads[f];
5264 KMP_DEBUG_ASSERT(th);
5265 th->th.th_task_team = NULL;
5266 }
5267 }
5268 if (__kmp_hot_teams_mode == 0) {
5269 // AC: saved number of threads should correspond to team's value in this
5270 // mode, can be bigger in mode 1, when hot team has threads in reserve
5271 KMP_DEBUG_ASSERT(hot_teams[level].hot_team_nth == team->t.t_nproc);
5272 hot_teams[level].hot_team_nth = new_nproc;
5273 /* release the extra threads we don't need any more */
5274 for (f = new_nproc; f < team->t.t_nproc; f++) {
5275 KMP_DEBUG_ASSERT(team->t.t_threads[f]);
5276 __kmp_free_thread(team->t.t_threads[f]);
5277 team->t.t_threads[f] = NULL;
5278 }
5279 } // (__kmp_hot_teams_mode == 0)
5280 else {
5281 // When keeping extra threads in team, switch threads to wait on own
5282 // b_go flag
5283 for (f = new_nproc; f < team->t.t_nproc; ++f) {
5284 KMP_DEBUG_ASSERT(team->t.t_threads[f]);
5285 kmp_balign_t *balign = team->t.t_threads[f]->th.th_bar;
5286 for (int b = 0; b < bs_last_barrier; ++b) {
5287 if (balign[b].bb.wait_flag == KMP_BARRIER_PARENT_FLAG) {
5288 balign[b].bb.wait_flag = KMP_BARRIER_SWITCH_TO_OWN_FLAG;
5289 }
5290 KMP_CHECK_UPDATE(balign[b].bb.leaf_kids, 0);
5291 }
5292 }
5293 }
5294 team->t.t_nproc = new_nproc;
5295 // TODO???: team->t.t_max_active_levels = new_max_active_levels;
5296 KMP_CHECK_UPDATE(team->t.t_sched.sched, new_icvs->sched.sched);
5297 __kmp_reinitialize_team(team, new_icvs,
5298 root->r.r_uber_thread->th.th_ident);
5299
5300 // Update remaining threads
5301 for (f = 0; f < new_nproc; ++f) {
5302 team->t.t_threads[f]->th.th_team_nproc = new_nproc;
5303 }
5304
5305 // restore the current task state of the primary thread: should be the
5306 // implicit task
5307 KF_TRACE(10, ("__kmp_allocate_team: T#%d, this_thread=%p team=%p\n", 0,
5308 team->t.t_threads[0], team));
5309
5310 __kmp_push_current_task_to_thread(team->t.t_threads[0], team, 0);
5311
5312#ifdef KMP_DEBUG
5313 for (f = 0; f < team->t.t_nproc; f++) {
5314 KMP_DEBUG_ASSERT(team->t.t_threads[f] &&
5315 team->t.t_threads[f]->th.th_team_nproc ==
5316 team->t.t_nproc);
5317 }
5318#endif
5319
5320 if (do_place_partition) {
5321 KMP_CHECK_UPDATE(team->t.t_proc_bind, new_proc_bind);
5322#if KMP_AFFINITY_SUPPORTED
5323 __kmp_partition_places(team);
5324#endif
5325 }
5326 } else { // team->t.t_nproc < new_nproc
5327
5328 KA_TRACE(20,
5329 ("__kmp_allocate_team: increasing hot team thread count to %d\n",
5330 new_nproc));
5331 int old_nproc = team->t.t_nproc; // save old value and use to update only
5332 team->t.t_size_changed = 1;
5333
5334 int avail_threads = hot_teams[level].hot_team_nth;
5335 if (new_nproc < avail_threads)
5336 avail_threads = new_nproc;
5337 kmp_info_t **other_threads = team->t.t_threads;
5338 for (f = team->t.t_nproc; f < avail_threads; ++f) {
5339 // Adjust barrier data of reserved threads (if any) of the team
5340 // Other data will be set in __kmp_initialize_info() below.
5341 int b;
5342 kmp_balign_t *balign = other_threads[f]->th.th_bar;
5343 for (b = 0; b < bs_last_barrier; ++b) {
5344 balign[b].bb.b_arrived = team->t.t_bar[b].b_arrived;
5345 KMP_DEBUG_ASSERT(balign[b].bb.wait_flag != KMP_BARRIER_PARENT_FLAG);
5346#if USE_DEBUGGER
5347 balign[b].bb.b_worker_arrived = team->t.t_bar[b].b_team_arrived;
5348#endif
5349 }
5350 }
5351 if (hot_teams[level].hot_team_nth >= new_nproc) {
5352 // we have all needed threads in reserve, no need to allocate any
5353 // this only possible in mode 1, cannot have reserved threads in mode 0
5354 KMP_DEBUG_ASSERT(__kmp_hot_teams_mode == 1);
5355 team->t.t_nproc = new_nproc; // just get reserved threads involved
5356 } else {
5357 // We may have some threads in reserve, but not enough;
5358 // get reserved threads involved if any.
5359 team->t.t_nproc = hot_teams[level].hot_team_nth;
5360 hot_teams[level].hot_team_nth = new_nproc; // adjust hot team max size
5361 if (team->t.t_max_nproc < new_nproc) {
5362 /* reallocate larger arrays */
5363 __kmp_reallocate_team_arrays(team, new_nproc);
5364 __kmp_reinitialize_team(team, new_icvs, NULL);
5365 }
5366
5367#if (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY) && \
5368 KMP_AFFINITY_SUPPORTED
5369 /* Temporarily set full mask for primary thread before creation of
5370 workers. The reason is that workers inherit the affinity from the
5371 primary thread, so if a lot of workers are created on the single
5372 core quickly, they don't get a chance to set their own affinity for
5373 a long time. */
5374 kmp_affinity_raii_t new_temp_affinity{__kmp_affin_fullMask};
5375#endif
5376
5377 /* allocate new threads for the hot team */
5378 for (f = team->t.t_nproc; f < new_nproc; f++) {
5379 kmp_info_t *new_worker = __kmp_allocate_thread(root, team, f);
5380 KMP_DEBUG_ASSERT(new_worker);
5381 team->t.t_threads[f] = new_worker;
5382
5383 KA_TRACE(20,
5384 ("__kmp_allocate_team: team %d init T#%d arrived: "
5385 "join=%llu, plain=%llu\n",
5386 team->t.t_id, __kmp_gtid_from_tid(f, team), team->t.t_id, f,
5387 team->t.t_bar[bs_forkjoin_barrier].b_arrived,
5388 team->t.t_bar[bs_plain_barrier].b_arrived));
5389
5390 { // Initialize barrier data for new threads.
5391 int b;
5392 kmp_balign_t *balign = new_worker->th.th_bar;
5393 for (b = 0; b < bs_last_barrier; ++b) {
5394 balign[b].bb.b_arrived = team->t.t_bar[b].b_arrived;
5395 KMP_DEBUG_ASSERT(balign[b].bb.wait_flag !=
5396 KMP_BARRIER_PARENT_FLAG);
5397#if USE_DEBUGGER
5398 balign[b].bb.b_worker_arrived = team->t.t_bar[b].b_team_arrived;
5399#endif
5400 }
5401 }
5402 }
5403
5404#if (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY) && \
5405 KMP_AFFINITY_SUPPORTED
5406 /* Restore initial primary thread's affinity mask */
5407 new_temp_affinity.restore();
5408#endif
5409 } // end of check of t_nproc vs. new_nproc vs. hot_team_nth
5410 if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5411 // Barrier size already increased earlier in this function
5412 // Activate team threads via th_used_in_team
5413 __kmp_add_threads_to_team(team, new_nproc);
5414 }
5415 /* make sure everyone is syncronized */
5416 // new threads below
5417 __kmp_initialize_team(team, new_nproc, new_icvs,
5418 root->r.r_uber_thread->th.th_ident);
5419
5420 /* reinitialize the threads */
5421 KMP_DEBUG_ASSERT(team->t.t_nproc == new_nproc);
5422 for (f = 0; f < team->t.t_nproc; ++f)
5423 __kmp_initialize_info(team->t.t_threads[f], team, f,
5424 __kmp_gtid_from_tid(f, team));
5425
5426 // set th_task_state for new threads in hot team with older thread's state
5427 kmp_uint8 old_state = team->t.t_threads[old_nproc - 1]->th.th_task_state;
5428 for (f = old_nproc; f < team->t.t_nproc; ++f)
5429 team->t.t_threads[f]->th.th_task_state = old_state;
5430
5431#ifdef KMP_DEBUG
5432 for (f = 0; f < team->t.t_nproc; ++f) {
5433 KMP_DEBUG_ASSERT(team->t.t_threads[f] &&
5434 team->t.t_threads[f]->th.th_team_nproc ==
5435 team->t.t_nproc);
5436 }
5437#endif
5438
5439 if (do_place_partition) {
5440 KMP_CHECK_UPDATE(team->t.t_proc_bind, new_proc_bind);
5441#if KMP_AFFINITY_SUPPORTED
5442 __kmp_partition_places(team);
5443#endif
5444 }
5445 } // Check changes in number of threads
5446
5447 if (master->th.th_teams_microtask) {
5448 for (f = 1; f < new_nproc; ++f) {
5449 // propagate teams construct specific info to workers
5450 kmp_info_t *thr = team->t.t_threads[f];
5451 thr->th.th_teams_microtask = master->th.th_teams_microtask;
5452 thr->th.th_teams_level = master->th.th_teams_level;
5453 thr->th.th_teams_size = master->th.th_teams_size;
5454 }
5455 }
5456 if (level) {
5457 // Sync barrier state for nested hot teams, not needed for outermost hot
5458 // team.
5459 for (f = 1; f < new_nproc; ++f) {
5460 kmp_info_t *thr = team->t.t_threads[f];
5461 int b;
5462 kmp_balign_t *balign = thr->th.th_bar;
5463 for (b = 0; b < bs_last_barrier; ++b) {
5464 balign[b].bb.b_arrived = team->t.t_bar[b].b_arrived;
5465 KMP_DEBUG_ASSERT(balign[b].bb.wait_flag != KMP_BARRIER_PARENT_FLAG);
5466#if USE_DEBUGGER
5467 balign[b].bb.b_worker_arrived = team->t.t_bar[b].b_team_arrived;
5468#endif
5469 }
5470 }
5471 }
5472
5473 /* reallocate space for arguments if necessary */
5474 __kmp_alloc_argv_entries(argc, team, TRUE);
5475 KMP_CHECK_UPDATE(team->t.t_argc, argc);
5476 // The hot team re-uses the previous task team,
5477 // if untouched during the previous release->gather phase.
5478
5479 KF_TRACE(10, (" hot_team = %p\n", team));
5480
5481#if KMP_DEBUG
5482 if (__kmp_tasking_mode != tskm_immediate_exec) {
5483 KA_TRACE(20, ("__kmp_allocate_team: hot team task_team[0] = %p "
5484 "task_team[1] = %p after reinit\n",
5485 team->t.t_task_team[0], team->t.t_task_team[1]));
5486 }
5487#endif
5488
5489#if OMPT_SUPPORT
5490 __ompt_team_assign_id(team, ompt_parallel_data);
5491#endif
5492
5493 KMP_MB();
5494
5495 return team;
5496 }
5497
5498 /* next, let's try to take one from the team pool */
5499 KMP_MB();
5500 for (team = CCAST(kmp_team_t *, __kmp_team_pool); (team);) {
5501 /* TODO: consider resizing undersized teams instead of reaping them, now
5502 that we have a resizing mechanism */
5503 if (team->t.t_max_nproc >= max_nproc) {
5504 /* take this team from the team pool */
5505 __kmp_team_pool = team->t.t_next_pool;
5506
5507 if (max_nproc > 1 &&
5508 __kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5509 if (!team->t.b) { // Allocate barrier structure
5510 team->t.b = distributedBarrier::allocate(__kmp_dflt_team_nth_ub);
5511 }
5512 }
5513
5514 /* setup the team for fresh use */
5515 __kmp_initialize_team(team, new_nproc, new_icvs, NULL);
5516
5517 KA_TRACE(20, ("__kmp_allocate_team: setting task_team[0] %p and "
5518 "task_team[1] %p to NULL\n",
5519 &team->t.t_task_team[0], &team->t.t_task_team[1]));
5520 team->t.t_task_team[0] = NULL;
5521 team->t.t_task_team[1] = NULL;
5522
5523 /* reallocate space for arguments if necessary */
5524 __kmp_alloc_argv_entries(argc, team, TRUE);
5525 KMP_CHECK_UPDATE(team->t.t_argc, argc);
5526
5527 KA_TRACE(
5528 20, ("__kmp_allocate_team: team %d init arrived: join=%u, plain=%u\n",
5529 team->t.t_id, KMP_INIT_BARRIER_STATE, KMP_INIT_BARRIER_STATE));
5530 { // Initialize barrier data.
5531 int b;
5532 for (b = 0; b < bs_last_barrier; ++b) {
5533 team->t.t_bar[b].b_arrived = KMP_INIT_BARRIER_STATE;
5534#if USE_DEBUGGER
5535 team->t.t_bar[b].b_master_arrived = 0;
5536 team->t.t_bar[b].b_team_arrived = 0;
5537#endif
5538 }
5539 }
5540
5541 team->t.t_proc_bind = new_proc_bind;
5542
5543 KA_TRACE(20, ("__kmp_allocate_team: using team from pool %d.\n",
5544 team->t.t_id));
5545
5546#if OMPT_SUPPORT
5547 __ompt_team_assign_id(team, ompt_parallel_data);
5548#endif
5549
5550 team->t.t_nested_nth = NULL;
5551
5552 KMP_MB();
5553
5554 return team;
5555 }
5556
5557 /* reap team if it is too small, then loop back and check the next one */
5558 // not sure if this is wise, but, will be redone during the hot-teams
5559 // rewrite.
5560 /* TODO: Use technique to find the right size hot-team, don't reap them */
5561 team = __kmp_reap_team(team);
5562 __kmp_team_pool = team;
5563 }
5564
5565 /* nothing available in the pool, no matter, make a new team! */
5566 KMP_MB();
5567 team = (kmp_team_t *)__kmp_allocate(sizeof(kmp_team_t));
5568
5569 /* and set it up */
5570 team->t.t_max_nproc = max_nproc;
5571 if (max_nproc > 1 &&
5572 __kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5573 // Allocate barrier structure
5574 team->t.b = distributedBarrier::allocate(__kmp_dflt_team_nth_ub);
5575 }
5576
5577 /* NOTE well, for some reason allocating one big buffer and dividing it up
5578 seems to really hurt performance a lot on the P4, so, let's not use this */
5579 __kmp_allocate_team_arrays(team, max_nproc);
5580
5581 KA_TRACE(20, ("__kmp_allocate_team: making a new team\n"));
5582 __kmp_initialize_team(team, new_nproc, new_icvs, NULL);
5583
5584 KA_TRACE(20, ("__kmp_allocate_team: setting task_team[0] %p and task_team[1] "
5585 "%p to NULL\n",
5586 &team->t.t_task_team[0], &team->t.t_task_team[1]));
5587 team->t.t_task_team[0] = NULL; // to be removed, as __kmp_allocate zeroes
5588 // memory, no need to duplicate
5589 team->t.t_task_team[1] = NULL; // to be removed, as __kmp_allocate zeroes
5590 // memory, no need to duplicate
5591
5592 if (__kmp_storage_map) {
5593 __kmp_print_team_storage_map("team", team, team->t.t_id, new_nproc);
5594 }
5595
5596 /* allocate space for arguments */
5597 __kmp_alloc_argv_entries(argc, team, FALSE);
5598 team->t.t_argc = argc;
5599
5600 KA_TRACE(20,
5601 ("__kmp_allocate_team: team %d init arrived: join=%u, plain=%u\n",
5602 team->t.t_id, KMP_INIT_BARRIER_STATE, KMP_INIT_BARRIER_STATE));
5603 { // Initialize barrier data.
5604 int b;
5605 for (b = 0; b < bs_last_barrier; ++b) {
5606 team->t.t_bar[b].b_arrived = KMP_INIT_BARRIER_STATE;
5607#if USE_DEBUGGER
5608 team->t.t_bar[b].b_master_arrived = 0;
5609 team->t.t_bar[b].b_team_arrived = 0;
5610#endif
5611 }
5612 }
5613
5614 team->t.t_proc_bind = new_proc_bind;
5615
5616#if OMPT_SUPPORT
5617 __ompt_team_assign_id(team, ompt_parallel_data);
5618 team->t.ompt_serialized_team_info = NULL;
5619#endif
5620
5621 KMP_MB();
5622
5623 team->t.t_nested_nth = NULL;
5624
5625 KA_TRACE(20, ("__kmp_allocate_team: done creating a new team %d.\n",
5626 team->t.t_id));
5627
5628 return team;
5629}
5630
5631/* TODO implement hot-teams at all levels */
5632/* TODO implement lazy thread release on demand (disband request) */
5633
5634/* free the team. return it to the team pool. release all the threads
5635 * associated with it */
5636void __kmp_free_team(kmp_root_t *root, kmp_team_t *team, kmp_info_t *master) {
5637 int f;
5638 KA_TRACE(20, ("__kmp_free_team: T#%d freeing team %d\n", __kmp_get_gtid(),
5639 team->t.t_id));
5640
5641 /* verify state */
5642 KMP_DEBUG_ASSERT(root);
5643 KMP_DEBUG_ASSERT(team);
5644 KMP_DEBUG_ASSERT(team->t.t_nproc <= team->t.t_max_nproc);
5645 KMP_DEBUG_ASSERT(team->t.t_threads);
5646
5647 int use_hot_team = team == root->r.r_hot_team;
5648 int level;
5649 if (master) {
5650 level = team->t.t_active_level - 1;
5651 if (master->th.th_teams_microtask) { // in teams construct?
5652 if (master->th.th_teams_size.nteams > 1) {
5653 ++level; // level was not increased in teams construct for
5654 // team_of_masters
5655 }
5656 if (team->t.t_pkfn != (microtask_t)__kmp_teams_master &&
5657 master->th.th_teams_level == team->t.t_level) {
5658 ++level; // level was not increased in teams construct for
5659 // team_of_workers before the parallel
5660 } // team->t.t_level will be increased inside parallel
5661 }
5662#if KMP_DEBUG
5663 kmp_hot_team_ptr_t *hot_teams = master->th.th_hot_teams;
5664#endif
5665 if (level < __kmp_hot_teams_max_level) {
5666 KMP_DEBUG_ASSERT(team == hot_teams[level].hot_team);
5667 use_hot_team = 1;
5668 }
5669 }
5670
5671 /* team is done working */
5672 TCW_SYNC_PTR(team->t.t_pkfn,
5673 NULL); // Important for Debugging Support Library.
5674#if KMP_OS_WINDOWS
5675 team->t.t_copyin_counter = 0; // init counter for possible reuse
5676#endif
5677 // Do not reset pointer to parent team to NULL for hot teams.
5678
5679 /* if we are non-hot team, release our threads */
5680 if (!use_hot_team) {
5681 if (__kmp_tasking_mode != tskm_immediate_exec) {
5682 // Wait for threads to reach reapable state
5683 for (f = 1; f < team->t.t_nproc; ++f) {
5684 KMP_DEBUG_ASSERT(team->t.t_threads[f]);
5685 kmp_info_t *th = team->t.t_threads[f];
5686 volatile kmp_uint32 *state = &th->th.th_reap_state;
5687 while (*state != KMP_SAFE_TO_REAP) {
5688#if KMP_OS_WINDOWS
5689 // On Windows a thread can be killed at any time, check this
5690 DWORD ecode;
5691 if (!__kmp_is_thread_alive(th, &ecode)) {
5692 *state = KMP_SAFE_TO_REAP; // reset the flag for dead thread
5693 break;
5694 }
5695#endif
5696 // first check if thread is sleeping
5697 if (th->th.th_sleep_loc)
5698 __kmp_null_resume_wrapper(th);
5699 KMP_CPU_PAUSE();
5700 }
5701 }
5702
5703 // Delete task teams
5704 int tt_idx;
5705 for (tt_idx = 0; tt_idx < 2; ++tt_idx) {
5706 kmp_task_team_t *task_team = team->t.t_task_team[tt_idx];
5707 if (task_team != NULL) {
5708 for (f = 0; f < team->t.t_nproc; ++f) { // threads unref task teams
5709 KMP_DEBUG_ASSERT(team->t.t_threads[f]);
5710 team->t.t_threads[f]->th.th_task_team = NULL;
5711 }
5712 KA_TRACE(
5713 20,
5714 ("__kmp_free_team: T#%d deactivating task_team %p on team %d\n",
5715 __kmp_get_gtid(), task_team, team->t.t_id));
5716 __kmp_free_task_team(master, task_team);
5717 team->t.t_task_team[tt_idx] = NULL;
5718 }
5719 }
5720 }
5721
5722 // Before clearing parent pointer, check if nested_nth list should be freed
5723 if (team->t.t_nested_nth && team->t.t_nested_nth != &__kmp_nested_nth &&
5724 team->t.t_nested_nth != team->t.t_parent->t.t_nested_nth) {
5725 KMP_INTERNAL_FREE(team->t.t_nested_nth->nth);
5726 KMP_INTERNAL_FREE(team->t.t_nested_nth);
5727 }
5728 team->t.t_nested_nth = NULL;
5729
5730 // Reset pointer to parent team only for non-hot teams.
5731 team->t.t_parent = NULL;
5732 team->t.t_level = 0;
5733 team->t.t_active_level = 0;
5734
5735 /* free the worker threads */
5736 for (f = 1; f < team->t.t_nproc; ++f) {
5737 KMP_DEBUG_ASSERT(team->t.t_threads[f]);
5738 if (__kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5739 (void)KMP_COMPARE_AND_STORE_ACQ32(
5740 &(team->t.t_threads[f]->th.th_used_in_team), 1, 2);
5741 }
5742 __kmp_free_thread(team->t.t_threads[f]);
5743 }
5744
5745 if (__kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5746 if (team->t.b) {
5747 // wake up thread at old location
5748 team->t.b->go_release();
5749 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) {
5750 for (f = 1; f < team->t.t_nproc; ++f) {
5751 if (team->t.b->sleep[f].sleep) {
5752 __kmp_atomic_resume_64(
5753 team->t.t_threads[f]->th.th_info.ds.ds_gtid,
5754 (kmp_atomic_flag_64<> *)NULL);
5755 }
5756 }
5757 }
5758 // Wait for threads to be removed from team
5759 for (int f = 1; f < team->t.t_nproc; ++f) {
5760 while (team->t.t_threads[f]->th.th_used_in_team.load() != 0)
5761 KMP_CPU_PAUSE();
5762 }
5763 }
5764 }
5765
5766 for (f = 1; f < team->t.t_nproc; ++f) {
5767 team->t.t_threads[f] = NULL;
5768 }
5769
5770 if (team->t.t_max_nproc > 1 &&
5771 __kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5772 distributedBarrier::deallocate(team->t.b);
5773 team->t.b = NULL;
5774 }
5775 /* put the team back in the team pool */
5776 /* TODO limit size of team pool, call reap_team if pool too large */
5777 team->t.t_next_pool = CCAST(kmp_team_t *, __kmp_team_pool);
5778 __kmp_team_pool = (volatile kmp_team_t *)team;
5779 } else { // Check if team was created for primary threads in teams construct
5780 // See if first worker is a CG root
5781 KMP_DEBUG_ASSERT(team->t.t_threads[1] &&
5782 team->t.t_threads[1]->th.th_cg_roots);
5783 if (team->t.t_threads[1]->th.th_cg_roots->cg_root == team->t.t_threads[1]) {
5784 // Clean up the CG root nodes on workers so that this team can be re-used
5785 for (f = 1; f < team->t.t_nproc; ++f) {
5786 kmp_info_t *thr = team->t.t_threads[f];
5787 KMP_DEBUG_ASSERT(thr && thr->th.th_cg_roots &&
5788 thr->th.th_cg_roots->cg_root == thr);
5789 // Pop current CG root off list
5790 kmp_cg_root_t *tmp = thr->th.th_cg_roots;
5791 thr->th.th_cg_roots = tmp->up;
5792 KA_TRACE(100, ("__kmp_free_team: Thread %p popping node %p and moving"
5793 " up to node %p. cg_nthreads was %d\n",
5794 thr, tmp, thr->th.th_cg_roots, tmp->cg_nthreads));
5795 int i = tmp->cg_nthreads--;
5796 if (i == 1) {
5797 __kmp_free(tmp); // free CG if we are the last thread in it
5798 }
5799 // Restore current task's thread_limit from CG root
5800 if (thr->th.th_cg_roots)
5801 thr->th.th_current_task->td_icvs.thread_limit =
5802 thr->th.th_cg_roots->cg_thread_limit;
5803 }
5804 }
5805 }
5806
5807 KMP_MB();
5808}
5809
5810/* reap the team. destroy it, reclaim all its resources and free its memory */
5811kmp_team_t *__kmp_reap_team(kmp_team_t *team) {
5812 kmp_team_t *next_pool = team->t.t_next_pool;
5813
5814 KMP_DEBUG_ASSERT(team);
5815 KMP_DEBUG_ASSERT(team->t.t_dispatch);
5816 KMP_DEBUG_ASSERT(team->t.t_disp_buffer);
5817 KMP_DEBUG_ASSERT(team->t.t_threads);
5818 KMP_DEBUG_ASSERT(team->t.t_argv);
5819
5820 /* TODO clean the threads that are a part of this? */
5821
5822 /* free stuff */
5823 __kmp_free_team_arrays(team);
5824 if (team->t.t_argv != &team->t.t_inline_argv[0])
5825 __kmp_free((void *)team->t.t_argv);
5826 __kmp_free(team);
5827
5828 KMP_MB();
5829 return next_pool;
5830}
5831
5832// Free the thread. Don't reap it, just place it on the pool of available
5833// threads.
5834//
5835// Changes for Quad issue 527845: We need a predictable OMP tid <-> gtid
5836// binding for the affinity mechanism to be useful.
5837//
5838// Now, we always keep the free list (__kmp_thread_pool) sorted by gtid.
5839// However, we want to avoid a potential performance problem by always
5840// scanning through the list to find the correct point at which to insert
5841// the thread (potential N**2 behavior). To do this we keep track of the
5842// last place a thread struct was inserted (__kmp_thread_pool_insert_pt).
5843// With single-level parallelism, threads will always be added to the tail
5844// of the list, kept track of by __kmp_thread_pool_insert_pt. With nested
5845// parallelism, all bets are off and we may need to scan through the entire
5846// free list.
5847//
5848// This change also has a potentially large performance benefit, for some
5849// applications. Previously, as threads were freed from the hot team, they
5850// would be placed back on the free list in inverse order. If the hot team
5851// grew back to it's original size, then the freed thread would be placed
5852// back on the hot team in reverse order. This could cause bad cache
5853// locality problems on programs where the size of the hot team regularly
5854// grew and shrunk.
5855//
5856// Now, for single-level parallelism, the OMP tid is always == gtid.
5857void __kmp_free_thread(kmp_info_t *this_th) {
5858 int gtid;
5859 kmp_info_t **scan;
5860
5861 KA_TRACE(20, ("__kmp_free_thread: T#%d putting T#%d back on free pool.\n",
5862 __kmp_get_gtid(), this_th->th.th_info.ds.ds_gtid));
5863
5864 KMP_DEBUG_ASSERT(this_th);
5865
5866 // When moving thread to pool, switch thread to wait on own b_go flag, and
5867 // uninitialized (NULL team).
5868 int b;
5869 kmp_balign_t *balign = this_th->th.th_bar;
5870 for (b = 0; b < bs_last_barrier; ++b) {
5871 if (balign[b].bb.wait_flag == KMP_BARRIER_PARENT_FLAG)
5872 balign[b].bb.wait_flag = KMP_BARRIER_SWITCH_TO_OWN_FLAG;
5873 balign[b].bb.team = NULL;
5874 balign[b].bb.leaf_kids = 0;
5875 }
5876 this_th->th.th_task_state = 0;
5877 this_th->th.th_reap_state = KMP_SAFE_TO_REAP;
5878
5879 /* put thread back on the free pool */
5880 TCW_PTR(this_th->th.th_team, NULL);
5881 TCW_PTR(this_th->th.th_root, NULL);
5882 TCW_PTR(this_th->th.th_dispatch, NULL); /* NOT NEEDED */
5883
5884 while (this_th->th.th_cg_roots) {
5885 this_th->th.th_cg_roots->cg_nthreads--;
5886 KA_TRACE(100, ("__kmp_free_thread: Thread %p decrement cg_nthreads on node"
5887 " %p of thread %p to %d\n",
5888 this_th, this_th->th.th_cg_roots,
5889 this_th->th.th_cg_roots->cg_root,
5890 this_th->th.th_cg_roots->cg_nthreads));
5891 kmp_cg_root_t *tmp = this_th->th.th_cg_roots;
5892 if (tmp->cg_root == this_th) { // Thread is a cg_root
5893 KMP_DEBUG_ASSERT(tmp->cg_nthreads == 0);
5894 KA_TRACE(
5895 5, ("__kmp_free_thread: Thread %p freeing node %p\n", this_th, tmp));
5896 this_th->th.th_cg_roots = tmp->up;
5897 __kmp_free(tmp);
5898 } else { // Worker thread
5899 if (tmp->cg_nthreads == 0) { // last thread leaves contention group
5900 __kmp_free(tmp);
5901 }
5902 this_th->th.th_cg_roots = NULL;
5903 break;
5904 }
5905 }
5906
5907 /* If the implicit task assigned to this thread can be used by other threads
5908 * -> multiple threads can share the data and try to free the task at
5909 * __kmp_reap_thread at exit. This duplicate use of the task data can happen
5910 * with higher probability when hot team is disabled but can occurs even when
5911 * the hot team is enabled */
5912 __kmp_free_implicit_task(this_th);
5913 this_th->th.th_current_task = NULL;
5914
5915 // If the __kmp_thread_pool_insert_pt is already past the new insert
5916 // point, then we need to re-scan the entire list.
5917 gtid = this_th->th.th_info.ds.ds_gtid;
5918 if (__kmp_thread_pool_insert_pt != NULL) {
5919 KMP_DEBUG_ASSERT(__kmp_thread_pool != NULL);
5920 if (__kmp_thread_pool_insert_pt->th.th_info.ds.ds_gtid > gtid) {
5921 __kmp_thread_pool_insert_pt = NULL;
5922 }
5923 }
5924
5925 // Scan down the list to find the place to insert the thread.
5926 // scan is the address of a link in the list, possibly the address of
5927 // __kmp_thread_pool itself.
5928 //
5929 // In the absence of nested parallelism, the for loop will have 0 iterations.
5930 if (__kmp_thread_pool_insert_pt != NULL) {
5931 scan = &(__kmp_thread_pool_insert_pt->th.th_next_pool);
5932 } else {
5933 scan = CCAST(kmp_info_t **, &__kmp_thread_pool);
5934 }
5935 for (; (*scan != NULL) && ((*scan)->th.th_info.ds.ds_gtid < gtid);
5936 scan = &((*scan)->th.th_next_pool))
5937 ;
5938
5939 // Insert the new element on the list, and set __kmp_thread_pool_insert_pt
5940 // to its address.
5941 TCW_PTR(this_th->th.th_next_pool, *scan);
5942 __kmp_thread_pool_insert_pt = *scan = this_th;
5943 KMP_DEBUG_ASSERT((this_th->th.th_next_pool == NULL) ||
5944 (this_th->th.th_info.ds.ds_gtid <
5945 this_th->th.th_next_pool->th.th_info.ds.ds_gtid));
5946 TCW_4(this_th->th.th_in_pool, TRUE);
5947 __kmp_suspend_initialize_thread(this_th);
5948 __kmp_lock_suspend_mx(this_th);
5949 if (this_th->th.th_active == TRUE) {
5950 KMP_ATOMIC_INC(&__kmp_thread_pool_active_nth);
5951 this_th->th.th_active_in_pool = TRUE;
5952 }
5953#if KMP_DEBUG
5954 else {
5955 KMP_DEBUG_ASSERT(this_th->th.th_active_in_pool == FALSE);
5956 }
5957#endif
5958 __kmp_unlock_suspend_mx(this_th);
5959
5960 TCW_4(__kmp_nth, __kmp_nth - 1);
5961
5962#ifdef KMP_ADJUST_BLOCKTIME
5963 /* Adjust blocktime back to user setting or default if necessary */
5964 /* Middle initialization might never have occurred */
5965 if (!__kmp_env_blocktime && (__kmp_avail_proc > 0)) {
5966 KMP_DEBUG_ASSERT(__kmp_avail_proc > 0);
5967 if (__kmp_nth <= __kmp_avail_proc) {
5968 __kmp_zero_bt = FALSE;
5969 }
5970 }
5971#endif /* KMP_ADJUST_BLOCKTIME */
5972
5973 KMP_MB();
5974}
5975
5976/* ------------------------------------------------------------------------ */
5977
5978void *__kmp_launch_thread(kmp_info_t *this_thr) {
5979#if OMP_PROFILING_SUPPORT
5980 ProfileTraceFile = getenv("LIBOMPTARGET_PROFILE");
5981 // TODO: add a configuration option for time granularity
5982 if (ProfileTraceFile)
5983 llvm::timeTraceProfilerInitialize(500 /* us */, "libomptarget");
5984#endif
5985
5986 int gtid = this_thr->th.th_info.ds.ds_gtid;
5987 /* void *stack_data;*/
5988 kmp_team_t **volatile pteam;
5989
5990 KMP_MB();
5991 KA_TRACE(10, ("__kmp_launch_thread: T#%d start\n", gtid));
5992
5993 if (__kmp_env_consistency_check) {
5994 this_thr->th.th_cons = __kmp_allocate_cons_stack(gtid); // ATT: Memory leak?
5995 }
5996
5997#if OMPD_SUPPORT
5998 if (ompd_state & OMPD_ENABLE_BP)
5999 ompd_bp_thread_begin();
6000#endif
6001
6002#if OMPT_SUPPORT
6003 ompt_data_t *thread_data = nullptr;
6004 if (ompt_enabled.enabled) {
6005 thread_data = &(this_thr->th.ompt_thread_info.thread_data);
6006 *thread_data = ompt_data_none;
6007
6008 this_thr->th.ompt_thread_info.state = ompt_state_overhead;
6009 this_thr->th.ompt_thread_info.wait_id = 0;
6010 this_thr->th.ompt_thread_info.idle_frame = OMPT_GET_FRAME_ADDRESS(0);
6011 this_thr->th.ompt_thread_info.parallel_flags = 0;
6012 if (ompt_enabled.ompt_callback_thread_begin) {
6013 ompt_callbacks.ompt_callback(ompt_callback_thread_begin)(
6014 ompt_thread_worker, thread_data);
6015 }
6016 this_thr->th.ompt_thread_info.state = ompt_state_idle;
6017 }
6018#endif
6019
6020 /* This is the place where threads wait for work */
6021 while (!TCR_4(__kmp_global.g.g_done)) {
6022 KMP_DEBUG_ASSERT(this_thr == __kmp_threads[gtid]);
6023 KMP_MB();
6024
6025 /* wait for work to do */
6026 KA_TRACE(20, ("__kmp_launch_thread: T#%d waiting for work\n", gtid));
6027
6028 /* No tid yet since not part of a team */
6029 __kmp_fork_barrier(gtid, KMP_GTID_DNE);
6030
6031#if OMPT_SUPPORT
6032 if (ompt_enabled.enabled) {
6033 this_thr->th.ompt_thread_info.state = ompt_state_overhead;
6034 }
6035#endif
6036
6037 pteam = &this_thr->th.th_team;
6038
6039 /* have we been allocated? */
6040 if (TCR_SYNC_PTR(*pteam) && !TCR_4(__kmp_global.g.g_done)) {
6041 /* we were just woken up, so run our new task */
6042 if (TCR_SYNC_PTR((*pteam)->t.t_pkfn) != NULL) {
6043 int rc;
6044 KA_TRACE(20,
6045 ("__kmp_launch_thread: T#%d(%d:%d) invoke microtask = %p\n",
6046 gtid, (*pteam)->t.t_id, __kmp_tid_from_gtid(gtid),
6047 (*pteam)->t.t_pkfn));
6048
6049 updateHWFPControl(*pteam);
6050
6051#if OMPT_SUPPORT
6052 if (ompt_enabled.enabled) {
6053 this_thr->th.ompt_thread_info.state = ompt_state_work_parallel;
6054 }
6055#endif
6056
6057 rc = (*pteam)->t.t_invoke(gtid);
6058 KMP_ASSERT(rc);
6059
6060 KMP_MB();
6061 KA_TRACE(20, ("__kmp_launch_thread: T#%d(%d:%d) done microtask = %p\n",
6062 gtid, (*pteam)->t.t_id, __kmp_tid_from_gtid(gtid),
6063 (*pteam)->t.t_pkfn));
6064 }
6065#if OMPT_SUPPORT
6066 if (ompt_enabled.enabled) {
6067 /* no frame set while outside task */
6068 __ompt_get_task_info_object(0)->frame.exit_frame = ompt_data_none;
6069
6070 this_thr->th.ompt_thread_info.state = ompt_state_overhead;
6071 }
6072#endif
6073 /* join barrier after parallel region */
6074 __kmp_join_barrier(gtid);
6075 }
6076 }
6077
6078#if OMPD_SUPPORT
6079 if (ompd_state & OMPD_ENABLE_BP)
6080 ompd_bp_thread_end();
6081#endif
6082
6083#if OMPT_SUPPORT
6084 if (ompt_enabled.ompt_callback_thread_end) {
6085 ompt_callbacks.ompt_callback(ompt_callback_thread_end)(thread_data);
6086 }
6087#endif
6088
6089 this_thr->th.th_task_team = NULL;
6090 /* run the destructors for the threadprivate data for this thread */
6091 __kmp_common_destroy_gtid(gtid);
6092
6093 KA_TRACE(10, ("__kmp_launch_thread: T#%d done\n", gtid));
6094 KMP_MB();
6095
6096#if OMP_PROFILING_SUPPORT
6097 llvm::timeTraceProfilerFinishThread();
6098#endif
6099 return this_thr;
6100}
6101
6102/* ------------------------------------------------------------------------ */
6103
6104void __kmp_internal_end_dest(void *specific_gtid) {
6105 // Make sure no significant bits are lost
6106 int gtid;
6107 __kmp_type_convert((kmp_intptr_t)specific_gtid - 1, &gtid);
6108
6109 KA_TRACE(30, ("__kmp_internal_end_dest: T#%d\n", gtid));
6110 /* NOTE: the gtid is stored as gitd+1 in the thread-local-storage
6111 * this is because 0 is reserved for the nothing-stored case */
6112
6113 __kmp_internal_end_thread(gtid);
6114}
6115
6116#if KMP_OS_UNIX && KMP_DYNAMIC_LIB
6117
6118__attribute__((destructor)) void __kmp_internal_end_dtor(void) {
6119 __kmp_internal_end_atexit();
6120}
6121
6122#endif
6123
6124/* [Windows] josh: when the atexit handler is called, there may still be more
6125 than one thread alive */
6126void __kmp_internal_end_atexit(void) {
6127 KA_TRACE(30, ("__kmp_internal_end_atexit\n"));
6128 /* [Windows]
6129 josh: ideally, we want to completely shutdown the library in this atexit
6130 handler, but stat code that depends on thread specific data for gtid fails
6131 because that data becomes unavailable at some point during the shutdown, so
6132 we call __kmp_internal_end_thread instead. We should eventually remove the
6133 dependency on __kmp_get_specific_gtid in the stat code and use
6134 __kmp_internal_end_library to cleanly shutdown the library.
6135
6136 // TODO: Can some of this comment about GVS be removed?
6137 I suspect that the offending stat code is executed when the calling thread
6138 tries to clean up a dead root thread's data structures, resulting in GVS
6139 code trying to close the GVS structures for that thread, but since the stat
6140 code uses __kmp_get_specific_gtid to get the gtid with the assumption that
6141 the calling thread is cleaning up itself instead of another thread, it get
6142 confused. This happens because allowing a thread to unregister and cleanup
6143 another thread is a recent modification for addressing an issue.
6144 Based on the current design (20050722), a thread may end up
6145 trying to unregister another thread only if thread death does not trigger
6146 the calling of __kmp_internal_end_thread. For Linux* OS, there is the
6147 thread specific data destructor function to detect thread death. For
6148 Windows dynamic, there is DllMain(THREAD_DETACH). For Windows static, there
6149 is nothing. Thus, the workaround is applicable only for Windows static
6150 stat library. */
6151 __kmp_internal_end_library(-1);
6152#if KMP_OS_WINDOWS
6153 __kmp_close_console();
6154#endif
6155}
6156
6157static void __kmp_reap_thread(kmp_info_t *thread, int is_root) {
6158 // It is assumed __kmp_forkjoin_lock is acquired.
6159
6160 int gtid;
6161
6162 KMP_DEBUG_ASSERT(thread != NULL);
6163
6164 gtid = thread->th.th_info.ds.ds_gtid;
6165
6166 if (!is_root) {
6167 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) {
6168 /* Assume the threads are at the fork barrier here */
6169 KA_TRACE(
6170 20, ("__kmp_reap_thread: releasing T#%d from fork barrier for reap\n",
6171 gtid));
6172 if (__kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
6173 while (
6174 !KMP_COMPARE_AND_STORE_ACQ32(&(thread->th.th_used_in_team), 0, 3))
6175 KMP_CPU_PAUSE();
6176 __kmp_resume_32(gtid, (kmp_flag_32<false, false> *)NULL);
6177 } else {
6178 /* Need release fence here to prevent seg faults for tree forkjoin
6179 barrier (GEH) */
6180 kmp_flag_64<> flag(&thread->th.th_bar[bs_forkjoin_barrier].bb.b_go,
6181 thread);
6182 __kmp_release_64(&flag);
6183 }
6184 }
6185
6186 // Terminate OS thread.
6187 __kmp_reap_worker(thread);
6188
6189 // The thread was killed asynchronously. If it was actively
6190 // spinning in the thread pool, decrement the global count.
6191 //
6192 // There is a small timing hole here - if the worker thread was just waking
6193 // up after sleeping in the pool, had reset it's th_active_in_pool flag but
6194 // not decremented the global counter __kmp_thread_pool_active_nth yet, then
6195 // the global counter might not get updated.
6196 //
6197 // Currently, this can only happen as the library is unloaded,
6198 // so there are no harmful side effects.
6199 if (thread->th.th_active_in_pool) {
6200 thread->th.th_active_in_pool = FALSE;
6201 KMP_ATOMIC_DEC(&__kmp_thread_pool_active_nth);
6202 KMP_DEBUG_ASSERT(__kmp_thread_pool_active_nth >= 0);
6203 }
6204 }
6205
6206 __kmp_free_implicit_task(thread);
6207
6208// Free the fast memory for tasking
6209#if USE_FAST_MEMORY
6210 __kmp_free_fast_memory(thread);
6211#endif /* USE_FAST_MEMORY */
6212
6213 __kmp_suspend_uninitialize_thread(thread);
6214
6215 KMP_DEBUG_ASSERT(__kmp_threads[gtid] == thread);
6216 TCW_SYNC_PTR(__kmp_threads[gtid], NULL);
6217
6218 --__kmp_all_nth;
6219 // __kmp_nth was decremented when thread is added to the pool.
6220
6221#ifdef KMP_ADJUST_BLOCKTIME
6222 /* Adjust blocktime back to user setting or default if necessary */
6223 /* Middle initialization might never have occurred */
6224 if (!__kmp_env_blocktime && (__kmp_avail_proc > 0)) {
6225 KMP_DEBUG_ASSERT(__kmp_avail_proc > 0);
6226 if (__kmp_nth <= __kmp_avail_proc) {
6227 __kmp_zero_bt = FALSE;
6228 }
6229 }
6230#endif /* KMP_ADJUST_BLOCKTIME */
6231
6232 /* free the memory being used */
6233 if (__kmp_env_consistency_check) {
6234 if (thread->th.th_cons) {
6235 __kmp_free_cons_stack(thread->th.th_cons);
6236 thread->th.th_cons = NULL;
6237 }
6238 }
6239
6240 if (thread->th.th_pri_common != NULL) {
6241 __kmp_free(thread->th.th_pri_common);
6242 thread->th.th_pri_common = NULL;
6243 }
6244
6245#if KMP_USE_BGET
6246 if (thread->th.th_local.bget_data != NULL) {
6247 __kmp_finalize_bget(thread);
6248 }
6249#endif
6250
6251#if KMP_AFFINITY_SUPPORTED
6252 if (thread->th.th_affin_mask != NULL) {
6253 KMP_CPU_FREE(thread->th.th_affin_mask);
6254 thread->th.th_affin_mask = NULL;
6255 }
6256#endif /* KMP_AFFINITY_SUPPORTED */
6257
6258#if KMP_USE_HIER_SCHED
6259 if (thread->th.th_hier_bar_data != NULL) {
6260 __kmp_free(thread->th.th_hier_bar_data);
6261 thread->th.th_hier_bar_data = NULL;
6262 }
6263#endif
6264
6265 __kmp_reap_team(thread->th.th_serial_team);
6266 thread->th.th_serial_team = NULL;
6267 __kmp_free(thread);
6268
6269 KMP_MB();
6270
6271} // __kmp_reap_thread
6272
6273static void __kmp_itthash_clean(kmp_info_t *th) {
6274#if USE_ITT_NOTIFY
6275 if (__kmp_itt_region_domains.count > 0) {
6276 for (int i = 0; i < KMP_MAX_FRAME_DOMAINS; ++i) {
6277 kmp_itthash_entry_t *bucket = __kmp_itt_region_domains.buckets[i];
6278 while (bucket) {
6279 kmp_itthash_entry_t *next = bucket->next_in_bucket;
6280 __kmp_thread_free(th, bucket);
6281 bucket = next;
6282 }
6283 }
6284 }
6285 if (__kmp_itt_barrier_domains.count > 0) {
6286 for (int i = 0; i < KMP_MAX_FRAME_DOMAINS; ++i) {
6287 kmp_itthash_entry_t *bucket = __kmp_itt_barrier_domains.buckets[i];
6288 while (bucket) {
6289 kmp_itthash_entry_t *next = bucket->next_in_bucket;
6290 __kmp_thread_free(th, bucket);
6291 bucket = next;
6292 }
6293 }
6294 }
6295#endif
6296}
6297
6298static void __kmp_internal_end(void) {
6299 int i;
6300
6301 /* First, unregister the library */
6302 __kmp_unregister_library();
6303
6304#if KMP_OS_WINDOWS
6305 /* In Win static library, we can't tell when a root actually dies, so we
6306 reclaim the data structures for any root threads that have died but not
6307 unregistered themselves, in order to shut down cleanly.
6308 In Win dynamic library we also can't tell when a thread dies. */
6309 __kmp_reclaim_dead_roots(); // AC: moved here to always clean resources of
6310// dead roots
6311#endif
6312
6313 for (i = 0; i < __kmp_threads_capacity; i++)
6314 if (__kmp_root[i])
6315 if (__kmp_root[i]->r.r_active)
6316 break;
6317 KMP_MB(); /* Flush all pending memory write invalidates. */
6318 TCW_SYNC_4(__kmp_global.g.g_done, TRUE);
6319
6320 if (i < __kmp_threads_capacity) {
6321#if KMP_USE_MONITOR
6322 // 2009-09-08 (lev): Other alive roots found. Why do we kill the monitor??
6323 KMP_MB(); /* Flush all pending memory write invalidates. */
6324
6325 // Need to check that monitor was initialized before reaping it. If we are
6326 // called form __kmp_atfork_child (which sets __kmp_init_parallel = 0), then
6327 // __kmp_monitor will appear to contain valid data, but it is only valid in
6328 // the parent process, not the child.
6329 // New behavior (201008): instead of keying off of the flag
6330 // __kmp_init_parallel, the monitor thread creation is keyed off
6331 // of the new flag __kmp_init_monitor.
6332 __kmp_acquire_bootstrap_lock(&__kmp_monitor_lock);
6333 if (TCR_4(__kmp_init_monitor)) {
6334 __kmp_reap_monitor(&__kmp_monitor);
6335 TCW_4(__kmp_init_monitor, 0);
6336 }
6337 __kmp_release_bootstrap_lock(&__kmp_monitor_lock);
6338 KA_TRACE(10, ("__kmp_internal_end: monitor reaped\n"));
6339#endif // KMP_USE_MONITOR
6340 } else {
6341/* TODO move this to cleanup code */
6342#ifdef KMP_DEBUG
6343 /* make sure that everything has properly ended */
6344 for (i = 0; i < __kmp_threads_capacity; i++) {
6345 if (__kmp_root[i]) {
6346 // KMP_ASSERT( ! KMP_UBER_GTID( i ) ); // AC:
6347 // there can be uber threads alive here
6348 KMP_ASSERT(!__kmp_root[i]->r.r_active); // TODO: can they be active?
6349 }
6350 }
6351#endif
6352
6353 KMP_MB();
6354
6355 // Reap the worker threads.
6356 // This is valid for now, but be careful if threads are reaped sooner.
6357 while (__kmp_thread_pool != NULL) { // Loop thru all the thread in the pool.
6358 // Get the next thread from the pool.
6359 kmp_info_t *thread = CCAST(kmp_info_t *, __kmp_thread_pool);
6360 __kmp_thread_pool = thread->th.th_next_pool;
6361 // Reap it.
6362 KMP_DEBUG_ASSERT(thread->th.th_reap_state == KMP_SAFE_TO_REAP);
6363 thread->th.th_next_pool = NULL;
6364 thread->th.th_in_pool = FALSE;
6365 __kmp_reap_thread(thread, 0);
6366 }
6367 __kmp_thread_pool_insert_pt = NULL;
6368
6369 // Reap teams.
6370 while (__kmp_team_pool != NULL) { // Loop thru all the teams in the pool.
6371 // Get the next team from the pool.
6372 kmp_team_t *team = CCAST(kmp_team_t *, __kmp_team_pool);
6373 __kmp_team_pool = team->t.t_next_pool;
6374 // Reap it.
6375 team->t.t_next_pool = NULL;
6376 __kmp_reap_team(team);
6377 }
6378
6379 __kmp_reap_task_teams();
6380
6381#if KMP_OS_UNIX
6382 // Threads that are not reaped should not access any resources since they
6383 // are going to be deallocated soon, so the shutdown sequence should wait
6384 // until all threads either exit the final spin-waiting loop or begin
6385 // sleeping after the given blocktime.
6386 for (i = 0; i < __kmp_threads_capacity; i++) {
6387 kmp_info_t *thr = __kmp_threads[i];
6388 while (thr && KMP_ATOMIC_LD_ACQ(&thr->th.th_blocking))
6389 KMP_CPU_PAUSE();
6390 }
6391#endif
6392
6393 for (i = 0; i < __kmp_threads_capacity; ++i) {
6394 // TBD: Add some checking...
6395 // Something like KMP_DEBUG_ASSERT( __kmp_thread[ i ] == NULL );
6396 }
6397
6398 /* Make sure all threadprivate destructors get run by joining with all
6399 worker threads before resetting this flag */
6400 TCW_SYNC_4(__kmp_init_common, FALSE);
6401
6402 KA_TRACE(10, ("__kmp_internal_end: all workers reaped\n"));
6403 KMP_MB();
6404
6405#if KMP_USE_MONITOR
6406 // See note above: One of the possible fixes for CQ138434 / CQ140126
6407 //
6408 // FIXME: push both code fragments down and CSE them?
6409 // push them into __kmp_cleanup() ?
6410 __kmp_acquire_bootstrap_lock(&__kmp_monitor_lock);
6411 if (TCR_4(__kmp_init_monitor)) {
6412 __kmp_reap_monitor(&__kmp_monitor);
6413 TCW_4(__kmp_init_monitor, 0);
6414 }
6415 __kmp_release_bootstrap_lock(&__kmp_monitor_lock);
6416 KA_TRACE(10, ("__kmp_internal_end: monitor reaped\n"));
6417#endif
6418 } /* else !__kmp_global.t_active */
6419 TCW_4(__kmp_init_gtid, FALSE);
6420 KMP_MB(); /* Flush all pending memory write invalidates. */
6421
6422 __kmp_cleanup();
6423#if OMPT_SUPPORT
6424 ompt_fini();
6425#endif
6426}
6427
6428void __kmp_internal_end_library(int gtid_req) {
6429 /* if we have already cleaned up, don't try again, it wouldn't be pretty */
6430 /* this shouldn't be a race condition because __kmp_internal_end() is the
6431 only place to clear __kmp_serial_init */
6432 /* we'll check this later too, after we get the lock */
6433 // 2009-09-06: We do not set g_abort without setting g_done. This check looks
6434 // redundant, because the next check will work in any case.
6435 if (__kmp_global.g.g_abort) {
6436 KA_TRACE(11, ("__kmp_internal_end_library: abort, exiting\n"));
6437 /* TODO abort? */
6438 return;
6439 }
6440 if (TCR_4(__kmp_global.g.g_done) || !__kmp_init_serial) {
6441 KA_TRACE(10, ("__kmp_internal_end_library: already finished\n"));
6442 return;
6443 }
6444
6445 // If hidden helper team has been initialized, we need to deinit it
6446 if (TCR_4(__kmp_init_hidden_helper) &&
6447 !TCR_4(__kmp_hidden_helper_team_done)) {
6448 TCW_SYNC_4(__kmp_hidden_helper_team_done, TRUE);
6449 // First release the main thread to let it continue its work
6450 __kmp_hidden_helper_main_thread_release();
6451 // Wait until the hidden helper team has been destroyed
6452 __kmp_hidden_helper_threads_deinitz_wait();
6453 }
6454
6455 KMP_MB(); /* Flush all pending memory write invalidates. */
6456 /* find out who we are and what we should do */
6457 {
6458 int gtid = (gtid_req >= 0) ? gtid_req : __kmp_gtid_get_specific();
6459 KA_TRACE(
6460 10, ("__kmp_internal_end_library: enter T#%d (%d)\n", gtid, gtid_req));
6461 if (gtid == KMP_GTID_SHUTDOWN) {
6462 KA_TRACE(10, ("__kmp_internal_end_library: !__kmp_init_runtime, system "
6463 "already shutdown\n"));
6464 return;
6465 } else if (gtid == KMP_GTID_MONITOR) {
6466 KA_TRACE(10, ("__kmp_internal_end_library: monitor thread, gtid not "
6467 "registered, or system shutdown\n"));
6468 return;
6469 } else if (gtid == KMP_GTID_DNE) {
6470 KA_TRACE(10, ("__kmp_internal_end_library: gtid not registered or system "
6471 "shutdown\n"));
6472 /* we don't know who we are, but we may still shutdown the library */
6473 } else if (KMP_UBER_GTID(gtid)) {
6474 /* unregister ourselves as an uber thread. gtid is no longer valid */
6475 if (__kmp_root[gtid]->r.r_active) {
6476 __kmp_global.g.g_abort = -1;
6477 TCW_SYNC_4(__kmp_global.g.g_done, TRUE);
6478 __kmp_unregister_library();
6479 KA_TRACE(10,
6480 ("__kmp_internal_end_library: root still active, abort T#%d\n",
6481 gtid));
6482 return;
6483 } else {
6484 __kmp_itthash_clean(__kmp_threads[gtid]);
6485 KA_TRACE(
6486 10,
6487 ("__kmp_internal_end_library: unregistering sibling T#%d\n", gtid));
6488 __kmp_unregister_root_current_thread(gtid);
6489 }
6490 } else {
6491/* worker threads may call this function through the atexit handler, if they
6492 * call exit() */
6493/* For now, skip the usual subsequent processing and just dump the debug buffer.
6494 TODO: do a thorough shutdown instead */
6495#ifdef DUMP_DEBUG_ON_EXIT
6496 if (__kmp_debug_buf)
6497 __kmp_dump_debug_buffer();
6498#endif
6499 // added unregister library call here when we switch to shm linux
6500 // if we don't, it will leave lots of files in /dev/shm
6501 // cleanup shared memory file before exiting.
6502 __kmp_unregister_library();
6503 return;
6504 }
6505 }
6506 /* synchronize the termination process */
6507 __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
6508
6509 /* have we already finished */
6510 if (__kmp_global.g.g_abort) {
6511 KA_TRACE(10, ("__kmp_internal_end_library: abort, exiting\n"));
6512 /* TODO abort? */
6513 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
6514 return;
6515 }
6516 if (TCR_4(__kmp_global.g.g_done) || !__kmp_init_serial) {
6517 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
6518 return;
6519 }
6520
6521 /* We need this lock to enforce mutex between this reading of
6522 __kmp_threads_capacity and the writing by __kmp_register_root.
6523 Alternatively, we can use a counter of roots that is atomically updated by
6524 __kmp_get_global_thread_id_reg, __kmp_do_serial_initialize and
6525 __kmp_internal_end_*. */
6526 __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
6527
6528 /* now we can safely conduct the actual termination */
6529 __kmp_internal_end();
6530
6531 __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
6532 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
6533
6534 KA_TRACE(10, ("__kmp_internal_end_library: exit\n"));
6535
6536#ifdef DUMP_DEBUG_ON_EXIT
6537 if (__kmp_debug_buf)
6538 __kmp_dump_debug_buffer();
6539#endif
6540
6541#if KMP_OS_WINDOWS
6542 __kmp_close_console();
6543#endif
6544
6545 __kmp_fini_allocator();
6546
6547} // __kmp_internal_end_library
6548
6549void __kmp_internal_end_thread(int gtid_req) {
6550 int i;
6551
6552 /* if we have already cleaned up, don't try again, it wouldn't be pretty */
6553 /* this shouldn't be a race condition because __kmp_internal_end() is the
6554 * only place to clear __kmp_serial_init */
6555 /* we'll check this later too, after we get the lock */
6556 // 2009-09-06: We do not set g_abort without setting g_done. This check looks
6557 // redundant, because the next check will work in any case.
6558 if (__kmp_global.g.g_abort) {
6559 KA_TRACE(11, ("__kmp_internal_end_thread: abort, exiting\n"));
6560 /* TODO abort? */
6561 return;
6562 }
6563 if (TCR_4(__kmp_global.g.g_done) || !__kmp_init_serial) {
6564 KA_TRACE(10, ("__kmp_internal_end_thread: already finished\n"));
6565 return;
6566 }
6567
6568 // If hidden helper team has been initialized, we need to deinit it
6569 if (TCR_4(__kmp_init_hidden_helper) &&
6570 !TCR_4(__kmp_hidden_helper_team_done)) {
6571 TCW_SYNC_4(__kmp_hidden_helper_team_done, TRUE);
6572 // First release the main thread to let it continue its work
6573 __kmp_hidden_helper_main_thread_release();
6574 // Wait until the hidden helper team has been destroyed
6575 __kmp_hidden_helper_threads_deinitz_wait();
6576 }
6577
6578 KMP_MB(); /* Flush all pending memory write invalidates. */
6579
6580 /* find out who we are and what we should do */
6581 {
6582 int gtid = (gtid_req >= 0) ? gtid_req : __kmp_gtid_get_specific();
6583 KA_TRACE(10,
6584 ("__kmp_internal_end_thread: enter T#%d (%d)\n", gtid, gtid_req));
6585 if (gtid == KMP_GTID_SHUTDOWN) {
6586 KA_TRACE(10, ("__kmp_internal_end_thread: !__kmp_init_runtime, system "
6587 "already shutdown\n"));
6588 return;
6589 } else if (gtid == KMP_GTID_MONITOR) {
6590 KA_TRACE(10, ("__kmp_internal_end_thread: monitor thread, gtid not "
6591 "registered, or system shutdown\n"));
6592 return;
6593 } else if (gtid == KMP_GTID_DNE) {
6594 KA_TRACE(10, ("__kmp_internal_end_thread: gtid not registered or system "
6595 "shutdown\n"));
6596 return;
6597 /* we don't know who we are */
6598 } else if (KMP_UBER_GTID(gtid)) {
6599 /* unregister ourselves as an uber thread. gtid is no longer valid */
6600 if (__kmp_root[gtid]->r.r_active) {
6601 __kmp_global.g.g_abort = -1;
6602 TCW_SYNC_4(__kmp_global.g.g_done, TRUE);
6603 KA_TRACE(10,
6604 ("__kmp_internal_end_thread: root still active, abort T#%d\n",
6605 gtid));
6606 return;
6607 } else {
6608 KA_TRACE(10, ("__kmp_internal_end_thread: unregistering sibling T#%d\n",
6609 gtid));
6610 __kmp_unregister_root_current_thread(gtid);
6611 }
6612 } else {
6613 /* just a worker thread, let's leave */
6614 KA_TRACE(10, ("__kmp_internal_end_thread: worker thread T#%d\n", gtid));
6615
6616 if (gtid >= 0) {
6617 __kmp_threads[gtid]->th.th_task_team = NULL;
6618 }
6619
6620 KA_TRACE(10,
6621 ("__kmp_internal_end_thread: worker thread done, exiting T#%d\n",
6622 gtid));
6623 return;
6624 }
6625 }
6626#if KMP_DYNAMIC_LIB
6627 if (__kmp_pause_status != kmp_hard_paused)
6628 // AC: lets not shutdown the dynamic library at the exit of uber thread,
6629 // because we will better shutdown later in the library destructor.
6630 {
6631 KA_TRACE(10, ("__kmp_internal_end_thread: exiting T#%d\n", gtid_req));
6632 return;
6633 }
6634#endif
6635 /* synchronize the termination process */
6636 __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
6637
6638 /* have we already finished */
6639 if (__kmp_global.g.g_abort) {
6640 KA_TRACE(10, ("__kmp_internal_end_thread: abort, exiting\n"));
6641 /* TODO abort? */
6642 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
6643 return;
6644 }
6645 if (TCR_4(__kmp_global.g.g_done) || !__kmp_init_serial) {
6646 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
6647 return;
6648 }
6649
6650 /* We need this lock to enforce mutex between this reading of
6651 __kmp_threads_capacity and the writing by __kmp_register_root.
6652 Alternatively, we can use a counter of roots that is atomically updated by
6653 __kmp_get_global_thread_id_reg, __kmp_do_serial_initialize and
6654 __kmp_internal_end_*. */
6655
6656 /* should we finish the run-time? are all siblings done? */
6657 __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
6658
6659 for (i = 0; i < __kmp_threads_capacity; ++i) {
6660 if (KMP_UBER_GTID(i)) {
6661 KA_TRACE(
6662 10,
6663 ("__kmp_internal_end_thread: remaining sibling task: gtid==%d\n", i));
6664 __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
6665 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
6666 return;
6667 }
6668 }
6669
6670 /* now we can safely conduct the actual termination */
6671
6672 __kmp_internal_end();
6673
6674 __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
6675 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
6676
6677 KA_TRACE(10, ("__kmp_internal_end_thread: exit T#%d\n", gtid_req));
6678
6679#ifdef DUMP_DEBUG_ON_EXIT
6680 if (__kmp_debug_buf)
6681 __kmp_dump_debug_buffer();
6682#endif
6683} // __kmp_internal_end_thread
6684
6685// -----------------------------------------------------------------------------
6686// Library registration stuff.
6687
6688static long __kmp_registration_flag = 0;
6689// Random value used to indicate library initialization.
6690static char *__kmp_registration_str = NULL;
6691// Value to be saved in env var __KMP_REGISTERED_LIB_<pid>.
6692
6693static inline char *__kmp_reg_status_name() {
6694/* On RHEL 3u5 if linked statically, getpid() returns different values in
6695 each thread. If registration and unregistration go in different threads
6696 (omp_misc_other_root_exit.cpp test case), the name of registered_lib_env
6697 env var can not be found, because the name will contain different pid. */
6698// macOS* complains about name being too long with additional getuid()
6699#if KMP_OS_UNIX && !KMP_OS_DARWIN && KMP_DYNAMIC_LIB
6700 return __kmp_str_format("__KMP_REGISTERED_LIB_%d_%d", (int)getpid(),
6701 (int)getuid());
6702#else
6703 return __kmp_str_format("__KMP_REGISTERED_LIB_%d", (int)getpid());
6704#endif
6705} // __kmp_reg_status_get
6706
6707#if defined(KMP_USE_SHM)
6708bool __kmp_shm_available = false;
6709bool __kmp_tmp_available = false;
6710// If /dev/shm is not accessible, we will create a temporary file under /tmp.
6711char *temp_reg_status_file_name = nullptr;
6712#endif
6713
6714void __kmp_register_library_startup(void) {
6715
6716 char *name = __kmp_reg_status_name(); // Name of the environment variable.
6717 int done = 0;
6718 union {
6719 double dtime;
6720 long ltime;
6721 } time;
6722#if KMP_ARCH_X86 || KMP_ARCH_X86_64
6723 __kmp_initialize_system_tick();
6724#endif
6725 __kmp_read_system_time(&time.dtime);
6726 __kmp_registration_flag = 0xCAFE0000L | (time.ltime & 0x0000FFFFL);
6727 __kmp_registration_str =
6728 __kmp_str_format("%p-%lx-%s", &__kmp_registration_flag,
6729 __kmp_registration_flag, KMP_LIBRARY_FILE);
6730
6731 KA_TRACE(50, ("__kmp_register_library_startup: %s=\"%s\"\n", name,
6732 __kmp_registration_str));
6733
6734 while (!done) {
6735
6736 char *value = NULL; // Actual value of the environment variable.
6737
6738#if defined(KMP_USE_SHM)
6739 char *shm_name = nullptr;
6740 char *data1 = nullptr;
6741 __kmp_shm_available = __kmp_detect_shm();
6742 if (__kmp_shm_available) {
6743 int fd1 = -1;
6744 shm_name = __kmp_str_format("/%s", name);
6745 int shm_preexist = 0;
6746 fd1 = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, 0600);
6747 if ((fd1 == -1) && (errno == EEXIST)) {
6748 // file didn't open because it already exists.
6749 // try opening existing file
6750 fd1 = shm_open(shm_name, O_RDWR, 0600);
6751 if (fd1 == -1) { // file didn't open
6752 KMP_WARNING(FunctionError, "Can't open SHM");
6753 __kmp_shm_available = false;
6754 } else { // able to open existing file
6755 shm_preexist = 1;
6756 }
6757 }
6758 if (__kmp_shm_available && shm_preexist == 0) { // SHM created, set size
6759 if (ftruncate(fd1, SHM_SIZE) == -1) { // error occurred setting size;
6760 KMP_WARNING(FunctionError, "Can't set size of SHM");
6761 __kmp_shm_available = false;
6762 }
6763 }
6764 if (__kmp_shm_available) { // SHM exists, now map it
6765 data1 = (char *)mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
6766 fd1, 0);
6767 if (data1 == MAP_FAILED) { // failed to map shared memory
6768 KMP_WARNING(FunctionError, "Can't map SHM");
6769 __kmp_shm_available = false;
6770 }
6771 }
6772 if (__kmp_shm_available) { // SHM mapped
6773 if (shm_preexist == 0) { // set data to SHM, set value
6774 KMP_STRCPY_S(data1, SHM_SIZE, __kmp_registration_str);
6775 }
6776 // Read value from either what we just wrote or existing file.
6777 value = __kmp_str_format("%s", data1); // read value from SHM
6778 munmap(data1, SHM_SIZE);
6779 }
6780 if (fd1 != -1)
6781 close(fd1);
6782 }
6783 if (!__kmp_shm_available)
6784 __kmp_tmp_available = __kmp_detect_tmp();
6785 if (!__kmp_shm_available && __kmp_tmp_available) {
6786 // SHM failed to work due to an error other than that the file already
6787 // exists. Try to create a temp file under /tmp.
6788 // If /tmp isn't accessible, fall back to using environment variable.
6789 // TODO: /tmp might not always be the temporary directory. For now we will
6790 // not consider TMPDIR.
6791 int fd1 = -1;
6792 temp_reg_status_file_name = __kmp_str_format("/tmp/%s", name);
6793 int tmp_preexist = 0;
6794 fd1 = open(temp_reg_status_file_name, O_CREAT | O_EXCL | O_RDWR, 0600);
6795 if ((fd1 == -1) && (errno == EEXIST)) {
6796 // file didn't open because it already exists.
6797 // try opening existing file
6798 fd1 = open(temp_reg_status_file_name, O_RDWR, 0600);
6799 if (fd1 == -1) { // file didn't open if (fd1 == -1) {
6800 KMP_WARNING(FunctionError, "Can't open TEMP");
6801 __kmp_tmp_available = false;
6802 } else {
6803 tmp_preexist = 1;
6804 }
6805 }
6806 if (__kmp_tmp_available && tmp_preexist == 0) {
6807 // we created /tmp file now set size
6808 if (ftruncate(fd1, SHM_SIZE) == -1) { // error occurred setting size;
6809 KMP_WARNING(FunctionError, "Can't set size of /tmp file");
6810 __kmp_tmp_available = false;
6811 }
6812 }
6813 if (__kmp_tmp_available) {
6814 data1 = (char *)mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
6815 fd1, 0);
6816 if (data1 == MAP_FAILED) { // failed to map /tmp
6817 KMP_WARNING(FunctionError, "Can't map /tmp");
6818 __kmp_tmp_available = false;
6819 }
6820 }
6821 if (__kmp_tmp_available) {
6822 if (tmp_preexist == 0) { // set data to TMP, set value
6823 KMP_STRCPY_S(data1, SHM_SIZE, __kmp_registration_str);
6824 }
6825 // Read value from either what we just wrote or existing file.
6826 value = __kmp_str_format("%s", data1); // read value from SHM
6827 munmap(data1, SHM_SIZE);
6828 }
6829 if (fd1 != -1)
6830 close(fd1);
6831 }
6832 if (!__kmp_shm_available && !__kmp_tmp_available) {
6833 // no /dev/shm and no /tmp -- fall back to environment variable
6834 // Set environment variable, but do not overwrite if it exists.
6835 __kmp_env_set(name, __kmp_registration_str, 0);
6836 // read value to see if it got set
6837 value = __kmp_env_get(name);
6838 }
6839#else // Windows and unix with static library
6840 // Set environment variable, but do not overwrite if it exists.
6841 __kmp_env_set(name, __kmp_registration_str, 0);
6842 // read value to see if it got set
6843 value = __kmp_env_get(name);
6844#endif
6845
6846 if (value != NULL && strcmp(value, __kmp_registration_str) == 0) {
6847 done = 1; // Ok, environment variable set successfully, exit the loop.
6848 } else {
6849 // Oops. Write failed. Another copy of OpenMP RTL is in memory.
6850 // Check whether it alive or dead.
6851 int neighbor = 0; // 0 -- unknown status, 1 -- alive, 2 -- dead.
6852 char *tail = value;
6853 char *flag_addr_str = NULL;
6854 char *flag_val_str = NULL;
6855 char const *file_name = NULL;
6856 __kmp_str_split(tail, '-', &flag_addr_str, &tail);
6857 __kmp_str_split(tail, '-', &flag_val_str, &tail);
6858 file_name = tail;
6859 if (tail != NULL) {
6860 unsigned long *flag_addr = 0;
6861 unsigned long flag_val = 0;
6862 KMP_SSCANF(flag_addr_str, "%p", RCAST(void **, &flag_addr));
6863 KMP_SSCANF(flag_val_str, "%lx", &flag_val);
6864 if (flag_addr != 0 && flag_val != 0 && strcmp(file_name, "") != 0) {
6865 // First, check whether environment-encoded address is mapped into
6866 // addr space.
6867 // If so, dereference it to see if it still has the right value.
6868 if (__kmp_is_address_mapped(flag_addr) && *flag_addr == flag_val) {
6869 neighbor = 1;
6870 } else {
6871 // If not, then we know the other copy of the library is no longer
6872 // running.
6873 neighbor = 2;
6874 }
6875 }
6876 }
6877 switch (neighbor) {
6878 case 0: // Cannot parse environment variable -- neighbor status unknown.
6879 // Assume it is the incompatible format of future version of the
6880 // library. Assume the other library is alive.
6881 // WARN( ... ); // TODO: Issue a warning.
6882 file_name = "unknown library";
6883 KMP_FALLTHROUGH();
6884 // Attention! Falling to the next case. That's intentional.
6885 case 1: { // Neighbor is alive.
6886 // Check it is allowed.
6887 char *duplicate_ok = __kmp_env_get("KMP_DUPLICATE_LIB_OK");
6888 if (!__kmp_str_match_true(duplicate_ok)) {
6889 // That's not allowed. Issue fatal error.
6890 __kmp_fatal(KMP_MSG(DuplicateLibrary, KMP_LIBRARY_FILE, file_name),
6891 KMP_HNT(DuplicateLibrary), __kmp_msg_null);
6892 }
6893 KMP_INTERNAL_FREE(duplicate_ok);
6894 __kmp_duplicate_library_ok = 1;
6895 done = 1; // Exit the loop.
6896 } break;
6897 case 2: { // Neighbor is dead.
6898
6899#if defined(KMP_USE_SHM)
6900 if (__kmp_shm_available) { // close shared memory.
6901 shm_unlink(shm_name); // this removes file in /dev/shm
6902 } else if (__kmp_tmp_available) {
6903 unlink(temp_reg_status_file_name); // this removes the temp file
6904 } else {
6905 // Clear the variable and try to register library again.
6906 __kmp_env_unset(name);
6907 }
6908#else
6909 // Clear the variable and try to register library again.
6910 __kmp_env_unset(name);
6911#endif
6912 } break;
6913 default: {
6914 KMP_DEBUG_ASSERT(0);
6915 } break;
6916 }
6917 }
6918 KMP_INTERNAL_FREE((void *)value);
6919#if defined(KMP_USE_SHM)
6920 if (shm_name)
6921 KMP_INTERNAL_FREE((void *)shm_name);
6922#endif
6923 } // while
6924 KMP_INTERNAL_FREE((void *)name);
6925
6926} // func __kmp_register_library_startup
6927
6928void __kmp_unregister_library(void) {
6929
6930 // The library can be torn down before it ever registered itself, e.g. when
6931 // __kmp_abort_process() runs for a fatal error raised during environment
6932 // parsing. There is nothing to unregister then, and __kmp_registration_str
6933 // is still NULL, so the strcmp() below would dereference it.
6934 if (__kmp_registration_flag == 0)
6935 return;
6936
6937 char *name = __kmp_reg_status_name();
6938 char *value = NULL;
6939
6940#if defined(KMP_USE_SHM)
6941 char *shm_name = nullptr;
6942 int fd1;
6943 if (__kmp_shm_available) {
6944 shm_name = __kmp_str_format("/%s", name);
6945 fd1 = shm_open(shm_name, O_RDONLY, 0600);
6946 if (fd1 != -1) { // File opened successfully
6947 char *data1 = (char *)mmap(0, SHM_SIZE, PROT_READ, MAP_SHARED, fd1, 0);
6948 if (data1 != MAP_FAILED) {
6949 value = __kmp_str_format("%s", data1); // read value from SHM
6950 munmap(data1, SHM_SIZE);
6951 }
6952 close(fd1);
6953 }
6954 } else if (__kmp_tmp_available) { // try /tmp
6955 fd1 = open(temp_reg_status_file_name, O_RDONLY);
6956 if (fd1 != -1) { // File opened successfully
6957 char *data1 = (char *)mmap(0, SHM_SIZE, PROT_READ, MAP_SHARED, fd1, 0);
6958 if (data1 != MAP_FAILED) {
6959 value = __kmp_str_format("%s", data1); // read value from /tmp
6960 munmap(data1, SHM_SIZE);
6961 }
6962 close(fd1);
6963 }
6964 } else { // fall back to envirable
6965 value = __kmp_env_get(name);
6966 }
6967#else
6968 value = __kmp_env_get(name);
6969#endif
6970
6971 KMP_DEBUG_ASSERT(__kmp_registration_flag != 0);
6972 KMP_DEBUG_ASSERT(__kmp_registration_str != NULL);
6973 if (value != NULL && strcmp(value, __kmp_registration_str) == 0) {
6974// Ok, this is our variable. Delete it.
6975#if defined(KMP_USE_SHM)
6976 if (__kmp_shm_available) {
6977 shm_unlink(shm_name); // this removes file in /dev/shm
6978 } else if (__kmp_tmp_available) {
6979 unlink(temp_reg_status_file_name); // this removes the temp file
6980 } else {
6981 __kmp_env_unset(name);
6982 }
6983#else
6984 __kmp_env_unset(name);
6985#endif
6986 }
6987
6988#if defined(KMP_USE_SHM)
6989 if (shm_name)
6990 KMP_INTERNAL_FREE(shm_name);
6991 if (temp_reg_status_file_name)
6992 KMP_INTERNAL_FREE(temp_reg_status_file_name);
6993#endif
6994
6995 KMP_INTERNAL_FREE(__kmp_registration_str);
6996 KMP_INTERNAL_FREE(value);
6997 KMP_INTERNAL_FREE(name);
6998
6999 __kmp_registration_flag = 0;
7000 __kmp_registration_str = NULL;
7001
7002} // __kmp_unregister_library
7003
7004// End of Library registration stuff.
7005// -----------------------------------------------------------------------------
7006
7007#if KMP_MIC_SUPPORTED
7008
7009static void __kmp_check_mic_type() {
7010 kmp_cpuid_t cpuid_state = {0};
7011 kmp_cpuid_t *cs_p = &cpuid_state;
7012 __kmp_x86_cpuid(1, 0, cs_p);
7013 // We don't support mic1 at the moment
7014 if ((cs_p->eax & 0xff0) == 0xB10) {
7015 __kmp_mic_type = mic2;
7016 } else if ((cs_p->eax & 0xf0ff0) == 0x50670) {
7017 __kmp_mic_type = mic3;
7018 } else {
7019 __kmp_mic_type = non_mic;
7020 }
7021}
7022
7023#endif /* KMP_MIC_SUPPORTED */
7024
7025#if KMP_HAVE_UMWAIT
7026static void __kmp_user_level_mwait_init() {
7027 struct kmp_cpuid buf;
7028 __kmp_x86_cpuid(7, 0, &buf);
7029 __kmp_waitpkg_enabled = ((buf.ecx >> 5) & 1);
7030 __kmp_umwait_enabled = __kmp_waitpkg_enabled && __kmp_user_level_mwait;
7031 __kmp_tpause_enabled = __kmp_waitpkg_enabled && (__kmp_tpause_state > 0);
7032 KF_TRACE(30, ("__kmp_user_level_mwait_init: __kmp_umwait_enabled = %d\n",
7033 __kmp_umwait_enabled));
7034}
7035#elif KMP_HAVE_MWAIT
7036#ifndef AT_INTELPHIUSERMWAIT
7037// Spurious, non-existent value that should always fail to return anything.
7038// Will be replaced with the correct value when we know that.
7039#define AT_INTELPHIUSERMWAIT 10000
7040#endif
7041// getauxval() function is available in RHEL7 and SLES12. If a system with an
7042// earlier OS is used to build the RTL, we'll use the following internal
7043// function when the entry is not found.
7044unsigned long getauxval(unsigned long) KMP_WEAK_ATTRIBUTE_EXTERNAL;
7045unsigned long getauxval(unsigned long) { return 0; }
7046
7047static void __kmp_user_level_mwait_init() {
7048 // When getauxval() and correct value of AT_INTELPHIUSERMWAIT are available
7049 // use them to find if the user-level mwait is enabled. Otherwise, forcibly
7050 // set __kmp_mwait_enabled=TRUE on Intel MIC if the environment variable
7051 // KMP_USER_LEVEL_MWAIT was set to TRUE.
7052 if (__kmp_mic_type == mic3) {
7053 unsigned long res = getauxval(AT_INTELPHIUSERMWAIT);
7054 if ((res & 0x1) || __kmp_user_level_mwait) {
7055 __kmp_mwait_enabled = TRUE;
7056 if (__kmp_user_level_mwait) {
7057 KMP_INFORM(EnvMwaitWarn);
7058 }
7059 } else {
7060 __kmp_mwait_enabled = FALSE;
7061 }
7062 }
7063 KF_TRACE(30, ("__kmp_user_level_mwait_init: __kmp_mic_type = %d, "
7064 "__kmp_mwait_enabled = %d\n",
7065 __kmp_mic_type, __kmp_mwait_enabled));
7066}
7067#endif /* KMP_HAVE_UMWAIT */
7068
7069static void __kmp_do_serial_initialize(void) {
7070 int i, gtid;
7071 size_t size;
7072
7073 KA_TRACE(10, ("__kmp_do_serial_initialize: enter\n"));
7074
7075 KMP_DEBUG_ASSERT(sizeof(kmp_int32) == 4);
7076 KMP_DEBUG_ASSERT(sizeof(kmp_uint32) == 4);
7077 KMP_DEBUG_ASSERT(sizeof(kmp_int64) == 8);
7078 KMP_DEBUG_ASSERT(sizeof(kmp_uint64) == 8);
7079 KMP_DEBUG_ASSERT(sizeof(kmp_intptr_t) == sizeof(void *));
7080
7081#if OMPT_SUPPORT
7082 ompt_pre_init();
7083#endif
7084#if OMPD_SUPPORT
7085 __kmp_env_dump();
7086 ompd_init();
7087#endif
7088
7089 __kmp_validate_locks();
7090
7091#if ENABLE_LIBOMPTARGET
7092 /* Initialize functions from libomptarget */
7093 __kmp_init_omptarget();
7094#endif
7095
7096 /* Initialize internal memory allocator */
7097 __kmp_init_allocator();
7098
7099 /* Register the library startup via an environment variable or via mapped
7100 shared memory file and check to see whether another copy of the library is
7101 already registered. Since forked child process is often terminated, we
7102 postpone the registration till middle initialization in the child */
7103 if (__kmp_need_register_serial)
7104 __kmp_register_library_startup();
7105
7106 /* TODO reinitialization of library */
7107 if (TCR_4(__kmp_global.g.g_done)) {
7108 KA_TRACE(10, ("__kmp_do_serial_initialize: reinitialization of library\n"));
7109 }
7110
7111 __kmp_global.g.g_abort = 0;
7112 TCW_SYNC_4(__kmp_global.g.g_done, FALSE);
7113
7114/* initialize the locks */
7115#if KMP_USE_ADAPTIVE_LOCKS
7116#if KMP_DEBUG_ADAPTIVE_LOCKS
7117 __kmp_init_speculative_stats();
7118#endif
7119#endif
7120#if KMP_STATS_ENABLED
7121 __kmp_stats_init();
7122#endif
7123 __kmp_init_lock(&__kmp_global_lock);
7124 __kmp_init_atomic_lock(&__kmp_atomic_lock);
7125 __kmp_init_atomic_lock(&__kmp_atomic_lock_1i);
7126 __kmp_init_atomic_lock(&__kmp_atomic_lock_2i);
7127 __kmp_init_atomic_lock(&__kmp_atomic_lock_4i);
7128 __kmp_init_atomic_lock(&__kmp_atomic_lock_4r);
7129 __kmp_init_atomic_lock(&__kmp_atomic_lock_8i);
7130 __kmp_init_atomic_lock(&__kmp_atomic_lock_8r);
7131 __kmp_init_atomic_lock(&__kmp_atomic_lock_8c);
7132 __kmp_init_atomic_lock(&__kmp_atomic_lock_10r);
7133 __kmp_init_atomic_lock(&__kmp_atomic_lock_16r);
7134 __kmp_init_atomic_lock(&__kmp_atomic_lock_16c);
7135 __kmp_init_atomic_lock(&__kmp_atomic_lock_20c);
7136 __kmp_init_atomic_lock(&__kmp_atomic_lock_32c);
7137 __kmp_init_bootstrap_lock(&__kmp_forkjoin_lock);
7138 __kmp_init_bootstrap_lock(&__kmp_exit_lock);
7139#if KMP_USE_MONITOR
7140 __kmp_init_bootstrap_lock(&__kmp_monitor_lock);
7141#endif
7142 __kmp_init_bootstrap_lock(&__kmp_tp_cached_lock);
7143
7144 /* conduct initialization and initial setup of configuration */
7145
7146 __kmp_runtime_initialize();
7147
7148#if KMP_MIC_SUPPORTED
7149 __kmp_check_mic_type();
7150#endif
7151#if ENABLE_LIBOMPTARGET
7152 __kmp_target_init();
7153#endif /* ENABLE_LIBOMPTARGET */
7154
7155// Some global variable initialization moved here from kmp_env_initialize()
7156#ifdef KMP_DEBUG
7157 kmp_diag = 0;
7158#endif
7159 __kmp_abort_delay = 0;
7160
7161 // From __kmp_init_dflt_team_nth()
7162 /* assume the entire machine will be used */
7163 __kmp_dflt_team_nth_ub = __kmp_xproc;
7164 if (__kmp_dflt_team_nth_ub < KMP_MIN_NTH) {
7165 __kmp_dflt_team_nth_ub = KMP_MIN_NTH;
7166 }
7167 if (__kmp_dflt_team_nth_ub > __kmp_sys_max_nth) {
7168 __kmp_dflt_team_nth_ub = __kmp_sys_max_nth;
7169 }
7170 __kmp_max_nth = __kmp_sys_max_nth;
7171 __kmp_cg_max_nth = __kmp_sys_max_nth;
7172 __kmp_teams_max_nth = __kmp_xproc; // set a "reasonable" default
7173 if (__kmp_teams_max_nth > __kmp_sys_max_nth) {
7174 __kmp_teams_max_nth = __kmp_sys_max_nth;
7175 }
7176
7177 // Three vars below moved here from __kmp_env_initialize() "KMP_BLOCKTIME"
7178 // part
7179 __kmp_dflt_blocktime = KMP_DEFAULT_BLOCKTIME;
7180#if KMP_USE_MONITOR
7181 __kmp_monitor_wakeups =
7182 KMP_WAKEUPS_FROM_BLOCKTIME(__kmp_dflt_blocktime, __kmp_monitor_wakeups);
7183 __kmp_bt_intervals =
7184 KMP_INTERVALS_FROM_BLOCKTIME(__kmp_dflt_blocktime, __kmp_monitor_wakeups);
7185#endif
7186 // From "KMP_LIBRARY" part of __kmp_env_initialize()
7187 __kmp_library = library_throughput;
7188 // From KMP_SCHEDULE initialization
7189 __kmp_static = kmp_sch_static_balanced;
7190// AC: do not use analytical here, because it is non-monotonous
7191//__kmp_guided = kmp_sch_guided_iterative_chunked;
7192//__kmp_auto = kmp_sch_guided_analytical_chunked; // AC: it is the default, no
7193// need to repeat assignment
7194// Barrier initialization. Moved here from __kmp_env_initialize() Barrier branch
7195// bit control and barrier method control parts
7196#if KMP_FAST_REDUCTION_BARRIER
7197#define kmp_reduction_barrier_gather_bb ((int)1)
7198#define kmp_reduction_barrier_release_bb ((int)1)
7199#define kmp_reduction_barrier_gather_pat __kmp_barrier_gather_pat_dflt
7200#define kmp_reduction_barrier_release_pat __kmp_barrier_release_pat_dflt
7201#endif // KMP_FAST_REDUCTION_BARRIER
7202 for (i = bs_plain_barrier; i < bs_last_barrier; i++) {
7203 __kmp_barrier_gather_branch_bits[i] = __kmp_barrier_gather_bb_dflt;
7204 __kmp_barrier_release_branch_bits[i] = __kmp_barrier_release_bb_dflt;
7205 __kmp_barrier_gather_pattern[i] = __kmp_barrier_gather_pat_dflt;
7206 __kmp_barrier_release_pattern[i] = __kmp_barrier_release_pat_dflt;
7207#if KMP_FAST_REDUCTION_BARRIER
7208 if (i == bs_reduction_barrier) { // tested and confirmed on ALTIX only (
7209 // lin_64 ): hyper,1
7210 __kmp_barrier_gather_branch_bits[i] = kmp_reduction_barrier_gather_bb;
7211 __kmp_barrier_release_branch_bits[i] = kmp_reduction_barrier_release_bb;
7212 __kmp_barrier_gather_pattern[i] = kmp_reduction_barrier_gather_pat;
7213 __kmp_barrier_release_pattern[i] = kmp_reduction_barrier_release_pat;
7214 }
7215#endif // KMP_FAST_REDUCTION_BARRIER
7216 }
7217#if KMP_FAST_REDUCTION_BARRIER
7218#undef kmp_reduction_barrier_release_pat
7219#undef kmp_reduction_barrier_gather_pat
7220#undef kmp_reduction_barrier_release_bb
7221#undef kmp_reduction_barrier_gather_bb
7222#endif // KMP_FAST_REDUCTION_BARRIER
7223#if KMP_MIC_SUPPORTED
7224 if (__kmp_mic_type == mic2) { // KNC
7225 // AC: plane=3,2, forkjoin=2,1 are optimal for 240 threads on KNC
7226 __kmp_barrier_gather_branch_bits[bs_plain_barrier] = 3; // plain gather
7227 __kmp_barrier_release_branch_bits[bs_forkjoin_barrier] =
7228 1; // forkjoin release
7229 __kmp_barrier_gather_pattern[bs_forkjoin_barrier] = bp_hierarchical_bar;
7230 __kmp_barrier_release_pattern[bs_forkjoin_barrier] = bp_hierarchical_bar;
7231 }
7232#if KMP_FAST_REDUCTION_BARRIER
7233 if (__kmp_mic_type == mic2) { // KNC
7234 __kmp_barrier_gather_pattern[bs_reduction_barrier] = bp_hierarchical_bar;
7235 __kmp_barrier_release_pattern[bs_reduction_barrier] = bp_hierarchical_bar;
7236 }
7237#endif // KMP_FAST_REDUCTION_BARRIER
7238#endif // KMP_MIC_SUPPORTED
7239
7240// From KMP_CHECKS initialization
7241#ifdef KMP_DEBUG
7242 __kmp_env_checks = TRUE; /* development versions have the extra checks */
7243#else
7244 __kmp_env_checks = FALSE; /* port versions do not have the extra checks */
7245#endif
7246
7247 // From "KMP_FOREIGN_THREADS_THREADPRIVATE" initialization
7248 __kmp_foreign_tp = TRUE;
7249
7250 __kmp_global.g.g_dynamic = FALSE;
7251 __kmp_global.g.g_dynamic_mode = dynamic_default;
7252
7253 __kmp_init_nesting_mode();
7254
7255 __kmp_env_initialize(NULL);
7256
7257#if KMP_HAVE_MWAIT || KMP_HAVE_UMWAIT
7258 __kmp_user_level_mwait_init();
7259#endif
7260// Print all messages in message catalog for testing purposes.
7261#ifdef KMP_DEBUG
7262 char const *val = __kmp_env_get("KMP_DUMP_CATALOG");
7263 if (__kmp_str_match_true(val)) {
7264 kmp_str_buf_t buffer;
7265 __kmp_str_buf_init(&buffer);
7266 __kmp_i18n_dump_catalog(&buffer);
7267 __kmp_printf("%s", buffer.str);
7268 __kmp_str_buf_free(&buffer);
7269 }
7270 __kmp_env_free(&val);
7271#endif
7272
7273 __kmp_threads_capacity =
7274 __kmp_initial_threads_capacity(__kmp_dflt_team_nth_ub);
7275 // Moved here from __kmp_env_initialize() "KMP_ALL_THREADPRIVATE" part
7276 __kmp_tp_capacity = __kmp_default_tp_capacity(
7277 __kmp_dflt_team_nth_ub, __kmp_max_nth, __kmp_allThreadsSpecified);
7278
7279 // If the library is shut down properly, both pools must be NULL. Just in
7280 // case, set them to NULL -- some memory may leak, but subsequent code will
7281 // work even if pools are not freed.
7282 KMP_DEBUG_ASSERT(__kmp_thread_pool == NULL);
7283 KMP_DEBUG_ASSERT(__kmp_thread_pool_insert_pt == NULL);
7284 KMP_DEBUG_ASSERT(__kmp_team_pool == NULL);
7285 __kmp_thread_pool = NULL;
7286 __kmp_thread_pool_insert_pt = NULL;
7287 __kmp_team_pool = NULL;
7288
7289 /* Allocate all of the variable sized records */
7290 /* NOTE: __kmp_threads_capacity entries are allocated, but the arrays are
7291 * expandable */
7292 /* Since allocation is cache-aligned, just add extra padding at the end */
7293 size =
7294 (sizeof(kmp_info_t *) + sizeof(kmp_root_t *)) * __kmp_threads_capacity +
7295 CACHE_LINE;
7296 __kmp_threads = (kmp_info_t **)__kmp_allocate(size);
7297 __kmp_root = (kmp_root_t **)((char *)__kmp_threads +
7298 sizeof(kmp_info_t *) * __kmp_threads_capacity);
7299
7300 /* init thread counts */
7301 KMP_DEBUG_ASSERT(__kmp_all_nth ==
7302 0); // Asserts fail if the library is reinitializing and
7303 KMP_DEBUG_ASSERT(__kmp_nth == 0); // something was wrong in termination.
7304 __kmp_all_nth = 0;
7305 __kmp_nth = 0;
7306
7307 /* setup the uber master thread and hierarchy */
7308 gtid = __kmp_register_root(TRUE);
7309 KA_TRACE(10, ("__kmp_do_serial_initialize T#%d\n", gtid));
7310 KMP_ASSERT(KMP_UBER_GTID(gtid));
7311 KMP_ASSERT(KMP_INITIAL_GTID(gtid));
7312
7313 KMP_MB(); /* Flush all pending memory write invalidates. */
7314
7315 __kmp_common_initialize();
7316
7317#if KMP_OS_UNIX
7318 /* invoke the child fork handler */
7319 __kmp_register_atfork();
7320#endif
7321
7322#if !KMP_DYNAMIC_LIB || \
7323 ((KMP_COMPILER_ICC || KMP_COMPILER_ICX) && KMP_OS_DARWIN)
7324 {
7325 /* Invoke the exit handler when the program finishes, only for static
7326 library and macOS* dynamic. For other dynamic libraries, we already
7327 have _fini and DllMain. */
7328 int rc = atexit(__kmp_internal_end_atexit);
7329 if (rc != 0) {
7330 __kmp_fatal(KMP_MSG(FunctionError, "atexit()"), KMP_ERR(rc),
7331 __kmp_msg_null);
7332 }
7333 }
7334#endif
7335
7336#if KMP_HANDLE_SIGNALS
7337#if KMP_OS_UNIX
7338 /* NOTE: make sure that this is called before the user installs their own
7339 signal handlers so that the user handlers are called first. this way they
7340 can return false, not call our handler, avoid terminating the library, and
7341 continue execution where they left off. */
7342 __kmp_install_signals(FALSE);
7343#endif /* KMP_OS_UNIX */
7344#if KMP_OS_WINDOWS
7345 __kmp_install_signals(TRUE);
7346#endif /* KMP_OS_WINDOWS */
7347#endif
7348
7349 /* we have finished the serial initialization */
7350 __kmp_init_counter++;
7351
7352 __kmp_init_serial = TRUE;
7353
7354 if (__kmp_version) {
7355 __kmp_print_version_1();
7356 }
7357
7358 if (__kmp_settings) {
7359 __kmp_env_print();
7360 }
7361
7362 if (__kmp_display_env || __kmp_display_env_verbose) {
7363 __kmp_env_print_2();
7364 }
7365
7366#if OMPT_SUPPORT
7367 ompt_post_init();
7368#endif
7369
7370 KMP_MB();
7371
7372 KA_TRACE(10, ("__kmp_do_serial_initialize: exit\n"));
7373}
7374
7375void __kmp_serial_initialize(void) {
7376 if (__kmp_init_serial) {
7377 return;
7378 }
7379 __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
7380 if (__kmp_init_serial) {
7381 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
7382 return;
7383 }
7384 __kmp_do_serial_initialize();
7385 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
7386}
7387
7388static void __kmp_do_middle_initialize(void) {
7389 int i, j;
7390 int prev_dflt_team_nth;
7391
7392 if (!__kmp_init_serial) {
7393 __kmp_do_serial_initialize();
7394 }
7395
7396 KA_TRACE(10, ("__kmp_middle_initialize: enter\n"));
7397
7398 if (UNLIKELY(!__kmp_need_register_serial)) {
7399 // We are in a forked child process. The registration was skipped during
7400 // serial initialization in __kmp_atfork_child handler. Do it here.
7401 __kmp_register_library_startup();
7402 }
7403
7404 // Save the previous value for the __kmp_dflt_team_nth so that
7405 // we can avoid some reinitialization if it hasn't changed.
7406 prev_dflt_team_nth = __kmp_dflt_team_nth;
7407
7408#if KMP_AFFINITY_SUPPORTED
7409 // __kmp_affinity_initialize() will try to set __kmp_ncores to the
7410 // number of cores on the machine.
7411 __kmp_affinity_initialize(__kmp_affinity);
7412
7413#endif /* KMP_AFFINITY_SUPPORTED */
7414
7415 KMP_ASSERT(__kmp_xproc > 0);
7416 if (__kmp_avail_proc == 0) {
7417 __kmp_avail_proc = __kmp_xproc;
7418 }
7419
7420 // If there were empty places in num_threads list (OMP_NUM_THREADS=,,2,3),
7421 // correct them now
7422 j = 0;
7423 while ((j < __kmp_nested_nth.used) && !__kmp_nested_nth.nth[j]) {
7424 __kmp_nested_nth.nth[j] = __kmp_dflt_team_nth = __kmp_dflt_team_nth_ub =
7425 __kmp_avail_proc;
7426 j++;
7427 }
7428
7429 if (__kmp_dflt_team_nth == 0) {
7430#ifdef KMP_DFLT_NTH_CORES
7431 // Default #threads = #cores
7432 __kmp_dflt_team_nth = __kmp_ncores;
7433 KA_TRACE(20, ("__kmp_middle_initialize: setting __kmp_dflt_team_nth = "
7434 "__kmp_ncores (%d)\n",
7435 __kmp_dflt_team_nth));
7436#else
7437 // Default #threads = #available OS procs
7438 __kmp_dflt_team_nth = __kmp_avail_proc;
7439 KA_TRACE(20, ("__kmp_middle_initialize: setting __kmp_dflt_team_nth = "
7440 "__kmp_avail_proc(%d)\n",
7441 __kmp_dflt_team_nth));
7442#endif /* KMP_DFLT_NTH_CORES */
7443 }
7444
7445 if (__kmp_dflt_team_nth < KMP_MIN_NTH) {
7446 __kmp_dflt_team_nth = KMP_MIN_NTH;
7447 }
7448 if (__kmp_dflt_team_nth > __kmp_sys_max_nth) {
7449 __kmp_dflt_team_nth = __kmp_sys_max_nth;
7450 }
7451
7452 if (__kmp_nesting_mode > 0)
7453 __kmp_set_nesting_mode_threads();
7454
7455 // There's no harm in continuing if the following check fails,
7456 // but it indicates an error in the previous logic.
7457 KMP_DEBUG_ASSERT(__kmp_dflt_team_nth <= __kmp_dflt_team_nth_ub);
7458
7459 if (__kmp_dflt_team_nth != prev_dflt_team_nth) {
7460 // Run through the __kmp_threads array and set the num threads icv for each
7461 // root thread that is currently registered with the RTL (which has not
7462 // already explicitly set its nthreads-var with a call to
7463 // omp_set_num_threads()).
7464 for (i = 0; i < __kmp_threads_capacity; i++) {
7465 kmp_info_t *thread = __kmp_threads[i];
7466 if (thread == NULL)
7467 continue;
7468 if (thread->th.th_current_task->td_icvs.nproc != 0)
7469 continue;
7470
7471 set__nproc(__kmp_threads[i], __kmp_dflt_team_nth);
7472 }
7473 }
7474 KA_TRACE(
7475 20,
7476 ("__kmp_middle_initialize: final value for __kmp_dflt_team_nth = %d\n",
7477 __kmp_dflt_team_nth));
7478
7479#ifdef KMP_ADJUST_BLOCKTIME
7480 /* Adjust blocktime to zero if necessary now that __kmp_avail_proc is set */
7481 if (!__kmp_env_blocktime && (__kmp_avail_proc > 0)) {
7482 KMP_DEBUG_ASSERT(__kmp_avail_proc > 0);
7483 if (__kmp_nth > __kmp_avail_proc) {
7484 __kmp_zero_bt = TRUE;
7485 }
7486 }
7487#endif /* KMP_ADJUST_BLOCKTIME */
7488
7489 /* we have finished middle initialization */
7490 TCW_SYNC_4(__kmp_init_middle, TRUE);
7491
7492 KA_TRACE(10, ("__kmp_do_middle_initialize: exit\n"));
7493}
7494
7495void __kmp_middle_initialize(void) {
7496 if (__kmp_init_middle) {
7497 return;
7498 }
7499 __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
7500 if (__kmp_init_middle) {
7501 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
7502 return;
7503 }
7504 __kmp_do_middle_initialize();
7505 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
7506}
7507
7508void __kmp_parallel_initialize(void) {
7509 int gtid = __kmp_entry_gtid(); // this might be a new root
7510
7511 /* synchronize parallel initialization (for sibling) */
7512 if (TCR_4(__kmp_init_parallel))
7513 return;
7514 __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
7515 if (TCR_4(__kmp_init_parallel)) {
7516 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
7517 return;
7518 }
7519
7520 /* TODO reinitialization after we have already shut down */
7521 if (TCR_4(__kmp_global.g.g_done)) {
7522 KA_TRACE(
7523 10,
7524 ("__kmp_parallel_initialize: attempt to init while shutting down\n"));
7525 __kmp_infinite_loop();
7526 }
7527
7528 /* jc: The lock __kmp_initz_lock is already held, so calling
7529 __kmp_serial_initialize would cause a deadlock. So we call
7530 __kmp_do_serial_initialize directly. */
7531 if (!__kmp_init_middle) {
7532 __kmp_do_middle_initialize();
7533 }
7534 __kmp_assign_root_init_mask();
7535 __kmp_resume_if_hard_paused();
7536
7537 /* begin initialization */
7538 KA_TRACE(10, ("__kmp_parallel_initialize: enter\n"));
7539 KMP_ASSERT(KMP_UBER_GTID(gtid));
7540
7541#if KMP_ARCH_X86 || KMP_ARCH_X86_64
7542 // Save the FP control regs.
7543 // Worker threads will set theirs to these values at thread startup.
7544 __kmp_store_x87_fpu_control_word(&__kmp_init_x87_fpu_control_word);
7545 __kmp_store_mxcsr(&__kmp_init_mxcsr);
7546 __kmp_init_mxcsr &= KMP_X86_MXCSR_MASK;
7547#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
7548
7549#if KMP_OS_UNIX
7550#if KMP_HANDLE_SIGNALS
7551 /* must be after __kmp_serial_initialize */
7552 __kmp_install_signals(TRUE);
7553#endif
7554#endif
7555
7556 __kmp_suspend_initialize();
7557
7558#if defined(USE_LOAD_BALANCE)
7559 if (__kmp_global.g.g_dynamic_mode == dynamic_default) {
7560 __kmp_global.g.g_dynamic_mode = dynamic_load_balance;
7561 }
7562#else
7563 if (__kmp_global.g.g_dynamic_mode == dynamic_default) {
7564 __kmp_global.g.g_dynamic_mode = dynamic_thread_limit;
7565 }
7566#endif
7567
7568 if (__kmp_version) {
7569 __kmp_print_version_2();
7570 }
7571
7572 /* we have finished parallel initialization */
7573 TCW_SYNC_4(__kmp_init_parallel, TRUE);
7574
7575 KMP_MB();
7576 KA_TRACE(10, ("__kmp_parallel_initialize: exit\n"));
7577
7578 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
7579}
7580
7581void __kmp_hidden_helper_initialize() {
7582 if (TCR_4(__kmp_init_hidden_helper))
7583 return;
7584
7585 // __kmp_parallel_initialize is required before we initialize hidden helper
7586 if (!TCR_4(__kmp_init_parallel))
7587 __kmp_parallel_initialize();
7588
7589 // Double check. Note that this double check should not be placed before
7590 // __kmp_parallel_initialize as it will cause dead lock.
7591 __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
7592 if (TCR_4(__kmp_init_hidden_helper)) {
7593 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
7594 return;
7595 }
7596
7597#if KMP_AFFINITY_SUPPORTED
7598 // Initialize hidden helper affinity settings.
7599 // The above __kmp_parallel_initialize() will initialize
7600 // regular affinity (and topology) if not already done.
7601 if (!__kmp_hh_affinity.flags.initialized)
7602 __kmp_affinity_initialize(__kmp_hh_affinity);
7603#endif
7604
7605 // Set the count of hidden helper tasks to be executed to zero
7606 KMP_ATOMIC_ST_REL(&__kmp_unexecuted_hidden_helper_tasks, 0);
7607
7608 // Set the global variable indicating that we're initializing hidden helper
7609 // team/threads
7610 TCW_SYNC_4(__kmp_init_hidden_helper_threads, TRUE);
7611
7612 // Platform independent initialization
7613 __kmp_do_initialize_hidden_helper_threads();
7614
7615 // Wait here for the finish of initialization of hidden helper teams
7616 __kmp_hidden_helper_threads_initz_wait();
7617
7618 // We have finished hidden helper initialization
7619 TCW_SYNC_4(__kmp_init_hidden_helper, TRUE);
7620
7621 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
7622}
7623
7624/* ------------------------------------------------------------------------ */
7625
7626void __kmp_run_before_invoked_task(int gtid, int tid, kmp_info_t *this_thr,
7627 kmp_team_t *team) {
7628 kmp_disp_t *dispatch;
7629
7630 KMP_MB();
7631
7632 /* none of the threads have encountered any constructs, yet. */
7633 this_thr->th.th_local.this_construct = 0;
7634#if KMP_CACHE_MANAGE
7635 KMP_CACHE_PREFETCH(&this_thr->th.th_bar[bs_forkjoin_barrier].bb.b_arrived);
7636#endif /* KMP_CACHE_MANAGE */
7637 dispatch = (kmp_disp_t *)TCR_PTR(this_thr->th.th_dispatch);
7638 KMP_DEBUG_ASSERT(dispatch);
7639 KMP_DEBUG_ASSERT(team->t.t_dispatch);
7640 // KMP_DEBUG_ASSERT( this_thr->th.th_dispatch == &team->t.t_dispatch[
7641 // this_thr->th.th_info.ds.ds_tid ] );
7642
7643 dispatch->th_disp_index = 0; /* reset the dispatch buffer counter */
7644 dispatch->th_doacross_buf_idx = 0; // reset doacross dispatch buffer counter
7645 if (__kmp_env_consistency_check)
7646 __kmp_push_parallel(gtid, team->t.t_ident);
7647
7648 KMP_MB(); /* Flush all pending memory write invalidates. */
7649}
7650
7651void __kmp_run_after_invoked_task(int gtid, int tid, kmp_info_t *this_thr,
7652 kmp_team_t *team) {
7653 if (__kmp_env_consistency_check)
7654 __kmp_pop_parallel(gtid, team->t.t_ident);
7655
7656 __kmp_finish_implicit_task(this_thr);
7657}
7658
7659int __kmp_invoke_task_func(int gtid) {
7660 int rc;
7661 int tid = __kmp_tid_from_gtid(gtid);
7662 kmp_info_t *this_thr = __kmp_threads[gtid];
7663 kmp_team_t *team = this_thr->th.th_team;
7664
7665 __kmp_run_before_invoked_task(gtid, tid, this_thr, team);
7666#if USE_ITT_BUILD
7667 if (__itt_stack_caller_create_ptr) {
7668 // inform ittnotify about entering user's code
7669 if (team->t.t_stack_id != NULL) {
7670 __kmp_itt_stack_callee_enter((__itt_caller)team->t.t_stack_id);
7671 } else {
7672 KMP_DEBUG_ASSERT(team->t.t_parent->t.t_stack_id != NULL);
7673 __kmp_itt_stack_callee_enter(
7674 (__itt_caller)team->t.t_parent->t.t_stack_id);
7675 }
7676 }
7677#endif /* USE_ITT_BUILD */
7678#if INCLUDE_SSC_MARKS
7679 SSC_MARK_INVOKING();
7680#endif
7681
7682#if OMPT_SUPPORT
7683 void *dummy;
7684 void **exit_frame_p;
7685 ompt_data_t *my_task_data;
7686 ompt_data_t *my_parallel_data;
7687 int ompt_team_size;
7688
7689 if (ompt_enabled.enabled) {
7690 exit_frame_p = &(team->t.t_implicit_task_taskdata[tid]
7691 .ompt_task_info.frame.exit_frame.ptr);
7692 } else {
7693 exit_frame_p = &dummy;
7694 }
7695
7696 my_task_data =
7697 &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data);
7698 my_parallel_data = &(team->t.ompt_team_info.parallel_data);
7699 if (ompt_enabled.ompt_callback_implicit_task) {
7700 ompt_team_size = team->t.t_nproc;
7701 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
7702 ompt_scope_begin, my_parallel_data, my_task_data, ompt_team_size,
7703 __kmp_tid_from_gtid(gtid), ompt_task_implicit);
7704 OMPT_CUR_TASK_INFO(this_thr)->thread_num = __kmp_tid_from_gtid(gtid);
7705 }
7706#endif
7707
7708#if KMP_STATS_ENABLED
7709 stats_state_e previous_state = KMP_GET_THREAD_STATE();
7710 if (previous_state == stats_state_e::TEAMS_REGION) {
7711 KMP_PUSH_PARTITIONED_TIMER(OMP_teams);
7712 } else {
7713 KMP_PUSH_PARTITIONED_TIMER(OMP_parallel);
7714 }
7715 KMP_SET_THREAD_STATE(IMPLICIT_TASK);
7716#endif
7717
7718 rc = __kmp_invoke_microtask((microtask_t)TCR_SYNC_PTR(team->t.t_pkfn), gtid,
7719 tid, (int)team->t.t_argc, (void **)team->t.t_argv
7720#if OMPT_SUPPORT
7721 ,
7722 exit_frame_p
7723#endif
7724 );
7725#if OMPT_SUPPORT
7726 *exit_frame_p = NULL;
7727 this_thr->th.ompt_thread_info.parallel_flags = ompt_parallel_team;
7728#endif
7729
7730#if KMP_STATS_ENABLED
7731 if (previous_state == stats_state_e::TEAMS_REGION) {
7732 KMP_SET_THREAD_STATE(previous_state);
7733 }
7734 KMP_POP_PARTITIONED_TIMER();
7735#endif
7736
7737#if USE_ITT_BUILD
7738 if (__itt_stack_caller_create_ptr) {
7739 // inform ittnotify about leaving user's code
7740 if (team->t.t_stack_id != NULL) {
7741 __kmp_itt_stack_callee_leave((__itt_caller)team->t.t_stack_id);
7742 } else {
7743 KMP_DEBUG_ASSERT(team->t.t_parent->t.t_stack_id != NULL);
7744 __kmp_itt_stack_callee_leave(
7745 (__itt_caller)team->t.t_parent->t.t_stack_id);
7746 }
7747 }
7748#endif /* USE_ITT_BUILD */
7749 __kmp_run_after_invoked_task(gtid, tid, this_thr, team);
7750
7751 return rc;
7752}
7753
7754void __kmp_teams_master(int gtid) {
7755 // This routine is called by all primary threads in teams construct
7756 kmp_info_t *thr = __kmp_threads[gtid];
7757 kmp_team_t *team = thr->th.th_team;
7758 ident_t *loc = team->t.t_ident;
7759 thr->th.th_set_nproc = thr->th.th_teams_size.nth;
7760 KMP_DEBUG_ASSERT(thr->th.th_teams_microtask);
7761 KMP_DEBUG_ASSERT(thr->th.th_set_nproc);
7762 KA_TRACE(20, ("__kmp_teams_master: T#%d, Tid %d, microtask %p\n", gtid,
7763 __kmp_tid_from_gtid(gtid), thr->th.th_teams_microtask));
7764
7765 // This thread is a new CG root. Set up the proper variables.
7766 kmp_cg_root_t *tmp = (kmp_cg_root_t *)__kmp_allocate(sizeof(kmp_cg_root_t));
7767 tmp->cg_root = thr; // Make thr the CG root
7768 // Init to thread limit stored when league primary threads were forked
7769 tmp->cg_thread_limit = thr->th.th_current_task->td_icvs.thread_limit;
7770 tmp->cg_nthreads = 1; // Init counter to one active thread, this one
7771 KA_TRACE(100, ("__kmp_teams_master: Thread %p created node %p and init"
7772 " cg_nthreads to 1\n",
7773 thr, tmp));
7774 tmp->up = thr->th.th_cg_roots;
7775 thr->th.th_cg_roots = tmp;
7776
7777// Launch league of teams now, but not let workers execute
7778// (they hang on fork barrier until next parallel)
7779#if INCLUDE_SSC_MARKS
7780 SSC_MARK_FORKING();
7781#endif
7782 __kmp_fork_call(loc, gtid, fork_context_intel, team->t.t_argc,
7783 (microtask_t)thr->th.th_teams_microtask, // "wrapped" task
7784 VOLATILE_CAST(launch_t) __kmp_invoke_task_func, NULL);
7785#if INCLUDE_SSC_MARKS
7786 SSC_MARK_JOINING();
7787#endif
7788 // If the team size was reduced from the limit, set it to the new size
7789 if (thr->th.th_team_nproc < thr->th.th_teams_size.nth)
7790 thr->th.th_teams_size.nth = thr->th.th_team_nproc;
7791 // AC: last parameter "1" eliminates join barrier which won't work because
7792 // worker threads are in a fork barrier waiting for more parallel regions
7793 __kmp_join_call(loc, gtid
7794#if OMPT_SUPPORT
7795 ,
7796 fork_context_intel
7797#endif
7798 ,
7799 1);
7800}
7801
7802int __kmp_invoke_teams_master(int gtid) {
7803 kmp_info_t *this_thr = __kmp_threads[gtid];
7804 kmp_team_t *team = this_thr->th.th_team;
7805#if KMP_DEBUG
7806 if (!__kmp_threads[gtid]->th.th_team->t.t_serialized)
7807 KMP_DEBUG_ASSERT((void *)__kmp_threads[gtid]->th.th_team->t.t_pkfn ==
7808 (void *)__kmp_teams_master);
7809#endif
7810 __kmp_run_before_invoked_task(gtid, 0, this_thr, team);
7811#if OMPT_SUPPORT
7812 int tid = __kmp_tid_from_gtid(gtid);
7813 ompt_data_t *task_data =
7814 &team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data;
7815 ompt_data_t *parallel_data = &team->t.ompt_team_info.parallel_data;
7816 if (ompt_enabled.ompt_callback_implicit_task) {
7817 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
7818 ompt_scope_begin, parallel_data, task_data, team->t.t_nproc, tid,
7819 ompt_task_initial);
7820 OMPT_CUR_TASK_INFO(this_thr)->thread_num = tid;
7821 }
7822#endif
7823 __kmp_teams_master(gtid);
7824#if OMPT_SUPPORT
7825 this_thr->th.ompt_thread_info.parallel_flags = ompt_parallel_league;
7826#endif
7827 __kmp_run_after_invoked_task(gtid, 0, this_thr, team);
7828 return 1;
7829}
7830
7831/* this sets the requested number of threads for the next parallel region
7832 encountered by this team. since this should be enclosed in the forkjoin
7833 critical section it should avoid race conditions with asymmetrical nested
7834 parallelism */
7835void __kmp_push_num_threads(ident_t *id, int gtid, int num_threads) {
7836 kmp_info_t *thr = __kmp_threads[gtid];
7837
7838 if (num_threads > 0)
7839 thr->th.th_set_nproc = num_threads;
7840}
7841
7842void __kmp_push_num_threads_list(ident_t *id, int gtid, kmp_uint32 list_length,
7843 int *num_threads_list) {
7844 kmp_info_t *thr = __kmp_threads[gtid];
7845
7846 KMP_DEBUG_ASSERT(list_length > 1);
7847
7848 if (num_threads_list[0] > 0)
7849 thr->th.th_set_nproc = num_threads_list[0];
7850 thr->th.th_set_nested_nth =
7851 (int *)KMP_INTERNAL_MALLOC(list_length * sizeof(int));
7852 for (kmp_uint32 i = 0; i < list_length; ++i)
7853 thr->th.th_set_nested_nth[i] = num_threads_list[i];
7854 thr->th.th_set_nested_nth_sz = list_length;
7855}
7856
7857void __kmp_set_strict_num_threads(ident_t *loc, int gtid, int sev,
7858 const char *msg) {
7859 kmp_info_t *thr = __kmp_threads[gtid];
7860 thr->th.th_nt_strict = true;
7861 thr->th.th_nt_loc = loc;
7862 // if sev is unset make fatal
7863 if (sev == severity_warning)
7864 thr->th.th_nt_sev = sev;
7865 else
7866 thr->th.th_nt_sev = severity_fatal;
7867 // if msg is unset, use an appropriate message
7868 if (msg)
7869 thr->th.th_nt_msg = msg;
7870 else
7871 thr->th.th_nt_msg = "Cannot form team with number of threads specified by "
7872 "strict num_threads clause.";
7873}
7874
7875static void __kmp_push_thread_limit(kmp_info_t *thr, int num_teams,
7876 int num_threads) {
7877 KMP_DEBUG_ASSERT(thr);
7878 // Remember the number of threads for inner parallel regions
7879 if (!TCR_4(__kmp_init_middle))
7880 __kmp_middle_initialize(); // get internal globals calculated
7881 __kmp_assign_root_init_mask();
7882 KMP_DEBUG_ASSERT(__kmp_avail_proc);
7883 KMP_DEBUG_ASSERT(__kmp_dflt_team_nth);
7884
7885 if (num_threads == 0) {
7886 if (__kmp_teams_thread_limit > 0) {
7887 num_threads = __kmp_teams_thread_limit;
7888 } else {
7889 num_threads = __kmp_avail_proc / num_teams;
7890 }
7891 // adjust num_threads w/o warning as it is not user setting
7892 // num_threads = min(num_threads, nthreads-var, thread-limit-var)
7893 // no thread_limit clause specified - do not change thread-limit-var ICV
7894 if (num_threads > __kmp_dflt_team_nth) {
7895 num_threads = __kmp_dflt_team_nth; // honor nthreads-var ICV
7896 }
7897 if (num_threads > thr->th.th_current_task->td_icvs.thread_limit) {
7898 num_threads = thr->th.th_current_task->td_icvs.thread_limit;
7899 } // prevent team size to exceed thread-limit-var
7900 if (num_teams * num_threads > __kmp_teams_max_nth) {
7901 num_threads = __kmp_teams_max_nth / num_teams;
7902 }
7903 if (num_threads == 0) {
7904 num_threads = 1;
7905 }
7906 } else {
7907 if (num_threads < 0) {
7908 __kmp_msg(kmp_ms_warning, KMP_MSG(CantFormThrTeam, num_threads, 1),
7909 __kmp_msg_null);
7910 num_threads = 1;
7911 }
7912 // This thread will be the primary thread of the league primary threads
7913 // Store new thread limit; old limit is saved in th_cg_roots list
7914 thr->th.th_current_task->td_icvs.thread_limit = num_threads;
7915 // num_threads = min(num_threads, nthreads-var)
7916 if (num_threads > __kmp_dflt_team_nth) {
7917 num_threads = __kmp_dflt_team_nth; // honor nthreads-var ICV
7918 }
7919 if (num_teams * num_threads > __kmp_teams_max_nth) {
7920 int new_threads = __kmp_teams_max_nth / num_teams;
7921 if (new_threads == 0) {
7922 new_threads = 1;
7923 }
7924 if (new_threads != num_threads) {
7925 if (!__kmp_reserve_warn) { // user asked for too many threads
7926 __kmp_reserve_warn = 1; // conflicts with KMP_TEAMS_THREAD_LIMIT
7927 __kmp_msg(kmp_ms_warning,
7928 KMP_MSG(CantFormThrTeam, num_threads, new_threads),
7929 KMP_HNT(Unset_ALL_THREADS), __kmp_msg_null);
7930 }
7931 }
7932 num_threads = new_threads;
7933 }
7934 }
7935 thr->th.th_teams_size.nth = num_threads;
7936}
7937
7938/* this sets the requested number of teams for the teams region and/or
7939 the number of threads for the next parallel region encountered */
7940void __kmp_push_num_teams(ident_t *id, int gtid, int num_teams,
7941 int num_threads) {
7942 kmp_info_t *thr = __kmp_threads[gtid];
7943 if (num_teams < 0) {
7944 // OpenMP specification requires requested values to be positive,
7945 // but people can send us any value, so we'd better check
7946 __kmp_msg(kmp_ms_warning, KMP_MSG(NumTeamsNotPositive, num_teams, 1),
7947 __kmp_msg_null);
7948 num_teams = 1;
7949 }
7950 if (num_teams == 0) {
7951 if (__kmp_nteams > 0) {
7952 num_teams = __kmp_nteams;
7953 } else {
7954 num_teams = 1; // default number of teams is 1.
7955 }
7956 }
7957 if (num_teams > __kmp_teams_max_nth) { // if too many teams requested?
7958 if (!__kmp_reserve_warn) {
7959 __kmp_reserve_warn = 1;
7960 __kmp_msg(kmp_ms_warning,
7961 KMP_MSG(CantFormThrTeam, num_teams, __kmp_teams_max_nth),
7962 KMP_HNT(Unset_ALL_THREADS), __kmp_msg_null);
7963 }
7964 num_teams = __kmp_teams_max_nth;
7965 }
7966 // Set number of teams (number of threads in the outer "parallel" of the
7967 // teams)
7968 thr->th.th_set_nproc = thr->th.th_teams_size.nteams = num_teams;
7969
7970 __kmp_push_thread_limit(thr, num_teams, num_threads);
7971}
7972
7973/* This sets the requested number of teams for the teams region and/or
7974 the number of threads for the next parallel region encountered */
7975void __kmp_push_num_teams_51(ident_t *id, int gtid, int num_teams_lb,
7976 int num_teams_ub, int num_threads) {
7977 kmp_info_t *thr = __kmp_threads[gtid];
7978 KMP_DEBUG_ASSERT(num_teams_lb >= 0 && num_teams_ub >= 0);
7979 KMP_DEBUG_ASSERT(num_teams_ub >= num_teams_lb);
7980 KMP_DEBUG_ASSERT(num_threads >= 0);
7981
7982 if (num_teams_lb > num_teams_ub) {
7983 __kmp_fatal(KMP_MSG(FailedToCreateTeam, num_teams_lb, num_teams_ub),
7984 KMP_HNT(SetNewBound, __kmp_teams_max_nth), __kmp_msg_null);
7985 }
7986
7987 int num_teams = 1; // defalt number of teams is 1.
7988
7989 if (num_teams_lb == 0 && num_teams_ub > 0)
7990 num_teams_lb = num_teams_ub;
7991
7992 if (num_teams_lb == 0 && num_teams_ub == 0) { // no num_teams clause
7993 num_teams = (__kmp_nteams > 0) ? __kmp_nteams : num_teams;
7994 if (num_teams > __kmp_teams_max_nth) {
7995 if (!__kmp_reserve_warn) {
7996 __kmp_reserve_warn = 1;
7997 __kmp_msg(kmp_ms_warning,
7998 KMP_MSG(CantFormThrTeam, num_teams, __kmp_teams_max_nth),
7999 KMP_HNT(Unset_ALL_THREADS), __kmp_msg_null);
8000 }
8001 num_teams = __kmp_teams_max_nth;
8002 }
8003 } else if (num_teams_lb == num_teams_ub) { // requires exact number of teams
8004 num_teams = num_teams_ub;
8005 } else { // num_teams_lb <= num_teams <= num_teams_ub
8006 if (num_threads <= 0) {
8007 if (num_teams_ub > __kmp_teams_max_nth) {
8008 num_teams = num_teams_lb;
8009 } else {
8010 num_teams = num_teams_ub;
8011 }
8012 } else {
8013 num_teams = (num_threads > __kmp_teams_max_nth)
8014 ? num_teams
8015 : __kmp_teams_max_nth / num_threads;
8016 if (num_teams < num_teams_lb) {
8017 num_teams = num_teams_lb;
8018 } else if (num_teams > num_teams_ub) {
8019 num_teams = num_teams_ub;
8020 }
8021 }
8022 }
8023 // Set number of teams (number of threads in the outer "parallel" of the
8024 // teams)
8025 thr->th.th_set_nproc = thr->th.th_teams_size.nteams = num_teams;
8026
8027 __kmp_push_thread_limit(thr, num_teams, num_threads);
8028}
8029
8030// Set the proc_bind var to use in the following parallel region.
8031void __kmp_push_proc_bind(ident_t *id, int gtid, kmp_proc_bind_t proc_bind) {
8032 kmp_info_t *thr = __kmp_threads[gtid];
8033 thr->th.th_set_proc_bind = proc_bind;
8034}
8035
8036/* Launch the worker threads into the microtask. */
8037
8038void __kmp_internal_fork(ident_t *id, int gtid, kmp_team_t *team) {
8039 kmp_info_t *this_thr = __kmp_threads[gtid];
8040
8041#ifdef KMP_DEBUG
8042 int f;
8043#endif /* KMP_DEBUG */
8044
8045 KMP_DEBUG_ASSERT(team);
8046 KMP_DEBUG_ASSERT(this_thr->th.th_team == team);
8047 KMP_ASSERT(KMP_MASTER_GTID(gtid));
8048 KMP_MB(); /* Flush all pending memory write invalidates. */
8049
8050 team->t.t_construct = 0; /* no single directives seen yet */
8051 team->t.t_ordered.dt.t_value =
8052 0; /* thread 0 enters the ordered section first */
8053
8054 /* Reset the identifiers on the dispatch buffer */
8055 KMP_DEBUG_ASSERT(team->t.t_disp_buffer);
8056 if (team->t.t_max_nproc > 1) {
8057 int i;
8058 for (i = 0; i < __kmp_dispatch_num_buffers; ++i) {
8059 team->t.t_disp_buffer[i].buffer_index = i;
8060 team->t.t_disp_buffer[i].doacross_buf_idx = i;
8061 }
8062 } else {
8063 team->t.t_disp_buffer[0].buffer_index = 0;
8064 team->t.t_disp_buffer[0].doacross_buf_idx = 0;
8065 }
8066
8067 KMP_MB(); /* Flush all pending memory write invalidates. */
8068 KMP_ASSERT(this_thr->th.th_team == team);
8069
8070#ifdef KMP_DEBUG
8071 for (f = 0; f < team->t.t_nproc; f++) {
8072 KMP_DEBUG_ASSERT(team->t.t_threads[f] &&
8073 team->t.t_threads[f]->th.th_team_nproc == team->t.t_nproc);
8074 }
8075#endif /* KMP_DEBUG */
8076
8077 /* release the worker threads so they may begin working */
8078 __kmp_fork_barrier(gtid, 0);
8079}
8080
8081void __kmp_internal_join(ident_t *id, int gtid, kmp_team_t *team) {
8082 kmp_info_t *this_thr = __kmp_threads[gtid];
8083
8084 KMP_DEBUG_ASSERT(team);
8085 KMP_DEBUG_ASSERT(this_thr->th.th_team == team);
8086 KMP_ASSERT(KMP_MASTER_GTID(gtid));
8087 KMP_MB(); /* Flush all pending memory write invalidates. */
8088
8089 /* Join barrier after fork */
8090
8091#ifdef KMP_DEBUG
8092 if (__kmp_threads[gtid] &&
8093 __kmp_threads[gtid]->th.th_team_nproc != team->t.t_nproc) {
8094 __kmp_printf("GTID: %d, __kmp_threads[%d]=%p\n", gtid, gtid,
8095 __kmp_threads[gtid]);
8096 __kmp_printf("__kmp_threads[%d]->th.th_team_nproc=%d, TEAM: %p, "
8097 "team->t.t_nproc=%d\n",
8098 gtid, __kmp_threads[gtid]->th.th_team_nproc, team,
8099 team->t.t_nproc);
8100 __kmp_print_structure();
8101 }
8102 KMP_DEBUG_ASSERT(__kmp_threads[gtid] &&
8103 __kmp_threads[gtid]->th.th_team_nproc == team->t.t_nproc);
8104#endif /* KMP_DEBUG */
8105
8106 __kmp_join_barrier(gtid); /* wait for everyone */
8107#if OMPT_SUPPORT
8108 ompt_state_t ompt_state = this_thr->th.ompt_thread_info.state;
8109 if (ompt_enabled.enabled &&
8110 (ompt_state == ompt_state_wait_barrier_teams ||
8111 ompt_state == ompt_state_wait_barrier_implicit_parallel)) {
8112 int ds_tid = this_thr->th.th_info.ds.ds_tid;
8113 ompt_data_t *task_data = OMPT_CUR_TASK_DATA(this_thr);
8114 this_thr->th.ompt_thread_info.state = ompt_state_overhead;
8115#if OMPT_OPTIONAL
8116 void *codeptr = NULL;
8117 if (KMP_MASTER_TID(ds_tid) &&
8118 (ompt_callbacks.ompt_callback(ompt_callback_sync_region_wait) ||
8119 ompt_callbacks.ompt_callback(ompt_callback_sync_region)))
8120 codeptr = OMPT_CUR_TEAM_INFO(this_thr)->master_return_address;
8121
8122 ompt_sync_region_t sync_kind = ompt_sync_region_barrier_implicit_parallel;
8123 if (this_thr->th.ompt_thread_info.parallel_flags & ompt_parallel_league)
8124 sync_kind = ompt_sync_region_barrier_teams;
8125 if (ompt_enabled.ompt_callback_sync_region_wait) {
8126 ompt_callbacks.ompt_callback(ompt_callback_sync_region_wait)(
8127 sync_kind, ompt_scope_end, NULL, task_data, codeptr);
8128 }
8129 if (ompt_enabled.ompt_callback_sync_region) {
8130 ompt_callbacks.ompt_callback(ompt_callback_sync_region)(
8131 sync_kind, ompt_scope_end, NULL, task_data, codeptr);
8132 }
8133#endif
8134 if (!KMP_MASTER_TID(ds_tid) && ompt_enabled.ompt_callback_implicit_task) {
8135 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
8136 ompt_scope_end, NULL, task_data, 0, ds_tid,
8137 ompt_task_implicit); // TODO: Can this be ompt_task_initial?
8138 }
8139 }
8140#endif
8141
8142 KMP_MB(); /* Flush all pending memory write invalidates. */
8143 KMP_ASSERT(this_thr->th.th_team == team);
8144}
8145
8146/* ------------------------------------------------------------------------ */
8147
8148#ifdef USE_LOAD_BALANCE
8149
8150// Return the worker threads actively spinning in the hot team, if we
8151// are at the outermost level of parallelism. Otherwise, return 0.
8152static int __kmp_active_hot_team_nproc(kmp_root_t *root) {
8153 int i;
8154 int retval;
8155 kmp_team_t *hot_team;
8156
8157 if (root->r.r_active) {
8158 return 0;
8159 }
8160 hot_team = root->r.r_hot_team;
8161 if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME) {
8162 return hot_team->t.t_nproc - 1; // Don't count primary thread
8163 }
8164
8165 // Skip the primary thread - it is accounted for elsewhere.
8166 retval = 0;
8167 for (i = 1; i < hot_team->t.t_nproc; i++) {
8168 if (hot_team->t.t_threads[i]->th.th_active) {
8169 retval++;
8170 }
8171 }
8172 return retval;
8173}
8174
8175// Perform an automatic adjustment to the number of
8176// threads used by the next parallel region.
8177static int __kmp_load_balance_nproc(kmp_root_t *root, int set_nproc) {
8178 int retval;
8179 int pool_active;
8180 int hot_team_active;
8181 int team_curr_active;
8182 int system_active;
8183
8184 KB_TRACE(20, ("__kmp_load_balance_nproc: called root:%p set_nproc:%d\n", root,
8185 set_nproc));
8186 KMP_DEBUG_ASSERT(root);
8187 KMP_DEBUG_ASSERT(root->r.r_root_team->t.t_threads[0]
8188 ->th.th_current_task->td_icvs.dynamic == TRUE);
8189 KMP_DEBUG_ASSERT(set_nproc > 1);
8190
8191 if (set_nproc == 1) {
8192 KB_TRACE(20, ("__kmp_load_balance_nproc: serial execution.\n"));
8193 return 1;
8194 }
8195
8196 // Threads that are active in the thread pool, active in the hot team for this
8197 // particular root (if we are at the outer par level), and the currently
8198 // executing thread (to become the primary thread) are available to add to the
8199 // new team, but are currently contributing to the system load, and must be
8200 // accounted for.
8201 pool_active = __kmp_thread_pool_active_nth;
8202 hot_team_active = __kmp_active_hot_team_nproc(root);
8203 team_curr_active = pool_active + hot_team_active + 1;
8204
8205 // Check the system load.
8206 system_active = __kmp_get_load_balance(__kmp_avail_proc + team_curr_active);
8207 KB_TRACE(30, ("__kmp_load_balance_nproc: system active = %d pool active = %d "
8208 "hot team active = %d\n",
8209 system_active, pool_active, hot_team_active));
8210
8211 if (system_active < 0) {
8212 // There was an error reading the necessary info from /proc, so use the
8213 // thread limit algorithm instead. Once we set __kmp_global.g.g_dynamic_mode
8214 // = dynamic_thread_limit, we shouldn't wind up getting back here.
8215 __kmp_global.g.g_dynamic_mode = dynamic_thread_limit;
8216 KMP_WARNING(CantLoadBalUsing, "KMP_DYNAMIC_MODE=thread limit");
8217
8218 // Make this call behave like the thread limit algorithm.
8219 retval = __kmp_avail_proc - __kmp_nth +
8220 (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc);
8221 if (retval > set_nproc) {
8222 retval = set_nproc;
8223 }
8224 if (retval < KMP_MIN_NTH) {
8225 retval = KMP_MIN_NTH;
8226 }
8227
8228 KB_TRACE(20, ("__kmp_load_balance_nproc: thread limit exit. retval:%d\n",
8229 retval));
8230 return retval;
8231 }
8232
8233 // There is a slight delay in the load balance algorithm in detecting new
8234 // running procs. The real system load at this instant should be at least as
8235 // large as the #active omp thread that are available to add to the team.
8236 if (system_active < team_curr_active) {
8237 system_active = team_curr_active;
8238 }
8239 retval = __kmp_avail_proc - system_active + team_curr_active;
8240 if (retval > set_nproc) {
8241 retval = set_nproc;
8242 }
8243 if (retval < KMP_MIN_NTH) {
8244 retval = KMP_MIN_NTH;
8245 }
8246
8247 KB_TRACE(20, ("__kmp_load_balance_nproc: exit. retval:%d\n", retval));
8248 return retval;
8249} // __kmp_load_balance_nproc()
8250
8251#endif /* USE_LOAD_BALANCE */
8252
8253/* ------------------------------------------------------------------------ */
8254
8255/* NOTE: this is called with the __kmp_init_lock held */
8256void __kmp_cleanup(void) {
8257 int f;
8258
8259 KA_TRACE(10, ("__kmp_cleanup: enter\n"));
8260
8261 if (TCR_4(__kmp_init_parallel)) {
8262#if KMP_HANDLE_SIGNALS
8263 __kmp_remove_signals();
8264#endif
8265 TCW_4(__kmp_init_parallel, FALSE);
8266 }
8267
8268 if (TCR_4(__kmp_init_middle)) {
8269#if KMP_AFFINITY_SUPPORTED
8270 __kmp_affinity_uninitialize();
8271#endif /* KMP_AFFINITY_SUPPORTED */
8272 __kmp_cleanup_hierarchy();
8273 TCW_4(__kmp_init_middle, FALSE);
8274 }
8275
8276 KA_TRACE(10, ("__kmp_cleanup: go serial cleanup\n"));
8277
8278 if (__kmp_init_serial) {
8279 __kmp_runtime_destroy();
8280 __kmp_init_serial = FALSE;
8281 }
8282
8283 __kmp_cleanup_threadprivate_caches();
8284
8285 for (f = 0; f < __kmp_threads_capacity; f++) {
8286 if (__kmp_root[f] != NULL) {
8287 __kmp_free(__kmp_root[f]);
8288 __kmp_root[f] = NULL;
8289 }
8290 }
8291 __kmp_free(__kmp_threads);
8292 // __kmp_threads and __kmp_root were allocated at once, as single block, so
8293 // there is no need in freeing __kmp_root.
8294 __kmp_threads = NULL;
8295 __kmp_root = NULL;
8296 __kmp_threads_capacity = 0;
8297
8298 // Free old __kmp_threads arrays if they exist.
8299 kmp_old_threads_list_t *ptr = __kmp_old_threads_list;
8300 while (ptr) {
8301 kmp_old_threads_list_t *next = ptr->next;
8302 __kmp_free(ptr->threads);
8303 __kmp_free(ptr);
8304 ptr = next;
8305 }
8306 __kmp_old_threads_list = NULL;
8307
8308#if KMP_USE_DYNAMIC_LOCK
8309 __kmp_cleanup_indirect_user_locks();
8310#else
8311 __kmp_cleanup_user_locks();
8312#endif
8313#if OMPD_SUPPORT
8314 if (ompd_env_block) {
8315 __kmp_free(ompd_env_block);
8316 ompd_env_block = NULL;
8317 ompd_env_block_size = 0;
8318 }
8319#endif
8320
8321#if KMP_AFFINITY_SUPPORTED
8322 KMP_INTERNAL_FREE(CCAST(char *, __kmp_cpuinfo_file));
8323 __kmp_cpuinfo_file = NULL;
8324#endif /* KMP_AFFINITY_SUPPORTED */
8325
8326#if KMP_USE_ADAPTIVE_LOCKS
8327#if KMP_DEBUG_ADAPTIVE_LOCKS
8328 __kmp_print_speculative_stats();
8329#endif
8330#endif
8331 KMP_INTERNAL_FREE(__kmp_nested_nth.nth);
8332 __kmp_nested_nth.nth = NULL;
8333 __kmp_nested_nth.size = 0;
8334 __kmp_nested_nth.used = 0;
8335
8336 KMP_INTERNAL_FREE(__kmp_nested_proc_bind.bind_types);
8337 __kmp_nested_proc_bind.bind_types = NULL;
8338 __kmp_nested_proc_bind.size = 0;
8339 __kmp_nested_proc_bind.used = 0;
8340 __kmp_dflt_team_nth = 0;
8341 __kmp_dflt_team_nth_ub = 0;
8342 if (__kmp_affinity_format) {
8343 KMP_INTERNAL_FREE(__kmp_affinity_format);
8344 __kmp_affinity_format = NULL;
8345 }
8346
8347 __kmp_i18n_catclose();
8348
8349 if (__kmp_nesting_nth_level)
8350 KMP_INTERNAL_FREE(__kmp_nesting_nth_level);
8351
8352#if KMP_USE_HIER_SCHED
8353 __kmp_hier_scheds.deallocate();
8354#endif
8355
8356#if KMP_STATS_ENABLED
8357 __kmp_stats_fini();
8358#endif
8359
8360 __kmpc_destroy_allocator(KMP_GTID_SHUTDOWN, __kmp_def_allocator);
8361 __kmp_def_allocator = omp_default_mem_alloc;
8362
8363 KA_TRACE(10, ("__kmp_cleanup: exit\n"));
8364}
8365
8366/* ------------------------------------------------------------------------ */
8367
8368int __kmp_ignore_mppbeg(void) {
8369 char *env;
8370
8371 if ((env = getenv("KMP_IGNORE_MPPBEG")) != NULL) {
8372 if (__kmp_str_match_false(env))
8373 return FALSE;
8374 }
8375 // By default __kmpc_begin() is no-op.
8376 return TRUE;
8377}
8378
8379int __kmp_ignore_mppend(void) {
8380 char *env;
8381
8382 if ((env = getenv("KMP_IGNORE_MPPEND")) != NULL) {
8383 if (__kmp_str_match_false(env))
8384 return FALSE;
8385 }
8386 // By default __kmpc_end() is no-op.
8387 return TRUE;
8388}
8389
8390void __kmp_internal_begin(void) {
8391 int gtid;
8392 kmp_root_t *root;
8393
8394 /* this is a very important step as it will register new sibling threads
8395 and assign these new uber threads a new gtid */
8396 gtid = __kmp_entry_gtid();
8397 root = __kmp_threads[gtid]->th.th_root;
8398 KMP_ASSERT(KMP_UBER_GTID(gtid));
8399
8400 if (root->r.r_begin)
8401 return;
8402 __kmp_acquire_lock(&root->r.r_begin_lock, gtid);
8403 if (root->r.r_begin) {
8404 __kmp_release_lock(&root->r.r_begin_lock, gtid);
8405 return;
8406 }
8407
8408 root->r.r_begin = TRUE;
8409
8410 __kmp_release_lock(&root->r.r_begin_lock, gtid);
8411}
8412
8413/* ------------------------------------------------------------------------ */
8414
8415void __kmp_user_set_library(enum library_type arg) {
8416 int gtid;
8417 kmp_root_t *root;
8418 kmp_info_t *thread;
8419
8420 /* first, make sure we are initialized so we can get our gtid */
8421
8422 gtid = __kmp_entry_gtid();
8423 thread = __kmp_threads[gtid];
8424
8425 root = thread->th.th_root;
8426
8427 KA_TRACE(20, ("__kmp_user_set_library: enter T#%d, arg: %d, %d\n", gtid, arg,
8428 library_serial));
8429 if (root->r.r_in_parallel) { /* Must be called in serial section of top-level
8430 thread */
8431 KMP_WARNING(SetLibraryIncorrectCall);
8432 return;
8433 }
8434
8435 switch (arg) {
8436 case library_serial:
8437 thread->th.th_set_nproc = 0;
8438 set__nproc(thread, 1);
8439 break;
8440 case library_turnaround:
8441 thread->th.th_set_nproc = 0;
8442 set__nproc(thread, __kmp_dflt_team_nth ? __kmp_dflt_team_nth
8443 : __kmp_dflt_team_nth_ub);
8444 break;
8445 case library_throughput:
8446 thread->th.th_set_nproc = 0;
8447 set__nproc(thread, __kmp_dflt_team_nth ? __kmp_dflt_team_nth
8448 : __kmp_dflt_team_nth_ub);
8449 break;
8450 default:
8451 KMP_FATAL(UnknownLibraryType, arg);
8452 }
8453
8454 __kmp_aux_set_library(arg);
8455}
8456
8457void __kmp_aux_set_stacksize(size_t arg) {
8458 if (!__kmp_init_serial)
8459 __kmp_serial_initialize();
8460
8461#if KMP_OS_DARWIN
8462 if (arg & (0x1000 - 1)) {
8463 arg &= ~(0x1000 - 1);
8464 if (arg + 0x1000) /* check for overflow if we round up */
8465 arg += 0x1000;
8466 }
8467#endif
8468 __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
8469
8470 /* only change the default stacksize before the first parallel region */
8471 if (!TCR_4(__kmp_init_parallel)) {
8472 size_t value = arg; /* argument is in bytes */
8473
8474 if (value < __kmp_sys_min_stksize)
8475 value = __kmp_sys_min_stksize;
8476 else if (value > KMP_MAX_STKSIZE)
8477 value = KMP_MAX_STKSIZE;
8478
8479 __kmp_stksize = value;
8480
8481 __kmp_env_stksize = TRUE; /* was KMP_STACKSIZE specified? */
8482 }
8483
8484 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
8485}
8486
8487/* set the behaviour of the runtime library */
8488/* TODO this can cause some odd behaviour with sibling parallelism... */
8489void __kmp_aux_set_library(enum library_type arg) {
8490 __kmp_library = arg;
8491
8492 switch (__kmp_library) {
8493 case library_serial: {
8494 KMP_INFORM(LibraryIsSerial);
8495 } break;
8496 case library_turnaround:
8497 if (__kmp_use_yield == 1 && !__kmp_use_yield_exp_set)
8498 __kmp_use_yield = 2; // only yield when oversubscribed
8499 break;
8500 case library_throughput:
8501 if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME)
8502 __kmp_dflt_blocktime = KMP_DEFAULT_BLOCKTIME;
8503 break;
8504 default:
8505 KMP_FATAL(UnknownLibraryType, arg);
8506 }
8507}
8508
8509/* Getting team information common for all team API */
8510// Returns NULL if not in teams construct
8511static kmp_team_t *__kmp_aux_get_team_info(int &teams_serialized) {
8512 kmp_info_t *thr = __kmp_entry_thread();
8513 teams_serialized = 0;
8514 if (thr->th.th_teams_microtask) {
8515 kmp_team_t *team = thr->th.th_team;
8516 int tlevel = thr->th.th_teams_level; // the level of the teams construct
8517 int ii = team->t.t_level;
8518 teams_serialized = team->t.t_serialized;
8519 int level = tlevel + 1;
8520 KMP_DEBUG_ASSERT(ii >= tlevel);
8521 while (ii > level) {
8522 for (teams_serialized = team->t.t_serialized;
8523 (teams_serialized > 0) && (ii > level); teams_serialized--, ii--) {
8524 }
8525 if (team->t.t_serialized && (!teams_serialized)) {
8526 team = team->t.t_parent;
8527 continue;
8528 }
8529 if (ii > level) {
8530 team = team->t.t_parent;
8531 ii--;
8532 }
8533 }
8534 return team;
8535 }
8536 return NULL;
8537}
8538
8539int __kmp_aux_get_team_num() {
8540 int serialized;
8541 kmp_team_t *team = __kmp_aux_get_team_info(serialized);
8542 if (team) {
8543 if (serialized > 1) {
8544 return 0; // teams region is serialized ( 1 team of 1 thread ).
8545 } else {
8546 return team->t.t_master_tid;
8547 }
8548 }
8549 return 0;
8550}
8551
8552int __kmp_aux_get_num_teams() {
8553 int serialized;
8554 kmp_team_t *team = __kmp_aux_get_team_info(serialized);
8555 if (team) {
8556 if (serialized > 1) {
8557 return 1;
8558 } else {
8559 return team->t.t_parent->t.t_nproc;
8560 }
8561 }
8562 return 1;
8563}
8564
8565/* ------------------------------------------------------------------------ */
8566
8567/*
8568 * Affinity Format Parser
8569 *
8570 * Field is in form of: %[[[0].]size]type
8571 * % and type are required (%% means print a literal '%')
8572 * type is either single char or long name surrounded by {},
8573 * e.g., N or {num_threads}
8574 * 0 => leading zeros
8575 * . => right justified when size is specified
8576 * by default output is left justified
8577 * size is the *minimum* field length
8578 * All other characters are printed as is
8579 *
8580 * Available field types:
8581 * L {thread_level} - omp_get_level()
8582 * n {thread_num} - omp_get_thread_num()
8583 * h {host} - name of host machine
8584 * P {process_id} - process id (integer)
8585 * T {thread_identifier} - native thread identifier (integer)
8586 * N {num_threads} - omp_get_num_threads()
8587 * A {ancestor_tnum} - omp_get_ancestor_thread_num(omp_get_level()-1)
8588 * a {thread_affinity} - comma separated list of integers or integer ranges
8589 * (values of affinity mask)
8590 *
8591 * Implementation-specific field types can be added
8592 * If a type is unknown, print "undefined"
8593 */
8594
8595// Structure holding the short name, long name, and corresponding data type
8596// for snprintf. A table of these will represent the entire valid keyword
8597// field types.
8598typedef struct kmp_affinity_format_field_t {
8599 char short_name; // from spec e.g., L -> thread level
8600 const char *long_name; // from spec thread_level -> thread level
8601 char field_format; // data type for snprintf (typically 'd' or 's'
8602 // for integer or string)
8603} kmp_affinity_format_field_t;
8604
8605static const kmp_affinity_format_field_t __kmp_affinity_format_table[] = {
8606#if KMP_AFFINITY_SUPPORTED
8607 {'A', "thread_affinity", 's'},
8608#endif
8609 {'t', "team_num", 'd'},
8610 {'T', "num_teams", 'd'},
8611 {'L', "nesting_level", 'd'},
8612 {'n', "thread_num", 'd'},
8613 {'N', "num_threads", 'd'},
8614 {'a', "ancestor_tnum", 'd'},
8615 {'H', "host", 's'},
8616 {'P', "process_id", 'd'},
8617 {'i', "native_thread_id", 'd'}};
8618
8619// Return the number of characters it takes to hold field
8620static int __kmp_aux_capture_affinity_field(int gtid, const kmp_info_t *th,
8621 const char **ptr,
8622 kmp_str_buf_t *field_buffer) {
8623 int rc, format_index, field_value;
8624 const char *width_left, *width_right;
8625 bool pad_zeros, right_justify, parse_long_name, found_valid_name;
8626 static const int FORMAT_SIZE = 20;
8627 char format[FORMAT_SIZE] = {0};
8628 char absolute_short_name = 0;
8629
8630 KMP_DEBUG_ASSERT(gtid >= 0);
8631 KMP_DEBUG_ASSERT(th);
8632 KMP_DEBUG_ASSERT(**ptr == '%');
8633 KMP_DEBUG_ASSERT(field_buffer);
8634
8635 __kmp_str_buf_clear(field_buffer);
8636
8637 // Skip the initial %
8638 (*ptr)++;
8639
8640 // Check for %% first
8641 if (**ptr == '%') {
8642 __kmp_str_buf_cat(field_buffer, "%", 1);
8643 (*ptr)++; // skip over the second %
8644 return 1;
8645 }
8646
8647 // Parse field modifiers if they are present
8648 pad_zeros = false;
8649 if (**ptr == '0') {
8650 pad_zeros = true;
8651 (*ptr)++; // skip over 0
8652 }
8653 right_justify = false;
8654 if (**ptr == '.') {
8655 right_justify = true;
8656 (*ptr)++; // skip over .
8657 }
8658 // Parse width of field: [width_left, width_right)
8659 width_left = width_right = NULL;
8660 if (**ptr >= '0' && **ptr <= '9') {
8661 width_left = *ptr;
8662 SKIP_DIGITS(*ptr);
8663 width_right = *ptr;
8664 }
8665
8666 // Create the format for KMP_SNPRINTF based on flags parsed above
8667 format_index = 0;
8668 format[format_index++] = '%';
8669 if (!right_justify)
8670 format[format_index++] = '-';
8671 if (pad_zeros)
8672 format[format_index++] = '0';
8673 if (width_left && width_right) {
8674 int i = 0;
8675 // Only allow 8 digit number widths.
8676 // This also prevents overflowing format variable
8677 while (i < 8 && width_left < width_right) {
8678 format[format_index++] = *width_left;
8679 width_left++;
8680 i++;
8681 }
8682 }
8683
8684 // Parse a name (long or short)
8685 // Canonicalize the name into absolute_short_name
8686 found_valid_name = false;
8687 parse_long_name = (**ptr == '{');
8688 if (parse_long_name)
8689 (*ptr)++; // skip initial left brace
8690 for (size_t i = 0; i < sizeof(__kmp_affinity_format_table) /
8691 sizeof(__kmp_affinity_format_table[0]);
8692 ++i) {
8693 char short_name = __kmp_affinity_format_table[i].short_name;
8694 const char *long_name = __kmp_affinity_format_table[i].long_name;
8695 char field_format = __kmp_affinity_format_table[i].field_format;
8696 if (parse_long_name) {
8697 size_t length = KMP_STRLEN(long_name);
8698 if (strncmp(*ptr, long_name, length) == 0) {
8699 found_valid_name = true;
8700 (*ptr) += length; // skip the long name
8701 }
8702 } else if (**ptr == short_name) {
8703 found_valid_name = true;
8704 (*ptr)++; // skip the short name
8705 }
8706 if (found_valid_name) {
8707 format[format_index++] = field_format;
8708 format[format_index++] = '\0';
8709 absolute_short_name = short_name;
8710 break;
8711 }
8712 }
8713 if (parse_long_name) {
8714 if (**ptr != '}') {
8715 absolute_short_name = 0;
8716 } else {
8717 (*ptr)++; // skip over the right brace
8718 }
8719 }
8720
8721 // Attempt to fill the buffer with the requested
8722 // value using snprintf within __kmp_str_buf_print()
8723 switch (absolute_short_name) {
8724 case 't':
8725 rc = __kmp_str_buf_print(field_buffer, format, __kmp_aux_get_team_num());
8726 break;
8727 case 'T':
8728 rc = __kmp_str_buf_print(field_buffer, format, __kmp_aux_get_num_teams());
8729 break;
8730 case 'L':
8731 rc = __kmp_str_buf_print(field_buffer, format, th->th.th_team->t.t_level);
8732 break;
8733 case 'n':
8734 rc = __kmp_str_buf_print(field_buffer, format, __kmp_tid_from_gtid(gtid));
8735 break;
8736 case 'H': {
8737 static const int BUFFER_SIZE = 256;
8738 char buf[BUFFER_SIZE];
8739 __kmp_expand_host_name(buf, BUFFER_SIZE);
8740 rc = __kmp_str_buf_print(field_buffer, format, buf);
8741 } break;
8742 case 'P':
8743 rc = __kmp_str_buf_print(field_buffer, format, getpid());
8744 break;
8745 case 'i':
8746 rc = __kmp_str_buf_print(field_buffer, format, __kmp_gettid());
8747 break;
8748 case 'N':
8749 rc = __kmp_str_buf_print(field_buffer, format, th->th.th_team->t.t_nproc);
8750 break;
8751 case 'a':
8752 field_value =
8753 __kmp_get_ancestor_thread_num(gtid, th->th.th_team->t.t_level - 1);
8754 rc = __kmp_str_buf_print(field_buffer, format, field_value);
8755 break;
8756#if KMP_AFFINITY_SUPPORTED
8757 case 'A': {
8758 if (th->th.th_affin_mask) {
8759 kmp_str_buf_t buf;
8760 __kmp_str_buf_init(&buf);
8761 __kmp_affinity_str_buf_mask(&buf, th->th.th_affin_mask);
8762 rc = __kmp_str_buf_print(field_buffer, format, buf.str);
8763 __kmp_str_buf_free(&buf);
8764 } else {
8765 rc = __kmp_str_buf_print(field_buffer, "%s", "disabled");
8766 }
8767 } break;
8768#endif
8769 default:
8770 // According to spec, If an implementation does not have info for field
8771 // type, then "undefined" is printed
8772 rc = __kmp_str_buf_print(field_buffer, "%s", "undefined");
8773 // Skip the field
8774 if (parse_long_name) {
8775 SKIP_TOKEN(*ptr);
8776 if (**ptr == '}')
8777 (*ptr)++;
8778 } else {
8779 (*ptr)++;
8780 }
8781 }
8782
8783 KMP_ASSERT(format_index <= FORMAT_SIZE);
8784 return rc;
8785}
8786
8787/*
8788 * Return number of characters needed to hold the affinity string
8789 * (not including null byte character)
8790 * The resultant string is printed to buffer, which the caller can then
8791 * handle afterwards
8792 */
8793size_t __kmp_aux_capture_affinity(int gtid, const char *format,
8794 kmp_str_buf_t *buffer) {
8795 const char *parse_ptr;
8796 size_t retval;
8797 const kmp_info_t *th;
8798 kmp_str_buf_t field;
8799
8800 KMP_DEBUG_ASSERT(buffer);
8801 KMP_DEBUG_ASSERT(gtid >= 0);
8802
8803 __kmp_str_buf_init(&field);
8804 __kmp_str_buf_clear(buffer);
8805
8806 th = __kmp_threads[gtid];
8807 retval = 0;
8808
8809 // If format is NULL or zero-length string, then we use
8810 // affinity-format-var ICV
8811 parse_ptr = format;
8812 if (parse_ptr == NULL || *parse_ptr == '\0') {
8813 parse_ptr = __kmp_affinity_format;
8814 }
8815 KMP_DEBUG_ASSERT(parse_ptr);
8816
8817 while (*parse_ptr != '\0') {
8818 // Parse a field
8819 if (*parse_ptr == '%') {
8820 // Put field in the buffer
8821 int rc = __kmp_aux_capture_affinity_field(gtid, th, &parse_ptr, &field);
8822 __kmp_str_buf_catbuf(buffer, &field);
8823 retval += rc;
8824 } else {
8825 // Put literal character in buffer
8826 __kmp_str_buf_cat(buffer, parse_ptr, 1);
8827 retval++;
8828 parse_ptr++;
8829 }
8830 }
8831 __kmp_str_buf_free(&field);
8832 return retval;
8833}
8834
8835// Displays the affinity string to stdout
8836void __kmp_aux_display_affinity(int gtid, const char *format) {
8837 kmp_str_buf_t buf;
8838 __kmp_str_buf_init(&buf);
8839 __kmp_aux_capture_affinity(gtid, format, &buf);
8840 __kmp_fprintf(kmp_out, "%s" KMP_END_OF_LINE, buf.str);
8841 __kmp_str_buf_free(&buf);
8842}
8843
8844/* ------------------------------------------------------------------------ */
8845void __kmp_aux_set_blocktime(int arg, kmp_info_t *thread, int tid) {
8846 int blocktime = arg; /* argument is in microseconds */
8847#if KMP_USE_MONITOR
8848 int bt_intervals;
8849#endif
8850 kmp_int8 bt_set;
8851
8852 __kmp_save_internal_controls(thread);
8853
8854 /* Normalize and set blocktime for the teams */
8855 if (blocktime < KMP_MIN_BLOCKTIME)
8856 blocktime = KMP_MIN_BLOCKTIME;
8857 else if (blocktime > KMP_MAX_BLOCKTIME)
8858 blocktime = KMP_MAX_BLOCKTIME;
8859
8860 set__blocktime_team(thread->th.th_team, tid, blocktime);
8861 set__blocktime_team(thread->th.th_serial_team, 0, blocktime);
8862
8863#if KMP_USE_MONITOR
8864 /* Calculate and set blocktime intervals for the teams */
8865 bt_intervals = KMP_INTERVALS_FROM_BLOCKTIME(blocktime, __kmp_monitor_wakeups);
8866
8867 set__bt_intervals_team(thread->th.th_team, tid, bt_intervals);
8868 set__bt_intervals_team(thread->th.th_serial_team, 0, bt_intervals);
8869#endif
8870
8871 /* Set whether blocktime has been set to "TRUE" */
8872 bt_set = TRUE;
8873
8874 set__bt_set_team(thread->th.th_team, tid, bt_set);
8875 set__bt_set_team(thread->th.th_serial_team, 0, bt_set);
8876#if KMP_USE_MONITOR
8877 KF_TRACE(10, ("kmp_set_blocktime: T#%d(%d:%d), blocktime=%d, "
8878 "bt_intervals=%d, monitor_updates=%d\n",
8879 __kmp_gtid_from_tid(tid, thread->th.th_team),
8880 thread->th.th_team->t.t_id, tid, blocktime, bt_intervals,
8881 __kmp_monitor_wakeups));
8882#else
8883 KF_TRACE(10, ("kmp_set_blocktime: T#%d(%d:%d), blocktime=%d\n",
8884 __kmp_gtid_from_tid(tid, thread->th.th_team),
8885 thread->th.th_team->t.t_id, tid, blocktime));
8886#endif
8887}
8888
8889void __kmp_aux_set_defaults(char const *str, size_t len) {
8890 if (!__kmp_init_serial) {
8891 __kmp_serial_initialize();
8892 }
8893 __kmp_env_initialize(str);
8894
8895 if (__kmp_settings || __kmp_display_env || __kmp_display_env_verbose) {
8896 __kmp_env_print();
8897 }
8898} // __kmp_aux_set_defaults
8899
8900/* ------------------------------------------------------------------------ */
8901/* internal fast reduction routines */
8902
8903PACKED_REDUCTION_METHOD_T
8904__kmp_determine_reduction_method(
8905 ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars, size_t reduce_size,
8906 void *reduce_data, void (*reduce_func)(void *lhs_data, void *rhs_data),
8907 kmp_critical_name *lck) {
8908
8909 // Default reduction method: critical construct ( lck != NULL, like in current
8910 // PAROPT )
8911 // If ( reduce_data!=NULL && reduce_func!=NULL ): the tree-reduction method
8912 // can be selected by RTL
8913 // If loc->flags contains KMP_IDENT_ATOMIC_REDUCE, the atomic reduce method
8914 // can be selected by RTL
8915 // Finally, it's up to OpenMP RTL to make a decision on which method to select
8916 // among generated by PAROPT.
8917
8918 PACKED_REDUCTION_METHOD_T retval;
8919
8920 int team_size;
8921
8922 KMP_DEBUG_ASSERT(lck); // it would be nice to test ( lck != 0 )
8923
8924#define FAST_REDUCTION_ATOMIC_METHOD_GENERATED \
8925 (loc && \
8926 ((loc->flags & (KMP_IDENT_ATOMIC_REDUCE)) == (KMP_IDENT_ATOMIC_REDUCE)))
8927#define FAST_REDUCTION_TREE_METHOD_GENERATED ((reduce_data) && (reduce_func))
8928
8929 retval = critical_reduce_block;
8930
8931 // another choice of getting a team size (with 1 dynamic deference) is slower
8932 team_size = __kmp_get_team_num_threads(global_tid);
8933 if (team_size == 1) {
8934
8935 retval = empty_reduce_block;
8936
8937 } else {
8938
8939 int atomic_available = FAST_REDUCTION_ATOMIC_METHOD_GENERATED;
8940
8941#if KMP_ARCH_X86_64 || KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 || \
8942 KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || \
8943 KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_WASM32 || KMP_ARCH_WASM64 || \
8944 KMP_ARCH_ARM64EC
8945
8946#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
8947 KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_DARWIN || KMP_OS_HAIKU || \
8948 KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_WASI || KMP_OS_AIX
8949
8950 int teamsize_cutoff = 4;
8951
8952#if KMP_MIC_SUPPORTED
8953 if (__kmp_mic_type != non_mic) {
8954 teamsize_cutoff = 8;
8955 }
8956#endif
8957 int tree_available = FAST_REDUCTION_TREE_METHOD_GENERATED;
8958 if (tree_available) {
8959 if (team_size <= teamsize_cutoff) {
8960 if (atomic_available) {
8961 retval = atomic_reduce_block;
8962 }
8963 } else {
8964 retval = TREE_REDUCE_BLOCK_WITH_REDUCTION_BARRIER;
8965 }
8966 } else if (atomic_available) {
8967 retval = atomic_reduce_block;
8968 }
8969#else
8970#error "Unknown or unsupported OS"
8971#endif // KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||
8972 // KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_DARWIN || KMP_OS_HAIKU ||
8973 // KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_WASI || KMP_OS_AIX
8974
8975#elif KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_AARCH || KMP_ARCH_MIPS || \
8976 KMP_ARCH_PPC || KMP_ARCH_AARCH64_32 || KMP_ARCH_SPARC
8977
8978#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
8979 KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_HAIKU || KMP_OS_HURD || \
8980 KMP_OS_SOLARIS || KMP_OS_WASI || KMP_OS_AIX
8981
8982 // basic tuning
8983
8984 if (atomic_available) {
8985 if (num_vars <= 2) { // && ( team_size <= 8 ) due to false-sharing ???
8986 retval = atomic_reduce_block;
8987 }
8988 } // otherwise: use critical section
8989
8990#elif KMP_OS_DARWIN
8991
8992 int tree_available = FAST_REDUCTION_TREE_METHOD_GENERATED;
8993 if (atomic_available && (num_vars <= 3)) {
8994 retval = atomic_reduce_block;
8995 } else if (tree_available) {
8996 if ((reduce_size > (9 * sizeof(kmp_real64))) &&
8997 (reduce_size < (2000 * sizeof(kmp_real64)))) {
8998 retval = TREE_REDUCE_BLOCK_WITH_PLAIN_BARRIER;
8999 }
9000 } // otherwise: use critical section
9001
9002#else
9003#error "Unknown or unsupported OS"
9004#endif
9005
9006#else
9007#error "Unknown or unsupported architecture"
9008#endif
9009 }
9010
9011 // KMP_FORCE_REDUCTION
9012
9013 // If the team is serialized (team_size == 1), ignore the forced reduction
9014 // method and stay with the unsynchronized method (empty_reduce_block)
9015 if (__kmp_force_reduction_method != reduction_method_not_defined &&
9016 team_size != 1) {
9017
9018 PACKED_REDUCTION_METHOD_T forced_retval = critical_reduce_block;
9019
9020 int atomic_available, tree_available;
9021
9022 switch ((forced_retval = __kmp_force_reduction_method)) {
9023 case critical_reduce_block:
9024 KMP_ASSERT(lck); // lck should be != 0
9025 break;
9026
9027 case atomic_reduce_block:
9028 atomic_available = FAST_REDUCTION_ATOMIC_METHOD_GENERATED;
9029 if (!atomic_available) {
9030 KMP_WARNING(RedMethodNotSupported, "atomic");
9031 forced_retval = critical_reduce_block;
9032 }
9033 break;
9034
9035 case tree_reduce_block:
9036 tree_available = FAST_REDUCTION_TREE_METHOD_GENERATED;
9037 if (!tree_available) {
9038 KMP_WARNING(RedMethodNotSupported, "tree");
9039 forced_retval = critical_reduce_block;
9040 } else {
9041#if KMP_FAST_REDUCTION_BARRIER
9042 forced_retval = TREE_REDUCE_BLOCK_WITH_REDUCTION_BARRIER;
9043#endif
9044 }
9045 break;
9046
9047 default:
9048 KMP_ASSERT(0); // "unsupported method specified"
9049 }
9050
9051 retval = forced_retval;
9052 }
9053
9054 KA_TRACE(10, ("reduction method selected=%08x\n", retval));
9055
9056#undef FAST_REDUCTION_TREE_METHOD_GENERATED
9057#undef FAST_REDUCTION_ATOMIC_METHOD_GENERATED
9058
9059 return (retval);
9060}
9061// this function is for testing set/get/determine reduce method
9062kmp_int32 __kmp_get_reduce_method(void) {
9063 return ((__kmp_entry_thread()->th.th_local.packed_reduction_method) >> 8);
9064}
9065
9066// Soft pause sets up threads to ignore blocktime and just go to sleep.
9067// Spin-wait code checks __kmp_pause_status and reacts accordingly.
9068void __kmp_soft_pause() { __kmp_pause_status = kmp_soft_paused; }
9069
9070// Hard pause shuts down the runtime completely. Resume happens naturally when
9071// OpenMP is used subsequently.
9072void __kmp_hard_pause() {
9073 __kmp_pause_status = kmp_hard_paused;
9074 __kmp_internal_end_thread(-1);
9075}
9076
9077// Soft resume sets __kmp_pause_status, and wakes up all threads.
9078void __kmp_resume_if_soft_paused() {
9079 if (__kmp_pause_status == kmp_soft_paused) {
9080 __kmp_pause_status = kmp_not_paused;
9081
9082 for (int gtid = 1; gtid < __kmp_threads_capacity; ++gtid) {
9083 kmp_info_t *thread = __kmp_threads[gtid];
9084 if (thread) { // Wake it if sleeping
9085 kmp_flag_64<> fl(&thread->th.th_bar[bs_forkjoin_barrier].bb.b_go,
9086 thread);
9087 if (fl.is_sleeping())
9088 fl.resume(gtid);
9089 else if (__kmp_try_suspend_mx(thread)) { // got suspend lock
9090 __kmp_unlock_suspend_mx(thread); // unlock it; it won't sleep
9091 } else { // thread holds the lock and may sleep soon
9092 do { // until either the thread sleeps, or we can get the lock
9093 if (fl.is_sleeping()) {
9094 fl.resume(gtid);
9095 break;
9096 } else if (__kmp_try_suspend_mx(thread)) {
9097 __kmp_unlock_suspend_mx(thread);
9098 break;
9099 }
9100 } while (1);
9101 }
9102 }
9103 }
9104 }
9105}
9106
9107// This function is called via __kmpc_pause_resource. Returns 0 if successful.
9108// TODO: add warning messages
9109int __kmp_pause_resource(kmp_pause_status_t level) {
9110 if (level == kmp_not_paused) { // requesting resume
9111 if (__kmp_pause_status == kmp_not_paused) {
9112 // error message about runtime not being paused, so can't resume
9113 return 1;
9114 } else {
9115 KMP_DEBUG_ASSERT(__kmp_pause_status == kmp_soft_paused ||
9116 __kmp_pause_status == kmp_hard_paused);
9117 __kmp_pause_status = kmp_not_paused;
9118 return 0;
9119 }
9120 } else if (level == kmp_soft_paused) { // requesting soft pause
9121 if (__kmp_pause_status != kmp_not_paused) {
9122 // error message about already being paused
9123 return 1;
9124 } else {
9125 __kmp_soft_pause();
9126 return 0;
9127 }
9128 } else if (level == kmp_hard_paused || level == kmp_stop_tool_paused) {
9129 // requesting hard pause or stop_tool pause
9130 if (__kmp_pause_status != kmp_not_paused) {
9131 // error message about already being paused
9132 return 1;
9133 } else {
9134 __kmp_hard_pause();
9135 return 0;
9136 }
9137 } else {
9138 // error message about invalid level
9139 return 1;
9140 }
9141}
9142
9143void __kmp_omp_display_env(int verbose) {
9144 __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
9145 if (__kmp_init_serial == 0)
9146 __kmp_do_serial_initialize();
9147 __kmp_display_env_impl(!verbose, verbose);
9148 __kmp_release_bootstrap_lock(&__kmp_initz_lock);
9149}
9150
9151// The team size is changing, so distributed barrier must be modified
9152void __kmp_resize_dist_barrier(kmp_team_t *team, int old_nthreads,
9153 int new_nthreads) {
9154 KMP_DEBUG_ASSERT(__kmp_barrier_release_pattern[bs_forkjoin_barrier] ==
9155 bp_dist_bar);
9156 kmp_info_t **other_threads = team->t.t_threads;
9157
9158 // We want all the workers to stop waiting on the barrier while we adjust the
9159 // size of the team.
9160 for (int f = 1; f < old_nthreads; ++f) {
9161 KMP_DEBUG_ASSERT(other_threads[f] != NULL);
9162 // Ignore threads that are already inactive or not present in the team
9163 if (team->t.t_threads[f]->th.th_used_in_team.load() == 0) {
9164 // teams construct causes thread_limit to get passed in, and some of
9165 // those could be inactive; just ignore them
9166 continue;
9167 }
9168 // If thread is transitioning still to in_use state, wait for it
9169 if (team->t.t_threads[f]->th.th_used_in_team.load() == 3) {
9170 while (team->t.t_threads[f]->th.th_used_in_team.load() == 3)
9171 KMP_CPU_PAUSE();
9172 }
9173 // The thread should be in_use now
9174 KMP_DEBUG_ASSERT(team->t.t_threads[f]->th.th_used_in_team.load() == 1);
9175 // Transition to unused state
9176 team->t.t_threads[f]->th.th_used_in_team.store(2);
9177 KMP_DEBUG_ASSERT(team->t.t_threads[f]->th.th_used_in_team.load() == 2);
9178 }
9179 // Release all the workers
9180 team->t.b->go_release();
9181
9182 KMP_MFENCE();
9183
9184 // Workers should see transition status 2 and move to 0; but may need to be
9185 // woken up first
9186 int count = old_nthreads - 1;
9187 while (count > 0) {
9188 count = old_nthreads - 1;
9189 for (int f = 1; f < old_nthreads; ++f) {
9190 if (other_threads[f]->th.th_used_in_team.load() != 0) {
9191 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) { // Wake up the workers
9192 kmp_atomic_flag_64<> *flag = (kmp_atomic_flag_64<> *)CCAST(
9193 void *, other_threads[f]->th.th_sleep_loc);
9194 __kmp_atomic_resume_64(other_threads[f]->th.th_info.ds.ds_gtid, flag);
9195 }
9196 } else {
9197 KMP_DEBUG_ASSERT(team->t.t_threads[f]->th.th_used_in_team.load() == 0);
9198 count--;
9199 }
9200 }
9201 }
9202 // Now update the barrier size
9203 team->t.b->update_num_threads(new_nthreads);
9204 team->t.b->go_reset();
9205}
9206
9207void __kmp_add_threads_to_team(kmp_team_t *team, int new_nthreads) {
9208 // Add the threads back to the team
9209 KMP_DEBUG_ASSERT(team);
9210 // Threads were paused and pointed at th_used_in_team temporarily during a
9211 // resize of the team. We're going to set th_used_in_team to 3 to indicate to
9212 // the thread that it should transition itself back into the team. Then, if
9213 // blocktime isn't infinite, the thread could be sleeping, so we send a resume
9214 // to wake it up.
9215 for (int f = 1; f < new_nthreads; ++f) {
9216 KMP_DEBUG_ASSERT(team->t.t_threads[f]);
9217 (void)KMP_COMPARE_AND_STORE_ACQ32(
9218 &(team->t.t_threads[f]->th.th_used_in_team), 0, 3);
9219 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) { // Wake up sleeping threads
9220 __kmp_resume_32(team->t.t_threads[f]->th.th_info.ds.ds_gtid,
9221 (kmp_flag_32<false, false> *)NULL);
9222 }
9223 }
9224 // The threads should be transitioning to the team; when they are done, they
9225 // should have set th_used_in_team to 1. This loop forces master to wait until
9226 // all threads have moved into the team and are waiting in the barrier.
9227 int count = new_nthreads - 1;
9228 while (count > 0) {
9229 count = new_nthreads - 1;
9230 for (int f = 1; f < new_nthreads; ++f) {
9231 if (team->t.t_threads[f]->th.th_used_in_team.load() == 1) {
9232 count--;
9233 }
9234 }
9235 }
9236}
9237
9238// Globals and functions for hidden helper task
9239kmp_info_t **__kmp_hidden_helper_threads;
9240kmp_info_t *__kmp_hidden_helper_main_thread;
9241std::atomic<kmp_int32> __kmp_unexecuted_hidden_helper_tasks;
9242#if KMP_OS_LINUX
9243kmp_int32 __kmp_hidden_helper_threads_num = 8;
9244kmp_int32 __kmp_enable_hidden_helper = TRUE;
9245#else
9246kmp_int32 __kmp_hidden_helper_threads_num = 0;
9247kmp_int32 __kmp_enable_hidden_helper = FALSE;
9248#endif
9249
9250namespace {
9251std::atomic<kmp_int32> __kmp_hit_hidden_helper_threads_num;
9252
9253void __kmp_hidden_helper_wrapper_fn(int *gtid, int *, ...) {
9254 // This is an explicit synchronization on all hidden helper threads in case
9255 // that when a regular thread pushes a hidden helper task to one hidden
9256 // helper thread, the thread has not been awaken once since they're released
9257 // by the main thread after creating the team.
9258 KMP_ATOMIC_INC(&__kmp_hit_hidden_helper_threads_num);
9259 while (KMP_ATOMIC_LD_ACQ(&__kmp_hit_hidden_helper_threads_num) !=
9260 __kmp_hidden_helper_threads_num)
9261 ;
9262
9263 // If main thread, then wait for signal
9264 if (__kmpc_master(nullptr, *gtid)) {
9265 // First, unset the initial state and release the initial thread
9266 TCW_4(__kmp_init_hidden_helper_threads, FALSE);
9267 __kmp_hidden_helper_initz_release();
9268 __kmp_hidden_helper_main_thread_wait();
9269 // Now wake up all worker threads
9270 for (int i = 1; i < __kmp_hit_hidden_helper_threads_num; ++i) {
9271 __kmp_hidden_helper_worker_thread_signal();
9272 }
9273 }
9274}
9275} // namespace
9276
9277void __kmp_hidden_helper_threads_initz_routine() {
9278 // Create a new root for hidden helper team/threads
9279 const int gtid = __kmp_register_root(TRUE);
9280 __kmp_hidden_helper_main_thread = __kmp_threads[gtid];
9281 __kmp_hidden_helper_threads = &__kmp_threads[gtid];
9282 __kmp_hidden_helper_main_thread->th.th_set_nproc =
9283 __kmp_hidden_helper_threads_num;
9284
9285 KMP_ATOMIC_ST_REL(&__kmp_hit_hidden_helper_threads_num, 0);
9286
9287 __kmpc_fork_call(nullptr, 0, __kmp_hidden_helper_wrapper_fn);
9288
9289 // Set the initialization flag to FALSE
9290 TCW_SYNC_4(__kmp_init_hidden_helper, FALSE);
9291
9292 __kmp_hidden_helper_threads_deinitz_release();
9293}
9294
9295/* Nesting Mode:
9296 Set via KMP_NESTING_MODE, which takes an integer.
9297 Note: we skip duplicate topology levels, and skip levels with only
9298 one entity.
9299 KMP_NESTING_MODE=0 is the default, and doesn't use nesting mode.
9300 KMP_NESTING_MODE=1 sets as many nesting levels as there are distinct levels
9301 in the topology, and initializes the number of threads at each of those
9302 levels to the number of entities at each level, respectively, below the
9303 entity at the parent level.
9304 KMP_NESTING_MODE=N, where N>1, attempts to create up to N nesting levels,
9305 but starts with nesting OFF -- max-active-levels-var is 1 -- and requires
9306 the user to turn nesting on explicitly. This is an even more experimental
9307 option to this experimental feature, and may change or go away in the
9308 future.
9309*/
9310
9311// Allocate space to store nesting levels
9312void __kmp_init_nesting_mode() {
9313 int levels = KMP_HW_LAST;
9314 __kmp_nesting_mode_nlevels = levels;
9315 __kmp_nesting_nth_level = (int *)KMP_INTERNAL_MALLOC(levels * sizeof(int));
9316 for (int i = 0; i < levels; ++i)
9317 __kmp_nesting_nth_level[i] = 0;
9318 if (__kmp_nested_nth.size < levels) {
9319 __kmp_nested_nth.nth =
9320 (int *)KMP_INTERNAL_REALLOC(__kmp_nested_nth.nth, levels * sizeof(int));
9321 __kmp_nested_nth.size = levels;
9322 }
9323}
9324
9325// Set # threads for top levels of nesting; must be called after topology set
9326void __kmp_set_nesting_mode_threads() {
9327 kmp_info_t *thread = __kmp_threads[__kmp_entry_gtid()];
9328
9329 if (__kmp_nesting_mode == 1)
9330 __kmp_nesting_mode_nlevels = KMP_MAX_ACTIVE_LEVELS_LIMIT;
9331 else if (__kmp_nesting_mode > 1)
9332 __kmp_nesting_mode_nlevels = __kmp_nesting_mode;
9333
9334 if (__kmp_topology) { // use topology info
9335 int loc, hw_level;
9336 for (loc = 0, hw_level = 0; hw_level < __kmp_topology->get_depth() &&
9337 loc < __kmp_nesting_mode_nlevels;
9338 loc++, hw_level++) {
9339 __kmp_nesting_nth_level[loc] = __kmp_topology->get_ratio(hw_level);
9340 if (__kmp_nesting_nth_level[loc] == 1)
9341 loc--;
9342 }
9343 // Make sure all cores are used
9344 if (__kmp_nesting_mode > 1 && loc > 1) {
9345 int core_level = __kmp_topology->get_level(KMP_HW_CORE);
9346 int num_cores = __kmp_topology->get_count(core_level);
9347 int upper_levels = 1;
9348 for (int level = 0; level < loc - 1; ++level)
9349 upper_levels *= __kmp_nesting_nth_level[level];
9350 if (upper_levels * __kmp_nesting_nth_level[loc - 1] < num_cores)
9351 __kmp_nesting_nth_level[loc - 1] =
9352 num_cores / __kmp_nesting_nth_level[loc - 2];
9353 }
9354 __kmp_nesting_mode_nlevels = loc;
9355 __kmp_nested_nth.used = __kmp_nesting_mode_nlevels;
9356 } else { // no topology info available; provide a reasonable guesstimation
9357 if (__kmp_avail_proc >= 4) {
9358 __kmp_nesting_nth_level[0] = __kmp_avail_proc / 2;
9359 __kmp_nesting_nth_level[1] = 2;
9360 __kmp_nesting_mode_nlevels = 2;
9361 } else {
9362 __kmp_nesting_nth_level[0] = __kmp_avail_proc;
9363 __kmp_nesting_mode_nlevels = 1;
9364 }
9365 __kmp_nested_nth.used = __kmp_nesting_mode_nlevels;
9366 }
9367 for (int i = 0; i < __kmp_nesting_mode_nlevels; ++i) {
9368 __kmp_nested_nth.nth[i] = __kmp_nesting_nth_level[i];
9369 }
9370 set__nproc(thread, __kmp_nesting_nth_level[0]);
9371 if (__kmp_nesting_mode > 1 && __kmp_nesting_mode_nlevels > __kmp_nesting_mode)
9372 __kmp_nesting_mode_nlevels = __kmp_nesting_mode;
9373 if (get__max_active_levels(thread) > 1) {
9374 // if max levels was set, set nesting mode levels to same
9375 __kmp_nesting_mode_nlevels = get__max_active_levels(thread);
9376 }
9377 if (__kmp_nesting_mode == 1) // turn on nesting for this case only
9378 set__max_active_levels(thread, __kmp_nesting_mode_nlevels);
9379}
9380
9381#if ENABLE_LIBOMPTARGET
9382void (*kmp_target_sync_cb)(ident_t *loc_ref, int gtid, void *current_task,
9383 void *event) = NULL;
9384void __kmp_target_init() {
9385 // Look for hooks in the libomptarget library
9386 *(void **)(&kmp_target_sync_cb) = KMP_DLSYM("__tgt_target_sync");
9387}
9388#endif // ENABLE_LIBOMPTARGET
9389
9390// Empty symbols to export (see exports_so.txt) when feature is disabled
9391extern "C" {
9392#if !KMP_STATS_ENABLED
9393void __kmp_reset_stats() {}
9394#endif
9395#if !USE_DEBUGGER
9396int __kmp_omp_debug_struct_info = FALSE;
9397int __kmp_debugging = FALSE;
9398#endif
9399#if !USE_ITT_BUILD || !USE_ITT_NOTIFY
9400void __kmp_itt_fini_ittlib() {}
9401void __kmp_itt_init_ittlib() {}
9402#endif
9403}
9404
9405// end of file
@ KMP_IDENT_AUTOPAR
Definition: kmp.h:182
KMP_EXPORT void __kmpc_serialized_parallel(ident_t *, kmp_int32 global_tid)
KMP_EXPORT void __kmpc_fork_call(ident_t *, kmp_int32 nargs, kmpc_micro microtask,...)
KMP_EXPORT void __kmpc_end_serialized_parallel(ident_t *, kmp_int32 global_tid)
#define KMP_INIT_PARTITIONED_TIMERS(name)
Initializes the partitioned timers to begin with name.
Definition: kmp_stats.h:940
#define KMP_COUNT_VALUE(name, value)
Adds value to specified timer (name).
Definition: kmp_stats.h:898
stats_state_e
the states which a thread can be in
Definition: kmp_stats.h:63
sched_type
Definition: kmp.h:340
KMP_EXPORT kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid)
@ kmp_sch_auto
Definition: kmp.h:347
@ kmp_sch_static
Definition: kmp.h:343
@ kmp_sch_guided_chunked
Definition: kmp.h:345
Definition: kmp.h:217
kmp_int32 flags
Definition: kmp.h:219