Changeset View
Changeset View
Standalone View
Standalone View
runtime/src/kmp_runtime.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 1,086 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
} | } | ||||
#if OMP_40_ENABLED && KMP_AFFINITY_SUPPORTED | #if OMP_40_ENABLED && KMP_AFFINITY_SUPPORTED | ||||
__kmp_partition_places(team); | __kmp_partition_places(team); | ||||
#endif | #endif | ||||
} | } | ||||
#if OMP_50_ENABLED | |||||
if (__kmp_display_affinity && team->t.t_display_affinity != 1) { | |||||
for (i = 0; i < team->t.t_nproc; i++) { | |||||
kmp_info_t *thr = team->t.t_threads[i]; | |||||
if (thr->th.th_prev_num_threads != team->t.t_nproc || | |||||
thr->th.th_prev_level != team->t.t_level) { | |||||
team->t.t_display_affinity = 1; | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
#endif | |||||
KMP_MB(); | KMP_MB(); | ||||
} | } | ||||
#if KMP_ARCH_X86 || KMP_ARCH_X86_64 | #if KMP_ARCH_X86 || KMP_ARCH_X86_64 | ||||
// Propagate any changes to the floating point control registers out to the team | // Propagate any changes to the floating point control registers out to the team | ||||
// We try to avoid unnecessary writes to the relevant cache line in the team | // We try to avoid unnecessary writes to the relevant cache line in the team | ||||
// structure, so we don't make changes unless they are needed. | // structure, so we don't make changes unless they are needed. | ||||
inline static void propagateFPControl(kmp_team_t *team) { | inline static void propagateFPControl(kmp_team_t *team) { | ||||
▲ Show 20 Lines • Show All 274 Lines • ▼ Show 20 Lines | #endif | ||||
this_thr->th.th_dispatch = serial_team->t.t_dispatch; | this_thr->th.th_dispatch = serial_team->t.t_dispatch; | ||||
KMP_MB(); | KMP_MB(); | ||||
} | } | ||||
#if OMP_40_ENABLED | #if OMP_40_ENABLED | ||||
KMP_CHECK_UPDATE(serial_team->t.t_cancel_request, cancel_noreq); | KMP_CHECK_UPDATE(serial_team->t.t_cancel_request, cancel_noreq); | ||||
#endif | #endif | ||||
#if OMP_50_ENABLED | |||||
// Perform the display affinity functionality for | |||||
// serialized parallel regions | |||||
if (__kmp_display_affinity) { | |||||
if (this_thr->th.th_prev_level != serial_team->t.t_level || | |||||
this_thr->th.th_prev_num_threads != 1) { | |||||
// NULL means use the affinity-format-var ICV | |||||
__kmp_aux_display_affinity(global_tid, NULL); | |||||
this_thr->th.th_prev_level = serial_team->t.t_level; | |||||
this_thr->th.th_prev_num_threads = 1; | |||||
} | |||||
} | |||||
#endif | |||||
if (__kmp_env_consistency_check) | if (__kmp_env_consistency_check) | ||||
__kmp_push_parallel(global_tid, NULL); | __kmp_push_parallel(global_tid, NULL); | ||||
#if OMPT_SUPPORT | #if OMPT_SUPPORT | ||||
serial_team->t.ompt_team_info.master_return_address = codeptr; | serial_team->t.ompt_team_info.master_return_address = codeptr; | ||||
if (ompt_enabled.enabled && | if (ompt_enabled.enabled && | ||||
this_thr->th.ompt_thread_info.state != omp_state_overhead) { | this_thr->th.ompt_thread_info.state != omp_state_overhead) { | ||||
OMPT_CUR_TASK_INFO(this_thr)->frame.exit_frame = OMPT_GET_FRAME_ADDRESS(1); | OMPT_CUR_TASK_INFO(this_thr)->frame.exit_frame = OMPT_GET_FRAME_ADDRESS(1); | ||||
▲ Show 20 Lines • Show All 550 Lines • ▼ Show 20 Lines | #endif | ||||
} else { | } else { | ||||
KMP_ASSERT2(call_context < fork_context_last, | KMP_ASSERT2(call_context < fork_context_last, | ||||
"__kmp_fork_call: unknown fork_context parameter"); | "__kmp_fork_call: unknown fork_context parameter"); | ||||
} | } | ||||
KA_TRACE(20, ("__kmp_fork_call: T#%d serial exit\n", gtid)); | KA_TRACE(20, ("__kmp_fork_call: T#%d serial exit\n", gtid)); | ||||
KMP_MB(); | KMP_MB(); | ||||
return FALSE; | return FALSE; | ||||
} | } // if (nthreads == 1) | ||||
// GEH: only modify the executing flag in the case when not serialized | // GEH: only modify the executing flag in the case when not serialized | ||||
// serialized case is handled in kmpc_serialized_parallel | // serialized case is handled in kmpc_serialized_parallel | ||||
KF_TRACE(10, ("__kmp_fork_call: parent_team_aclevel=%d, master_th=%p, " | KF_TRACE(10, ("__kmp_fork_call: parent_team_aclevel=%d, master_th=%p, " | ||||
"curtask=%p, curtask_max_aclevel=%d\n", | "curtask=%p, curtask_max_aclevel=%d\n", | ||||
parent_team->t.t_active_level, master_th, | parent_team->t.t_active_level, master_th, | ||||
master_th->th.th_current_task, | master_th->th.th_current_task, | ||||
master_th->th.th_current_task->td_icvs.max_active_levels)); | master_th->th.th_current_task->td_icvs.max_active_levels)); | ||||
▲ Show 20 Lines • Show All 1,854 Lines • ▼ Show 20 Lines | #if OMP_40_ENABLED | ||||
root_thread->th.th_last_place = KMP_PLACE_UNDEFINED; | root_thread->th.th_last_place = KMP_PLACE_UNDEFINED; | ||||
#endif | #endif | ||||
if (TCR_4(__kmp_init_middle)) { | if (TCR_4(__kmp_init_middle)) { | ||||
__kmp_affinity_set_init_mask(gtid, TRUE); | __kmp_affinity_set_init_mask(gtid, TRUE); | ||||
} | } | ||||
#endif /* KMP_AFFINITY_SUPPORTED */ | #endif /* KMP_AFFINITY_SUPPORTED */ | ||||
#if OMP_50_ENABLED | #if OMP_50_ENABLED | ||||
root_thread->th.th_def_allocator = __kmp_def_allocator; | root_thread->th.th_def_allocator = __kmp_def_allocator; | ||||
root_thread->th.th_prev_level = 0; | |||||
root_thread->th.th_prev_num_threads = 1; | |||||
#endif | #endif | ||||
__kmp_root_counter++; | __kmp_root_counter++; | ||||
#if OMPT_SUPPORT | #if OMPT_SUPPORT | ||||
if (!initial_thread && ompt_enabled.enabled) { | if (!initial_thread && ompt_enabled.enabled) { | ||||
kmp_info_t *root_thread = ompt_get_thread(); | kmp_info_t *root_thread = ompt_get_thread(); | ||||
▲ Show 20 Lines • Show All 525 Lines • ▼ Show 20 Lines | |||||
#if OMP_40_ENABLED && KMP_AFFINITY_SUPPORTED | #if OMP_40_ENABLED && KMP_AFFINITY_SUPPORTED | ||||
new_thr->th.th_current_place = KMP_PLACE_UNDEFINED; | new_thr->th.th_current_place = KMP_PLACE_UNDEFINED; | ||||
new_thr->th.th_new_place = KMP_PLACE_UNDEFINED; | new_thr->th.th_new_place = KMP_PLACE_UNDEFINED; | ||||
new_thr->th.th_first_place = KMP_PLACE_UNDEFINED; | new_thr->th.th_first_place = KMP_PLACE_UNDEFINED; | ||||
new_thr->th.th_last_place = KMP_PLACE_UNDEFINED; | new_thr->th.th_last_place = KMP_PLACE_UNDEFINED; | ||||
#endif | #endif | ||||
#if OMP_50_ENABLED | #if OMP_50_ENABLED | ||||
new_thr->th.th_def_allocator = __kmp_def_allocator; | new_thr->th.th_def_allocator = __kmp_def_allocator; | ||||
new_thr->th.th_prev_level = 0; | |||||
new_thr->th.th_prev_num_threads = 1; | |||||
#endif | #endif | ||||
TCW_4(new_thr->th.th_in_pool, FALSE); | TCW_4(new_thr->th.th_in_pool, FALSE); | ||||
new_thr->th.th_active_in_pool = FALSE; | new_thr->th.th_active_in_pool = FALSE; | ||||
TCW_4(new_thr->th.th_active, TRUE); | TCW_4(new_thr->th.th_active, TRUE); | ||||
/* adjust the global counters */ | /* adjust the global counters */ | ||||
__kmp_all_nth++; | __kmp_all_nth++; | ||||
▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | case proc_bind_master: { | ||||
int f; | int f; | ||||
int n_th = team->t.t_nproc; | int n_th = team->t.t_nproc; | ||||
for (f = 1; f < n_th; f++) { | for (f = 1; f < n_th; f++) { | ||||
kmp_info_t *th = team->t.t_threads[f]; | kmp_info_t *th = team->t.t_threads[f]; | ||||
KMP_DEBUG_ASSERT(th != NULL); | KMP_DEBUG_ASSERT(th != NULL); | ||||
th->th.th_first_place = first_place; | th->th.th_first_place = first_place; | ||||
th->th.th_last_place = last_place; | th->th.th_last_place = last_place; | ||||
th->th.th_new_place = masters_place; | th->th.th_new_place = masters_place; | ||||
#if OMP_50_ENABLED | |||||
if (__kmp_display_affinity && masters_place != th->th.th_current_place && | |||||
team->t.t_display_affinity != 1) { | |||||
team->t.t_display_affinity = 1; | |||||
} | |||||
#endif | |||||
KA_TRACE(100, ("__kmp_partition_places: master: T#%d(%d:%d) place %d " | KA_TRACE(100, ("__kmp_partition_places: master: T#%d(%d:%d) place %d " | ||||
"partition = [%d,%d]\n", | "partition = [%d,%d]\n", | ||||
__kmp_gtid_from_thread(team->t.t_threads[f]), team->t.t_id, | __kmp_gtid_from_thread(team->t.t_threads[f]), team->t.t_id, | ||||
f, masters_place, first_place, last_place)); | f, masters_place, first_place, last_place)); | ||||
} | } | ||||
} break; | } break; | ||||
Show All 17 Lines | if (n_th <= n_places) { | ||||
} else if (place == (int)(__kmp_affinity_num_masks - 1)) { | } else if (place == (int)(__kmp_affinity_num_masks - 1)) { | ||||
place = 0; | place = 0; | ||||
} else { | } else { | ||||
place++; | place++; | ||||
} | } | ||||
th->th.th_first_place = first_place; | th->th.th_first_place = first_place; | ||||
th->th.th_last_place = last_place; | th->th.th_last_place = last_place; | ||||
th->th.th_new_place = place; | th->th.th_new_place = place; | ||||
#if OMP_50_ENABLED | |||||
if (__kmp_display_affinity && place != th->th.th_current_place && | |||||
team->t.t_display_affinity != 1) { | |||||
team->t.t_display_affinity = 1; | |||||
} | |||||
#endif | |||||
KA_TRACE(100, ("__kmp_partition_places: close: T#%d(%d:%d) place %d " | KA_TRACE(100, ("__kmp_partition_places: close: T#%d(%d:%d) place %d " | ||||
"partition = [%d,%d]\n", | "partition = [%d,%d]\n", | ||||
__kmp_gtid_from_thread(team->t.t_threads[f]), | __kmp_gtid_from_thread(team->t.t_threads[f]), | ||||
team->t.t_id, f, place, first_place, last_place)); | team->t.t_id, f, place, first_place, last_place)); | ||||
} | } | ||||
} else { | } else { | ||||
int S, rem, gap, s_count; | int S, rem, gap, s_count; | ||||
S = n_th / n_places; | S = n_th / n_places; | ||||
s_count = 0; | s_count = 0; | ||||
rem = n_th - (S * n_places); | rem = n_th - (S * n_places); | ||||
gap = rem > 0 ? n_places / rem : n_places; | gap = rem > 0 ? n_places / rem : n_places; | ||||
int place = masters_place; | int place = masters_place; | ||||
int gap_ct = gap; | int gap_ct = gap; | ||||
for (f = 0; f < n_th; f++) { | for (f = 0; f < n_th; f++) { | ||||
kmp_info_t *th = team->t.t_threads[f]; | kmp_info_t *th = team->t.t_threads[f]; | ||||
KMP_DEBUG_ASSERT(th != NULL); | KMP_DEBUG_ASSERT(th != NULL); | ||||
th->th.th_first_place = first_place; | th->th.th_first_place = first_place; | ||||
th->th.th_last_place = last_place; | th->th.th_last_place = last_place; | ||||
th->th.th_new_place = place; | th->th.th_new_place = place; | ||||
#if OMP_50_ENABLED | |||||
if (__kmp_display_affinity && place != th->th.th_current_place && | |||||
team->t.t_display_affinity != 1) { | |||||
team->t.t_display_affinity = 1; | |||||
} | |||||
#endif | |||||
s_count++; | s_count++; | ||||
if ((s_count == S) && rem && (gap_ct == gap)) { | if ((s_count == S) && rem && (gap_ct == gap)) { | ||||
// do nothing, add an extra thread to place on next iteration | // do nothing, add an extra thread to place on next iteration | ||||
} else if ((s_count == S + 1) && rem && (gap_ct == gap)) { | } else if ((s_count == S + 1) && rem && (gap_ct == gap)) { | ||||
// we added an extra thread to this place; move to next place | // we added an extra thread to this place; move to next place | ||||
if (place == last_place) { | if (place == last_place) { | ||||
place = first_place; | place = first_place; | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | if (n_th <= n_places) { | ||||
if (update_master_only == 1) | if (update_master_only == 1) | ||||
thidx = 1; | thidx = 1; | ||||
for (f = 0; f < thidx; f++) { | for (f = 0; f < thidx; f++) { | ||||
kmp_info_t *th = team->t.t_threads[f]; | kmp_info_t *th = team->t.t_threads[f]; | ||||
KMP_DEBUG_ASSERT(th != NULL); | KMP_DEBUG_ASSERT(th != NULL); | ||||
th->th.th_first_place = place; | th->th.th_first_place = place; | ||||
th->th.th_new_place = place; | th->th.th_new_place = place; | ||||
#if OMP_50_ENABLED | |||||
if (__kmp_display_affinity && place != th->th.th_current_place && | |||||
team->t.t_display_affinity != 1) { | |||||
team->t.t_display_affinity = 1; | |||||
} | |||||
#endif | |||||
s_count = 1; | s_count = 1; | ||||
while (s_count < S) { | while (s_count < S) { | ||||
if (place == last_place) { | if (place == last_place) { | ||||
place = first_place; | place = first_place; | ||||
} else if (place == (int)(__kmp_affinity_num_masks - 1)) { | } else if (place == (int)(__kmp_affinity_num_masks - 1)) { | ||||
place = 0; | place = 0; | ||||
} else { | } else { | ||||
place++; | place++; | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | #endif | ||||
KMP_DEBUG_ASSERT(0 <= last); | KMP_DEBUG_ASSERT(0 <= last); | ||||
KMP_DEBUG_ASSERT(n_places > last); | KMP_DEBUG_ASSERT(n_places > last); | ||||
KMP_DEBUG_ASSERT(last_place >= first_place); | KMP_DEBUG_ASSERT(last_place >= first_place); | ||||
th = team->t.t_threads[f]; | th = team->t.t_threads[f]; | ||||
KMP_DEBUG_ASSERT(th); | KMP_DEBUG_ASSERT(th); | ||||
th->th.th_first_place = first; | th->th.th_first_place = first; | ||||
th->th.th_new_place = place; | th->th.th_new_place = place; | ||||
th->th.th_last_place = last; | th->th.th_last_place = last; | ||||
#if OMP_50_ENABLED | |||||
if (__kmp_display_affinity && place != th->th.th_current_place && | |||||
team->t.t_display_affinity != 1) { | |||||
team->t.t_display_affinity = 1; | |||||
} | |||||
#endif | |||||
KA_TRACE(100, | KA_TRACE(100, | ||||
("__kmp_partition_places: spread: T#%d(%d:%d) place %d " | ("__kmp_partition_places: spread: T#%d(%d:%d) place %d " | ||||
"partition = [%d,%d], spacing = %.4f\n", | "partition = [%d,%d], spacing = %.4f\n", | ||||
__kmp_gtid_from_thread(team->t.t_threads[f]), | __kmp_gtid_from_thread(team->t.t_threads[f]), | ||||
team->t.t_id, f, th->th.th_new_place, | team->t.t_id, f, th->th.th_new_place, | ||||
th->th.th_first_place, th->th.th_last_place, spacing)); | th->th.th_first_place, th->th.th_last_place, spacing)); | ||||
} | } | ||||
} | } | ||||
Show All 12 Lines | #endif | ||||
thidx = 1; | thidx = 1; | ||||
for (f = 0; f < thidx; f++) { | for (f = 0; f < thidx; f++) { | ||||
kmp_info_t *th = team->t.t_threads[f]; | kmp_info_t *th = team->t.t_threads[f]; | ||||
KMP_DEBUG_ASSERT(th != NULL); | KMP_DEBUG_ASSERT(th != NULL); | ||||
th->th.th_first_place = place; | th->th.th_first_place = place; | ||||
th->th.th_last_place = place; | th->th.th_last_place = place; | ||||
th->th.th_new_place = place; | th->th.th_new_place = place; | ||||
#if OMP_50_ENABLED | |||||
if (__kmp_display_affinity && place != th->th.th_current_place && | |||||
team->t.t_display_affinity != 1) { | |||||
team->t.t_display_affinity = 1; | |||||
} | |||||
#endif | |||||
s_count++; | s_count++; | ||||
if ((s_count == S) && rem && (gap_ct == gap)) { | if ((s_count == S) && rem && (gap_ct == gap)) { | ||||
// do nothing, add an extra thread to place on next iteration | // do nothing, add an extra thread to place on next iteration | ||||
} else if ((s_count == S + 1) && rem && (gap_ct == gap)) { | } else if ((s_count == S + 1) && rem && (gap_ct == gap)) { | ||||
// we added an extra thread to this place; move on to next place | // we added an extra thread to this place; move on to next place | ||||
if (place == last_place) { | if (place == last_place) { | ||||
place = first_place; | place = first_place; | ||||
▲ Show 20 Lines • Show All 2,604 Lines • ▼ Show 20 Lines | #endif | ||||
KMP_INTERNAL_FREE(__kmp_nested_nth.nth); | KMP_INTERNAL_FREE(__kmp_nested_nth.nth); | ||||
__kmp_nested_nth.nth = NULL; | __kmp_nested_nth.nth = NULL; | ||||
__kmp_nested_nth.size = 0; | __kmp_nested_nth.size = 0; | ||||
__kmp_nested_nth.used = 0; | __kmp_nested_nth.used = 0; | ||||
KMP_INTERNAL_FREE(__kmp_nested_proc_bind.bind_types); | KMP_INTERNAL_FREE(__kmp_nested_proc_bind.bind_types); | ||||
__kmp_nested_proc_bind.bind_types = NULL; | __kmp_nested_proc_bind.bind_types = NULL; | ||||
__kmp_nested_proc_bind.size = 0; | __kmp_nested_proc_bind.size = 0; | ||||
__kmp_nested_proc_bind.used = 0; | __kmp_nested_proc_bind.used = 0; | ||||
#if OMP_50_ENABLED | |||||
if (__kmp_affinity_format) { | |||||
KMP_INTERNAL_FREE(__kmp_affinity_format); | |||||
__kmp_affinity_format = NULL; | |||||
} | |||||
#endif | |||||
__kmp_i18n_catclose(); | __kmp_i18n_catclose(); | ||||
#if KMP_USE_HIER_SCHED | #if KMP_USE_HIER_SCHED | ||||
__kmp_hier_scheds.deallocate(); | __kmp_hier_scheds.deallocate(); | ||||
#endif | #endif | ||||
#if KMP_STATS_ENABLED | #if KMP_STATS_ENABLED | ||||
▲ Show 20 Lines • Show All 140 Lines • ▼ Show 20 Lines | void __kmp_aux_set_library(enum library_type arg) { | ||||
case library_throughput: | case library_throughput: | ||||
(void)__kmp_change_library(FALSE); | (void)__kmp_change_library(FALSE); | ||||
break; | break; | ||||
default: | default: | ||||
KMP_FATAL(UnknownLibraryType, arg); | KMP_FATAL(UnknownLibraryType, arg); | ||||
} | } | ||||
} | } | ||||
/* Getting team information common for all team API */ | |||||
// Returns NULL if not in teams construct | |||||
static kmp_team_t *__kmp_aux_get_team_info(int &teams_serialized) { | |||||
kmp_info_t *thr = __kmp_entry_thread(); | |||||
teams_serialized = 0; | |||||
if (thr->th.th_teams_microtask) { | |||||
kmp_team_t *team = thr->th.th_team; | |||||
int tlevel = thr->th.th_teams_level; // the level of the teams construct | |||||
int ii = team->t.t_level; | |||||
teams_serialized = team->t.t_serialized; | |||||
int level = tlevel + 1; | |||||
KMP_DEBUG_ASSERT(ii >= tlevel); | |||||
while (ii > level) { | |||||
for (teams_serialized = team->t.t_serialized; | |||||
(teams_serialized > 0) && (ii > level); teams_serialized--, ii--) { | |||||
} | |||||
if (team->t.t_serialized && (!teams_serialized)) { | |||||
team = team->t.t_parent; | |||||
continue; | |||||
} | |||||
if (ii > level) { | |||||
team = team->t.t_parent; | |||||
ii--; | |||||
} | |||||
} | |||||
return team; | |||||
} | |||||
return NULL; | |||||
} | |||||
int __kmp_aux_get_team_num() { | |||||
int serialized; | |||||
kmp_team_t *team = __kmp_aux_get_team_info(serialized); | |||||
if (team) { | |||||
if (serialized > 1) { | |||||
return 0; // teams region is serialized ( 1 team of 1 thread ). | |||||
} else { | |||||
return team->t.t_master_tid; | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
int __kmp_aux_get_num_teams() { | |||||
int serialized; | |||||
kmp_team_t *team = __kmp_aux_get_team_info(serialized); | |||||
if (team) { | |||||
if (serialized > 1) { | |||||
return 1; | |||||
} else { | |||||
return team->t.t_parent->t.t_nproc; | |||||
} | |||||
} | |||||
return 1; | |||||
} | |||||
/* ------------------------------------------------------------------------ */ | |||||
#if OMP_50_ENABLED | |||||
/* | |||||
* Affinity Format Parser | |||||
* | |||||
* Field is in form of: %[[[0].]size]type | |||||
* % and type are required (%% means print a literal '%') | |||||
* type is either single char or long name surrounded by {}, | |||||
* e.g., N or {num_threads} | |||||
* 0 => leading zeros | |||||
* . => right justified when size is specified | |||||
* by default output is left justified | |||||
* size is the *minimum* field length | |||||
* All other characters are printed as is | |||||
* | |||||
* Available field types: | |||||
* L {thread_level} - omp_get_level() | |||||
* n {thread_num} - omp_get_thread_num() | |||||
* h {host} - name of host machine | |||||
* P {process_id} - process id (integer) | |||||
* T {thread_identifier} - native thread identifier (integer) | |||||
* N {num_threads} - omp_get_num_threads() | |||||
* A {ancestor_tnum} - omp_get_ancestor_thread_num(omp_get_level()-1) | |||||
* a {thread_affinity} - comma separated list of integers or integer ranges | |||||
* (values of affinity mask) | |||||
* | |||||
* Implementation-specific field types can be added | |||||
* If a type is unknown, print "undefined" | |||||
*/ | |||||
// Structure holding the short name, long name, and corresponding data type | |||||
// for snprintf. A table of these will represent the entire valid keyword | |||||
// field types. | |||||
typedef struct kmp_affinity_format_field_t { | |||||
char short_name; // from spec e.g., L -> thread level | |||||
const char *long_name; // from spec thread_level -> thread level | |||||
char field_format; // data type for snprintf (typically 'd' or 's' | |||||
// for integer or string) | |||||
} kmp_affinity_format_field_t; | |||||
static const kmp_affinity_format_field_t __kmp_affinity_format_table[] = { | |||||
#if KMP_AFFINITY_SUPPORTED | |||||
{'A', "thread_affinity", 's'}, | |||||
#endif | |||||
{'t', "team_num", 'd'}, | |||||
{'T', "num_teams", 'd'}, | |||||
{'L', "nesting_level", 'd'}, | |||||
{'n', "thread_num", 'd'}, | |||||
{'N', "num_threads", 'd'}, | |||||
{'a', "ancestor_tnum", 'd'}, | |||||
{'H', "host", 's'}, | |||||
{'P', "process_id", 'd'}, | |||||
{'i', "native_thread_id", 'd'}}; | |||||
// Return the number of characters it takes to hold field | |||||
static int __kmp_aux_capture_affinity_field(int gtid, const kmp_info_t *th, | |||||
const char **ptr, | |||||
kmp_str_buf_t *field_buffer) { | |||||
int rc, format_index, field_value; | |||||
const char *width_left, *width_right; | |||||
bool pad_zeros, right_justify, parse_long_name, found_valid_name; | |||||
static const int FORMAT_SIZE = 20; | |||||
char format[FORMAT_SIZE] = {0}; | |||||
char absolute_short_name = 0; | |||||
KMP_DEBUG_ASSERT(gtid >= 0); | |||||
KMP_DEBUG_ASSERT(th); | |||||
KMP_DEBUG_ASSERT(**ptr == '%'); | |||||
KMP_DEBUG_ASSERT(field_buffer); | |||||
__kmp_str_buf_clear(field_buffer); | |||||
// Skip the initial % | |||||
(*ptr)++; | |||||
// Check for %% first | |||||
if (**ptr == '%') { | |||||
__kmp_str_buf_cat(field_buffer, "%", 1); | |||||
(*ptr)++; // skip over the second % | |||||
return 1; | |||||
} | |||||
// Parse field modifiers if they are present | |||||
pad_zeros = false; | |||||
if (**ptr == '0') { | |||||
pad_zeros = true; | |||||
(*ptr)++; // skip over 0 | |||||
} | |||||
right_justify = false; | |||||
if (**ptr == '.') { | |||||
right_justify = true; | |||||
(*ptr)++; // skip over . | |||||
} | |||||
// Parse width of field: [width_left, width_right) | |||||
width_left = width_right = NULL; | |||||
if (**ptr >= '0' && **ptr <= '9') { | |||||
width_left = *ptr; | |||||
SKIP_DIGITS(*ptr); | |||||
width_right = *ptr; | |||||
} | |||||
// Create the format for KMP_SNPRINTF based on flags parsed above | |||||
format_index = 0; | |||||
format[format_index++] = '%'; | |||||
if (!right_justify) | |||||
format[format_index++] = '-'; | |||||
if (pad_zeros) | |||||
format[format_index++] = '0'; | |||||
if (width_left && width_right) { | |||||
int i = 0; | |||||
// Only allow 8 digit number widths. | |||||
// This also prevents overflowing format variable | |||||
while (i < 8 && width_left < width_right) { | |||||
format[format_index++] = *width_left; | |||||
width_left++; | |||||
i++; | |||||
} | |||||
} | |||||
// Parse a name (long or short) | |||||
// Canonicalize the name into absolute_short_name | |||||
found_valid_name = false; | |||||
parse_long_name = (**ptr == '{'); | |||||
if (parse_long_name) | |||||
(*ptr)++; // skip initial left brace | |||||
for (size_t i = 0; i < sizeof(__kmp_affinity_format_table) / | |||||
sizeof(__kmp_affinity_format_table[0]); | |||||
++i) { | |||||
char short_name = __kmp_affinity_format_table[i].short_name; | |||||
const char *long_name = __kmp_affinity_format_table[i].long_name; | |||||
char field_format = __kmp_affinity_format_table[i].field_format; | |||||
if (parse_long_name) { | |||||
int length = KMP_STRLEN(long_name); | |||||
if (strncmp(*ptr, long_name, length) == 0) { | |||||
found_valid_name = true; | |||||
(*ptr) += length; // skip the long name | |||||
} | |||||
} else if (**ptr == short_name) { | |||||
found_valid_name = true; | |||||
(*ptr)++; // skip the short name | |||||
} | |||||
if (found_valid_name) { | |||||
format[format_index++] = field_format; | |||||
format[format_index++] = '\0'; | |||||
absolute_short_name = short_name; | |||||
break; | |||||
} | |||||
} | |||||
if (parse_long_name) { | |||||
if (**ptr != '}') { | |||||
absolute_short_name = 0; | |||||
} else { | |||||
(*ptr)++; // skip over the right brace | |||||
} | |||||
} | |||||
// Attempt to fill the buffer with the requested | |||||
// value using snprintf within __kmp_str_buf_print() | |||||
switch (absolute_short_name) { | |||||
case 't': | |||||
rc = __kmp_str_buf_print(field_buffer, format, __kmp_aux_get_team_num()); | |||||
break; | |||||
case 'T': | |||||
rc = __kmp_str_buf_print(field_buffer, format, __kmp_aux_get_num_teams()); | |||||
break; | |||||
case 'L': | |||||
rc = __kmp_str_buf_print(field_buffer, format, th->th.th_team->t.t_level); | |||||
break; | |||||
case 'n': | |||||
rc = __kmp_str_buf_print(field_buffer, format, __kmp_tid_from_gtid(gtid)); | |||||
break; | |||||
case 'H': { | |||||
static const int BUFFER_SIZE = 256; | |||||
char buf[BUFFER_SIZE]; | |||||
__kmp_expand_host_name(buf, BUFFER_SIZE); | |||||
rc = __kmp_str_buf_print(field_buffer, format, buf); | |||||
} break; | |||||
case 'P': | |||||
rc = __kmp_str_buf_print(field_buffer, format, getpid()); | |||||
break; | |||||
case 'i': | |||||
rc = __kmp_str_buf_print(field_buffer, format, __kmp_gettid()); | |||||
break; | |||||
case 'N': | |||||
rc = __kmp_str_buf_print(field_buffer, format, th->th.th_team->t.t_nproc); | |||||
break; | |||||
case 'a': | |||||
field_value = | |||||
__kmp_get_ancestor_thread_num(gtid, th->th.th_team->t.t_level - 1); | |||||
rc = __kmp_str_buf_print(field_buffer, format, field_value); | |||||
break; | |||||
#if KMP_AFFINITY_SUPPORTED | |||||
case 'A': { | |||||
kmp_str_buf_t buf; | |||||
__kmp_str_buf_init(&buf); | |||||
__kmp_affinity_str_buf_mask(&buf, th->th.th_affin_mask); | |||||
rc = __kmp_str_buf_print(field_buffer, format, buf.str); | |||||
__kmp_str_buf_free(&buf); | |||||
} break; | |||||
#endif | |||||
default: | |||||
// According to spec, If an implementation does not have info for field | |||||
// type, then "undefined" is printed | |||||
rc = __kmp_str_buf_print(field_buffer, "%s", "undefined"); | |||||
// Skip the field | |||||
if (parse_long_name) { | |||||
SKIP_TOKEN(*ptr); | |||||
if (**ptr == '}') | |||||
(*ptr)++; | |||||
} else { | |||||
(*ptr)++; | |||||
} | |||||
} | |||||
KMP_ASSERT(format_index <= FORMAT_SIZE); | |||||
return rc; | |||||
} | |||||
/* | |||||
* Return number of characters needed to hold the affinity string | |||||
* (not including null byte character) | |||||
* The resultant string is printed to buffer, which the caller can then | |||||
* handle afterwards | |||||
*/ | |||||
size_t __kmp_aux_capture_affinity(int gtid, const char *format, | |||||
kmp_str_buf_t *buffer) { | |||||
const char *parse_ptr; | |||||
size_t retval; | |||||
const kmp_info_t *th; | |||||
kmp_str_buf_t field; | |||||
KMP_DEBUG_ASSERT(buffer); | |||||
KMP_DEBUG_ASSERT(gtid >= 0); | |||||
__kmp_str_buf_init(&field); | |||||
__kmp_str_buf_clear(buffer); | |||||
th = __kmp_threads[gtid]; | |||||
retval = 0; | |||||
// If format is NULL or zero-length string, then we use | |||||
// affinity-format-var ICV | |||||
parse_ptr = format; | |||||
if (parse_ptr == NULL || *parse_ptr == '\0') { | |||||
parse_ptr = __kmp_affinity_format; | |||||
} | |||||
KMP_DEBUG_ASSERT(parse_ptr); | |||||
while (*parse_ptr != '\0') { | |||||
// Parse a field | |||||
if (*parse_ptr == '%') { | |||||
// Put field in the buffer | |||||
int rc = __kmp_aux_capture_affinity_field(gtid, th, &parse_ptr, &field); | |||||
__kmp_str_buf_catbuf(buffer, &field); | |||||
retval += rc; | |||||
} else { | |||||
// Put literal character in buffer | |||||
__kmp_str_buf_cat(buffer, parse_ptr, 1); | |||||
retval++; | |||||
parse_ptr++; | |||||
} | |||||
} | |||||
__kmp_str_buf_free(&field); | |||||
return retval; | |||||
} | |||||
// Displays the affinity string to stdout | |||||
void __kmp_aux_display_affinity(int gtid, const char *format) { | |||||
kmp_str_buf_t buf; | |||||
__kmp_str_buf_init(&buf); | |||||
__kmp_aux_capture_affinity(gtid, format, &buf); | |||||
__kmp_fprintf(kmp_out, "%s" KMP_END_OF_LINE, buf.str); | |||||
__kmp_str_buf_free(&buf); | |||||
} | |||||
#endif // OMP_50_ENABLED | |||||
/* ------------------------------------------------------------------------ */ | /* ------------------------------------------------------------------------ */ | ||||
void __kmp_aux_set_blocktime(int arg, kmp_info_t *thread, int tid) { | void __kmp_aux_set_blocktime(int arg, kmp_info_t *thread, int tid) { | ||||
int blocktime = arg; /* argument is in milliseconds */ | int blocktime = arg; /* argument is in milliseconds */ | ||||
#if KMP_USE_MONITOR | #if KMP_USE_MONITOR | ||||
int bt_intervals; | int bt_intervals; | ||||
#endif | #endif | ||||
int bt_set; | int bt_set; | ||||
▲ Show 20 Lines • Show All 211 Lines • Show Last 20 Lines |