#if USE_DEBUGGER /* * kmp_debugger.c -- debugger support. */ //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.txt for details. // //===----------------------------------------------------------------------===// #include "kmp.h" #include "kmp_lock.h" #include "kmp_omp.h" #include "kmp_str.h" /* NOTE: All variable names are known to the debugger, do not change! */ #ifdef __cplusplus extern "C" { extern kmp_omp_struct_info_t __kmp_omp_debug_struct_info; } // extern "C" #endif // __cplusplus int __kmp_debugging = FALSE; // Boolean whether currently debugging OpenMP RTL. #define offset_and_size_of( structure, field ) \ { \ offsetof( structure, field ), \ sizeof( ( (structure *) NULL)->field ) \ } #define offset_and_size_not_available \ { -1, -1 } #define addr_and_size_of( var ) \ { \ (kmp_uint64)( & var ), \ sizeof( var ) \ } #define nthr_buffer_size 1024 static kmp_int32 kmp_omp_nthr_info_buffer[ nthr_buffer_size ] = { nthr_buffer_size * sizeof( kmp_int32 ) }; /* TODO: Check punctuation for various platforms here */ static char func_microtask[] = "__kmp_invoke_microtask"; static char func_fork[] = "__kmpc_fork_call"; static char func_fork_teams[] = "__kmpc_fork_teams"; // Various info about runtime structures: addresses, field offsets, sizes, etc. kmp_omp_struct_info_t __kmp_omp_debug_struct_info = { /* Change this only if you make a fundamental data structure change here */ KMP_OMP_VERSION, /* sanity check. Only should be checked if versions are identical * This is also used for backward compatibility to get the runtime * structure size if it the runtime is older than the interface */ sizeof( kmp_omp_struct_info_t ), /* OpenMP RTL version info. */ addr_and_size_of( __kmp_version_major ), addr_and_size_of( __kmp_version_minor ), addr_and_size_of( __kmp_version_build ), addr_and_size_of( __kmp_openmp_version ), { (kmp_uint64)( __kmp_copyright ) + KMP_VERSION_MAGIC_LEN, 0 }, // Skip magic prefix. /* Various globals. */ addr_and_size_of( __kmp_threads ), addr_and_size_of( __kmp_root ), addr_and_size_of( __kmp_threads_capacity ), addr_and_size_of( __kmp_monitor ), #if ! KMP_USE_DYNAMIC_LOCK addr_and_size_of( __kmp_user_lock_table ), #endif addr_and_size_of( func_microtask ), addr_and_size_of( func_fork ), addr_and_size_of( func_fork_teams ), addr_and_size_of( __kmp_team_counter ), addr_and_size_of( __kmp_task_counter ), addr_and_size_of( kmp_omp_nthr_info_buffer ), sizeof( void * ), OMP_LOCK_T_SIZE < sizeof(void *), bs_last_barrier, INITIAL_TASK_DEQUE_SIZE, // thread structure information sizeof( kmp_base_info_t ), offset_and_size_of( kmp_base_info_t, th_info ), offset_and_size_of( kmp_base_info_t, th_team ), offset_and_size_of( kmp_base_info_t, th_root ), offset_and_size_of( kmp_base_info_t, th_serial_team ), offset_and_size_of( kmp_base_info_t, th_ident ), offset_and_size_of( kmp_base_info_t, th_spin_here ), offset_and_size_of( kmp_base_info_t, th_next_waiting ), offset_and_size_of( kmp_base_info_t, th_task_team ), offset_and_size_of( kmp_base_info_t, th_current_task ), offset_and_size_of( kmp_base_info_t, th_task_state ), offset_and_size_of( kmp_base_info_t, th_bar ), offset_and_size_of( kmp_bstate_t, b_worker_arrived ), #if OMP_40_ENABLED // teams information offset_and_size_of( kmp_base_info_t, th_teams_microtask), offset_and_size_of( kmp_base_info_t, th_teams_level), offset_and_size_of( kmp_teams_size_t, nteams ), offset_and_size_of( kmp_teams_size_t, nth ), #endif // kmp_desc structure (for info field above) sizeof( kmp_desc_base_t ), offset_and_size_of( kmp_desc_base_t, ds_tid ), offset_and_size_of( kmp_desc_base_t, ds_gtid ), // On Windows* OS, ds_thread contains a thread /handle/, which is not usable, while thread /id/ // is in ds_thread_id. #if KMP_OS_WINDOWS offset_and_size_of( kmp_desc_base_t, ds_thread_id), #else offset_and_size_of( kmp_desc_base_t, ds_thread), #endif // team structure information sizeof( kmp_base_team_t ), offset_and_size_of( kmp_base_team_t, t_master_tid ), offset_and_size_of( kmp_base_team_t, t_ident ), offset_and_size_of( kmp_base_team_t, t_parent ), offset_and_size_of( kmp_base_team_t, t_nproc ), offset_and_size_of( kmp_base_team_t, t_threads ), offset_and_size_of( kmp_base_team_t, t_serialized ), offset_and_size_of( kmp_base_team_t, t_id ), offset_and_size_of( kmp_base_team_t, t_pkfn ), offset_and_size_of( kmp_base_team_t, t_task_team ), offset_and_size_of( kmp_base_team_t, t_implicit_task_taskdata ), #if OMP_40_ENABLED offset_and_size_of( kmp_base_team_t, t_cancel_request ), #endif offset_and_size_of( kmp_base_team_t, t_bar ), offset_and_size_of( kmp_balign_team_t, b_master_arrived ), offset_and_size_of( kmp_balign_team_t, b_team_arrived ), // root structure information sizeof( kmp_base_root_t ), offset_and_size_of( kmp_base_root_t, r_root_team ), offset_and_size_of( kmp_base_root_t, r_hot_team ), offset_and_size_of( kmp_base_root_t, r_uber_thread ), offset_and_size_not_available, // ident structure information sizeof( ident_t ), offset_and_size_of( ident_t, psource ), offset_and_size_of( ident_t, flags ), // lock structure information sizeof( kmp_base_queuing_lock_t ), offset_and_size_of( kmp_base_queuing_lock_t, initialized ), offset_and_size_of( kmp_base_queuing_lock_t, location ), offset_and_size_of( kmp_base_queuing_lock_t, tail_id ), offset_and_size_of( kmp_base_queuing_lock_t, head_id ), offset_and_size_of( kmp_base_queuing_lock_t, next_ticket ), offset_and_size_of( kmp_base_queuing_lock_t, now_serving ), offset_and_size_of( kmp_base_queuing_lock_t, owner_id ), offset_and_size_of( kmp_base_queuing_lock_t, depth_locked ), offset_and_size_of( kmp_base_queuing_lock_t, flags ), #if ! KMP_USE_DYNAMIC_LOCK /* Lock table. */ sizeof( kmp_lock_table_t ), offset_and_size_of( kmp_lock_table_t, used ), offset_and_size_of( kmp_lock_table_t, allocated ), offset_and_size_of( kmp_lock_table_t, table ), #endif // Task team structure information. sizeof( kmp_base_task_team_t ), offset_and_size_of( kmp_base_task_team_t, tt_threads_data ), offset_and_size_of( kmp_base_task_team_t, tt_found_tasks ), offset_and_size_of( kmp_base_task_team_t, tt_nproc ), offset_and_size_of( kmp_base_task_team_t, tt_unfinished_threads ), offset_and_size_of( kmp_base_task_team_t, tt_active ), // task_data_t. sizeof( kmp_taskdata_t ), offset_and_size_of( kmp_taskdata_t, td_task_id ), offset_and_size_of( kmp_taskdata_t, td_flags ), offset_and_size_of( kmp_taskdata_t, td_team ), offset_and_size_of( kmp_taskdata_t, td_parent ), offset_and_size_of( kmp_taskdata_t, td_level ), offset_and_size_of( kmp_taskdata_t, td_ident ), offset_and_size_of( kmp_taskdata_t, td_allocated_child_tasks ), offset_and_size_of( kmp_taskdata_t, td_incomplete_child_tasks ), offset_and_size_of( kmp_taskdata_t, td_taskwait_ident ), offset_and_size_of( kmp_taskdata_t, td_taskwait_counter ), offset_and_size_of( kmp_taskdata_t, td_taskwait_thread ), #if OMP_40_ENABLED offset_and_size_of( kmp_taskdata_t, td_taskgroup ), offset_and_size_of( kmp_taskgroup_t, count ), offset_and_size_of( kmp_taskgroup_t, cancel_request ), offset_and_size_of( kmp_taskdata_t, td_depnode ), offset_and_size_of( kmp_depnode_list_t, node ), offset_and_size_of( kmp_depnode_list_t, next ), offset_and_size_of( kmp_base_depnode_t, successors ), offset_and_size_of( kmp_base_depnode_t, task ), offset_and_size_of( kmp_base_depnode_t, npredecessors ), offset_and_size_of( kmp_base_depnode_t, nrefs ), #endif offset_and_size_of( kmp_task_t, routine ), // thread_data_t. sizeof( kmp_thread_data_t ), offset_and_size_of( kmp_base_thread_data_t, td_deque ), offset_and_size_of( kmp_base_thread_data_t, td_deque_size ), offset_and_size_of( kmp_base_thread_data_t, td_deque_head ), offset_and_size_of( kmp_base_thread_data_t, td_deque_tail ), offset_and_size_of( kmp_base_thread_data_t, td_deque_ntasks ), offset_and_size_of( kmp_base_thread_data_t, td_deque_last_stolen ), // The last field. KMP_OMP_VERSION, }; // __kmp_omp_debug_struct_info #undef offset_and_size_of #undef addr_and_size_of /* Intel compiler on IA-32 architecture issues a warning "conversion from "unsigned long long" to "char *" may lose significant bits" when 64-bit value is assigned to 32-bit pointer. Use this function to suppress the warning. */ static inline void * __kmp_convert_to_ptr( kmp_uint64 addr ) { #if KMP_COMPILER_ICC #pragma warning( push ) #pragma warning( disable: 810 ) // conversion from "unsigned long long" to "char *" may lose significant bits #pragma warning( disable: 1195 ) // conversion from integer to smaller pointer #endif // KMP_COMPILER_ICC return (void *) addr; #if KMP_COMPILER_ICC #pragma warning( pop ) #endif // KMP_COMPILER_ICC } // __kmp_convert_to_ptr static int kmp_location_match( kmp_str_loc_t * loc, kmp_omp_nthr_item_t * item ) { int file_match = 0; int func_match = 0; int line_match = 0; char * file = (char *) __kmp_convert_to_ptr( item->file ); char * func = (char *) __kmp_convert_to_ptr( item->func ); file_match = __kmp_str_fname_match( & loc->fname, file ); func_match = item->func == 0 // If item->func is NULL, it allows any func name. || strcmp( func, "*" ) == 0 || ( loc->func != NULL && strcmp( loc->func, func ) == 0 ); line_match = item->begin <= loc->line && ( item->end <= 0 || loc->line <= item->end ); // if item->end <= 0, it means "end of file". return ( file_match && func_match && line_match ); } // kmp_location_match int __kmp_omp_num_threads( ident_t const * ident ) { int num_threads = 0; kmp_omp_nthr_info_t * info = (kmp_omp_nthr_info_t *) __kmp_convert_to_ptr( __kmp_omp_debug_struct_info.nthr_info.addr ); if ( info->num > 0 && info->array != 0 ) { kmp_omp_nthr_item_t * items = (kmp_omp_nthr_item_t *) __kmp_convert_to_ptr( info->array ); kmp_str_loc_t loc = __kmp_str_loc_init( ident->psource, 1 ); int i; for ( i = 0; i < info->num; ++ i ) { if ( kmp_location_match( & loc, & items[ i ] ) ) { num_threads = items[ i ].num_threads; }; // if }; // for __kmp_str_loc_free( & loc ); }; // if return num_threads;; } // __kmp_omp_num_threads #endif /* USE_DEBUGGER */