[Openmp-commits] [openmp] r289732 - Change source files from .c to .cpp
Jonathan Peyton via Openmp-commits
openmp-commits at lists.llvm.org
Wed Dec 14 14:39:12 PST 2016
Removed: openmp/trunk/runtime/src/kmp_settings.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/kmp_settings.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/kmp_settings.c (original)
+++ openmp/trunk/runtime/src/kmp_settings.c (removed)
@@ -1,5631 +0,0 @@
-/*
- * kmp_settings.c -- Initialize environment variables
- */
-
-
-//===----------------------------------------------------------------------===//
-//
-// 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_wrapper_getpid.h"
-#include "kmp_environment.h"
-#include "kmp_atomic.h"
-#include "kmp_itt.h"
-#include "kmp_str.h"
-#include "kmp_settings.h"
-#include "kmp_i18n.h"
-#include "kmp_lock.h"
-#include "kmp_io.h"
-#include "kmp_affinity.h"
-
-static int __kmp_env_toPrint( char const * name, int flag );
-
-bool __kmp_env_format = 0; // 0 - old format; 1 - new format
-// -------------------------------------------------------------------------------------------------
-// Helper string functions. Subject to move to kmp_str.
-// -------------------------------------------------------------------------------------------------
-
-static double
-__kmp_convert_to_double( char const * s )
-{
- double result;
-
- if ( KMP_SSCANF( s, "%lf", &result ) < 1 ) {
- result = 0.0;
- }
-
- return result;
-}
-
-#ifdef KMP_DEBUG
-static unsigned int
-__kmp_readstr_with_sentinel(char *dest, char const * src, size_t len, char sentinel) {
- unsigned int i;
- for (i = 0; i < len; i++) {
- if ((*src == '\0') || (*src == sentinel)) {
- break;
- }
- *(dest++) = *(src++);
- }
- *dest = '\0';
- return i;
-}
-#endif
-
-static int
-__kmp_match_with_sentinel( char const * a, char const * b, size_t len, char sentinel ) {
- size_t l = 0;
-
- if(a == NULL)
- a = "";
- if(b == NULL)
- b = "";
- while(*a && *b && *b != sentinel) {
- char ca = *a, cb = *b;
-
- if(ca >= 'a' && ca <= 'z')
- ca -= 'a' - 'A';
- if(cb >= 'a' && cb <= 'z')
- cb -= 'a' - 'A';
- if(ca != cb)
- return FALSE;
- ++l;
- ++a;
- ++b;
- }
- return l >= len;
-}
-
-//
-// Expected usage:
-// token is the token to check for.
-// buf is the string being parsed.
-// *end returns the char after the end of the token.
-// it is not modified unless a match occurs.
-//
-//
-// Example 1:
-//
-// if (__kmp_match_str("token", buf, *end) {
-// <do something>
-// buf = end;
-// }
-//
-// Example 2:
-//
-// if (__kmp_match_str("token", buf, *end) {
-// char *save = **end;
-// **end = sentinel;
-// <use any of the __kmp*_with_sentinel() functions>
-// **end = save;
-// buf = end;
-// }
-//
-
-static int
-__kmp_match_str( char const *token, char const *buf, const char **end) {
-
- KMP_ASSERT(token != NULL);
- KMP_ASSERT(buf != NULL);
- KMP_ASSERT(end != NULL);
-
- while (*token && *buf) {
- char ct = *token, cb = *buf;
-
- if(ct >= 'a' && ct <= 'z')
- ct -= 'a' - 'A';
- if(cb >= 'a' && cb <= 'z')
- cb -= 'a' - 'A';
- if (ct != cb)
- return FALSE;
- ++token;
- ++buf;
- }
- if (*token) {
- return FALSE;
- }
- *end = buf;
- return TRUE;
-}
-
-
-static size_t
-__kmp_round4k( size_t size ) {
- size_t _4k = 4 * 1024;
- if ( size & ( _4k - 1 ) ) {
- size &= ~ ( _4k - 1 );
- if ( size <= KMP_SIZE_T_MAX - _4k ) {
- size += _4k; // Round up if there is no overflow.
- }; // if
- }; // if
- return size;
-} // __kmp_round4k
-
-
-/*
- Here, multipliers are like __kmp_convert_to_seconds, but floating-point
- values are allowed, and the return value is in milliseconds. The default
- multiplier is milliseconds. Returns INT_MAX only if the value specified
- matches "infinit*". Returns -1 if specified string is invalid.
-*/
-int
-__kmp_convert_to_milliseconds( char const * data )
-{
- int ret, nvalues, factor;
- char mult, extra;
- double value;
-
- if (data == NULL) return (-1);
- if ( __kmp_str_match( "infinit", -1, data)) return (INT_MAX);
- value = (double) 0.0;
- mult = '\0';
- nvalues = KMP_SSCANF (data, "%lf%c%c", &value, &mult, &extra);
- if (nvalues < 1) return (-1);
- if (nvalues == 1) mult = '\0';
- if (nvalues == 3) return (-1);
-
- if (value < 0) return (-1);
-
- switch (mult) {
- case '\0':
- /* default is milliseconds */
- factor = 1;
- break;
- case 's': case 'S':
- factor = 1000;
- break;
- case 'm': case 'M':
- factor = 1000 * 60;
- break;
- case 'h': case 'H':
- factor = 1000 * 60 * 60;
- break;
- case 'd': case 'D':
- factor = 1000 * 24 * 60 * 60;
- break;
- default:
- return (-1);
- }
-
- if ( value >= ( (INT_MAX-1) / factor) )
- ret = INT_MAX-1; /* Don't allow infinite value here */
- else
- ret = (int) (value * (double) factor); /* truncate to int */
-
- return ret;
-}
-
-
-static int
-__kmp_strcasecmp_with_sentinel( char const * a, char const * b, char sentinel ) {
- if(a == NULL)
- a = "";
- if(b == NULL)
- b = "";
- while(*a && *b && *b != sentinel) {
- char ca = *a, cb = *b;
-
- if(ca >= 'a' && ca <= 'z')
- ca -= 'a' - 'A';
- if(cb >= 'a' && cb <= 'z')
- cb -= 'a' - 'A';
- if(ca != cb)
- return (int)(unsigned char)*a - (int)(unsigned char)*b;
- ++a;
- ++b;
- }
- return *a ?
- (*b && *b != sentinel) ? (int)(unsigned char)*a - (int)(unsigned char)*b : 1 :
- (*b && *b != sentinel) ? -1 : 0;
-}
-
-
-// =================================================================================================
-// Table structures and helper functions.
-// =================================================================================================
-
-typedef struct __kmp_setting kmp_setting_t;
-typedef struct __kmp_stg_ss_data kmp_stg_ss_data_t;
-typedef struct __kmp_stg_wp_data kmp_stg_wp_data_t;
-typedef struct __kmp_stg_fr_data kmp_stg_fr_data_t;
-
-typedef void ( * kmp_stg_parse_func_t )( char const * name, char const * value, void * data );
-typedef void ( * kmp_stg_print_func_t )( kmp_str_buf_t * buffer, char const * name, void * data );
-
-struct __kmp_setting {
- char const * name; // Name of setting (environment variable).
- kmp_stg_parse_func_t parse; // Parser function.
- kmp_stg_print_func_t print; // Print function.
- void * data; // Data passed to parser and printer.
- int set; // Variable set during this "session"
- // (__kmp_env_initialize() or kmp_set_defaults() call).
- int defined; // Variable set in any "session".
-}; // struct __kmp_setting
-
-struct __kmp_stg_ss_data {
- size_t factor; // Default factor: 1 for KMP_STACKSIZE, 1024 for others.
- kmp_setting_t * * rivals; // Array of pointers to rivals (including itself).
-}; // struct __kmp_stg_ss_data
-
-struct __kmp_stg_wp_data {
- int omp; // 0 -- KMP_LIBRARY, 1 -- OMP_WAIT_POLICY.
- kmp_setting_t * * rivals; // Array of pointers to rivals (including itself).
-}; // struct __kmp_stg_wp_data
-
-struct __kmp_stg_fr_data {
- int force; // 0 -- KMP_DETERMINISTIC_REDUCTION, 1 -- KMP_FORCE_REDUCTION.
- kmp_setting_t * * rivals; // Array of pointers to rivals (including itself).
-}; // struct __kmp_stg_fr_data
-
-static int
-__kmp_stg_check_rivals( // 0 -- Ok, 1 -- errors found.
- char const * name, // Name of variable.
- char const * value, // Value of the variable.
- kmp_setting_t * * rivals // List of rival settings (the list must include current one).
-);
-
-
-// -------------------------------------------------------------------------------------------------
-// Helper parse functions.
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_bool(
- char const * name,
- char const * value,
- int * out
-) {
- if ( __kmp_str_match_true( value ) ) {
- * out = TRUE;
- } else if (__kmp_str_match_false( value ) ) {
- * out = FALSE;
- } else {
- __kmp_msg(
- kmp_ms_warning,
- KMP_MSG( BadBoolValue, name, value ),
- KMP_HNT( ValidBoolValues ),
- __kmp_msg_null
- );
- }; // if
-} // __kmp_stg_parse_bool
-
-static void
-__kmp_stg_parse_size(
- char const * name,
- char const * value,
- size_t size_min,
- size_t size_max,
- int * is_specified,
- size_t * out,
- size_t factor
-) {
- char const * msg = NULL;
- #if KMP_OS_DARWIN
- size_min = __kmp_round4k( size_min );
- size_max = __kmp_round4k( size_max );
- #endif // KMP_OS_DARWIN
- if ( value ) {
- if ( is_specified != NULL ) {
- * is_specified = 1;
- }; // if
- __kmp_str_to_size( value, out, factor, & msg );
- if ( msg == NULL ) {
- if ( * out > size_max ) {
- * out = size_max;
- msg = KMP_I18N_STR( ValueTooLarge );
- } else if ( * out < size_min ) {
- * out = size_min;
- msg = KMP_I18N_STR( ValueTooSmall );
- } else {
- #if KMP_OS_DARWIN
- size_t round4k = __kmp_round4k( * out );
- if ( * out != round4k ) {
- * out = round4k;
- msg = KMP_I18N_STR( NotMultiple4K );
- }; // if
- #endif
- }; // if
- } else {
- // If integer overflow occurred, * out == KMP_SIZE_T_MAX. Cut it to size_max silently.
- if ( * out < size_min ) {
- * out = size_max;
- }
- else if ( * out > size_max ) {
- * out = size_max;
- }; // if
- }; // if
- if ( msg != NULL ) {
- // Message is not empty. Print warning.
- kmp_str_buf_t buf;
- __kmp_str_buf_init( & buf );
- __kmp_str_buf_print_size( & buf, * out );
- KMP_WARNING( ParseSizeIntWarn, name, value, msg );
- KMP_INFORM( Using_str_Value, name, buf.str );
- __kmp_str_buf_free( & buf );
- }; // if
- }; // if
-} // __kmp_stg_parse_size
-
-#if KMP_AFFINITY_SUPPORTED
-static void
-__kmp_stg_parse_str(
- char const * name,
- char const * value,
- char const * * out
-) {
- __kmp_str_free(out);
- * out = __kmp_str_format( "%s", value );
-} // __kmp_stg_parse_str
-#endif
-
-static void
-__kmp_stg_parse_int(
- char const * name, // I: Name of environment variable (used in warning messages).
- char const * value, // I: Value of environment variable to parse.
- int min, // I: Miminal allowed value.
- int max, // I: Maximum allowed value.
- int * out // O: Output (parsed) value.
-) {
- char const * msg = NULL;
- kmp_uint64 uint = * out;
- __kmp_str_to_uint( value, & uint, & msg );
- if ( msg == NULL ) {
- if ( uint < (unsigned int)min ) {
- msg = KMP_I18N_STR( ValueTooSmall );
- uint = min;
- } else if ( uint > (unsigned int)max ) {
- msg = KMP_I18N_STR( ValueTooLarge );
- uint = max;
- }; // if
- } else {
- // If overflow occurred msg contains error message and uint is very big. Cut tmp it
- // to INT_MAX.
- if ( uint < (unsigned int)min ) {
- uint = min;
- }
- else if ( uint > (unsigned int)max ) {
- uint = max;
- }; // if
- }; // if
- if ( msg != NULL ) {
- // Message is not empty. Print warning.
- kmp_str_buf_t buf;
- KMP_WARNING( ParseSizeIntWarn, name, value, msg );
- __kmp_str_buf_init( & buf );
- __kmp_str_buf_print( &buf, "%" KMP_UINT64_SPEC "", uint );
- KMP_INFORM( Using_uint64_Value, name, buf.str );
- __kmp_str_buf_free( &buf );
- }; // if
- * out = uint;
-} // __kmp_stg_parse_int
-
-
-#if KMP_DEBUG_ADAPTIVE_LOCKS
-static void
-__kmp_stg_parse_file(
- char const * name,
- char const * value,
- char * suffix,
- char * * out
-) {
- char buffer[256];
- char *t;
- int hasSuffix;
- __kmp_str_free(out);
- t = (char *) strrchr(value, '.');
- hasSuffix = t && __kmp_str_eqf( t, suffix );
- t = __kmp_str_format( "%s%s", value, hasSuffix ? "" : suffix );
- __kmp_expand_file_name( buffer, sizeof(buffer), t);
- __kmp_str_free(&t);
- * out = __kmp_str_format( "%s", buffer );
-} // __kmp_stg_parse_file
-#endif
-
-#ifdef KMP_DEBUG
-static char * par_range_to_print = NULL;
-
-static void
-__kmp_stg_parse_par_range(
- char const * name,
- char const * value,
- int * out_range,
- char * out_routine,
- char * out_file,
- int * out_lb,
- int * out_ub
-) {
- size_t len = KMP_STRLEN( value + 1 );
- par_range_to_print = (char *) KMP_INTERNAL_MALLOC( len +1 );
- KMP_STRNCPY_S( par_range_to_print, len + 1, value, len + 1);
- __kmp_par_range = +1;
- __kmp_par_range_lb = 0;
- __kmp_par_range_ub = INT_MAX;
- for (;;) {
- unsigned int len;
- if (( value == NULL ) || ( *value == '\0' )) {
- break;
- }
- if ( ! __kmp_strcasecmp_with_sentinel( "routine", value, '=' )) {
- value = strchr( value, '=' ) + 1;
- len = __kmp_readstr_with_sentinel( out_routine,
- value, KMP_PAR_RANGE_ROUTINE_LEN - 1, ',' );
- if ( len == 0 ) {
- goto par_range_error;
- }
- value = strchr( value, ',' );
- if ( value != NULL ) {
- value++;
- }
- continue;
- }
- if ( ! __kmp_strcasecmp_with_sentinel( "filename", value, '=' )) {
- value = strchr( value, '=' ) + 1;
- len = __kmp_readstr_with_sentinel( out_file,
- value, KMP_PAR_RANGE_FILENAME_LEN - 1, ',' );
- if ( len == 0) {
- goto par_range_error;
- }
- value = strchr( value, ',' );
- if ( value != NULL ) {
- value++;
- }
- continue;
- }
- if (( ! __kmp_strcasecmp_with_sentinel( "range", value, '=' ))
- || ( ! __kmp_strcasecmp_with_sentinel( "incl_range", value, '=' ))) {
- value = strchr( value, '=' ) + 1;
- if ( KMP_SSCANF( value, "%d:%d", out_lb, out_ub ) != 2 ) {
- goto par_range_error;
- }
- *out_range = +1;
- value = strchr( value, ',' );
- if ( value != NULL ) {
- value++;
- }
- continue;
- }
- if ( ! __kmp_strcasecmp_with_sentinel( "excl_range", value, '=' )) {
- value = strchr( value, '=' ) + 1;
- if ( KMP_SSCANF( value, "%d:%d", out_lb, out_ub) != 2 ) {
- goto par_range_error;
- }
- *out_range = -1;
- value = strchr( value, ',' );
- if ( value != NULL ) {
- value++;
- }
- continue;
- }
- par_range_error:
- KMP_WARNING( ParRangeSyntax, name );
- __kmp_par_range = 0;
- break;
- }
-} // __kmp_stg_parse_par_range
-#endif
-
-int
-__kmp_initial_threads_capacity( int req_nproc )
-{
- int nth = 32;
-
- /* MIN( MAX( 32, 4 * $OMP_NUM_THREADS, 4 * omp_get_num_procs() ), __kmp_max_nth) */
- if (nth < (4 * req_nproc))
- nth = (4 * req_nproc);
- if (nth < (4 * __kmp_xproc))
- nth = (4 * __kmp_xproc);
-
- if (nth > __kmp_max_nth)
- nth = __kmp_max_nth;
-
- return nth;
-}
-
-
-int
-__kmp_default_tp_capacity( int req_nproc, int max_nth, int all_threads_specified) {
- int nth = 128;
-
- if(all_threads_specified)
- return max_nth;
- /* MIN( MAX (128, 4 * $OMP_NUM_THREADS, 4 * omp_get_num_procs() ), __kmp_max_nth ) */
- if (nth < (4 * req_nproc))
- nth = (4 * req_nproc);
- if (nth < (4 * __kmp_xproc))
- nth = (4 * __kmp_xproc);
-
- if (nth > __kmp_max_nth)
- nth = __kmp_max_nth;
-
- return nth;
-}
-
-
-// -------------------------------------------------------------------------------------------------
-// Helper print functions.
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_print_bool( kmp_str_buf_t * buffer, char const * name, int value ) {
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_BOOL;
- } else {
- __kmp_str_buf_print( buffer, " %s=%s\n", name, value ? "true" : "false" );
- }
-} // __kmp_stg_print_bool
-
-static void
-__kmp_stg_print_int( kmp_str_buf_t * buffer, char const * name, int value ) {
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_INT;
- } else {
- __kmp_str_buf_print( buffer, " %s=%d\n", name, value );
- }
-} // __kmp_stg_print_int
-
-static void
-__kmp_stg_print_uint64( kmp_str_buf_t * buffer, char const * name, kmp_uint64 value ) {
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_UINT64;
- } else {
- __kmp_str_buf_print( buffer, " %s=%" KMP_UINT64_SPEC "\n", name, value );
- }
-} // __kmp_stg_print_uint64
-
-static void
-__kmp_stg_print_str( kmp_str_buf_t * buffer, char const * name, char const * value ) {
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_STR;
- } else {
- __kmp_str_buf_print( buffer, " %s=%s\n", name, value );
- }
-} // __kmp_stg_print_str
-
-static void
-__kmp_stg_print_size( kmp_str_buf_t * buffer, char const * name, size_t value ) {
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME_EX(name);
- __kmp_str_buf_print_size( buffer, value );
- __kmp_str_buf_print( buffer, "'\n" );
- } else {
- __kmp_str_buf_print( buffer, " %s=", name );
- __kmp_str_buf_print_size( buffer, value );
- __kmp_str_buf_print( buffer, "\n" );
- return;
- }
-} // __kmp_stg_print_size
-
-
-// =================================================================================================
-// Parse and print functions.
-// =================================================================================================
-
-// -------------------------------------------------------------------------------------------------
-// KMP_ALL_THREADS, KMP_MAX_THREADS, OMP_THREAD_LIMIT
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_all_threads( char const * name, char const * value, void * data ) {
-
- kmp_setting_t * * rivals = (kmp_setting_t * *) data;
- int rc;
- rc = __kmp_stg_check_rivals( name, value, rivals );
- if ( rc ) {
- return;
- }; // if
- if ( ! __kmp_strcasecmp_with_sentinel( "all", value, 0 ) ) {
- __kmp_max_nth = __kmp_xproc;
- __kmp_allThreadsSpecified = 1;
- } else {
- __kmp_stg_parse_int( name, value, 1, __kmp_sys_max_nth, & __kmp_max_nth );
- __kmp_allThreadsSpecified = 0;
- }
- K_DIAG( 1, ( "__kmp_max_nth == %d\n", __kmp_max_nth ) );
-
-} // __kmp_stg_parse_all_threads
-
-static void
-__kmp_stg_print_all_threads( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_max_nth );
-} // __kmp_stg_print_all_threads
-
-// -------------------------------------------------------------------------------------------------
-// KMP_BLOCKTIME
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_blocktime( char const * name, char const * value, void * data ) {
- __kmp_dflt_blocktime = __kmp_convert_to_milliseconds( value );
- if ( __kmp_dflt_blocktime < 0 ) {
- __kmp_dflt_blocktime = KMP_DEFAULT_BLOCKTIME;
- __kmp_msg( kmp_ms_warning, KMP_MSG( InvalidValue, name, value ), __kmp_msg_null );
- KMP_INFORM( Using_int_Value, name, __kmp_dflt_blocktime );
- __kmp_env_blocktime = FALSE; // Revert to default as if var not set.
- } else {
- if ( __kmp_dflt_blocktime < KMP_MIN_BLOCKTIME ) {
- __kmp_dflt_blocktime = KMP_MIN_BLOCKTIME;
- __kmp_msg( kmp_ms_warning, KMP_MSG( SmallValue, name, value ), __kmp_msg_null );
- KMP_INFORM( MinValueUsing, name, __kmp_dflt_blocktime );
- } else if ( __kmp_dflt_blocktime > KMP_MAX_BLOCKTIME ) {
- __kmp_dflt_blocktime = KMP_MAX_BLOCKTIME;
- __kmp_msg( kmp_ms_warning, KMP_MSG( LargeValue, name, value ), __kmp_msg_null );
- KMP_INFORM( MaxValueUsing, name, __kmp_dflt_blocktime );
- }; // if
- __kmp_env_blocktime = TRUE; // KMP_BLOCKTIME was specified.
- }; // if
-#if KMP_USE_MONITOR
- // calculate number of monitor thread wakeup intervals corresponding to blocktime.
- __kmp_monitor_wakeups = KMP_WAKEUPS_FROM_BLOCKTIME( __kmp_dflt_blocktime, __kmp_monitor_wakeups );
- __kmp_bt_intervals = KMP_INTERVALS_FROM_BLOCKTIME( __kmp_dflt_blocktime, __kmp_monitor_wakeups );
-#endif
- K_DIAG( 1, ( "__kmp_env_blocktime == %d\n", __kmp_env_blocktime ) );
- if ( __kmp_env_blocktime ) {
- K_DIAG( 1, ( "__kmp_dflt_blocktime == %d\n", __kmp_dflt_blocktime ) );
- }
-} // __kmp_stg_parse_blocktime
-
-static void
-__kmp_stg_print_blocktime( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_dflt_blocktime );
-} // __kmp_stg_print_blocktime
-
-// -------------------------------------------------------------------------------------------------
-// KMP_DUPLICATE_LIB_OK
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_duplicate_lib_ok( char const * name, char const * value, void * data ) {
- /* actually this variable is not supported,
- put here for compatibility with earlier builds and for static/dynamic combination */
- __kmp_stg_parse_bool( name, value, & __kmp_duplicate_library_ok );
-} // __kmp_stg_parse_duplicate_lib_ok
-
-static void
-__kmp_stg_print_duplicate_lib_ok( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_duplicate_library_ok );
-} // __kmp_stg_print_duplicate_lib_ok
-
-// -------------------------------------------------------------------------------------------------
-// KMP_INHERIT_FP_CONTROL
-// -------------------------------------------------------------------------------------------------
-
-#if KMP_ARCH_X86 || KMP_ARCH_X86_64
-
-static void
-__kmp_stg_parse_inherit_fp_control( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_bool( name, value, & __kmp_inherit_fp_control );
-} // __kmp_stg_parse_inherit_fp_control
-
-static void
-__kmp_stg_print_inherit_fp_control( kmp_str_buf_t * buffer, char const * name, void * data ) {
-#if KMP_DEBUG
- __kmp_stg_print_bool( buffer, name, __kmp_inherit_fp_control );
-#endif /* KMP_DEBUG */
-} // __kmp_stg_print_inherit_fp_control
-
-#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
-
-// -------------------------------------------------------------------------------------------------
-// KMP_LIBRARY, OMP_WAIT_POLICY
-// -------------------------------------------------------------------------------------------------
-
-static char const *blocktime_str = NULL;
-
-static void
-__kmp_stg_parse_wait_policy( char const * name, char const * value, void * data ) {
-
- kmp_stg_wp_data_t * wait = (kmp_stg_wp_data_t *) data;
- int rc;
-
- rc = __kmp_stg_check_rivals( name, value, wait->rivals );
- if ( rc ) {
- return;
- }; // if
-
- if ( wait->omp ) {
- if ( __kmp_str_match( "ACTIVE", 1, value ) ) {
- __kmp_library = library_turnaround;
- if ( blocktime_str == NULL ) {
- // KMP_BLOCKTIME not specified, so set default to "infinite".
- __kmp_dflt_blocktime = KMP_MAX_BLOCKTIME;
- }
- } else if ( __kmp_str_match( "PASSIVE", 1, value ) ) {
- __kmp_library = library_throughput;
- if ( blocktime_str == NULL ) {
- // KMP_BLOCKTIME not specified, so set default to 0.
- __kmp_dflt_blocktime = 0;
- }
- } else {
- KMP_WARNING( StgInvalidValue, name, value );
- }; // if
- } else {
- if ( __kmp_str_match( "serial", 1, value ) ) { /* S */
- __kmp_library = library_serial;
- } else if ( __kmp_str_match( "throughput", 2, value ) ) { /* TH */
- __kmp_library = library_throughput;
- } else if ( __kmp_str_match( "turnaround", 2, value ) ) { /* TU */
- __kmp_library = library_turnaround;
- } else if ( __kmp_str_match( "dedicated", 1, value ) ) { /* D */
- __kmp_library = library_turnaround;
- } else if ( __kmp_str_match( "multiuser", 1, value ) ) { /* M */
- __kmp_library = library_throughput;
- } else {
- KMP_WARNING( StgInvalidValue, name, value );
- }; // if
- }; // if
- __kmp_aux_set_library( __kmp_library );
-
-} // __kmp_stg_parse_wait_policy
-
-static void
-__kmp_stg_print_wait_policy( kmp_str_buf_t * buffer, char const * name, void * data ) {
-
- kmp_stg_wp_data_t * wait = (kmp_stg_wp_data_t *) data;
- char const * value = NULL;
-
- if ( wait->omp ) {
- switch ( __kmp_library ) {
- case library_turnaround : {
- value = "ACTIVE";
- } break;
- case library_throughput : {
- value = "PASSIVE";
- } break;
- }; // switch
- } else {
- switch ( __kmp_library ) {
- case library_serial : {
- value = "serial";
- } break;
- case library_turnaround : {
- value = "turnaround";
- } break;
- case library_throughput : {
- value = "throughput";
- } break;
- }; // switch
- }; // if
- if ( value != NULL ) {
- __kmp_stg_print_str( buffer, name, value );
- }; // if
-
-} // __kmp_stg_print_wait_policy
-
-#if KMP_USE_MONITOR
-// -------------------------------------------------------------------------------------------------
-// KMP_MONITOR_STACKSIZE
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_monitor_stacksize( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_size(
- name,
- value,
- __kmp_sys_min_stksize,
- KMP_MAX_STKSIZE,
- NULL,
- & __kmp_monitor_stksize,
- 1
- );
-} // __kmp_stg_parse_monitor_stacksize
-
-static void
-__kmp_stg_print_monitor_stacksize( kmp_str_buf_t * buffer, char const * name, void * data ) {
- if( __kmp_env_format ) {
- if ( __kmp_monitor_stksize > 0 )
- KMP_STR_BUF_PRINT_NAME_EX(name);
- else
- KMP_STR_BUF_PRINT_NAME;
- } else {
- __kmp_str_buf_print( buffer, " %s", name );
- }
- if ( __kmp_monitor_stksize > 0 ) {
- __kmp_str_buf_print_size( buffer, __kmp_monitor_stksize );
- } else {
- __kmp_str_buf_print( buffer, ": %s\n", KMP_I18N_STR( NotDefined ) );
- }
- if( __kmp_env_format && __kmp_monitor_stksize ) {
- __kmp_str_buf_print( buffer, "'\n");
- }
-
-} // __kmp_stg_print_monitor_stacksize
-#endif // KMP_USE_MONITOR
-
-// -------------------------------------------------------------------------------------------------
-// KMP_SETTINGS
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_settings( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_bool( name, value, & __kmp_settings );
-} // __kmp_stg_parse_settings
-
-static void
-__kmp_stg_print_settings( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_settings );
-} // __kmp_stg_print_settings
-
-// -------------------------------------------------------------------------------------------------
-// KMP_STACKPAD
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_stackpad( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_int(
- name, // Env var name
- value, // Env var value
- KMP_MIN_STKPADDING, // Min value
- KMP_MAX_STKPADDING, // Max value
- & __kmp_stkpadding // Var to initialize
- );
-} // __kmp_stg_parse_stackpad
-
-static void
-__kmp_stg_print_stackpad( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_stkpadding );
-} // __kmp_stg_print_stackpad
-
-// -------------------------------------------------------------------------------------------------
-// KMP_STACKOFFSET
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_stackoffset( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_size(
- name, // Env var name
- value, // Env var value
- KMP_MIN_STKOFFSET, // Min value
- KMP_MAX_STKOFFSET, // Max value
- NULL, //
- & __kmp_stkoffset, // Var to initialize
- 1
- );
-} // __kmp_stg_parse_stackoffset
-
-static void
-__kmp_stg_print_stackoffset( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_size( buffer, name, __kmp_stkoffset );
-} // __kmp_stg_print_stackoffset
-
-// -------------------------------------------------------------------------------------------------
-// KMP_STACKSIZE, OMP_STACKSIZE, GOMP_STACKSIZE
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_stacksize( char const * name, char const * value, void * data ) {
-
- kmp_stg_ss_data_t * stacksize = (kmp_stg_ss_data_t *) data;
- int rc;
-
- rc = __kmp_stg_check_rivals( name, value, stacksize->rivals );
- if ( rc ) {
- return;
- }; // if
- __kmp_stg_parse_size(
- name, // Env var name
- value, // Env var value
- __kmp_sys_min_stksize, // Min value
- KMP_MAX_STKSIZE, // Max value
- & __kmp_env_stksize, //
- & __kmp_stksize, // Var to initialize
- stacksize->factor
- );
-
-} // __kmp_stg_parse_stacksize
-
-// This function is called for printing both KMP_STACKSIZE (factor is 1) and OMP_STACKSIZE (factor is 1024).
-// Currently it is not possible to print OMP_STACKSIZE value in bytes. We can consider adding this
-// possibility by a customer request in future.
-static void
-__kmp_stg_print_stacksize( kmp_str_buf_t * buffer, char const * name, void * data ) {
- kmp_stg_ss_data_t * stacksize = (kmp_stg_ss_data_t *) data;
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME_EX(name);
- __kmp_str_buf_print_size( buffer, (__kmp_stksize % 1024) ? __kmp_stksize / stacksize->factor : __kmp_stksize );
- __kmp_str_buf_print( buffer, "'\n" );
- } else {
- __kmp_str_buf_print( buffer, " %s=", name );
- __kmp_str_buf_print_size( buffer, (__kmp_stksize % 1024) ? __kmp_stksize / stacksize->factor : __kmp_stksize );
- __kmp_str_buf_print( buffer, "\n" );
- }
-} // __kmp_stg_print_stacksize
-
-// -------------------------------------------------------------------------------------------------
-// KMP_VERSION
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_version( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_bool( name, value, & __kmp_version );
-} // __kmp_stg_parse_version
-
-static void
-__kmp_stg_print_version( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_version );
-} // __kmp_stg_print_version
-
-// -------------------------------------------------------------------------------------------------
-// KMP_WARNINGS
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_warnings( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_bool( name, value, & __kmp_generate_warnings );
- if (__kmp_generate_warnings != kmp_warnings_off) { // AC: we have only 0/1 values documented,
- __kmp_generate_warnings = kmp_warnings_explicit; // so reset it to explicit in order to
- } // distinguish from default setting
-} // __kmp_env_parse_warnings
-
-static void
-__kmp_stg_print_warnings( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_generate_warnings ); // AC: TODO: change to print_int?
-} // __kmp_env_print_warnings // (needs documentation change)...
-
-// -------------------------------------------------------------------------------------------------
-// OMP_NESTED, OMP_NUM_THREADS
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_nested( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_bool( name, value, & __kmp_dflt_nested );
-} // __kmp_stg_parse_nested
-
-static void
-__kmp_stg_print_nested( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_dflt_nested );
-} // __kmp_stg_print_nested
-
-static void
-__kmp_parse_nested_num_threads( const char *var, const char *env, kmp_nested_nthreads_t *nth_array )
-{
- const char *next = env;
- const char *scan = next;
-
- int total = 0; // Count elements that were set. It'll be used as an array size
- int prev_comma = FALSE; // For correct processing sequential commas
-
- // Count the number of values in the env. var string
- for ( ; ; ) {
- SKIP_WS( next );
-
- if ( *next == '\0' ) {
- break;
- }
- // Next character is not an integer or not a comma => end of list
- if ( ( ( *next < '0' ) || ( *next > '9' ) ) && ( *next !=',') ) {
- KMP_WARNING( NthSyntaxError, var, env );
- return;
- }
- // The next character is ','
- if ( *next == ',' ) {
- // ',' is the fisrt character
- if ( total == 0 || prev_comma ) {
- total++;
- }
- prev_comma = TRUE;
- next++; //skip ','
- SKIP_WS( next );
- }
- // Next character is a digit
- if ( *next >= '0' && *next <= '9' ) {
- prev_comma = FALSE;
- SKIP_DIGITS( next );
- total++;
- const char *tmp = next;
- SKIP_WS( tmp );
- if ( ( *next == ' ' || *next == '\t' ) && ( *tmp >= '0' && *tmp <= '9' ) ) {
- KMP_WARNING( NthSpacesNotAllowed, var, env );
- return;
- }
- }
- }
- KMP_DEBUG_ASSERT( total > 0 );
- if( total <= 0 ) {
- KMP_WARNING( NthSyntaxError, var, env );
- return;
- }
-
- // Check if the nested nthreads array exists
- if ( ! nth_array->nth ) {
- // Allocate an array of double size
- nth_array->nth = ( int * )KMP_INTERNAL_MALLOC( sizeof( int ) * total * 2 );
- if ( nth_array->nth == NULL ) {
- KMP_FATAL( MemoryAllocFailed );
- }
- nth_array->size = total * 2;
- } else {
- if ( nth_array->size < total ) {
- // Increase the array size
- do {
- nth_array->size *= 2;
- } while ( nth_array->size < total );
-
- nth_array->nth = (int *) KMP_INTERNAL_REALLOC(
- nth_array->nth, sizeof( int ) * nth_array->size );
- if ( nth_array->nth == NULL ) {
- KMP_FATAL( MemoryAllocFailed );
- }
- }
- }
- nth_array->used = total;
- int i = 0;
-
- prev_comma = FALSE;
- total = 0;
- // Save values in the array
- for ( ; ; ) {
- SKIP_WS( scan );
- if ( *scan == '\0' ) {
- break;
- }
- // The next character is ','
- if ( *scan == ',' ) {
- // ',' in the beginning of the list
- if ( total == 0 ) {
- // The value is supposed to be equal to __kmp_avail_proc but it is unknown at the moment.
- // So let's put a placeholder (#threads = 0) to correct it later.
- nth_array->nth[i++] = 0;
- total++;
- }else if ( prev_comma ) {
- // Num threads is inherited from the previous level
- nth_array->nth[i] = nth_array->nth[i - 1];
- i++;
- total++;
- }
- prev_comma = TRUE;
- scan++; //skip ','
- SKIP_WS( scan );
- }
- // Next character is a digit
- if ( *scan >= '0' && *scan <= '9' ) {
- int num;
- const char *buf = scan;
- char const * msg = NULL;
- prev_comma = FALSE;
- SKIP_DIGITS( scan );
- total++;
-
- num = __kmp_str_to_int( buf, *scan );
- if ( num < KMP_MIN_NTH ) {
- msg = KMP_I18N_STR( ValueTooSmall );
- num = KMP_MIN_NTH;
- } else if ( num > __kmp_sys_max_nth ) {
- msg = KMP_I18N_STR( ValueTooLarge );
- num = __kmp_sys_max_nth;
- }
- if ( msg != NULL ) {
- // Message is not empty. Print warning.
- KMP_WARNING( ParseSizeIntWarn, var, env, msg );
- KMP_INFORM( Using_int_Value, var, num );
- }
- nth_array->nth[i++] = num;
- }
- }
-}
-
-static void
-__kmp_stg_parse_num_threads( char const * name, char const * value, void * data ) {
- // TODO: Remove this option. OMP_NUM_THREADS is a list of positive integers!
- if ( ! __kmp_strcasecmp_with_sentinel( "all", value, 0 ) ) {
- // The array of 1 element
- __kmp_nested_nth.nth = ( int* )KMP_INTERNAL_MALLOC( sizeof( int ) );
- __kmp_nested_nth.size = __kmp_nested_nth.used = 1;
- __kmp_nested_nth.nth[0] = __kmp_dflt_team_nth = __kmp_dflt_team_nth_ub = __kmp_xproc;
- } else {
- __kmp_parse_nested_num_threads( name, value, & __kmp_nested_nth );
- if ( __kmp_nested_nth.nth ) {
- __kmp_dflt_team_nth = __kmp_nested_nth.nth[0];
- if ( __kmp_dflt_team_nth_ub < __kmp_dflt_team_nth ) {
- __kmp_dflt_team_nth_ub = __kmp_dflt_team_nth;
- }
- }
- }; // if
- K_DIAG( 1, ( "__kmp_dflt_team_nth == %d\n", __kmp_dflt_team_nth ) );
-} // __kmp_stg_parse_num_threads
-
-static void
-__kmp_stg_print_num_threads( kmp_str_buf_t * buffer, char const * name, void * data ) {
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME;
- } else {
- __kmp_str_buf_print( buffer, " %s", name );
- }
- if ( __kmp_nested_nth.used ) {
- kmp_str_buf_t buf;
- __kmp_str_buf_init( &buf );
- for ( int i = 0; i < __kmp_nested_nth.used; i++) {
- __kmp_str_buf_print( &buf, "%d", __kmp_nested_nth.nth[i] );
- if ( i < __kmp_nested_nth.used - 1 ) {
- __kmp_str_buf_print( &buf, "," );
- }
- }
- __kmp_str_buf_print( buffer, "='%s'\n", buf.str );
- __kmp_str_buf_free(&buf);
- } else {
- __kmp_str_buf_print( buffer, ": %s\n", KMP_I18N_STR( NotDefined ) );
- }
-} // __kmp_stg_print_num_threads
-
-// -------------------------------------------------------------------------------------------------
-// OpenMP 3.0: KMP_TASKING, OMP_MAX_ACTIVE_LEVELS,
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_tasking( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_int( name, value, 0, (int)tskm_max, (int *)&__kmp_tasking_mode );
-} // __kmp_stg_parse_tasking
-
-static void
-__kmp_stg_print_tasking( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_tasking_mode );
-} // __kmp_stg_print_tasking
-
-static void
-__kmp_stg_parse_task_stealing( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_int( name, value, 0, 1, (int *)&__kmp_task_stealing_constraint );
-} // __kmp_stg_parse_task_stealing
-
-static void
-__kmp_stg_print_task_stealing( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_task_stealing_constraint );
-} // __kmp_stg_print_task_stealing
-
-static void
-__kmp_stg_parse_max_active_levels( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_int( name, value, 0, KMP_MAX_ACTIVE_LEVELS_LIMIT, & __kmp_dflt_max_active_levels );
-} // __kmp_stg_parse_max_active_levels
-
-static void
-__kmp_stg_print_max_active_levels( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_dflt_max_active_levels );
-} // __kmp_stg_print_max_active_levels
-
-#if OMP_40_ENABLED
-// -------------------------------------------------------------------------------------------------
-// OpenMP 4.0: OMP_DEFAULT_DEVICE
-// -------------------------------------------------------------------------------------------------
-static void __kmp_stg_parse_default_device(char const *name, char const *value, void *data) {
- __kmp_stg_parse_int(name, value, 0, KMP_MAX_DEFAULT_DEVICE_LIMIT, &__kmp_default_device);
-} // __kmp_stg_parse_default_device
-
-static void __kmp_stg_print_default_device(kmp_str_buf_t *buffer, char const *name, void *data) {
- __kmp_stg_print_int(buffer, name, __kmp_default_device);
-} // __kmp_stg_print_default_device
-#endif
-
-#if OMP_45_ENABLED
-// -------------------------------------------------------------------------------------------------
-// OpenMP 4.5: OMP_MAX_TASK_PRIORITY
-// -------------------------------------------------------------------------------------------------
-static void
-__kmp_stg_parse_max_task_priority(char const *name, char const *value, void *data) {
- __kmp_stg_parse_int(name, value, 0, KMP_MAX_TASK_PRIORITY_LIMIT, &__kmp_max_task_priority);
-} // __kmp_stg_parse_max_task_priority
-
-static void
-__kmp_stg_print_max_task_priority(kmp_str_buf_t *buffer, char const *name, void *data) {
- __kmp_stg_print_int(buffer, name, __kmp_max_task_priority);
-} // __kmp_stg_print_max_task_priority
-#endif // OMP_45_ENABLED
-
-// -------------------------------------------------------------------------------------------------
-// KMP_DISP_NUM_BUFFERS
-// -------------------------------------------------------------------------------------------------
-static void
-__kmp_stg_parse_disp_buffers( char const * name, char const * value, void * data ) {
- if ( TCR_4(__kmp_init_serial) ) {
- KMP_WARNING( EnvSerialWarn, name );
- return;
- } // read value before serial initialization only
- __kmp_stg_parse_int( name, value, 1, KMP_MAX_NTH, & __kmp_dispatch_num_buffers );
-} // __kmp_stg_parse_disp_buffers
-
-static void
-__kmp_stg_print_disp_buffers( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_dispatch_num_buffers );
-} // __kmp_stg_print_disp_buffers
-
-#if KMP_NESTED_HOT_TEAMS
-// -------------------------------------------------------------------------------------------------
-// KMP_HOT_TEAMS_MAX_LEVEL, KMP_HOT_TEAMS_MODE
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_hot_teams_level( char const * name, char const * value, void * data ) {
- if ( TCR_4(__kmp_init_parallel) ) {
- KMP_WARNING( EnvParallelWarn, name );
- return;
- } // read value before first parallel only
- __kmp_stg_parse_int( name, value, 0, KMP_MAX_ACTIVE_LEVELS_LIMIT, & __kmp_hot_teams_max_level );
-} // __kmp_stg_parse_hot_teams_level
-
-static void
-__kmp_stg_print_hot_teams_level( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_hot_teams_max_level );
-} // __kmp_stg_print_hot_teams_level
-
-static void
-__kmp_stg_parse_hot_teams_mode( char const * name, char const * value, void * data ) {
- if ( TCR_4(__kmp_init_parallel) ) {
- KMP_WARNING( EnvParallelWarn, name );
- return;
- } // read value before first parallel only
- __kmp_stg_parse_int( name, value, 0, KMP_MAX_ACTIVE_LEVELS_LIMIT, & __kmp_hot_teams_mode );
-} // __kmp_stg_parse_hot_teams_mode
-
-static void
-__kmp_stg_print_hot_teams_mode( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_hot_teams_mode );
-} // __kmp_stg_print_hot_teams_mode
-
-#endif // KMP_NESTED_HOT_TEAMS
-
-// -------------------------------------------------------------------------------------------------
-// KMP_HANDLE_SIGNALS
-// -------------------------------------------------------------------------------------------------
-
-#if KMP_HANDLE_SIGNALS
-
-static void
-__kmp_stg_parse_handle_signals( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_bool( name, value, & __kmp_handle_signals );
-} // __kmp_stg_parse_handle_signals
-
-static void
-__kmp_stg_print_handle_signals( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_handle_signals );
-} // __kmp_stg_print_handle_signals
-
-#endif // KMP_HANDLE_SIGNALS
-
-// -------------------------------------------------------------------------------------------------
-// KMP_X_DEBUG, KMP_DEBUG, KMP_DEBUG_BUF_*, KMP_DIAG
-// -------------------------------------------------------------------------------------------------
-
-#ifdef KMP_DEBUG
-
-#define KMP_STG_X_DEBUG( x ) \
- static void __kmp_stg_parse_##x##_debug( char const * name, char const * value, void * data ) { \
- __kmp_stg_parse_int( name, value, 0, INT_MAX, & kmp_##x##_debug ); \
- } /* __kmp_stg_parse_x_debug */ \
- static void __kmp_stg_print_##x##_debug( kmp_str_buf_t * buffer, char const * name, void * data ) { \
- __kmp_stg_print_int( buffer, name, kmp_##x##_debug ); \
- } /* __kmp_stg_print_x_debug */
-
-KMP_STG_X_DEBUG( a )
-KMP_STG_X_DEBUG( b )
-KMP_STG_X_DEBUG( c )
-KMP_STG_X_DEBUG( d )
-KMP_STG_X_DEBUG( e )
-KMP_STG_X_DEBUG( f )
-
-#undef KMP_STG_X_DEBUG
-
-static void
-__kmp_stg_parse_debug( char const * name, char const * value, void * data ) {
- int debug = 0;
- __kmp_stg_parse_int( name, value, 0, INT_MAX, & debug );
- if ( kmp_a_debug < debug ) {
- kmp_a_debug = debug;
- }; // if
- if ( kmp_b_debug < debug ) {
- kmp_b_debug = debug;
- }; // if
- if ( kmp_c_debug < debug ) {
- kmp_c_debug = debug;
- }; // if
- if ( kmp_d_debug < debug ) {
- kmp_d_debug = debug;
- }; // if
- if ( kmp_e_debug < debug ) {
- kmp_e_debug = debug;
- }; // if
- if ( kmp_f_debug < debug ) {
- kmp_f_debug = debug;
- }; // if
-} // __kmp_stg_parse_debug
-
-static void
-__kmp_stg_parse_debug_buf( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_bool( name, value, & __kmp_debug_buf );
- // !!! TODO: Move buffer initialization of of this file! It may works incorrectly if
- // KMP_DEBUG_BUF is parsed before KMP_DEBUG_BUF_LINES or KMP_DEBUG_BUF_CHARS.
- if ( __kmp_debug_buf ) {
- int i;
- int elements = __kmp_debug_buf_lines * __kmp_debug_buf_chars;
-
- /* allocate and initialize all entries in debug buffer to empty */
- __kmp_debug_buffer = (char *) __kmp_page_allocate( elements * sizeof( char ) );
- for ( i = 0; i < elements; i += __kmp_debug_buf_chars )
- __kmp_debug_buffer[i] = '\0';
-
- __kmp_debug_count = 0;
- }
- K_DIAG( 1, ( "__kmp_debug_buf = %d\n", __kmp_debug_buf ) );
-} // __kmp_stg_parse_debug_buf
-
-static void
-__kmp_stg_print_debug_buf( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_debug_buf );
-} // __kmp_stg_print_debug_buf
-
-static void
-__kmp_stg_parse_debug_buf_atomic( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_bool( name, value, & __kmp_debug_buf_atomic );
-} // __kmp_stg_parse_debug_buf_atomic
-
-static void
-__kmp_stg_print_debug_buf_atomic( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_debug_buf_atomic );
-} // __kmp_stg_print_debug_buf_atomic
-
-static void
-__kmp_stg_parse_debug_buf_chars( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_int(
- name,
- value,
- KMP_DEBUG_BUF_CHARS_MIN,
- INT_MAX,
- & __kmp_debug_buf_chars
- );
-} // __kmp_stg_debug_parse_buf_chars
-
-static void
-__kmp_stg_print_debug_buf_chars( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_debug_buf_chars );
-} // __kmp_stg_print_debug_buf_chars
-
-static void
-__kmp_stg_parse_debug_buf_lines( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_int(
- name,
- value,
- KMP_DEBUG_BUF_LINES_MIN,
- INT_MAX,
- & __kmp_debug_buf_lines
- );
-} // __kmp_stg_parse_debug_buf_lines
-
-static void
-__kmp_stg_print_debug_buf_lines( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_debug_buf_lines );
-} // __kmp_stg_print_debug_buf_lines
-
-static void
-__kmp_stg_parse_diag( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_int( name, value, 0, INT_MAX, & kmp_diag );
-} // __kmp_stg_parse_diag
-
-static void
-__kmp_stg_print_diag( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, kmp_diag );
-} // __kmp_stg_print_diag
-
-#endif // KMP_DEBUG
-
-// -------------------------------------------------------------------------------------------------
-// KMP_ALIGN_ALLOC
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_align_alloc( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_size(
- name,
- value,
- CACHE_LINE,
- INT_MAX,
- NULL,
- & __kmp_align_alloc,
- 1
- );
-} // __kmp_stg_parse_align_alloc
-
-static void
-__kmp_stg_print_align_alloc( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_size( buffer, name, __kmp_align_alloc );
-} // __kmp_stg_print_align_alloc
-
-// -------------------------------------------------------------------------------------------------
-// KMP_PLAIN_BARRIER, KMP_FORKJOIN_BARRIER, KMP_REDUCTION_BARRIER
-// -------------------------------------------------------------------------------------------------
-
-// TODO: Remove __kmp_barrier_branch_bit_env_name varibale, remove loops from parse and print
-// functions, pass required info through data argument.
-
-static void
-__kmp_stg_parse_barrier_branch_bit( char const * name, char const * value, void * data ) {
- const char *var;
-
- /* ---------- Barrier branch bit control ------------ */
- for ( int i=bs_plain_barrier; i<bs_last_barrier; i++ ) {
- var = __kmp_barrier_branch_bit_env_name[ i ];
- if ( ( strcmp( var, name) == 0 ) && ( value != 0 ) ) {
- char *comma;
-
- comma = (char *) strchr( value, ',' );
- __kmp_barrier_gather_branch_bits[ i ] = ( kmp_uint32 ) __kmp_str_to_int( value, ',' );
- /* is there a specified release parameter? */
- if ( comma == NULL ) {
- __kmp_barrier_release_branch_bits[ i ] = __kmp_barrier_release_bb_dflt;
- } else {
- __kmp_barrier_release_branch_bits[ i ] = (kmp_uint32) __kmp_str_to_int( comma + 1, 0 );
-
- if ( __kmp_barrier_release_branch_bits[ i ] > KMP_MAX_BRANCH_BITS ) {
- __kmp_msg( kmp_ms_warning, KMP_MSG( BarrReleaseValueInvalid, name, comma + 1 ), __kmp_msg_null );
- __kmp_barrier_release_branch_bits[ i ] = __kmp_barrier_release_bb_dflt;
- }
- }
- if ( __kmp_barrier_gather_branch_bits[ i ] > KMP_MAX_BRANCH_BITS ) {
- KMP_WARNING( BarrGatherValueInvalid, name, value );
- KMP_INFORM( Using_uint_Value, name, __kmp_barrier_gather_bb_dflt );
- __kmp_barrier_gather_branch_bits[ i ] = __kmp_barrier_gather_bb_dflt;
- }
- }
- K_DIAG(1, ("%s == %d,%d\n", __kmp_barrier_branch_bit_env_name[ i ], \
- __kmp_barrier_gather_branch_bits [ i ], \
- __kmp_barrier_release_branch_bits [ i ]))
- }
-} // __kmp_stg_parse_barrier_branch_bit
-
-static void
-__kmp_stg_print_barrier_branch_bit( kmp_str_buf_t * buffer, char const * name, void * data ) {
- const char *var;
- for ( int i=bs_plain_barrier; i<bs_last_barrier; i++ ) {
- var = __kmp_barrier_branch_bit_env_name[ i ];
- if ( strcmp( var, name) == 0 ) {
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME_EX(__kmp_barrier_branch_bit_env_name[ i ]);
- } else {
- __kmp_str_buf_print( buffer, " %s='", __kmp_barrier_branch_bit_env_name[ i ] );
- }
- __kmp_str_buf_print( buffer, "%d,%d'\n", __kmp_barrier_gather_branch_bits [ i ], __kmp_barrier_release_branch_bits [ i ]);
- }
- }
-} // __kmp_stg_print_barrier_branch_bit
-
-
-// -------------------------------------------------------------------------------------------------
-// KMP_PLAIN_BARRIER_PATTERN, KMP_FORKJOIN_BARRIER_PATTERN, KMP_REDUCTION_BARRIER_PATTERN
-// -------------------------------------------------------------------------------------------------
-
-// TODO: Remove __kmp_barrier_pattern_name variable, remove loops from parse and print functions,
-// pass required data to functions through data argument.
-
-static void
-__kmp_stg_parse_barrier_pattern( char const * name, char const * value, void * data ) {
- const char *var;
- /* ---------- Barrier method control ------------ */
-
- for ( int i=bs_plain_barrier; i<bs_last_barrier; i++ ) {
- var = __kmp_barrier_pattern_env_name[ i ];
-
- if ( ( strcmp ( var, name ) == 0 ) && ( value != 0 ) ) {
- int j;
- char *comma = (char *) strchr( value, ',' );
-
- /* handle first parameter: gather pattern */
- for ( j = bp_linear_bar; j<bp_last_bar; j++ ) {
- if (__kmp_match_with_sentinel( __kmp_barrier_pattern_name[j], value, 1, ',' )) {
- __kmp_barrier_gather_pattern[ i ] = (kmp_bar_pat_e) j;
- break;
- }
- }
- if ( j == bp_last_bar ) {
- KMP_WARNING( BarrGatherValueInvalid, name, value );
- KMP_INFORM( Using_str_Value, name, __kmp_barrier_pattern_name[ bp_linear_bar ] );
- }
-
- /* handle second parameter: release pattern */
- if ( comma != NULL ) {
- for ( j = bp_linear_bar; j < bp_last_bar; j++ ) {
- if ( __kmp_str_match( __kmp_barrier_pattern_name[j], 1, comma + 1 ) ) {
- __kmp_barrier_release_pattern[ i ] = (kmp_bar_pat_e) j;
- break;
- }
- }
- if (j == bp_last_bar) {
- __kmp_msg( kmp_ms_warning, KMP_MSG( BarrReleaseValueInvalid, name, comma + 1 ), __kmp_msg_null );
- KMP_INFORM( Using_str_Value, name, __kmp_barrier_pattern_name[ bp_linear_bar ] );
- }
- }
- }
- }
-} // __kmp_stg_parse_barrier_pattern
-
-static void
-__kmp_stg_print_barrier_pattern( kmp_str_buf_t * buffer, char const * name, void * data ) {
- const char *var;
- for ( int i=bs_plain_barrier; i<bs_last_barrier; i++ ) {
- var = __kmp_barrier_pattern_env_name[ i ];
- if ( strcmp ( var, name ) == 0 ) {
- int j = __kmp_barrier_gather_pattern [ i ];
- int k = __kmp_barrier_release_pattern [ i ];
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME_EX(__kmp_barrier_pattern_env_name[ i ]);
- } else {
- __kmp_str_buf_print( buffer, " %s='", __kmp_barrier_pattern_env_name[ i ] );
- }
- __kmp_str_buf_print( buffer, "%s,%s'\n", __kmp_barrier_pattern_name [ j ], __kmp_barrier_pattern_name [ k ]);
- }
- }
-} // __kmp_stg_print_barrier_pattern
-
-// -------------------------------------------------------------------------------------------------
-// KMP_ABORT_DELAY
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_abort_delay( char const * name, char const * value, void * data ) {
- // Units of KMP_DELAY_ABORT are seconds, units of __kmp_abort_delay is milliseconds.
- int delay = __kmp_abort_delay / 1000;
- __kmp_stg_parse_int( name, value, 0, INT_MAX / 1000, & delay );
- __kmp_abort_delay = delay * 1000;
-} // __kmp_stg_parse_abort_delay
-
-static void
-__kmp_stg_print_abort_delay( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_abort_delay );
-} // __kmp_stg_print_abort_delay
-
-// -------------------------------------------------------------------------------------------------
-// KMP_CPUINFO_FILE
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_cpuinfo_file( char const * name, char const * value, void * data ) {
- #if KMP_AFFINITY_SUPPORTED
- __kmp_stg_parse_str( name, value, & __kmp_cpuinfo_file );
- K_DIAG( 1, ( "__kmp_cpuinfo_file == %s\n", __kmp_cpuinfo_file ) );
- #endif
-} //__kmp_stg_parse_cpuinfo_file
-
-static void
-__kmp_stg_print_cpuinfo_file( kmp_str_buf_t * buffer, char const * name, void * data ) {
- #if KMP_AFFINITY_SUPPORTED
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME;
- } else {
- __kmp_str_buf_print( buffer, " %s", name );
- }
- if ( __kmp_cpuinfo_file ) {
- __kmp_str_buf_print( buffer, "='%s'\n", __kmp_cpuinfo_file );
- } else {
- __kmp_str_buf_print( buffer, ": %s\n", KMP_I18N_STR( NotDefined ) );
- }
- #endif
-} //__kmp_stg_print_cpuinfo_file
-
-// -------------------------------------------------------------------------------------------------
-// KMP_FORCE_REDUCTION, KMP_DETERMINISTIC_REDUCTION
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_force_reduction( char const * name, char const * value, void * data )
-{
- kmp_stg_fr_data_t * reduction = (kmp_stg_fr_data_t *) data;
- int rc;
-
- rc = __kmp_stg_check_rivals( name, value, reduction->rivals );
- if ( rc ) {
- return;
- }; // if
- if ( reduction->force ) {
- if( value != 0 ) {
- if( __kmp_str_match( "critical", 0, value ) )
- __kmp_force_reduction_method = critical_reduce_block;
- else if( __kmp_str_match( "atomic", 0, value ) )
- __kmp_force_reduction_method = atomic_reduce_block;
- else if( __kmp_str_match( "tree", 0, value ) )
- __kmp_force_reduction_method = tree_reduce_block;
- else {
- KMP_FATAL( UnknownForceReduction, name, value );
- }
- }
- } else {
- __kmp_stg_parse_bool( name, value, & __kmp_determ_red );
- if( __kmp_determ_red ) {
- __kmp_force_reduction_method = tree_reduce_block;
- } else {
- __kmp_force_reduction_method = reduction_method_not_defined;
- }
- }
- K_DIAG( 1, ( "__kmp_force_reduction_method == %d\n", __kmp_force_reduction_method ) );
-} // __kmp_stg_parse_force_reduction
-
-static void
-__kmp_stg_print_force_reduction( kmp_str_buf_t * buffer, char const * name, void * data ) {
-
- kmp_stg_fr_data_t * reduction = (kmp_stg_fr_data_t *) data;
- if ( reduction->force ) {
- if( __kmp_force_reduction_method == critical_reduce_block) {
- __kmp_stg_print_str( buffer, name, "critical");
- } else if ( __kmp_force_reduction_method == atomic_reduce_block ) {
- __kmp_stg_print_str( buffer, name, "atomic");
- } else if ( __kmp_force_reduction_method == tree_reduce_block ) {
- __kmp_stg_print_str( buffer, name, "tree");
- } else {
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME;
- } else {
- __kmp_str_buf_print( buffer, " %s", name );
- }
- __kmp_str_buf_print( buffer, ": %s\n", KMP_I18N_STR( NotDefined ) );
- }
- } else {
- __kmp_stg_print_bool( buffer, name, __kmp_determ_red );
- }
-
-
-} // __kmp_stg_print_force_reduction
-
-// -------------------------------------------------------------------------------------------------
-// KMP_STORAGE_MAP
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_storage_map( char const * name, char const * value, void * data ) {
- if ( __kmp_str_match( "verbose", 1, value ) ) {
- __kmp_storage_map = TRUE;
- __kmp_storage_map_verbose = TRUE;
- __kmp_storage_map_verbose_specified = TRUE;
-
- } else {
- __kmp_storage_map_verbose = FALSE;
- __kmp_stg_parse_bool( name, value, & __kmp_storage_map ); // !!!
- }; // if
-} // __kmp_stg_parse_storage_map
-
-static void
-__kmp_stg_print_storage_map( kmp_str_buf_t * buffer, char const * name, void * data ) {
- if ( __kmp_storage_map_verbose || __kmp_storage_map_verbose_specified ) {
- __kmp_stg_print_str( buffer, name, "verbose" );
- } else {
- __kmp_stg_print_bool( buffer, name, __kmp_storage_map );
- }
-} // __kmp_stg_print_storage_map
-
-// -------------------------------------------------------------------------------------------------
-// KMP_ALL_THREADPRIVATE
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_all_threadprivate( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_int( name, value, __kmp_allThreadsSpecified ? __kmp_max_nth : 1, __kmp_max_nth,
- & __kmp_tp_capacity );
-} // __kmp_stg_parse_all_threadprivate
-
-static void
-__kmp_stg_print_all_threadprivate( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_tp_capacity );
-
-}
-
-// -------------------------------------------------------------------------------------------------
-// KMP_FOREIGN_THREADS_THREADPRIVATE
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_foreign_threads_threadprivate( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_bool( name, value, & __kmp_foreign_tp );
-} // __kmp_stg_parse_foreign_threads_threadprivate
-
-static void
-__kmp_stg_print_foreign_threads_threadprivate( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_foreign_tp );
-} // __kmp_stg_print_foreign_threads_threadprivate
-
-
-// -------------------------------------------------------------------------------------------------
-// KMP_AFFINITY, GOMP_CPU_AFFINITY, KMP_TOPOLOGY_METHOD
-// -------------------------------------------------------------------------------------------------
-
-#if KMP_AFFINITY_SUPPORTED
-//
-// Parse the proc id list. Return TRUE if successful, FALSE otherwise.
-//
-static int
-__kmp_parse_affinity_proc_id_list( const char *var, const char *env,
- const char **nextEnv, char **proclist )
-{
- const char *scan = env;
- const char *next = scan;
- int empty = TRUE;
-
- *proclist = NULL;
-
- for (;;) {
- int start, end, stride;
-
- SKIP_WS(scan);
- next = scan;
- if (*next == '\0') {
- break;
- }
-
- if (*next == '{') {
- int num;
- next++; // skip '{'
- SKIP_WS(next);
- scan = next;
-
- //
- // Read the first integer in the set.
- //
- if ((*next < '0') || (*next > '9')) {
- KMP_WARNING( AffSyntaxError, var );
- return FALSE;
- }
- SKIP_DIGITS(next);
- num = __kmp_str_to_int(scan, *next);
- KMP_ASSERT(num >= 0);
-
- for (;;) {
- //
- // Check for end of set.
- //
- SKIP_WS(next);
- if (*next == '}') {
- next++; // skip '}'
- break;
- }
-
- //
- // Skip optional comma.
- //
- if (*next == ',') {
- next++;
- }
- SKIP_WS(next);
-
- //
- // Read the next integer in the set.
- //
- scan = next;
- if ((*next < '0') || (*next > '9')) {
- KMP_WARNING( AffSyntaxError, var );
- return FALSE;
- }
-
- SKIP_DIGITS(next);
- num = __kmp_str_to_int(scan, *next);
- KMP_ASSERT(num >= 0);
- }
- empty = FALSE;
-
- SKIP_WS(next);
- if (*next == ',') {
- next++;
- }
- scan = next;
- continue;
- }
-
- //
- // Next character is not an integer => end of list
- //
- if ((*next < '0') || (*next > '9')) {
- if (empty) {
- KMP_WARNING( AffSyntaxError, var );
- return FALSE;
- }
- break;
- }
-
- //
- // Read the first integer.
- //
- SKIP_DIGITS(next);
- start = __kmp_str_to_int(scan, *next);
- KMP_ASSERT(start >= 0);
- SKIP_WS(next);
-
- //
- // If this isn't a range, then go on.
- //
- if (*next != '-') {
- empty = FALSE;
-
- //
- // Skip optional comma.
- //
- if (*next == ',') {
- next++;
- }
- scan = next;
- continue;
- }
-
- //
- // This is a range. Skip over the '-' and read in the 2nd int.
- //
- next++; // skip '-'
- SKIP_WS(next);
- scan = next;
- if ((*next < '0') || (*next > '9')) {
- KMP_WARNING( AffSyntaxError, var );
- return FALSE;
- }
- SKIP_DIGITS(next);
- end = __kmp_str_to_int(scan, *next);
- KMP_ASSERT(end >= 0);
-
- //
- // Check for a stride parameter
- //
- stride = 1;
- SKIP_WS(next);
- if (*next == ':') {
- //
- // A stride is specified. Skip over the ':" and read the 3rd int.
- //
- int sign = +1;
- next++; // skip ':'
- SKIP_WS(next);
- scan = next;
- if (*next == '-') {
- sign = -1;
- next++;
- SKIP_WS(next);
- scan = next;
- }
- if ((*next < '0') || (*next > '9')) {
- KMP_WARNING( AffSyntaxError, var );
- return FALSE;
- }
- SKIP_DIGITS(next);
- stride = __kmp_str_to_int(scan, *next);
- KMP_ASSERT(stride >= 0);
- stride *= sign;
- }
-
- //
- // Do some range checks.
- //
- if (stride == 0) {
- KMP_WARNING( AffZeroStride, var );
- return FALSE;
- }
- if (stride > 0) {
- if (start > end) {
- KMP_WARNING( AffStartGreaterEnd, var, start, end );
- return FALSE;
- }
- }
- else {
- if (start < end) {
- KMP_WARNING( AffStrideLessZero, var, start, end );
- return FALSE;
- }
- }
- if ((end - start) / stride > 65536 ) {
- KMP_WARNING( AffRangeTooBig, var, end, start, stride );
- return FALSE;
- }
-
- empty = FALSE;
-
- //
- // Skip optional comma.
- //
- SKIP_WS(next);
- if (*next == ',') {
- next++;
- }
- scan = next;
- }
-
- *nextEnv = next;
-
- {
- int len = next - env;
- char *retlist = (char *)__kmp_allocate((len + 1) * sizeof(char));
- KMP_MEMCPY_S(retlist, (len+1)*sizeof(char), env, len * sizeof(char));
- retlist[len] = '\0';
- *proclist = retlist;
- }
- return TRUE;
-}
-
-
-//
-// If KMP_AFFINITY is specified without a type, then
-// __kmp_affinity_notype should point to its setting.
-//
-static kmp_setting_t *__kmp_affinity_notype = NULL;
-
-static void
-__kmp_parse_affinity_env( char const * name, char const * value,
- enum affinity_type * out_type,
- char ** out_proclist,
- int * out_verbose,
- int * out_warn,
- int * out_respect,
- enum affinity_gran * out_gran,
- int * out_gran_levels,
- int * out_dups,
- int * out_compact,
- int * out_offset
-)
-{
- char * buffer = NULL; // Copy of env var value.
- char * buf = NULL; // Buffer for strtok_r() function.
- char * next = NULL; // end of token / start of next.
- const char * start; // start of current token (for err msgs)
- int count = 0; // Counter of parsed integer numbers.
- int number[ 2 ]; // Parsed numbers.
-
- // Guards.
- int type = 0;
- int proclist = 0;
- int max_proclist = 0;
- int verbose = 0;
- int warnings = 0;
- int respect = 0;
- int gran = 0;
- int dups = 0;
-
- KMP_ASSERT( value != NULL );
-
- if ( TCR_4(__kmp_init_middle) ) {
- KMP_WARNING( EnvMiddleWarn, name );
- __kmp_env_toPrint( name, 0 );
- return;
- }
- __kmp_env_toPrint( name, 1 );
-
- buffer = __kmp_str_format( "%s", value ); // Copy env var to keep original intact.
- buf = buffer;
- SKIP_WS(buf);
-
- // Helper macros.
-
- //
- // If we see a parse error, emit a warning and scan to the next ",".
- //
- // FIXME - there's got to be a better way to print an error
- // message, hopefully without overwritting peices of buf.
- //
- #define EMIT_WARN(skip,errlist) \
- { \
- char ch; \
- if (skip) { \
- SKIP_TO(next, ','); \
- } \
- ch = *next; \
- *next = '\0'; \
- KMP_WARNING errlist; \
- *next = ch; \
- if (skip) { \
- if (ch == ',') next++; \
- } \
- buf = next; \
- }
-
- #define _set_param(_guard,_var,_val) \
- { \
- if ( _guard == 0 ) { \
- _var = _val; \
- } else { \
- EMIT_WARN( FALSE, ( AffParamDefined, name, start ) ); \
- }; \
- ++ _guard; \
- }
-
- #define set_type(val) _set_param( type, *out_type, val )
- #define set_verbose(val) _set_param( verbose, *out_verbose, val )
- #define set_warnings(val) _set_param( warnings, *out_warn, val )
- #define set_respect(val) _set_param( respect, *out_respect, val )
- #define set_dups(val) _set_param( dups, *out_dups, val )
- #define set_proclist(val) _set_param( proclist, *out_proclist, val )
-
- #define set_gran(val,levels) \
- { \
- if ( gran == 0 ) { \
- *out_gran = val; \
- *out_gran_levels = levels; \
- } else { \
- EMIT_WARN( FALSE, ( AffParamDefined, name, start ) ); \
- }; \
- ++ gran; \
- }
-
-# if OMP_40_ENABLED
- KMP_DEBUG_ASSERT( ( __kmp_nested_proc_bind.bind_types != NULL )
- && ( __kmp_nested_proc_bind.used > 0 ) );
-# endif
-
- while ( *buf != '\0' ) {
- start = next = buf;
-
- if (__kmp_match_str("none", buf, (const char **)&next)) {
- set_type( affinity_none );
-# if OMP_40_ENABLED
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
-# endif
- buf = next;
- } else if (__kmp_match_str("scatter", buf, (const char **)&next)) {
- set_type( affinity_scatter );
-# if OMP_40_ENABLED
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
-# endif
- buf = next;
- } else if (__kmp_match_str("compact", buf, (const char **)&next)) {
- set_type( affinity_compact );
-# if OMP_40_ENABLED
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
-# endif
- buf = next;
- } else if (__kmp_match_str("logical", buf, (const char **)&next)) {
- set_type( affinity_logical );
-# if OMP_40_ENABLED
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
-# endif
- buf = next;
- } else if (__kmp_match_str("physical", buf, (const char **)&next)) {
- set_type( affinity_physical );
-# if OMP_40_ENABLED
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
-# endif
- buf = next;
- } else if (__kmp_match_str("explicit", buf, (const char **)&next)) {
- set_type( affinity_explicit );
-# if OMP_40_ENABLED
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
-# endif
- buf = next;
- } else if (__kmp_match_str("balanced", buf, (const char **)&next)) {
- set_type( affinity_balanced );
-# if OMP_40_ENABLED
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
-# endif
- buf = next;
- } else if (__kmp_match_str("disabled", buf, (const char **)&next)) {
- set_type( affinity_disabled );
-# if OMP_40_ENABLED
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
-# endif
- buf = next;
- } else if (__kmp_match_str("verbose", buf, (const char **)&next)) {
- set_verbose( TRUE );
- buf = next;
- } else if (__kmp_match_str("noverbose", buf, (const char **)&next)) {
- set_verbose( FALSE );
- buf = next;
- } else if (__kmp_match_str("warnings", buf, (const char **)&next)) {
- set_warnings( TRUE );
- buf = next;
- } else if (__kmp_match_str("nowarnings", buf, (const char **)&next)) {
- set_warnings( FALSE );
- buf = next;
- } else if (__kmp_match_str("respect", buf, (const char **)&next)) {
- set_respect( TRUE );
- buf = next;
- } else if (__kmp_match_str("norespect", buf, (const char **)&next)) {
- set_respect( FALSE );
- buf = next;
- } else if (__kmp_match_str("duplicates", buf, (const char **)&next)
- || __kmp_match_str("dups", buf, (const char **)&next)) {
- set_dups( TRUE );
- buf = next;
- } else if (__kmp_match_str("noduplicates", buf, (const char **)&next)
- || __kmp_match_str("nodups", buf, (const char **)&next)) {
- set_dups( FALSE );
- buf = next;
- } else if (__kmp_match_str("granularity", buf, (const char **)&next)
- || __kmp_match_str("gran", buf, (const char **)&next)) {
- SKIP_WS(next);
- if (*next != '=') {
- EMIT_WARN( TRUE, ( AffInvalidParam, name, start ) );
- continue;
- }
- next++; // skip '='
- SKIP_WS(next);
-
- buf = next;
- if (__kmp_match_str("fine", buf, (const char **)&next)) {
- set_gran( affinity_gran_fine, -1 );
- buf = next;
- } else if (__kmp_match_str("thread", buf, (const char **)&next)) {
- set_gran( affinity_gran_thread, -1 );
- buf = next;
- } else if (__kmp_match_str("core", buf, (const char **)&next)) {
- set_gran( affinity_gran_core, -1 );
- buf = next;
- } else if (__kmp_match_str("package", buf, (const char **)&next)) {
- set_gran( affinity_gran_package, -1 );
- buf = next;
- } else if (__kmp_match_str("node", buf, (const char **)&next)) {
- set_gran( affinity_gran_node, -1 );
- buf = next;
-# if KMP_GROUP_AFFINITY
- } else if (__kmp_match_str("group", buf, (const char **)&next)) {
- set_gran( affinity_gran_group, -1 );
- buf = next;
-# endif /* KMP_GROUP AFFINITY */
- } else if ((*buf >= '0') && (*buf <= '9')) {
- int n;
- next = buf;
- SKIP_DIGITS(next);
- n = __kmp_str_to_int( buf, *next );
- KMP_ASSERT(n >= 0);
- buf = next;
- set_gran( affinity_gran_default, n );
- } else {
- EMIT_WARN( TRUE, ( AffInvalidParam, name, start ) );
- continue;
- }
- } else if (__kmp_match_str("proclist", buf, (const char **)&next)) {
- char *temp_proclist;
-
- SKIP_WS(next);
- if (*next != '=') {
- EMIT_WARN( TRUE, ( AffInvalidParam, name, start ) );
- continue;
- }
- next++; // skip '='
- SKIP_WS(next);
- if (*next != '[') {
- EMIT_WARN( TRUE, ( AffInvalidParam, name, start ) );
- continue;
- }
- next++; // skip '['
- buf = next;
- if (! __kmp_parse_affinity_proc_id_list(name, buf,
- (const char **)&next, &temp_proclist)) {
- //
- // warning already emitted.
- //
- SKIP_TO(next, ']');
- if (*next == ']') next++;
- SKIP_TO(next, ',');
- if (*next == ',') next++;
- buf = next;
- continue;
- }
- if (*next != ']') {
- EMIT_WARN( TRUE, ( AffInvalidParam, name, start ) );
- continue;
- }
- next++; // skip ']'
- set_proclist( temp_proclist );
- } else if ((*buf >= '0') && (*buf <= '9')) {
- // Parse integer numbers -- permute and offset.
- int n;
- next = buf;
- SKIP_DIGITS(next);
- n = __kmp_str_to_int( buf, *next );
- KMP_ASSERT(n >= 0);
- buf = next;
- if ( count < 2 ) {
- number[ count ] = n;
- } else {
- KMP_WARNING( AffManyParams, name, start );
- }; // if
- ++ count;
- } else {
- EMIT_WARN( TRUE, ( AffInvalidParam, name, start ) );
- continue;
- }
-
- SKIP_WS(next);
- if (*next == ',') {
- next++;
- SKIP_WS(next);
- }
- else if (*next != '\0') {
- const char *temp = next;
- EMIT_WARN( TRUE, ( ParseExtraCharsWarn, name, temp ) );
- continue;
- }
- buf = next;
- } // while
-
- #undef EMIT_WARN
- #undef _set_param
- #undef set_type
- #undef set_verbose
- #undef set_warnings
- #undef set_respect
- #undef set_granularity
-
- __kmp_str_free((const char **) &buffer);
-
- if ( proclist ) {
- if ( ! type ) {
- KMP_WARNING( AffProcListNoType, name );
- __kmp_affinity_type = affinity_explicit;
- }
- else if ( __kmp_affinity_type != affinity_explicit ) {
- KMP_WARNING( AffProcListNotExplicit, name );
- KMP_ASSERT( *out_proclist != NULL );
- KMP_INTERNAL_FREE( *out_proclist );
- *out_proclist = NULL;
- }
- }
- switch ( *out_type ) {
- case affinity_logical:
- case affinity_physical: {
- if ( count > 0 ) {
- *out_offset = number[ 0 ];
- }; // if
- if ( count > 1 ) {
- KMP_WARNING( AffManyParamsForLogic, name, number[ 1 ] );
- }; // if
- } break;
- case affinity_balanced: {
- if ( count > 0 ) {
- *out_compact = number[ 0 ];
- }; // if
- if ( count > 1 ) {
- *out_offset = number[ 1 ];
- }; // if
-
- if ( __kmp_affinity_gran == affinity_gran_default ) {
-#if KMP_ARCH_X86_64 && (KMP_OS_LINUX || KMP_OS_WINDOWS)
- if( __kmp_mic_type != non_mic ) {
- if( __kmp_affinity_verbose || __kmp_affinity_warnings ) {
- KMP_WARNING( AffGranUsing, "KMP_AFFINITY", "fine" );
- }
- __kmp_affinity_gran = affinity_gran_fine;
- } else
-#endif
- {
- if( __kmp_affinity_verbose || __kmp_affinity_warnings ) {
- KMP_WARNING( AffGranUsing, "KMP_AFFINITY", "core" );
- }
- __kmp_affinity_gran = affinity_gran_core;
- }
- }
- } break;
- case affinity_scatter:
- case affinity_compact: {
- if ( count > 0 ) {
- *out_compact = number[ 0 ];
- }; // if
- if ( count > 1 ) {
- *out_offset = number[ 1 ];
- }; // if
- } break;
- case affinity_explicit: {
- if ( *out_proclist == NULL ) {
- KMP_WARNING( AffNoProcList, name );
- __kmp_affinity_type = affinity_none;
- }
- if ( count > 0 ) {
- KMP_WARNING( AffNoParam, name, "explicit" );
- }
- } break;
- case affinity_none: {
- if ( count > 0 ) {
- KMP_WARNING( AffNoParam, name, "none" );
- }; // if
- } break;
- case affinity_disabled: {
- if ( count > 0 ) {
- KMP_WARNING( AffNoParam, name, "disabled" );
- }; // if
- } break;
- case affinity_default: {
- if ( count > 0 ) {
- KMP_WARNING( AffNoParam, name, "default" );
- }; // if
- } break;
- default: {
- KMP_ASSERT( 0 );
- };
- }; // switch
-} // __kmp_parse_affinity_env
-
-static void
-__kmp_stg_parse_affinity( char const * name, char const * value, void * data )
-{
- kmp_setting_t **rivals = (kmp_setting_t **) data;
- int rc;
-
- rc = __kmp_stg_check_rivals( name, value, rivals );
- if ( rc ) {
- return;
- }
-
- __kmp_parse_affinity_env( name, value, & __kmp_affinity_type,
- & __kmp_affinity_proclist, & __kmp_affinity_verbose,
- & __kmp_affinity_warnings, & __kmp_affinity_respect_mask,
- & __kmp_affinity_gran, & __kmp_affinity_gran_levels,
- & __kmp_affinity_dups, & __kmp_affinity_compact,
- & __kmp_affinity_offset );
-
-} // __kmp_stg_parse_affinity
-
-static void
-__kmp_stg_print_affinity( kmp_str_buf_t * buffer, char const * name, void * data ) {
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME_EX(name);
- } else {
- __kmp_str_buf_print( buffer, " %s='", name );
- }
- if ( __kmp_affinity_verbose ) {
- __kmp_str_buf_print( buffer, "%s,", "verbose");
- } else {
- __kmp_str_buf_print( buffer, "%s,", "noverbose");
- }
- if ( __kmp_affinity_warnings ) {
- __kmp_str_buf_print( buffer, "%s,", "warnings");
- } else {
- __kmp_str_buf_print( buffer, "%s,", "nowarnings");
- }
- if ( KMP_AFFINITY_CAPABLE() ) {
- if ( __kmp_affinity_respect_mask ) {
- __kmp_str_buf_print( buffer, "%s,", "respect");
- } else {
- __kmp_str_buf_print( buffer, "%s,", "norespect");
- }
- switch ( __kmp_affinity_gran ) {
- case affinity_gran_default:
- __kmp_str_buf_print( buffer, "%s", "granularity=default,");
- break;
- case affinity_gran_fine:
- __kmp_str_buf_print( buffer, "%s", "granularity=fine,");
- break;
- case affinity_gran_thread:
- __kmp_str_buf_print( buffer, "%s", "granularity=thread,");
- break;
- case affinity_gran_core:
- __kmp_str_buf_print( buffer, "%s", "granularity=core,");
- break;
- case affinity_gran_package:
- __kmp_str_buf_print( buffer, "%s", "granularity=package,");
- break;
- case affinity_gran_node:
- __kmp_str_buf_print( buffer, "%s", "granularity=node,");
- break;
-# if KMP_GROUP_AFFINITY
- case affinity_gran_group:
- __kmp_str_buf_print( buffer, "%s", "granularity=group,");
- break;
-# endif /* KMP_GROUP_AFFINITY */
- }
- if ( __kmp_affinity_dups ) {
- __kmp_str_buf_print( buffer, "%s,", "duplicates");
- } else {
- __kmp_str_buf_print( buffer, "%s,", "noduplicates");
- }
- }
- if ( ! KMP_AFFINITY_CAPABLE() ) {
- __kmp_str_buf_print( buffer, "%s", "disabled" );
- }
- else switch ( __kmp_affinity_type ){
- case affinity_none:
- __kmp_str_buf_print( buffer, "%s", "none");
- break;
- case affinity_physical:
- __kmp_str_buf_print( buffer, "%s,%d", "physical",
- __kmp_affinity_offset );
- break;
- case affinity_logical:
- __kmp_str_buf_print( buffer, "%s,%d", "logical",
- __kmp_affinity_offset );
- break;
- case affinity_compact:
- __kmp_str_buf_print( buffer, "%s,%d,%d", "compact",
- __kmp_affinity_compact, __kmp_affinity_offset );
- break;
- case affinity_scatter:
- __kmp_str_buf_print( buffer, "%s,%d,%d", "scatter",
- __kmp_affinity_compact, __kmp_affinity_offset );
- break;
- case affinity_explicit:
- __kmp_str_buf_print( buffer, "%s=[%s],%s", "proclist",
- __kmp_affinity_proclist, "explicit" );
- break;
- case affinity_balanced:
- __kmp_str_buf_print( buffer, "%s,%d,%d", "balanced",
- __kmp_affinity_compact, __kmp_affinity_offset );
- break;
- case affinity_disabled:
- __kmp_str_buf_print( buffer, "%s", "disabled");
- break;
- case affinity_default:
- __kmp_str_buf_print( buffer, "%s", "default");
- break;
- default:
- __kmp_str_buf_print( buffer, "%s", "<unknown>");
- break;
- }
- __kmp_str_buf_print( buffer, "'\n" );
-} //__kmp_stg_print_affinity
-
-# ifdef KMP_GOMP_COMPAT
-
-static void
-__kmp_stg_parse_gomp_cpu_affinity( char const * name, char const * value, void * data )
-{
- const char * next = NULL;
- char * temp_proclist;
- kmp_setting_t **rivals = (kmp_setting_t **) data;
- int rc;
-
- rc = __kmp_stg_check_rivals( name, value, rivals );
- if ( rc ) {
- return;
- }
-
- if ( TCR_4(__kmp_init_middle) ) {
- KMP_WARNING( EnvMiddleWarn, name );
- __kmp_env_toPrint( name, 0 );
- return;
- }
-
- __kmp_env_toPrint( name, 1 );
-
- if ( __kmp_parse_affinity_proc_id_list( name, value, &next,
- &temp_proclist )) {
- SKIP_WS(next);
- if (*next == '\0') {
- //
- // GOMP_CPU_AFFINITY => granularity=fine,explicit,proclist=...
- //
- __kmp_affinity_proclist = temp_proclist;
- __kmp_affinity_type = affinity_explicit;
- __kmp_affinity_gran = affinity_gran_fine;
-# if OMP_40_ENABLED
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
-# endif
- }
- else {
- KMP_WARNING( AffSyntaxError, name );
- if (temp_proclist != NULL) {
- KMP_INTERNAL_FREE((void *)temp_proclist);
- }
- }
- }
- else {
- //
- // Warning already emitted
- //
- __kmp_affinity_type = affinity_none;
-# if OMP_40_ENABLED
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
-# endif
- }
-} // __kmp_stg_parse_gomp_cpu_affinity
-
-# endif /* KMP_GOMP_COMPAT */
-
-
-# if OMP_40_ENABLED
-
-/*-----------------------------------------------------------------------------
-
-The OMP_PLACES proc id list parser. Here is the grammar:
-
-place_list := place
-place_list := place , place_list
-place := num
-place := place : num
-place := place : num : signed
-place := { subplacelist }
-place := ! place // (lowest priority)
-subplace_list := subplace
-subplace_list := subplace , subplace_list
-subplace := num
-subplace := num : num
-subplace := num : num : signed
-signed := num
-signed := + signed
-signed := - signed
-
------------------------------------------------------------------------------*/
-
-static int
-__kmp_parse_subplace_list( const char *var, const char **scan )
-{
- const char *next;
-
- for (;;) {
- int start, count, stride;
-
- //
- // Read in the starting proc id
- //
- SKIP_WS(*scan);
- if ((**scan < '0') || (**scan > '9')) {
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
- next = *scan;
- SKIP_DIGITS(next);
- start = __kmp_str_to_int(*scan, *next);
- KMP_ASSERT(start >= 0);
- *scan = next;
-
- //
- // valid follow sets are ',' ':' and '}'
- //
- SKIP_WS(*scan);
- if (**scan == '}') {
- break;
- }
- if (**scan == ',') {
- (*scan)++; // skip ','
- continue;
- }
- if (**scan != ':') {
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
- (*scan)++; // skip ':'
-
- //
- // Read count parameter
- //
- SKIP_WS(*scan);
- if ((**scan < '0') || (**scan > '9')) {
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
- next = *scan;
- SKIP_DIGITS(next);
- count = __kmp_str_to_int(*scan, *next);
- KMP_ASSERT(count >= 0);
- *scan = next;
-
- //
- // valid follow sets are ',' ':' and '}'
- //
- SKIP_WS(*scan);
- if (**scan == '}') {
- break;
- }
- if (**scan == ',') {
- (*scan)++; // skip ','
- continue;
- }
- if (**scan != ':') {
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
- (*scan)++; // skip ':'
-
- //
- // Read stride parameter
- //
- int sign = +1;
- for (;;) {
- SKIP_WS(*scan);
- if (**scan == '+') {
- (*scan)++; // skip '+'
- continue;
- }
- if (**scan == '-') {
- sign *= -1;
- (*scan)++; // skip '-'
- continue;
- }
- break;
- }
- SKIP_WS(*scan);
- if ((**scan < '0') || (**scan > '9')) {
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
- next = *scan;
- SKIP_DIGITS(next);
- stride = __kmp_str_to_int(*scan, *next);
- KMP_ASSERT(stride >= 0);
- *scan = next;
- stride *= sign;
-
- //
- // valid follow sets are ',' and '}'
- //
- SKIP_WS(*scan);
- if (**scan == '}') {
- break;
- }
- if (**scan == ',') {
- (*scan)++; // skip ','
- continue;
- }
-
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
- return TRUE;
-}
-
-static int
-__kmp_parse_place( const char *var, const char ** scan )
-{
- const char *next;
-
- //
- // valid follow sets are '{' '!' and num
- //
- SKIP_WS(*scan);
- if (**scan == '{') {
- (*scan)++; // skip '{'
- if (! __kmp_parse_subplace_list(var, scan)) {
- return FALSE;
- }
- if (**scan != '}') {
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
- (*scan)++; // skip '}'
- }
- else if (**scan == '!') {
- (*scan)++; // skip '!'
- return __kmp_parse_place(var, scan); //'!' has lower precedence than ':'
- }
- else if ((**scan >= '0') && (**scan <= '9')) {
- next = *scan;
- SKIP_DIGITS(next);
- int proc = __kmp_str_to_int(*scan, *next);
- KMP_ASSERT(proc >= 0);
- *scan = next;
- }
- else {
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
- return TRUE;
-}
-
-static int
-__kmp_parse_place_list( const char *var, const char *env, char **place_list )
-{
- const char *scan = env;
- const char *next = scan;
-
- for (;;) {
- int start, count, stride;
-
- if (! __kmp_parse_place(var, &scan)) {
- return FALSE;
- }
-
- //
- // valid follow sets are ',' ':' and EOL
- //
- SKIP_WS(scan);
- if (*scan == '\0') {
- break;
- }
- if (*scan == ',') {
- scan++; // skip ','
- continue;
- }
- if (*scan != ':') {
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
- scan++; // skip ':'
-
- //
- // Read count parameter
- //
- SKIP_WS(scan);
- if ((*scan < '0') || (*scan > '9')) {
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
- next = scan;
- SKIP_DIGITS(next);
- count = __kmp_str_to_int(scan, *next);
- KMP_ASSERT(count >= 0);
- scan = next;
-
- //
- // valid follow sets are ',' ':' and EOL
- //
- SKIP_WS(scan);
- if (*scan == '\0') {
- break;
- }
- if (*scan == ',') {
- scan++; // skip ','
- continue;
- }
- if (*scan != ':') {
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
- scan++; // skip ':'
-
- //
- // Read stride parameter
- //
- int sign = +1;
- for (;;) {
- SKIP_WS(scan);
- if (*scan == '+') {
- scan++; // skip '+'
- continue;
- }
- if (*scan == '-') {
- sign *= -1;
- scan++; // skip '-'
- continue;
- }
- break;
- }
- SKIP_WS(scan);
- if ((*scan < '0') || (*scan > '9')) {
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
- next = scan;
- SKIP_DIGITS(next);
- stride = __kmp_str_to_int(scan, *next);
- KMP_ASSERT(stride >= 0);
- scan = next;
- stride *= sign;
-
- //
- // valid follow sets are ',' and EOL
- //
- SKIP_WS(scan);
- if (*scan == '\0') {
- break;
- }
- if (*scan == ',') {
- scan++; // skip ','
- continue;
- }
-
- KMP_WARNING( SyntaxErrorUsing, var, "\"threads\"" );
- return FALSE;
- }
-
- {
- int len = scan - env;
- char *retlist = (char *)__kmp_allocate((len + 1) * sizeof(char));
- KMP_MEMCPY_S(retlist, (len+1)*sizeof(char), env, len * sizeof(char));
- retlist[len] = '\0';
- *place_list = retlist;
- }
- return TRUE;
-}
-
-static void
-__kmp_stg_parse_places( char const * name, char const * value, void * data )
-{
- int count;
- const char *scan = value;
- const char *next = scan;
- const char *kind = "\"threads\"";
- kmp_setting_t **rivals = (kmp_setting_t **) data;
- int rc;
-
- rc = __kmp_stg_check_rivals( name, value, rivals );
- if ( rc ) {
- return;
- }
-
- //
- // If OMP_PROC_BIND is not specified but OMP_PLACES is,
- // then let OMP_PROC_BIND default to true.
- //
- if ( __kmp_nested_proc_bind.bind_types[0] == proc_bind_default ) {
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_true;
- }
-
- //__kmp_affinity_num_places = 0;
-
- if ( __kmp_match_str( "threads", scan, &next ) ) {
- scan = next;
- __kmp_affinity_type = affinity_compact;
- __kmp_affinity_gran = affinity_gran_thread;
- __kmp_affinity_dups = FALSE;
- kind = "\"threads\"";
- }
- else if ( __kmp_match_str( "cores", scan, &next ) ) {
- scan = next;
- __kmp_affinity_type = affinity_compact;
- __kmp_affinity_gran = affinity_gran_core;
- __kmp_affinity_dups = FALSE;
- kind = "\"cores\"";
- }
- else if ( __kmp_match_str( "sockets", scan, &next ) ) {
- scan = next;
- __kmp_affinity_type = affinity_compact;
- __kmp_affinity_gran = affinity_gran_package;
- __kmp_affinity_dups = FALSE;
- kind = "\"sockets\"";
- }
- else {
- if ( __kmp_affinity_proclist != NULL ) {
- KMP_INTERNAL_FREE( (void *)__kmp_affinity_proclist );
- __kmp_affinity_proclist = NULL;
- }
- if ( __kmp_parse_place_list( name, value, &__kmp_affinity_proclist ) ) {
- __kmp_affinity_type = affinity_explicit;
- __kmp_affinity_gran = affinity_gran_fine;
- __kmp_affinity_dups = FALSE;
- if ( __kmp_nested_proc_bind.bind_types[0] == proc_bind_default ) {
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_true;
- }
- }
- return;
- }
-
- if ( __kmp_nested_proc_bind.bind_types[0] == proc_bind_default ) {
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_true;
- }
-
- SKIP_WS(scan);
- if ( *scan == '\0' ) {
- return;
- }
-
- //
- // Parse option count parameter in parentheses
- //
- if ( *scan != '(' ) {
- KMP_WARNING( SyntaxErrorUsing, name, kind );
- return;
- }
- scan++; // skip '('
-
- SKIP_WS(scan);
- next = scan;
- SKIP_DIGITS(next);
- count = __kmp_str_to_int(scan, *next);
- KMP_ASSERT(count >= 0);
- scan = next;
-
- SKIP_WS(scan);
- if ( *scan != ')' ) {
- KMP_WARNING( SyntaxErrorUsing, name, kind );
- return;
- }
- scan++; // skip ')'
-
- SKIP_WS(scan);
- if ( *scan != '\0' ) {
- KMP_WARNING( ParseExtraCharsWarn, name, scan );
- }
- __kmp_affinity_num_places = count;
-}
-
-static void
-__kmp_stg_print_places( kmp_str_buf_t * buffer, char const * name,
- void * data )
-{
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME;
- } else {
- __kmp_str_buf_print( buffer, " %s", name );
- }
- if ( ( __kmp_nested_proc_bind.used == 0 )
- || ( __kmp_nested_proc_bind.bind_types == NULL )
- || ( __kmp_nested_proc_bind.bind_types[0] == proc_bind_false ) ) {
- __kmp_str_buf_print( buffer, ": %s\n", KMP_I18N_STR( NotDefined ) );
- }
- else if ( __kmp_affinity_type == affinity_explicit ) {
- if ( __kmp_affinity_proclist != NULL ) {
- __kmp_str_buf_print( buffer, "='%s'\n", __kmp_affinity_proclist );
- }
- else {
- __kmp_str_buf_print( buffer, ": %s\n", KMP_I18N_STR( NotDefined ) );
- }
- }
- else if ( __kmp_affinity_type == affinity_compact ) {
- int num;
- if ( __kmp_affinity_num_masks > 0 ) {
- num = __kmp_affinity_num_masks;
- }
- else if ( __kmp_affinity_num_places > 0 ) {
- num = __kmp_affinity_num_places;
- }
- else {
- num = 0;
- }
- if ( __kmp_affinity_gran == affinity_gran_thread ) {
- if ( num > 0 ) {
- __kmp_str_buf_print( buffer, "='threads(%d)'\n", num );
- }
- else {
- __kmp_str_buf_print( buffer, "='threads'\n" );
- }
- }
- else if ( __kmp_affinity_gran == affinity_gran_core ) {
- if ( num > 0 ) {
- __kmp_str_buf_print( buffer, "='cores(%d)' \n", num );
- }
- else {
- __kmp_str_buf_print( buffer, "='cores'\n" );
- }
- }
- else if ( __kmp_affinity_gran == affinity_gran_package ) {
- if ( num > 0 ) {
- __kmp_str_buf_print( buffer, "='sockets(%d)'\n", num );
- }
- else {
- __kmp_str_buf_print( buffer, "='sockets'\n" );
- }
- }
- else {
- __kmp_str_buf_print( buffer, ": %s\n", KMP_I18N_STR( NotDefined ) );
- }
- }
- else {
- __kmp_str_buf_print( buffer, ": %s\n", KMP_I18N_STR( NotDefined ) );
- }
-}
-
-# endif /* OMP_40_ENABLED */
-
-# if (! OMP_40_ENABLED)
-
-static void
-__kmp_stg_parse_proc_bind( char const * name, char const * value, void * data )
-{
- int enabled;
- kmp_setting_t **rivals = (kmp_setting_t **) data;
- int rc;
-
- rc = __kmp_stg_check_rivals( name, value, rivals );
- if ( rc ) {
- return;
- }
-
- //
- // in OMP 3.1, OMP_PROC_BIND is strictly a boolean
- //
- __kmp_stg_parse_bool( name, value, & enabled );
- if ( enabled ) {
- //
- // OMP_PROC_BIND => granularity=fine,scatter on MIC
- // OMP_PROC_BIND => granularity=core,scatter elsewhere
- //
- __kmp_affinity_type = affinity_scatter;
-# if KMP_ARCH_X86_64 && (KMP_OS_LINUX || KMP_OS_WINDOWS)
- if( __kmp_mic_type != non_mic )
- __kmp_affinity_gran = affinity_gran_fine;
- else
-# endif
- __kmp_affinity_gran = affinity_gran_core;
- }
- else {
- __kmp_affinity_type = affinity_none;
- }
-} // __kmp_parse_proc_bind
-
-# endif /* if (! OMP_40_ENABLED) */
-
-
-static void
-__kmp_stg_parse_topology_method( char const * name, char const * value,
- void * data ) {
- if ( __kmp_str_match( "all", 1, value ) ) {
- __kmp_affinity_top_method = affinity_top_method_all;
- }
-# if KMP_ARCH_X86 || KMP_ARCH_X86_64
- else if ( __kmp_str_match( "x2apic id", 9, value )
- || __kmp_str_match( "x2apic_id", 9, value )
- || __kmp_str_match( "x2apic-id", 9, value )
- || __kmp_str_match( "x2apicid", 8, value )
- || __kmp_str_match( "cpuid leaf 11", 13, value )
- || __kmp_str_match( "cpuid_leaf_11", 13, value )
- || __kmp_str_match( "cpuid-leaf-11", 13, value )
- || __kmp_str_match( "cpuid leaf11", 12, value )
- || __kmp_str_match( "cpuid_leaf11", 12, value )
- || __kmp_str_match( "cpuid-leaf11", 12, value )
- || __kmp_str_match( "cpuidleaf 11", 12, value )
- || __kmp_str_match( "cpuidleaf_11", 12, value )
- || __kmp_str_match( "cpuidleaf-11", 12, value )
- || __kmp_str_match( "cpuidleaf11", 11, value )
- || __kmp_str_match( "cpuid 11", 8, value )
- || __kmp_str_match( "cpuid_11", 8, value )
- || __kmp_str_match( "cpuid-11", 8, value )
- || __kmp_str_match( "cpuid11", 7, value )
- || __kmp_str_match( "leaf 11", 7, value )
- || __kmp_str_match( "leaf_11", 7, value )
- || __kmp_str_match( "leaf-11", 7, value )
- || __kmp_str_match( "leaf11", 6, value ) ) {
- __kmp_affinity_top_method = affinity_top_method_x2apicid;
- }
- else if ( __kmp_str_match( "apic id", 7, value )
- || __kmp_str_match( "apic_id", 7, value )
- || __kmp_str_match( "apic-id", 7, value )
- || __kmp_str_match( "apicid", 6, value )
- || __kmp_str_match( "cpuid leaf 4", 12, value )
- || __kmp_str_match( "cpuid_leaf_4", 12, value )
- || __kmp_str_match( "cpuid-leaf-4", 12, value )
- || __kmp_str_match( "cpuid leaf4", 11, value )
- || __kmp_str_match( "cpuid_leaf4", 11, value )
- || __kmp_str_match( "cpuid-leaf4", 11, value )
- || __kmp_str_match( "cpuidleaf 4", 11, value )
- || __kmp_str_match( "cpuidleaf_4", 11, value )
- || __kmp_str_match( "cpuidleaf-4", 11, value )
- || __kmp_str_match( "cpuidleaf4", 10, value )
- || __kmp_str_match( "cpuid 4", 7, value )
- || __kmp_str_match( "cpuid_4", 7, value )
- || __kmp_str_match( "cpuid-4", 7, value )
- || __kmp_str_match( "cpuid4", 6, value )
- || __kmp_str_match( "leaf 4", 6, value )
- || __kmp_str_match( "leaf_4", 6, value )
- || __kmp_str_match( "leaf-4", 6, value )
- || __kmp_str_match( "leaf4", 5, value ) ) {
- __kmp_affinity_top_method = affinity_top_method_apicid;
- }
-# endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
- else if ( __kmp_str_match( "/proc/cpuinfo", 2, value )
- || __kmp_str_match( "cpuinfo", 5, value )) {
- __kmp_affinity_top_method = affinity_top_method_cpuinfo;
- }
-# if KMP_GROUP_AFFINITY
- else if ( __kmp_str_match( "group", 1, value ) ) {
- __kmp_affinity_top_method = affinity_top_method_group;
- }
-# endif /* KMP_GROUP_AFFINITY */
- else if ( __kmp_str_match( "flat", 1, value ) ) {
- __kmp_affinity_top_method = affinity_top_method_flat;
- }
-# if KMP_USE_HWLOC
- else if ( __kmp_str_match( "hwloc", 1, value) ) {
- __kmp_affinity_top_method = affinity_top_method_hwloc;
- }
-# endif
- else {
- KMP_WARNING( StgInvalidValue, name, value );
- }
-} // __kmp_stg_parse_topology_method
-
-static void
-__kmp_stg_print_topology_method( kmp_str_buf_t * buffer, char const * name,
- void * data ) {
-# if KMP_DEBUG
- char const * value = NULL;
-
- switch ( __kmp_affinity_top_method ) {
- case affinity_top_method_default:
- value = "default";
- break;
-
- case affinity_top_method_all:
- value = "all";
- break;
-
-# if KMP_ARCH_X86 || KMP_ARCH_X86_64
- case affinity_top_method_x2apicid:
- value = "x2APIC id";
- break;
-
- case affinity_top_method_apicid:
- value = "APIC id";
- break;
-# endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
-
- case affinity_top_method_cpuinfo:
- value = "cpuinfo";
- break;
-
-# if KMP_GROUP_AFFINITY
- case affinity_top_method_group:
- value = "group";
- break;
-# endif /* KMP_GROUP_AFFINITY */
-
- case affinity_top_method_flat:
- value = "flat";
- break;
- }
-
- if ( value != NULL ) {
- __kmp_stg_print_str( buffer, name, value );
- }
-# endif /* KMP_DEBUG */
-} // __kmp_stg_print_topology_method
-
-#endif /* KMP_AFFINITY_SUPPORTED */
-
-
-#if OMP_40_ENABLED
-
-//
-// OMP_PROC_BIND / bind-var is functional on all 4.0 builds, including OS X*
-// OMP_PLACES / place-partition-var is not.
-//
-static void
-__kmp_stg_parse_proc_bind( char const * name, char const * value, void * data )
-{
- kmp_setting_t **rivals = (kmp_setting_t **) data;
- int rc;
-
- rc = __kmp_stg_check_rivals( name, value, rivals );
- if ( rc ) {
- return;
- }
-
- //
- // in OMP 4.0 OMP_PROC_BIND is a vector of proc_bind types.
- //
- KMP_DEBUG_ASSERT( (__kmp_nested_proc_bind.bind_types != NULL)
- && ( __kmp_nested_proc_bind.used > 0 ) );
-
- const char *buf = value;
- const char *next;
- int num;
- SKIP_WS( buf );
- if ( (*buf >= '0') && (*buf <= '9') ) {
- next = buf;
- SKIP_DIGITS( next );
- num = __kmp_str_to_int( buf, *next );
- KMP_ASSERT( num >= 0 );
- buf = next;
- SKIP_WS( buf );
- }
- else {
- num = -1;
- }
-
- next = buf;
- if ( __kmp_match_str( "disabled", buf, &next ) ) {
- buf = next;
- SKIP_WS( buf );
-# if KMP_AFFINITY_SUPPORTED
- __kmp_affinity_type = affinity_disabled;
-# endif /* KMP_AFFINITY_SUPPORTED */
- __kmp_nested_proc_bind.used = 1;
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
- }
- else if ( ( num == (int)proc_bind_false )
- || __kmp_match_str( "false", buf, &next ) ) {
- buf = next;
- SKIP_WS( buf );
-# if KMP_AFFINITY_SUPPORTED
- __kmp_affinity_type = affinity_none;
-# endif /* KMP_AFFINITY_SUPPORTED */
- __kmp_nested_proc_bind.used = 1;
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
- }
- else if ( ( num == (int)proc_bind_true )
- || __kmp_match_str( "true", buf, &next ) ) {
- buf = next;
- SKIP_WS( buf );
- __kmp_nested_proc_bind.used = 1;
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_true;
- }
- else {
- //
- // Count the number of values in the env var string
- //
- const char *scan;
- int nelem = 1;
- for ( scan = buf; *scan != '\0'; scan++ ) {
- if ( *scan == ',' ) {
- nelem++;
- }
- }
-
- //
- // Create / expand the nested proc_bind array as needed
- //
- if ( __kmp_nested_proc_bind.size < nelem ) {
- __kmp_nested_proc_bind.bind_types = (kmp_proc_bind_t *)
- KMP_INTERNAL_REALLOC( __kmp_nested_proc_bind.bind_types,
- sizeof(kmp_proc_bind_t) * nelem );
- if ( __kmp_nested_proc_bind.bind_types == NULL ) {
- KMP_FATAL( MemoryAllocFailed );
- }
- __kmp_nested_proc_bind.size = nelem;
- }
- __kmp_nested_proc_bind.used = nelem;
-
- //
- // Save values in the nested proc_bind array
- //
- int i = 0;
- for (;;) {
- enum kmp_proc_bind_t bind;
-
- if ( ( num == (int)proc_bind_master )
- || __kmp_match_str( "master", buf, &next ) ) {
- buf = next;
- SKIP_WS( buf );
- bind = proc_bind_master;
- }
- else if ( ( num == (int)proc_bind_close )
- || __kmp_match_str( "close", buf, &next ) ) {
- buf = next;
- SKIP_WS( buf );
- bind = proc_bind_close;
- }
- else if ( ( num == (int)proc_bind_spread )
- || __kmp_match_str( "spread", buf, &next ) ) {
- buf = next;
- SKIP_WS( buf );
- bind = proc_bind_spread;
- }
- else {
- KMP_WARNING( StgInvalidValue, name, value );
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
- __kmp_nested_proc_bind.used = 1;
- return;
- }
-
- __kmp_nested_proc_bind.bind_types[i++] = bind;
- if ( i >= nelem ) {
- break;
- }
- KMP_DEBUG_ASSERT( *buf == ',' );
- buf++;
- SKIP_WS( buf );
-
- //
- // Read next value if it was specified as an integer
- //
- if ( (*buf >= '0') && (*buf <= '9') ) {
- next = buf;
- SKIP_DIGITS( next );
- num = __kmp_str_to_int( buf, *next );
- KMP_ASSERT( num >= 0 );
- buf = next;
- SKIP_WS( buf );
- }
- else {
- num = -1;
- }
- }
- SKIP_WS( buf );
- }
- if ( *buf != '\0' ) {
- KMP_WARNING( ParseExtraCharsWarn, name, buf );
- }
-}
-
-
-static void
-__kmp_stg_print_proc_bind( kmp_str_buf_t * buffer, char const * name,
- void * data )
-{
- int nelem = __kmp_nested_proc_bind.used;
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME;
- } else {
- __kmp_str_buf_print( buffer, " %s", name );
- }
- if ( nelem == 0 ) {
- __kmp_str_buf_print( buffer, ": %s\n", KMP_I18N_STR( NotDefined ) );
- }
- else {
- int i;
- __kmp_str_buf_print( buffer, "='", name );
- for ( i = 0; i < nelem; i++ ) {
- switch ( __kmp_nested_proc_bind.bind_types[i] ) {
- case proc_bind_false:
- __kmp_str_buf_print( buffer, "false" );
- break;
-
- case proc_bind_true:
- __kmp_str_buf_print( buffer, "true" );
- break;
-
- case proc_bind_master:
- __kmp_str_buf_print( buffer, "master" );
- break;
-
- case proc_bind_close:
- __kmp_str_buf_print( buffer, "close" );
- break;
-
- case proc_bind_spread:
- __kmp_str_buf_print( buffer, "spread" );
- break;
-
- case proc_bind_intel:
- __kmp_str_buf_print( buffer, "intel" );
- break;
-
- case proc_bind_default:
- __kmp_str_buf_print( buffer, "default" );
- break;
- }
- if ( i < nelem - 1 ) {
- __kmp_str_buf_print( buffer, "," );
- }
- }
- __kmp_str_buf_print( buffer, "'\n" );
- }
-}
-
-#endif /* OMP_40_ENABLED */
-
-
-// -------------------------------------------------------------------------------------------------
-// OMP_DYNAMIC
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_omp_dynamic( char const * name, char const * value, void * data )
-{
- __kmp_stg_parse_bool( name, value, & (__kmp_global.g.g_dynamic) );
-} // __kmp_stg_parse_omp_dynamic
-
-static void
-__kmp_stg_print_omp_dynamic( kmp_str_buf_t * buffer, char const * name, void * data )
-{
- __kmp_stg_print_bool( buffer, name, __kmp_global.g.g_dynamic );
-} // __kmp_stg_print_omp_dynamic
-
-static void
-__kmp_stg_parse_kmp_dynamic_mode( char const * name, char const * value, void * data )
-{
- if ( TCR_4(__kmp_init_parallel) ) {
- KMP_WARNING( EnvParallelWarn, name );
- __kmp_env_toPrint( name, 0 );
- return;
- }
-#ifdef USE_LOAD_BALANCE
- else if ( __kmp_str_match( "load balance", 2, value )
- || __kmp_str_match( "load_balance", 2, value )
- || __kmp_str_match( "load-balance", 2, value )
- || __kmp_str_match( "loadbalance", 2, value )
- || __kmp_str_match( "balance", 1, value ) ) {
- __kmp_global.g.g_dynamic_mode = dynamic_load_balance;
- }
-#endif /* USE_LOAD_BALANCE */
- else if ( __kmp_str_match( "thread limit", 1, value )
- || __kmp_str_match( "thread_limit", 1, value )
- || __kmp_str_match( "thread-limit", 1, value )
- || __kmp_str_match( "threadlimit", 1, value )
- || __kmp_str_match( "limit", 2, value ) ) {
- __kmp_global.g.g_dynamic_mode = dynamic_thread_limit;
- }
- else if ( __kmp_str_match( "random", 1, value ) ) {
- __kmp_global.g.g_dynamic_mode = dynamic_random;
- }
- else {
- KMP_WARNING( StgInvalidValue, name, value );
- }
-} //__kmp_stg_parse_kmp_dynamic_mode
-
-static void
-__kmp_stg_print_kmp_dynamic_mode( kmp_str_buf_t * buffer, char const * name, void * data )
-{
-#if KMP_DEBUG
- if ( __kmp_global.g.g_dynamic_mode == dynamic_default ) {
- __kmp_str_buf_print( buffer, " %s: %s \n", name, KMP_I18N_STR( NotDefined ) );
- }
-# ifdef USE_LOAD_BALANCE
- else if ( __kmp_global.g.g_dynamic_mode == dynamic_load_balance ) {
- __kmp_stg_print_str( buffer, name, "load balance" );
- }
-# endif /* USE_LOAD_BALANCE */
- else if ( __kmp_global.g.g_dynamic_mode == dynamic_thread_limit ) {
- __kmp_stg_print_str( buffer, name, "thread limit" );
- }
- else if ( __kmp_global.g.g_dynamic_mode == dynamic_random ) {
- __kmp_stg_print_str( buffer, name, "random" );
- }
- else {
- KMP_ASSERT(0);
- }
-#endif /* KMP_DEBUG */
-} // __kmp_stg_print_kmp_dynamic_mode
-
-
-#ifdef USE_LOAD_BALANCE
-
-// -------------------------------------------------------------------------------------------------
-// KMP_LOAD_BALANCE_INTERVAL
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_ld_balance_interval( char const * name, char const * value, void * data )
-{
- double interval = __kmp_convert_to_double( value );
- if ( interval >= 0 ) {
- __kmp_load_balance_interval = interval;
- } else {
- KMP_WARNING( StgInvalidValue, name, value );
- }; // if
-} // __kmp_stg_parse_load_balance_interval
-
-static void
-__kmp_stg_print_ld_balance_interval( kmp_str_buf_t * buffer, char const * name, void * data ) {
-#if KMP_DEBUG
- __kmp_str_buf_print( buffer, " %s=%8.6f\n", name, __kmp_load_balance_interval );
-#endif /* KMP_DEBUG */
-} // __kmp_stg_print_load_balance_interval
-
-#endif /* USE_LOAD_BALANCE */
-
-// -------------------------------------------------------------------------------------------------
-// KMP_INIT_AT_FORK
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_init_at_fork( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_bool( name, value, & __kmp_need_register_atfork );
- if ( __kmp_need_register_atfork ) {
- __kmp_need_register_atfork_specified = TRUE;
- };
-} // __kmp_stg_parse_init_at_fork
-
-static void
-__kmp_stg_print_init_at_fork( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_need_register_atfork_specified );
-} // __kmp_stg_print_init_at_fork
-
-// -------------------------------------------------------------------------------------------------
-// KMP_SCHEDULE
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_schedule( char const * name, char const * value, void * data ) {
-
- if ( value != NULL ) {
- size_t length = KMP_STRLEN( value );
- if ( length > INT_MAX ) {
- KMP_WARNING( LongValue, name );
- } else {
- char *semicolon;
- if( value[ length - 1 ] == '"' || value[ length -1 ] == '\'' )
- KMP_WARNING( UnbalancedQuotes, name );
- do {
- char sentinel;
-
- semicolon = (char *) strchr( value, ';' );
- if( *value && semicolon != value ) {
- char *comma = (char *) strchr( value, ',' );
-
- if ( comma ) {
- ++comma;
- sentinel = ',';
- } else
- sentinel = ';';
- if ( !__kmp_strcasecmp_with_sentinel( "static", value, sentinel ) ) {
- if( !__kmp_strcasecmp_with_sentinel( "greedy", comma, ';' ) ) {
- __kmp_static = kmp_sch_static_greedy;
- continue;
- } else if( !__kmp_strcasecmp_with_sentinel( "balanced", comma, ';' ) ) {
- __kmp_static = kmp_sch_static_balanced;
- continue;
- }
- } else if ( !__kmp_strcasecmp_with_sentinel( "guided", value, sentinel ) ) {
- if ( !__kmp_strcasecmp_with_sentinel( "iterative", comma, ';' ) ) {
- __kmp_guided = kmp_sch_guided_iterative_chunked;
- continue;
- } else if ( !__kmp_strcasecmp_with_sentinel( "analytical", comma, ';' ) ) {
- /* analytical not allowed for too many threads */
- __kmp_guided = kmp_sch_guided_analytical_chunked;
- continue;
- }
- }
- KMP_WARNING( InvalidClause, name, value );
- } else
- KMP_WARNING( EmptyClause, name );
- } while ( (value = semicolon ? semicolon + 1 : NULL) );
- }
- }; // if
-
-} // __kmp_stg_parse__schedule
-
-static void
-__kmp_stg_print_schedule( kmp_str_buf_t * buffer, char const * name, void * data ) {
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME_EX(name);
- } else {
- __kmp_str_buf_print( buffer, " %s='", name );
- }
- if ( __kmp_static == kmp_sch_static_greedy ) {
- __kmp_str_buf_print( buffer, "%s", "static,greedy");
- } else if ( __kmp_static == kmp_sch_static_balanced ) {
- __kmp_str_buf_print ( buffer, "%s", "static,balanced");
- }
- if ( __kmp_guided == kmp_sch_guided_iterative_chunked ) {
- __kmp_str_buf_print( buffer, ";%s'\n", "guided,iterative");
- } else if ( __kmp_guided == kmp_sch_guided_analytical_chunked ) {
- __kmp_str_buf_print( buffer, ";%s'\n", "guided,analytical");
- }
-} // __kmp_stg_print_schedule
-
-// -------------------------------------------------------------------------------------------------
-// OMP_SCHEDULE
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_omp_schedule( char const * name, char const * value, void * data )
-{
- size_t length;
- if( value ) {
- length = KMP_STRLEN( value );
- if( length ) {
- char *comma = (char *) strchr( value, ',' );
- if( value[ length - 1 ] == '"' || value[ length -1 ] == '\'')
- KMP_WARNING( UnbalancedQuotes, name );
- /* get the specified scheduling style */
- if (!__kmp_strcasecmp_with_sentinel("dynamic", value, ',')) /* DYNAMIC */
- __kmp_sched = kmp_sch_dynamic_chunked;
- else if (!__kmp_strcasecmp_with_sentinel("guided", value, ',')) /* GUIDED */
- __kmp_sched = kmp_sch_guided_chunked;
-// AC: TODO: add AUTO schedule, and pprobably remove TRAPEZOIDAL (OMP 3.0 does not allow it)
- else if (!__kmp_strcasecmp_with_sentinel("auto", value, ',')) { /* AUTO */
- __kmp_sched = kmp_sch_auto;
- if( comma ) {
- __kmp_msg( kmp_ms_warning, KMP_MSG( IgnoreChunk, name, comma ), __kmp_msg_null );
- comma = NULL;
- }
- }
- else if (!__kmp_strcasecmp_with_sentinel("trapezoidal", value, ',')) /* TRAPEZOIDAL */
- __kmp_sched = kmp_sch_trapezoidal;
- else if (!__kmp_strcasecmp_with_sentinel("static", value, ',')) /* STATIC */
- __kmp_sched = kmp_sch_static;
-#if KMP_STATIC_STEAL_ENABLED
- else if (!__kmp_strcasecmp_with_sentinel("static_steal", value, ','))
- __kmp_sched = kmp_sch_static_steal;
-#endif
- else {
- KMP_WARNING( StgInvalidValue, name, value );
- value = NULL; /* skip processing of comma */
- }
- if( value && comma ) {
- __kmp_env_chunk = TRUE;
-
- if(__kmp_sched == kmp_sch_static)
- __kmp_sched = kmp_sch_static_chunked;
- ++comma;
- __kmp_chunk = __kmp_str_to_int( comma, 0 );
- if ( __kmp_chunk < 1 ) {
- __kmp_chunk = KMP_DEFAULT_CHUNK;
- __kmp_msg( kmp_ms_warning, KMP_MSG( InvalidChunk, name, comma ), __kmp_msg_null );
- KMP_INFORM( Using_int_Value, name, __kmp_chunk );
-// AC: next block commented out until KMP_DEFAULT_CHUNK != KMP_MIN_CHUNK (to improve code coverage :)
-// The default chunk size is 1 according to standard, thus making KMP_MIN_CHUNK not 1 we would introduce mess:
-// wrong chunk becomes 1, but it will be impossible to explicitely set 1, because it becomes KMP_MIN_CHUNK...
-// } else if ( __kmp_chunk < KMP_MIN_CHUNK ) {
-// __kmp_chunk = KMP_MIN_CHUNK;
- } else if ( __kmp_chunk > KMP_MAX_CHUNK ) {
- __kmp_chunk = KMP_MAX_CHUNK;
- __kmp_msg( kmp_ms_warning, KMP_MSG( LargeChunk, name, comma ), __kmp_msg_null );
- KMP_INFORM( Using_int_Value, name, __kmp_chunk );
- }
- } else
- __kmp_env_chunk = FALSE;
- } else
- KMP_WARNING( EmptyString, name );
- }
- K_DIAG(1, ("__kmp_static == %d\n", __kmp_static))
- K_DIAG(1, ("__kmp_guided == %d\n", __kmp_guided))
- K_DIAG(1, ("__kmp_sched == %d\n", __kmp_sched))
- K_DIAG(1, ("__kmp_chunk == %d\n", __kmp_chunk))
-} // __kmp_stg_parse_omp_schedule
-
-static void
-__kmp_stg_print_omp_schedule( kmp_str_buf_t * buffer, char const * name, void * data ) {
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME_EX(name);
- } else {
- __kmp_str_buf_print( buffer, " %s='", name );
- }
- if ( __kmp_chunk ) {
- switch ( __kmp_sched ) {
- case kmp_sch_dynamic_chunked:
- __kmp_str_buf_print( buffer, "%s,%d'\n", "dynamic", __kmp_chunk);
- break;
- case kmp_sch_guided_iterative_chunked:
- case kmp_sch_guided_analytical_chunked:
- __kmp_str_buf_print( buffer, "%s,%d'\n", "guided", __kmp_chunk);
- break;
- case kmp_sch_trapezoidal:
- __kmp_str_buf_print( buffer, "%s,%d'\n", "trapezoidal", __kmp_chunk);
- break;
- case kmp_sch_static:
- case kmp_sch_static_chunked:
- case kmp_sch_static_balanced:
- case kmp_sch_static_greedy:
- __kmp_str_buf_print( buffer, "%s,%d'\n", "static", __kmp_chunk);
- break;
- case kmp_sch_static_steal:
- __kmp_str_buf_print( buffer, "%s,%d'\n", "static_steal", __kmp_chunk);
- break;
- case kmp_sch_auto:
- __kmp_str_buf_print( buffer, "%s,%d'\n", "auto", __kmp_chunk);
- break;
- }
- } else {
- switch ( __kmp_sched ) {
- case kmp_sch_dynamic_chunked:
- __kmp_str_buf_print( buffer, "%s'\n", "dynamic");
- break;
- case kmp_sch_guided_iterative_chunked:
- case kmp_sch_guided_analytical_chunked:
- __kmp_str_buf_print( buffer, "%s'\n", "guided");
- break;
- case kmp_sch_trapezoidal:
- __kmp_str_buf_print( buffer, "%s'\n", "trapezoidal");
- break;
- case kmp_sch_static:
- case kmp_sch_static_chunked:
- case kmp_sch_static_balanced:
- case kmp_sch_static_greedy:
- __kmp_str_buf_print( buffer, "%s'\n", "static");
- break;
- case kmp_sch_static_steal:
- __kmp_str_buf_print( buffer, "%s'\n", "static_steal");
- break;
- case kmp_sch_auto:
- __kmp_str_buf_print( buffer, "%s'\n", "auto");
- break;
- }
- }
-} // __kmp_stg_print_omp_schedule
-
-// -------------------------------------------------------------------------------------------------
-// KMP_ATOMIC_MODE
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_atomic_mode( char const * name, char const * value, void * data ) {
- // Modes: 0 -- do not change default; 1 -- Intel perf mode, 2 -- GOMP compatibility mode.
- int mode = 0;
- int max = 1;
- #ifdef KMP_GOMP_COMPAT
- max = 2;
- #endif /* KMP_GOMP_COMPAT */
- __kmp_stg_parse_int( name, value, 0, max, & mode );
- // TODO; parse_int is not very suitable for this case. In case of overflow it is better to use
- // 0 rather that max value.
- if ( mode > 0 ) {
- __kmp_atomic_mode = mode;
- }; // if
-} // __kmp_stg_parse_atomic_mode
-
-static void
-__kmp_stg_print_atomic_mode( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_atomic_mode );
-} // __kmp_stg_print_atomic_mode
-
-
-// -------------------------------------------------------------------------------------------------
-// KMP_CONSISTENCY_CHECK
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_consistency_check( char const * name, char const * value, void * data ) {
- if ( ! __kmp_strcasecmp_with_sentinel( "all", value, 0 ) ) {
- // Note, this will not work from kmp_set_defaults because th_cons stack was not allocated
- // for existed thread(s) thus the first __kmp_push_<construct> will break with assertion.
- // TODO: allocate th_cons if called from kmp_set_defaults.
- __kmp_env_consistency_check = TRUE;
- } else if ( ! __kmp_strcasecmp_with_sentinel( "none", value, 0 ) ) {
- __kmp_env_consistency_check = FALSE;
- } else {
- KMP_WARNING( StgInvalidValue, name, value );
- }; // if
-} // __kmp_stg_parse_consistency_check
-
-static void
-__kmp_stg_print_consistency_check( kmp_str_buf_t * buffer, char const * name, void * data ) {
-#if KMP_DEBUG
- const char *value = NULL;
-
- if ( __kmp_env_consistency_check ) {
- value = "all";
- } else {
- value = "none";
- }
-
- if ( value != NULL ) {
- __kmp_stg_print_str( buffer, name, value );
- }
-#endif /* KMP_DEBUG */
-} // __kmp_stg_print_consistency_check
-
-
-#if USE_ITT_BUILD
-// -------------------------------------------------------------------------------------------------
-// KMP_ITT_PREPARE_DELAY
-// -------------------------------------------------------------------------------------------------
-
-#if USE_ITT_NOTIFY
-
-static void
-__kmp_stg_parse_itt_prepare_delay( char const * name, char const * value, void * data )
-{
- // Experimental code: KMP_ITT_PREPARE_DELAY specifies numbert of loop iterations.
- int delay = 0;
- __kmp_stg_parse_int( name, value, 0, INT_MAX, & delay );
- __kmp_itt_prepare_delay = delay;
-} // __kmp_str_parse_itt_prepare_delay
-
-static void
-__kmp_stg_print_itt_prepare_delay( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_uint64( buffer, name, __kmp_itt_prepare_delay );
-
-} // __kmp_str_print_itt_prepare_delay
-
-#endif // USE_ITT_NOTIFY
-#endif /* USE_ITT_BUILD */
-
-// -------------------------------------------------------------------------------------------------
-// KMP_MALLOC_POOL_INCR
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_malloc_pool_incr( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_size(
- name,
- value,
- KMP_MIN_MALLOC_POOL_INCR,
- KMP_MAX_MALLOC_POOL_INCR,
- NULL,
- & __kmp_malloc_pool_incr,
- 1
- );
-} // __kmp_stg_parse_malloc_pool_incr
-
-static void
-__kmp_stg_print_malloc_pool_incr( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_size( buffer, name, __kmp_malloc_pool_incr );
-
-} // _kmp_stg_print_malloc_pool_incr
-
-
-#ifdef KMP_DEBUG
-
-// -------------------------------------------------------------------------------------------------
-// KMP_PAR_RANGE
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_par_range_env( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_par_range(
- name,
- value,
- & __kmp_par_range,
- __kmp_par_range_routine,
- __kmp_par_range_filename,
- & __kmp_par_range_lb,
- & __kmp_par_range_ub
- );
-} // __kmp_stg_parse_par_range_env
-
-static void
-__kmp_stg_print_par_range_env( kmp_str_buf_t * buffer, char const * name, void * data ) {
- if (__kmp_par_range != 0) {
- __kmp_stg_print_str( buffer, name, par_range_to_print );
- }
-} // __kmp_stg_print_par_range_env
-
-#if KMP_USE_MONITOR
-// -------------------------------------------------------------------------------------------------
-// KMP_YIELD_CYCLE, KMP_YIELD_ON, KMP_YIELD_OFF
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_yield_cycle( char const * name, char const * value, void * data ) {
- int flag = __kmp_yield_cycle;
- __kmp_stg_parse_bool( name, value, & flag );
- __kmp_yield_cycle = flag;
-} // __kmp_stg_parse_yield_cycle
-
-static void
-__kmp_stg_print_yield_cycle( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_yield_cycle );
-} // __kmp_stg_print_yield_cycle
-
-static void
-__kmp_stg_parse_yield_on( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_int( name, value, 2, INT_MAX, & __kmp_yield_on_count );
-} // __kmp_stg_parse_yield_on
-
-static void
-__kmp_stg_print_yield_on( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_yield_on_count );
-} // __kmp_stg_print_yield_on
-
-static void
-__kmp_stg_parse_yield_off( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_int( name, value, 2, INT_MAX, & __kmp_yield_off_count );
-} // __kmp_stg_parse_yield_off
-
-static void
-__kmp_stg_print_yield_off( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_yield_off_count );
-} // __kmp_stg_print_yield_off
-#endif // KMP_USE_MONITOR
-
-#endif
-
-// -------------------------------------------------------------------------------------------------
-// KMP_INIT_WAIT, KMP_NEXT_WAIT
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_init_wait( char const * name, char const * value, void * data ) {
- int wait;
- KMP_ASSERT( ( __kmp_init_wait & 1 ) == 0 );
- wait = __kmp_init_wait / 2;
- __kmp_stg_parse_int( name, value, KMP_MIN_INIT_WAIT, KMP_MAX_INIT_WAIT, & wait );
- __kmp_init_wait = wait * 2;
- KMP_ASSERT( ( __kmp_init_wait & 1 ) == 0 );
- __kmp_yield_init = __kmp_init_wait;
-} // __kmp_stg_parse_init_wait
-
-static void
-__kmp_stg_print_init_wait( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_init_wait );
-} // __kmp_stg_print_init_wait
-
-static void
-__kmp_stg_parse_next_wait( char const * name, char const * value, void * data ) {
- int wait;
- KMP_ASSERT( ( __kmp_next_wait & 1 ) == 0 );
- wait = __kmp_next_wait / 2;
- __kmp_stg_parse_int( name, value, KMP_MIN_NEXT_WAIT, KMP_MAX_NEXT_WAIT, & wait );
- __kmp_next_wait = wait * 2;
- KMP_ASSERT( ( __kmp_next_wait & 1 ) == 0 );
- __kmp_yield_next = __kmp_next_wait;
-} // __kmp_stg_parse_next_wait
-
-static void
-__kmp_stg_print_next_wait( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_next_wait );
-} //__kmp_stg_print_next_wait
-
-
-// -------------------------------------------------------------------------------------------------
-// KMP_GTID_MODE
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_gtid_mode( char const * name, char const * value, void * data ) {
- //
- // Modes:
- // 0 -- do not change default
- // 1 -- sp search
- // 2 -- use "keyed" TLS var, i.e.
- // pthread_getspecific(Linux* OS/OS X*) or TlsGetValue(Windows* OS)
- // 3 -- __declspec(thread) TLS var in tdata section
- //
- int mode = 0;
- int max = 2;
- #ifdef KMP_TDATA_GTID
- max = 3;
- #endif /* KMP_TDATA_GTID */
- __kmp_stg_parse_int( name, value, 0, max, & mode );
- // TODO; parse_int is not very suitable for this case. In case of overflow it is better to use
- // 0 rather that max value.
- if ( mode == 0 ) {
- __kmp_adjust_gtid_mode = TRUE;
- }
- else {
- __kmp_gtid_mode = mode;
- __kmp_adjust_gtid_mode = FALSE;
- }; // if
-} // __kmp_str_parse_gtid_mode
-
-static void
-__kmp_stg_print_gtid_mode( kmp_str_buf_t * buffer, char const * name, void * data ) {
- if ( __kmp_adjust_gtid_mode ) {
- __kmp_stg_print_int( buffer, name, 0 );
- }
- else {
- __kmp_stg_print_int( buffer, name, __kmp_gtid_mode );
- }
-} // __kmp_stg_print_gtid_mode
-
-// -------------------------------------------------------------------------------------------------
-// KMP_NUM_LOCKS_IN_BLOCK
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_lock_block( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_int( name, value, 0, KMP_INT_MAX, & __kmp_num_locks_in_block );
-} // __kmp_str_parse_lock_block
-
-static void
-__kmp_stg_print_lock_block( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_num_locks_in_block );
-} // __kmp_stg_print_lock_block
-
-// -------------------------------------------------------------------------------------------------
-// KMP_LOCK_KIND
-// -------------------------------------------------------------------------------------------------
-
-#if KMP_USE_DYNAMIC_LOCK
-# define KMP_STORE_LOCK_SEQ(a) (__kmp_user_lock_seq = lockseq_##a)
-#else
-# define KMP_STORE_LOCK_SEQ(a)
-#endif
-
-static void
-__kmp_stg_parse_lock_kind( char const * name, char const * value, void * data ) {
- if ( __kmp_init_user_locks ) {
- KMP_WARNING( EnvLockWarn, name );
- return;
- }
-
- if ( __kmp_str_match( "tas", 2, value )
- || __kmp_str_match( "test and set", 2, value )
- || __kmp_str_match( "test_and_set", 2, value )
- || __kmp_str_match( "test-and-set", 2, value )
- || __kmp_str_match( "test andset", 2, value )
- || __kmp_str_match( "test_andset", 2, value )
- || __kmp_str_match( "test-andset", 2, value )
- || __kmp_str_match( "testand set", 2, value )
- || __kmp_str_match( "testand_set", 2, value )
- || __kmp_str_match( "testand-set", 2, value )
- || __kmp_str_match( "testandset", 2, value ) ) {
- __kmp_user_lock_kind = lk_tas;
- KMP_STORE_LOCK_SEQ(tas);
- }
-#if KMP_USE_FUTEX
- else if ( __kmp_str_match( "futex", 1, value ) ) {
- if ( __kmp_futex_determine_capable() ) {
- __kmp_user_lock_kind = lk_futex;
- KMP_STORE_LOCK_SEQ(futex);
- }
- else {
- KMP_WARNING( FutexNotSupported, name, value );
- }
- }
-#endif
- else if ( __kmp_str_match( "ticket", 2, value ) ) {
- __kmp_user_lock_kind = lk_ticket;
- KMP_STORE_LOCK_SEQ(ticket);
- }
- else if ( __kmp_str_match( "queuing", 1, value )
- || __kmp_str_match( "queue", 1, value ) ) {
- __kmp_user_lock_kind = lk_queuing;
- KMP_STORE_LOCK_SEQ(queuing);
- }
- else if ( __kmp_str_match( "drdpa ticket", 1, value )
- || __kmp_str_match( "drdpa_ticket", 1, value )
- || __kmp_str_match( "drdpa-ticket", 1, value )
- || __kmp_str_match( "drdpaticket", 1, value )
- || __kmp_str_match( "drdpa", 1, value ) ) {
- __kmp_user_lock_kind = lk_drdpa;
- KMP_STORE_LOCK_SEQ(drdpa);
- }
-#if KMP_USE_ADAPTIVE_LOCKS
- else if ( __kmp_str_match( "adaptive", 1, value ) ) {
- if( __kmp_cpuinfo.rtm ) { // ??? Is cpuinfo available here?
- __kmp_user_lock_kind = lk_adaptive;
- KMP_STORE_LOCK_SEQ(adaptive);
- } else {
- KMP_WARNING( AdaptiveNotSupported, name, value );
- __kmp_user_lock_kind = lk_queuing;
- KMP_STORE_LOCK_SEQ(queuing);
- }
- }
-#endif // KMP_USE_ADAPTIVE_LOCKS
-#if KMP_USE_DYNAMIC_LOCK && KMP_USE_TSX
- else if ( __kmp_str_match("rtm", 1, value) ) {
- if ( __kmp_cpuinfo.rtm ) {
- __kmp_user_lock_kind = lk_rtm;
- KMP_STORE_LOCK_SEQ(rtm);
- } else {
- KMP_WARNING( AdaptiveNotSupported, name, value );
- __kmp_user_lock_kind = lk_queuing;
- KMP_STORE_LOCK_SEQ(queuing);
- }
- }
- else if ( __kmp_str_match("hle", 1, value) ) {
- __kmp_user_lock_kind = lk_hle;
- KMP_STORE_LOCK_SEQ(hle);
- }
-#endif
- else {
- KMP_WARNING( StgInvalidValue, name, value );
- }
-}
-
-static void
-__kmp_stg_print_lock_kind( kmp_str_buf_t * buffer, char const * name, void * data ) {
- const char *value = NULL;
-
- switch ( __kmp_user_lock_kind ) {
- case lk_default:
- value = "default";
- break;
-
- case lk_tas:
- value = "tas";
- break;
-
-#if KMP_USE_FUTEX
- case lk_futex:
- value = "futex";
- break;
-#endif
-
-#if KMP_USE_DYNAMIC_LOCK && KMP_USE_TSX
- case lk_rtm:
- value = "rtm";
- break;
-
- case lk_hle:
- value = "hle";
- break;
-#endif
-
- case lk_ticket:
- value = "ticket";
- break;
-
- case lk_queuing:
- value = "queuing";
- break;
-
- case lk_drdpa:
- value = "drdpa";
- break;
-#if KMP_USE_ADAPTIVE_LOCKS
- case lk_adaptive:
- value = "adaptive";
- break;
-#endif
- }
-
- if ( value != NULL ) {
- __kmp_stg_print_str( buffer, name, value );
- }
-}
-
-// -------------------------------------------------------------------------------------------------
-// KMP_SPIN_BACKOFF_PARAMS
-// -------------------------------------------------------------------------------------------------
-
-// KMP_SPIN_BACKOFF_PARAMS=max_backoff[,min_tick] (max backoff size, min tick for machine pause)
-static void
-__kmp_stg_parse_spin_backoff_params(const char* name, const char* value, void* data)
-{
- const char *next = value;
-
- int total = 0; // Count elements that were set. It'll be used as an array size
- int prev_comma = FALSE; // For correct processing sequential commas
- int i;
-
- kmp_uint32 max_backoff = __kmp_spin_backoff_params.max_backoff;
- kmp_uint32 min_tick = __kmp_spin_backoff_params.min_tick;
-
- // Run only 3 iterations because it is enough to read two values or find a syntax error
- for ( i = 0; i < 3 ; i++) {
- SKIP_WS( next );
-
- if ( *next == '\0' ) {
- break;
- }
- // Next character is not an integer or not a comma OR number of values > 2 => end of list
- if ( ( ( *next < '0' || *next > '9' ) && *next !=',' ) || total > 2 ) {
- KMP_WARNING( EnvSyntaxError, name, value );
- return;
- }
- // The next character is ','
- if ( *next == ',' ) {
- // ',' is the fisrt character
- if ( total == 0 || prev_comma ) {
- total++;
- }
- prev_comma = TRUE;
- next++; //skip ','
- SKIP_WS( next );
- }
- // Next character is a digit
- if ( *next >= '0' && *next <= '9' ) {
- int num;
- const char *buf = next;
- char const * msg = NULL;
- prev_comma = FALSE;
- SKIP_DIGITS( next );
- total++;
-
- const char *tmp = next;
- SKIP_WS( tmp );
- if ( ( *next == ' ' || *next == '\t' ) && ( *tmp >= '0' && *tmp <= '9' ) ) {
- KMP_WARNING( EnvSpacesNotAllowed, name, value );
- return;
- }
-
- num = __kmp_str_to_int( buf, *next );
- if ( num <= 0 ) { // The number of retries should be > 0
- msg = KMP_I18N_STR( ValueTooSmall );
- num = 1;
- } else if ( num > KMP_INT_MAX ) {
- msg = KMP_I18N_STR( ValueTooLarge );
- num = KMP_INT_MAX;
- }
- if ( msg != NULL ) {
- // Message is not empty. Print warning.
- KMP_WARNING( ParseSizeIntWarn, name, value, msg );
- KMP_INFORM( Using_int_Value, name, num );
- }
- if( total == 1 ) {
- max_backoff = num;
- } else if( total == 2 ) {
- min_tick = num;
- }
- }
- }
- KMP_DEBUG_ASSERT( total > 0 );
- if( total <= 0 ) {
- KMP_WARNING( EnvSyntaxError, name, value );
- return;
- }
- __kmp_spin_backoff_params.max_backoff = max_backoff;
- __kmp_spin_backoff_params.min_tick = min_tick;
-}
-
-static void
-__kmp_stg_print_spin_backoff_params(kmp_str_buf_t *buffer, char const* name, void* data)
-{
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME_EX(name);
- } else {
- __kmp_str_buf_print( buffer, " %s='", name );
- }
- __kmp_str_buf_print( buffer, "%d,%d'\n", __kmp_spin_backoff_params.max_backoff,
- __kmp_spin_backoff_params.min_tick );
-}
-
-#if KMP_USE_ADAPTIVE_LOCKS
-
-// -------------------------------------------------------------------------------------------------
-// KMP_ADAPTIVE_LOCK_PROPS, KMP_SPECULATIVE_STATSFILE
-// -------------------------------------------------------------------------------------------------
-
-// Parse out values for the tunable parameters from a string of the form
-// KMP_ADAPTIVE_LOCK_PROPS=max_soft_retries[,max_badness]
-static void
-__kmp_stg_parse_adaptive_lock_props( const char *name, const char *value, void *data )
-{
- int max_retries = 0;
- int max_badness = 0;
-
- const char *next = value;
-
- int total = 0; // Count elements that were set. It'll be used as an array size
- int prev_comma = FALSE; // For correct processing sequential commas
- int i;
-
- // Save values in the structure __kmp_speculative_backoff_params
- // Run only 3 iterations because it is enough to read two values or find a syntax error
- for ( i = 0; i < 3 ; i++) {
- SKIP_WS( next );
-
- if ( *next == '\0' ) {
- break;
- }
- // Next character is not an integer or not a comma OR number of values > 2 => end of list
- if ( ( ( *next < '0' || *next > '9' ) && *next !=',' ) || total > 2 ) {
- KMP_WARNING( EnvSyntaxError, name, value );
- return;
- }
- // The next character is ','
- if ( *next == ',' ) {
- // ',' is the fisrt character
- if ( total == 0 || prev_comma ) {
- total++;
- }
- prev_comma = TRUE;
- next++; //skip ','
- SKIP_WS( next );
- }
- // Next character is a digit
- if ( *next >= '0' && *next <= '9' ) {
- int num;
- const char *buf = next;
- char const * msg = NULL;
- prev_comma = FALSE;
- SKIP_DIGITS( next );
- total++;
-
- const char *tmp = next;
- SKIP_WS( tmp );
- if ( ( *next == ' ' || *next == '\t' ) && ( *tmp >= '0' && *tmp <= '9' ) ) {
- KMP_WARNING( EnvSpacesNotAllowed, name, value );
- return;
- }
-
- num = __kmp_str_to_int( buf, *next );
- if ( num < 0 ) { // The number of retries should be >= 0
- msg = KMP_I18N_STR( ValueTooSmall );
- num = 1;
- } else if ( num > KMP_INT_MAX ) {
- msg = KMP_I18N_STR( ValueTooLarge );
- num = KMP_INT_MAX;
- }
- if ( msg != NULL ) {
- // Message is not empty. Print warning.
- KMP_WARNING( ParseSizeIntWarn, name, value, msg );
- KMP_INFORM( Using_int_Value, name, num );
- }
- if( total == 1 ) {
- max_retries = num;
- } else if( total == 2 ) {
- max_badness = num;
- }
- }
- }
- KMP_DEBUG_ASSERT( total > 0 );
- if( total <= 0 ) {
- KMP_WARNING( EnvSyntaxError, name, value );
- return;
- }
- __kmp_adaptive_backoff_params.max_soft_retries = max_retries;
- __kmp_adaptive_backoff_params.max_badness = max_badness;
-}
-
-
-static void
-__kmp_stg_print_adaptive_lock_props(kmp_str_buf_t * buffer, char const * name, void * data )
-{
- if( __kmp_env_format ) {
- KMP_STR_BUF_PRINT_NAME_EX(name);
- } else {
- __kmp_str_buf_print( buffer, " %s='", name );
- }
- __kmp_str_buf_print( buffer, "%d,%d'\n", __kmp_adaptive_backoff_params.max_soft_retries,
- __kmp_adaptive_backoff_params.max_badness );
-} // __kmp_stg_print_adaptive_lock_props
-
-#if KMP_DEBUG_ADAPTIVE_LOCKS
-
-static void
-__kmp_stg_parse_speculative_statsfile( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_file( name, value, "", & __kmp_speculative_statsfile );
-} // __kmp_stg_parse_speculative_statsfile
-
-static void
-__kmp_stg_print_speculative_statsfile( kmp_str_buf_t * buffer, char const * name, void * data ) {
- if ( __kmp_str_match( "-", 0, __kmp_speculative_statsfile ) ) {
- __kmp_stg_print_str( buffer, name, "stdout" );
- } else {
- __kmp_stg_print_str( buffer, name, __kmp_speculative_statsfile );
- }
-
-} // __kmp_stg_print_speculative_statsfile
-
-#endif // KMP_DEBUG_ADAPTIVE_LOCKS
-
-#endif // KMP_USE_ADAPTIVE_LOCKS
-
-// -------------------------------------------------------------------------------------------------
-// KMP_HW_SUBSET (was KMP_PLACE_THREADS)
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_hw_subset( char const * name, char const * value, void * data ) {
- // Value example: 5Cx2Tx15O
- // Which means "use 5 cores with offset 15, 2 threads per core"
- // AC: extended to sockets level, examples of
- // "use 2 sockets with offset 6, 2 cores with offset 2 per socket, 2 threads per core":
- // 2s,6o,2c,2o,2t; 2s,6o,2c,2t,2o; 2s at 6,2c at 2,2t
- // To not break legacy code core-offset can be last;
- // postfix "o" or prefix @ can be offset designator.
- // Note: not all syntax errors are analyzed, some may be skipped.
-#define CHECK_DELIM(_x) (*(_x) == ',' || *(_x) == 'x')
- static int parsed = 0;
- int num;
- int single_warning = 0;
- int flagS = 0, flagC = 0, flagT = 0, flagSO = 0, flagCO = 0;
- const char *next = value;
- const char *prev;
-
- if( strcmp(name, "KMP_PLACE_THREADS") == 0 ) {
- KMP_INFORM(EnvVarDeprecated,name,"KMP_HW_SUBSET");
- if( parsed == 1 ) {
- return; // already parsed KMP_HW_SUBSET
- }
- }
- parsed = 1;
-
- SKIP_WS(next); // skip white spaces
- if (*next == '\0')
- return; // no data provided, retain default values
- if( strcmp(name, "KMP_PLACE_THREADS") == 0 ) {
- KMP_INFORM(EnvVarDeprecated,name,"KMP_HW_SUBSET");
- if( parsed == 1 ) {
- return; // already parsed KMP_HW_SUBSET
- }
- }
- parsed = 1;
-
- SKIP_WS(next); // skip white spaces
- if (*next == '\0')
- return; // no data provided, retain default values
- // Get num_sockets first (or whatever specified)
- if (*next >= '0' && *next <= '9') {
- prev = next;
- SKIP_DIGITS(next);
- num = __kmp_str_to_int(prev, *next);
- SKIP_WS(next);
- if (*next == 's' || *next == 'S') { // e.g. "2s"
- __kmp_place_num_sockets = num;
- flagS = 1; // got num sockets
- next++;
- if (*next == '@') { // socket offset, e.g. "2s at 4"
- flagSO = 1;
- prev = ++next; // don't allow spaces for simplicity
- if (!(*next >= '0' && *next <= '9')) {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- return;
- }
- SKIP_DIGITS(next);
- num = __kmp_str_to_int(prev, *next);
- __kmp_place_socket_offset = num;
- }
- } else if (*next == 'c' || *next == 'C') {
- __kmp_place_num_cores = num;
- flagS = flagC = 1; // sockets were not specified - use default
- next++;
- if (*next == '@') { // core offset, e.g. "2c at 6"
- flagCO = 1;
- prev = ++next; // don't allow spaces for simplicity
- if (!(*next >= '0' && *next <= '9')) {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- return;
- }
- SKIP_DIGITS(next);
- num = __kmp_str_to_int(prev, *next);
- __kmp_place_core_offset = num;
- }
- } else if (CHECK_DELIM(next)) {
- __kmp_place_num_cores = num; // no letter-designator - num cores
- flagS = flagC = 1; // sockets were not specified - use default
- next++;
- } else if (*next == 't' || *next == 'T') {
- __kmp_place_num_threads_per_core = num;
- // sockets, cores were not specified - use default
- return; // we ignore offset value in case all cores are used
- } else if (*next == '\0') {
- __kmp_place_num_cores = num;
- return; // the only value provided - set num cores
- } else {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- return;
- }
- } else {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- return;
- }
- KMP_DEBUG_ASSERT(flagS); // num sockets should already be set here
- SKIP_WS(next);
- if (*next == '\0')
- return; // " n " - something like this
- if (CHECK_DELIM(next)) {
- next++; // skip delimiter
- SKIP_WS(next);
- }
-
- // Get second value (could be offset, num_cores, num_threads)
- if (*next >= '0' && *next <= '9') {
- prev = next;
- SKIP_DIGITS(next);
- num = __kmp_str_to_int(prev, *next);
- SKIP_WS(next);
- if (*next == 'c' || *next == 'C') {
- KMP_DEBUG_ASSERT(flagC == 0);
- __kmp_place_num_cores = num;
- flagC = 1;
- next++;
- if (*next == '@') { // core offset, e.g. "2c at 6"
- flagCO = 1;
- prev = ++next; // don't allow spaces for simplicity
- if (!(*next >= '0' && *next <= '9')) {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- return;
- }
- SKIP_DIGITS(next);
- num = __kmp_str_to_int(prev, *next);
- __kmp_place_core_offset = num;
- }
- } else if (*next == 'o' || *next == 'O') { // offset specified
- KMP_WARNING(AffHWSubsetDeprecated);
- single_warning = 1;
- if (flagC) { // whether num_cores already specified (sockets skipped)
- KMP_DEBUG_ASSERT(!flagCO); // either "o" or @, not both
- __kmp_place_core_offset = num;
- } else {
- KMP_DEBUG_ASSERT(!flagSO); // either "o" or @, not both
- __kmp_place_socket_offset = num;
- }
- next++;
- } else if (*next == 't' || *next == 'T') {
- KMP_DEBUG_ASSERT(flagT == 0);
- __kmp_place_num_threads_per_core = num;
- flagC = 1; // num_cores could be skipped ?
- flagT = 1;
- next++; // can have core-offset specified after num threads
- } else if (*next == '\0') {
- KMP_DEBUG_ASSERT(flagC); // 4x2 means 4 cores 2 threads per core
- __kmp_place_num_threads_per_core = num;
- return; // two values provided without letter-designator
- } else {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- return;
- }
- } else {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- return;
- }
- SKIP_WS(next);
- if (*next == '\0')
- return; // " Ns,Nc " - something like this
- if (CHECK_DELIM(next)) {
- next++; // skip delimiter
- SKIP_WS(next);
- }
-
- // Get third value (could be core-offset, num_cores, num_threads)
- if (*next >= '0' && *next <= '9') {
- prev = next;
- SKIP_DIGITS(next);
- num = __kmp_str_to_int(prev, *next);
- SKIP_WS(next);
- if (*next == 't' || *next == 'T') {
- KMP_DEBUG_ASSERT(flagT == 0);
- __kmp_place_num_threads_per_core = num;
- if (flagC == 0)
- return; // num_cores could be skipped (e.g. 2s,4o,2t)
- flagT = 1;
- next++; // can have core-offset specified later (e.g. 2s,1c,2t,3o)
- } else if (*next == 'c' || *next == 'C') {
- KMP_DEBUG_ASSERT(flagC == 0);
- __kmp_place_num_cores = num;
- flagC = 1;
- next++;
- //KMP_DEBUG_ASSERT(*next != '@'); // socket offset used "o" designator
- } else if (*next == 'o' || *next == 'O') {
- KMP_WARNING(AffHWSubsetDeprecated);
- single_warning = 1;
- KMP_DEBUG_ASSERT(flagC);
- //KMP_DEBUG_ASSERT(!flagSO); // socket offset couldn't use @ designator
- __kmp_place_core_offset = num;
- next++;
- } else {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- return;
- }
- } else {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- return;
- }
- KMP_DEBUG_ASSERT(flagC);
- SKIP_WS(next);
- if ( *next == '\0' )
- return;
- if (CHECK_DELIM(next)) {
- next++; // skip delimiter
- SKIP_WS(next);
- }
-
- // Get 4-th value (could be core-offset, num_threads)
- if (*next >= '0' && *next <= '9') {
- prev = next;
- SKIP_DIGITS(next);
- num = __kmp_str_to_int(prev, *next);
- SKIP_WS(next);
- if (*next == 'o' || *next == 'O') {
- if (!single_warning) { // warn once
- KMP_WARNING(AffHWSubsetDeprecated);
- }
- KMP_DEBUG_ASSERT(!flagSO); // socket offset couldn't use @ designator
- __kmp_place_core_offset = num;
- next++;
- } else if (*next == 't' || *next == 'T') {
- KMP_DEBUG_ASSERT(flagT == 0);
- __kmp_place_num_threads_per_core = num;
- flagT = 1;
- next++; // can have core-offset specified after num threads
- } else {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- return;
- }
- } else {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- return;
- }
- SKIP_WS(next);
- if ( *next == '\0' )
- return;
- if (CHECK_DELIM(next)) {
- next++; // skip delimiter
- SKIP_WS(next);
- }
-
- // Get 5-th value (could be core-offset, num_threads)
- if (*next >= '0' && *next <= '9') {
- prev = next;
- SKIP_DIGITS(next);
- num = __kmp_str_to_int(prev, *next);
- SKIP_WS(next);
- if (*next == 'o' || *next == 'O') {
- if (!single_warning) { // warn once
- KMP_WARNING(AffHWSubsetDeprecated);
- }
- KMP_DEBUG_ASSERT(flagT);
- KMP_DEBUG_ASSERT(!flagSO); // socket offset couldn't use @ designator
- __kmp_place_core_offset = num;
- } else if (*next == 't' || *next == 'T') {
- KMP_DEBUG_ASSERT(flagT == 0);
- __kmp_place_num_threads_per_core = num;
- } else {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- }
- } else {
- KMP_WARNING(AffHWSubsetInvalid, name, value);
- }
- return;
-#undef CHECK_DELIM
-}
-
-static void
-__kmp_stg_print_hw_subset( kmp_str_buf_t * buffer, char const * name, void * data ) {
- if (__kmp_place_num_sockets + __kmp_place_num_cores + __kmp_place_num_threads_per_core) {
- int comma = 0;
- kmp_str_buf_t buf;
- __kmp_str_buf_init(&buf);
- if(__kmp_env_format)
- KMP_STR_BUF_PRINT_NAME_EX(name);
- else
- __kmp_str_buf_print(buffer, " %s='", name);
- if (__kmp_place_num_sockets) {
- __kmp_str_buf_print(&buf, "%ds", __kmp_place_num_sockets);
- if (__kmp_place_socket_offset)
- __kmp_str_buf_print(&buf, "@%d", __kmp_place_socket_offset);
- comma = 1;
- }
- if (__kmp_place_num_cores) {
- __kmp_str_buf_print(&buf, "%s%dc", comma?",":"", __kmp_place_num_cores);
- if (__kmp_place_core_offset)
- __kmp_str_buf_print(&buf, "@%d", __kmp_place_core_offset);
- comma = 1;
- }
- if (__kmp_place_num_threads_per_core)
- __kmp_str_buf_print(&buf, "%s%dt", comma?",":"", __kmp_place_num_threads_per_core);
- __kmp_str_buf_print(buffer, "%s'\n", buf.str );
- __kmp_str_buf_free(&buf);
-/*
- } else {
- __kmp_str_buf_print( buffer, " %s: %s \n", name, KMP_I18N_STR( NotDefined ) );
-*/
- }
-}
-
-#if USE_ITT_BUILD
-// -------------------------------------------------------------------------------------------------
-// KMP_FORKJOIN_FRAMES
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_forkjoin_frames( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_bool( name, value, & __kmp_forkjoin_frames );
-} // __kmp_stg_parse_forkjoin_frames
-
-static void
-__kmp_stg_print_forkjoin_frames( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_forkjoin_frames );
-} // __kmp_stg_print_forkjoin_frames
-
-// -------------------------------------------------------------------------------------------------
-// KMP_FORKJOIN_FRAMES_MODE
-// -------------------------------------------------------------------------------------------------
-
-static void
-__kmp_stg_parse_forkjoin_frames_mode( char const * name, char const * value, void * data ) {
- __kmp_stg_parse_int( name, value, 0, 3, & __kmp_forkjoin_frames_mode );
-} // __kmp_stg_parse_forkjoin_frames
-
-static void
-__kmp_stg_print_forkjoin_frames_mode( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_int( buffer, name, __kmp_forkjoin_frames_mode );
-} // __kmp_stg_print_forkjoin_frames
-#endif /* USE_ITT_BUILD */
-
-// -------------------------------------------------------------------------------------------------
-// OMP_DISPLAY_ENV
-// -------------------------------------------------------------------------------------------------
-
-#if OMP_40_ENABLED
-
-static void
-__kmp_stg_parse_omp_display_env( char const * name, char const * value, void * data )
-{
- if ( __kmp_str_match( "VERBOSE", 1, value ) )
- {
- __kmp_display_env_verbose = TRUE;
- } else {
- __kmp_stg_parse_bool( name, value, & __kmp_display_env );
- }
-
-} // __kmp_stg_parse_omp_display_env
-
-static void
-__kmp_stg_print_omp_display_env( kmp_str_buf_t * buffer, char const * name, void * data )
-{
- if ( __kmp_display_env_verbose )
- {
- __kmp_stg_print_str( buffer, name, "VERBOSE" );
- } else {
- __kmp_stg_print_bool( buffer, name, __kmp_display_env );
- }
-} // __kmp_stg_print_omp_display_env
-
-static void
-__kmp_stg_parse_omp_cancellation( char const * name, char const * value, void * data ) {
- if ( TCR_4(__kmp_init_parallel) ) {
- KMP_WARNING( EnvParallelWarn, name );
- return;
- } // read value before first parallel only
- __kmp_stg_parse_bool( name, value, & __kmp_omp_cancellation );
-} // __kmp_stg_parse_omp_cancellation
-
-static void
-__kmp_stg_print_omp_cancellation( kmp_str_buf_t * buffer, char const * name, void * data ) {
- __kmp_stg_print_bool( buffer, name, __kmp_omp_cancellation );
-} // __kmp_stg_print_omp_cancellation
-
-#endif
-
-// -------------------------------------------------------------------------------------------------
-// Table.
-// -------------------------------------------------------------------------------------------------
-
-
-static kmp_setting_t __kmp_stg_table[] = {
-
- { "KMP_ALL_THREADS", __kmp_stg_parse_all_threads, __kmp_stg_print_all_threads, NULL, 0, 0 },
- { "KMP_BLOCKTIME", __kmp_stg_parse_blocktime, __kmp_stg_print_blocktime, NULL, 0, 0 },
- { "KMP_DUPLICATE_LIB_OK", __kmp_stg_parse_duplicate_lib_ok, __kmp_stg_print_duplicate_lib_ok, NULL, 0, 0 },
- { "KMP_LIBRARY", __kmp_stg_parse_wait_policy, __kmp_stg_print_wait_policy, NULL, 0, 0 },
- { "KMP_MAX_THREADS", __kmp_stg_parse_all_threads, NULL, NULL, 0, 0 }, // For backward compatibility
-#if KMP_USE_MONITOR
- { "KMP_MONITOR_STACKSIZE", __kmp_stg_parse_monitor_stacksize, __kmp_stg_print_monitor_stacksize, NULL, 0, 0 },
-#endif
- { "KMP_SETTINGS", __kmp_stg_parse_settings, __kmp_stg_print_settings, NULL, 0, 0 },
- { "KMP_STACKOFFSET", __kmp_stg_parse_stackoffset, __kmp_stg_print_stackoffset, NULL, 0, 0 },
- { "KMP_STACKSIZE", __kmp_stg_parse_stacksize, __kmp_stg_print_stacksize, NULL, 0, 0 },
- { "KMP_STACKPAD", __kmp_stg_parse_stackpad, __kmp_stg_print_stackpad, NULL, 0, 0 },
- { "KMP_VERSION", __kmp_stg_parse_version, __kmp_stg_print_version, NULL, 0, 0 },
- { "KMP_WARNINGS", __kmp_stg_parse_warnings, __kmp_stg_print_warnings, NULL, 0, 0 },
-
- { "OMP_NESTED", __kmp_stg_parse_nested, __kmp_stg_print_nested, NULL, 0, 0 },
- { "OMP_NUM_THREADS", __kmp_stg_parse_num_threads, __kmp_stg_print_num_threads, NULL, 0, 0 },
- { "OMP_STACKSIZE", __kmp_stg_parse_stacksize, __kmp_stg_print_stacksize, NULL, 0, 0 },
-
- { "KMP_TASKING", __kmp_stg_parse_tasking, __kmp_stg_print_tasking, NULL, 0, 0 },
- { "KMP_TASK_STEALING_CONSTRAINT", __kmp_stg_parse_task_stealing, __kmp_stg_print_task_stealing, NULL, 0, 0 },
- { "OMP_MAX_ACTIVE_LEVELS", __kmp_stg_parse_max_active_levels, __kmp_stg_print_max_active_levels, NULL, 0, 0 },
-#if OMP_40_ENABLED
- { "OMP_DEFAULT_DEVICE", __kmp_stg_parse_default_device, __kmp_stg_print_default_device, NULL, 0, 0 },
-#endif
-#if OMP_45_ENABLED
- { "OMP_MAX_TASK_PRIORITY", __kmp_stg_parse_max_task_priority, __kmp_stg_print_max_task_priority, NULL, 0, 0 },
-#endif
- { "OMP_THREAD_LIMIT", __kmp_stg_parse_all_threads, __kmp_stg_print_all_threads, NULL, 0, 0 },
- { "OMP_WAIT_POLICY", __kmp_stg_parse_wait_policy, __kmp_stg_print_wait_policy, NULL, 0, 0 },
- { "KMP_DISP_NUM_BUFFERS", __kmp_stg_parse_disp_buffers, __kmp_stg_print_disp_buffers, NULL, 0, 0 },
-#if KMP_NESTED_HOT_TEAMS
- { "KMP_HOT_TEAMS_MAX_LEVEL", __kmp_stg_parse_hot_teams_level, __kmp_stg_print_hot_teams_level, NULL, 0, 0 },
- { "KMP_HOT_TEAMS_MODE", __kmp_stg_parse_hot_teams_mode, __kmp_stg_print_hot_teams_mode, NULL, 0, 0 },
-#endif // KMP_NESTED_HOT_TEAMS
-
-#if KMP_HANDLE_SIGNALS
- { "KMP_HANDLE_SIGNALS", __kmp_stg_parse_handle_signals, __kmp_stg_print_handle_signals, NULL, 0, 0 },
-#endif
-
-#if KMP_ARCH_X86 || KMP_ARCH_X86_64
- { "KMP_INHERIT_FP_CONTROL", __kmp_stg_parse_inherit_fp_control, __kmp_stg_print_inherit_fp_control, NULL, 0, 0 },
-#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
-
-#ifdef KMP_GOMP_COMPAT
- { "GOMP_STACKSIZE", __kmp_stg_parse_stacksize, NULL, NULL, 0, 0 },
-#endif
-
-#ifdef KMP_DEBUG
- { "KMP_A_DEBUG", __kmp_stg_parse_a_debug, __kmp_stg_print_a_debug, NULL, 0, 0 },
- { "KMP_B_DEBUG", __kmp_stg_parse_b_debug, __kmp_stg_print_b_debug, NULL, 0, 0 },
- { "KMP_C_DEBUG", __kmp_stg_parse_c_debug, __kmp_stg_print_c_debug, NULL, 0, 0 },
- { "KMP_D_DEBUG", __kmp_stg_parse_d_debug, __kmp_stg_print_d_debug, NULL, 0, 0 },
- { "KMP_E_DEBUG", __kmp_stg_parse_e_debug, __kmp_stg_print_e_debug, NULL, 0, 0 },
- { "KMP_F_DEBUG", __kmp_stg_parse_f_debug, __kmp_stg_print_f_debug, NULL, 0, 0 },
- { "KMP_DEBUG", __kmp_stg_parse_debug, NULL, /* no print */ NULL, 0, 0 },
- { "KMP_DEBUG_BUF", __kmp_stg_parse_debug_buf, __kmp_stg_print_debug_buf, NULL, 0, 0 },
- { "KMP_DEBUG_BUF_ATOMIC", __kmp_stg_parse_debug_buf_atomic, __kmp_stg_print_debug_buf_atomic, NULL, 0, 0 },
- { "KMP_DEBUG_BUF_CHARS", __kmp_stg_parse_debug_buf_chars, __kmp_stg_print_debug_buf_chars, NULL, 0, 0 },
- { "KMP_DEBUG_BUF_LINES", __kmp_stg_parse_debug_buf_lines, __kmp_stg_print_debug_buf_lines, NULL, 0, 0 },
- { "KMP_DIAG", __kmp_stg_parse_diag, __kmp_stg_print_diag, NULL, 0, 0 },
-
- { "KMP_PAR_RANGE", __kmp_stg_parse_par_range_env, __kmp_stg_print_par_range_env, NULL, 0, 0 },
-#if KMP_USE_MONITOR
- { "KMP_YIELD_CYCLE", __kmp_stg_parse_yield_cycle, __kmp_stg_print_yield_cycle, NULL, 0, 0 },
- { "KMP_YIELD_ON", __kmp_stg_parse_yield_on, __kmp_stg_print_yield_on, NULL, 0, 0 },
- { "KMP_YIELD_OFF", __kmp_stg_parse_yield_off, __kmp_stg_print_yield_off, NULL, 0, 0 },
-#endif
-#endif // KMP_DEBUG
-
- { "KMP_ALIGN_ALLOC", __kmp_stg_parse_align_alloc, __kmp_stg_print_align_alloc, NULL, 0, 0 },
-
- { "KMP_PLAIN_BARRIER", __kmp_stg_parse_barrier_branch_bit, __kmp_stg_print_barrier_branch_bit, NULL, 0, 0 },
- { "KMP_PLAIN_BARRIER_PATTERN", __kmp_stg_parse_barrier_pattern, __kmp_stg_print_barrier_pattern, NULL, 0, 0 },
- { "KMP_FORKJOIN_BARRIER", __kmp_stg_parse_barrier_branch_bit, __kmp_stg_print_barrier_branch_bit, NULL, 0, 0 },
- { "KMP_FORKJOIN_BARRIER_PATTERN", __kmp_stg_parse_barrier_pattern, __kmp_stg_print_barrier_pattern, NULL, 0, 0 },
-#if KMP_FAST_REDUCTION_BARRIER
- { "KMP_REDUCTION_BARRIER", __kmp_stg_parse_barrier_branch_bit, __kmp_stg_print_barrier_branch_bit, NULL, 0, 0 },
- { "KMP_REDUCTION_BARRIER_PATTERN", __kmp_stg_parse_barrier_pattern, __kmp_stg_print_barrier_pattern, NULL, 0, 0 },
-#endif
-
- { "KMP_ABORT_DELAY", __kmp_stg_parse_abort_delay, __kmp_stg_print_abort_delay, NULL, 0, 0 },
- { "KMP_CPUINFO_FILE", __kmp_stg_parse_cpuinfo_file, __kmp_stg_print_cpuinfo_file, NULL, 0, 0 },
- { "KMP_FORCE_REDUCTION", __kmp_stg_parse_force_reduction, __kmp_stg_print_force_reduction, NULL, 0, 0 },
- { "KMP_DETERMINISTIC_REDUCTION", __kmp_stg_parse_force_reduction, __kmp_stg_print_force_reduction, NULL, 0, 0 },
- { "KMP_STORAGE_MAP", __kmp_stg_parse_storage_map, __kmp_stg_print_storage_map, NULL, 0, 0 },
- { "KMP_ALL_THREADPRIVATE", __kmp_stg_parse_all_threadprivate, __kmp_stg_print_all_threadprivate, NULL, 0, 0 },
- { "KMP_FOREIGN_THREADS_THREADPRIVATE", __kmp_stg_parse_foreign_threads_threadprivate, __kmp_stg_print_foreign_threads_threadprivate, NULL, 0, 0 },
-
-#if KMP_AFFINITY_SUPPORTED
- { "KMP_AFFINITY", __kmp_stg_parse_affinity, __kmp_stg_print_affinity, NULL, 0, 0 },
-# ifdef KMP_GOMP_COMPAT
- { "GOMP_CPU_AFFINITY", __kmp_stg_parse_gomp_cpu_affinity, NULL, /* no print */ NULL, 0, 0 },
-# endif /* KMP_GOMP_COMPAT */
-# if OMP_40_ENABLED
- { "OMP_PROC_BIND", __kmp_stg_parse_proc_bind, __kmp_stg_print_proc_bind, NULL, 0, 0 },
- { "OMP_PLACES", __kmp_stg_parse_places, __kmp_stg_print_places, NULL, 0, 0 },
-# else
- { "OMP_PROC_BIND", __kmp_stg_parse_proc_bind, NULL, /* no print */ NULL, 0, 0 },
-# endif /* OMP_40_ENABLED */
-
- { "KMP_TOPOLOGY_METHOD", __kmp_stg_parse_topology_method, __kmp_stg_print_topology_method, NULL, 0, 0 },
-
-#else
-
- //
- // KMP_AFFINITY is not supported on OS X*, nor is OMP_PLACES.
- // OMP_PROC_BIND and proc-bind-var are supported, however.
- //
-# if OMP_40_ENABLED
- { "OMP_PROC_BIND", __kmp_stg_parse_proc_bind, __kmp_stg_print_proc_bind, NULL, 0, 0 },
-# endif
-
-#endif // KMP_AFFINITY_SUPPORTED
-
- { "KMP_INIT_AT_FORK", __kmp_stg_parse_init_at_fork, __kmp_stg_print_init_at_fork, NULL, 0, 0 },
- { "KMP_SCHEDULE", __kmp_stg_parse_schedule, __kmp_stg_print_schedule, NULL, 0, 0 },
- { "OMP_SCHEDULE", __kmp_stg_parse_omp_schedule, __kmp_stg_print_omp_schedule, NULL, 0, 0 },
- { "KMP_ATOMIC_MODE", __kmp_stg_parse_atomic_mode, __kmp_stg_print_atomic_mode, NULL, 0, 0 },
- { "KMP_CONSISTENCY_CHECK", __kmp_stg_parse_consistency_check, __kmp_stg_print_consistency_check, NULL, 0, 0 },
-
-#if USE_ITT_BUILD && USE_ITT_NOTIFY
- { "KMP_ITT_PREPARE_DELAY", __kmp_stg_parse_itt_prepare_delay, __kmp_stg_print_itt_prepare_delay, NULL, 0, 0 },
-#endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */
- { "KMP_MALLOC_POOL_INCR", __kmp_stg_parse_malloc_pool_incr, __kmp_stg_print_malloc_pool_incr, NULL, 0, 0 },
- { "KMP_INIT_WAIT", __kmp_stg_parse_init_wait, __kmp_stg_print_init_wait, NULL, 0, 0 },
- { "KMP_NEXT_WAIT", __kmp_stg_parse_next_wait, __kmp_stg_print_next_wait, NULL, 0, 0 },
- { "KMP_GTID_MODE", __kmp_stg_parse_gtid_mode, __kmp_stg_print_gtid_mode, NULL, 0, 0 },
- { "OMP_DYNAMIC", __kmp_stg_parse_omp_dynamic, __kmp_stg_print_omp_dynamic, NULL, 0, 0 },
- { "KMP_DYNAMIC_MODE", __kmp_stg_parse_kmp_dynamic_mode, __kmp_stg_print_kmp_dynamic_mode, NULL, 0, 0 },
-
-#ifdef USE_LOAD_BALANCE
- { "KMP_LOAD_BALANCE_INTERVAL", __kmp_stg_parse_ld_balance_interval,__kmp_stg_print_ld_balance_interval,NULL, 0, 0 },
-#endif
-
- { "KMP_NUM_LOCKS_IN_BLOCK", __kmp_stg_parse_lock_block, __kmp_stg_print_lock_block, NULL, 0, 0 },
- { "KMP_LOCK_KIND", __kmp_stg_parse_lock_kind, __kmp_stg_print_lock_kind, NULL, 0, 0 },
- { "KMP_SPIN_BACKOFF_PARAMS", __kmp_stg_parse_spin_backoff_params, __kmp_stg_print_spin_backoff_params, NULL, 0, 0 },
-#if KMP_USE_ADAPTIVE_LOCKS
- { "KMP_ADAPTIVE_LOCK_PROPS", __kmp_stg_parse_adaptive_lock_props,__kmp_stg_print_adaptive_lock_props, NULL, 0, 0 },
-#if KMP_DEBUG_ADAPTIVE_LOCKS
- { "KMP_SPECULATIVE_STATSFILE", __kmp_stg_parse_speculative_statsfile,__kmp_stg_print_speculative_statsfile, NULL, 0, 0 },
-#endif
-#endif // KMP_USE_ADAPTIVE_LOCKS
- { "KMP_PLACE_THREADS", __kmp_stg_parse_hw_subset, __kmp_stg_print_hw_subset, NULL, 0, 0 },
- { "KMP_HW_SUBSET", __kmp_stg_parse_hw_subset, __kmp_stg_print_hw_subset, NULL, 0, 0 },
-#if USE_ITT_BUILD
- { "KMP_FORKJOIN_FRAMES", __kmp_stg_parse_forkjoin_frames, __kmp_stg_print_forkjoin_frames, NULL, 0, 0 },
- { "KMP_FORKJOIN_FRAMES_MODE", __kmp_stg_parse_forkjoin_frames_mode,__kmp_stg_print_forkjoin_frames_mode, NULL, 0, 0 },
-#endif
-
-# if OMP_40_ENABLED
- { "OMP_DISPLAY_ENV", __kmp_stg_parse_omp_display_env, __kmp_stg_print_omp_display_env, NULL, 0, 0 },
- { "OMP_CANCELLATION", __kmp_stg_parse_omp_cancellation, __kmp_stg_print_omp_cancellation, NULL, 0, 0 },
-#endif
- { "", NULL, NULL, NULL, 0, 0 }
-}; // settings
-
-static int const __kmp_stg_count = sizeof( __kmp_stg_table ) / sizeof( kmp_setting_t );
-
-static inline
-kmp_setting_t *
-__kmp_stg_find( char const * name ) {
-
- int i;
- if ( name != NULL ) {
- for ( i = 0; i < __kmp_stg_count; ++ i ) {
- if ( strcmp( __kmp_stg_table[ i ].name, name ) == 0 ) {
- return & __kmp_stg_table[ i ];
- }; // if
- }; // for
- }; // if
- return NULL;
-
-} // __kmp_stg_find
-
-
-static int
-__kmp_stg_cmp( void const * _a, void const * _b ) {
- kmp_setting_t * a = (kmp_setting_t *) _a;
- kmp_setting_t * b = (kmp_setting_t *) _b;
-
- //
- // Process KMP_AFFINITY last.
- // It needs to come after OMP_PLACES and GOMP_CPU_AFFINITY.
- //
- if ( strcmp( a->name, "KMP_AFFINITY" ) == 0 ) {
- if ( strcmp( b->name, "KMP_AFFINITY" ) == 0 ) {
- return 0;
- }
- return 1;
- }
- else if ( strcmp( b->name, "KMP_AFFINITY" ) == 0 ) {
- return -1;
- }
- return strcmp( a->name, b->name );
-} // __kmp_stg_cmp
-
-
-static void
-__kmp_stg_init( void
-) {
-
- static int initialized = 0;
-
- if ( ! initialized ) {
-
- // Sort table.
- qsort( __kmp_stg_table, __kmp_stg_count - 1, sizeof( kmp_setting_t ), __kmp_stg_cmp );
-
- { // Initialize *_STACKSIZE data.
-
- kmp_setting_t * kmp_stacksize = __kmp_stg_find( "KMP_STACKSIZE" ); // 1st priority.
-#ifdef KMP_GOMP_COMPAT
- kmp_setting_t * gomp_stacksize = __kmp_stg_find( "GOMP_STACKSIZE" ); // 2nd priority.
-#endif
- kmp_setting_t * omp_stacksize = __kmp_stg_find( "OMP_STACKSIZE" ); // 3rd priority.
-
- // !!! volatile keyword is Intel (R) C Compiler bug CQ49908 workaround.
- // !!! Compiler does not understand rivals is used and optimizes out assignments
- // !!! rivals[ i ++ ] = ...;
- static kmp_setting_t * volatile rivals[ 4 ];
- static kmp_stg_ss_data_t kmp_data = { 1, (kmp_setting_t **)rivals };
-#ifdef KMP_GOMP_COMPAT
- static kmp_stg_ss_data_t gomp_data = { 1024, (kmp_setting_t **)rivals };
-#endif
- static kmp_stg_ss_data_t omp_data = { 1024, (kmp_setting_t **)rivals };
- int i = 0;
-
- rivals[ i ++ ] = kmp_stacksize;
-#ifdef KMP_GOMP_COMPAT
- if ( gomp_stacksize != NULL ) {
- rivals[ i ++ ] = gomp_stacksize;
- }; // if
-#endif
- rivals[ i ++ ] = omp_stacksize;
- rivals[ i ++ ] = NULL;
-
- kmp_stacksize->data = & kmp_data;
-#ifdef KMP_GOMP_COMPAT
- if ( gomp_stacksize != NULL ) {
- gomp_stacksize->data = & gomp_data;
- }; // if
-#endif
- omp_stacksize->data = & omp_data;
-
- }
-
- { // Initialize KMP_LIBRARY and OMP_WAIT_POLICY data.
-
- kmp_setting_t * kmp_library = __kmp_stg_find( "KMP_LIBRARY" ); // 1st priority.
- kmp_setting_t * omp_wait_policy = __kmp_stg_find( "OMP_WAIT_POLICY" ); // 2nd priority.
-
- // !!! volatile keyword is Intel (R) C Compiler bug CQ49908 workaround.
- static kmp_setting_t * volatile rivals[ 3 ];
- static kmp_stg_wp_data_t kmp_data = { 0, (kmp_setting_t **)rivals };
- static kmp_stg_wp_data_t omp_data = { 1, (kmp_setting_t **)rivals };
- int i = 0;
-
- rivals[ i ++ ] = kmp_library;
- if ( omp_wait_policy != NULL ) {
- rivals[ i ++ ] = omp_wait_policy;
- }; // if
- rivals[ i ++ ] = NULL;
-
- kmp_library->data = & kmp_data;
- if ( omp_wait_policy != NULL ) {
- omp_wait_policy->data = & omp_data;
- }; // if
-
- }
-
- { // Initialize KMP_ALL_THREADS, KMP_MAX_THREADS, and OMP_THREAD_LIMIT data.
-
- kmp_setting_t * kmp_all_threads = __kmp_stg_find( "KMP_ALL_THREADS" ); // 1st priority.
- kmp_setting_t * kmp_max_threads = __kmp_stg_find( "KMP_MAX_THREADS" ); // 2nd priority.
- kmp_setting_t * omp_thread_limit = __kmp_stg_find( "OMP_THREAD_LIMIT" ); // 3rd priority.
-
- // !!! volatile keyword is Intel (R) C Compiler bug CQ49908 workaround.
- static kmp_setting_t * volatile rivals[ 4 ];
- int i = 0;
-
- rivals[ i ++ ] = kmp_all_threads;
- rivals[ i ++ ] = kmp_max_threads;
- if ( omp_thread_limit != NULL ) {
- rivals[ i ++ ] = omp_thread_limit;
- }; // if
- rivals[ i ++ ] = NULL;
-
- kmp_all_threads->data = (void*)& rivals;
- kmp_max_threads->data = (void*)& rivals;
- if ( omp_thread_limit != NULL ) {
- omp_thread_limit->data = (void*)& rivals;
- }; // if
-
- }
-
-#if KMP_AFFINITY_SUPPORTED
- { // Initialize KMP_AFFINITY, GOMP_CPU_AFFINITY, and OMP_PROC_BIND data.
-
- kmp_setting_t * kmp_affinity = __kmp_stg_find( "KMP_AFFINITY" ); // 1st priority.
- KMP_DEBUG_ASSERT( kmp_affinity != NULL );
-
-# ifdef KMP_GOMP_COMPAT
- kmp_setting_t * gomp_cpu_affinity = __kmp_stg_find( "GOMP_CPU_AFFINITY" ); // 2nd priority.
- KMP_DEBUG_ASSERT( gomp_cpu_affinity != NULL );
-# endif
-
- kmp_setting_t * omp_proc_bind = __kmp_stg_find( "OMP_PROC_BIND" ); // 3rd priority.
- KMP_DEBUG_ASSERT( omp_proc_bind != NULL );
-
- // !!! volatile keyword is Intel (R) C Compiler bug CQ49908 workaround.
- static kmp_setting_t * volatile rivals[ 4 ];
- int i = 0;
-
- rivals[ i ++ ] = kmp_affinity;
-
-# ifdef KMP_GOMP_COMPAT
- rivals[ i ++ ] = gomp_cpu_affinity;
- gomp_cpu_affinity->data = (void*)& rivals;
-# endif
-
- rivals[ i ++ ] = omp_proc_bind;
- omp_proc_bind->data = (void*)& rivals;
- rivals[ i ++ ] = NULL;
-
-# if OMP_40_ENABLED
- static kmp_setting_t * volatile places_rivals[ 4 ];
- i = 0;
-
- kmp_setting_t * omp_places = __kmp_stg_find( "OMP_PLACES" ); // 3rd priority.
- KMP_DEBUG_ASSERT( omp_places != NULL );
-
- places_rivals[ i ++ ] = kmp_affinity;
-# ifdef KMP_GOMP_COMPAT
- places_rivals[ i ++ ] = gomp_cpu_affinity;
-# endif
- places_rivals[ i ++ ] = omp_places;
- omp_places->data = (void*)& places_rivals;
- places_rivals[ i ++ ] = NULL;
-# endif
- }
-#else
- // KMP_AFFINITY not supported, so OMP_PROC_BIND has no rivals.
- // OMP_PLACES not supported yet.
-#endif // KMP_AFFINITY_SUPPORTED
-
- { // Initialize KMP_DETERMINISTIC_REDUCTION and KMP_FORCE_REDUCTION data.
-
- kmp_setting_t * kmp_force_red = __kmp_stg_find( "KMP_FORCE_REDUCTION" ); // 1st priority.
- kmp_setting_t * kmp_determ_red = __kmp_stg_find( "KMP_DETERMINISTIC_REDUCTION" ); // 2nd priority.
-
- // !!! volatile keyword is Intel (R) C Compiler bug CQ49908 workaround.
- static kmp_setting_t * volatile rivals[ 3 ];
- static kmp_stg_fr_data_t force_data = { 1, (kmp_setting_t **)rivals };
- static kmp_stg_fr_data_t determ_data = { 0, (kmp_setting_t **)rivals };
- int i = 0;
-
- rivals[ i ++ ] = kmp_force_red;
- if ( kmp_determ_red != NULL ) {
- rivals[ i ++ ] = kmp_determ_red;
- }; // if
- rivals[ i ++ ] = NULL;
-
- kmp_force_red->data = & force_data;
- if ( kmp_determ_red != NULL ) {
- kmp_determ_red->data = & determ_data;
- }; // if
- }
-
- initialized = 1;
-
- }; // if
-
- // Reset flags.
- int i;
- for ( i = 0; i < __kmp_stg_count; ++ i ) {
- __kmp_stg_table[ i ].set = 0;
- }; // for
-
-} // __kmp_stg_init
-
-
-static void
-__kmp_stg_parse(
- char const * name,
- char const * value
-) {
-
- // On Windows* OS there are some nameless variables like "C:=C:\" (yeah, really nameless, they are
- // presented in environment block as "=C:=C\\\x00=D:=D:\\\x00...", so let us skip them.
- if ( name[ 0 ] == 0 ) {
- return;
- }; // if
-
- if ( value != NULL ) {
- kmp_setting_t * setting = __kmp_stg_find( name );
- if ( setting != NULL ) {
- setting->parse( name, value, setting->data );
- setting->defined = 1;
- }; // if
- }; // if
-
-} // __kmp_stg_parse
-
-
-static int
-__kmp_stg_check_rivals( // 0 -- Ok, 1 -- errors found.
- char const * name, // Name of variable.
- char const * value, // Value of the variable.
- kmp_setting_t * * rivals // List of rival settings (the list must include current one).
-) {
-
- if ( rivals == NULL ) {
- return 0;
- }
-
- // Loop thru higher priority settings (listed before current).
- int i = 0;
- for ( ; strcmp( rivals[ i ]->name, name ) != 0; i++ ) {
- KMP_DEBUG_ASSERT( rivals[ i ] != NULL );
-
-#if KMP_AFFINITY_SUPPORTED
- if ( rivals[ i ] == __kmp_affinity_notype ) {
- //
- // If KMP_AFFINITY is specified without a type name,
- // it does not rival OMP_PROC_BIND or GOMP_CPU_AFFINITY.
- //
- continue;
- }
-#endif
-
- if ( rivals[ i ]->set ) {
- KMP_WARNING( StgIgnored, name, rivals[ i ]->name );
- return 1;
- }; // if
- }; // while
-
- ++ i; // Skip current setting.
- return 0;
-
-}; // __kmp_stg_check_rivals
-
-
-static int
-__kmp_env_toPrint( char const * name, int flag ) {
- int rc = 0;
- kmp_setting_t * setting = __kmp_stg_find( name );
- if ( setting != NULL ) {
- rc = setting->defined;
- if ( flag >= 0 ) {
- setting->defined = flag;
- }; // if
- }; // if
- return rc;
-}
-
-
-static void
-__kmp_aux_env_initialize( kmp_env_blk_t* block ) {
-
- char const * value;
-
- /* OMP_NUM_THREADS */
- value = __kmp_env_blk_var( block, "OMP_NUM_THREADS" );
- if ( value ) {
- ompc_set_num_threads( __kmp_dflt_team_nth );
- }
-
- /* KMP_BLOCKTIME */
- value = __kmp_env_blk_var( block, "KMP_BLOCKTIME" );
- if ( value ) {
- kmpc_set_blocktime( __kmp_dflt_blocktime );
- }
-
- /* OMP_NESTED */
- value = __kmp_env_blk_var( block, "OMP_NESTED" );
- if ( value ) {
- ompc_set_nested( __kmp_dflt_nested );
- }
-
- /* OMP_DYNAMIC */
- value = __kmp_env_blk_var( block, "OMP_DYNAMIC" );
- if ( value ) {
- ompc_set_dynamic( __kmp_global.g.g_dynamic );
- }
-
-}
-
-void
-__kmp_env_initialize( char const * string ) {
-
- kmp_env_blk_t block;
- int i;
-
- __kmp_stg_init();
-
- // Hack!!!
- if ( string == NULL ) {
- // __kmp_max_nth = __kmp_sys_max_nth;
- __kmp_threads_capacity = __kmp_initial_threads_capacity( __kmp_dflt_team_nth_ub );
- }; // if
- __kmp_env_blk_init( & block, string );
-
- //
- // update the set flag on all entries that have an env var
- //
- for ( i = 0; i < block.count; ++ i ) {
- if (( block.vars[ i ].name == NULL )
- || ( *block.vars[ i ].name == '\0')) {
- continue;
- }
- if ( block.vars[ i ].value == NULL ) {
- continue;
- }
- kmp_setting_t * setting = __kmp_stg_find( block.vars[ i ].name );
- if ( setting != NULL ) {
- setting->set = 1;
- }
- }; // for i
-
- // We need to know if blocktime was set when processing OMP_WAIT_POLICY
- blocktime_str = __kmp_env_blk_var( & block, "KMP_BLOCKTIME" );
-
- // Special case. If we parse environment, not a string, process KMP_WARNINGS first.
- if ( string == NULL ) {
- char const * name = "KMP_WARNINGS";
- char const * value = __kmp_env_blk_var( & block, name );
- __kmp_stg_parse( name, value );
- }; // if
-
-#if KMP_AFFINITY_SUPPORTED
- //
- // Special case. KMP_AFFINITY is not a rival to other affinity env vars
- // if no affinity type is specified. We want to allow
- // KMP_AFFINITY=[no],verbose/[no]warnings/etc. to be enabled when
- // specifying the affinity type via GOMP_CPU_AFFINITY or the OMP 4.0
- // affinity mechanism.
- //
- __kmp_affinity_notype = NULL;
- char const *aff_str = __kmp_env_blk_var( & block, "KMP_AFFINITY" );
- if ( aff_str != NULL ) {
- //
- // Check if the KMP_AFFINITY type is specified in the string.
- // We just search the string for "compact", "scatter", etc.
- // without really parsing the string. The syntax of the
- // KMP_AFFINITY env var is such that none of the affinity
- // type names can appear anywhere other that the type
- // specifier, even as substrings.
- //
- // I can't find a case-insensitive version of strstr on Windows* OS.
- // Use the case-sensitive version for now.
- //
-
-# if KMP_OS_WINDOWS
-# define FIND strstr
-# else
-# define FIND strcasestr
-# endif
-
- if ( ( FIND( aff_str, "none" ) == NULL )
- && ( FIND( aff_str, "physical" ) == NULL )
- && ( FIND( aff_str, "logical" ) == NULL )
- && ( FIND( aff_str, "compact" ) == NULL )
- && ( FIND( aff_str, "scatter" ) == NULL )
- && ( FIND( aff_str, "explicit" ) == NULL )
- && ( FIND( aff_str, "balanced" ) == NULL )
- && ( FIND( aff_str, "disabled" ) == NULL ) ) {
- __kmp_affinity_notype = __kmp_stg_find( "KMP_AFFINITY" );
- }
- else {
- //
- // A new affinity type is specified.
- // Reset the affinity flags to their default values,
- // in case this is called from kmp_set_defaults().
- //
- __kmp_affinity_type = affinity_default;
- __kmp_affinity_gran = affinity_gran_default;
- __kmp_affinity_top_method = affinity_top_method_default;
- __kmp_affinity_respect_mask = affinity_respect_mask_default;
- }
-# undef FIND
-
-#if OMP_40_ENABLED
- //
- // Also reset the affinity flags if OMP_PROC_BIND is specified.
- //
- aff_str = __kmp_env_blk_var( & block, "OMP_PROC_BIND" );
- if ( aff_str != NULL ) {
- __kmp_affinity_type = affinity_default;
- __kmp_affinity_gran = affinity_gran_default;
- __kmp_affinity_top_method = affinity_top_method_default;
- __kmp_affinity_respect_mask = affinity_respect_mask_default;
- }
-#endif /* OMP_40_ENABLED */
- }
-
-#endif /* KMP_AFFINITY_SUPPORTED */
-
-#if OMP_40_ENABLED
- //
- // Set up the nested proc bind type vector.
- //
- if ( __kmp_nested_proc_bind.bind_types == NULL ) {
- __kmp_nested_proc_bind.bind_types = (kmp_proc_bind_t *)
- KMP_INTERNAL_MALLOC( sizeof(kmp_proc_bind_t) );
- if ( __kmp_nested_proc_bind.bind_types == NULL ) {
- KMP_FATAL( MemoryAllocFailed );
- }
- __kmp_nested_proc_bind.size = 1;
- __kmp_nested_proc_bind.used = 1;
-# if KMP_AFFINITY_SUPPORTED
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_default;
-# else
- // default proc bind is false if affinity not supported
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
-# endif
-
- }
-#endif /* OMP_40_ENABLED */
-
- //
- // Now process all of the settings.
- //
- for ( i = 0; i < block.count; ++ i ) {
- __kmp_stg_parse( block.vars[ i ].name, block.vars[ i ].value );
- }; // for i
-
- //
- // If user locks have been allocated yet, don't reset the lock vptr table.
- //
- if ( ! __kmp_init_user_locks ) {
- if ( __kmp_user_lock_kind == lk_default ) {
- __kmp_user_lock_kind = lk_queuing;
- }
-#if KMP_USE_DYNAMIC_LOCK
- __kmp_init_dynamic_user_locks();
-#else
- __kmp_set_user_lock_vptrs( __kmp_user_lock_kind );
-#endif
- }
- else {
- KMP_DEBUG_ASSERT( string != NULL); // kmp_set_defaults() was called
- KMP_DEBUG_ASSERT( __kmp_user_lock_kind != lk_default );
- // Binds lock functions again to follow the transition between different
- // KMP_CONSISTENCY_CHECK values. Calling this again is harmless as long
- // as we do not allow lock kind changes after making a call to any
- // user lock functions (true).
-#if KMP_USE_DYNAMIC_LOCK
- __kmp_init_dynamic_user_locks();
-#else
- __kmp_set_user_lock_vptrs( __kmp_user_lock_kind );
-#endif
- }
-
-#if KMP_AFFINITY_SUPPORTED
-
- if ( ! TCR_4(__kmp_init_middle) ) {
- //
- // Determine if the machine/OS is actually capable of supporting
- // affinity.
- //
- const char *var = "KMP_AFFINITY";
- KMPAffinity::pick_api();
- if ( __kmp_affinity_type == affinity_disabled ) {
- KMP_AFFINITY_DISABLE();
- }
- else if ( ! KMP_AFFINITY_CAPABLE() ) {
- __kmp_affinity_dispatch->determine_capable(var);
- if ( ! KMP_AFFINITY_CAPABLE() ) {
- if ( __kmp_affinity_verbose || ( __kmp_affinity_warnings
- && ( __kmp_affinity_type != affinity_default )
- && ( __kmp_affinity_type != affinity_none )
- && ( __kmp_affinity_type != affinity_disabled ) ) ) {
- KMP_WARNING( AffNotSupported, var );
- }
- __kmp_affinity_type = affinity_disabled;
- __kmp_affinity_respect_mask = 0;
- __kmp_affinity_gran = affinity_gran_fine;
- }
- }
-
-# if OMP_40_ENABLED
- if ( __kmp_affinity_type == affinity_disabled ) {
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
- }
- else if ( __kmp_nested_proc_bind.bind_types[0] == proc_bind_true ) {
- //
- // OMP_PROC_BIND=true maps to OMP_PROC_BIND=spread.
- //
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_spread;
- }
-# endif /* OMP_40_ENABLED */
-
- if ( KMP_AFFINITY_CAPABLE() ) {
-
-# if KMP_GROUP_AFFINITY
-
- //
- // Handle the Win 64 group affinity stuff if there are multiple
- // processor groups, or if the user requested it, and OMP 4.0
- // affinity is not in effect.
- //
- if ( ( ( __kmp_num_proc_groups > 1 )
- && ( __kmp_affinity_type == affinity_default )
-# if OMP_40_ENABLED
- && ( __kmp_nested_proc_bind.bind_types[0] == proc_bind_default ) )
-# endif
- || ( __kmp_affinity_top_method == affinity_top_method_group ) ) {
- if ( __kmp_affinity_respect_mask == affinity_respect_mask_default ) {
- __kmp_affinity_respect_mask = FALSE;
- }
- if ( __kmp_affinity_type == affinity_default ) {
- __kmp_affinity_type = affinity_compact;
-# if OMP_40_ENABLED
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
-# endif
- }
- if ( __kmp_affinity_top_method == affinity_top_method_default ) {
- if ( __kmp_affinity_gran == affinity_gran_default ) {
- __kmp_affinity_top_method = affinity_top_method_group;
- __kmp_affinity_gran = affinity_gran_group;
- }
- else if ( __kmp_affinity_gran == affinity_gran_group ) {
- __kmp_affinity_top_method = affinity_top_method_group;
- }
- else {
- __kmp_affinity_top_method = affinity_top_method_all;
- }
- }
- else if ( __kmp_affinity_top_method == affinity_top_method_group ) {
- if ( __kmp_affinity_gran == affinity_gran_default ) {
- __kmp_affinity_gran = affinity_gran_group;
- }
- else if ( ( __kmp_affinity_gran != affinity_gran_group )
- && ( __kmp_affinity_gran != affinity_gran_fine )
- && ( __kmp_affinity_gran != affinity_gran_thread ) ) {
- const char *str = NULL;
- switch ( __kmp_affinity_gran ) {
- case affinity_gran_core: str = "core"; break;
- case affinity_gran_package: str = "package"; break;
- case affinity_gran_node: str = "node"; break;
- default: KMP_DEBUG_ASSERT( 0 );
- }
- KMP_WARNING( AffGranTopGroup, var, str );
- __kmp_affinity_gran = affinity_gran_fine;
- }
- }
- else {
- if ( __kmp_affinity_gran == affinity_gran_default ) {
- __kmp_affinity_gran = affinity_gran_core;
- }
- else if ( __kmp_affinity_gran == affinity_gran_group ) {
- const char *str = NULL;
- switch ( __kmp_affinity_type ) {
- case affinity_physical: str = "physical"; break;
- case affinity_logical: str = "logical"; break;
- case affinity_compact: str = "compact"; break;
- case affinity_scatter: str = "scatter"; break;
- case affinity_explicit: str = "explicit"; break;
- // No MIC on windows, so no affinity_balanced case
- default: KMP_DEBUG_ASSERT( 0 );
- }
- KMP_WARNING( AffGranGroupType, var, str );
- __kmp_affinity_gran = affinity_gran_core;
- }
- }
- }
- else
-
-# endif /* KMP_GROUP_AFFINITY */
-
- {
- if ( __kmp_affinity_respect_mask == affinity_respect_mask_default ) {
-# if KMP_GROUP_AFFINITY
- if ( __kmp_num_proc_groups > 1 ) {
- __kmp_affinity_respect_mask = FALSE;
- }
- else
-# endif /* KMP_GROUP_AFFINITY */
- {
- __kmp_affinity_respect_mask = TRUE;
- }
- }
-# if OMP_40_ENABLED
- if ( ( __kmp_nested_proc_bind.bind_types[0] != proc_bind_intel )
- && ( __kmp_nested_proc_bind.bind_types[0] != proc_bind_default ) ) {
- if ( __kmp_affinity_type == affinity_default ) {
- __kmp_affinity_type = affinity_compact;
- __kmp_affinity_dups = FALSE;
- }
- }
- else
-# endif /* OMP_40_ENABLED */
- if ( __kmp_affinity_type == affinity_default ) {
-#if OMP_40_ENABLED
-#if KMP_ARCH_X86_64 && (KMP_OS_LINUX || KMP_OS_WINDOWS)
- if( __kmp_mic_type != non_mic ) {
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
- } else
-#endif
- {
- __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
- }
-#endif /* OMP_40_ENABLED */
-#if KMP_ARCH_X86_64 && (KMP_OS_LINUX || KMP_OS_WINDOWS)
- if( __kmp_mic_type != non_mic ) {
- __kmp_affinity_type = affinity_scatter;
- } else
-#endif
- {
- __kmp_affinity_type = affinity_none;
- }
-
- }
- if ( ( __kmp_affinity_gran == affinity_gran_default )
- && ( __kmp_affinity_gran_levels < 0 ) ) {
-#if KMP_ARCH_X86_64 && (KMP_OS_LINUX || KMP_OS_WINDOWS)
- if( __kmp_mic_type != non_mic ) {
- __kmp_affinity_gran = affinity_gran_fine;
- } else
-#endif
- {
- __kmp_affinity_gran = affinity_gran_core;
- }
- }
- if ( __kmp_affinity_top_method == affinity_top_method_default ) {
- __kmp_affinity_top_method = affinity_top_method_all;
- }
- }
- }
-
- K_DIAG( 1, ( "__kmp_affinity_type == %d\n", __kmp_affinity_type ) );
- K_DIAG( 1, ( "__kmp_affinity_compact == %d\n", __kmp_affinity_compact ) );
- K_DIAG( 1, ( "__kmp_affinity_offset == %d\n", __kmp_affinity_offset ) );
- K_DIAG( 1, ( "__kmp_affinity_verbose == %d\n", __kmp_affinity_verbose ) );
- K_DIAG( 1, ( "__kmp_affinity_warnings == %d\n", __kmp_affinity_warnings ) );
- K_DIAG( 1, ( "__kmp_affinity_respect_mask == %d\n", __kmp_affinity_respect_mask ) );
- K_DIAG( 1, ( "__kmp_affinity_gran == %d\n", __kmp_affinity_gran ) );
-
- KMP_DEBUG_ASSERT( __kmp_affinity_type != affinity_default);
-# if OMP_40_ENABLED
- KMP_DEBUG_ASSERT( __kmp_nested_proc_bind.bind_types[0] != proc_bind_default );
-# endif
- }
-
-#endif /* KMP_AFFINITY_SUPPORTED */
-
- if ( __kmp_version ) {
- __kmp_print_version_1();
- }; // if
-
- // Post-initialization step: some env. vars need their value's further processing
- if ( string != NULL) { // kmp_set_defaults() was called
- __kmp_aux_env_initialize( &block );
- }
-
- __kmp_env_blk_free( & block );
-
- KMP_MB();
-
-} // __kmp_env_initialize
-
-
-void
-__kmp_env_print() {
-
- kmp_env_blk_t block;
- int i;
- kmp_str_buf_t buffer;
-
- __kmp_stg_init();
- __kmp_str_buf_init( & buffer );
-
- __kmp_env_blk_init( & block, NULL );
- __kmp_env_blk_sort( & block );
-
- // Print real environment values.
- __kmp_str_buf_print( & buffer, "\n%s\n\n", KMP_I18N_STR( UserSettings ) );
- for ( i = 0; i < block.count; ++ i ) {
- char const * name = block.vars[ i ].name;
- char const * value = block.vars[ i ].value;
- if (
- ( KMP_STRLEN( name ) > 4 && strncmp( name, "KMP_", 4 ) == 0 )
- || strncmp( name, "OMP_", 4 ) == 0
- #ifdef KMP_GOMP_COMPAT
- || strncmp( name, "GOMP_", 5 ) == 0
- #endif // KMP_GOMP_COMPAT
- ) {
- __kmp_str_buf_print( & buffer, " %s=%s\n", name, value );
- }; // if
- }; // for
- __kmp_str_buf_print( & buffer, "\n" );
-
- // Print internal (effective) settings.
- __kmp_str_buf_print( & buffer, "%s\n\n", KMP_I18N_STR( EffectiveSettings ) );
- for ( int i = 0; i < __kmp_stg_count; ++ i ) {
- if ( __kmp_stg_table[ i ].print != NULL ) {
- __kmp_stg_table[ i ].print( & buffer, __kmp_stg_table[ i ].name, __kmp_stg_table[ i ].data );
- }; // if
- }; // for
-
- __kmp_printf( "%s", buffer.str );
-
- __kmp_env_blk_free( & block );
- __kmp_str_buf_free( & buffer );
-
- __kmp_printf("\n");
-
-} // __kmp_env_print
-
-
-#if OMP_40_ENABLED
-void
-__kmp_env_print_2() {
-
- kmp_env_blk_t block;
- kmp_str_buf_t buffer;
-
- __kmp_env_format = 1;
-
- __kmp_stg_init();
- __kmp_str_buf_init( & buffer );
-
- __kmp_env_blk_init( & block, NULL );
- __kmp_env_blk_sort( & block );
-
- __kmp_str_buf_print( & buffer, "\n%s\n", KMP_I18N_STR( DisplayEnvBegin ) );
- __kmp_str_buf_print( & buffer, " _OPENMP='%d'\n", __kmp_openmp_version );
-
- for ( int i = 0; i < __kmp_stg_count; ++ i ) {
- if ( __kmp_stg_table[ i ].print != NULL &&
- ( ( __kmp_display_env && strncmp( __kmp_stg_table[ i ].name, "OMP_", 4 ) == 0 ) || __kmp_display_env_verbose ) ) {
- __kmp_stg_table[ i ].print( & buffer, __kmp_stg_table[ i ].name, __kmp_stg_table[ i ].data );
- }; // if
- }; // for
-
- __kmp_str_buf_print( & buffer, "%s\n", KMP_I18N_STR( DisplayEnvEnd ) );
- __kmp_str_buf_print( & buffer, "\n" );
-
- __kmp_printf( "%s", buffer.str );
-
- __kmp_env_blk_free( & block );
- __kmp_str_buf_free( & buffer );
-
- __kmp_printf("\n");
-
-} // __kmp_env_print_2
-#endif // OMP_40_ENABLED
-
-// end of file
-
Removed: openmp/trunk/runtime/src/kmp_str.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/kmp_str.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/kmp_str.c (original)
+++ openmp/trunk/runtime/src/kmp_str.c (removed)
@@ -1,880 +0,0 @@
-/*
- * kmp_str.c -- String manipulation routines.
- */
-
-
-//===----------------------------------------------------------------------===//
-//
-// 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_str.h"
-
-#include <stdarg.h> // va_*
-#include <stdio.h> // vsnprintf()
-#include <stdlib.h> // malloc(), realloc()
-
-#include "kmp.h"
-#include "kmp_i18n.h"
-
-/*
- ------------------------------------------------------------------------------------------------
- String buffer.
- ------------------------------------------------------------------------------------------------
-
- Usage:
-
- // Declare buffer and initialize it.
- kmp_str_buf_t buffer;
- __kmp_str_buf_init( & buffer );
-
- // Print to buffer.
- __kmp_str_buf_print( & buffer, "Error in file \"%s\" line %d\n", "foo.c", 12 );
- __kmp_str_buf_print( & buffer, " <%s>\n", line );
-
- // Use buffer contents. buffer.str is a pointer to data, buffer.used is a number of printed
- // characters (not including terminating zero).
- write( fd, buffer.str, buffer.used );
-
- // Free buffer.
- __kmp_str_buf_free( & buffer );
-
- // Alternatively, you can detach allocated memory from buffer:
- __kmp_str_buf_detach( & buffer );
- return buffer.str; // That memory should be freed eventually.
-
-
- Notes:
-
- * Buffer users may use buffer.str and buffer.used. Users should not change any fields of
- buffer directly.
-
- * buffer.str is never NULL. If buffer is empty, buffer.str points to empty string ("").
-
- * For performance reasons, buffer uses stack memory (buffer.bulk) first. If stack memory is
- exhausted, buffer allocates memory on heap by malloc(), and reallocates it by realloc()
- as amount of used memory grows.
-
- * Buffer doubles amount of allocated memory each time it is exhausted.
-
- ------------------------------------------------------------------------------------------------
-*/
-
-// TODO: __kmp_str_buf_print() can use thread local memory allocator.
-
-#define KMP_STR_BUF_INVARIANT( b ) \
- { \
- KMP_DEBUG_ASSERT( (b)->str != NULL ); \
- KMP_DEBUG_ASSERT( (b)->size >= sizeof( (b)->bulk ) ); \
- KMP_DEBUG_ASSERT( (b)->size % sizeof( (b)->bulk ) == 0 ); \
- KMP_DEBUG_ASSERT( (unsigned)(b)->used < (b)->size ); \
- KMP_DEBUG_ASSERT( (b)->size == sizeof( (b)->bulk ) ? (b)->str == & (b)->bulk[ 0 ] : 1 ); \
- KMP_DEBUG_ASSERT( (b)->size > sizeof( (b)->bulk ) ? (b)->str != & (b)->bulk[ 0 ] : 1 ); \
- }
-
-void
- __kmp_str_buf_clear(
- kmp_str_buf_t * buffer
-) {
- KMP_STR_BUF_INVARIANT( buffer );
- if ( buffer->used > 0 ) {
- buffer->used = 0;
- buffer->str[ 0 ] = 0;
- }; // if
- KMP_STR_BUF_INVARIANT( buffer );
-} // __kmp_str_buf_clear
-
-
-void
-__kmp_str_buf_reserve(
- kmp_str_buf_t * buffer,
- int size
-) {
-
- KMP_STR_BUF_INVARIANT( buffer );
- KMP_DEBUG_ASSERT( size >= 0 );
-
- if ( buffer->size < (unsigned int)size ) {
-
- // Calculate buffer size.
- do {
- buffer->size *= 2;
- } while ( buffer->size < (unsigned int)size );
-
- // Enlarge buffer.
- if ( buffer->str == & buffer->bulk[ 0 ] ) {
- buffer->str = (char *) KMP_INTERNAL_MALLOC( buffer->size );
- if ( buffer->str == NULL ) {
- KMP_FATAL( MemoryAllocFailed );
- }; // if
- KMP_MEMCPY_S( buffer->str, buffer->size, buffer->bulk, buffer->used + 1 );
- } else {
- buffer->str = (char *) KMP_INTERNAL_REALLOC( buffer->str, buffer->size );
- if ( buffer->str == NULL ) {
- KMP_FATAL( MemoryAllocFailed );
- }; // if
- }; // if
-
- }; // if
-
- KMP_DEBUG_ASSERT( buffer->size > 0 );
- KMP_DEBUG_ASSERT( buffer->size >= (unsigned)size );
- KMP_STR_BUF_INVARIANT( buffer );
-
-} // __kmp_str_buf_reserve
-
-
-void
-__kmp_str_buf_detach(
- kmp_str_buf_t * buffer
-) {
-
- KMP_STR_BUF_INVARIANT( buffer );
-
- // If internal bulk is used, allocate memory and copy it.
- if ( buffer->size <= sizeof( buffer->bulk ) ) {
- buffer->str = (char *) KMP_INTERNAL_MALLOC( buffer->size );
- if ( buffer->str == NULL ) {
- KMP_FATAL( MemoryAllocFailed );
- }; // if
- KMP_MEMCPY_S( buffer->str, buffer->size, buffer->bulk, buffer->used + 1 );
- }; // if
-
-} // __kmp_str_buf_detach
-
-
-void
-__kmp_str_buf_free(
- kmp_str_buf_t * buffer
-) {
- KMP_STR_BUF_INVARIANT( buffer );
- if ( buffer->size > sizeof( buffer->bulk ) ) {
- KMP_INTERNAL_FREE( buffer->str );
- }; // if
- buffer->str = buffer->bulk;
- buffer->size = sizeof( buffer->bulk );
- buffer->used = 0;
- KMP_STR_BUF_INVARIANT( buffer );
-} // __kmp_str_buf_free
-
-
-void
-__kmp_str_buf_cat(
- kmp_str_buf_t * buffer,
- char const * str,
- int len
-) {
- KMP_STR_BUF_INVARIANT( buffer );
- KMP_DEBUG_ASSERT( str != NULL );
- KMP_DEBUG_ASSERT( len >= 0 );
- __kmp_str_buf_reserve( buffer, buffer->used + len + 1 );
- KMP_MEMCPY( buffer->str + buffer->used, str, len );
- buffer->str[ buffer->used + len ] = 0;
- buffer->used += len;
- KMP_STR_BUF_INVARIANT( buffer );
-} // __kmp_str_buf_cat
-
-
-void
-__kmp_str_buf_vprint(
- kmp_str_buf_t * buffer,
- char const * format,
- va_list args
-) {
-
- KMP_STR_BUF_INVARIANT( buffer );
-
- for ( ; ; ) {
-
- int const free = buffer->size - buffer->used;
- int rc;
- int size;
-
- // Try to format string.
- {
- /*
- On Linux* OS Intel(R) 64, vsnprintf() modifies args argument, so vsnprintf() crashes if it
- is called for the second time with the same args. To prevent the crash, we have to
- pass a fresh intact copy of args to vsnprintf() on each iteration.
-
- Unfortunately, standard va_copy() macro is not available on Windows* OS. However, it
- seems vsnprintf() does not modify args argument on Windows* OS.
- */
-
- #if ! KMP_OS_WINDOWS
- va_list _args;
- __va_copy( _args, args ); // Make copy of args.
- #define args _args // Substitute args with its copy, _args.
- #endif // KMP_OS_WINDOWS
- rc = KMP_VSNPRINTF( buffer->str + buffer->used, free, format, args );
- #if ! KMP_OS_WINDOWS
- #undef args // Remove substitution.
- va_end( _args );
- #endif // KMP_OS_WINDOWS
- }
-
- // No errors, string has been formatted.
- if ( rc >= 0 && rc < free ) {
- buffer->used += rc;
- break;
- }; // if
-
- // Error occurred, buffer is too small.
- if ( rc >= 0 ) {
- // C99-conforming implementation of vsnprintf returns required buffer size.
- size = buffer->used + rc + 1;
- } else {
- // Older implementations just return -1. Double buffer size.
- size = buffer->size * 2;
- }; // if
-
- // Enlarge buffer.
- __kmp_str_buf_reserve( buffer, size );
-
- // And try again.
-
- }; // forever
-
- KMP_DEBUG_ASSERT( buffer->size > 0 );
- KMP_STR_BUF_INVARIANT( buffer );
-
-} // __kmp_str_buf_vprint
-
-
-void
-__kmp_str_buf_print(
- kmp_str_buf_t * buffer,
- char const * format,
- ...
-) {
-
- va_list args;
- va_start( args, format );
- __kmp_str_buf_vprint( buffer, format, args );
- va_end( args );
-
-} // __kmp_str_buf_print
-
-
-/*
- The function prints specified size to buffer. Size is expressed using biggest possible unit, for
- example 1024 is printed as "1k".
-*/
-
-void
-__kmp_str_buf_print_size(
- kmp_str_buf_t * buf,
- size_t size
-) {
-
- char const * names[] = { "", "k", "M", "G", "T", "P", "E", "Z", "Y" };
- int const units = sizeof( names ) / sizeof( char const * );
- int u = 0;
- if ( size > 0 ) {
- while ( ( size % 1024 == 0 ) && ( u + 1 < units ) ) {
- size = size / 1024;
- ++ u;
- }; // while
- }; // if
-
- __kmp_str_buf_print( buf, "%" KMP_SIZE_T_SPEC "%s", size, names[ u ] );
-
-} // __kmp_str_buf_print_size
-
-
-void
-__kmp_str_fname_init(
- kmp_str_fname_t * fname,
- char const * path
-) {
-
- fname->path = NULL;
- fname->dir = NULL;
- fname->base = NULL;
-
- if ( path != NULL ) {
- char * slash = NULL; // Pointer to the last character of dir.
- char * base = NULL; // Pointer to the beginning of basename.
- fname->path = __kmp_str_format( "%s", path );
- // Original code used strdup() function to copy a string, but on Windows* OS Intel(R) 64 it
- // causes assertioon id debug heap, so I had to replace strdup with __kmp_str_format().
- if ( KMP_OS_WINDOWS ) {
- __kmp_str_replace( fname->path, '\\', '/' );
- }; // if
- fname->dir = __kmp_str_format( "%s", fname->path );
- slash = strrchr( fname->dir, '/' );
- if ( KMP_OS_WINDOWS && slash == NULL ) { // On Windows* OS, if slash not found,
- char first = TOLOWER( fname->dir[ 0 ] ); // look for drive.
- if ( 'a' <= first && first <= 'z' && fname->dir[ 1 ] == ':' ) {
- slash = & fname->dir[ 1 ];
- }; // if
- }; // if
- base = ( slash == NULL ? fname->dir : slash + 1 );
- fname->base = __kmp_str_format( "%s", base ); // Copy basename
- * base = 0; // and truncate dir.
- }; // if
-
-} // kmp_str_fname_init
-
-
-void
-__kmp_str_fname_free(
- kmp_str_fname_t * fname
-) {
- __kmp_str_free( (char const **)( & fname->path ) );
- __kmp_str_free( (char const **)( & fname->dir ) );
- __kmp_str_free( (char const **)( & fname->base ) );
-} // kmp_str_fname_free
-
-
-int
-__kmp_str_fname_match(
- kmp_str_fname_t const * fname,
- char const * pattern
-) {
-
- int dir_match = 1;
- int base_match = 1;
-
- if ( pattern != NULL ) {
- kmp_str_fname_t ptrn;
- __kmp_str_fname_init( & ptrn, pattern );
- dir_match =
- strcmp( ptrn.dir, "*/" ) == 0
- ||
- ( fname->dir != NULL && __kmp_str_eqf( fname->dir, ptrn.dir ) );
- base_match =
- strcmp( ptrn.base, "*" ) == 0
- ||
- ( fname->base != NULL && __kmp_str_eqf( fname->base, ptrn.base ) );
- __kmp_str_fname_free( & ptrn );
- }; // if
-
- return dir_match && base_match;
-
-} // __kmp_str_fname_match
-
-
-kmp_str_loc_t
-__kmp_str_loc_init(
- char const * psource,
- int init_fname
-) {
-
- kmp_str_loc_t loc;
-
- loc._bulk = NULL;
- loc.file = NULL;
- loc.func = NULL;
- loc.line = 0;
- loc.col = 0;
-
- if ( psource != NULL ) {
-
- char * str = NULL;
- char * dummy = NULL;
- char * line = NULL;
- char * col = NULL;
-
- // Copy psource to keep it intact.
- loc._bulk = __kmp_str_format( "%s", psource );
-
- // Parse psource string: ";file;func;line;col;;"
- str = loc._bulk;
- __kmp_str_split( str, ';', & dummy, & str );
- __kmp_str_split( str, ';', & loc.file, & str );
- __kmp_str_split( str, ';', & loc.func, & str );
- __kmp_str_split( str, ';', & line, & str );
- __kmp_str_split( str, ';', & col, & str );
-
- // Convert line and col into numberic values.
- if ( line != NULL ) {
- loc.line = atoi( line );
- if ( loc.line < 0 ) {
- loc.line = 0;
- }; // if
- }; // if
- if ( col != NULL ) {
- loc.col = atoi( col );
- if ( loc.col < 0 ) {
- loc.col = 0;
- }; // if
- }; // if
-
- }; // if
-
- __kmp_str_fname_init( & loc.fname, init_fname ? loc.file : NULL );
-
- return loc;
-
-} // kmp_str_loc_init
-
-
-void
-__kmp_str_loc_free(
- kmp_str_loc_t * loc
-) {
- __kmp_str_fname_free( & loc->fname );
- __kmp_str_free((const char **) &(loc->_bulk));
- loc->file = NULL;
- loc->func = NULL;
-} // kmp_str_loc_free
-
-
-
-/*
- This function is intended to compare file names. On Windows* OS file names are case-insensitive,
- so functions performs case-insensitive comparison. On Linux* OS it performs case-sensitive
- comparison.
- Note: The function returns *true* if strings are *equal*.
-*/
-
-int
-__kmp_str_eqf( // True, if strings are equal, false otherwise.
- char const * lhs, // First string.
- char const * rhs // Second string.
-) {
- int result;
- #if KMP_OS_WINDOWS
- result = ( _stricmp( lhs, rhs ) == 0 );
- #else
- result = ( strcmp( lhs, rhs ) == 0 );
- #endif
- return result;
-} // __kmp_str_eqf
-
-
-/*
- This function is like sprintf, but it *allocates* new buffer, which must be freed eventually by
- __kmp_str_free(). The function is very convenient for constructing strings, it successfully
- replaces strdup(), strcat(), it frees programmer from buffer allocations and helps to avoid
- buffer overflows. Examples:
-
- str = __kmp_str_format( "%s", orig ); // strdup(), do not care about buffer size.
- __kmp_str_free( & str );
- str = __kmp_str_format( "%s%s", orig1, orig2 ); // strcat(), do not care about buffer size.
- __kmp_str_free( & str );
- str = __kmp_str_format( "%s/%s.txt", path, file ); // constructing string.
- __kmp_str_free( & str );
-
- Performance note:
- This function allocates memory with malloc() calls, so do not call it from
- performance-critical code. In performance-critical code consider using kmp_str_buf_t
- instead, since it uses stack-allocated buffer for short strings.
-
- Why does this function use malloc()?
- 1. __kmp_allocate() returns cache-aligned memory allocated with malloc(). There are no
- reasons in using __kmp_allocate() for strings due to extra overhead while cache-aligned
- memory is not necessary.
- 2. __kmp_thread_malloc() cannot be used because it requires pointer to thread structure.
- We need to perform string operations during library startup (for example, in
- __kmp_register_library_startup()) when no thread structures are allocated yet.
- So standard malloc() is the only available option.
-*/
-
-char *
-__kmp_str_format( // Allocated string.
- char const * format, // Format string.
- ... // Other parameters.
-) {
-
- va_list args;
- int size = 512;
- char * buffer = NULL;
- int rc;
-
- // Allocate buffer.
- buffer = (char *) KMP_INTERNAL_MALLOC( size );
- if ( buffer == NULL ) {
- KMP_FATAL( MemoryAllocFailed );
- }; // if
-
- for ( ; ; ) {
-
- // Try to format string.
- va_start( args, format );
- rc = KMP_VSNPRINTF( buffer, size, format, args );
- va_end( args );
-
- // No errors, string has been formatted.
- if ( rc >= 0 && rc < size ) {
- break;
- }; // if
-
- // Error occurred, buffer is too small.
- if ( rc >= 0 ) {
- // C99-conforming implementation of vsnprintf returns required buffer size.
- size = rc + 1;
- } else {
- // Older implementations just return -1.
- size = size * 2;
- }; // if
-
- // Enlarge buffer and try again.
- buffer = (char *) KMP_INTERNAL_REALLOC( buffer, size );
- if ( buffer == NULL ) {
- KMP_FATAL( MemoryAllocFailed );
- }; // if
-
- }; // forever
-
- return buffer;
-
-} // func __kmp_str_format
-
-
-void
-__kmp_str_free(
- char const * * str
-) {
- KMP_DEBUG_ASSERT( str != NULL );
- KMP_INTERNAL_FREE( (void *) * str );
- * str = NULL;
-} // func __kmp_str_free
-
-
-/* If len is zero, returns true iff target and data have exact case-insensitive match.
- If len is negative, returns true iff target is a case-insensitive substring of data.
- If len is positive, returns true iff target is a case-insensitive substring of data or
- vice versa, and neither is shorter than len.
-*/
-int
-__kmp_str_match(
- char const * target,
- int len,
- char const * data
-) {
- int i;
- if ( target == NULL || data == NULL ) {
- return FALSE;
- }; // if
- for ( i = 0; target[i] && data[i]; ++ i ) {
- if ( TOLOWER( target[i] ) != TOLOWER( data[i] ) ) {
- return FALSE;
- }; // if
- }; // for i
- return ( ( len > 0 ) ? i >= len : ( ! target[i] && ( len || ! data[i] ) ) );
-} // __kmp_str_match
-
-
-int
-__kmp_str_match_false( char const * data ) {
- int result =
- __kmp_str_match( "false", 1, data ) ||
- __kmp_str_match( "off", 2, data ) ||
- __kmp_str_match( "0", 1, data ) ||
- __kmp_str_match( ".false.", 2, data ) ||
- __kmp_str_match( ".f.", 2, data ) ||
- __kmp_str_match( "no", 1, data );
- return result;
-} // __kmp_str_match_false
-
-
-int
-__kmp_str_match_true( char const * data ) {
- int result =
- __kmp_str_match( "true", 1, data ) ||
- __kmp_str_match( "on", 2, data ) ||
- __kmp_str_match( "1", 1, data ) ||
- __kmp_str_match( ".true.", 2, data ) ||
- __kmp_str_match( ".t.", 2, data ) ||
- __kmp_str_match( "yes", 1, data );
- return result;
-} // __kmp_str_match_true
-
-void
-__kmp_str_replace(
- char * str,
- char search_for,
- char replace_with
-) {
-
- char * found = NULL;
-
- found = strchr( str, search_for );
- while ( found ) {
- * found = replace_with;
- found = strchr( found + 1, search_for );
- }; // while
-
-} // __kmp_str_replace
-
-
-void
-__kmp_str_split(
- char * str, // I: String to split.
- char delim, // I: Character to split on.
- char ** head, // O: Pointer to head (may be NULL).
- char ** tail // O: Pointer to tail (may be NULL).
-) {
- char * h = str;
- char * t = NULL;
- if ( str != NULL ) {
- char * ptr = strchr( str, delim );
- if ( ptr != NULL ) {
- * ptr = 0;
- t = ptr + 1;
- }; // if
- }; // if
- if ( head != NULL ) {
- * head = h;
- }; // if
- if ( tail != NULL ) {
- * tail = t;
- }; // if
-} // __kmp_str_split
-
-/*
- strtok_r() is not available on Windows* OS. This function reimplements strtok_r().
-*/
-char *
-__kmp_str_token(
- char * str, // String to split into tokens. Note: String *is* modified!
- char const * delim, // Delimiters.
- char ** buf // Internal buffer.
-) {
- char * token = NULL;
- #if KMP_OS_WINDOWS
- // On Windows* OS there is no strtok_r() function. Let us implement it.
- if ( str != NULL ) {
- * buf = str; // First call, initialize buf.
- }; // if
- * buf += strspn( * buf, delim ); // Skip leading delimiters.
- if ( ** buf != 0 ) { // Rest of the string is not yet empty.
- token = * buf; // Use it as result.
- * buf += strcspn( * buf, delim ); // Skip non-delimiters.
- if ( ** buf != 0 ) { // Rest of the string is not yet empty.
- ** buf = 0; // Terminate token here.
- * buf += 1; // Advance buf to start with the next token next time.
- }; // if
- }; // if
- #else
- // On Linux* OS and OS X*, strtok_r() is available. Let us use it.
- token = strtok_r( str, delim, buf );
- #endif
- return token;
-}; // __kmp_str_token
-
-
-int
-__kmp_str_to_int(
- char const * str,
- char sentinel
-) {
- int result, factor;
- char const * t;
-
- result = 0;
-
- for (t = str; *t != '\0'; ++t) {
- if (*t < '0' || *t > '9')
- break;
- result = (result * 10) + (*t - '0');
- }
-
- switch (*t) {
- case '\0': /* the current default for no suffix is bytes */
- factor = 1;
- break;
- case 'b': case 'B': /* bytes */
- ++t;
- factor = 1;
- break;
- case 'k': case 'K': /* kilo-bytes */
- ++t;
- factor = 1024;
- break;
- case 'm': case 'M': /* mega-bytes */
- ++t;
- factor = (1024 * 1024);
- break;
- default:
- if(*t != sentinel)
- return (-1);
- t = "";
- factor = 1;
- }
-
- if (result > (INT_MAX / factor))
- result = INT_MAX;
- else
- result *= factor;
-
- return (*t != 0 ? 0 : result);
-
-} // __kmp_str_to_int
-
-
-/*
- The routine parses input string. It is expected it is a unsigned integer with optional unit.
- Units are: "b" for bytes, "kb" or just "k" for kilobytes, "mb" or "m" for megabytes, ..., "yb"
- or "y" for yottabytes. :-) Unit name is case-insensitive. The routine returns 0 if everything is
- ok, or error code: -1 in case of overflow, -2 in case of unknown unit. *size is set to parsed
- value. In case of overflow *size is set to KMP_SIZE_T_MAX, in case of unknown unit *size is set
- to zero.
-*/
-void
-__kmp_str_to_size( // R: Error code.
- char const * str, // I: String of characters, unsigned number and unit ("b", "kb", etc).
- size_t * out, // O: Parsed number.
- size_t dfactor, // I: The factor if none of the letters specified.
- char const * * error // O: Null if everything is ok, error message otherwise.
-) {
-
- size_t value = 0;
- size_t factor = 0;
- int overflow = 0;
- int i = 0;
- int digit;
-
-
- KMP_DEBUG_ASSERT( str != NULL );
-
- // Skip spaces.
- while ( str[ i ] == ' ' || str[ i ] == '\t') {
- ++ i;
- }; // while
-
- // Parse number.
- if ( str[ i ] < '0' || str[ i ] > '9' ) {
- * error = KMP_I18N_STR( NotANumber );
- return;
- }; // if
- do {
- digit = str[ i ] - '0';
- overflow = overflow || ( value > ( KMP_SIZE_T_MAX - digit ) / 10 );
- value = ( value * 10 ) + digit;
- ++ i;
- } while ( str[ i ] >= '0' && str[ i ] <= '9' );
-
- // Skip spaces.
- while ( str[ i ] == ' ' || str[ i ] == '\t' ) {
- ++ i;
- }; // while
-
- // Parse unit.
- #define _case( ch, exp ) \
- case ch : \
- case ch - ( 'a' - 'A' ) : { \
- size_t shift = (exp) * 10; \
- ++ i; \
- if ( shift < sizeof( size_t ) * 8 ) { \
- factor = (size_t)( 1 ) << shift; \
- } else { \
- overflow = 1; \
- }; \
- } break;
- switch ( str[ i ] ) {
- _case( 'k', 1 ); // Kilo
- _case( 'm', 2 ); // Mega
- _case( 'g', 3 ); // Giga
- _case( 't', 4 ); // Tera
- _case( 'p', 5 ); // Peta
- _case( 'e', 6 ); // Exa
- _case( 'z', 7 ); // Zetta
- _case( 'y', 8 ); // Yotta
- // Oops. No more units...
- }; // switch
- #undef _case
- if ( str[ i ] == 'b' || str[ i ] == 'B' ) { // Skip optional "b".
- if ( factor == 0 ) {
- factor = 1;
- }
- ++ i;
- }; // if
- if ( ! ( str[ i ] == ' ' || str[ i ] == '\t' || str[ i ] == 0 ) ) { // Bad unit
- * error = KMP_I18N_STR( BadUnit );
- return;
- }; // if
-
- if ( factor == 0 ) {
- factor = dfactor;
- }
-
- // Apply factor.
- overflow = overflow || ( value > ( KMP_SIZE_T_MAX / factor ) );
- value *= factor;
-
- // Skip spaces.
- while ( str[ i ] == ' ' || str[ i ] == '\t' ) {
- ++ i;
- }; // while
-
- if ( str[ i ] != 0 ) {
- * error = KMP_I18N_STR( IllegalCharacters );
- return;
- }; // if
-
- if ( overflow ) {
- * error = KMP_I18N_STR( ValueTooLarge );
- * out = KMP_SIZE_T_MAX;
- return;
- }; // if
-
- * error = NULL;
- * out = value;
-
-} // __kmp_str_to_size
-
-
-void
-__kmp_str_to_uint( // R: Error code.
- char const * str, // I: String of characters, unsigned number.
- kmp_uint64 * out, // O: Parsed number.
- char const * * error // O: Null if everything is ok, error message otherwise.
-) {
-
- size_t value = 0;
- int overflow = 0;
- int i = 0;
- int digit;
-
-
- KMP_DEBUG_ASSERT( str != NULL );
-
- // Skip spaces.
- while ( str[ i ] == ' ' || str[ i ] == '\t' ) {
- ++ i;
- }; // while
-
- // Parse number.
- if ( str[ i ] < '0' || str[ i ] > '9' ) {
- * error = KMP_I18N_STR( NotANumber );
- return;
- }; // if
- do {
- digit = str[ i ] - '0';
- overflow = overflow || ( value > ( KMP_SIZE_T_MAX - digit ) / 10 );
- value = ( value * 10 ) + digit;
- ++ i;
- } while ( str[ i ] >= '0' && str[ i ] <= '9' );
-
- // Skip spaces.
- while ( str[ i ] == ' ' || str[ i ] == '\t' ) {
- ++ i;
- }; // while
-
- if ( str[ i ] != 0 ) {
- * error = KMP_I18N_STR( IllegalCharacters );
- return;
- }; // if
-
- if ( overflow ) {
- * error = KMP_I18N_STR( ValueTooLarge );
- * out = (kmp_uint64) -1;
- return;
- }; // if
-
- * error = NULL;
- * out = value;
-
-} // __kmp_str_to_unit
-
-
-
-// end of file //
Removed: openmp/trunk/runtime/src/kmp_stub.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/kmp_stub.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/kmp_stub.c (original)
+++ openmp/trunk/runtime/src/kmp_stub.c (removed)
@@ -1,270 +0,0 @@
-/*
- * kmp_stub.c -- stub versions of user-callable OpenMP RT functions.
- */
-
-
-//===----------------------------------------------------------------------===//
-//
-// 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 <stdlib.h>
-#include <limits.h>
-#include <errno.h>
-
-#include "omp.h" // Function renamings.
-#include "kmp.h" // KMP_DEFAULT_STKSIZE
-#include "kmp_stub.h"
-
-#if KMP_OS_WINDOWS
- #include <windows.h>
-#else
- #include <sys/time.h>
-#endif
-
-// Moved from omp.h
-#define omp_set_max_active_levels ompc_set_max_active_levels
-#define omp_set_schedule ompc_set_schedule
-#define omp_get_ancestor_thread_num ompc_get_ancestor_thread_num
-#define omp_get_team_size ompc_get_team_size
-
-#define omp_set_num_threads ompc_set_num_threads
-#define omp_set_dynamic ompc_set_dynamic
-#define omp_set_nested ompc_set_nested
-#define kmp_set_stacksize kmpc_set_stacksize
-#define kmp_set_stacksize_s kmpc_set_stacksize_s
-#define kmp_set_blocktime kmpc_set_blocktime
-#define kmp_set_library kmpc_set_library
-#define kmp_set_defaults kmpc_set_defaults
-#define kmp_set_disp_num_buffers kmpc_set_disp_num_buffers
-#define kmp_malloc kmpc_malloc
-#define kmp_aligned_malloc kmpc_aligned_malloc
-#define kmp_calloc kmpc_calloc
-#define kmp_realloc kmpc_realloc
-#define kmp_free kmpc_free
-
-static double frequency = 0.0;
-
-// Helper functions.
-static size_t __kmps_init() {
- static int initialized = 0;
- static size_t dummy = 0;
- if ( ! initialized ) {
-
- // TODO: Analyze KMP_VERSION environment variable, print __kmp_version_copyright and
- // __kmp_version_build_time.
- // WARNING: Do not use "fprintf( stderr, ... )" because it will cause unresolved "__iob"
- // symbol (see C70080). We need to extract __kmp_printf() stuff from kmp_runtime.c and use
- // it.
-
- // Trick with dummy variable forces linker to keep __kmp_version_copyright and
- // __kmp_version_build_time strings in executable file (in case of static linkage).
- // When KMP_VERSION analyze is implemented, dummy variable should be deleted, function
- // should return void.
- dummy = __kmp_version_copyright - __kmp_version_build_time;
-
- #if KMP_OS_WINDOWS
- LARGE_INTEGER freq;
- BOOL status = QueryPerformanceFrequency( & freq );
- if ( status ) {
- frequency = double( freq.QuadPart );
- }; // if
- #endif
-
- initialized = 1;
- }; // if
- return dummy;
-}; // __kmps_init
-
-#define i __kmps_init();
-
-/* set API functions */
-void omp_set_num_threads( omp_int_t num_threads ) { i; }
-void omp_set_dynamic( omp_int_t dynamic ) { i; __kmps_set_dynamic( dynamic ); }
-void omp_set_nested( omp_int_t nested ) { i; __kmps_set_nested( nested ); }
-void omp_set_max_active_levels( omp_int_t max_active_levels ) { i; }
-void omp_set_schedule( omp_sched_t kind, omp_int_t modifier ) { i; __kmps_set_schedule( (kmp_sched_t)kind, modifier ); }
-int omp_get_ancestor_thread_num( omp_int_t level ) { i; return ( level ) ? ( -1 ) : ( 0 ); }
-int omp_get_team_size( omp_int_t level ) { i; return ( level ) ? ( -1 ) : ( 1 ); }
-int kmpc_set_affinity_mask_proc( int proc, void **mask ) { i; return -1; }
-int kmpc_unset_affinity_mask_proc( int proc, void **mask ) { i; return -1; }
-int kmpc_get_affinity_mask_proc( int proc, void **mask ) { i; return -1; }
-
-/* kmp API functions */
-void kmp_set_stacksize( omp_int_t arg ) { i; __kmps_set_stacksize( arg ); }
-void kmp_set_stacksize_s( size_t arg ) { i; __kmps_set_stacksize( arg ); }
-void kmp_set_blocktime( omp_int_t arg ) { i; __kmps_set_blocktime( arg ); }
-void kmp_set_library( omp_int_t arg ) { i; __kmps_set_library( arg ); }
-void kmp_set_defaults( char const * str ) { i; }
-void kmp_set_disp_num_buffers( omp_int_t arg ) { i; }
-
-/* KMP memory management functions. */
-void * kmp_malloc( size_t size ) { i; return malloc( size ); }
-void * kmp_aligned_malloc( size_t sz, size_t a ) {
- i;
-#if KMP_OS_WINDOWS
- errno = ENOSYS; // not supported
- return NULL; // no standard aligned allocator on Windows (pre - C11)
-#else
- void *res;
- int err;
- if( err = posix_memalign( &res, a, sz ) ) {
- errno = err; // can be EINVAL or ENOMEM
- return NULL;
- }
- return res;
-#endif
-}
-void * kmp_calloc( size_t nelem, size_t elsize ) { i; return calloc( nelem, elsize ); }
-void * kmp_realloc( void *ptr, size_t size ) { i; return realloc( ptr, size ); }
-void kmp_free( void * ptr ) { i; free( ptr ); }
-
-static int __kmps_blocktime = INT_MAX;
-
-void __kmps_set_blocktime( int arg ) {
- i;
- __kmps_blocktime = arg;
-} // __kmps_set_blocktime
-
-int __kmps_get_blocktime( void ) {
- i;
- return __kmps_blocktime;
-} // __kmps_get_blocktime
-
-static int __kmps_dynamic = 0;
-
-void __kmps_set_dynamic( int arg ) {
- i;
- __kmps_dynamic = arg;
-} // __kmps_set_dynamic
-
-int __kmps_get_dynamic( void ) {
- i;
- return __kmps_dynamic;
-} // __kmps_get_dynamic
-
-static int __kmps_library = 1000;
-
-void __kmps_set_library( int arg ) {
- i;
- __kmps_library = arg;
-} // __kmps_set_library
-
-int __kmps_get_library( void ) {
- i;
- return __kmps_library;
-} // __kmps_get_library
-
-static int __kmps_nested = 0;
-
-void __kmps_set_nested( int arg ) {
- i;
- __kmps_nested = arg;
-} // __kmps_set_nested
-
-int __kmps_get_nested( void ) {
- i;
- return __kmps_nested;
-} // __kmps_get_nested
-
-static size_t __kmps_stacksize = KMP_DEFAULT_STKSIZE;
-
-void __kmps_set_stacksize( int arg ) {
- i;
- __kmps_stacksize = arg;
-} // __kmps_set_stacksize
-
-int __kmps_get_stacksize( void ) {
- i;
- return __kmps_stacksize;
-} // __kmps_get_stacksize
-
-static kmp_sched_t __kmps_sched_kind = kmp_sched_default;
-static int __kmps_sched_modifier = 0;
-
- void __kmps_set_schedule( kmp_sched_t kind, int modifier ) {
- i;
- __kmps_sched_kind = kind;
- __kmps_sched_modifier = modifier;
- } // __kmps_set_schedule
-
- void __kmps_get_schedule( kmp_sched_t *kind, int *modifier ) {
- i;
- *kind = __kmps_sched_kind;
- *modifier = __kmps_sched_modifier;
- } // __kmps_get_schedule
-
-#if OMP_40_ENABLED
-
-static kmp_proc_bind_t __kmps_proc_bind = proc_bind_false;
-
-void __kmps_set_proc_bind( kmp_proc_bind_t arg ) {
- i;
- __kmps_proc_bind = arg;
-} // __kmps_set_proc_bind
-
-kmp_proc_bind_t __kmps_get_proc_bind( void ) {
- i;
- return __kmps_proc_bind;
-} // __kmps_get_proc_bind
-
-#endif /* OMP_40_ENABLED */
-
-double __kmps_get_wtime( void ) {
- // Elapsed wall clock time (in second) from "sometime in the past".
- double wtime = 0.0;
- i;
- #if KMP_OS_WINDOWS
- if ( frequency > 0.0 ) {
- LARGE_INTEGER now;
- BOOL status = QueryPerformanceCounter( & now );
- if ( status ) {
- wtime = double( now.QuadPart ) / frequency;
- }; // if
- }; // if
- #else
- // gettimeofday() returns seconds and microseconds since the Epoch.
- struct timeval tval;
- int rc;
- rc = gettimeofday( & tval, NULL );
- if ( rc == 0 ) {
- wtime = (double)( tval.tv_sec ) + 1.0E-06 * (double)( tval.tv_usec );
- } else {
- // TODO: Assert or abort here.
- }; // if
- #endif
- return wtime;
-}; // __kmps_get_wtime
-
-double __kmps_get_wtick( void ) {
- // Number of seconds between successive clock ticks.
- double wtick = 0.0;
- i;
- #if KMP_OS_WINDOWS
- {
- DWORD increment;
- DWORD adjustment;
- BOOL disabled;
- BOOL rc;
- rc = GetSystemTimeAdjustment( & adjustment, & increment, & disabled );
- if ( rc ) {
- wtick = 1.0E-07 * (double)( disabled ? increment : adjustment );
- } else {
- // TODO: Assert or abort here.
- wtick = 1.0E-03;
- }; // if
- }
- #else
- // TODO: gettimeofday() returns in microseconds, but what the precision?
- wtick = 1.0E-06;
- #endif
- return wtick;
-}; // __kmps_get_wtick
-
-// end of file //
-
Removed: openmp/trunk/runtime/src/kmp_tasking.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/kmp_tasking.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/kmp_tasking.c (original)
+++ openmp/trunk/runtime/src/kmp_tasking.c (removed)
@@ -1,3162 +0,0 @@
-/*
- * kmp_tasking.c -- OpenMP 3.0 tasking 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_i18n.h"
-#include "kmp_itt.h"
-#include "kmp_wait_release.h"
-#include "kmp_stats.h"
-
-#if OMPT_SUPPORT
-#include "ompt-specific.h"
-#endif
-
-#include "tsan_annotations.h"
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-
-/* forward declaration */
-static void __kmp_enable_tasking( kmp_task_team_t *task_team, kmp_info_t *this_thr );
-static void __kmp_alloc_task_deque( kmp_info_t *thread, kmp_thread_data_t *thread_data );
-static int __kmp_realloc_task_threads_data( kmp_info_t *thread, kmp_task_team_t *task_team );
-
-#ifdef OMP_45_ENABLED
-static void __kmp_bottom_half_finish_proxy( kmp_int32 gtid, kmp_task_t * ptask );
-#endif
-
-#ifdef BUILD_TIED_TASK_STACK
-
-//---------------------------------------------------------------------------
-// __kmp_trace_task_stack: print the tied tasks from the task stack in order
-// from top do bottom
-//
-// gtid: global thread identifier for thread containing stack
-// thread_data: thread data for task team thread containing stack
-// threshold: value above which the trace statement triggers
-// location: string identifying call site of this function (for trace)
-
-static void
-__kmp_trace_task_stack( kmp_int32 gtid, kmp_thread_data_t *thread_data, int threshold, char *location )
-{
- kmp_task_stack_t *task_stack = & thread_data->td.td_susp_tied_tasks;
- kmp_taskdata_t **stack_top = task_stack -> ts_top;
- kmp_int32 entries = task_stack -> ts_entries;
- kmp_taskdata_t *tied_task;
-
- KA_TRACE(threshold, ("__kmp_trace_task_stack(start): location = %s, gtid = %d, entries = %d, "
- "first_block = %p, stack_top = %p \n",
- location, gtid, entries, task_stack->ts_first_block, stack_top ) );
-
- KMP_DEBUG_ASSERT( stack_top != NULL );
- KMP_DEBUG_ASSERT( entries > 0 );
-
- while ( entries != 0 )
- {
- KMP_DEBUG_ASSERT( stack_top != & task_stack->ts_first_block.sb_block[0] );
- // fix up ts_top if we need to pop from previous block
- if ( entries & TASK_STACK_INDEX_MASK == 0 )
- {
- kmp_stack_block_t *stack_block = (kmp_stack_block_t *) (stack_top) ;
-
- stack_block = stack_block -> sb_prev;
- stack_top = & stack_block -> sb_block[TASK_STACK_BLOCK_SIZE];
- }
-
- // finish bookkeeping
- stack_top--;
- entries--;
-
- tied_task = * stack_top;
-
- KMP_DEBUG_ASSERT( tied_task != NULL );
- KMP_DEBUG_ASSERT( tied_task -> td_flags.tasktype == TASK_TIED );
-
- KA_TRACE(threshold, ("__kmp_trace_task_stack(%s): gtid=%d, entry=%d, "
- "stack_top=%p, tied_task=%p\n",
- location, gtid, entries, stack_top, tied_task ) );
- }
- KMP_DEBUG_ASSERT( stack_top == & task_stack->ts_first_block.sb_block[0] );
-
- KA_TRACE(threshold, ("__kmp_trace_task_stack(exit): location = %s, gtid = %d\n",
- location, gtid ) );
-}
-
-//---------------------------------------------------------------------------
-// __kmp_init_task_stack: initialize the task stack for the first time
-// after a thread_data structure is created.
-// It should not be necessary to do this again (assuming the stack works).
-//
-// gtid: global thread identifier of calling thread
-// thread_data: thread data for task team thread containing stack
-
-static void
-__kmp_init_task_stack( kmp_int32 gtid, kmp_thread_data_t *thread_data )
-{
- kmp_task_stack_t *task_stack = & thread_data->td.td_susp_tied_tasks;
- kmp_stack_block_t *first_block;
-
- // set up the first block of the stack
- first_block = & task_stack -> ts_first_block;
- task_stack -> ts_top = (kmp_taskdata_t **) first_block;
- memset( (void *) first_block, '\0', TASK_STACK_BLOCK_SIZE * sizeof(kmp_taskdata_t *));
-
- // initialize the stack to be empty
- task_stack -> ts_entries = TASK_STACK_EMPTY;
- first_block -> sb_next = NULL;
- first_block -> sb_prev = NULL;
-}
-
-
-//---------------------------------------------------------------------------
-// __kmp_free_task_stack: free the task stack when thread_data is destroyed.
-//
-// gtid: global thread identifier for calling thread
-// thread_data: thread info for thread containing stack
-
-static void
-__kmp_free_task_stack( kmp_int32 gtid, kmp_thread_data_t *thread_data )
-{
- kmp_task_stack_t *task_stack = & thread_data->td.td_susp_tied_tasks;
- kmp_stack_block_t *stack_block = & task_stack -> ts_first_block;
-
- KMP_DEBUG_ASSERT( task_stack -> ts_entries == TASK_STACK_EMPTY );
- // free from the second block of the stack
- while ( stack_block != NULL ) {
- kmp_stack_block_t *next_block = (stack_block) ? stack_block -> sb_next : NULL;
-
- stack_block -> sb_next = NULL;
- stack_block -> sb_prev = NULL;
- if (stack_block != & task_stack -> ts_first_block) {
- __kmp_thread_free( thread, stack_block ); // free the block, if not the first
- }
- stack_block = next_block;
- }
- // initialize the stack to be empty
- task_stack -> ts_entries = 0;
- task_stack -> ts_top = NULL;
-}
-
-
-//---------------------------------------------------------------------------
-// __kmp_push_task_stack: Push the tied task onto the task stack.
-// Grow the stack if necessary by allocating another block.
-//
-// gtid: global thread identifier for calling thread
-// thread: thread info for thread containing stack
-// tied_task: the task to push on the stack
-
-static void
-__kmp_push_task_stack( kmp_int32 gtid, kmp_info_t *thread, kmp_taskdata_t * tied_task )
-{
- // GEH - need to consider what to do if tt_threads_data not allocated yet
- kmp_thread_data_t *thread_data = & thread -> th.th_task_team ->
- tt.tt_threads_data[ __kmp_tid_from_gtid( gtid ) ];
- kmp_task_stack_t *task_stack = & thread_data->td.td_susp_tied_tasks ;
-
- if ( tied_task->td_flags.team_serial || tied_task->td_flags.tasking_ser ) {
- return; // Don't push anything on stack if team or team tasks are serialized
- }
-
- KMP_DEBUG_ASSERT( tied_task -> td_flags.tasktype == TASK_TIED );
- KMP_DEBUG_ASSERT( task_stack -> ts_top != NULL );
-
- KA_TRACE(20, ("__kmp_push_task_stack(enter): GTID: %d; THREAD: %p; TASK: %p\n",
- gtid, thread, tied_task ) );
- // Store entry
- * (task_stack -> ts_top) = tied_task;
-
- // Do bookkeeping for next push
- task_stack -> ts_top++;
- task_stack -> ts_entries++;
-
- if ( task_stack -> ts_entries & TASK_STACK_INDEX_MASK == 0 )
- {
- // Find beginning of this task block
- kmp_stack_block_t *stack_block =
- (kmp_stack_block_t *) (task_stack -> ts_top - TASK_STACK_BLOCK_SIZE);
-
- // Check if we already have a block
- if ( stack_block -> sb_next != NULL )
- { // reset ts_top to beginning of next block
- task_stack -> ts_top = & stack_block -> sb_next -> sb_block[0];
- }
- else
- { // Alloc new block and link it up
- kmp_stack_block_t *new_block = (kmp_stack_block_t *)
- __kmp_thread_calloc(thread, sizeof(kmp_stack_block_t));
-
- task_stack -> ts_top = & new_block -> sb_block[0];
- stack_block -> sb_next = new_block;
- new_block -> sb_prev = stack_block;
- new_block -> sb_next = NULL;
-
- KA_TRACE(30, ("__kmp_push_task_stack(): GTID: %d; TASK: %p; Alloc new block: %p\n",
- gtid, tied_task, new_block ) );
- }
- }
- KA_TRACE(20, ("__kmp_push_task_stack(exit): GTID: %d; TASK: %p\n", gtid, tied_task ) );
-}
-
-//---------------------------------------------------------------------------
-// __kmp_pop_task_stack: Pop the tied task from the task stack. Don't return
-// the task, just check to make sure it matches the ending task passed in.
-//
-// gtid: global thread identifier for the calling thread
-// thread: thread info structure containing stack
-// tied_task: the task popped off the stack
-// ending_task: the task that is ending (should match popped task)
-
-static void
-__kmp_pop_task_stack( kmp_int32 gtid, kmp_info_t *thread, kmp_taskdata_t *ending_task )
-{
- // GEH - need to consider what to do if tt_threads_data not allocated yet
- kmp_thread_data_t *thread_data = & thread -> th.th_task_team -> tt_threads_data[ __kmp_tid_from_gtid( gtid ) ];
- kmp_task_stack_t *task_stack = & thread_data->td.td_susp_tied_tasks ;
- kmp_taskdata_t *tied_task;
-
- if ( ending_task->td_flags.team_serial || ending_task->td_flags.tasking_ser ) {
- return; // Don't pop anything from stack if team or team tasks are serialized
- }
-
- KMP_DEBUG_ASSERT( task_stack -> ts_top != NULL );
- KMP_DEBUG_ASSERT( task_stack -> ts_entries > 0 );
-
- KA_TRACE(20, ("__kmp_pop_task_stack(enter): GTID: %d; THREAD: %p\n", gtid, thread ) );
-
- // fix up ts_top if we need to pop from previous block
- if ( task_stack -> ts_entries & TASK_STACK_INDEX_MASK == 0 )
- {
- kmp_stack_block_t *stack_block =
- (kmp_stack_block_t *) (task_stack -> ts_top) ;
-
- stack_block = stack_block -> sb_prev;
- task_stack -> ts_top = & stack_block -> sb_block[TASK_STACK_BLOCK_SIZE];
- }
-
- // finish bookkeeping
- task_stack -> ts_top--;
- task_stack -> ts_entries--;
-
- tied_task = * (task_stack -> ts_top );
-
- KMP_DEBUG_ASSERT( tied_task != NULL );
- KMP_DEBUG_ASSERT( tied_task -> td_flags.tasktype == TASK_TIED );
- KMP_DEBUG_ASSERT( tied_task == ending_task ); // If we built the stack correctly
-
- KA_TRACE(20, ("__kmp_pop_task_stack(exit): GTID: %d; TASK: %p\n", gtid, tied_task ) );
- return;
-}
-#endif /* BUILD_TIED_TASK_STACK */
-
-//---------------------------------------------------
-// __kmp_push_task: Add a task to the thread's deque
-
-static kmp_int32
-__kmp_push_task(kmp_int32 gtid, kmp_task_t * task )
-{
- kmp_info_t * thread = __kmp_threads[ gtid ];
- kmp_taskdata_t * taskdata = KMP_TASK_TO_TASKDATA(task);
- kmp_task_team_t * task_team = thread->th.th_task_team;
- kmp_int32 tid = __kmp_tid_from_gtid( gtid );
- kmp_thread_data_t * thread_data;
-
- KA_TRACE(20, ("__kmp_push_task: T#%d trying to push task %p.\n", gtid, taskdata ) );
-
- if ( taskdata->td_flags.tiedness == TASK_UNTIED ) {
- // untied task needs to increment counter so that the task structure is not freed prematurely
- kmp_int32 counter = 1 + KMP_TEST_THEN_INC32(&taskdata->td_untied_count);
- KA_TRACE(20, ( "__kmp_push_task: T#%d untied_count (%d) incremented for task %p\n",
- gtid, counter, taskdata ) );
- }
-
- // The first check avoids building task_team thread data if serialized
- if ( taskdata->td_flags.task_serial ) {
- KA_TRACE(20, ( "__kmp_push_task: T#%d team serialized; returning TASK_NOT_PUSHED for task %p\n",
- gtid, taskdata ) );
- return TASK_NOT_PUSHED;
- }
-
- // Now that serialized tasks have returned, we can assume that we are not in immediate exec mode
- KMP_DEBUG_ASSERT( __kmp_tasking_mode != tskm_immediate_exec );
- if ( ! KMP_TASKING_ENABLED(task_team) ) {
- __kmp_enable_tasking( task_team, thread );
- }
- KMP_DEBUG_ASSERT( TCR_4(task_team -> tt.tt_found_tasks) == TRUE );
- KMP_DEBUG_ASSERT( TCR_PTR(task_team -> tt.tt_threads_data) != NULL );
-
- // Find tasking deque specific to encountering thread
- thread_data = & task_team -> tt.tt_threads_data[ tid ];
-
- // No lock needed since only owner can allocate
- if (thread_data -> td.td_deque == NULL ) {
- __kmp_alloc_task_deque( thread, thread_data );
- }
-
- // Check if deque is full
- if ( TCR_4(thread_data -> td.td_deque_ntasks) >= TASK_DEQUE_SIZE(thread_data->td) )
- {
- KA_TRACE(20, ( "__kmp_push_task: T#%d deque is full; returning TASK_NOT_PUSHED for task %p\n",
- gtid, taskdata ) );
- return TASK_NOT_PUSHED;
- }
-
- // Lock the deque for the task push operation
- __kmp_acquire_bootstrap_lock( & thread_data -> td.td_deque_lock );
-
-#if OMP_45_ENABLED
- // Need to recheck as we can get a proxy task from a thread outside of OpenMP
- if ( TCR_4(thread_data -> td.td_deque_ntasks) >= TASK_DEQUE_SIZE(thread_data->td) )
- {
- __kmp_release_bootstrap_lock( & thread_data -> td.td_deque_lock );
- KA_TRACE(20, ( "__kmp_push_task: T#%d deque is full on 2nd check; returning TASK_NOT_PUSHED for task %p\n",
- gtid, taskdata ) );
- return TASK_NOT_PUSHED;
- }
-#else
- // Must have room since no thread can add tasks but calling thread
- KMP_DEBUG_ASSERT( TCR_4(thread_data -> td.td_deque_ntasks) < TASK_DEQUE_SIZE(thread_data->td) );
-#endif
-
- thread_data -> td.td_deque[ thread_data -> td.td_deque_tail ] = taskdata; // Push taskdata
- // Wrap index.
- thread_data -> td.td_deque_tail = ( thread_data -> td.td_deque_tail + 1 ) & TASK_DEQUE_MASK(thread_data->td);
- TCW_4(thread_data -> td.td_deque_ntasks, TCR_4(thread_data -> td.td_deque_ntasks) + 1); // Adjust task count
-
- KA_TRACE(20, ("__kmp_push_task: T#%d returning TASK_SUCCESSFULLY_PUSHED: "
- "task=%p ntasks=%d head=%u tail=%u\n",
- gtid, taskdata, thread_data->td.td_deque_ntasks,
- thread_data->td.td_deque_head, thread_data->td.td_deque_tail) );
-
- __kmp_release_bootstrap_lock( & thread_data->td.td_deque_lock );
-
- return TASK_SUCCESSFULLY_PUSHED;
-}
-
-
-//-----------------------------------------------------------------------------------------
-// __kmp_pop_current_task_from_thread: set up current task from called thread when team ends
-// this_thr: thread structure to set current_task in.
-
-void
-__kmp_pop_current_task_from_thread( kmp_info_t *this_thr )
-{
- KF_TRACE( 10, ("__kmp_pop_current_task_from_thread(enter): T#%d this_thread=%p, curtask=%p, "
- "curtask_parent=%p\n",
- 0, this_thr, this_thr -> th.th_current_task,
- this_thr -> th.th_current_task -> td_parent ) );
-
- this_thr -> th.th_current_task = this_thr -> th.th_current_task -> td_parent;
-
- KF_TRACE( 10, ("__kmp_pop_current_task_from_thread(exit): T#%d this_thread=%p, curtask=%p, "
- "curtask_parent=%p\n",
- 0, this_thr, this_thr -> th.th_current_task,
- this_thr -> th.th_current_task -> td_parent ) );
-}
-
-
-//---------------------------------------------------------------------------------------
-// __kmp_push_current_task_to_thread: set up current task in called thread for a new team
-// this_thr: thread structure to set up
-// team: team for implicit task data
-// tid: thread within team to set up
-
-void
-__kmp_push_current_task_to_thread( kmp_info_t *this_thr, kmp_team_t *team, int tid )
-{
- // current task of the thread is a parent of the new just created implicit tasks of new team
- KF_TRACE( 10, ( "__kmp_push_current_task_to_thread(enter): T#%d this_thread=%p curtask=%p "
- "parent_task=%p\n",
- tid, this_thr, this_thr->th.th_current_task,
- team->t.t_implicit_task_taskdata[tid].td_parent ) );
-
- KMP_DEBUG_ASSERT (this_thr != NULL);
-
- if( tid == 0 ) {
- if( this_thr->th.th_current_task != & team -> t.t_implicit_task_taskdata[ 0 ] ) {
- team -> t.t_implicit_task_taskdata[ 0 ].td_parent = this_thr->th.th_current_task;
- this_thr->th.th_current_task = & team -> t.t_implicit_task_taskdata[ 0 ];
- }
- } else {
- team -> t.t_implicit_task_taskdata[ tid ].td_parent = team -> t.t_implicit_task_taskdata[ 0 ].td_parent;
- this_thr->th.th_current_task = & team -> t.t_implicit_task_taskdata[ tid ];
- }
-
- KF_TRACE( 10, ( "__kmp_push_current_task_to_thread(exit): T#%d this_thread=%p curtask=%p "
- "parent_task=%p\n",
- tid, this_thr, this_thr->th.th_current_task,
- team->t.t_implicit_task_taskdata[tid].td_parent ) );
-}
-
-
-//----------------------------------------------------------------------
-// __kmp_task_start: bookkeeping for a task starting execution
-// GTID: global thread id of calling thread
-// task: task starting execution
-// current_task: task suspending
-
-static void
-__kmp_task_start( kmp_int32 gtid, kmp_task_t * task, kmp_taskdata_t * current_task )
-{
- kmp_taskdata_t * taskdata = KMP_TASK_TO_TASKDATA(task);
- kmp_info_t * thread = __kmp_threads[ gtid ];
-
- KA_TRACE(10, ("__kmp_task_start(enter): T#%d starting task %p: current_task=%p\n",
- gtid, taskdata, current_task) );
-
- KMP_DEBUG_ASSERT( taskdata -> td_flags.tasktype == TASK_EXPLICIT );
-
- // mark currently executing task as suspended
- // TODO: GEH - make sure root team implicit task is initialized properly.
- // KMP_DEBUG_ASSERT( current_task -> td_flags.executing == 1 );
- current_task -> td_flags.executing = 0;
-
- // Add task to stack if tied
-#ifdef BUILD_TIED_TASK_STACK
- if ( taskdata -> td_flags.tiedness == TASK_TIED )
- {
- __kmp_push_task_stack( gtid, thread, taskdata );
- }
-#endif /* BUILD_TIED_TASK_STACK */
-
- // mark starting task as executing and as current task
- thread -> th.th_current_task = taskdata;
-
- KMP_DEBUG_ASSERT( taskdata->td_flags.started == 0 || taskdata->td_flags.tiedness == TASK_UNTIED );
- KMP_DEBUG_ASSERT( taskdata->td_flags.executing == 0 || taskdata->td_flags.tiedness == TASK_UNTIED );
- taskdata -> td_flags.started = 1;
- taskdata -> td_flags.executing = 1;
- KMP_DEBUG_ASSERT( taskdata -> td_flags.complete == 0 );
- KMP_DEBUG_ASSERT( taskdata -> td_flags.freed == 0 );
-
- // GEH TODO: shouldn't we pass some sort of location identifier here?
- // APT: yes, we will pass location here.
- // need to store current thread state (in a thread or taskdata structure)
- // before setting work_state, otherwise wrong state is set after end of task
-
- KA_TRACE(10, ("__kmp_task_start(exit): T#%d task=%p\n",
- gtid, taskdata ) );
-
-#if OMPT_SUPPORT
- if (ompt_enabled &&
- ompt_callbacks.ompt_callback(ompt_event_task_begin)) {
- kmp_taskdata_t *parent = taskdata->td_parent;
- ompt_callbacks.ompt_callback(ompt_event_task_begin)(
- parent ? parent->ompt_task_info.task_id : ompt_task_id_none,
- parent ? &(parent->ompt_task_info.frame) : NULL,
- taskdata->ompt_task_info.task_id,
- taskdata->ompt_task_info.function);
- }
-#endif
-#if OMP_40_ENABLED && OMPT_SUPPORT && OMPT_TRACE
- /* OMPT emit all dependences if requested by the tool */
- if (ompt_enabled && taskdata->ompt_task_info.ndeps > 0 &&
- ompt_callbacks.ompt_callback(ompt_event_task_dependences))
- {
- ompt_callbacks.ompt_callback(ompt_event_task_dependences)(
- taskdata->ompt_task_info.task_id,
- taskdata->ompt_task_info.deps,
- taskdata->ompt_task_info.ndeps
- );
- /* We can now free the allocated memory for the dependencies */
- KMP_OMPT_DEPS_FREE (thread, taskdata->ompt_task_info.deps);
- taskdata->ompt_task_info.deps = NULL;
- taskdata->ompt_task_info.ndeps = 0;
- }
-#endif /* OMP_40_ENABLED && OMPT_SUPPORT && OMPT_TRACE */
-
- return;
-}
-
-
-//----------------------------------------------------------------------
-// __kmpc_omp_task_begin_if0: report that a given serialized task has started execution
-// loc_ref: source location information; points to beginning of task block.
-// gtid: global thread number.
-// task: task thunk for the started task.
-
-void
-__kmpc_omp_task_begin_if0( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * task )
-{
- kmp_taskdata_t * taskdata = KMP_TASK_TO_TASKDATA(task);
- kmp_taskdata_t * current_task = __kmp_threads[ gtid ] -> th.th_current_task;
-
- KA_TRACE(10, ("__kmpc_omp_task_begin_if0(enter): T#%d loc=%p task=%p current_task=%p\n",
- gtid, loc_ref, taskdata, current_task ) );
-
- if ( taskdata->td_flags.tiedness == TASK_UNTIED ) {
- // untied task needs to increment counter so that the task structure is not freed prematurely
- kmp_int32 counter = 1 + KMP_TEST_THEN_INC32(&taskdata->td_untied_count);
- KA_TRACE(20, ( "__kmpc_omp_task_begin_if0: T#%d untied_count (%d) incremented for task %p\n",
- gtid, counter, taskdata ) );
- }
-
- taskdata -> td_flags.task_serial = 1; // Execute this task immediately, not deferred.
- __kmp_task_start( gtid, task, current_task );
-
- KA_TRACE(10, ("__kmpc_omp_task_begin_if0(exit): T#%d loc=%p task=%p,\n",
- gtid, loc_ref, taskdata ) );
-
- return;
-}
-
-#ifdef TASK_UNUSED
-//----------------------------------------------------------------------
-// __kmpc_omp_task_begin: report that a given task has started execution
-// NEVER GENERATED BY COMPILER, DEPRECATED!!!
-
-void
-__kmpc_omp_task_begin( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * task )
-{
- kmp_taskdata_t * current_task = __kmp_threads[ gtid ] -> th.th_current_task;
-
- KA_TRACE(10, ("__kmpc_omp_task_begin(enter): T#%d loc=%p task=%p current_task=%p\n",
- gtid, loc_ref, KMP_TASK_TO_TASKDATA(task), current_task ) );
-
- __kmp_task_start( gtid, task, current_task );
-
- KA_TRACE(10, ("__kmpc_omp_task_begin(exit): T#%d loc=%p task=%p,\n",
- gtid, loc_ref, KMP_TASK_TO_TASKDATA(task) ) );
-
- return;
-}
-#endif // TASK_UNUSED
-
-
-//-------------------------------------------------------------------------------------
-// __kmp_free_task: free the current task space and the space for shareds
-// gtid: Global thread ID of calling thread
-// taskdata: task to free
-// thread: thread data structure of caller
-
-static void
-__kmp_free_task( kmp_int32 gtid, kmp_taskdata_t * taskdata, kmp_info_t * thread )
-{
- KA_TRACE(30, ("__kmp_free_task: T#%d freeing data from task %p\n",
- gtid, taskdata) );
-
- // Check to make sure all flags and counters have the correct values
- KMP_DEBUG_ASSERT( taskdata->td_flags.tasktype == TASK_EXPLICIT );
- KMP_DEBUG_ASSERT( taskdata->td_flags.executing == 0 );
- KMP_DEBUG_ASSERT( taskdata->td_flags.complete == 1 );
- KMP_DEBUG_ASSERT( taskdata->td_flags.freed == 0 );
- KMP_DEBUG_ASSERT( TCR_4(taskdata->td_allocated_child_tasks) == 0 || taskdata->td_flags.task_serial == 1);
- KMP_DEBUG_ASSERT( TCR_4(taskdata->td_incomplete_child_tasks) == 0 );
-
- taskdata->td_flags.freed = 1;
- ANNOTATE_HAPPENS_BEFORE(taskdata);
- // deallocate the taskdata and shared variable blocks associated with this task
- #if USE_FAST_MEMORY
- __kmp_fast_free( thread, taskdata );
- #else /* ! USE_FAST_MEMORY */
- __kmp_thread_free( thread, taskdata );
- #endif
-
- KA_TRACE(20, ("__kmp_free_task: T#%d freed task %p\n",
- gtid, taskdata) );
-}
-
-//-------------------------------------------------------------------------------------
-// __kmp_free_task_and_ancestors: free the current task and ancestors without children
-//
-// gtid: Global thread ID of calling thread
-// taskdata: task to free
-// thread: thread data structure of caller
-
-static void
-__kmp_free_task_and_ancestors( kmp_int32 gtid, kmp_taskdata_t * taskdata, kmp_info_t * thread )
-{
-#if OMP_45_ENABLED
- // Proxy tasks must always be allowed to free their parents
- // because they can be run in background even in serial mode.
- kmp_int32 team_serial = ( taskdata->td_flags.team_serial ||
- taskdata->td_flags.tasking_ser ) && !taskdata->td_flags.proxy;
-#else
- kmp_int32 team_serial = taskdata->td_flags.team_serial ||
- taskdata->td_flags.tasking_ser;
-#endif
- KMP_DEBUG_ASSERT( taskdata -> td_flags.tasktype == TASK_EXPLICIT );
-
- kmp_int32 children = KMP_TEST_THEN_DEC32( (kmp_int32 *)(& taskdata -> td_allocated_child_tasks) ) - 1;
- KMP_DEBUG_ASSERT( children >= 0 );
-
- // Now, go up the ancestor tree to see if any ancestors can now be freed.
- while ( children == 0 )
- {
- kmp_taskdata_t * parent_taskdata = taskdata -> td_parent;
-
- KA_TRACE(20, ("__kmp_free_task_and_ancestors(enter): T#%d task %p complete "
- "and freeing itself\n", gtid, taskdata) );
-
- // --- Deallocate my ancestor task ---
- __kmp_free_task( gtid, taskdata, thread );
-
- taskdata = parent_taskdata;
-
- // Stop checking ancestors at implicit task
- // instead of walking up ancestor tree to avoid premature deallocation of ancestors.
- if ( team_serial || taskdata -> td_flags.tasktype == TASK_IMPLICIT )
- return;
-
- // Predecrement simulated by "- 1" calculation
- children = KMP_TEST_THEN_DEC32( (kmp_int32 *)(& taskdata -> td_allocated_child_tasks) ) - 1;
- KMP_DEBUG_ASSERT( children >= 0 );
- }
-
- KA_TRACE(20, ("__kmp_free_task_and_ancestors(exit): T#%d task %p has %d children; "
- "not freeing it yet\n", gtid, taskdata, children) );
-}
-
-//---------------------------------------------------------------------
-// __kmp_task_finish: bookkeeping to do when a task finishes execution
-// gtid: global thread ID for calling thread
-// task: task to be finished
-// resumed_task: task to be resumed. (may be NULL if task is serialized)
-
-static void
-__kmp_task_finish( kmp_int32 gtid, kmp_task_t *task, kmp_taskdata_t *resumed_task )
-{
- kmp_taskdata_t * taskdata = KMP_TASK_TO_TASKDATA(task);
- kmp_info_t * thread = __kmp_threads[ gtid ];
- kmp_task_team_t * task_team = thread->th.th_task_team; // might be NULL for serial teams...
- kmp_int32 children = 0;
-
-#if OMPT_SUPPORT
- if (ompt_enabled &&
- ompt_callbacks.ompt_callback(ompt_event_task_end)) {
- kmp_taskdata_t *parent = taskdata->td_parent;
- ompt_callbacks.ompt_callback(ompt_event_task_end)(
- taskdata->ompt_task_info.task_id);
- }
-#endif
-
- KA_TRACE(10, ("__kmp_task_finish(enter): T#%d finishing task %p and resuming task %p\n",
- gtid, taskdata, resumed_task) );
-
- KMP_DEBUG_ASSERT( taskdata -> td_flags.tasktype == TASK_EXPLICIT );
-
- // Pop task from stack if tied
-#ifdef BUILD_TIED_TASK_STACK
- if ( taskdata -> td_flags.tiedness == TASK_TIED )
- {
- __kmp_pop_task_stack( gtid, thread, taskdata );
- }
-#endif /* BUILD_TIED_TASK_STACK */
-
- if ( taskdata->td_flags.tiedness == TASK_UNTIED ) {
- // untied task needs to check the counter so that the task structure is not freed prematurely
- kmp_int32 counter = KMP_TEST_THEN_DEC32(&taskdata->td_untied_count) - 1;
- KA_TRACE(20, ( "__kmp_task_finish: T#%d untied_count (%d) decremented for task %p\n",
- gtid, counter, taskdata ) );
- if ( counter > 0 ) {
- // untied task is not done, to be continued possibly by other thread, do not free it now
- if (resumed_task == NULL) {
- KMP_DEBUG_ASSERT( taskdata->td_flags.task_serial );
- resumed_task = taskdata->td_parent; // In a serialized task, the resumed task is the parent
- }
- thread->th.th_current_task = resumed_task; // restore current_task
- resumed_task->td_flags.executing = 1; // resume previous task
- KA_TRACE(10, ("__kmp_task_finish(exit): T#%d partially done task %p, resuming task %p\n",
- gtid, taskdata, resumed_task) );
- return;
- }
- }
-
- KMP_DEBUG_ASSERT( taskdata -> td_flags.complete == 0 );
- taskdata -> td_flags.complete = 1; // mark the task as completed
- KMP_DEBUG_ASSERT( taskdata -> td_flags.started == 1 );
- KMP_DEBUG_ASSERT( taskdata -> td_flags.freed == 0 );
-
- // Only need to keep track of count if team parallel and tasking not serialized
- if ( !( taskdata -> td_flags.team_serial || taskdata -> td_flags.tasking_ser ) ) {
- // Predecrement simulated by "- 1" calculation
- children = KMP_TEST_THEN_DEC32( (kmp_int32 *)(& taskdata -> td_parent -> td_incomplete_child_tasks) ) - 1;
- KMP_DEBUG_ASSERT( children >= 0 );
-#if OMP_40_ENABLED
- if ( taskdata->td_taskgroup )
- KMP_TEST_THEN_DEC32( (kmp_int32 *)(& taskdata->td_taskgroup->count) );
-#if OMP_45_ENABLED
- }
- // if we found proxy tasks there could exist a dependency chain
- // with the proxy task as origin
- if ( !( taskdata -> td_flags.team_serial || taskdata -> td_flags.tasking_ser ) || (task_team && task_team->tt.tt_found_proxy_tasks) ) {
-#endif
- __kmp_release_deps(gtid,taskdata);
-#endif
- }
-
- // td_flags.executing must be marked as 0 after __kmp_release_deps has been called
- // Othertwise, if a task is executed immediately from the release_deps code
- // the flag will be reset to 1 again by this same function
- KMP_DEBUG_ASSERT( taskdata -> td_flags.executing == 1 );
- taskdata -> td_flags.executing = 0; // suspend the finishing task
-
- KA_TRACE(20, ("__kmp_task_finish: T#%d finished task %p, %d incomplete children\n",
- gtid, taskdata, children) );
-
-#if OMP_40_ENABLED
- /* If the tasks' destructor thunk flag has been set, we need to invoke the
- destructor thunk that has been generated by the compiler.
- The code is placed here, since at this point other tasks might have been released
- hence overlapping the destructor invokations with some other work in the
- released tasks. The OpenMP spec is not specific on when the destructors are
- invoked, so we should be free to choose.
- */
- if (taskdata->td_flags.destructors_thunk) {
- kmp_routine_entry_t destr_thunk = task->data1.destructors;
- KMP_ASSERT(destr_thunk);
- destr_thunk(gtid, task);
- }
-#endif // OMP_40_ENABLED
-
- // bookkeeping for resuming task:
- // GEH - note tasking_ser => task_serial
- KMP_DEBUG_ASSERT( (taskdata->td_flags.tasking_ser || taskdata->td_flags.task_serial) ==
- taskdata->td_flags.task_serial);
- if ( taskdata->td_flags.task_serial )
- {
- if (resumed_task == NULL) {
- resumed_task = taskdata->td_parent; // In a serialized task, the resumed task is the parent
- }
- else
-#if OMP_45_ENABLED
- if ( !(task_team && task_team->tt.tt_found_proxy_tasks) )
-#endif
- {
- // verify resumed task passed in points to parent
- KMP_DEBUG_ASSERT( resumed_task == taskdata->td_parent );
- }
- }
- else {
- KMP_DEBUG_ASSERT( resumed_task != NULL ); // verify that resumed task is passed as arguemnt
- }
-
- // Free this task and then ancestor tasks if they have no children.
- // Restore th_current_task first as suggested by John:
- // johnmc: if an asynchronous inquiry peers into the runtime system
- // it doesn't see the freed task as the current task.
- thread->th.th_current_task = resumed_task;
- __kmp_free_task_and_ancestors(gtid, taskdata, thread);
-
- // TODO: GEH - make sure root team implicit task is initialized properly.
- // KMP_DEBUG_ASSERT( resumed_task->td_flags.executing == 0 );
- resumed_task->td_flags.executing = 1; // resume previous task
-
- KA_TRACE(10, ("__kmp_task_finish(exit): T#%d finished task %p, resuming task %p\n",
- gtid, taskdata, resumed_task) );
-
- return;
-}
-
-//---------------------------------------------------------------------
-// __kmpc_omp_task_complete_if0: report that a task has completed execution
-// loc_ref: source location information; points to end of task block.
-// gtid: global thread number.
-// task: task thunk for the completed task.
-
-void
-__kmpc_omp_task_complete_if0( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t *task )
-{
- KA_TRACE(10, ("__kmpc_omp_task_complete_if0(enter): T#%d loc=%p task=%p\n",
- gtid, loc_ref, KMP_TASK_TO_TASKDATA(task) ) );
-
- __kmp_task_finish( gtid, task, NULL ); // this routine will provide task to resume
-
- KA_TRACE(10, ("__kmpc_omp_task_complete_if0(exit): T#%d loc=%p task=%p\n",
- gtid, loc_ref, KMP_TASK_TO_TASKDATA(task) ) );
-
- return;
-}
-
-#ifdef TASK_UNUSED
-//---------------------------------------------------------------------
-// __kmpc_omp_task_complete: report that a task has completed execution
-// NEVER GENERATED BY COMPILER, DEPRECATED!!!
-
-void
-__kmpc_omp_task_complete( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t *task )
-{
- KA_TRACE(10, ("__kmpc_omp_task_complete(enter): T#%d loc=%p task=%p\n",
- gtid, loc_ref, KMP_TASK_TO_TASKDATA(task) ) );
-
- __kmp_task_finish( gtid, task, NULL ); // Not sure how to find task to resume
-
- KA_TRACE(10, ("__kmpc_omp_task_complete(exit): T#%d loc=%p task=%p\n",
- gtid, loc_ref, KMP_TASK_TO_TASKDATA(task) ) );
- return;
-}
-#endif // TASK_UNUSED
-
-
-#if OMPT_SUPPORT
-//----------------------------------------------------------------------------------------------------
-// __kmp_task_init_ompt:
-// Initialize OMPT fields maintained by a task. This will only be called after
-// ompt_tool, so we already know whether ompt is enabled or not.
-
-static inline void
-__kmp_task_init_ompt( kmp_taskdata_t * task, int tid, void * function )
-{
- if (ompt_enabled) {
- task->ompt_task_info.task_id = __ompt_task_id_new(tid);
- task->ompt_task_info.function = function;
- task->ompt_task_info.frame.exit_runtime_frame = NULL;
- task->ompt_task_info.frame.reenter_runtime_frame = NULL;
-#if OMP_40_ENABLED
- task->ompt_task_info.ndeps = 0;
- task->ompt_task_info.deps = NULL;
-#endif /* OMP_40_ENABLED */
- }
-}
-#endif
-
-
-//----------------------------------------------------------------------------------------------------
-// __kmp_init_implicit_task: Initialize the appropriate fields in the implicit task for a given thread
-//
-// loc_ref: reference to source location of parallel region
-// this_thr: thread data structure corresponding to implicit task
-// team: team for this_thr
-// tid: thread id of given thread within team
-// set_curr_task: TRUE if need to push current task to thread
-// NOTE: Routine does not set up the implicit task ICVS. This is assumed to have already been done elsewhere.
-// TODO: Get better loc_ref. Value passed in may be NULL
-
-void
-__kmp_init_implicit_task( ident_t *loc_ref, kmp_info_t *this_thr, kmp_team_t *team, int tid, int set_curr_task )
-{
- kmp_taskdata_t * task = & team->t.t_implicit_task_taskdata[ tid ];
-
- KF_TRACE(10, ("__kmp_init_implicit_task(enter): T#:%d team=%p task=%p, reinit=%s\n",
- tid, team, task, set_curr_task ? "TRUE" : "FALSE" ) );
-
- task->td_task_id = KMP_GEN_TASK_ID();
- task->td_team = team;
-// task->td_parent = NULL; // fix for CQ230101 (broken parent task info in debugger)
- task->td_ident = loc_ref;
- task->td_taskwait_ident = NULL;
- task->td_taskwait_counter = 0;
- task->td_taskwait_thread = 0;
-
- task->td_flags.tiedness = TASK_TIED;
- task->td_flags.tasktype = TASK_IMPLICIT;
-#if OMP_45_ENABLED
- task->td_flags.proxy = TASK_FULL;
-#endif
-
- // All implicit tasks are executed immediately, not deferred
- task->td_flags.task_serial = 1;
- task->td_flags.tasking_ser = ( __kmp_tasking_mode == tskm_immediate_exec );
- task->td_flags.team_serial = ( team->t.t_serialized ) ? 1 : 0;
-
- task->td_flags.started = 1;
- task->td_flags.executing = 1;
- task->td_flags.complete = 0;
- task->td_flags.freed = 0;
-
-#if OMP_40_ENABLED
- task->td_depnode = NULL;
-#endif
-
- if (set_curr_task) { // only do this initialization the first time a thread is created
- task->td_incomplete_child_tasks = 0;
- task->td_allocated_child_tasks = 0; // Not used because do not need to deallocate implicit task
-#if OMP_40_ENABLED
- task->td_taskgroup = NULL; // An implicit task does not have taskgroup
- task->td_dephash = NULL;
-#endif
- __kmp_push_current_task_to_thread( this_thr, team, tid );
- } else {
- KMP_DEBUG_ASSERT(task->td_incomplete_child_tasks == 0);
- KMP_DEBUG_ASSERT(task->td_allocated_child_tasks == 0);
- }
-
-#if OMPT_SUPPORT
- __kmp_task_init_ompt(task, tid, NULL);
-#endif
-
- KF_TRACE(10, ("__kmp_init_implicit_task(exit): T#:%d team=%p task=%p\n",
- tid, team, task ) );
-}
-
-
-//-----------------------------------------------------------------------------
-//// __kmp_finish_implicit_task: Release resources associated to implicit tasks
-//// at the end of parallel regions. Some resources are kept for reuse in the
-//// next parallel region.
-////
-//// thread: thread data structure corresponding to implicit task
-//
-void
-__kmp_finish_implicit_task(kmp_info_t *thread)
-{
- kmp_taskdata_t *task = thread->th.th_current_task;
- if (task->td_dephash)
- __kmp_dephash_free_entries(thread, task->td_dephash);
-}
-
-
-//-----------------------------------------------------------------------------
-//// __kmp_free_implicit_task: Release resources associated to implicit tasks
-//// when these are destroyed regions
-////
-//// thread: thread data structure corresponding to implicit task
-//
-void
-__kmp_free_implicit_task(kmp_info_t *thread)
-{
- kmp_taskdata_t *task = thread->th.th_current_task;
- if (task->td_dephash)
- __kmp_dephash_free(thread, task->td_dephash);
- task->td_dephash = NULL;
-}
-
-
-// Round up a size to a power of two specified by val
-// Used to insert padding between structures co-allocated using a single malloc() call
-static size_t
-__kmp_round_up_to_val( size_t size, size_t val ) {
- if ( size & ( val - 1 ) ) {
- size &= ~ ( val - 1 );
- if ( size <= KMP_SIZE_T_MAX - val ) {
- size += val; // Round up if there is no overflow.
- }; // if
- }; // if
- return size;
-} // __kmp_round_up_to_va
-
-
-//---------------------------------------------------------------------------------
-// __kmp_task_alloc: Allocate the taskdata and task data structures for a task
-//
-// loc_ref: source location information
-// gtid: global thread number.
-// flags: include tiedness & task type (explicit vs. implicit) of the ''new'' task encountered.
-// Converted from kmp_int32 to kmp_tasking_flags_t in routine.
-// sizeof_kmp_task_t: Size in bytes of kmp_task_t data structure including private vars accessed in task.
-// sizeof_shareds: Size in bytes of array of pointers to shared vars accessed in task.
-// task_entry: Pointer to task code entry point generated by compiler.
-// returns: a pointer to the allocated kmp_task_t structure (task).
-
-kmp_task_t *
-__kmp_task_alloc( ident_t *loc_ref, kmp_int32 gtid, kmp_tasking_flags_t *flags,
- size_t sizeof_kmp_task_t, size_t sizeof_shareds,
- kmp_routine_entry_t task_entry )
-{
- kmp_task_t *task;
- kmp_taskdata_t *taskdata;
- kmp_info_t *thread = __kmp_threads[ gtid ];
- kmp_team_t *team = thread->th.th_team;
- kmp_taskdata_t *parent_task = thread->th.th_current_task;
- size_t shareds_offset;
-
- KA_TRACE(10, ("__kmp_task_alloc(enter): T#%d loc=%p, flags=(0x%x) "
- "sizeof_task=%ld sizeof_shared=%ld entry=%p\n",
- gtid, loc_ref, *((kmp_int32 *)flags), sizeof_kmp_task_t,
- sizeof_shareds, task_entry) );
-
- if ( parent_task->td_flags.final ) {
- if (flags->merged_if0) {
- }
- flags->final = 1;
- }
-
-#if OMP_45_ENABLED
- if ( flags->proxy == TASK_PROXY ) {
- flags->tiedness = TASK_UNTIED;
- flags->merged_if0 = 1;
-
- /* are we running in a sequential parallel or tskm_immediate_exec... we need tasking support enabled */
- if ( (thread->th.th_task_team) == NULL ) {
- /* This should only happen if the team is serialized
- setup a task team and propagate it to the thread
- */
- KMP_DEBUG_ASSERT(team->t.t_serialized);
- KA_TRACE(30,("T#%d creating task team in __kmp_task_alloc for proxy task\n", gtid));
- __kmp_task_team_setup(thread,team,1); // 1 indicates setup the current team regardless of nthreads
- thread->th.th_task_team = team->t.t_task_team[thread->th.th_task_state];
- }
- kmp_task_team_t * task_team = thread->th.th_task_team;
-
- /* tasking must be enabled now as the task might not be pushed */
- if ( !KMP_TASKING_ENABLED( task_team ) ) {
- KA_TRACE(30,("T#%d enabling tasking in __kmp_task_alloc for proxy task\n", gtid));
- __kmp_enable_tasking( task_team, thread );
- kmp_int32 tid = thread->th.th_info.ds.ds_tid;
- kmp_thread_data_t * thread_data = & task_team -> tt.tt_threads_data[ tid ];
- // No lock needed since only owner can allocate
- if (thread_data -> td.td_deque == NULL ) {
- __kmp_alloc_task_deque( thread, thread_data );
- }
- }
-
- if ( task_team->tt.tt_found_proxy_tasks == FALSE )
- TCW_4(task_team -> tt.tt_found_proxy_tasks, TRUE);
- }
-#endif
-
- // Calculate shared structure offset including padding after kmp_task_t struct
- // to align pointers in shared struct
- shareds_offset = sizeof( kmp_taskdata_t ) + sizeof_kmp_task_t;
- shareds_offset = __kmp_round_up_to_val( shareds_offset, sizeof( void * ));
-
- // Allocate a kmp_taskdata_t block and a kmp_task_t block.
- KA_TRACE(30, ("__kmp_task_alloc: T#%d First malloc size: %ld\n",
- gtid, shareds_offset) );
- KA_TRACE(30, ("__kmp_task_alloc: T#%d Second malloc size: %ld\n",
- gtid, sizeof_shareds) );
-
- // Avoid double allocation here by combining shareds with taskdata
- #if USE_FAST_MEMORY
- taskdata = (kmp_taskdata_t *) __kmp_fast_allocate( thread, shareds_offset + sizeof_shareds );
- #else /* ! USE_FAST_MEMORY */
- taskdata = (kmp_taskdata_t *) __kmp_thread_malloc( thread, shareds_offset + sizeof_shareds );
- #endif /* USE_FAST_MEMORY */
- ANNOTATE_HAPPENS_AFTER(taskdata);
-
- task = KMP_TASKDATA_TO_TASK(taskdata);
-
- // Make sure task & taskdata are aligned appropriately
-#if KMP_ARCH_X86 || KMP_ARCH_PPC64 || !KMP_HAVE_QUAD
- KMP_DEBUG_ASSERT( ( ((kmp_uintptr_t)taskdata) & (sizeof(double)-1) ) == 0 );
- KMP_DEBUG_ASSERT( ( ((kmp_uintptr_t)task) & (sizeof(double)-1) ) == 0 );
-#else
- KMP_DEBUG_ASSERT( ( ((kmp_uintptr_t)taskdata) & (sizeof(_Quad)-1) ) == 0 );
- KMP_DEBUG_ASSERT( ( ((kmp_uintptr_t)task) & (sizeof(_Quad)-1) ) == 0 );
-#endif
- if (sizeof_shareds > 0) {
- // Avoid double allocation here by combining shareds with taskdata
- task->shareds = & ((char *) taskdata)[ shareds_offset ];
- // Make sure shareds struct is aligned to pointer size
- KMP_DEBUG_ASSERT( ( ((kmp_uintptr_t)task->shareds) & (sizeof(void *)-1) ) == 0 );
- } else {
- task->shareds = NULL;
- }
- task->routine = task_entry;
- task->part_id = 0; // AC: Always start with 0 part id
-
- taskdata->td_task_id = KMP_GEN_TASK_ID();
- taskdata->td_team = team;
- taskdata->td_alloc_thread = thread;
- taskdata->td_parent = parent_task;
- taskdata->td_level = parent_task->td_level + 1; // increment nesting level
- taskdata->td_untied_count = 0;
- taskdata->td_ident = loc_ref;
- taskdata->td_taskwait_ident = NULL;
- taskdata->td_taskwait_counter = 0;
- taskdata->td_taskwait_thread = 0;
- KMP_DEBUG_ASSERT( taskdata->td_parent != NULL );
-#if OMP_45_ENABLED
- // avoid copying icvs for proxy tasks
- if ( flags->proxy == TASK_FULL )
-#endif
- copy_icvs( &taskdata->td_icvs, &taskdata->td_parent->td_icvs );
-
- taskdata->td_flags.tiedness = flags->tiedness;
- taskdata->td_flags.final = flags->final;
- taskdata->td_flags.merged_if0 = flags->merged_if0;
-#if OMP_40_ENABLED
- taskdata->td_flags.destructors_thunk = flags->destructors_thunk;
-#endif // OMP_40_ENABLED
-#if OMP_45_ENABLED
- taskdata->td_flags.proxy = flags->proxy;
- taskdata->td_task_team = thread->th.th_task_team;
- taskdata->td_size_alloc = shareds_offset + sizeof_shareds;
-#endif
- taskdata->td_flags.tasktype = TASK_EXPLICIT;
-
- // GEH - TODO: fix this to copy parent task's value of tasking_ser flag
- taskdata->td_flags.tasking_ser = ( __kmp_tasking_mode == tskm_immediate_exec );
-
- // GEH - TODO: fix this to copy parent task's value of team_serial flag
- taskdata->td_flags.team_serial = ( team->t.t_serialized ) ? 1 : 0;
-
- // GEH - Note we serialize the task if the team is serialized to make sure implicit parallel region
- // tasks are not left until program termination to execute. Also, it helps locality to execute
- // immediately.
- taskdata->td_flags.task_serial = ( parent_task->td_flags.final
- || taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser );
-
- taskdata->td_flags.started = 0;
- taskdata->td_flags.executing = 0;
- taskdata->td_flags.complete = 0;
- taskdata->td_flags.freed = 0;
-
- taskdata->td_flags.native = flags->native;
-
- taskdata->td_incomplete_child_tasks = 0;
- taskdata->td_allocated_child_tasks = 1; // start at one because counts current task and children
-#if OMP_40_ENABLED
- taskdata->td_taskgroup = parent_task->td_taskgroup; // task inherits the taskgroup from the parent task
- taskdata->td_dephash = NULL;
- taskdata->td_depnode = NULL;
-#endif
-
- // Only need to keep track of child task counts if team parallel and tasking not serialized or if it is a proxy task
-#if OMP_45_ENABLED
- if ( flags->proxy == TASK_PROXY || !( taskdata -> td_flags.team_serial || taskdata -> td_flags.tasking_ser ) )
-#else
- if ( !( taskdata -> td_flags.team_serial || taskdata -> td_flags.tasking_ser ) )
-#endif
- {
- KMP_TEST_THEN_INC32( (kmp_int32 *)(& parent_task->td_incomplete_child_tasks) );
-#if OMP_40_ENABLED
- if ( parent_task->td_taskgroup )
- KMP_TEST_THEN_INC32( (kmp_int32 *)(& parent_task->td_taskgroup->count) );
-#endif
- // Only need to keep track of allocated child tasks for explicit tasks since implicit not deallocated
- if ( taskdata->td_parent->td_flags.tasktype == TASK_EXPLICIT ) {
- KMP_TEST_THEN_INC32( (kmp_int32 *)(& taskdata->td_parent->td_allocated_child_tasks) );
- }
- }
-
- KA_TRACE(20, ("__kmp_task_alloc(exit): T#%d created task %p parent=%p\n",
- gtid, taskdata, taskdata->td_parent) );
- ANNOTATE_HAPPENS_BEFORE(task);
-
-#if OMPT_SUPPORT
- __kmp_task_init_ompt(taskdata, gtid, (void*) task_entry);
-#endif
-
- return task;
-}
-
-
-kmp_task_t *
-__kmpc_omp_task_alloc( ident_t *loc_ref, kmp_int32 gtid, kmp_int32 flags,
- size_t sizeof_kmp_task_t, size_t sizeof_shareds,
- kmp_routine_entry_t task_entry )
-{
- kmp_task_t *retval;
- kmp_tasking_flags_t *input_flags = (kmp_tasking_flags_t *) & flags;
-
- input_flags->native = FALSE;
- // __kmp_task_alloc() sets up all other runtime flags
-
-#if OMP_45_ENABLED
- KA_TRACE(10, ("__kmpc_omp_task_alloc(enter): T#%d loc=%p, flags=(%s %s) "
- "sizeof_task=%ld sizeof_shared=%ld entry=%p\n",
- gtid, loc_ref, input_flags->tiedness ? "tied " : "untied",
- input_flags->proxy ? "proxy" : "",
- sizeof_kmp_task_t, sizeof_shareds, task_entry) );
-#else
- KA_TRACE(10, ("__kmpc_omp_task_alloc(enter): T#%d loc=%p, flags=(%s) "
- "sizeof_task=%ld sizeof_shared=%ld entry=%p\n",
- gtid, loc_ref, input_flags->tiedness ? "tied " : "untied",
- sizeof_kmp_task_t, sizeof_shareds, task_entry) );
-#endif
-
- retval = __kmp_task_alloc( loc_ref, gtid, input_flags, sizeof_kmp_task_t,
- sizeof_shareds, task_entry );
-
- KA_TRACE(20, ("__kmpc_omp_task_alloc(exit): T#%d retval %p\n", gtid, retval) );
-
- return retval;
-}
-
-//-----------------------------------------------------------
-// __kmp_invoke_task: invoke the specified task
-//
-// gtid: global thread ID of caller
-// task: the task to invoke
-// current_task: the task to resume after task invokation
-
-static void
-__kmp_invoke_task( kmp_int32 gtid, kmp_task_t *task, kmp_taskdata_t * current_task )
-{
- kmp_taskdata_t * taskdata = KMP_TASK_TO_TASKDATA(task);
- kmp_uint64 cur_time;
-#if OMP_40_ENABLED
- int discard = 0 /* false */;
-#endif
- KA_TRACE(30, ("__kmp_invoke_task(enter): T#%d invoking task %p, current_task=%p\n",
- gtid, taskdata, current_task) );
- KMP_DEBUG_ASSERT(task);
-#if OMP_45_ENABLED
- if ( taskdata->td_flags.proxy == TASK_PROXY &&
- taskdata->td_flags.complete == 1)
- {
- // This is a proxy task that was already completed but it needs to run
- // its bottom-half finish
- KA_TRACE(30, ("__kmp_invoke_task: T#%d running bottom finish for proxy task %p\n",
- gtid, taskdata) );
-
- __kmp_bottom_half_finish_proxy(gtid,task);
-
- KA_TRACE(30, ("__kmp_invoke_task(exit): T#%d completed bottom finish for proxy task %p, resuming task %p\n", gtid, taskdata, current_task) );
-
- return;
- }
-#endif
-
-#if USE_ITT_BUILD && USE_ITT_NOTIFY
- if(__kmp_forkjoin_frames_mode == 3) {
- // Get the current time stamp to measure task execution time to correct barrier imbalance time
- cur_time = __itt_get_timestamp();
- }
-#endif
-
-#if OMP_45_ENABLED
- // Proxy tasks are not handled by the runtime
- if ( taskdata->td_flags.proxy != TASK_PROXY ) {
-#endif
- ANNOTATE_HAPPENS_AFTER(task);
- __kmp_task_start( gtid, task, current_task );
-#if OMP_45_ENABLED
- }
-#endif
-
-#if OMPT_SUPPORT
- ompt_thread_info_t oldInfo;
- kmp_info_t * thread;
- if (ompt_enabled) {
- // Store the threads states and restore them after the task
- thread = __kmp_threads[ gtid ];
- oldInfo = thread->th.ompt_thread_info;
- thread->th.ompt_thread_info.wait_id = 0;
- thread->th.ompt_thread_info.state = ompt_state_work_parallel;
- taskdata->ompt_task_info.frame.exit_runtime_frame = __builtin_frame_address(0);
- }
-#endif
-
-#if OMP_40_ENABLED
- // TODO: cancel tasks if the parallel region has also been cancelled
- // TODO: check if this sequence can be hoisted above __kmp_task_start
- // if cancellation has been enabled for this run ...
- if (__kmp_omp_cancellation) {
- kmp_info_t *this_thr = __kmp_threads [ gtid ];
- kmp_team_t * this_team = this_thr->th.th_team;
- kmp_taskgroup_t * taskgroup = taskdata->td_taskgroup;
- if ((taskgroup && taskgroup->cancel_request) || (this_team->t.t_cancel_request == cancel_parallel)) {
- KMP_COUNT_BLOCK(TASK_cancelled);
- // this task belongs to a task group and we need to cancel it
- discard = 1 /* true */;
- }
- }
-
- //
- // Invoke the task routine and pass in relevant data.
- // Thunks generated by gcc take a different argument list.
- //
- if (!discard) {
-#if KMP_STATS_ENABLED
- KMP_COUNT_BLOCK(TASK_executed);
- switch(KMP_GET_THREAD_STATE()) {
- case FORK_JOIN_BARRIER: KMP_PUSH_PARTITIONED_TIMER(OMP_task_join_bar); break;
- case PLAIN_BARRIER: KMP_PUSH_PARTITIONED_TIMER(OMP_task_plain_bar); break;
- case TASKYIELD: KMP_PUSH_PARTITIONED_TIMER(OMP_task_taskyield); break;
- case TASKWAIT: KMP_PUSH_PARTITIONED_TIMER(OMP_task_taskwait); break;
- case TASKGROUP: KMP_PUSH_PARTITIONED_TIMER(OMP_task_taskgroup); break;
- default: KMP_PUSH_PARTITIONED_TIMER(OMP_task_immediate); break;
- }
-#endif // KMP_STATS_ENABLED
-#endif // OMP_40_ENABLED
-
-#if OMPT_SUPPORT && OMPT_TRACE
- /* let OMPT know that we're about to run this task */
- if (ompt_enabled &&
- ompt_callbacks.ompt_callback(ompt_event_task_switch))
- {
- ompt_callbacks.ompt_callback(ompt_event_task_switch)(
- current_task->ompt_task_info.task_id,
- taskdata->ompt_task_info.task_id);
- }
-#endif
-
-#ifdef KMP_GOMP_COMPAT
- if (taskdata->td_flags.native) {
- ((void (*)(void *))(*(task->routine)))(task->shareds);
- }
- else
-#endif /* KMP_GOMP_COMPAT */
- {
- (*(task->routine))(gtid, task);
- }
- KMP_POP_PARTITIONED_TIMER();
-
-#if OMPT_SUPPORT && OMPT_TRACE
- /* let OMPT know that we're returning to the callee task */
- if (ompt_enabled &&
- ompt_callbacks.ompt_callback(ompt_event_task_switch))
- {
- ompt_callbacks.ompt_callback(ompt_event_task_switch)(
- taskdata->ompt_task_info.task_id,
- current_task->ompt_task_info.task_id);
- }
-#endif
-
-#if OMP_40_ENABLED
- }
-#endif // OMP_40_ENABLED
-
-
-#if OMPT_SUPPORT
- if (ompt_enabled) {
- thread->th.ompt_thread_info = oldInfo;
- taskdata->ompt_task_info.frame.exit_runtime_frame = NULL;
- }
-#endif
-
-#if OMP_45_ENABLED
- // Proxy tasks are not handled by the runtime
- if ( taskdata->td_flags.proxy != TASK_PROXY ) {
-#endif
- ANNOTATE_HAPPENS_BEFORE(taskdata->td_parent);
- __kmp_task_finish( gtid, task, current_task );
-#if OMP_45_ENABLED
- }
-#endif
-
-#if USE_ITT_BUILD && USE_ITT_NOTIFY
- // Barrier imbalance - correct arrive time after the task finished
- if(__kmp_forkjoin_frames_mode == 3) {
- kmp_info_t *this_thr = __kmp_threads [ gtid ];
- if(this_thr->th.th_bar_arrive_time) {
- this_thr->th.th_bar_arrive_time += (__itt_get_timestamp() - cur_time);
- }
- }
-#endif
- KA_TRACE(30, ("__kmp_invoke_task(exit): T#%d completed task %p, resuming task %p\n",
- gtid, taskdata, current_task) );
- return;
-}
-
-//-----------------------------------------------------------------------
-// __kmpc_omp_task_parts: Schedule a thread-switchable task for execution
-//
-// loc_ref: location of original task pragma (ignored)
-// gtid: Global Thread ID of encountering thread
-// new_task: task thunk allocated by __kmp_omp_task_alloc() for the ''new task''
-// Returns:
-// TASK_CURRENT_NOT_QUEUED (0) if did not suspend and queue current task to be resumed later.
-// TASK_CURRENT_QUEUED (1) if suspended and queued the current task to be resumed later.
-
-kmp_int32
-__kmpc_omp_task_parts( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task)
-{
- kmp_taskdata_t * new_taskdata = KMP_TASK_TO_TASKDATA(new_task);
-
- KA_TRACE(10, ("__kmpc_omp_task_parts(enter): T#%d loc=%p task=%p\n",
- gtid, loc_ref, new_taskdata ) );
-
- /* Should we execute the new task or queue it? For now, let's just always try to
- queue it. If the queue fills up, then we'll execute it. */
-
- if ( __kmp_push_task( gtid, new_task ) == TASK_NOT_PUSHED ) // if cannot defer
- { // Execute this task immediately
- kmp_taskdata_t * current_task = __kmp_threads[ gtid ] -> th.th_current_task;
- new_taskdata->td_flags.task_serial = 1;
- __kmp_invoke_task( gtid, new_task, current_task );
- }
-
- KA_TRACE(10, ("__kmpc_omp_task_parts(exit): T#%d returning TASK_CURRENT_NOT_QUEUED: "
- "loc=%p task=%p, return: TASK_CURRENT_NOT_QUEUED\n", gtid, loc_ref,
- new_taskdata ) );
-
- ANNOTATE_HAPPENS_BEFORE(new_task);
- return TASK_CURRENT_NOT_QUEUED;
-}
-
-//---------------------------------------------------------------------
-// __kmp_omp_task: Schedule a non-thread-switchable task for execution
-// gtid: Global Thread ID of encountering thread
-// new_task: non-thread-switchable task thunk allocated by __kmp_omp_task_alloc()
-// serialize_immediate: if TRUE then if the task is executed immediately its execution will be serialized
-// returns:
-//
-// TASK_CURRENT_NOT_QUEUED (0) if did not suspend and queue current task to be resumed later.
-// TASK_CURRENT_QUEUED (1) if suspended and queued the current task to be resumed later.
-kmp_int32
-__kmp_omp_task( kmp_int32 gtid, kmp_task_t * new_task, bool serialize_immediate )
-{
- kmp_taskdata_t * new_taskdata = KMP_TASK_TO_TASKDATA(new_task);
-
-#if OMPT_SUPPORT
- if (ompt_enabled) {
- new_taskdata->ompt_task_info.frame.reenter_runtime_frame =
- __builtin_frame_address(1);
- }
-#endif
-
- /* Should we execute the new task or queue it? For now, let's just always try to
- queue it. If the queue fills up, then we'll execute it. */
-#if OMP_45_ENABLED
- if ( new_taskdata->td_flags.proxy == TASK_PROXY || __kmp_push_task( gtid, new_task ) == TASK_NOT_PUSHED ) // if cannot defer
-#else
- if ( __kmp_push_task( gtid, new_task ) == TASK_NOT_PUSHED ) // if cannot defer
-#endif
- { // Execute this task immediately
- kmp_taskdata_t * current_task = __kmp_threads[ gtid ] -> th.th_current_task;
- if ( serialize_immediate )
- new_taskdata -> td_flags.task_serial = 1;
- __kmp_invoke_task( gtid, new_task, current_task );
- }
-
-#if OMPT_SUPPORT
- if (ompt_enabled) {
- new_taskdata->ompt_task_info.frame.reenter_runtime_frame = NULL;
- }
-#endif
-
- ANNOTATE_HAPPENS_BEFORE(new_task);
- return TASK_CURRENT_NOT_QUEUED;
-}
-
-//---------------------------------------------------------------------
-// __kmpc_omp_task: Wrapper around __kmp_omp_task to schedule a non-thread-switchable task from
-// the parent thread only!
-// loc_ref: location of original task pragma (ignored)
-// gtid: Global Thread ID of encountering thread
-// new_task: non-thread-switchable task thunk allocated by __kmp_omp_task_alloc()
-// returns:
-//
-// TASK_CURRENT_NOT_QUEUED (0) if did not suspend and queue current task to be resumed later.
-// TASK_CURRENT_QUEUED (1) if suspended and queued the current task to be resumed later.
-
-kmp_int32
-__kmpc_omp_task( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task)
-{
- kmp_int32 res;
- KMP_SET_THREAD_STATE_BLOCK(EXPLICIT_TASK);
-
-#if KMP_DEBUG
- kmp_taskdata_t * new_taskdata = KMP_TASK_TO_TASKDATA(new_task);
-#endif
- KA_TRACE(10, ("__kmpc_omp_task(enter): T#%d loc=%p task=%p\n",
- gtid, loc_ref, new_taskdata ) );
-
- res = __kmp_omp_task(gtid,new_task,true);
-
- KA_TRACE(10, ("__kmpc_omp_task(exit): T#%d returning TASK_CURRENT_NOT_QUEUED: loc=%p task=%p\n",
- gtid, loc_ref, new_taskdata ) );
- return res;
-}
-
-//-------------------------------------------------------------------------------------
-// __kmpc_omp_taskwait: Wait until all tasks generated by the current task are complete
-
-kmp_int32
-__kmpc_omp_taskwait( ident_t *loc_ref, kmp_int32 gtid )
-{
- kmp_taskdata_t * taskdata;
- kmp_info_t * thread;
- int thread_finished = FALSE;
- KMP_SET_THREAD_STATE_BLOCK(TASKWAIT);
-
- KA_TRACE(10, ("__kmpc_omp_taskwait(enter): T#%d loc=%p\n", gtid, loc_ref) );
-
- if ( __kmp_tasking_mode != tskm_immediate_exec ) {
- // GEH TODO: shouldn't we have some sort of OMPRAP API calls here to mark begin wait?
-
- thread = __kmp_threads[ gtid ];
- taskdata = thread -> th.th_current_task;
-
-#if OMPT_SUPPORT && OMPT_TRACE
- ompt_task_id_t my_task_id;
- ompt_parallel_id_t my_parallel_id;
-
- if (ompt_enabled) {
- kmp_team_t *team = thread->th.th_team;
- my_task_id = taskdata->ompt_task_info.task_id;
- my_parallel_id = team->t.ompt_team_info.parallel_id;
-
- taskdata->ompt_task_info.frame.reenter_runtime_frame = __builtin_frame_address(1);
- if (ompt_callbacks.ompt_callback(ompt_event_taskwait_begin)) {
- ompt_callbacks.ompt_callback(ompt_event_taskwait_begin)(
- my_parallel_id, my_task_id);
- }
- }
-#endif
-
- // Debugger: The taskwait is active. Store location and thread encountered the taskwait.
-#if USE_ITT_BUILD
- // Note: These values are used by ITT events as well.
-#endif /* USE_ITT_BUILD */
- taskdata->td_taskwait_counter += 1;
- taskdata->td_taskwait_ident = loc_ref;
- taskdata->td_taskwait_thread = gtid + 1;
-
-#if USE_ITT_BUILD
- void * itt_sync_obj = __kmp_itt_taskwait_object( gtid );
- if ( itt_sync_obj != NULL )
- __kmp_itt_taskwait_starting( gtid, itt_sync_obj );
-#endif /* USE_ITT_BUILD */
-
- bool must_wait = ! taskdata->td_flags.team_serial && ! taskdata->td_flags.final;
-
-#if OMP_45_ENABLED
- must_wait = must_wait || (thread->th.th_task_team != NULL && thread->th.th_task_team->tt.tt_found_proxy_tasks);
-#endif
- if (must_wait)
- {
- kmp_flag_32 flag(&(taskdata->td_incomplete_child_tasks), 0U);
- while ( TCR_4(taskdata -> td_incomplete_child_tasks) != 0 ) {
- flag.execute_tasks(thread, gtid, FALSE, &thread_finished
- USE_ITT_BUILD_ARG(itt_sync_obj), __kmp_task_stealing_constraint );
- }
- }
-#if USE_ITT_BUILD
- if ( itt_sync_obj != NULL )
- __kmp_itt_taskwait_finished( gtid, itt_sync_obj );
-#endif /* USE_ITT_BUILD */
-
- // GEH TODO: shouldn't we have some sort of OMPRAP API calls here to mark end of wait?
- // Debugger: The taskwait is completed. Location remains, but thread is negated.
- taskdata->td_taskwait_thread = - taskdata->td_taskwait_thread;
-
-#if OMPT_SUPPORT && OMPT_TRACE
- if (ompt_enabled) {
- if (ompt_callbacks.ompt_callback(ompt_event_taskwait_end)) {
- ompt_callbacks.ompt_callback(ompt_event_taskwait_end)(
- my_parallel_id, my_task_id);
- }
- taskdata->ompt_task_info.frame.reenter_runtime_frame = NULL;
- }
-#endif
- ANNOTATE_HAPPENS_AFTER(taskdata);
- }
-
- KA_TRACE(10, ("__kmpc_omp_taskwait(exit): T#%d task %p finished waiting, "
- "returning TASK_CURRENT_NOT_QUEUED\n", gtid, taskdata) );
-
- return TASK_CURRENT_NOT_QUEUED;
-}
-
-
-//-------------------------------------------------
-// __kmpc_omp_taskyield: switch to a different task
-
-kmp_int32
-__kmpc_omp_taskyield( ident_t *loc_ref, kmp_int32 gtid, int end_part )
-{
- kmp_taskdata_t * taskdata;
- kmp_info_t * thread;
- int thread_finished = FALSE;
-
- KMP_COUNT_BLOCK(OMP_TASKYIELD);
- KMP_SET_THREAD_STATE_BLOCK(TASKYIELD);
-
- KA_TRACE(10, ("__kmpc_omp_taskyield(enter): T#%d loc=%p end_part = %d\n",
- gtid, loc_ref, end_part) );
-
- if ( __kmp_tasking_mode != tskm_immediate_exec && __kmp_init_parallel ) {
- // GEH TODO: shouldn't we have some sort of OMPRAP API calls here to mark begin wait?
-
- thread = __kmp_threads[ gtid ];
- taskdata = thread -> th.th_current_task;
- // Should we model this as a task wait or not?
- // Debugger: The taskwait is active. Store location and thread encountered the taskwait.
-#if USE_ITT_BUILD
- // Note: These values are used by ITT events as well.
-#endif /* USE_ITT_BUILD */
- taskdata->td_taskwait_counter += 1;
- taskdata->td_taskwait_ident = loc_ref;
- taskdata->td_taskwait_thread = gtid + 1;
-
-#if USE_ITT_BUILD
- void * itt_sync_obj = __kmp_itt_taskwait_object( gtid );
- if ( itt_sync_obj != NULL )
- __kmp_itt_taskwait_starting( gtid, itt_sync_obj );
-#endif /* USE_ITT_BUILD */
- if ( ! taskdata->td_flags.team_serial ) {
- kmp_task_team_t * task_team = thread->th.th_task_team;
- if (task_team != NULL) {
- if (KMP_TASKING_ENABLED(task_team)) {
- __kmp_execute_tasks_32( thread, gtid, NULL, FALSE, &thread_finished
- USE_ITT_BUILD_ARG(itt_sync_obj), __kmp_task_stealing_constraint );
- }
- }
- }
-#if USE_ITT_BUILD
- if ( itt_sync_obj != NULL )
- __kmp_itt_taskwait_finished( gtid, itt_sync_obj );
-#endif /* USE_ITT_BUILD */
-
- // GEH TODO: shouldn't we have some sort of OMPRAP API calls here to mark end of wait?
- // Debugger: The taskwait is completed. Location remains, but thread is negated.
- taskdata->td_taskwait_thread = - taskdata->td_taskwait_thread;
- }
-
- KA_TRACE(10, ("__kmpc_omp_taskyield(exit): T#%d task %p resuming, "
- "returning TASK_CURRENT_NOT_QUEUED\n", gtid, taskdata) );
-
- return TASK_CURRENT_NOT_QUEUED;
-}
-
-
-#if OMP_40_ENABLED
-//-------------------------------------------------------------------------------------
-// __kmpc_taskgroup: Start a new taskgroup
-
-void
-__kmpc_taskgroup( ident_t* loc, int gtid )
-{
- kmp_info_t * thread = __kmp_threads[ gtid ];
- kmp_taskdata_t * taskdata = thread->th.th_current_task;
- kmp_taskgroup_t * tg_new =
- (kmp_taskgroup_t *)__kmp_thread_malloc( thread, sizeof( kmp_taskgroup_t ) );
- KA_TRACE(10, ("__kmpc_taskgroup: T#%d loc=%p group=%p\n", gtid, loc, tg_new) );
- tg_new->count = 0;
- tg_new->cancel_request = cancel_noreq;
- tg_new->parent = taskdata->td_taskgroup;
- taskdata->td_taskgroup = tg_new;
-}
-
-
-//-------------------------------------------------------------------------------------
-// __kmpc_end_taskgroup: Wait until all tasks generated by the current task
-// and its descendants are complete
-
-void
-__kmpc_end_taskgroup( ident_t* loc, int gtid )
-{
- kmp_info_t * thread = __kmp_threads[ gtid ];
- kmp_taskdata_t * taskdata = thread->th.th_current_task;
- kmp_taskgroup_t * taskgroup = taskdata->td_taskgroup;
- int thread_finished = FALSE;
-
- KA_TRACE(10, ("__kmpc_end_taskgroup(enter): T#%d loc=%p\n", gtid, loc) );
- KMP_DEBUG_ASSERT( taskgroup != NULL );
- KMP_SET_THREAD_STATE_BLOCK(TASKGROUP);
-
- if ( __kmp_tasking_mode != tskm_immediate_exec ) {
-#if USE_ITT_BUILD
- // For ITT the taskgroup wait is similar to taskwait until we need to distinguish them
- void * itt_sync_obj = __kmp_itt_taskwait_object( gtid );
- if ( itt_sync_obj != NULL )
- __kmp_itt_taskwait_starting( gtid, itt_sync_obj );
-#endif /* USE_ITT_BUILD */
-
-#if OMP_45_ENABLED
- if ( ! taskdata->td_flags.team_serial || (thread->th.th_task_team != NULL && thread->th.th_task_team->tt.tt_found_proxy_tasks) )
-#else
- if ( ! taskdata->td_flags.team_serial )
-#endif
- {
- kmp_flag_32 flag(&(taskgroup->count), 0U);
- while ( TCR_4(taskgroup->count) != 0 ) {
- flag.execute_tasks(thread, gtid, FALSE, &thread_finished
- USE_ITT_BUILD_ARG(itt_sync_obj), __kmp_task_stealing_constraint );
- }
- }
-
-#if USE_ITT_BUILD
- if ( itt_sync_obj != NULL )
- __kmp_itt_taskwait_finished( gtid, itt_sync_obj );
-#endif /* USE_ITT_BUILD */
- }
- KMP_DEBUG_ASSERT( taskgroup->count == 0 );
-
- // Restore parent taskgroup for the current task
- taskdata->td_taskgroup = taskgroup->parent;
- __kmp_thread_free( thread, taskgroup );
-
- KA_TRACE(10, ("__kmpc_end_taskgroup(exit): T#%d task %p finished waiting\n", gtid, taskdata) );
- ANNOTATE_HAPPENS_AFTER(taskdata);
-}
-#endif
-
-
-//------------------------------------------------------
-// __kmp_remove_my_task: remove a task from my own deque
-
-static kmp_task_t *
-__kmp_remove_my_task( kmp_info_t * thread, kmp_int32 gtid, kmp_task_team_t *task_team,
- kmp_int32 is_constrained )
-{
- kmp_task_t * task;
- kmp_taskdata_t * taskdata;
- kmp_thread_data_t *thread_data;
- kmp_uint32 tail;
-
- KMP_DEBUG_ASSERT( __kmp_tasking_mode != tskm_immediate_exec );
- KMP_DEBUG_ASSERT( task_team -> tt.tt_threads_data != NULL ); // Caller should check this condition
-
- thread_data = & task_team -> tt.tt_threads_data[ __kmp_tid_from_gtid( gtid ) ];
-
- KA_TRACE(10, ("__kmp_remove_my_task(enter): T#%d ntasks=%d head=%u tail=%u\n",
- gtid, thread_data->td.td_deque_ntasks, thread_data->td.td_deque_head,
- thread_data->td.td_deque_tail) );
-
- if (TCR_4(thread_data -> td.td_deque_ntasks) == 0) {
- KA_TRACE(10, ("__kmp_remove_my_task(exit #1): T#%d No tasks to remove: ntasks=%d head=%u tail=%u\n",
- gtid, thread_data->td.td_deque_ntasks, thread_data->td.td_deque_head,
- thread_data->td.td_deque_tail) );
- return NULL;
- }
-
- __kmp_acquire_bootstrap_lock( & thread_data -> td.td_deque_lock );
-
- if (TCR_4(thread_data -> td.td_deque_ntasks) == 0) {
- __kmp_release_bootstrap_lock( & thread_data -> td.td_deque_lock );
- KA_TRACE(10, ("__kmp_remove_my_task(exit #2): T#%d No tasks to remove: ntasks=%d head=%u tail=%u\n",
- gtid, thread_data->td.td_deque_ntasks, thread_data->td.td_deque_head,
- thread_data->td.td_deque_tail) );
- return NULL;
- }
-
- tail = ( thread_data -> td.td_deque_tail - 1 ) & TASK_DEQUE_MASK(thread_data->td); // Wrap index.
- taskdata = thread_data -> td.td_deque[ tail ];
-
- if (is_constrained && (taskdata->td_flags.tiedness == TASK_TIED)) {
- // we need to check if the candidate obeys task scheduling constraint:
- // only child of current task can be scheduled
- kmp_taskdata_t * current = thread->th.th_current_task;
- kmp_int32 level = current->td_level;
- kmp_taskdata_t * parent = taskdata->td_parent;
- while ( parent != current && parent->td_level > level ) {
- parent = parent->td_parent; // check generation up to the level of the current task
- KMP_DEBUG_ASSERT(parent != NULL);
- }
- if ( parent != current ) {
- // If the tail task is not a child, then no other child can appear in the deque.
- __kmp_release_bootstrap_lock( & thread_data -> td.td_deque_lock );
- KA_TRACE(10, ("__kmp_remove_my_task(exit #2): T#%d No tasks to remove: ntasks=%d head=%u tail=%u\n",
- gtid, thread_data->td.td_deque_ntasks, thread_data->td.td_deque_head,
- thread_data->td.td_deque_tail) );
- return NULL;
- }
- }
-
- thread_data -> td.td_deque_tail = tail;
- TCW_4(thread_data -> td.td_deque_ntasks, thread_data -> td.td_deque_ntasks - 1);
-
- __kmp_release_bootstrap_lock( & thread_data->td.td_deque_lock );
-
- KA_TRACE(10, ("__kmp_remove_my_task(exit #2): T#%d task %p removed: ntasks=%d head=%u tail=%u\n",
- gtid, taskdata, thread_data->td.td_deque_ntasks, thread_data->td.td_deque_head,
- thread_data->td.td_deque_tail) );
-
- task = KMP_TASKDATA_TO_TASK( taskdata );
- return task;
-}
-
-
-//-----------------------------------------------------------
-// __kmp_steal_task: remove a task from another thread's deque
-// Assume that calling thread has already checked existence of
-// task_team thread_data before calling this routine.
-
-static kmp_task_t *
-__kmp_steal_task( kmp_info_t *victim, kmp_int32 gtid, kmp_task_team_t *task_team,
- volatile kmp_uint32 *unfinished_threads, int *thread_finished,
- kmp_int32 is_constrained )
-{
- kmp_task_t * task;
- kmp_taskdata_t * taskdata;
- kmp_thread_data_t *victim_td, *threads_data;
- kmp_int32 victim_tid;
-
- KMP_DEBUG_ASSERT( __kmp_tasking_mode != tskm_immediate_exec );
-
- threads_data = task_team -> tt.tt_threads_data;
- KMP_DEBUG_ASSERT( threads_data != NULL ); // Caller should check this condition
-
- victim_tid = victim->th.th_info.ds.ds_tid;
- victim_td = & threads_data[ victim_tid ];
-
- KA_TRACE(10, ("__kmp_steal_task(enter): T#%d try to steal from T#%d: task_team=%p ntasks=%d "
- "head=%u tail=%u\n",
- gtid, __kmp_gtid_from_thread( victim ), task_team, victim_td->td.td_deque_ntasks,
- victim_td->td.td_deque_head, victim_td->td.td_deque_tail) );
-
- if ( (TCR_4(victim_td -> td.td_deque_ntasks) == 0) || // Caller should not check this condition
- (TCR_PTR(victim->th.th_task_team) != task_team)) // GEH: why would this happen?
- {
- KA_TRACE(10, ("__kmp_steal_task(exit #1): T#%d could not steal from T#%d: task_team=%p "
- "ntasks=%d head=%u tail=%u\n",
- gtid, __kmp_gtid_from_thread( victim ), task_team, victim_td->td.td_deque_ntasks,
- victim_td->td.td_deque_head, victim_td->td.td_deque_tail) );
- return NULL;
- }
-
- __kmp_acquire_bootstrap_lock( & victim_td -> td.td_deque_lock );
-
- // Check again after we acquire the lock
- if ( (TCR_4(victim_td -> td.td_deque_ntasks) == 0) ||
- (TCR_PTR(victim->th.th_task_team) != task_team)) // GEH: why would this happen?
- {
- __kmp_release_bootstrap_lock( & victim_td -> td.td_deque_lock );
- KA_TRACE(10, ("__kmp_steal_task(exit #2): T#%d could not steal from T#%d: task_team=%p "
- "ntasks=%d head=%u tail=%u\n",
- gtid, __kmp_gtid_from_thread( victim ), task_team, victim_td->td.td_deque_ntasks,
- victim_td->td.td_deque_head, victim_td->td.td_deque_tail) );
- return NULL;
- }
-
- KMP_DEBUG_ASSERT( victim_td -> td.td_deque != NULL );
-
- taskdata = victim_td->td.td_deque[victim_td->td.td_deque_head];
- if ( is_constrained ) {
- // we need to check if the candidate obeys task scheduling constraint:
- // only descendant of current task can be scheduled
- kmp_taskdata_t * current = __kmp_threads[ gtid ]->th.th_current_task;
- kmp_int32 level = current->td_level;
- kmp_taskdata_t * parent = taskdata->td_parent;
- while ( parent != current && parent->td_level > level ) {
- parent = parent->td_parent; // check generation up to the level of the current task
- KMP_DEBUG_ASSERT(parent != NULL);
- }
- if ( parent != current ) {
- // If the head task is not a descendant of the current task then do not
- // steal it. No other task in victim's deque can be a descendant of the
- // current task.
- __kmp_release_bootstrap_lock( & victim_td -> td.td_deque_lock );
- KA_TRACE(10, ("__kmp_steal_task(exit #2): T#%d could not steal from T#%d: task_team=%p "
- "ntasks=%d head=%u tail=%u\n",
- gtid, __kmp_gtid_from_thread( threads_data[victim_tid].td.td_thr ),
- task_team, victim_td->td.td_deque_ntasks,
- victim_td->td.td_deque_head, victim_td->td.td_deque_tail) );
- return NULL;
- }
- }
- // Bump head pointer and Wrap.
- victim_td->td.td_deque_head = (victim_td->td.td_deque_head + 1) & TASK_DEQUE_MASK(victim_td->td);
- if (*thread_finished) {
- // We need to un-mark this victim as a finished victim. This must be done before
- // releasing the lock, or else other threads (starting with the master victim)
- // might be prematurely released from the barrier!!!
- kmp_uint32 count;
-
- count = KMP_TEST_THEN_INC32( (kmp_int32 *)unfinished_threads );
-
- KA_TRACE(20, ("__kmp_steal_task: T#%d inc unfinished_threads to %d: task_team=%p\n",
- gtid, count + 1, task_team) );
-
- *thread_finished = FALSE;
- }
- TCW_4(victim_td -> td.td_deque_ntasks, TCR_4(victim_td -> td.td_deque_ntasks) - 1);
-
- __kmp_release_bootstrap_lock( & victim_td -> td.td_deque_lock );
-
- KMP_COUNT_BLOCK(TASK_stolen);
- KA_TRACE(10, ("__kmp_steal_task(exit #3): T#%d stole task %p from T#%d: task_team=%p "
- "ntasks=%d head=%u tail=%u\n",
- gtid, taskdata, __kmp_gtid_from_thread( victim ), task_team,
- victim_td->td.td_deque_ntasks, victim_td->td.td_deque_head,
- victim_td->td.td_deque_tail) );
-
- task = KMP_TASKDATA_TO_TASK( taskdata );
- return task;
-}
-
-
-//-----------------------------------------------------------------------------
-// __kmp_execute_tasks_template: Choose and execute tasks until either the condition
-// is statisfied (return true) or there are none left (return false).
-// final_spin is TRUE if this is the spin at the release barrier.
-// thread_finished indicates whether the thread is finished executing all
-// the tasks it has on its deque, and is at the release barrier.
-// spinner is the location on which to spin.
-// spinner == NULL means only execute a single task and return.
-// checker is the value to check to terminate the spin.
-template <class C>
-static inline int __kmp_execute_tasks_template(kmp_info_t *thread, kmp_int32 gtid, C *flag, int final_spin,
- int *thread_finished
- USE_ITT_BUILD_ARG(void * itt_sync_obj), kmp_int32 is_constrained)
-{
- kmp_task_team_t * task_team = thread->th.th_task_team;
- kmp_thread_data_t * threads_data;
- kmp_task_t * task;
- kmp_info_t * other_thread;
- kmp_taskdata_t * current_task = thread -> th.th_current_task;
- volatile kmp_uint32 * unfinished_threads;
- kmp_int32 nthreads, victim=-2, use_own_tasks=1, new_victim=0, tid=thread->th.th_info.ds.ds_tid;
-
- KMP_DEBUG_ASSERT( __kmp_tasking_mode != tskm_immediate_exec );
- KMP_DEBUG_ASSERT( thread == __kmp_threads[ gtid ] );
-
- if (task_team == NULL) return FALSE;
-
- KA_TRACE(15, ("__kmp_execute_tasks_template(enter): T#%d final_spin=%d *thread_finished=%d\n",
- gtid, final_spin, *thread_finished) );
-
- threads_data = (kmp_thread_data_t *)TCR_PTR(task_team -> tt.tt_threads_data);
- KMP_DEBUG_ASSERT( threads_data != NULL );
-
- nthreads = task_team -> tt.tt_nproc;
- unfinished_threads = &(task_team -> tt.tt_unfinished_threads);
-#if OMP_45_ENABLED
- KMP_DEBUG_ASSERT( nthreads > 1 || task_team->tt.tt_found_proxy_tasks);
-#else
- KMP_DEBUG_ASSERT( nthreads > 1 );
-#endif
- KMP_DEBUG_ASSERT( (int)(TCR_4(*unfinished_threads)) >= 0 );
-
- while (1) { // Outer loop keeps trying to find tasks in case of single thread getting tasks from target constructs
- while (1) { // Inner loop to find a task and execute it
- task = NULL;
- if (use_own_tasks) { // check on own queue first
- task = __kmp_remove_my_task( thread, gtid, task_team, is_constrained );
- }
- if ((task == NULL) && (nthreads > 1)) { // Steal a task
- int asleep = 1;
- use_own_tasks = 0;
- // Try to steal from the last place I stole from successfully.
- if (victim == -2) { // haven't stolen anything yet
- victim = threads_data[tid].td.td_deque_last_stolen;
- if (victim != -1) // if we have a last stolen from victim, get the thread
- other_thread = threads_data[victim].td.td_thr;
- }
- if (victim != -1) { // found last victim
- asleep = 0;
- }
- else if (!new_victim) { // no recent steals and we haven't already used a new victim; select a random thread
- do { // Find a different thread to steal work from.
- // Pick a random thread. Initial plan was to cycle through all the threads, and only return if
- // we tried to steal from every thread, and failed. Arch says that's not such a great idea.
- victim = __kmp_get_random(thread) % (nthreads - 1);
- if (victim >= tid) {
- ++victim; // Adjusts random distribution to exclude self
- }
- // Found a potential victim
- other_thread = threads_data[victim].td.td_thr;
- // There is a slight chance that __kmp_enable_tasking() did not wake up all threads
- // waiting at the barrier. If victim is sleeping, then wake it up. Since we were going to
- // pay the cache miss penalty for referencing another thread's kmp_info_t struct anyway,
- // the check shouldn't cost too much performance at this point. In extra barrier mode, tasks
- // do not sleep at the separate tasking barrier, so this isn't a problem.
- asleep = 0;
- if ( ( __kmp_tasking_mode == tskm_task_teams ) &&
- (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) &&
- (TCR_PTR(other_thread->th.th_sleep_loc) != NULL)) {
- asleep = 1;
- __kmp_null_resume_wrapper(__kmp_gtid_from_thread(other_thread), other_thread->th.th_sleep_loc);
- // A sleeping thread should not have any tasks on it's queue. There is a slight
- // possibility that it resumes, steals a task from another thread, which spawns more
- // tasks, all in the time that it takes this thread to check => don't write an assertion
- // that the victim's queue is empty. Try stealing from a different thread.
- }
- } while (asleep);
- }
-
- if (!asleep) {
- // We have a victim to try to steal from
- task = __kmp_steal_task(other_thread, gtid, task_team, unfinished_threads, thread_finished, is_constrained);
- }
- if (task != NULL) { // set last stolen to victim
- if (threads_data[tid].td.td_deque_last_stolen != victim) {
- threads_data[tid].td.td_deque_last_stolen = victim;
- // The pre-refactored code did not try more than 1 successful new vicitm,
- // unless the last one generated more local tasks; new_victim keeps track of this
- new_victim = 1;
- }
- }
- else { // No tasks found; unset last_stolen
- KMP_CHECK_UPDATE(threads_data[tid].td.td_deque_last_stolen, -1);
- victim = -2; // no successful victim found
- }
- }
-
- if (task == NULL) // break out of tasking loop
- break;
-
- // Found a task; execute it
-#if USE_ITT_BUILD && USE_ITT_NOTIFY
- if ( __itt_sync_create_ptr || KMP_ITT_DEBUG ) {
- if ( itt_sync_obj == NULL ) { // we are at fork barrier where we could not get the object reliably
- itt_sync_obj = __kmp_itt_barrier_object( gtid, bs_forkjoin_barrier );
- }
- __kmp_itt_task_starting( itt_sync_obj );
- }
-#endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */
- __kmp_invoke_task( gtid, task, current_task );
-#if USE_ITT_BUILD
- if ( itt_sync_obj != NULL ) __kmp_itt_task_finished( itt_sync_obj );
-#endif /* USE_ITT_BUILD */
- // If this thread is only partway through the barrier and the condition is met, then return now,
- // so that the barrier gather/release pattern can proceed. If this thread is in the last spin loop
- // in the barrier, waiting to be released, we know that the termination condition will not be
- // satisified, so don't waste any cycles checking it.
- if (flag == NULL || (!final_spin && flag->done_check())) {
- KA_TRACE(15, ("__kmp_execute_tasks_template: T#%d spin condition satisfied\n", gtid) );
- return TRUE;
- }
- if (thread->th.th_task_team == NULL) {
- break;
- }
- KMP_YIELD( __kmp_library == library_throughput ); // Yield before executing next task
- // If execution of a stolen task results in more tasks being placed on our run queue, reset use_own_tasks
- if (!use_own_tasks && TCR_4(threads_data[tid].td.td_deque_ntasks) != 0) {
- KA_TRACE(20, ("__kmp_execute_tasks_template: T#%d stolen task spawned other tasks, restart\n", gtid));
- use_own_tasks = 1;
- new_victim = 0;
- }
- }
-
- // The task source has been exhausted. If in final spin loop of barrier, check if termination condition is satisfied.
-#if OMP_45_ENABLED
- // The work queue may be empty but there might be proxy tasks still executing
- if (final_spin && TCR_4(current_task->td_incomplete_child_tasks) == 0)
-#else
- if (final_spin)
-#endif
- {
- // First, decrement the #unfinished threads, if that has not already been done. This decrement
- // might be to the spin location, and result in the termination condition being satisfied.
- if (! *thread_finished) {
- kmp_uint32 count;
-
- count = KMP_TEST_THEN_DEC32( (kmp_int32 *)unfinished_threads ) - 1;
- KA_TRACE(20, ("__kmp_execute_tasks_template: T#%d dec unfinished_threads to %d task_team=%p\n",
- gtid, count, task_team) );
- *thread_finished = TRUE;
- }
-
- // It is now unsafe to reference thread->th.th_team !!!
- // Decrementing task_team->tt.tt_unfinished_threads can allow the master thread to pass through
- // the barrier, where it might reset each thread's th.th_team field for the next parallel region.
- // If we can steal more work, we know that this has not happened yet.
- if (flag != NULL && flag->done_check()) {
- KA_TRACE(15, ("__kmp_execute_tasks_template: T#%d spin condition satisfied\n", gtid) );
- return TRUE;
- }
- }
-
- // If this thread's task team is NULL, master has recognized that there are no more tasks; bail out
- if (thread->th.th_task_team == NULL) {
- KA_TRACE(15, ("__kmp_execute_tasks_template: T#%d no more tasks\n", gtid) );
- return FALSE;
- }
-
-#if OMP_45_ENABLED
- // We could be getting tasks from target constructs; if this is the only thread, keep trying to execute
- // tasks from own queue
- if (nthreads == 1)
- use_own_tasks = 1;
- else
-#endif
- {
- KA_TRACE(15, ("__kmp_execute_tasks_template: T#%d can't find work\n", gtid) );
- return FALSE;
- }
- }
-}
-
-int __kmp_execute_tasks_32(kmp_info_t *thread, kmp_int32 gtid, kmp_flag_32 *flag, int final_spin,
- int *thread_finished
- USE_ITT_BUILD_ARG(void * itt_sync_obj), kmp_int32 is_constrained)
-{
- return __kmp_execute_tasks_template(thread, gtid, flag, final_spin, thread_finished
- USE_ITT_BUILD_ARG(itt_sync_obj), is_constrained);
-}
-
-int __kmp_execute_tasks_64(kmp_info_t *thread, kmp_int32 gtid, kmp_flag_64 *flag, int final_spin,
- int *thread_finished
- USE_ITT_BUILD_ARG(void * itt_sync_obj), kmp_int32 is_constrained)
-{
- return __kmp_execute_tasks_template(thread, gtid, flag, final_spin, thread_finished
- USE_ITT_BUILD_ARG(itt_sync_obj), is_constrained);
-}
-
-int __kmp_execute_tasks_oncore(kmp_info_t *thread, kmp_int32 gtid, kmp_flag_oncore *flag, int final_spin,
- int *thread_finished
- USE_ITT_BUILD_ARG(void * itt_sync_obj), kmp_int32 is_constrained)
-{
- return __kmp_execute_tasks_template(thread, gtid, flag, final_spin, thread_finished
- USE_ITT_BUILD_ARG(itt_sync_obj), is_constrained);
-}
-
-
-
-//-----------------------------------------------------------------------------
-// __kmp_enable_tasking: Allocate task team and resume threads sleeping at the
-// next barrier so they can assist in executing enqueued tasks.
-// First thread in allocates the task team atomically.
-
-static void
-__kmp_enable_tasking( kmp_task_team_t *task_team, kmp_info_t *this_thr )
-{
- kmp_thread_data_t *threads_data;
- int nthreads, i, is_init_thread;
-
- KA_TRACE( 10, ( "__kmp_enable_tasking(enter): T#%d\n",
- __kmp_gtid_from_thread( this_thr ) ) );
-
- KMP_DEBUG_ASSERT(task_team != NULL);
- KMP_DEBUG_ASSERT(this_thr->th.th_team != NULL);
-
- nthreads = task_team->tt.tt_nproc;
- KMP_DEBUG_ASSERT(nthreads > 0);
- KMP_DEBUG_ASSERT(nthreads == this_thr->th.th_team->t.t_nproc);
-
- // Allocate or increase the size of threads_data if necessary
- is_init_thread = __kmp_realloc_task_threads_data( this_thr, task_team );
-
- if (!is_init_thread) {
- // Some other thread already set up the array.
- KA_TRACE( 20, ( "__kmp_enable_tasking(exit): T#%d: threads array already set up.\n",
- __kmp_gtid_from_thread( this_thr ) ) );
- return;
- }
- threads_data = (kmp_thread_data_t *)TCR_PTR(task_team -> tt.tt_threads_data);
- KMP_DEBUG_ASSERT( threads_data != NULL );
-
- if ( ( __kmp_tasking_mode == tskm_task_teams ) &&
- ( __kmp_dflt_blocktime != KMP_MAX_BLOCKTIME ) )
- {
- // Release any threads sleeping at the barrier, so that they can steal
- // tasks and execute them. In extra barrier mode, tasks do not sleep
- // at the separate tasking barrier, so this isn't a problem.
- for (i = 0; i < nthreads; i++) {
- volatile void *sleep_loc;
- kmp_info_t *thread = threads_data[i].td.td_thr;
-
- if (i == this_thr->th.th_info.ds.ds_tid) {
- continue;
- }
- // Since we haven't locked the thread's suspend mutex lock at this
- // point, there is a small window where a thread might be putting
- // itself to sleep, but hasn't set the th_sleep_loc field yet.
- // To work around this, __kmp_execute_tasks_template() periodically checks
- // see if other threads are sleeping (using the same random
- // mechanism that is used for task stealing) and awakens them if
- // they are.
- if ( ( sleep_loc = TCR_PTR( thread -> th.th_sleep_loc) ) != NULL )
- {
- KF_TRACE( 50, ( "__kmp_enable_tasking: T#%d waking up thread T#%d\n",
- __kmp_gtid_from_thread( this_thr ),
- __kmp_gtid_from_thread( thread ) ) );
- __kmp_null_resume_wrapper(__kmp_gtid_from_thread(thread), sleep_loc);
- }
- else {
- KF_TRACE( 50, ( "__kmp_enable_tasking: T#%d don't wake up thread T#%d\n",
- __kmp_gtid_from_thread( this_thr ),
- __kmp_gtid_from_thread( thread ) ) );
- }
- }
- }
-
- KA_TRACE( 10, ( "__kmp_enable_tasking(exit): T#%d\n",
- __kmp_gtid_from_thread( this_thr ) ) );
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* // TODO: Check the comment consistency
- * Utility routines for "task teams". A task team (kmp_task_t) is kind of
- * like a shadow of the kmp_team_t data struct, with a different lifetime.
- * After a child * thread checks into a barrier and calls __kmp_release() from
- * the particular variant of __kmp_<barrier_kind>_barrier_gather(), it can no
- * longer assume that the kmp_team_t structure is intact (at any moment, the
- * master thread may exit the barrier code and free the team data structure,
- * and return the threads to the thread pool).
- *
- * This does not work with the the tasking code, as the thread is still
- * expected to participate in the execution of any tasks that may have been
- * spawned my a member of the team, and the thread still needs access to all
- * to each thread in the team, so that it can steal work from it.
- *
- * Enter the existence of the kmp_task_team_t struct. It employs a reference
- * counting mechanims, and is allocated by the master thread before calling
- * __kmp_<barrier_kind>_release, and then is release by the last thread to
- * exit __kmp_<barrier_kind>_release at the next barrier. I.e. the lifetimes
- * of the kmp_task_team_t structs for consecutive barriers can overlap
- * (and will, unless the master thread is the last thread to exit the barrier
- * release phase, which is not typical).
- *
- * The existence of such a struct is useful outside the context of tasking,
- * but for now, I'm trying to keep it specific to the OMP_30_ENABLED macro,
- * so that any performance differences show up when comparing the 2.5 vs. 3.0
- * libraries.
- *
- * We currently use the existence of the threads array as an indicator that
- * tasks were spawned since the last barrier. If the structure is to be
- * useful outside the context of tasking, then this will have to change, but
- * not settting the field minimizes the performance impact of tasking on
- * barriers, when no explicit tasks were spawned (pushed, actually).
- */
-
-
-static kmp_task_team_t *__kmp_free_task_teams = NULL; // Free list for task_team data structures
-// Lock for task team data structures
-static kmp_bootstrap_lock_t __kmp_task_team_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( __kmp_task_team_lock );
-
-
-//------------------------------------------------------------------------------
-// __kmp_alloc_task_deque:
-// Allocates a task deque for a particular thread, and initialize the necessary
-// data structures relating to the deque. This only happens once per thread
-// per task team since task teams are recycled.
-// No lock is needed during allocation since each thread allocates its own
-// deque.
-
-static void
-__kmp_alloc_task_deque( kmp_info_t *thread, kmp_thread_data_t *thread_data )
-{
- __kmp_init_bootstrap_lock( & thread_data -> td.td_deque_lock );
- KMP_DEBUG_ASSERT( thread_data -> td.td_deque == NULL );
-
- // Initialize last stolen task field to "none"
- thread_data -> td.td_deque_last_stolen = -1;
-
- KMP_DEBUG_ASSERT( TCR_4(thread_data -> td.td_deque_ntasks) == 0 );
- KMP_DEBUG_ASSERT( thread_data -> td.td_deque_head == 0 );
- KMP_DEBUG_ASSERT( thread_data -> td.td_deque_tail == 0 );
-
- KE_TRACE( 10, ( "__kmp_alloc_task_deque: T#%d allocating deque[%d] for thread_data %p\n",
- __kmp_gtid_from_thread( thread ), INITIAL_TASK_DEQUE_SIZE, thread_data ) );
- // Allocate space for task deque, and zero the deque
- // Cannot use __kmp_thread_calloc() because threads not around for
- // kmp_reap_task_team( ).
- thread_data -> td.td_deque = (kmp_taskdata_t **)
- __kmp_allocate( INITIAL_TASK_DEQUE_SIZE * sizeof(kmp_taskdata_t *));
- thread_data -> td.td_deque_size = INITIAL_TASK_DEQUE_SIZE;
-}
-
-//------------------------------------------------------------------------------
-// __kmp_realloc_task_deque:
-// Re-allocates a task deque for a particular thread, copies the content from the old deque
-// and adjusts the necessary data structures relating to the deque.
-// This operation must be done with a the deque_lock being held
-
-static void __kmp_realloc_task_deque ( kmp_info_t *thread, kmp_thread_data_t *thread_data )
-{
- kmp_int32 size = TASK_DEQUE_SIZE(thread_data->td);
- kmp_int32 new_size = 2 * size;
-
- KE_TRACE( 10, ( "__kmp_realloc_task_deque: T#%d reallocating deque[from %d to %d] for thread_data %p\n",
- __kmp_gtid_from_thread( thread ), size, new_size, thread_data ) );
-
- kmp_taskdata_t ** new_deque = (kmp_taskdata_t **) __kmp_allocate( new_size * sizeof(kmp_taskdata_t *));
-
- int i,j;
- for ( i = thread_data->td.td_deque_head, j = 0; j < size; i = (i+1) & TASK_DEQUE_MASK(thread_data->td), j++ )
- new_deque[j] = thread_data->td.td_deque[i];
-
- __kmp_free(thread_data->td.td_deque);
-
- thread_data -> td.td_deque_head = 0;
- thread_data -> td.td_deque_tail = size;
- thread_data -> td.td_deque = new_deque;
- thread_data -> td.td_deque_size = new_size;
-}
-
-//------------------------------------------------------------------------------
-// __kmp_free_task_deque:
-// Deallocates a task deque for a particular thread.
-// Happens at library deallocation so don't need to reset all thread data fields.
-
-static void
-__kmp_free_task_deque( kmp_thread_data_t *thread_data )
-{
- __kmp_acquire_bootstrap_lock( & thread_data -> td.td_deque_lock );
-
- if ( thread_data -> td.td_deque != NULL ) {
- TCW_4(thread_data -> td.td_deque_ntasks, 0);
- __kmp_free( thread_data -> td.td_deque );
- thread_data -> td.td_deque = NULL;
- }
- __kmp_release_bootstrap_lock( & thread_data -> td.td_deque_lock );
-
-#ifdef BUILD_TIED_TASK_STACK
- // GEH: Figure out what to do here for td_susp_tied_tasks
- if ( thread_data -> td.td_susp_tied_tasks.ts_entries != TASK_STACK_EMPTY ) {
- __kmp_free_task_stack( __kmp_thread_from_gtid( gtid ), thread_data );
- }
-#endif // BUILD_TIED_TASK_STACK
-}
-
-
-//------------------------------------------------------------------------------
-// __kmp_realloc_task_threads_data:
-// Allocates a threads_data array for a task team, either by allocating an initial
-// array or enlarging an existing array. Only the first thread to get the lock
-// allocs or enlarges the array and re-initializes the array eleemnts.
-// That thread returns "TRUE", the rest return "FALSE".
-// Assumes that the new array size is given by task_team -> tt.tt_nproc.
-// The current size is given by task_team -> tt.tt_max_threads.
-
-static int
-__kmp_realloc_task_threads_data( kmp_info_t *thread, kmp_task_team_t *task_team )
-{
- kmp_thread_data_t ** threads_data_p;
- kmp_int32 nthreads, maxthreads;
- int is_init_thread = FALSE;
-
- if ( TCR_4(task_team -> tt.tt_found_tasks) ) {
- // Already reallocated and initialized.
- return FALSE;
- }
-
- threads_data_p = & task_team -> tt.tt_threads_data;
- nthreads = task_team -> tt.tt_nproc;
- maxthreads = task_team -> tt.tt_max_threads;
-
- // All threads must lock when they encounter the first task of the implicit task
- // region to make sure threads_data fields are (re)initialized before used.
- __kmp_acquire_bootstrap_lock( & task_team -> tt.tt_threads_lock );
-
- if ( ! TCR_4(task_team -> tt.tt_found_tasks) ) {
- // first thread to enable tasking
- kmp_team_t *team = thread -> th.th_team;
- int i;
-
- is_init_thread = TRUE;
- if ( maxthreads < nthreads ) {
-
- if ( *threads_data_p != NULL ) {
- kmp_thread_data_t *old_data = *threads_data_p;
- kmp_thread_data_t *new_data = NULL;
-
- KE_TRACE( 10, ( "__kmp_realloc_task_threads_data: T#%d reallocating "
- "threads data for task_team %p, new_size = %d, old_size = %d\n",
- __kmp_gtid_from_thread( thread ), task_team,
- nthreads, maxthreads ) );
- // Reallocate threads_data to have more elements than current array
- // Cannot use __kmp_thread_realloc() because threads not around for
- // kmp_reap_task_team( ). Note all new array entries are initialized
- // to zero by __kmp_allocate().
- new_data = (kmp_thread_data_t *)
- __kmp_allocate( nthreads * sizeof(kmp_thread_data_t) );
- // copy old data to new data
- KMP_MEMCPY_S( (void *) new_data, nthreads * sizeof(kmp_thread_data_t),
- (void *) old_data,
- maxthreads * sizeof(kmp_taskdata_t *) );
-
-#ifdef BUILD_TIED_TASK_STACK
- // GEH: Figure out if this is the right thing to do
- for (i = maxthreads; i < nthreads; i++) {
- kmp_thread_data_t *thread_data = & (*threads_data_p)[i];
- __kmp_init_task_stack( __kmp_gtid_from_thread( thread ), thread_data );
- }
-#endif // BUILD_TIED_TASK_STACK
- // Install the new data and free the old data
- (*threads_data_p) = new_data;
- __kmp_free( old_data );
- }
- else {
- KE_TRACE( 10, ( "__kmp_realloc_task_threads_data: T#%d allocating "
- "threads data for task_team %p, size = %d\n",
- __kmp_gtid_from_thread( thread ), task_team, nthreads ) );
- // Make the initial allocate for threads_data array, and zero entries
- // Cannot use __kmp_thread_calloc() because threads not around for
- // kmp_reap_task_team( ).
- ANNOTATE_IGNORE_WRITES_BEGIN();
- *threads_data_p = (kmp_thread_data_t *)
- __kmp_allocate( nthreads * sizeof(kmp_thread_data_t) );
- ANNOTATE_IGNORE_WRITES_END();
-#ifdef BUILD_TIED_TASK_STACK
- // GEH: Figure out if this is the right thing to do
- for (i = 0; i < nthreads; i++) {
- kmp_thread_data_t *thread_data = & (*threads_data_p)[i];
- __kmp_init_task_stack( __kmp_gtid_from_thread( thread ), thread_data );
- }
-#endif // BUILD_TIED_TASK_STACK
- }
- task_team -> tt.tt_max_threads = nthreads;
- }
- else {
- // If array has (more than) enough elements, go ahead and use it
- KMP_DEBUG_ASSERT( *threads_data_p != NULL );
- }
-
- // initialize threads_data pointers back to thread_info structures
- for (i = 0; i < nthreads; i++) {
- kmp_thread_data_t *thread_data = & (*threads_data_p)[i];
- thread_data -> td.td_thr = team -> t.t_threads[i];
-
- if ( thread_data -> td.td_deque_last_stolen >= nthreads) {
- // The last stolen field survives across teams / barrier, and the number
- // of threads may have changed. It's possible (likely?) that a new
- // parallel region will exhibit the same behavior as the previous region.
- thread_data -> td.td_deque_last_stolen = -1;
- }
- }
-
- KMP_MB();
- TCW_SYNC_4(task_team -> tt.tt_found_tasks, TRUE);
- }
-
- __kmp_release_bootstrap_lock( & task_team -> tt.tt_threads_lock );
- return is_init_thread;
-}
-
-
-//------------------------------------------------------------------------------
-// __kmp_free_task_threads_data:
-// Deallocates a threads_data array for a task team, including any attached
-// tasking deques. Only occurs at library shutdown.
-
-static void
-__kmp_free_task_threads_data( kmp_task_team_t *task_team )
-{
- __kmp_acquire_bootstrap_lock( & task_team -> tt.tt_threads_lock );
- if ( task_team -> tt.tt_threads_data != NULL ) {
- int i;
- for (i = 0; i < task_team->tt.tt_max_threads; i++ ) {
- __kmp_free_task_deque( & task_team -> tt.tt_threads_data[i] );
- }
- __kmp_free( task_team -> tt.tt_threads_data );
- task_team -> tt.tt_threads_data = NULL;
- }
- __kmp_release_bootstrap_lock( & task_team -> tt.tt_threads_lock );
-}
-
-
-//------------------------------------------------------------------------------
-// __kmp_allocate_task_team:
-// Allocates a task team associated with a specific team, taking it from
-// the global task team free list if possible. Also initializes data structures.
-
-static kmp_task_team_t *
-__kmp_allocate_task_team( kmp_info_t *thread, kmp_team_t *team )
-{
- kmp_task_team_t *task_team = NULL;
- int nthreads;
-
- KA_TRACE( 20, ( "__kmp_allocate_task_team: T#%d entering; team = %p\n",
- (thread ? __kmp_gtid_from_thread( thread ) : -1), team ) );
-
- if (TCR_PTR(__kmp_free_task_teams) != NULL) {
- // Take a task team from the task team pool
- __kmp_acquire_bootstrap_lock( &__kmp_task_team_lock );
- if (__kmp_free_task_teams != NULL) {
- task_team = __kmp_free_task_teams;
- TCW_PTR(__kmp_free_task_teams, task_team -> tt.tt_next);
- task_team -> tt.tt_next = NULL;
- }
- __kmp_release_bootstrap_lock( &__kmp_task_team_lock );
- }
-
- if (task_team == NULL) {
- KE_TRACE( 10, ( "__kmp_allocate_task_team: T#%d allocating "
- "task team for team %p\n",
- __kmp_gtid_from_thread( thread ), team ) );
- // Allocate a new task team if one is not available.
- // Cannot use __kmp_thread_malloc() because threads not around for
- // kmp_reap_task_team( ).
- task_team = (kmp_task_team_t *) __kmp_allocate( sizeof(kmp_task_team_t) );
- __kmp_init_bootstrap_lock( & task_team -> tt.tt_threads_lock );
- //task_team -> tt.tt_threads_data = NULL; // AC: __kmp_allocate zeroes returned memory
- //task_team -> tt.tt_max_threads = 0;
- //task_team -> tt.tt_next = NULL;
- }
-
- TCW_4(task_team -> tt.tt_found_tasks, FALSE);
-#if OMP_45_ENABLED
- TCW_4(task_team -> tt.tt_found_proxy_tasks, FALSE);
-#endif
- task_team -> tt.tt_nproc = nthreads = team->t.t_nproc;
-
- TCW_4( task_team -> tt.tt_unfinished_threads, nthreads );
- TCW_4( task_team -> tt.tt_active, TRUE );
-
- KA_TRACE( 20, ( "__kmp_allocate_task_team: T#%d exiting; task_team = %p unfinished_threads init'd to %d\n",
- (thread ? __kmp_gtid_from_thread( thread ) : -1), task_team, task_team -> tt.tt_unfinished_threads) );
- return task_team;
-}
-
-
-//------------------------------------------------------------------------------
-// __kmp_free_task_team:
-// Frees the task team associated with a specific thread, and adds it
-// to the global task team free list.
-
-void
-__kmp_free_task_team( kmp_info_t *thread, kmp_task_team_t *task_team )
-{
- KA_TRACE( 20, ( "__kmp_free_task_team: T#%d task_team = %p\n",
- thread ? __kmp_gtid_from_thread( thread ) : -1, task_team ) );
-
- // Put task team back on free list
- __kmp_acquire_bootstrap_lock( & __kmp_task_team_lock );
-
- KMP_DEBUG_ASSERT( task_team -> tt.tt_next == NULL );
- task_team -> tt.tt_next = __kmp_free_task_teams;
- TCW_PTR(__kmp_free_task_teams, task_team);
-
- __kmp_release_bootstrap_lock( & __kmp_task_team_lock );
-}
-
-
-//------------------------------------------------------------------------------
-// __kmp_reap_task_teams:
-// Free all the task teams on the task team free list.
-// Should only be done during library shutdown.
-// Cannot do anything that needs a thread structure or gtid since they are already gone.
-
-void
-__kmp_reap_task_teams( void )
-{
- kmp_task_team_t *task_team;
-
- if ( TCR_PTR(__kmp_free_task_teams) != NULL ) {
- // Free all task_teams on the free list
- __kmp_acquire_bootstrap_lock( &__kmp_task_team_lock );
- while ( ( task_team = __kmp_free_task_teams ) != NULL ) {
- __kmp_free_task_teams = task_team -> tt.tt_next;
- task_team -> tt.tt_next = NULL;
-
- // Free threads_data if necessary
- if ( task_team -> tt.tt_threads_data != NULL ) {
- __kmp_free_task_threads_data( task_team );
- }
- __kmp_free( task_team );
- }
- __kmp_release_bootstrap_lock( &__kmp_task_team_lock );
- }
-}
-
-//------------------------------------------------------------------------------
-// __kmp_wait_to_unref_task_teams:
-// Some threads could still be in the fork barrier release code, possibly
-// trying to steal tasks. Wait for each thread to unreference its task team.
-//
-void
-__kmp_wait_to_unref_task_teams(void)
-{
- kmp_info_t *thread;
- kmp_uint32 spins;
- int done;
-
- KMP_INIT_YIELD( spins );
-
- for (;;) {
- done = TRUE;
-
- // TODO: GEH - this may be is wrong because some sync would be necessary
- // in case threads are added to the pool during the traversal.
- // Need to verify that lock for thread pool is held when calling
- // this routine.
- for (thread = (kmp_info_t *)__kmp_thread_pool;
- thread != NULL;
- thread = thread->th.th_next_pool)
- {
-#if KMP_OS_WINDOWS
- DWORD exit_val;
-#endif
- if ( TCR_PTR(thread->th.th_task_team) == NULL ) {
- KA_TRACE( 10, ("__kmp_wait_to_unref_task_team: T#%d task_team == NULL\n",
- __kmp_gtid_from_thread( thread ) ) );
- continue;
- }
-#if KMP_OS_WINDOWS
- // TODO: GEH - add this check for Linux* OS / OS X* as well?
- if (!__kmp_is_thread_alive(thread, &exit_val)) {
- thread->th.th_task_team = NULL;
- continue;
- }
-#endif
-
- done = FALSE; // Because th_task_team pointer is not NULL for this thread
-
- KA_TRACE( 10, ("__kmp_wait_to_unref_task_team: Waiting for T#%d to unreference task_team\n",
- __kmp_gtid_from_thread( thread ) ) );
-
- if ( __kmp_dflt_blocktime != KMP_MAX_BLOCKTIME ) {
- volatile void *sleep_loc;
- // If the thread is sleeping, awaken it.
- if ( ( sleep_loc = TCR_PTR( thread->th.th_sleep_loc) ) != NULL ) {
- KA_TRACE( 10, ( "__kmp_wait_to_unref_task_team: T#%d waking up thread T#%d\n",
- __kmp_gtid_from_thread( thread ), __kmp_gtid_from_thread( thread ) ) );
- __kmp_null_resume_wrapper(__kmp_gtid_from_thread(thread), sleep_loc);
- }
- }
- }
- if (done) {
- break;
- }
-
- // If we are oversubscribed,
- // or have waited a bit (and library mode is throughput), yield.
- // Pause is in the following code.
- KMP_YIELD( TCR_4(__kmp_nth) > __kmp_avail_proc );
- KMP_YIELD_SPIN( spins ); // Yields only if KMP_LIBRARY=throughput
- }
-}
-
-
-//------------------------------------------------------------------------------
-// __kmp_task_team_setup: Create a task_team for the current team, but use
-// an already created, unused one if it already exists.
-void
-__kmp_task_team_setup( kmp_info_t *this_thr, kmp_team_t *team, int always )
-{
- KMP_DEBUG_ASSERT( __kmp_tasking_mode != tskm_immediate_exec );
-
- // If this task_team hasn't been created yet, allocate it. It will be used in the region after the next.
- // If it exists, it is the current task team and shouldn't be touched yet as it may still be in use.
- if (team->t.t_task_team[this_thr->th.th_task_state] == NULL && (always || team->t.t_nproc > 1) ) {
- team->t.t_task_team[this_thr->th.th_task_state] = __kmp_allocate_task_team( this_thr, team );
- KA_TRACE(20, ("__kmp_task_team_setup: Master T#%d created new task_team %p for team %d at parity=%d\n",
- __kmp_gtid_from_thread(this_thr), team->t.t_task_team[this_thr->th.th_task_state],
- ((team != NULL) ? team->t.t_id : -1), this_thr->th.th_task_state));
- }
-
- // After threads exit the release, they will call sync, and then point to this other task_team; make sure it is
- // allocated and properly initialized. As threads spin in the barrier release phase, they will continue to use the
- // previous task_team struct(above), until they receive the signal to stop checking for tasks (they can't safely
- // reference the kmp_team_t struct, which could be reallocated by the master thread). No task teams are formed for
- // serialized teams.
- if (team->t.t_nproc > 1) {
- int other_team = 1 - this_thr->th.th_task_state;
- if (team->t.t_task_team[other_team] == NULL) { // setup other team as well
- team->t.t_task_team[other_team] = __kmp_allocate_task_team( this_thr, team );
- KA_TRACE(20, ("__kmp_task_team_setup: Master T#%d created second new task_team %p for team %d at parity=%d\n",
- __kmp_gtid_from_thread( this_thr ), team->t.t_task_team[other_team],
- ((team != NULL) ? team->t.t_id : -1), other_team ));
- }
- else { // Leave the old task team struct in place for the upcoming region; adjust as needed
- kmp_task_team_t *task_team = team->t.t_task_team[other_team];
- if (!task_team->tt.tt_active || team->t.t_nproc != task_team->tt.tt_nproc) {
- TCW_4(task_team->tt.tt_nproc, team->t.t_nproc);
- TCW_4(task_team->tt.tt_found_tasks, FALSE);
-#if OMP_45_ENABLED
- TCW_4(task_team->tt.tt_found_proxy_tasks, FALSE);
-#endif
- TCW_4(task_team->tt.tt_unfinished_threads, team->t.t_nproc );
- TCW_4(task_team->tt.tt_active, TRUE );
- }
- // if team size has changed, the first thread to enable tasking will realloc threads_data if necessary
- KA_TRACE(20, ("__kmp_task_team_setup: Master T#%d reset next task_team %p for team %d at parity=%d\n",
- __kmp_gtid_from_thread( this_thr ), team->t.t_task_team[other_team],
- ((team != NULL) ? team->t.t_id : -1), other_team ));
- }
- }
-}
-
-
-//------------------------------------------------------------------------------
-// __kmp_task_team_sync: Propagation of task team data from team to threads
-// which happens just after the release phase of a team barrier. This may be
-// called by any thread, but only for teams with # threads > 1.
-
-void
-__kmp_task_team_sync( kmp_info_t *this_thr, kmp_team_t *team )
-{
- KMP_DEBUG_ASSERT( __kmp_tasking_mode != tskm_immediate_exec );
-
- // Toggle the th_task_state field, to switch which task_team this thread refers to
- this_thr->th.th_task_state = 1 - this_thr->th.th_task_state;
- // It is now safe to propagate the task team pointer from the team struct to the current thread.
- TCW_PTR(this_thr->th.th_task_team, team->t.t_task_team[this_thr->th.th_task_state]);
- KA_TRACE(20, ("__kmp_task_team_sync: Thread T#%d task team switched to task_team %p from Team #%d (parity=%d)\n",
- __kmp_gtid_from_thread( this_thr ), this_thr->th.th_task_team,
- ((team != NULL) ? team->t.t_id : -1), this_thr->th.th_task_state));
-}
-
-
-//--------------------------------------------------------------------------------------------
-// __kmp_task_team_wait: Master thread waits for outstanding tasks after the barrier gather
-// phase. Only called by master thread if #threads in team > 1 or if proxy tasks were created.
-// wait is a flag that defaults to 1 (see kmp.h), but waiting can be turned off by passing in 0
-// optionally as the last argument. When wait is zero, master thread does not wait for
-// unfinished_threads to reach 0.
-void
-__kmp_task_team_wait( kmp_info_t *this_thr, kmp_team_t *team
- USE_ITT_BUILD_ARG(void * itt_sync_obj)
- , int wait)
-{
- kmp_task_team_t *task_team = team->t.t_task_team[this_thr->th.th_task_state];
-
- KMP_DEBUG_ASSERT( __kmp_tasking_mode != tskm_immediate_exec );
- KMP_DEBUG_ASSERT( task_team == this_thr->th.th_task_team );
-
- if ( ( task_team != NULL ) && KMP_TASKING_ENABLED(task_team) ) {
- if (wait) {
- KA_TRACE(20, ("__kmp_task_team_wait: Master T#%d waiting for all tasks (for unfinished_threads to reach 0) on task_team = %p\n",
- __kmp_gtid_from_thread(this_thr), task_team));
- // Worker threads may have dropped through to release phase, but could still be executing tasks. Wait
- // here for tasks to complete. To avoid memory contention, only master thread checks termination condition.
- kmp_flag_32 flag(&task_team->tt.tt_unfinished_threads, 0U);
- flag.wait(this_thr, TRUE
- USE_ITT_BUILD_ARG(itt_sync_obj));
- }
- // Deactivate the old task team, so that the worker threads will stop referencing it while spinning.
- KA_TRACE(20, ("__kmp_task_team_wait: Master T#%d deactivating task_team %p: "
- "setting active to false, setting local and team's pointer to NULL\n",
- __kmp_gtid_from_thread(this_thr), task_team));
-#if OMP_45_ENABLED
- KMP_DEBUG_ASSERT( task_team->tt.tt_nproc > 1 || task_team->tt.tt_found_proxy_tasks == TRUE );
- TCW_SYNC_4( task_team->tt.tt_found_proxy_tasks, FALSE );
-#else
- KMP_DEBUG_ASSERT( task_team->tt.tt_nproc > 1 );
-#endif
- TCW_SYNC_4( task_team->tt.tt_active, FALSE );
- KMP_MB();
-
- TCW_PTR(this_thr->th.th_task_team, NULL);
- }
-}
-
-
-//------------------------------------------------------------------------------
-// __kmp_tasking_barrier:
-// This routine may only called when __kmp_tasking_mode == tskm_extra_barrier.
-// Internal function to execute all tasks prior to a regular barrier or a
-// join barrier. It is a full barrier itself, which unfortunately turns
-// regular barriers into double barriers and join barriers into 1 1/2
-// barriers.
-void
-__kmp_tasking_barrier( kmp_team_t *team, kmp_info_t *thread, int gtid )
-{
- volatile kmp_uint32 *spin = &team->t.t_task_team[thread->th.th_task_state]->tt.tt_unfinished_threads;
- int flag = FALSE;
- KMP_DEBUG_ASSERT( __kmp_tasking_mode == tskm_extra_barrier );
-
-#if USE_ITT_BUILD
- KMP_FSYNC_SPIN_INIT( spin, (kmp_uint32*) NULL );
-#endif /* USE_ITT_BUILD */
- kmp_flag_32 spin_flag(spin, 0U);
- while (! spin_flag.execute_tasks(thread, gtid, TRUE, &flag
- USE_ITT_BUILD_ARG(NULL), 0 ) ) {
-#if USE_ITT_BUILD
- // TODO: What about itt_sync_obj??
- KMP_FSYNC_SPIN_PREPARE( spin );
-#endif /* USE_ITT_BUILD */
-
- if( TCR_4(__kmp_global.g.g_done) ) {
- if( __kmp_global.g.g_abort )
- __kmp_abort_thread( );
- break;
- }
- KMP_YIELD( TRUE ); // GH: We always yield here
- }
-#if USE_ITT_BUILD
- KMP_FSYNC_SPIN_ACQUIRED( (void*) spin );
-#endif /* USE_ITT_BUILD */
-}
-
-
-#if OMP_45_ENABLED
-
-/* __kmp_give_task puts a task into a given thread queue if:
- - the queue for that thread was created
- - there's space in that queue
-
- Because of this, __kmp_push_task needs to check if there's space after getting the lock
- */
-static bool __kmp_give_task ( kmp_info_t *thread, kmp_int32 tid, kmp_task_t * task, kmp_int32 pass )
-{
- kmp_taskdata_t * taskdata = KMP_TASK_TO_TASKDATA(task);
- kmp_task_team_t * task_team = taskdata->td_task_team;
-
- KA_TRACE(20, ("__kmp_give_task: trying to give task %p to thread %d.\n", taskdata, tid ) );
-
- // If task_team is NULL something went really bad...
- KMP_DEBUG_ASSERT( task_team != NULL );
-
- bool result = false;
- kmp_thread_data_t * thread_data = & task_team -> tt.tt_threads_data[ tid ];
-
- if (thread_data -> td.td_deque == NULL ) {
- // There's no queue in this thread, go find another one
- // We're guaranteed that at least one thread has a queue
- KA_TRACE(30, ("__kmp_give_task: thread %d has no queue while giving task %p.\n", tid, taskdata ) );
- return result;
- }
-
- if ( TCR_4(thread_data -> td.td_deque_ntasks) >= TASK_DEQUE_SIZE(thread_data->td) )
- {
- KA_TRACE(30, ("__kmp_give_task: queue is full while giving task %p to thread %d.\n", taskdata, tid ) );
-
- // if this deque is bigger than the pass ratio give a chance to another thread
- if ( TASK_DEQUE_SIZE(thread_data->td)/INITIAL_TASK_DEQUE_SIZE >= pass ) return result;
-
- __kmp_acquire_bootstrap_lock( & thread_data-> td.td_deque_lock );
- __kmp_realloc_task_deque(thread,thread_data);
-
- } else {
-
- __kmp_acquire_bootstrap_lock( & thread_data-> td.td_deque_lock );
-
- if ( TCR_4(thread_data -> td.td_deque_ntasks) >= TASK_DEQUE_SIZE(thread_data->td) )
- {
- KA_TRACE(30, ("__kmp_give_task: queue is full while giving task %p to thread %d.\n", taskdata, tid ) );
-
- // if this deque is bigger than the pass ratio give a chance to another thread
- if ( TASK_DEQUE_SIZE(thread_data->td)/INITIAL_TASK_DEQUE_SIZE >= pass )
- goto release_and_exit;
-
- __kmp_realloc_task_deque(thread,thread_data);
- }
- }
-
- // lock is held here, and there is space in the deque
-
- thread_data -> td.td_deque[ thread_data -> td.td_deque_tail ] = taskdata;
- // Wrap index.
- thread_data -> td.td_deque_tail = ( thread_data -> td.td_deque_tail + 1 ) & TASK_DEQUE_MASK(thread_data->td);
- TCW_4(thread_data -> td.td_deque_ntasks, TCR_4(thread_data -> td.td_deque_ntasks) + 1);
-
- result = true;
- KA_TRACE(30, ("__kmp_give_task: successfully gave task %p to thread %d.\n", taskdata, tid ) );
-
-release_and_exit:
- __kmp_release_bootstrap_lock( & thread_data-> td.td_deque_lock );
-
- return result;
-}
-
-
-/* The finish of the a proxy tasks is divided in two pieces:
- - the top half is the one that can be done from a thread outside the team
- - the bottom half must be run from a them within the team
-
- In order to run the bottom half the task gets queued back into one of the threads of the team.
- Once the td_incomplete_child_task counter of the parent is decremented the threads can leave the barriers.
- So, the bottom half needs to be queued before the counter is decremented. The top half is therefore divided in two parts:
- - things that can be run before queuing the bottom half
- - things that must be run after queuing the bottom half
-
- This creates a second race as the bottom half can free the task before the second top half is executed. To avoid this
- we use the td_incomplete_child_task of the proxy task to synchronize the top and bottom half.
-*/
-
-static void __kmp_first_top_half_finish_proxy( kmp_taskdata_t * taskdata )
-{
- KMP_DEBUG_ASSERT( taskdata -> td_flags.tasktype == TASK_EXPLICIT );
- KMP_DEBUG_ASSERT( taskdata -> td_flags.proxy == TASK_PROXY );
- KMP_DEBUG_ASSERT( taskdata -> td_flags.complete == 0 );
- KMP_DEBUG_ASSERT( taskdata -> td_flags.freed == 0 );
-
- taskdata -> td_flags.complete = 1; // mark the task as completed
-
- if ( taskdata->td_taskgroup )
- KMP_TEST_THEN_DEC32( (kmp_int32 *)(& taskdata->td_taskgroup->count) );
-
- // Create an imaginary children for this task so the bottom half cannot release the task before we have completed the second top half
- TCI_4(taskdata->td_incomplete_child_tasks);
-}
-
-static void __kmp_second_top_half_finish_proxy( kmp_taskdata_t * taskdata )
-{
- kmp_int32 children = 0;
-
- // Predecrement simulated by "- 1" calculation
- children = KMP_TEST_THEN_DEC32( (kmp_int32 *)(& taskdata -> td_parent -> td_incomplete_child_tasks) ) - 1;
- KMP_DEBUG_ASSERT( children >= 0 );
-
- // Remove the imaginary children
- TCD_4(taskdata->td_incomplete_child_tasks);
-}
-
-static void __kmp_bottom_half_finish_proxy( kmp_int32 gtid, kmp_task_t * ptask )
-{
- kmp_taskdata_t * taskdata = KMP_TASK_TO_TASKDATA(ptask);
- kmp_info_t * thread = __kmp_threads[ gtid ];
-
- KMP_DEBUG_ASSERT( taskdata -> td_flags.proxy == TASK_PROXY );
- KMP_DEBUG_ASSERT( taskdata -> td_flags.complete == 1 ); // top half must run before bottom half
-
- // We need to wait to make sure the top half is finished
- // Spinning here should be ok as this should happen quickly
- while ( TCR_4(taskdata->td_incomplete_child_tasks) > 0 ) ;
-
- __kmp_release_deps(gtid,taskdata);
- __kmp_free_task_and_ancestors(gtid, taskdata, thread);
-}
-
-/*!
- at ingroup TASKING
- at param gtid Global Thread ID of encountering thread
- at param ptask Task which execution is completed
-
-Execute the completation of a proxy task from a thread of that is part of the team. Run first and bottom halves directly.
-*/
-void __kmpc_proxy_task_completed( kmp_int32 gtid, kmp_task_t *ptask )
-{
- KMP_DEBUG_ASSERT( ptask != NULL );
- kmp_taskdata_t * taskdata = KMP_TASK_TO_TASKDATA(ptask);
- KA_TRACE(10, ("__kmp_proxy_task_completed(enter): T#%d proxy task %p completing\n", gtid, taskdata ) );
-
- KMP_DEBUG_ASSERT( taskdata->td_flags.proxy == TASK_PROXY );
-
- __kmp_first_top_half_finish_proxy(taskdata);
- __kmp_second_top_half_finish_proxy(taskdata);
- __kmp_bottom_half_finish_proxy(gtid,ptask);
-
- KA_TRACE(10, ("__kmp_proxy_task_completed(exit): T#%d proxy task %p completing\n", gtid, taskdata ) );
-}
-
-/*!
- at ingroup TASKING
- at param ptask Task which execution is completed
-
-Execute the completation of a proxy task from a thread that could not belong to the team.
-*/
-void __kmpc_proxy_task_completed_ooo ( kmp_task_t *ptask )
-{
- KMP_DEBUG_ASSERT( ptask != NULL );
- kmp_taskdata_t * taskdata = KMP_TASK_TO_TASKDATA(ptask);
-
- KA_TRACE(10, ("__kmp_proxy_task_completed_ooo(enter): proxy task completing ooo %p\n", taskdata ) );
-
- KMP_DEBUG_ASSERT( taskdata->td_flags.proxy == TASK_PROXY );
-
- __kmp_first_top_half_finish_proxy(taskdata);
-
- // Enqueue task to complete bottom half completion from a thread within the corresponding team
- kmp_team_t * team = taskdata->td_team;
- kmp_int32 nthreads = team->t.t_nproc;
- kmp_info_t *thread;
-
- //This should be similar to start_k = __kmp_get_random( thread ) % nthreads but we cannot use __kmp_get_random here
- kmp_int32 start_k = 0;
- kmp_int32 pass = 1;
- kmp_int32 k = start_k;
-
- do {
- //For now we're just linearly trying to find a thread
- thread = team->t.t_threads[k];
- k = (k+1) % nthreads;
-
- // we did a full pass through all the threads
- if ( k == start_k ) pass = pass << 1;
-
- } while ( !__kmp_give_task( thread, k, ptask, pass ) );
-
- __kmp_second_top_half_finish_proxy(taskdata);
-
- KA_TRACE(10, ("__kmp_proxy_task_completed_ooo(exit): proxy task completing ooo %p\n", taskdata ) );
-}
-
-//---------------------------------------------------------------------------------
-// __kmp_task_dup_alloc: Allocate the taskdata and make a copy of source task for taskloop
-//
-// thread: allocating thread
-// task_src: pointer to source task to be duplicated
-// returns: a pointer to the allocated kmp_task_t structure (task).
-kmp_task_t *
-__kmp_task_dup_alloc( kmp_info_t *thread, kmp_task_t *task_src )
-{
- kmp_task_t *task;
- kmp_taskdata_t *taskdata;
- kmp_taskdata_t *taskdata_src;
- kmp_taskdata_t *parent_task = thread->th.th_current_task;
- size_t shareds_offset;
- size_t task_size;
-
- KA_TRACE(10, ("__kmp_task_dup_alloc(enter): Th %p, source task %p\n", thread, task_src) );
- taskdata_src = KMP_TASK_TO_TASKDATA( task_src );
- KMP_DEBUG_ASSERT( taskdata_src->td_flags.proxy == TASK_FULL ); // it should not be proxy task
- KMP_DEBUG_ASSERT( taskdata_src->td_flags.tasktype == TASK_EXPLICIT );
- task_size = taskdata_src->td_size_alloc;
-
- // Allocate a kmp_taskdata_t block and a kmp_task_t block.
- KA_TRACE(30, ("__kmp_task_dup_alloc: Th %p, malloc size %ld\n", thread, task_size) );
- #if USE_FAST_MEMORY
- taskdata = (kmp_taskdata_t *)__kmp_fast_allocate( thread, task_size );
- #else
- taskdata = (kmp_taskdata_t *)__kmp_thread_malloc( thread, task_size );
- #endif /* USE_FAST_MEMORY */
- KMP_MEMCPY(taskdata, taskdata_src, task_size);
-
- task = KMP_TASKDATA_TO_TASK(taskdata);
-
- // Initialize new task (only specific fields not affected by memcpy)
- taskdata->td_task_id = KMP_GEN_TASK_ID();
- if( task->shareds != NULL ) { // need setup shareds pointer
- shareds_offset = (char*)task_src->shareds - (char*)taskdata_src;
- task->shareds = &((char*)taskdata)[shareds_offset];
- KMP_DEBUG_ASSERT( (((kmp_uintptr_t)task->shareds) & (sizeof(void*)-1)) == 0 );
- }
- taskdata->td_alloc_thread = thread;
- taskdata->td_taskgroup = parent_task->td_taskgroup; // task inherits the taskgroup from the parent task
-
- // Only need to keep track of child task counts if team parallel and tasking not serialized
- if ( !( taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser ) ) {
- KMP_TEST_THEN_INC32( (kmp_int32 *)(& parent_task->td_incomplete_child_tasks) );
- if ( parent_task->td_taskgroup )
- KMP_TEST_THEN_INC32( (kmp_int32 *)(& parent_task->td_taskgroup->count) );
- // Only need to keep track of allocated child tasks for explicit tasks since implicit not deallocated
- if ( taskdata->td_parent->td_flags.tasktype == TASK_EXPLICIT )
- KMP_TEST_THEN_INC32( (kmp_int32 *)(& taskdata->td_parent->td_allocated_child_tasks) );
- }
-
- KA_TRACE(20, ("__kmp_task_dup_alloc(exit): Th %p, created task %p, parent=%p\n",
- thread, taskdata, taskdata->td_parent) );
-#if OMPT_SUPPORT
- __kmp_task_init_ompt(taskdata, thread->th.th_info.ds.ds_gtid, (void*)task->routine);
-#endif
- return task;
-}
-
-// Routine optionally generated by th ecompiler for setting the lastprivate flag
-// and calling needed constructors for private/firstprivate objects
-// (used to form taskloop tasks from pattern task)
-typedef void(*p_task_dup_t)(kmp_task_t *, kmp_task_t *, kmp_int32);
-
-//---------------------------------------------------------------------------------
-// __kmp_taskloop_linear: Start tasks of the taskloop linearly
-//
-// loc Source location information
-// gtid Global thread ID
-// task Task with whole loop iteration range
-// lb Pointer to loop lower bound
-// ub Pointer to loop upper bound
-// st Loop stride
-// sched Schedule specified 0/1/2 for none/grainsize/num_tasks
-// grainsize Schedule value if specified
-// task_dup Tasks duplication routine
-void
-__kmp_taskloop_linear(ident_t *loc, int gtid, kmp_task_t *task,
- kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st,
- int sched, kmp_uint64 grainsize, void *task_dup )
-{
- KMP_COUNT_BLOCK(OMP_TASKLOOP);
- KMP_TIME_PARTITIONED_BLOCK(OMP_taskloop_scheduling);
- p_task_dup_t ptask_dup = (p_task_dup_t)task_dup;
- kmp_uint64 tc;
- kmp_uint64 lower = *lb; // compiler provides global bounds here
- kmp_uint64 upper = *ub;
- kmp_uint64 i, num_tasks = 0, extras = 0;
- kmp_info_t *thread = __kmp_threads[gtid];
- kmp_taskdata_t *current_task = thread->th.th_current_task;
- kmp_task_t *next_task;
- kmp_int32 lastpriv = 0;
- size_t lower_offset = (char*)lb - (char*)task; // remember offset of lb in the task structure
- size_t upper_offset = (char*)ub - (char*)task; // remember offset of ub in the task structure
-
- // compute trip count
- if ( st == 1 ) { // most common case
- tc = upper - lower + 1;
- } else if ( st < 0 ) {
- tc = (lower - upper) / (-st) + 1;
- } else { // st > 0
- tc = (upper - lower) / st + 1;
- }
- if(tc == 0) {
- KA_TRACE(20, ("__kmpc_taskloop(exit): T#%d zero-trip loop\n", gtid));
- // free the pattern task and exit
- __kmp_task_start( gtid, task, current_task );
- // do not execute anything for zero-trip loop
- __kmp_task_finish( gtid, task, current_task );
- return;
- }
-
- // compute num_tasks/grainsize based on the input provided
- switch( sched ) {
- case 0: // no schedule clause specified, we can choose the default
- // let's try to schedule (team_size*10) tasks
- grainsize = thread->th.th_team_nproc * 10;
- case 2: // num_tasks provided
- if( grainsize > tc ) {
- num_tasks = tc; // too big num_tasks requested, adjust values
- grainsize = 1;
- extras = 0;
- } else {
- num_tasks = grainsize;
- grainsize = tc / num_tasks;
- extras = tc % num_tasks;
- }
- break;
- case 1: // grainsize provided
- if( grainsize > tc ) {
- num_tasks = 1; // too big grainsize requested, adjust values
- grainsize = tc;
- extras = 0;
- } else {
- num_tasks = tc / grainsize;
- grainsize = tc / num_tasks; // adjust grainsize for balanced distribution of iterations
- extras = tc % num_tasks;
- }
- break;
- default:
- KMP_ASSERT2(0, "unknown scheduling of taskloop");
- }
- KMP_DEBUG_ASSERT(tc == num_tasks * grainsize + extras);
- KMP_DEBUG_ASSERT(num_tasks > extras);
- KMP_DEBUG_ASSERT(num_tasks > 0);
- KA_TRACE(20, ("__kmpc_taskloop: T#%d will launch: num_tasks %lld, grainsize %lld, extras %lld\n",
- gtid, num_tasks, grainsize, extras));
-
- // Main loop, launch num_tasks tasks, assign grainsize iterations each task
- for( i = 0; i < num_tasks; ++i ) {
- kmp_uint64 chunk_minus_1;
- if( extras == 0 ) {
- chunk_minus_1 = grainsize - 1;
- } else {
- chunk_minus_1 = grainsize;
- --extras; // first extras iterations get bigger chunk (grainsize+1)
- }
- upper = lower + st * chunk_minus_1;
- if( i == num_tasks - 1 ) {
- // schedule the last task, set lastprivate flag
- lastpriv = 1;
-#if KMP_DEBUG
- if( st == 1 )
- KMP_DEBUG_ASSERT(upper == *ub);
- else if( st > 0 )
- KMP_DEBUG_ASSERT(upper+st > *ub);
- else
- KMP_DEBUG_ASSERT(upper+st < *ub);
-#endif
- }
- next_task = __kmp_task_dup_alloc(thread, task); // allocate new task
- *(kmp_uint64*)((char*)next_task + lower_offset) = lower; // adjust task-specific bounds
- *(kmp_uint64*)((char*)next_task + upper_offset) = upper;
- if( ptask_dup != NULL )
- ptask_dup(next_task, task, lastpriv); // set lastprivate flag, construct fistprivates, etc.
- KA_TRACE(20, ("__kmpc_taskloop: T#%d schedule task %p: lower %lld, upper %lld (offsets %p %p)\n",
- gtid, next_task, lower, upper, lower_offset, upper_offset));
- __kmp_omp_task(gtid, next_task, true); // schedule new task
- lower = upper + st; // adjust lower bound for the next iteration
- }
- // free the pattern task and exit
- __kmp_task_start( gtid, task, current_task );
- // do not execute the pattern task, just do bookkeeping
- __kmp_task_finish( gtid, task, current_task );
-}
-
-/*!
- at ingroup TASKING
- at param loc Source location information
- at param gtid Global thread ID
- at param task Task structure
- at param if_val Value of the if clause
- at param lb Pointer to loop lower bound
- at param ub Pointer to loop upper bound
- at param st Loop stride
- at param nogroup Flag, 1 if nogroup clause specified, 0 otherwise
- at param sched Schedule specified 0/1/2 for none/grainsize/num_tasks
- at param grainsize Schedule value if specified
- at param task_dup Tasks duplication routine
-
-Execute the taskloop construct.
-*/
-void
-__kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int if_val,
- kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st,
- int nogroup, int sched, kmp_uint64 grainsize, void *task_dup )
-{
- kmp_taskdata_t * taskdata = KMP_TASK_TO_TASKDATA(task);
- KMP_DEBUG_ASSERT( task != NULL );
-
- KA_TRACE(10, ("__kmpc_taskloop(enter): T#%d, pattern task %p, lb %lld ub %lld st %lld, grain %llu(%d)\n",
- gtid, taskdata, *lb, *ub, st, grainsize, sched));
-
- // check if clause value first
- if( if_val == 0 ) { // if(0) specified, mark task as serial
- taskdata->td_flags.task_serial = 1;
- taskdata->td_flags.tiedness = TASK_TIED; // AC: serial task cannot be untied
- }
- if( nogroup == 0 ) {
- __kmpc_taskgroup( loc, gtid );
- }
-
- if( 1 /* AC: use some heuristic here to choose task scheduling method */ ) {
- __kmp_taskloop_linear( loc, gtid, task, lb, ub, st, sched, grainsize, task_dup );
- }
-
- if( nogroup == 0 ) {
- __kmpc_end_taskgroup( loc, gtid );
- }
- KA_TRACE(10, ("__kmpc_taskloop(exit): T#%d\n", gtid));
-}
-
-#endif
Removed: openmp/trunk/runtime/src/kmp_taskq.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/kmp_taskq.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/kmp_taskq.c (original)
+++ openmp/trunk/runtime/src/kmp_taskq.c (removed)
@@ -1,2032 +0,0 @@
-/*
- * kmp_taskq.c -- TASKQ support for OpenMP.
- */
-
-
-//===----------------------------------------------------------------------===//
-//
-// 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_i18n.h"
-#include "kmp_io.h"
-#include "kmp_error.h"
-
-#define MAX_MESSAGE 512
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-/*
- * Taskq routines and global variables
- */
-
-#define KMP_DEBUG_REF_CTS(x) KF_TRACE(1, x);
-
-#define THREAD_ALLOC_FOR_TASKQ
-
-static int
-in_parallel_context( kmp_team_t *team )
-{
- return ! team -> t.t_serialized;
-}
-
-static void
-__kmp_taskq_eo( int *gtid_ref, int *cid_ref, ident_t *loc_ref )
-{
- int gtid = *gtid_ref;
- int tid = __kmp_tid_from_gtid( gtid );
- kmp_uint32 my_token;
- kmpc_task_queue_t *taskq;
- kmp_taskq_t *tq = & __kmp_threads[gtid] -> th.th_team -> t.t_taskq;
-
- if ( __kmp_env_consistency_check )
-#if KMP_USE_DYNAMIC_LOCK
- __kmp_push_sync( gtid, ct_ordered_in_taskq, loc_ref, NULL, 0 );
-#else
- __kmp_push_sync( gtid, ct_ordered_in_taskq, loc_ref, NULL );
-#endif
-
- if ( ! __kmp_threads[ gtid ]-> th.th_team -> t.t_serialized ) {
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- /* GEH - need check here under stats to make sure */
- /* inside task (curr_thunk[*tid_ref] != NULL) */
-
- my_token =tq->tq_curr_thunk[ tid ]-> th_tasknum;
-
- taskq = tq->tq_curr_thunk[ tid ]-> th.th_shareds -> sv_queue;
-
- KMP_WAIT_YIELD(&taskq->tq_tasknum_serving, my_token, KMP_EQ, NULL);
- KMP_MB();
- }
-}
-
-static void
-__kmp_taskq_xo( int *gtid_ref, int *cid_ref, ident_t *loc_ref )
-{
- int gtid = *gtid_ref;
- int tid = __kmp_tid_from_gtid( gtid );
- kmp_uint32 my_token;
- kmp_taskq_t *tq = & __kmp_threads[gtid] -> th.th_team -> t.t_taskq;
-
- if ( __kmp_env_consistency_check )
- __kmp_pop_sync( gtid, ct_ordered_in_taskq, loc_ref );
-
- if ( ! __kmp_threads[ gtid ]-> th.th_team -> t.t_serialized ) {
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- /* GEH - need check here under stats to make sure */
- /* inside task (curr_thunk[tid] != NULL) */
-
- my_token = tq->tq_curr_thunk[ tid ]->th_tasknum;
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- tq->tq_curr_thunk[ tid ]-> th.th_shareds -> sv_queue -> tq_tasknum_serving = my_token + 1;
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
- }
-}
-
-static void
-__kmp_taskq_check_ordered( kmp_int32 gtid, kmpc_thunk_t *thunk )
-{
- kmp_uint32 my_token;
- kmpc_task_queue_t *taskq;
-
- /* assume we are always called from an active parallel context */
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- my_token = thunk -> th_tasknum;
-
- taskq = thunk -> th.th_shareds -> sv_queue;
-
- if(taskq->tq_tasknum_serving <= my_token) {
- KMP_WAIT_YIELD(&taskq->tq_tasknum_serving, my_token, KMP_GE, NULL);
- KMP_MB();
- taskq->tq_tasknum_serving = my_token +1;
- KMP_MB();
- }
-}
-
-#ifdef KMP_DEBUG
-
-static void
-__kmp_dump_TQF(kmp_int32 flags)
-{
- if (flags & TQF_IS_ORDERED)
- __kmp_printf("ORDERED ");
- if (flags & TQF_IS_LASTPRIVATE)
- __kmp_printf("LAST_PRIV ");
- if (flags & TQF_IS_NOWAIT)
- __kmp_printf("NOWAIT ");
- if (flags & TQF_HEURISTICS)
- __kmp_printf("HEURIST ");
- if (flags & TQF_INTERFACE_RESERVED1)
- __kmp_printf("RESERV1 ");
- if (flags & TQF_INTERFACE_RESERVED2)
- __kmp_printf("RESERV2 ");
- if (flags & TQF_INTERFACE_RESERVED3)
- __kmp_printf("RESERV3 ");
- if (flags & TQF_INTERFACE_RESERVED4)
- __kmp_printf("RESERV4 ");
- if (flags & TQF_IS_LAST_TASK)
- __kmp_printf("LAST_TASK ");
- if (flags & TQF_TASKQ_TASK)
- __kmp_printf("TASKQ_TASK ");
- if (flags & TQF_RELEASE_WORKERS)
- __kmp_printf("RELEASE ");
- if (flags & TQF_ALL_TASKS_QUEUED)
- __kmp_printf("ALL_QUEUED ");
- if (flags & TQF_PARALLEL_CONTEXT)
- __kmp_printf("PARALLEL ");
- if (flags & TQF_DEALLOCATED)
- __kmp_printf("DEALLOC ");
- if (!(flags & (TQF_INTERNAL_FLAGS|TQF_INTERFACE_FLAGS)))
- __kmp_printf("(NONE)");
-}
-
-static void
-__kmp_dump_thunk( kmp_taskq_t *tq, kmpc_thunk_t *thunk, kmp_int32 global_tid )
-{
- int i;
- int nproc = __kmp_threads[global_tid] -> th.th_team -> t.t_nproc;
-
- __kmp_printf("\tThunk at %p on (%d): ", thunk, global_tid);
-
- if (thunk != NULL) {
- for (i = 0; i < nproc; i++) {
- if( tq->tq_curr_thunk[i] == thunk ) {
- __kmp_printf("[%i] ", i);
- }
- }
- __kmp_printf("th_shareds=%p, ", thunk->th.th_shareds);
- __kmp_printf("th_task=%p, ", thunk->th_task);
- __kmp_printf("th_encl_thunk=%p, ", thunk->th_encl_thunk);
- __kmp_printf("th_status=%d, ", thunk->th_status);
- __kmp_printf("th_tasknum=%u, ", thunk->th_tasknum);
- __kmp_printf("th_flags="); __kmp_dump_TQF(thunk->th_flags);
- }
-
- __kmp_printf("\n");
-}
-
-static void
-__kmp_dump_thunk_stack(kmpc_thunk_t *thunk, kmp_int32 thread_num)
-{
- kmpc_thunk_t *th;
-
- __kmp_printf(" Thunk stack for T#%d: ", thread_num);
-
- for (th = thunk; th != NULL; th = th->th_encl_thunk )
- __kmp_printf("%p ", th);
-
- __kmp_printf("\n");
-}
-
-static void
-__kmp_dump_task_queue( kmp_taskq_t *tq, kmpc_task_queue_t *queue, kmp_int32 global_tid )
-{
- int qs, count, i;
- kmpc_thunk_t *thunk;
- kmpc_task_queue_t *taskq;
-
- __kmp_printf("Task Queue at %p on (%d):\n", queue, global_tid);
-
- if (queue != NULL) {
- int in_parallel = queue->tq_flags & TQF_PARALLEL_CONTEXT;
-
- if ( __kmp_env_consistency_check ) {
- __kmp_printf(" tq_loc : ");
- }
- if (in_parallel) {
-
- //if (queue->tq.tq_parent != 0)
- //__kmp_acquire_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
-
- //__kmp_acquire_lock(& queue->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- __kmp_printf(" tq_parent : %p\n", queue->tq.tq_parent);
- __kmp_printf(" tq_first_child : %p\n", queue->tq_first_child);
- __kmp_printf(" tq_next_child : %p\n", queue->tq_next_child);
- __kmp_printf(" tq_prev_child : %p\n", queue->tq_prev_child);
- __kmp_printf(" tq_ref_count : %d\n", queue->tq_ref_count);
-
- //__kmp_release_lock(& queue->tq_link_lck, global_tid);
-
- //if (queue->tq.tq_parent != 0)
- //__kmp_release_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
-
- //__kmp_acquire_lock(& queue->tq_free_thunks_lck, global_tid);
- //__kmp_acquire_lock(& queue->tq_queue_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
- }
-
- __kmp_printf(" tq_shareds : ");
- for (i=0; i<((queue == tq->tq_root) ? queue->tq_nproc : 1); i++)
- __kmp_printf("%p ", queue->tq_shareds[i].ai_data);
- __kmp_printf("\n");
-
- if (in_parallel) {
- __kmp_printf(" tq_tasknum_queuing : %u\n", queue->tq_tasknum_queuing);
- __kmp_printf(" tq_tasknum_serving : %u\n", queue->tq_tasknum_serving);
- }
-
- __kmp_printf(" tq_queue : %p\n", queue->tq_queue);
- __kmp_printf(" tq_thunk_space : %p\n", queue->tq_thunk_space);
- __kmp_printf(" tq_taskq_slot : %p\n", queue->tq_taskq_slot);
-
- __kmp_printf(" tq_free_thunks : ");
- for (thunk = queue->tq_free_thunks; thunk != NULL; thunk = thunk->th.th_next_free )
- __kmp_printf("%p ", thunk);
- __kmp_printf("\n");
-
- __kmp_printf(" tq_nslots : %d\n", queue->tq_nslots);
- __kmp_printf(" tq_head : %d\n", queue->tq_head);
- __kmp_printf(" tq_tail : %d\n", queue->tq_tail);
- __kmp_printf(" tq_nfull : %d\n", queue->tq_nfull);
- __kmp_printf(" tq_hiwat : %d\n", queue->tq_hiwat);
- __kmp_printf(" tq_flags : "); __kmp_dump_TQF(queue->tq_flags);
- __kmp_printf("\n");
-
- if (in_parallel) {
- __kmp_printf(" tq_th_thunks : ");
- for (i = 0; i < queue->tq_nproc; i++) {
- __kmp_printf("%d ", queue->tq_th_thunks[i].ai_data);
- }
- __kmp_printf("\n");
- }
-
- __kmp_printf("\n");
- __kmp_printf(" Queue slots:\n");
-
-
- qs = queue->tq_tail;
- for ( count = 0; count < queue->tq_nfull; ++count ) {
- __kmp_printf("(%d)", qs);
- __kmp_dump_thunk( tq, queue->tq_queue[qs].qs_thunk, global_tid );
- qs = (qs+1) % queue->tq_nslots;
- }
-
- __kmp_printf("\n");
-
- if (in_parallel) {
- if (queue->tq_taskq_slot != NULL) {
- __kmp_printf(" TaskQ slot:\n");
- __kmp_dump_thunk( tq, (kmpc_thunk_t *) queue->tq_taskq_slot, global_tid );
- __kmp_printf("\n");
- }
- //__kmp_release_lock(& queue->tq_queue_lck, global_tid);
- //__kmp_release_lock(& queue->tq_free_thunks_lck, global_tid);
- }
- }
-
- __kmp_printf(" Taskq freelist: ");
-
- //__kmp_acquire_lock( & tq->tq_freelist_lck, global_tid );
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- for( taskq = tq->tq_freelist; taskq != NULL; taskq = taskq->tq.tq_next_free )
- __kmp_printf("%p ", taskq);
-
- //__kmp_release_lock( & tq->tq_freelist_lck, global_tid );
-
- __kmp_printf("\n\n");
-}
-
-static void
-__kmp_aux_dump_task_queue_tree( kmp_taskq_t *tq, kmpc_task_queue_t *curr_queue, kmp_int32 level, kmp_int32 global_tid )
-{
- int i, count, qs;
- int nproc = __kmp_threads[global_tid] -> th.th_team -> t.t_nproc;
- kmpc_task_queue_t *queue = curr_queue;
-
- if (curr_queue == NULL)
- return;
-
- __kmp_printf(" ");
-
- for (i=0; i<level; i++)
- __kmp_printf(" ");
-
- __kmp_printf("%p", curr_queue);
-
- for (i = 0; i < nproc; i++) {
- if( tq->tq_curr_thunk[i] && tq->tq_curr_thunk[i]->th.th_shareds->sv_queue == curr_queue ) {
- __kmp_printf(" [%i]", i);
- }
- }
-
- __kmp_printf(":");
-
- //__kmp_acquire_lock(& curr_queue->tq_queue_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- qs = curr_queue->tq_tail;
-
- for ( count = 0; count < curr_queue->tq_nfull; ++count ) {
- __kmp_printf("%p ", curr_queue->tq_queue[qs].qs_thunk);
- qs = (qs+1) % curr_queue->tq_nslots;
- }
-
- //__kmp_release_lock(& curr_queue->tq_queue_lck, global_tid);
-
- __kmp_printf("\n");
-
- if (curr_queue->tq_first_child) {
- //__kmp_acquire_lock(& curr_queue->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- if (curr_queue->tq_first_child) {
- for(queue = (kmpc_task_queue_t *)curr_queue->tq_first_child;
- queue != NULL;
- queue = queue->tq_next_child) {
- __kmp_aux_dump_task_queue_tree( tq, queue, level+1, global_tid );
- }
- }
-
- //__kmp_release_lock(& curr_queue->tq_link_lck, global_tid);
- }
-}
-
-static void
-__kmp_dump_task_queue_tree( kmp_taskq_t *tq, kmpc_task_queue_t *tqroot, kmp_int32 global_tid)
-{
- __kmp_printf("TaskQ Tree at root %p on (%d):\n", tqroot, global_tid);
-
- __kmp_aux_dump_task_queue_tree( tq, tqroot, 0, global_tid );
-
- __kmp_printf("\n");
-}
-#endif
-
-/* --------------------------------------------------------------------------- */
-
-/*
- New taskq storage routines that try to minimize overhead of mallocs but
- still provide cache line alignment.
-*/
-
-
-static void *
-__kmp_taskq_allocate(size_t size, kmp_int32 global_tid)
-{
- void *addr, *orig_addr;
- size_t bytes;
-
- KB_TRACE( 5, ("__kmp_taskq_allocate: called size=%d, gtid=%d\n", (int) size, global_tid ) );
-
- bytes = sizeof(void *) + CACHE_LINE + size;
-
-#ifdef THREAD_ALLOC_FOR_TASKQ
- orig_addr = (void *) __kmp_thread_malloc( __kmp_thread_from_gtid(global_tid), bytes );
-#else
- KE_TRACE( 10, ("%%%%%% MALLOC( %d )\n", bytes ) );
- orig_addr = (void *) KMP_INTERNAL_MALLOC( bytes );
-#endif /* THREAD_ALLOC_FOR_TASKQ */
-
- if (orig_addr == 0)
- KMP_FATAL( OutOfHeapMemory );
-
- addr = orig_addr;
-
- if (((kmp_uintptr_t) addr & ( CACHE_LINE - 1 )) != 0) {
- KB_TRACE( 50, ("__kmp_taskq_allocate: adjust for cache alignment\n" ) );
- addr = (void *) (((kmp_uintptr_t) addr + CACHE_LINE) & ~( CACHE_LINE - 1 ));
- }
-
- (* (void **) addr) = orig_addr;
-
- KB_TRACE( 10, ("__kmp_taskq_allocate: allocate: %p, use: %p - %p, size: %d, gtid: %d\n",
- orig_addr, ((void **) addr) + 1, ((char *)(((void **) addr) + 1)) + size-1,
- (int) size, global_tid ));
-
- return ( ((void **) addr) + 1 );
-}
-
-static void
-__kmpc_taskq_free(void *p, kmp_int32 global_tid)
-{
- KB_TRACE( 5, ("__kmpc_taskq_free: called addr=%p, gtid=%d\n", p, global_tid ) );
-
- KB_TRACE(10, ("__kmpc_taskq_free: freeing: %p, gtid: %d\n", (*( ((void **) p)-1)), global_tid ));
-
-#ifdef THREAD_ALLOC_FOR_TASKQ
- __kmp_thread_free( __kmp_thread_from_gtid(global_tid), *( ((void **) p)-1) );
-#else
- KMP_INTERNAL_FREE( *( ((void **) p)-1) );
-#endif /* THREAD_ALLOC_FOR_TASKQ */
-}
-
-/* --------------------------------------------------------------------------- */
-
-/*
- * Keep freed kmpc_task_queue_t on an internal freelist and recycle since
- * they're of constant size.
- */
-
-static kmpc_task_queue_t *
-__kmp_alloc_taskq ( kmp_taskq_t *tq, int in_parallel, kmp_int32 nslots, kmp_int32 nthunks,
- kmp_int32 nshareds, kmp_int32 nproc, size_t sizeof_thunk,
- size_t sizeof_shareds, kmpc_thunk_t **new_taskq_thunk, kmp_int32 global_tid )
-{
- kmp_int32 i;
- size_t bytes;
- kmpc_task_queue_t *new_queue;
- kmpc_aligned_shared_vars_t *shared_var_array;
- char *shared_var_storage;
- char *pt; /* for doing byte-adjusted address computations */
-
- __kmp_acquire_lock( & tq->tq_freelist_lck, global_tid );
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- if( tq->tq_freelist ) {
- new_queue = tq -> tq_freelist;
- tq -> tq_freelist = tq -> tq_freelist -> tq.tq_next_free;
-
- KMP_DEBUG_ASSERT(new_queue->tq_flags & TQF_DEALLOCATED);
-
- new_queue->tq_flags = 0;
-
- __kmp_release_lock( & tq->tq_freelist_lck, global_tid );
- }
- else {
- __kmp_release_lock( & tq->tq_freelist_lck, global_tid );
-
- new_queue = (kmpc_task_queue_t *) __kmp_taskq_allocate (sizeof (kmpc_task_queue_t), global_tid);
- new_queue->tq_flags = 0;
- }
-
- /* space in the task queue for queue slots (allocate as one big chunk */
- /* of storage including new_taskq_task space) */
-
- sizeof_thunk += (CACHE_LINE - (sizeof_thunk % CACHE_LINE)); /* pad to cache line size */
- pt = (char *) __kmp_taskq_allocate (nthunks * sizeof_thunk, global_tid);
- new_queue->tq_thunk_space = (kmpc_thunk_t *)pt;
- *new_taskq_thunk = (kmpc_thunk_t *)(pt + (nthunks - 1) * sizeof_thunk);
-
- /* chain the allocated thunks into a freelist for this queue */
-
- new_queue->tq_free_thunks = (kmpc_thunk_t *)pt;
-
- for (i = 0; i < (nthunks - 2); i++) {
- ((kmpc_thunk_t *)(pt+i*sizeof_thunk))->th.th_next_free = (kmpc_thunk_t *)(pt + (i+1)*sizeof_thunk);
-#ifdef KMP_DEBUG
- ((kmpc_thunk_t *)(pt+i*sizeof_thunk))->th_flags = TQF_DEALLOCATED;
-#endif
- }
-
- ((kmpc_thunk_t *)(pt+(nthunks-2)*sizeof_thunk))->th.th_next_free = NULL;
-#ifdef KMP_DEBUG
- ((kmpc_thunk_t *)(pt+(nthunks-2)*sizeof_thunk))->th_flags = TQF_DEALLOCATED;
-#endif
-
- /* initialize the locks */
-
- if (in_parallel) {
- __kmp_init_lock( & new_queue->tq_link_lck );
- __kmp_init_lock( & new_queue->tq_free_thunks_lck );
- __kmp_init_lock( & new_queue->tq_queue_lck );
- }
-
- /* now allocate the slots */
-
- bytes = nslots * sizeof (kmpc_aligned_queue_slot_t);
- new_queue->tq_queue = (kmpc_aligned_queue_slot_t *) __kmp_taskq_allocate( bytes, global_tid );
-
- /* space for array of pointers to shared variable structures */
- sizeof_shareds += sizeof(kmpc_task_queue_t *);
- sizeof_shareds += (CACHE_LINE - (sizeof_shareds % CACHE_LINE)); /* pad to cache line size */
-
- bytes = nshareds * sizeof (kmpc_aligned_shared_vars_t);
- shared_var_array = (kmpc_aligned_shared_vars_t *) __kmp_taskq_allocate ( bytes, global_tid);
-
- bytes = nshareds * sizeof_shareds;
- shared_var_storage = (char *) __kmp_taskq_allocate ( bytes, global_tid);
-
- for (i=0; i<nshareds; i++) {
- shared_var_array[i].ai_data = (kmpc_shared_vars_t *) (shared_var_storage + i*sizeof_shareds);
- shared_var_array[i].ai_data->sv_queue = new_queue;
- }
- new_queue->tq_shareds = shared_var_array;
-
-
- /* array for number of outstanding thunks per thread */
-
- if (in_parallel) {
- bytes = nproc * sizeof(kmpc_aligned_int32_t);
- new_queue->tq_th_thunks = (kmpc_aligned_int32_t *) __kmp_taskq_allocate ( bytes, global_tid);
- new_queue->tq_nproc = nproc;
-
- for (i=0; i<nproc; i++)
- new_queue->tq_th_thunks[i].ai_data = 0;
- }
-
- return new_queue;
-}
-
-static void
-__kmp_free_taskq (kmp_taskq_t *tq, kmpc_task_queue_t *p, int in_parallel, kmp_int32 global_tid)
-{
- __kmpc_taskq_free(p->tq_thunk_space, global_tid);
- __kmpc_taskq_free(p->tq_queue, global_tid);
-
- /* free shared var structure storage */
- __kmpc_taskq_free((void *) p->tq_shareds[0].ai_data, global_tid);
-
- /* free array of pointers to shared vars storage */
- __kmpc_taskq_free(p->tq_shareds, global_tid);
-
-#ifdef KMP_DEBUG
- p->tq_first_child = NULL;
- p->tq_next_child = NULL;
- p->tq_prev_child = NULL;
- p->tq_ref_count = -10;
- p->tq_shareds = NULL;
- p->tq_tasknum_queuing = 0;
- p->tq_tasknum_serving = 0;
- p->tq_queue = NULL;
- p->tq_thunk_space = NULL;
- p->tq_taskq_slot = NULL;
- p->tq_free_thunks = NULL;
- p->tq_nslots = 0;
- p->tq_head = 0;
- p->tq_tail = 0;
- p->tq_nfull = 0;
- p->tq_hiwat = 0;
-
- if (in_parallel) {
- int i;
-
- for (i=0; i<p->tq_nproc; i++)
- p->tq_th_thunks[i].ai_data = 0;
- }
- if ( __kmp_env_consistency_check )
- p->tq_loc = NULL;
- KMP_DEBUG_ASSERT( p->tq_flags & TQF_DEALLOCATED );
- p->tq_flags = TQF_DEALLOCATED;
-#endif /* KMP_DEBUG */
-
- if (in_parallel) {
- __kmpc_taskq_free(p->tq_th_thunks, global_tid);
- __kmp_destroy_lock(& p->tq_link_lck);
- __kmp_destroy_lock(& p->tq_queue_lck);
- __kmp_destroy_lock(& p->tq_free_thunks_lck);
- }
-#ifdef KMP_DEBUG
- p->tq_th_thunks = NULL;
-#endif /* KMP_DEBUG */
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- __kmp_acquire_lock( & tq->tq_freelist_lck, global_tid );
- p->tq.tq_next_free = tq->tq_freelist;
-
- tq->tq_freelist = p;
- __kmp_release_lock( & tq->tq_freelist_lck, global_tid );
-}
-
-/*
- * Once a group of thunks has been allocated for use in a particular queue,
- * these are managed via a per-queue freelist.
- * We force a check that there's always a thunk free if we need one.
- */
-
-static kmpc_thunk_t *
-__kmp_alloc_thunk (kmpc_task_queue_t *queue, int in_parallel, kmp_int32 global_tid)
-{
- kmpc_thunk_t *fl;
-
- if (in_parallel) {
- __kmp_acquire_lock(& queue->tq_free_thunks_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
- }
-
- fl = queue->tq_free_thunks;
-
- KMP_DEBUG_ASSERT (fl != NULL);
-
- queue->tq_free_thunks = fl->th.th_next_free;
- fl->th_flags = 0;
-
- if (in_parallel)
- __kmp_release_lock(& queue->tq_free_thunks_lck, global_tid);
-
- return fl;
-}
-
-static void
-__kmp_free_thunk (kmpc_task_queue_t *queue, kmpc_thunk_t *p, int in_parallel, kmp_int32 global_tid)
-{
-#ifdef KMP_DEBUG
- p->th_task = 0;
- p->th_encl_thunk = 0;
- p->th_status = 0;
- p->th_tasknum = 0;
- /* Also could zero pointers to private vars */
-#endif
-
- if (in_parallel) {
- __kmp_acquire_lock(& queue->tq_free_thunks_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
- }
-
- p->th.th_next_free = queue->tq_free_thunks;
- queue->tq_free_thunks = p;
-
-#ifdef KMP_DEBUG
- p->th_flags = TQF_DEALLOCATED;
-#endif
-
- if (in_parallel)
- __kmp_release_lock(& queue->tq_free_thunks_lck, global_tid);
-}
-
-/* --------------------------------------------------------------------------- */
-
-/* returns nonzero if the queue just became full after the enqueue */
-
-static kmp_int32
-__kmp_enqueue_task ( kmp_taskq_t *tq, kmp_int32 global_tid, kmpc_task_queue_t *queue, kmpc_thunk_t *thunk, int in_parallel )
-{
- kmp_int32 ret;
-
- /* dkp: can we get around the lock in the TQF_RELEASE_WORKERS case (only the master is executing then) */
- if (in_parallel) {
- __kmp_acquire_lock(& queue->tq_queue_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
- }
-
- KMP_DEBUG_ASSERT (queue->tq_nfull < queue->tq_nslots); /* check queue not full */
-
- queue->tq_queue[(queue->tq_head)++].qs_thunk = thunk;
-
- if (queue->tq_head >= queue->tq_nslots)
- queue->tq_head = 0;
-
- (queue->tq_nfull)++;
-
- KMP_MB(); /* to assure that nfull is seen to increase before TQF_ALL_TASKS_QUEUED is set */
-
- ret = (in_parallel) ? (queue->tq_nfull == queue->tq_nslots) : FALSE;
-
- if (in_parallel) {
- /* don't need to wait until workers are released before unlocking */
- __kmp_release_lock(& queue->tq_queue_lck, global_tid);
-
- if( tq->tq_global_flags & TQF_RELEASE_WORKERS ) {
- /* If just creating the root queue, the worker threads are waiting at */
- /* a join barrier until now, when there's something in the queue for */
- /* them to do; release them now to do work. */
- /* This should only be done when this is the first task enqueued, */
- /* so reset the flag here also. */
-
- tq->tq_global_flags &= ~TQF_RELEASE_WORKERS; /* no lock needed, workers are still in spin mode */
-
- KMP_MB(); /* avoid releasing barrier twice if taskq_task switches threads */
-
- __kmpc_end_barrier_master( NULL, global_tid);
- }
- }
-
- return ret;
-}
-
-static kmpc_thunk_t *
-__kmp_dequeue_task (kmp_int32 global_tid, kmpc_task_queue_t *queue, int in_parallel)
-{
- kmpc_thunk_t *pt;
- int tid = __kmp_tid_from_gtid( global_tid );
-
- KMP_DEBUG_ASSERT (queue->tq_nfull > 0); /* check queue not empty */
-
- if (queue->tq.tq_parent != NULL && in_parallel) {
- int ct;
- __kmp_acquire_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
- ct = ++(queue->tq_ref_count);
- __kmp_release_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p inc %d\n",
- __LINE__, global_tid, queue, ct));
- }
-
- pt = queue->tq_queue[(queue->tq_tail)++].qs_thunk;
-
- if (queue->tq_tail >= queue->tq_nslots)
- queue->tq_tail = 0;
-
- if (in_parallel) {
- queue->tq_th_thunks[tid].ai_data++;
-
- KMP_MB(); /* necessary so ai_data increment is propagated to other threads immediately (digital) */
-
- KF_TRACE(200, ("__kmp_dequeue_task: T#%d(:%d) now has %d outstanding thunks from queue %p\n",
- global_tid, tid, queue->tq_th_thunks[tid].ai_data, queue));
- }
-
- (queue->tq_nfull)--;
-
-#ifdef KMP_DEBUG
- KMP_MB();
-
- /* necessary so (queue->tq_nfull > 0) above succeeds after tq_nfull is decremented */
-
- KMP_DEBUG_ASSERT(queue->tq_nfull >= 0);
-
- if (in_parallel) {
- KMP_DEBUG_ASSERT(queue->tq_th_thunks[tid].ai_data <= __KMP_TASKQ_THUNKS_PER_TH);
- }
-#endif
-
- return pt;
-}
-
-/*
- * Find the next (non-null) task to dequeue and return it.
- * This is never called unless in_parallel=TRUE
- *
- * Here are the rules for deciding which queue to take the task from:
- * 1. Walk up the task queue tree from the current queue's parent and look
- * on the way up (for loop, below).
- * 2. Do a depth-first search back down the tree from the root and
- * look (find_task_in_descendant_queue()).
- *
- * Here are the rules for deciding which task to take from a queue
- * (__kmp_find_task_in_queue ()):
- * 1. Never take the last task from a queue if TQF_IS_LASTPRIVATE; this task
- * must be staged to make sure we execute the last one with
- * TQF_IS_LAST_TASK at the end of task queue execution.
- * 2. If the queue length is below some high water mark and the taskq task
- * is enqueued, prefer running the taskq task.
- * 3. Otherwise, take a (normal) task from the queue.
- *
- * If we do all this and return pt == NULL at the bottom of this routine,
- * this means there are no more tasks to execute (except possibly for
- * TQF_IS_LASTPRIVATE).
- */
-
-static kmpc_thunk_t *
-__kmp_find_task_in_queue (kmp_int32 global_tid, kmpc_task_queue_t *queue)
-{
- kmpc_thunk_t *pt = NULL;
- int tid = __kmp_tid_from_gtid( global_tid );
-
- /* To prevent deadlock from tq_queue_lck if queue already deallocated */
- if ( !(queue->tq_flags & TQF_DEALLOCATED) ) {
-
- __kmp_acquire_lock(& queue->tq_queue_lck, global_tid);
-
- /* Check again to avoid race in __kmpc_end_taskq() */
- if ( !(queue->tq_flags & TQF_DEALLOCATED) ) {
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- if ((queue->tq_taskq_slot != NULL) && (queue->tq_nfull <= queue->tq_hiwat)) {
- /* if there's enough room in the queue and the dispatcher */
- /* (taskq task) is available, schedule more tasks */
- pt = (kmpc_thunk_t *) queue->tq_taskq_slot;
- queue->tq_taskq_slot = NULL;
- }
- else if (queue->tq_nfull == 0 ||
- queue->tq_th_thunks[tid].ai_data >= __KMP_TASKQ_THUNKS_PER_TH) {
- /* do nothing if no thunks available or this thread can't */
- /* run any because it already is executing too many */
-
- pt = NULL;
- }
- else if (queue->tq_nfull > 1) {
- /* always safe to schedule a task even if TQF_IS_LASTPRIVATE */
-
- pt = __kmp_dequeue_task (global_tid, queue, TRUE);
- }
- else if (!(queue->tq_flags & TQF_IS_LASTPRIVATE)) {
- /* one thing in queue, always safe to schedule if !TQF_IS_LASTPRIVATE */
-
- pt = __kmp_dequeue_task (global_tid, queue, TRUE);
- }
- else if (queue->tq_flags & TQF_IS_LAST_TASK) {
- /* TQF_IS_LASTPRIVATE, one thing in queue, kmpc_end_taskq_task() */
- /* has been run so this is last task, run with TQF_IS_LAST_TASK so */
- /* instrumentation does copy-out. */
-
- pt = __kmp_dequeue_task (global_tid, queue, TRUE);
- pt->th_flags |= TQF_IS_LAST_TASK; /* don't need test_then_or since already locked */
- }
- }
-
- /* GEH - What happens here if is lastprivate, but not last task? */
- __kmp_release_lock(& queue->tq_queue_lck, global_tid);
- }
-
- return pt;
-}
-
-/*
- * Walk a tree of queues starting at queue's first child
- * and return a non-NULL thunk if one can be scheduled.
- * Must only be called when in_parallel=TRUE
- */
-
-static kmpc_thunk_t *
-__kmp_find_task_in_descendant_queue (kmp_int32 global_tid, kmpc_task_queue_t *curr_queue)
-{
- kmpc_thunk_t *pt = NULL;
- kmpc_task_queue_t *queue = curr_queue;
-
- if (curr_queue->tq_first_child != NULL) {
- __kmp_acquire_lock(& curr_queue->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- queue = (kmpc_task_queue_t *) curr_queue->tq_first_child;
- if (queue == NULL) {
- __kmp_release_lock(& curr_queue->tq_link_lck, global_tid);
- return NULL;
- }
-
- while (queue != NULL) {
- int ct;
- kmpc_task_queue_t *next;
-
- ct= ++(queue->tq_ref_count);
- __kmp_release_lock(& curr_queue->tq_link_lck, global_tid);
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p inc %d\n",
- __LINE__, global_tid, queue, ct));
-
- pt = __kmp_find_task_in_queue (global_tid, queue);
-
- if (pt != NULL) {
- int ct;
-
- __kmp_acquire_lock(& curr_queue->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- ct = --(queue->tq_ref_count);
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p dec %d\n",
- __LINE__, global_tid, queue, ct));
- KMP_DEBUG_ASSERT( queue->tq_ref_count >= 0 );
-
- __kmp_release_lock(& curr_queue->tq_link_lck, global_tid);
-
- return pt;
- }
-
- /* although reference count stays active during descendant walk, shouldn't matter */
- /* since if children still exist, reference counts aren't being monitored anyway */
-
- pt = __kmp_find_task_in_descendant_queue (global_tid, queue);
-
- if (pt != NULL) {
- int ct;
-
- __kmp_acquire_lock(& curr_queue->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- ct = --(queue->tq_ref_count);
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p dec %d\n",
- __LINE__, global_tid, queue, ct));
- KMP_DEBUG_ASSERT( ct >= 0 );
-
- __kmp_release_lock(& curr_queue->tq_link_lck, global_tid);
-
- return pt;
- }
-
- __kmp_acquire_lock(& curr_queue->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- next = queue->tq_next_child;
-
- ct = --(queue->tq_ref_count);
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p dec %d\n",
- __LINE__, global_tid, queue, ct));
- KMP_DEBUG_ASSERT( ct >= 0 );
-
- queue = next;
- }
-
- __kmp_release_lock(& curr_queue->tq_link_lck, global_tid);
- }
-
- return pt;
-}
-
-/*
- * Walk up the taskq tree looking for a task to execute.
- * If we get to the root, search the tree for a descendent queue task.
- * Must only be called when in_parallel=TRUE
- */
-
-static kmpc_thunk_t *
-__kmp_find_task_in_ancestor_queue (kmp_taskq_t *tq, kmp_int32 global_tid, kmpc_task_queue_t *curr_queue)
-{
- kmpc_task_queue_t *queue;
- kmpc_thunk_t *pt;
-
- pt = NULL;
-
- if (curr_queue->tq.tq_parent != NULL) {
- queue = curr_queue->tq.tq_parent;
-
- while (queue != NULL) {
- if (queue->tq.tq_parent != NULL) {
- int ct;
- __kmp_acquire_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- ct = ++(queue->tq_ref_count);
- __kmp_release_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p inc %d\n",
- __LINE__, global_tid, queue, ct));
- }
-
- pt = __kmp_find_task_in_queue (global_tid, queue);
- if (pt != NULL) {
- if (queue->tq.tq_parent != NULL) {
- int ct;
- __kmp_acquire_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work without this call for digital/alpha, needed for IBM/RS6000 */
-
- ct = --(queue->tq_ref_count);
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p dec %d\n",
- __LINE__, global_tid, queue, ct));
- KMP_DEBUG_ASSERT( ct >= 0 );
-
- __kmp_release_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
- }
-
- return pt;
- }
-
- if (queue->tq.tq_parent != NULL) {
- int ct;
- __kmp_acquire_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- ct = --(queue->tq_ref_count);
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p dec %d\n",
- __LINE__, global_tid, queue, ct));
- KMP_DEBUG_ASSERT( ct >= 0 );
- }
- queue = queue->tq.tq_parent;
-
- if (queue != NULL)
- __kmp_release_lock(& queue->tq_link_lck, global_tid);
- }
-
- }
-
- pt = __kmp_find_task_in_descendant_queue( global_tid, tq->tq_root );
-
- return pt;
-}
-
-static int
-__kmp_taskq_tasks_finished (kmpc_task_queue_t *queue)
-{
- int i;
-
- /* KMP_MB(); *//* is this really necessary? */
-
- for (i=0; i<queue->tq_nproc; i++) {
- if (queue->tq_th_thunks[i].ai_data != 0)
- return FALSE;
- }
-
- return TRUE;
-}
-
-static int
-__kmp_taskq_has_any_children (kmpc_task_queue_t *queue)
-{
- return (queue->tq_first_child != NULL);
-}
-
-static void
-__kmp_remove_queue_from_tree( kmp_taskq_t *tq, kmp_int32 global_tid, kmpc_task_queue_t *queue, int in_parallel )
-{
-#ifdef KMP_DEBUG
- kmp_int32 i;
- kmpc_thunk_t *thunk;
-#endif
-
- KF_TRACE(50, ("Before Deletion of TaskQ at %p on (%d):\n", queue, global_tid));
- KF_DUMP(50, __kmp_dump_task_queue( tq, queue, global_tid ));
-
- /* sub-queue in a recursion, not the root task queue */
- KMP_DEBUG_ASSERT (queue->tq.tq_parent != NULL);
-
- if (in_parallel) {
- __kmp_acquire_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
- }
-
- KMP_DEBUG_ASSERT (queue->tq_first_child == NULL);
-
- /* unlink queue from its siblings if any at this level */
- if (queue->tq_prev_child != NULL)
- queue->tq_prev_child->tq_next_child = queue->tq_next_child;
- if (queue->tq_next_child != NULL)
- queue->tq_next_child->tq_prev_child = queue->tq_prev_child;
- if (queue->tq.tq_parent->tq_first_child == queue)
- queue->tq.tq_parent->tq_first_child = queue->tq_next_child;
-
- queue->tq_prev_child = NULL;
- queue->tq_next_child = NULL;
-
- if (in_parallel) {
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p waiting for ref_count of %d to reach 1\n",
- __LINE__, global_tid, queue, queue->tq_ref_count));
-
- /* wait until all other threads have stopped accessing this queue */
- while (queue->tq_ref_count > 1) {
- __kmp_release_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
-
- KMP_WAIT_YIELD((volatile kmp_uint32*)&queue->tq_ref_count, 1, KMP_LE, NULL);
-
- __kmp_acquire_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
- }
-
- __kmp_release_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
- }
-
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p freeing queue\n",
- __LINE__, global_tid, queue));
-
-#ifdef KMP_DEBUG
- KMP_DEBUG_ASSERT(queue->tq_flags & TQF_ALL_TASKS_QUEUED);
- KMP_DEBUG_ASSERT(queue->tq_nfull == 0);
-
- for (i=0; i<queue->tq_nproc; i++) {
- KMP_DEBUG_ASSERT(queue->tq_th_thunks[i].ai_data == 0);
- }
-
- i = 0;
- for (thunk=queue->tq_free_thunks; thunk != NULL; thunk=thunk->th.th_next_free)
- ++i;
-
- KMP_ASSERT (i == queue->tq_nslots + (queue->tq_nproc * __KMP_TASKQ_THUNKS_PER_TH));
-#endif
-
- /* release storage for queue entry */
- __kmp_free_taskq ( tq, queue, TRUE, global_tid );
-
- KF_TRACE(50, ("After Deletion of TaskQ at %p on (%d):\n", queue, global_tid));
- KF_DUMP(50, __kmp_dump_task_queue_tree( tq, tq->tq_root, global_tid ));
-}
-
-/*
- * Starting from indicated queue, proceed downward through tree and
- * remove all taskqs which are finished, but only go down to taskqs
- * which have the "nowait" clause present. Assume this is only called
- * when in_parallel=TRUE.
- */
-
-static void
-__kmp_find_and_remove_finished_child_taskq( kmp_taskq_t *tq, kmp_int32 global_tid, kmpc_task_queue_t *curr_queue )
-{
- kmpc_task_queue_t *queue = curr_queue;
-
- if (curr_queue->tq_first_child != NULL) {
- __kmp_acquire_lock(& curr_queue->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- queue = (kmpc_task_queue_t *) curr_queue->tq_first_child;
- if (queue != NULL) {
- __kmp_release_lock(& curr_queue->tq_link_lck, global_tid);
- return;
- }
-
- while (queue != NULL) {
- kmpc_task_queue_t *next;
- int ct = ++(queue->tq_ref_count);
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p inc %d\n",
- __LINE__, global_tid, queue, ct));
-
-
- /* although reference count stays active during descendant walk, */
- /* shouldn't matter since if children still exist, reference */
- /* counts aren't being monitored anyway */
-
- if (queue->tq_flags & TQF_IS_NOWAIT) {
- __kmp_find_and_remove_finished_child_taskq ( tq, global_tid, queue );
-
- if ((queue->tq_flags & TQF_ALL_TASKS_QUEUED) && (queue->tq_nfull == 0) &&
- __kmp_taskq_tasks_finished(queue) && ! __kmp_taskq_has_any_children(queue)) {
-
- /*
- Only remove this if we have not already marked it for deallocation.
- This should prevent multiple threads from trying to free this.
- */
-
- if ( __kmp_test_lock(& queue->tq_queue_lck, global_tid) ) {
- if ( !(queue->tq_flags & TQF_DEALLOCATED) ) {
- queue->tq_flags |= TQF_DEALLOCATED;
- __kmp_release_lock(& queue->tq_queue_lck, global_tid);
-
- __kmp_remove_queue_from_tree( tq, global_tid, queue, TRUE );
-
- /* Can't do any more here since can't be sure where sibling queue is so just exit this level */
- return;
- }
- else {
- __kmp_release_lock(& queue->tq_queue_lck, global_tid);
- }
- }
- /* otherwise, just fall through and decrement reference count */
- }
- }
-
- __kmp_acquire_lock(& curr_queue->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- next = queue->tq_next_child;
-
- ct = --(queue->tq_ref_count);
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p dec %d\n",
- __LINE__, global_tid, queue, ct));
- KMP_DEBUG_ASSERT( ct >= 0 );
-
- queue = next;
- }
-
- __kmp_release_lock(& curr_queue->tq_link_lck, global_tid);
- }
-}
-
-/*
- * Starting from indicated queue, proceed downward through tree and
- * remove all taskq's assuming all are finished and
- * assuming NO other threads are executing at this point.
- */
-
-static void
-__kmp_remove_all_child_taskq( kmp_taskq_t *tq, kmp_int32 global_tid, kmpc_task_queue_t *queue )
-{
- kmpc_task_queue_t *next_child;
-
- queue = (kmpc_task_queue_t *) queue->tq_first_child;
-
- while (queue != NULL) {
- __kmp_remove_all_child_taskq ( tq, global_tid, queue );
-
- next_child = queue->tq_next_child;
- queue->tq_flags |= TQF_DEALLOCATED;
- __kmp_remove_queue_from_tree ( tq, global_tid, queue, FALSE );
- queue = next_child;
- }
-}
-
-static void
-__kmp_execute_task_from_queue( kmp_taskq_t *tq, ident_t *loc, kmp_int32 global_tid, kmpc_thunk_t *thunk, int in_parallel )
-{
- kmpc_task_queue_t *queue = thunk->th.th_shareds->sv_queue;
- kmp_int32 tid = __kmp_tid_from_gtid( global_tid );
-
- KF_TRACE(100, ("After dequeueing this Task on (%d):\n", global_tid));
- KF_DUMP(100, __kmp_dump_thunk( tq, thunk, global_tid ));
- KF_TRACE(100, ("Task Queue: %p looks like this (%d):\n", queue, global_tid));
- KF_DUMP(100, __kmp_dump_task_queue( tq, queue, global_tid ));
-
- /*
- * For the taskq task, the curr_thunk pushes and pop pairs are set up as follows:
- *
- * happens exactly once:
- * 1) __kmpc_taskq : push (if returning thunk only)
- * 4) __kmpc_end_taskq_task : pop
- *
- * optionally happens *each* time taskq task is dequeued/enqueued:
- * 2) __kmpc_taskq_task : pop
- * 3) __kmp_execute_task_from_queue : push
- *
- * execution ordering: 1,(2,3)*,4
- */
-
- if (!(thunk->th_flags & TQF_TASKQ_TASK)) {
- kmp_int32 index = (queue == tq->tq_root) ? tid : 0;
- thunk->th.th_shareds = (kmpc_shared_vars_t *) queue->tq_shareds[index].ai_data;
-
- if ( __kmp_env_consistency_check ) {
- __kmp_push_workshare( global_tid,
- (queue->tq_flags & TQF_IS_ORDERED) ? ct_task_ordered : ct_task,
- queue->tq_loc );
- }
- }
- else {
- if ( __kmp_env_consistency_check )
- __kmp_push_workshare( global_tid, ct_taskq, queue->tq_loc );
- }
-
- if (in_parallel) {
- thunk->th_encl_thunk = tq->tq_curr_thunk[tid];
- tq->tq_curr_thunk[tid] = thunk;
-
- KF_DUMP( 200, __kmp_dump_thunk_stack( tq->tq_curr_thunk[tid], global_tid ));
- }
-
- KF_TRACE( 50, ("Begin Executing Thunk %p from queue %p on (%d)\n", thunk, queue, global_tid));
- thunk->th_task (global_tid, thunk);
- KF_TRACE( 50, ("End Executing Thunk %p from queue %p on (%d)\n", thunk, queue, global_tid));
-
- if (!(thunk->th_flags & TQF_TASKQ_TASK)) {
- if ( __kmp_env_consistency_check )
- __kmp_pop_workshare( global_tid, (queue->tq_flags & TQF_IS_ORDERED) ? ct_task_ordered : ct_task,
- queue->tq_loc );
-
- if (in_parallel) {
- tq->tq_curr_thunk[tid] = thunk->th_encl_thunk;
- thunk->th_encl_thunk = NULL;
- KF_DUMP( 200, __kmp_dump_thunk_stack( tq->tq_curr_thunk[tid], global_tid ));
- }
-
- if ((thunk->th_flags & TQF_IS_ORDERED) && in_parallel) {
- __kmp_taskq_check_ordered(global_tid, thunk);
- }
-
- __kmp_free_thunk (queue, thunk, in_parallel, global_tid);
-
- KF_TRACE(100, ("T#%d After freeing thunk: %p, TaskQ looks like this:\n", global_tid, thunk));
- KF_DUMP(100, __kmp_dump_task_queue( tq, queue, global_tid ));
-
- if (in_parallel) {
- KMP_MB(); /* needed so thunk put on free list before outstanding thunk count is decremented */
-
- KMP_DEBUG_ASSERT(queue->tq_th_thunks[tid].ai_data >= 1);
-
- KF_TRACE( 200, ("__kmp_execute_task_from_queue: T#%d has %d thunks in queue %p\n",
- global_tid, queue->tq_th_thunks[tid].ai_data-1, queue));
-
- queue->tq_th_thunks[tid].ai_data--;
-
- /* KMP_MB(); */ /* is MB really necessary ? */
- }
-
- if (queue->tq.tq_parent != NULL && in_parallel) {
- int ct;
- __kmp_acquire_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
- ct = --(queue->tq_ref_count);
- __kmp_release_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p dec %d\n",
- __LINE__, global_tid, queue, ct));
- KMP_DEBUG_ASSERT( ct >= 0 );
- }
- }
-}
-
-/* --------------------------------------------------------------------------- */
-
-/* starts a taskq; creates and returns a thunk for the taskq_task */
-/* also, returns pointer to shared vars for this thread in "shareds" arg */
-
-kmpc_thunk_t *
-__kmpc_taskq( ident_t *loc, kmp_int32 global_tid, kmpc_task_t taskq_task,
- size_t sizeof_thunk, size_t sizeof_shareds,
- kmp_int32 flags, kmpc_shared_vars_t **shareds )
-{
- int in_parallel;
- kmp_int32 nslots, nthunks, nshareds, nproc;
- kmpc_task_queue_t *new_queue, *curr_queue;
- kmpc_thunk_t *new_taskq_thunk;
- kmp_info_t *th;
- kmp_team_t *team;
- kmp_taskq_t *tq;
- kmp_int32 tid;
-
- KE_TRACE( 10, ("__kmpc_taskq called (%d)\n", global_tid));
-
- th = __kmp_threads[ global_tid ];
- team = th -> th.th_team;
- tq = & team -> t.t_taskq;
- nproc = team -> t.t_nproc;
- tid = __kmp_tid_from_gtid( global_tid );
-
- /* find out whether this is a parallel taskq or serialized one. */
- in_parallel = in_parallel_context( team );
-
- if( ! tq->tq_root ) {
- if (in_parallel) {
- /* Vector ORDERED SECTION to taskq version */
- th->th.th_dispatch->th_deo_fcn = __kmp_taskq_eo;
-
- /* Vector ORDERED SECTION to taskq version */
- th->th.th_dispatch->th_dxo_fcn = __kmp_taskq_xo;
- }
-
- if (in_parallel) {
- /* This shouldn't be a barrier region boundary, it will confuse the user. */
- /* Need the boundary to be at the end taskq instead. */
- if ( __kmp_barrier( bs_plain_barrier, global_tid, TRUE, 0, NULL, NULL )) {
- /* Creating the active root queue, and we are not the master thread. */
- /* The master thread below created the queue and tasks have been */
- /* enqueued, and the master thread released this barrier. This */
- /* worker thread can now proceed and execute tasks. See also the */
- /* TQF_RELEASE_WORKERS which is used to handle this case. */
-
- *shareds = (kmpc_shared_vars_t *) tq->tq_root->tq_shareds[tid].ai_data;
-
- KE_TRACE( 10, ("__kmpc_taskq return (%d)\n", global_tid));
-
- return NULL;
- }
- }
-
- /* master thread only executes this code */
-
- if( tq->tq_curr_thunk_capacity < nproc ) {
- if(tq->tq_curr_thunk)
- __kmp_free(tq->tq_curr_thunk);
- else {
- /* only need to do this once at outer level, i.e. when tq_curr_thunk is still NULL */
- __kmp_init_lock( & tq->tq_freelist_lck );
- }
-
- tq->tq_curr_thunk = (kmpc_thunk_t **) __kmp_allocate( nproc * sizeof(kmpc_thunk_t *) );
- tq -> tq_curr_thunk_capacity = nproc;
- }
-
- if (in_parallel)
- tq->tq_global_flags = TQF_RELEASE_WORKERS;
- }
-
- /* dkp: in future, if flags & TQF_HEURISTICS, will choose nslots based */
- /* on some heuristics (e.g., depth of queue nesting?). */
-
- nslots = (in_parallel) ? (2 * nproc) : 1;
-
- /* There must be nproc * __KMP_TASKQ_THUNKS_PER_TH extra slots for pending */
- /* jobs being executed by other threads, and one extra for taskq slot */
-
- nthunks = (in_parallel) ? (nslots + (nproc * __KMP_TASKQ_THUNKS_PER_TH) + 1) : nslots + 2;
-
- /* Only the root taskq gets a per-thread array of shareds. */
- /* The rest of the taskq's only get one copy of the shared vars. */
-
- nshareds = ( !tq->tq_root && in_parallel) ? nproc : 1;
-
- /* create overall queue data structure and its components that require allocation */
-
- new_queue = __kmp_alloc_taskq ( tq, in_parallel, nslots, nthunks, nshareds, nproc,
- sizeof_thunk, sizeof_shareds, &new_taskq_thunk, global_tid );
-
- /* rest of new_queue initializations */
-
- new_queue->tq_flags = flags & TQF_INTERFACE_FLAGS;
-
- if (in_parallel) {
- new_queue->tq_tasknum_queuing = 0;
- new_queue->tq_tasknum_serving = 0;
- new_queue->tq_flags |= TQF_PARALLEL_CONTEXT;
- }
-
- new_queue->tq_taskq_slot = NULL;
- new_queue->tq_nslots = nslots;
- new_queue->tq_hiwat = HIGH_WATER_MARK (nslots);
- new_queue->tq_nfull = 0;
- new_queue->tq_head = 0;
- new_queue->tq_tail = 0;
- new_queue->tq_loc = loc;
-
- if ((new_queue->tq_flags & TQF_IS_ORDERED) && in_parallel) {
- /* prepare to serve the first-queued task's ORDERED directive */
- new_queue->tq_tasknum_serving = 1;
-
- /* Vector ORDERED SECTION to taskq version */
- th->th.th_dispatch->th_deo_fcn = __kmp_taskq_eo;
-
- /* Vector ORDERED SECTION to taskq version */
- th->th.th_dispatch->th_dxo_fcn = __kmp_taskq_xo;
- }
-
- /* create a new thunk for the taskq_task in the new_queue */
- *shareds = (kmpc_shared_vars_t *) new_queue->tq_shareds[0].ai_data;
-
- new_taskq_thunk->th.th_shareds = *shareds;
- new_taskq_thunk->th_task = taskq_task;
- new_taskq_thunk->th_flags = new_queue->tq_flags | TQF_TASKQ_TASK;
- new_taskq_thunk->th_status = 0;
-
- KMP_DEBUG_ASSERT (new_taskq_thunk->th_flags & TQF_TASKQ_TASK);
-
- /* KMP_MB(); */ /* make sure these inits complete before threads start using this queue (necessary?) */
-
- /* insert the new task queue into the tree, but only after all fields initialized */
-
- if (in_parallel) {
- if( ! tq->tq_root ) {
- new_queue->tq.tq_parent = NULL;
- new_queue->tq_first_child = NULL;
- new_queue->tq_next_child = NULL;
- new_queue->tq_prev_child = NULL;
- new_queue->tq_ref_count = 1;
- tq->tq_root = new_queue;
- }
- else {
- curr_queue = tq->tq_curr_thunk[tid]->th.th_shareds->sv_queue;
- new_queue->tq.tq_parent = curr_queue;
- new_queue->tq_first_child = NULL;
- new_queue->tq_prev_child = NULL;
- new_queue->tq_ref_count = 1; /* for this the thread that built the queue */
-
- KMP_DEBUG_REF_CTS(("line %d gtid %d: Q %p alloc %d\n",
- __LINE__, global_tid, new_queue, new_queue->tq_ref_count));
-
- __kmp_acquire_lock(& curr_queue->tq_link_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- new_queue->tq_next_child = (struct kmpc_task_queue_t *) curr_queue->tq_first_child;
-
- if (curr_queue->tq_first_child != NULL)
- curr_queue->tq_first_child->tq_prev_child = new_queue;
-
- curr_queue->tq_first_child = new_queue;
-
- __kmp_release_lock(& curr_queue->tq_link_lck, global_tid);
- }
-
- /* set up thunk stack only after code that determines curr_queue above */
- new_taskq_thunk->th_encl_thunk = tq->tq_curr_thunk[tid];
- tq->tq_curr_thunk[tid] = new_taskq_thunk;
-
- KF_DUMP( 200, __kmp_dump_thunk_stack( tq->tq_curr_thunk[tid], global_tid ));
- }
- else {
- new_taskq_thunk->th_encl_thunk = 0;
- new_queue->tq.tq_parent = NULL;
- new_queue->tq_first_child = NULL;
- new_queue->tq_next_child = NULL;
- new_queue->tq_prev_child = NULL;
- new_queue->tq_ref_count = 1;
- }
-
-#ifdef KMP_DEBUG
- KF_TRACE(150, ("Creating TaskQ Task on (%d):\n", global_tid));
- KF_DUMP(150, __kmp_dump_thunk( tq, new_taskq_thunk, global_tid ));
-
- if (in_parallel) {
- KF_TRACE(25, ("After TaskQ at %p Creation on (%d):\n", new_queue, global_tid));
- } else {
- KF_TRACE(25, ("After Serial TaskQ at %p Creation on (%d):\n", new_queue, global_tid));
- }
-
- KF_DUMP(25, __kmp_dump_task_queue( tq, new_queue, global_tid ));
-
- if (in_parallel) {
- KF_DUMP(50, __kmp_dump_task_queue_tree( tq, tq->tq_root, global_tid ));
- }
-#endif /* KMP_DEBUG */
-
- if ( __kmp_env_consistency_check )
- __kmp_push_workshare( global_tid, ct_taskq, new_queue->tq_loc );
-
- KE_TRACE( 10, ("__kmpc_taskq return (%d)\n", global_tid));
-
- return new_taskq_thunk;
-}
-
-
-/* ends a taskq; last thread out destroys the queue */
-
-void
-__kmpc_end_taskq(ident_t *loc, kmp_int32 global_tid, kmpc_thunk_t *taskq_thunk)
-{
-#ifdef KMP_DEBUG
- kmp_int32 i;
-#endif
- kmp_taskq_t *tq;
- int in_parallel;
- kmp_info_t *th;
- kmp_int32 is_outermost;
- kmpc_task_queue_t *queue;
- kmpc_thunk_t *thunk;
- int nproc;
-
- KE_TRACE( 10, ("__kmpc_end_taskq called (%d)\n", global_tid));
-
- tq = & __kmp_threads[global_tid] -> th.th_team -> t.t_taskq;
- nproc = __kmp_threads[global_tid] -> th.th_team -> t.t_nproc;
-
- /* For the outermost taskq only, all but one thread will have taskq_thunk == NULL */
- queue = (taskq_thunk == NULL) ? tq->tq_root : taskq_thunk->th.th_shareds->sv_queue;
-
- KE_TRACE( 50, ("__kmpc_end_taskq queue=%p (%d) \n", queue, global_tid));
- is_outermost = (queue == tq->tq_root);
- in_parallel = (queue->tq_flags & TQF_PARALLEL_CONTEXT);
-
- if (in_parallel) {
- kmp_uint32 spins;
-
- /* this is just a safeguard to release the waiting threads if */
- /* the outermost taskq never queues a task */
-
- if (is_outermost && (KMP_MASTER_GTID( global_tid ))) {
- if( tq->tq_global_flags & TQF_RELEASE_WORKERS ) {
- /* no lock needed, workers are still in spin mode */
- tq->tq_global_flags &= ~TQF_RELEASE_WORKERS;
-
- __kmp_end_split_barrier( bs_plain_barrier, global_tid );
- }
- }
-
- /* keep dequeueing work until all tasks are queued and dequeued */
-
- do {
- /* wait until something is available to dequeue */
- KMP_INIT_YIELD(spins);
-
- while ( (queue->tq_nfull == 0)
- && (queue->tq_taskq_slot == NULL)
- && (! __kmp_taskq_has_any_children(queue) )
- && (! (queue->tq_flags & TQF_ALL_TASKS_QUEUED) )
- ) {
- KMP_YIELD_WHEN( TRUE, spins );
- }
-
- /* check to see if we can execute tasks in the queue */
- while ( ( (queue->tq_nfull != 0) || (queue->tq_taskq_slot != NULL) )
- && (thunk = __kmp_find_task_in_queue(global_tid, queue)) != NULL
- ) {
- KF_TRACE(50, ("Found thunk: %p in primary queue %p (%d)\n", thunk, queue, global_tid));
- __kmp_execute_task_from_queue( tq, loc, global_tid, thunk, in_parallel );
- }
-
- /* see if work found can be found in a descendant queue */
- if ( (__kmp_taskq_has_any_children(queue))
- && (thunk = __kmp_find_task_in_descendant_queue(global_tid, queue)) != NULL
- ) {
-
- KF_TRACE(50, ("Stole thunk: %p in descendant queue: %p while waiting in queue: %p (%d)\n",
- thunk, thunk->th.th_shareds->sv_queue, queue, global_tid ));
-
- __kmp_execute_task_from_queue( tq, loc, global_tid, thunk, in_parallel );
- }
-
- } while ( (! (queue->tq_flags & TQF_ALL_TASKS_QUEUED))
- || (queue->tq_nfull != 0)
- );
-
- KF_TRACE(50, ("All tasks queued and dequeued in queue: %p (%d)\n", queue, global_tid));
-
- /* wait while all tasks are not finished and more work found
- in descendant queues */
-
- while ( (!__kmp_taskq_tasks_finished(queue))
- && (thunk = __kmp_find_task_in_descendant_queue(global_tid, queue)) != NULL
- ) {
-
- KF_TRACE(50, ("Stole thunk: %p in descendant queue: %p while waiting in queue: %p (%d)\n",
- thunk, thunk->th.th_shareds->sv_queue, queue, global_tid));
-
- __kmp_execute_task_from_queue( tq, loc, global_tid, thunk, in_parallel );
- }
-
- KF_TRACE(50, ("No work found in descendent queues or all work finished in queue: %p (%d)\n", queue, global_tid));
-
- if (!is_outermost) {
- /* need to return if NOWAIT present and not outermost taskq */
-
- if (queue->tq_flags & TQF_IS_NOWAIT) {
- __kmp_acquire_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
- queue->tq_ref_count--;
- KMP_DEBUG_ASSERT( queue->tq_ref_count >= 0 );
- __kmp_release_lock(& queue->tq.tq_parent->tq_link_lck, global_tid);
-
- KE_TRACE( 10, ("__kmpc_end_taskq return for nowait case (%d)\n", global_tid));
-
- return;
- }
-
- __kmp_find_and_remove_finished_child_taskq( tq, global_tid, queue );
-
- /* WAIT until all tasks are finished and no child queues exist before proceeding */
- KMP_INIT_YIELD(spins);
-
- while (!__kmp_taskq_tasks_finished(queue) || __kmp_taskq_has_any_children(queue)) {
- thunk = __kmp_find_task_in_ancestor_queue( tq, global_tid, queue );
-
- if (thunk != NULL) {
- KF_TRACE(50, ("Stole thunk: %p in ancestor queue: %p while waiting in queue: %p (%d)\n",
- thunk, thunk->th.th_shareds->sv_queue, queue, global_tid));
- __kmp_execute_task_from_queue( tq, loc, global_tid, thunk, in_parallel );
- }
-
- KMP_YIELD_WHEN( thunk == NULL, spins );
-
- __kmp_find_and_remove_finished_child_taskq( tq, global_tid, queue );
- }
-
- __kmp_acquire_lock(& queue->tq_queue_lck, global_tid);
- if ( !(queue->tq_flags & TQF_DEALLOCATED) ) {
- queue->tq_flags |= TQF_DEALLOCATED;
- }
- __kmp_release_lock(& queue->tq_queue_lck, global_tid);
-
- /* only the allocating thread can deallocate the queue */
- if (taskq_thunk != NULL) {
- __kmp_remove_queue_from_tree( tq, global_tid, queue, TRUE );
- }
-
- KE_TRACE( 10, ("__kmpc_end_taskq return for non_outermost queue, wait case (%d)\n", global_tid));
-
- return;
- }
-
- /* Outermost Queue: steal work from descendants until all tasks are finished */
-
- KMP_INIT_YIELD(spins);
-
- while (!__kmp_taskq_tasks_finished(queue)) {
- thunk = __kmp_find_task_in_descendant_queue(global_tid, queue);
-
- if (thunk != NULL) {
- KF_TRACE(50, ("Stole thunk: %p in descendant queue: %p while waiting in queue: %p (%d)\n",
- thunk, thunk->th.th_shareds->sv_queue, queue, global_tid));
-
- __kmp_execute_task_from_queue( tq, loc, global_tid, thunk, in_parallel );
- }
-
- KMP_YIELD_WHEN( thunk == NULL, spins );
- }
-
- /* Need this barrier to prevent destruction of queue before threads have all executed above code */
- /* This may need to be done earlier when NOWAIT is implemented for the outermost level */
-
- if ( !__kmp_barrier( bs_plain_barrier, global_tid, TRUE, 0, NULL, NULL )) {
- /* the queue->tq_flags & TQF_IS_NOWAIT case is not yet handled here; */
- /* for right now, everybody waits, and the master thread destroys the */
- /* remaining queues. */
-
- __kmp_remove_all_child_taskq( tq, global_tid, queue );
-
- /* Now destroy the root queue */
- KF_TRACE(100, ("T#%d Before Deletion of top-level TaskQ at %p:\n", global_tid, queue ));
- KF_DUMP(100, __kmp_dump_task_queue( tq, queue, global_tid ));
-
-#ifdef KMP_DEBUG
- /* the root queue entry */
- KMP_DEBUG_ASSERT ((queue->tq.tq_parent == NULL) && (queue->tq_next_child == NULL));
-
- /* children must all be gone by now because of barrier above */
- KMP_DEBUG_ASSERT (queue->tq_first_child == NULL);
-
- for (i=0; i<nproc; i++) {
- KMP_DEBUG_ASSERT(queue->tq_th_thunks[i].ai_data == 0);
- }
-
- for (i=0, thunk=queue->tq_free_thunks; thunk != NULL; i++, thunk=thunk->th.th_next_free);
-
- KMP_DEBUG_ASSERT (i == queue->tq_nslots + (nproc * __KMP_TASKQ_THUNKS_PER_TH));
-
- for (i = 0; i < nproc; i++) {
- KMP_DEBUG_ASSERT( ! tq->tq_curr_thunk[i] );
- }
-#endif
- /* unlink the root queue entry */
- tq -> tq_root = NULL;
-
- /* release storage for root queue entry */
- KF_TRACE(50, ("After Deletion of top-level TaskQ at %p on (%d):\n", queue, global_tid));
-
- queue->tq_flags |= TQF_DEALLOCATED;
- __kmp_free_taskq ( tq, queue, in_parallel, global_tid );
-
- KF_DUMP(50, __kmp_dump_task_queue_tree( tq, tq->tq_root, global_tid ));
-
- /* release the workers now that the data structures are up to date */
- __kmp_end_split_barrier( bs_plain_barrier, global_tid );
- }
-
- th = __kmp_threads[ global_tid ];
-
- /* Reset ORDERED SECTION to parallel version */
- th->th.th_dispatch->th_deo_fcn = 0;
-
- /* Reset ORDERED SECTION to parallel version */
- th->th.th_dispatch->th_dxo_fcn = 0;
- }
- else {
- /* in serial execution context, dequeue the last task */
- /* and execute it, if there were any tasks encountered */
-
- if (queue->tq_nfull > 0) {
- KMP_DEBUG_ASSERT(queue->tq_nfull == 1);
-
- thunk = __kmp_dequeue_task(global_tid, queue, in_parallel);
-
- if (queue->tq_flags & TQF_IS_LAST_TASK) {
- /* TQF_IS_LASTPRIVATE, one thing in queue, __kmpc_end_taskq_task() */
- /* has been run so this is last task, run with TQF_IS_LAST_TASK so */
- /* instrumentation does copy-out. */
-
- /* no need for test_then_or call since already locked */
- thunk->th_flags |= TQF_IS_LAST_TASK;
- }
-
- KF_TRACE(50, ("T#%d found thunk: %p in serial queue: %p\n", global_tid, thunk, queue));
-
- __kmp_execute_task_from_queue( tq, loc, global_tid, thunk, in_parallel );
- }
-
- /* destroy the unattached serial queue now that there is no more work to do */
- KF_TRACE(100, ("Before Deletion of Serialized TaskQ at %p on (%d):\n", queue, global_tid));
- KF_DUMP(100, __kmp_dump_task_queue( tq, queue, global_tid ));
-
-#ifdef KMP_DEBUG
- i = 0;
- for (thunk=queue->tq_free_thunks; thunk != NULL; thunk=thunk->th.th_next_free)
- ++i;
- KMP_DEBUG_ASSERT (i == queue->tq_nslots + 1);
-#endif
- /* release storage for unattached serial queue */
- KF_TRACE(50, ("Serialized TaskQ at %p deleted on (%d).\n", queue, global_tid));
-
- queue->tq_flags |= TQF_DEALLOCATED;
- __kmp_free_taskq ( tq, queue, in_parallel, global_tid );
- }
-
- KE_TRACE( 10, ("__kmpc_end_taskq return (%d)\n", global_tid));
-}
-
-/* Enqueues a task for thunk previously created by __kmpc_task_buffer. */
-/* Returns nonzero if just filled up queue */
-
-kmp_int32
-__kmpc_task(ident_t *loc, kmp_int32 global_tid, kmpc_thunk_t *thunk)
-{
- kmp_int32 ret;
- kmpc_task_queue_t *queue;
- int in_parallel;
- kmp_taskq_t *tq;
-
- KE_TRACE( 10, ("__kmpc_task called (%d)\n", global_tid));
-
- KMP_DEBUG_ASSERT (!(thunk->th_flags & TQF_TASKQ_TASK)); /* thunk->th_task is a regular task */
-
- tq = &__kmp_threads[global_tid] -> th.th_team -> t.t_taskq;
- queue = thunk->th.th_shareds->sv_queue;
- in_parallel = (queue->tq_flags & TQF_PARALLEL_CONTEXT);
-
- if (in_parallel && (thunk->th_flags & TQF_IS_ORDERED))
- thunk->th_tasknum = ++queue->tq_tasknum_queuing;
-
- /* For serial execution dequeue the preceding task and execute it, if one exists */
- /* This cannot be the last task. That one is handled in __kmpc_end_taskq */
-
- if (!in_parallel && queue->tq_nfull > 0) {
- kmpc_thunk_t *prev_thunk;
-
- KMP_DEBUG_ASSERT(queue->tq_nfull == 1);
-
- prev_thunk = __kmp_dequeue_task(global_tid, queue, in_parallel);
-
- KF_TRACE(50, ("T#%d found thunk: %p in serial queue: %p\n", global_tid, prev_thunk, queue));
-
- __kmp_execute_task_from_queue( tq, loc, global_tid, prev_thunk, in_parallel );
- }
-
- /* The instrumentation sequence is: __kmpc_task_buffer(), initialize private */
- /* variables, __kmpc_task(). The __kmpc_task_buffer routine checks that the */
- /* task queue is not full and allocates a thunk (which is then passed to */
- /* __kmpc_task()). So, the enqueue below should never fail due to a full queue. */
-
- KF_TRACE(100, ("After enqueueing this Task on (%d):\n", global_tid));
- KF_DUMP(100, __kmp_dump_thunk( tq, thunk, global_tid ));
-
- ret = __kmp_enqueue_task ( tq, global_tid, queue, thunk, in_parallel );
-
- KF_TRACE(100, ("Task Queue looks like this on (%d):\n", global_tid));
- KF_DUMP(100, __kmp_dump_task_queue( tq, queue, global_tid ));
-
- KE_TRACE( 10, ("__kmpc_task return (%d)\n", global_tid));
-
- return ret;
-}
-
-/* enqueues a taskq_task for thunk previously created by __kmpc_taskq */
-/* this should never be called unless in a parallel context */
-
-void
-__kmpc_taskq_task(ident_t *loc, kmp_int32 global_tid, kmpc_thunk_t *thunk, kmp_int32 status)
-{
- kmpc_task_queue_t *queue;
- kmp_taskq_t *tq = &__kmp_threads[global_tid] -> th.th_team -> t.t_taskq;
- int tid = __kmp_tid_from_gtid( global_tid );
-
- KE_TRACE( 10, ("__kmpc_taskq_task called (%d)\n", global_tid));
- KF_TRACE(100, ("TaskQ Task argument thunk on (%d):\n", global_tid));
- KF_DUMP(100, __kmp_dump_thunk( tq, thunk, global_tid ));
-
- queue = thunk->th.th_shareds->sv_queue;
-
- if ( __kmp_env_consistency_check )
- __kmp_pop_workshare( global_tid, ct_taskq, loc );
-
- /* thunk->th_task is the taskq_task */
- KMP_DEBUG_ASSERT (thunk->th_flags & TQF_TASKQ_TASK);
-
- /* not supposed to call __kmpc_taskq_task if it's already enqueued */
- KMP_DEBUG_ASSERT (queue->tq_taskq_slot == NULL);
-
- /* dequeue taskq thunk from curr_thunk stack */
- tq->tq_curr_thunk[tid] = thunk->th_encl_thunk;
- thunk->th_encl_thunk = NULL;
-
- KF_DUMP( 200, __kmp_dump_thunk_stack( tq->tq_curr_thunk[tid], global_tid ));
-
- thunk->th_status = status;
-
- KMP_MB(); /* flush thunk->th_status before taskq_task enqueued to avoid race condition */
-
- /* enqueue taskq_task in thunk into special slot in queue */
- /* GEH - probably don't need to lock taskq slot since only one */
- /* thread enqueues & already a lock set at dequeue point */
-
- queue->tq_taskq_slot = thunk;
-
- KE_TRACE( 10, ("__kmpc_taskq_task return (%d)\n", global_tid));
-}
-
-/* ends a taskq_task; done generating tasks */
-
-void
-__kmpc_end_taskq_task(ident_t *loc, kmp_int32 global_tid, kmpc_thunk_t *thunk)
-{
- kmp_taskq_t *tq;
- kmpc_task_queue_t *queue;
- int in_parallel;
- int tid;
-
- KE_TRACE( 10, ("__kmpc_end_taskq_task called (%d)\n", global_tid));
-
- tq = &__kmp_threads[global_tid] -> th.th_team -> t.t_taskq;
- queue = thunk->th.th_shareds->sv_queue;
- in_parallel = (queue->tq_flags & TQF_PARALLEL_CONTEXT);
- tid = __kmp_tid_from_gtid( global_tid );
-
- if ( __kmp_env_consistency_check )
- __kmp_pop_workshare( global_tid, ct_taskq, loc );
-
- if (in_parallel) {
-#if KMP_ARCH_X86 || \
- KMP_ARCH_X86_64
-
- KMP_TEST_THEN_OR32( &queue->tq_flags, (kmp_int32) TQF_ALL_TASKS_QUEUED );
-#else
- {
- __kmp_acquire_lock(& queue->tq_queue_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work fine without this call for digital/alpha, needed for IBM/RS6000 */
-
- queue->tq_flags |= TQF_ALL_TASKS_QUEUED;
-
- __kmp_release_lock(& queue->tq_queue_lck, global_tid);
- }
-#endif
- }
-
- if (thunk->th_flags & TQF_IS_LASTPRIVATE) {
- /* Normally, __kmp_find_task_in_queue() refuses to schedule the last task in the */
- /* queue if TQF_IS_LASTPRIVATE so we can positively identify that last task */
- /* and run it with its TQF_IS_LAST_TASK bit turned on in th_flags. When */
- /* __kmpc_end_taskq_task() is called we are done generating all the tasks, so */
- /* we know the last one in the queue is the lastprivate task. Mark the queue */
- /* as having gotten to this state via tq_flags & TQF_IS_LAST_TASK; when that */
- /* task actually executes mark it via th_flags & TQF_IS_LAST_TASK (this th_flags */
- /* bit signals the instrumented code to do copy-outs after execution). */
-
- if (! in_parallel) {
- /* No synchronization needed for serial context */
- queue->tq_flags |= TQF_IS_LAST_TASK;
- }
- else {
-#if KMP_ARCH_X86 || \
- KMP_ARCH_X86_64
-
- KMP_TEST_THEN_OR32( &queue->tq_flags, (kmp_int32) TQF_IS_LAST_TASK );
-#else
- {
- __kmp_acquire_lock(& queue->tq_queue_lck, global_tid);
-
- KMP_MB(); /* make sure data structures are in consistent state before querying them */
- /* Seems to work without this call for digital/alpha, needed for IBM/RS6000 */
-
- queue->tq_flags |= TQF_IS_LAST_TASK;
-
- __kmp_release_lock(& queue->tq_queue_lck, global_tid);
- }
-#endif
- /* to prevent race condition where last task is dequeued but */
- /* flag isn't visible yet (not sure about this) */
- KMP_MB();
- }
- }
-
- /* dequeue taskq thunk from curr_thunk stack */
- if (in_parallel) {
- tq->tq_curr_thunk[tid] = thunk->th_encl_thunk;
- thunk->th_encl_thunk = NULL;
-
- KF_DUMP( 200, __kmp_dump_thunk_stack( tq->tq_curr_thunk[tid], global_tid ));
- }
-
- KE_TRACE( 10, ("__kmpc_end_taskq_task return (%d)\n", global_tid));
-}
-
-/* returns thunk for a regular task based on taskq_thunk */
-/* (__kmpc_taskq_task does the analogous thing for a TQF_TASKQ_TASK) */
-
-kmpc_thunk_t *
-__kmpc_task_buffer(ident_t *loc, kmp_int32 global_tid, kmpc_thunk_t *taskq_thunk, kmpc_task_t task)
-{
- kmp_taskq_t *tq;
- kmpc_task_queue_t *queue;
- kmpc_thunk_t *new_thunk;
- int in_parallel;
-
- KE_TRACE( 10, ("__kmpc_task_buffer called (%d)\n", global_tid));
-
- KMP_DEBUG_ASSERT (taskq_thunk->th_flags & TQF_TASKQ_TASK); /* taskq_thunk->th_task is the taskq_task */
-
- tq = &__kmp_threads[global_tid] -> th.th_team -> t.t_taskq;
- queue = taskq_thunk->th.th_shareds->sv_queue;
- in_parallel = (queue->tq_flags & TQF_PARALLEL_CONTEXT);
-
- /* The instrumentation sequence is: __kmpc_task_buffer(), initialize private */
- /* variables, __kmpc_task(). The __kmpc_task_buffer routine checks that the */
- /* task queue is not full and allocates a thunk (which is then passed to */
- /* __kmpc_task()). So, we can pre-allocate a thunk here assuming it will be */
- /* the next to be enqueued in __kmpc_task(). */
-
- new_thunk = __kmp_alloc_thunk (queue, in_parallel, global_tid);
- new_thunk->th.th_shareds = (kmpc_shared_vars_t *) queue->tq_shareds[0].ai_data;
- new_thunk->th_encl_thunk = NULL;
- new_thunk->th_task = task;
-
- /* GEH - shouldn't need to lock the read of tq_flags here */
- new_thunk->th_flags = queue->tq_flags & TQF_INTERFACE_FLAGS;
-
- new_thunk->th_status = 0;
-
- KMP_DEBUG_ASSERT (!(new_thunk->th_flags & TQF_TASKQ_TASK));
-
- KF_TRACE(100, ("Creating Regular Task on (%d):\n", global_tid));
- KF_DUMP(100, __kmp_dump_thunk( tq, new_thunk, global_tid ));
-
- KE_TRACE( 10, ("__kmpc_task_buffer return (%d)\n", global_tid));
-
- return new_thunk;
-}
-
-/* --------------------------------------------------------------------------- */
Removed: openmp/trunk/runtime/src/kmp_threadprivate.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/kmp_threadprivate.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/kmp_threadprivate.c (original)
+++ openmp/trunk/runtime/src/kmp_threadprivate.c (removed)
@@ -1,733 +0,0 @@
-/*
- * kmp_threadprivate.c -- OpenMP threadprivate support library
- */
-
-
-//===----------------------------------------------------------------------===//
-//
-// 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_itt.h"
-#include "kmp_i18n.h"
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-#define USE_CHECKS_COMMON
-
-#define KMP_INLINE_SUBR 1
-
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-void
-kmp_threadprivate_insert_private_data( int gtid, void *pc_addr, void *data_addr, size_t pc_size );
-struct private_common *
-kmp_threadprivate_insert( int gtid, void *pc_addr, void *data_addr, size_t pc_size );
-
-struct shared_table __kmp_threadprivate_d_table;
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-static
-#ifdef KMP_INLINE_SUBR
-__forceinline
-#endif
-struct private_common *
-__kmp_threadprivate_find_task_common( struct common_table *tbl, int gtid, void *pc_addr )
-
-{
- struct private_common *tn;
-
-#ifdef KMP_TASK_COMMON_DEBUG
- KC_TRACE( 10, ( "__kmp_threadprivate_find_task_common: thread#%d, called with address %p\n",
- gtid, pc_addr ) );
- dump_list();
-#endif
-
- for (tn = tbl->data[ KMP_HASH(pc_addr) ]; tn; tn = tn->next) {
- if (tn->gbl_addr == pc_addr) {
-#ifdef KMP_TASK_COMMON_DEBUG
- KC_TRACE( 10, ( "__kmp_threadprivate_find_task_common: thread#%d, found node %p on list\n",
- gtid, pc_addr ) );
-#endif
- return tn;
- }
- }
- return 0;
-}
-
-static
-#ifdef KMP_INLINE_SUBR
-__forceinline
-#endif
-struct shared_common *
-__kmp_find_shared_task_common( struct shared_table *tbl, int gtid, void *pc_addr )
-{
- struct shared_common *tn;
-
- for (tn = tbl->data[ KMP_HASH(pc_addr) ]; tn; tn = tn->next) {
- if (tn->gbl_addr == pc_addr) {
-#ifdef KMP_TASK_COMMON_DEBUG
- KC_TRACE( 10, ( "__kmp_find_shared_task_common: thread#%d, found node %p on list\n",
- gtid, pc_addr ) );
-#endif
- return tn;
- }
- }
- return 0;
-}
-
-
-/*
- * Create a template for the data initialized storage.
- * Either the template is NULL indicating zero fill,
- * or the template is a copy of the original data.
- */
-
-static struct private_data *
-__kmp_init_common_data( void *pc_addr, size_t pc_size )
-{
- struct private_data *d;
- size_t i;
- char *p;
-
- d = (struct private_data *) __kmp_allocate( sizeof( struct private_data ) );
-/*
- d->data = 0; // AC: commented out because __kmp_allocate zeroes the memory
- d->next = 0;
-*/
- d->size = pc_size;
- d->more = 1;
-
- p = (char*)pc_addr;
-
- for (i = pc_size; i > 0; --i) {
- if (*p++ != '\0') {
- d->data = __kmp_allocate( pc_size );
- KMP_MEMCPY( d->data, pc_addr, pc_size );
- break;
- }
- }
-
- return d;
-}
-
-/*
- * Initialize the data area from the template.
- */
-
-static void
-__kmp_copy_common_data( void *pc_addr, struct private_data *d )
-{
- char *addr = (char *) pc_addr;
- int i, offset;
-
- for (offset = 0; d != 0; d = d->next) {
- for (i = d->more; i > 0; --i) {
- if (d->data == 0)
- memset( & addr[ offset ], '\0', d->size );
- else
- KMP_MEMCPY( & addr[ offset ], d->data, d->size );
- offset += d->size;
- }
- }
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-/* we are called from __kmp_serial_initialize() with __kmp_initz_lock held. */
-void
-__kmp_common_initialize( void )
-{
- if( ! TCR_4(__kmp_init_common) ) {
- int q;
-#ifdef KMP_DEBUG
- int gtid;
-#endif
-
- __kmp_threadpriv_cache_list = NULL;
-
-#ifdef KMP_DEBUG
- /* verify the uber masters were initialized */
- for(gtid = 0 ; gtid < __kmp_threads_capacity; gtid++ )
- if( __kmp_root[gtid] ) {
- KMP_DEBUG_ASSERT( __kmp_root[gtid]->r.r_uber_thread );
- for ( q = 0; q< KMP_HASH_TABLE_SIZE; ++q)
- KMP_DEBUG_ASSERT( !__kmp_root[gtid]->r.r_uber_thread->th.th_pri_common->data[q] );
-/* __kmp_root[ gitd ]-> r.r_uber_thread -> th.th_pri_common -> data[ q ] = 0;*/
- }
-#endif /* KMP_DEBUG */
-
- for (q = 0; q < KMP_HASH_TABLE_SIZE; ++q)
- __kmp_threadprivate_d_table.data[ q ] = 0;
-
- TCW_4(__kmp_init_common, TRUE);
- }
-}
-
-/* Call all destructors for threadprivate data belonging to all threads.
- Currently unused! */
-void
-__kmp_common_destroy( void )
-{
- if( TCR_4(__kmp_init_common) ) {
- int q;
-
- TCW_4(__kmp_init_common, FALSE);
-
- for (q = 0; q < KMP_HASH_TABLE_SIZE; ++q) {
- int gtid;
- struct private_common *tn;
- struct shared_common *d_tn;
-
- /* C++ destructors need to be called once per thread before exiting */
- /* don't call destructors for master thread though unless we used copy constructor */
-
- for (d_tn = __kmp_threadprivate_d_table.data[ q ]; d_tn; d_tn = d_tn->next) {
- if (d_tn->is_vec) {
- if (d_tn->dt.dtorv != 0) {
- for (gtid = 0; gtid < __kmp_all_nth; ++gtid) {
- if( __kmp_threads[gtid] ) {
- if( (__kmp_foreign_tp) ? (! KMP_INITIAL_GTID (gtid)) :
- (! KMP_UBER_GTID (gtid)) ) {
- tn = __kmp_threadprivate_find_task_common( __kmp_threads[ gtid ]->th.th_pri_common,
- gtid, d_tn->gbl_addr );
- if (tn) {
- (*d_tn->dt.dtorv) (tn->par_addr, d_tn->vec_len);
- }
- }
- }
- }
- if (d_tn->obj_init != 0) {
- (*d_tn->dt.dtorv) (d_tn->obj_init, d_tn->vec_len);
- }
- }
- } else {
- if (d_tn->dt.dtor != 0) {
- for (gtid = 0; gtid < __kmp_all_nth; ++gtid) {
- if( __kmp_threads[gtid] ) {
- if( (__kmp_foreign_tp) ? (! KMP_INITIAL_GTID (gtid)) :
- (! KMP_UBER_GTID (gtid)) ) {
- tn = __kmp_threadprivate_find_task_common( __kmp_threads[ gtid ]->th.th_pri_common,
- gtid, d_tn->gbl_addr );
- if (tn) {
- (*d_tn->dt.dtor) (tn->par_addr);
- }
- }
- }
- }
- if (d_tn->obj_init != 0) {
- (*d_tn->dt.dtor) (d_tn->obj_init);
- }
- }
- }
- }
- __kmp_threadprivate_d_table.data[ q ] = 0;
- }
- }
-}
-
-/* Call all destructors for threadprivate data belonging to this thread */
-void
-__kmp_common_destroy_gtid( int gtid )
-{
- struct private_common *tn;
- struct shared_common *d_tn;
-
- KC_TRACE( 10, ("__kmp_common_destroy_gtid: T#%d called\n", gtid ) );
- if( (__kmp_foreign_tp) ? (! KMP_INITIAL_GTID (gtid)) :
- (! KMP_UBER_GTID (gtid)) ) {
-
- if( TCR_4(__kmp_init_common) ) {
-
- /* Cannot do this here since not all threads have destroyed their data */
- /* TCW_4(__kmp_init_common, FALSE); */
-
- for (tn = __kmp_threads[ gtid ]->th.th_pri_head; tn; tn = tn->link) {
-
- d_tn = __kmp_find_shared_task_common( &__kmp_threadprivate_d_table,
- gtid, tn->gbl_addr );
-
- KMP_DEBUG_ASSERT( d_tn );
-
- if (d_tn->is_vec) {
- if (d_tn->dt.dtorv != 0) {
- (void) (*d_tn->dt.dtorv) (tn->par_addr, d_tn->vec_len);
- }
- if (d_tn->obj_init != 0) {
- (void) (*d_tn->dt.dtorv) (d_tn->obj_init, d_tn->vec_len);
- }
- } else {
- if (d_tn->dt.dtor != 0) {
- (void) (*d_tn->dt.dtor) (tn->par_addr);
- }
- if (d_tn->obj_init != 0) {
- (void) (*d_tn->dt.dtor) (d_tn->obj_init);
- }
- }
- }
- KC_TRACE( 30, ("__kmp_common_destroy_gtid: T#%d threadprivate destructors complete\n",
- gtid ) );
- }
- }
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-#ifdef KMP_TASK_COMMON_DEBUG
-static void
-dump_list( void )
-{
- int p, q;
-
- for (p = 0; p < __kmp_all_nth; ++p) {
- if( !__kmp_threads[p] ) continue;
- for (q = 0; q < KMP_HASH_TABLE_SIZE; ++q) {
- if (__kmp_threads[ p ]->th.th_pri_common->data[ q ]) {
- struct private_common *tn;
-
- KC_TRACE( 10, ( "\tdump_list: gtid:%d addresses\n", p ) );
-
- for (tn = __kmp_threads[ p ]->th.th_pri_common->data[ q ]; tn; tn = tn->next) {
- KC_TRACE( 10, ( "\tdump_list: THREADPRIVATE: Serial %p -> Parallel %p\n",
- tn->gbl_addr, tn->par_addr ) );
- }
- }
- }
- }
-}
-#endif /* KMP_TASK_COMMON_DEBUG */
-
-
-/*
- * NOTE: this routine is to be called only from the serial part of the program.
- */
-
-void
-kmp_threadprivate_insert_private_data( int gtid, void *pc_addr, void *data_addr, size_t pc_size )
-{
- struct shared_common **lnk_tn, *d_tn;
- KMP_DEBUG_ASSERT( __kmp_threads[ gtid ] &&
- __kmp_threads[ gtid ] -> th.th_root -> r.r_active == 0 );
-
- d_tn = __kmp_find_shared_task_common( &__kmp_threadprivate_d_table,
- gtid, pc_addr );
-
- if (d_tn == 0) {
- d_tn = (struct shared_common *) __kmp_allocate( sizeof( struct shared_common ) );
-
- d_tn->gbl_addr = pc_addr;
- d_tn->pod_init = __kmp_init_common_data( data_addr, pc_size );
-/*
- d_tn->obj_init = 0; // AC: commented out because __kmp_allocate zeroes the memory
- d_tn->ct.ctor = 0;
- d_tn->cct.cctor = 0;;
- d_tn->dt.dtor = 0;
- d_tn->is_vec = FALSE;
- d_tn->vec_len = 0L;
-*/
- d_tn->cmn_size = pc_size;
-
- __kmp_acquire_lock( &__kmp_global_lock, gtid );
-
- lnk_tn = &(__kmp_threadprivate_d_table.data[ KMP_HASH(pc_addr) ]);
-
- d_tn->next = *lnk_tn;
- *lnk_tn = d_tn;
-
- __kmp_release_lock( &__kmp_global_lock, gtid );
- }
-}
-
-struct private_common *
-kmp_threadprivate_insert( int gtid, void *pc_addr, void *data_addr, size_t pc_size )
-{
- struct private_common *tn, **tt;
- struct shared_common *d_tn;
-
- /* +++++++++ START OF CRITICAL SECTION +++++++++ */
-
- __kmp_acquire_lock( & __kmp_global_lock, gtid );
-
- tn = (struct private_common *) __kmp_allocate( sizeof (struct private_common) );
-
- tn->gbl_addr = pc_addr;
-
- d_tn = __kmp_find_shared_task_common( &__kmp_threadprivate_d_table,
- gtid, pc_addr ); /* Only the MASTER data table exists. */
-
- if (d_tn != 0) {
- /* This threadprivate variable has already been seen. */
-
- if ( d_tn->pod_init == 0 && d_tn->obj_init == 0 ) {
- d_tn->cmn_size = pc_size;
-
- if (d_tn->is_vec) {
- if (d_tn->ct.ctorv != 0) {
- /* Construct from scratch so no prototype exists */
- d_tn->obj_init = 0;
- }
- else if (d_tn->cct.cctorv != 0) {
- /* Now data initialize the prototype since it was previously registered */
- d_tn->obj_init = (void *) __kmp_allocate( d_tn->cmn_size );
- (void) (*d_tn->cct.cctorv) (d_tn->obj_init, pc_addr, d_tn->vec_len);
- }
- else {
- d_tn->pod_init = __kmp_init_common_data( data_addr, d_tn->cmn_size );
- }
- } else {
- if (d_tn->ct.ctor != 0) {
- /* Construct from scratch so no prototype exists */
- d_tn->obj_init = 0;
- }
- else if (d_tn->cct.cctor != 0) {
- /* Now data initialize the prototype since it was previously registered */
- d_tn->obj_init = (void *) __kmp_allocate( d_tn->cmn_size );
- (void) (*d_tn->cct.cctor) (d_tn->obj_init, pc_addr);
- }
- else {
- d_tn->pod_init = __kmp_init_common_data( data_addr, d_tn->cmn_size );
- }
- }
- }
- }
- else {
- struct shared_common **lnk_tn;
-
- d_tn = (struct shared_common *) __kmp_allocate( sizeof( struct shared_common ) );
- d_tn->gbl_addr = pc_addr;
- d_tn->cmn_size = pc_size;
- d_tn->pod_init = __kmp_init_common_data( data_addr, pc_size );
-/*
- d_tn->obj_init = 0; // AC: commented out because __kmp_allocate zeroes the memory
- d_tn->ct.ctor = 0;
- d_tn->cct.cctor = 0;
- d_tn->dt.dtor = 0;
- d_tn->is_vec = FALSE;
- d_tn->vec_len = 0L;
-*/
- lnk_tn = &(__kmp_threadprivate_d_table.data[ KMP_HASH(pc_addr) ]);
-
- d_tn->next = *lnk_tn;
- *lnk_tn = d_tn;
- }
-
- tn->cmn_size = d_tn->cmn_size;
-
- if ( (__kmp_foreign_tp) ? (KMP_INITIAL_GTID (gtid)) : (KMP_UBER_GTID (gtid)) ) {
- tn->par_addr = (void *) pc_addr;
- }
- else {
- tn->par_addr = (void *) __kmp_allocate( tn->cmn_size );
- }
-
- __kmp_release_lock( & __kmp_global_lock, gtid );
-
- /* +++++++++ END OF CRITICAL SECTION +++++++++ */
-
-#ifdef USE_CHECKS_COMMON
- if (pc_size > d_tn->cmn_size) {
- KC_TRACE( 10, ( "__kmp_threadprivate_insert: THREADPRIVATE: %p (%"
- KMP_UINTPTR_SPEC " ,%" KMP_UINTPTR_SPEC ")\n",
- pc_addr, pc_size, d_tn->cmn_size ) );
- KMP_FATAL( TPCommonBlocksInconsist );
- }
-#endif /* USE_CHECKS_COMMON */
-
- tt = &(__kmp_threads[ gtid ]->th.th_pri_common->data[ KMP_HASH(pc_addr) ]);
-
-#ifdef KMP_TASK_COMMON_DEBUG
- if (*tt != 0) {
- KC_TRACE( 10, ( "__kmp_threadprivate_insert: WARNING! thread#%d: collision on %p\n",
- gtid, pc_addr ) );
- }
-#endif
- tn->next = *tt;
- *tt = tn;
-
-#ifdef KMP_TASK_COMMON_DEBUG
- KC_TRACE( 10, ( "__kmp_threadprivate_insert: thread#%d, inserted node %p on list\n",
- gtid, pc_addr ) );
- dump_list( );
-#endif
-
- /* Link the node into a simple list */
-
- tn->link = __kmp_threads[ gtid ]->th.th_pri_head;
- __kmp_threads[ gtid ]->th.th_pri_head = tn;
-
-#ifdef BUILD_TV
- __kmp_tv_threadprivate_store( __kmp_threads[ gtid ], tn->gbl_addr, tn->par_addr );
-#endif
-
- if( (__kmp_foreign_tp) ? (KMP_INITIAL_GTID (gtid)) : (KMP_UBER_GTID (gtid)) )
- return tn;
-
- /*
- * if C++ object with copy constructor, use it;
- * else if C++ object with constructor, use it for the non-master copies only;
- * else use pod_init and memcpy
- *
- * C++ constructors need to be called once for each non-master thread on allocate
- * C++ copy constructors need to be called once for each thread on allocate
- */
-
- /*
- * C++ object with constructors/destructors;
- * don't call constructors for master thread though
- */
- if (d_tn->is_vec) {
- if ( d_tn->ct.ctorv != 0) {
- (void) (*d_tn->ct.ctorv) (tn->par_addr, d_tn->vec_len);
- } else if (d_tn->cct.cctorv != 0) {
- (void) (*d_tn->cct.cctorv) (tn->par_addr, d_tn->obj_init, d_tn->vec_len);
- } else if (tn->par_addr != tn->gbl_addr) {
- __kmp_copy_common_data( tn->par_addr, d_tn->pod_init );
- }
- } else {
- if ( d_tn->ct.ctor != 0 ) {
- (void) (*d_tn->ct.ctor) (tn->par_addr);
- } else if (d_tn->cct.cctor != 0) {
- (void) (*d_tn->cct.cctor) (tn->par_addr, d_tn->obj_init);
- } else if (tn->par_addr != tn->gbl_addr) {
- __kmp_copy_common_data( tn->par_addr, d_tn->pod_init );
- }
- }
-/* !BUILD_OPENMP_C
- if (tn->par_addr != tn->gbl_addr)
- __kmp_copy_common_data( tn->par_addr, d_tn->pod_init ); */
-
- return tn;
-}
-
-/* ------------------------------------------------------------------------ */
-/* We are currently parallel, and we know the thread id. */
-/* ------------------------------------------------------------------------ */
-
-/*!
- @ingroup THREADPRIVATE
-
- @param loc source location information
- @param data pointer to data being privatized
- @param ctor pointer to constructor function for data
- @param cctor pointer to copy constructor function for data
- @param dtor pointer to destructor function for data
-
- Register constructors and destructors for thread private data.
- This function is called when executing in parallel, when we know the thread id.
-*/
-void
-__kmpc_threadprivate_register(ident_t *loc, void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor)
-{
- struct shared_common *d_tn, **lnk_tn;
-
- KC_TRACE( 10, ("__kmpc_threadprivate_register: called\n" ) );
-
-#ifdef USE_CHECKS_COMMON
- /* copy constructor must be zero for current code gen (Nov 2002 - jph) */
- KMP_ASSERT( cctor == 0);
-#endif /* USE_CHECKS_COMMON */
-
- /* Only the global data table exists. */
- d_tn = __kmp_find_shared_task_common( &__kmp_threadprivate_d_table, -1, data );
-
- if (d_tn == 0) {
- d_tn = (struct shared_common *) __kmp_allocate( sizeof( struct shared_common ) );
- d_tn->gbl_addr = data;
-
- d_tn->ct.ctor = ctor;
- d_tn->cct.cctor = cctor;
- d_tn->dt.dtor = dtor;
-/*
- d_tn->is_vec = FALSE; // AC: commented out because __kmp_allocate zeroes the memory
- d_tn->vec_len = 0L;
- d_tn->obj_init = 0;
- d_tn->pod_init = 0;
-*/
- lnk_tn = &(__kmp_threadprivate_d_table.data[ KMP_HASH(data) ]);
-
- d_tn->next = *lnk_tn;
- *lnk_tn = d_tn;
- }
-}
-
-void *
-__kmpc_threadprivate(ident_t *loc, kmp_int32 global_tid, void *data, size_t size)
-{
- void *ret;
- struct private_common *tn;
-
- KC_TRACE( 10, ("__kmpc_threadprivate: T#%d called\n", global_tid ) );
-
-#ifdef USE_CHECKS_COMMON
- if (! __kmp_init_serial)
- KMP_FATAL( RTLNotInitialized );
-#endif /* USE_CHECKS_COMMON */
-
- if ( ! __kmp_threads[global_tid] -> th.th_root -> r.r_active && ! __kmp_foreign_tp ) {
- /* The parallel address will NEVER overlap with the data_address */
- /* dkp: 3rd arg to kmp_threadprivate_insert_private_data() is the data_address; use data_address = data */
-
- KC_TRACE( 20, ("__kmpc_threadprivate: T#%d inserting private data\n", global_tid ) );
- kmp_threadprivate_insert_private_data( global_tid, data, data, size );
-
- ret = data;
- }
- else {
- KC_TRACE( 50, ("__kmpc_threadprivate: T#%d try to find private data at address %p\n",
- global_tid, data ) );
- tn = __kmp_threadprivate_find_task_common( __kmp_threads[ global_tid ]->th.th_pri_common, global_tid, data );
-
- if ( tn ) {
- KC_TRACE( 20, ("__kmpc_threadprivate: T#%d found data\n", global_tid ) );
-#ifdef USE_CHECKS_COMMON
- if ((size_t) size > tn->cmn_size) {
- KC_TRACE( 10, ( "THREADPRIVATE: %p (%" KMP_UINTPTR_SPEC " ,%" KMP_UINTPTR_SPEC ")\n",
- data, size, tn->cmn_size ) );
- KMP_FATAL( TPCommonBlocksInconsist );
- }
-#endif /* USE_CHECKS_COMMON */
- }
- else {
- /* The parallel address will NEVER overlap with the data_address */
- /* dkp: 3rd arg to kmp_threadprivate_insert() is the data_address; use data_address = data */
- KC_TRACE( 20, ("__kmpc_threadprivate: T#%d inserting data\n", global_tid ) );
- tn = kmp_threadprivate_insert( global_tid, data, data, size );
- }
-
- ret = tn->par_addr;
- }
- KC_TRACE( 10, ("__kmpc_threadprivate: T#%d exiting; return value = %p\n",
- global_tid, ret ) );
-
- return ret;
-}
-
-/*!
- @ingroup THREADPRIVATE
- @param loc source location information
- @param global_tid global thread number
- @param data pointer to data to privatize
- @param size size of data to privatize
- @param cache pointer to cache
- @return pointer to private storage
-
- Allocate private storage for threadprivate data.
-*/
-void *
-__kmpc_threadprivate_cached(
- ident_t * loc,
- kmp_int32 global_tid, // gtid.
- void * data, // Pointer to original global variable.
- size_t size, // Size of original global variable.
- void *** cache
-) {
- KC_TRACE( 10, ("__kmpc_threadprivate_cached: T#%d called with cache: %p, address: %p, size: %"
- KMP_SIZE_T_SPEC "\n",
- global_tid, *cache, data, size ) );
-
- if ( TCR_PTR(*cache) == 0) {
- __kmp_acquire_lock( & __kmp_global_lock, global_tid );
-
- if ( TCR_PTR(*cache) == 0) {
- __kmp_acquire_bootstrap_lock(&__kmp_tp_cached_lock);
- __kmp_tp_cached = 1;
- __kmp_release_bootstrap_lock(&__kmp_tp_cached_lock);
- void ** my_cache;
- KMP_ITT_IGNORE(
- my_cache = (void**)
- __kmp_allocate(sizeof( void * ) * __kmp_tp_capacity + sizeof ( kmp_cached_addr_t ));
- );
- // No need to zero the allocated memory; __kmp_allocate does that.
- KC_TRACE( 50, ("__kmpc_threadprivate_cached: T#%d allocated cache at address %p\n",
- global_tid, my_cache ) );
-
- /* TODO: free all this memory in __kmp_common_destroy using __kmp_threadpriv_cache_list */
- /* Add address of mycache to linked list for cleanup later */
- kmp_cached_addr_t *tp_cache_addr;
-
- tp_cache_addr = (kmp_cached_addr_t *) & my_cache[__kmp_tp_capacity];
- tp_cache_addr -> addr = my_cache;
- tp_cache_addr -> next = __kmp_threadpriv_cache_list;
- __kmp_threadpriv_cache_list = tp_cache_addr;
-
- KMP_MB();
-
- TCW_PTR( *cache, my_cache);
-
- KMP_MB();
- }
-
- __kmp_release_lock( & __kmp_global_lock, global_tid );
- }
-
- void *ret;
- if ((ret = TCR_PTR((*cache)[ global_tid ])) == 0) {
- ret = __kmpc_threadprivate( loc, global_tid, data, (size_t) size);
-
- TCW_PTR( (*cache)[ global_tid ], ret);
- }
- KC_TRACE( 10, ("__kmpc_threadprivate_cached: T#%d exiting; return value = %p\n",
- global_tid, ret ) );
-
- return ret;
-}
-
-/*!
- @ingroup THREADPRIVATE
- @param loc source location information
- @param data pointer to data being privatized
- @param ctor pointer to constructor function for data
- @param cctor pointer to copy constructor function for data
- @param dtor pointer to destructor function for data
- @param vector_length length of the vector (bytes or elements?)
- Register vector constructors and destructors for thread private data.
-*/
-void
-__kmpc_threadprivate_register_vec( ident_t *loc, void *data, kmpc_ctor_vec ctor,
- kmpc_cctor_vec cctor, kmpc_dtor_vec dtor,
- size_t vector_length )
-{
- struct shared_common *d_tn, **lnk_tn;
-
- KC_TRACE( 10, ("__kmpc_threadprivate_register_vec: called\n" ) );
-
-#ifdef USE_CHECKS_COMMON
- /* copy constructor must be zero for current code gen (Nov 2002 - jph) */
- KMP_ASSERT( cctor == 0);
-#endif /* USE_CHECKS_COMMON */
-
- d_tn = __kmp_find_shared_task_common( &__kmp_threadprivate_d_table,
- -1, data ); /* Only the global data table exists. */
-
- if (d_tn == 0) {
- d_tn = (struct shared_common *) __kmp_allocate( sizeof( struct shared_common ) );
- d_tn->gbl_addr = data;
-
- d_tn->ct.ctorv = ctor;
- d_tn->cct.cctorv = cctor;
- d_tn->dt.dtorv = dtor;
- d_tn->is_vec = TRUE;
- d_tn->vec_len = (size_t) vector_length;
-/*
- d_tn->obj_init = 0; // AC: commented out because __kmp_allocate zeroes the memory
- d_tn->pod_init = 0;
-*/
- lnk_tn = &(__kmp_threadprivate_d_table.data[ KMP_HASH(data) ]);
-
- d_tn->next = *lnk_tn;
- *lnk_tn = d_tn;
- }
-}
Removed: openmp/trunk/runtime/src/kmp_utility.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/kmp_utility.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/kmp_utility.c (original)
+++ openmp/trunk/runtime/src/kmp_utility.c (removed)
@@ -1,429 +0,0 @@
-/*
- * kmp_utility.c -- Utility routines for the OpenMP support library.
- */
-
-
-//===----------------------------------------------------------------------===//
-//
-// 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_wrapper_getpid.h"
-#include "kmp_str.h"
-#include <float.h>
-#include "kmp_i18n.h"
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-static const char *unknown = "unknown";
-
-#if KMP_ARCH_X86 || KMP_ARCH_X86_64
-
-/* NOTE: If called before serial_initialize (i.e. from runtime_initialize), then */
-/* the debugging package has not been initialized yet, and only "0" will print */
-/* debugging output since the environment variables have not been read. */
-
-#ifdef KMP_DEBUG
-static int trace_level = 5;
-#endif
-
-/*
- * LOG_ID_BITS = ( 1 + floor( log_2( max( log_per_phy - 1, 1 ))))
- * APIC_ID = (PHY_ID << LOG_ID_BITS) | LOG_ID
- * PHY_ID = APIC_ID >> LOG_ID_BITS
- */
-int
-__kmp_get_physical_id( int log_per_phy, int apic_id )
-{
- int index_lsb, index_msb, temp;
-
- if (log_per_phy > 1) {
- index_lsb = 0;
- index_msb = 31;
-
- temp = log_per_phy;
- while ( (temp & 1) == 0 ) {
- temp >>= 1;
- index_lsb++;
- }
-
- temp = log_per_phy;
- while ( (temp & 0x80000000)==0 ) {
- temp <<= 1;
- index_msb--;
- }
-
- /* If >1 bits were set in log_per_phy, choose next higher power of 2 */
- if (index_lsb != index_msb) index_msb++;
-
- return ( (int) (apic_id >> index_msb) );
- }
-
- return apic_id;
-}
-
-
-/*
- * LOG_ID_BITS = ( 1 + floor( log_2( max( log_per_phy - 1, 1 ))))
- * APIC_ID = (PHY_ID << LOG_ID_BITS) | LOG_ID
- * LOG_ID = APIC_ID & (( 1 << LOG_ID_BITS ) - 1 )
- */
-int
-__kmp_get_logical_id( int log_per_phy, int apic_id )
-{
- unsigned current_bit;
- int bits_seen;
-
- if (log_per_phy <= 1) return ( 0 );
-
- bits_seen = 0;
-
- for (current_bit = 1; log_per_phy != 0; current_bit <<= 1) {
- if ( log_per_phy & current_bit ) {
- log_per_phy &= ~current_bit;
- bits_seen++;
- }
- }
-
- /* If exactly 1 bit was set in log_per_phy, choose next lower power of 2 */
- if (bits_seen == 1) {
- current_bit >>= 1;
- }
-
- return ( (int) ((current_bit - 1) & apic_id) );
-}
-
-
-static
-kmp_uint64
-__kmp_parse_frequency( // R: Frequency in Hz.
- char const * frequency // I: Float number and unit: MHz, GHz, or TGz.
-) {
-
- double value = 0.0;
- char const * unit = NULL;
- kmp_uint64 result = 0; /* Zero is a better unknown value than all ones. */
-
- if ( frequency == NULL ) {
- return result;
- }; // if
- value = strtod( frequency, (char * *) & unit ); // strtod() does not like "char const *".
- if ( 0 < value && value <= DBL_MAX ) { // Good value (not overflow, underflow, etc).
- if ( strcmp( unit, "MHz" ) == 0 ) {
- value = value * 1.0E+6;
- } else if ( strcmp( unit, "GHz" ) == 0 ) {
- value = value * 1.0E+9;
- } else if ( strcmp( unit, "THz" ) == 0 ) {
- value = value * 1.0E+12;
- } else { // Wrong unit.
- return result;
- }; // if
- result = value;
- }; // if
- return result;
-
-}; // func __kmp_parse_cpu_frequency
-
-void
-__kmp_query_cpuid( kmp_cpuinfo_t *p )
-{
- struct kmp_cpuid buf;
- int max_arg;
- int log_per_phy;
-#ifdef KMP_DEBUG
- int cflush_size;
-#endif
-
- p->initialized = 1;
-
- p->sse2 = 1; // Assume SSE2 by default.
-
- __kmp_x86_cpuid( 0, 0, &buf );
-
- KA_TRACE( trace_level, ("INFO: CPUID %d: EAX=0x%08X EBX=0x%08X ECX=0x%08X EDX=0x%08X\n",
- 0, buf.eax, buf.ebx, buf.ecx, buf.edx ) );
-
- max_arg = buf.eax;
-
- p->apic_id = -1;
-
- if (max_arg >= 1) {
- int i;
- kmp_uint32 t, data[ 4 ];
-
- __kmp_x86_cpuid( 1, 0, &buf );
- KA_TRACE( trace_level, ("INFO: CPUID %d: EAX=0x%08X EBX=0x%08X ECX=0x%08X EDX=0x%08X\n",
- 1, buf.eax, buf.ebx, buf.ecx, buf.edx ) );
-
- {
-#define get_value(reg,lo,mask) ( ( ( reg ) >> ( lo ) ) & ( mask ) )
-
- p->signature = buf.eax;
- p->family = get_value( buf.eax, 20, 0xff ) + get_value( buf.eax, 8, 0x0f );
- p->model = ( get_value( buf.eax, 16, 0x0f ) << 4 ) + get_value( buf.eax, 4, 0x0f );
- p->stepping = get_value( buf.eax, 0, 0x0f );
-
-#undef get_value
-
- KA_TRACE( trace_level, (" family = %d, model = %d, stepping = %d\n", p->family, p->model, p->stepping ) );
- }
-
- for ( t = buf.ebx, i = 0; i < 4; t >>= 8, ++i ) {
- data[ i ] = (t & 0xff);
- }; // for
-
- p->sse2 = ( buf.edx >> 26 ) & 1;
-
-#ifdef KMP_DEBUG
-
- if ( (buf.edx >> 4) & 1 ) {
- /* TSC - Timestamp Counter Available */
- KA_TRACE( trace_level, (" TSC" ) );
- }
- if ( (buf.edx >> 8) & 1 ) {
- /* CX8 - CMPXCHG8B Instruction Available */
- KA_TRACE( trace_level, (" CX8" ) );
- }
- if ( (buf.edx >> 9) & 1 ) {
- /* APIC - Local APIC Present (multi-processor operation support */
- KA_TRACE( trace_level, (" APIC" ) );
- }
- if ( (buf.edx >> 15) & 1 ) {
- /* CMOV - Conditional MOVe Instruction Available */
- KA_TRACE( trace_level, (" CMOV" ) );
- }
- if ( (buf.edx >> 18) & 1 ) {
- /* PSN - Processor Serial Number Available */
- KA_TRACE( trace_level, (" PSN" ) );
- }
- if ( (buf.edx >> 19) & 1 ) {
- /* CLFULSH - Cache Flush Instruction Available */
- cflush_size = data[ 1 ] * 8; /* Bits 15-08: CLFLUSH line size = 8 (64 bytes) */
- KA_TRACE( trace_level, (" CLFLUSH(%db)", cflush_size ) );
-
- }
- if ( (buf.edx >> 21) & 1 ) {
- /* DTES - Debug Trace & EMON Store */
- KA_TRACE( trace_level, (" DTES" ) );
- }
- if ( (buf.edx >> 22) & 1 ) {
- /* ACPI - ACPI Support Available */
- KA_TRACE( trace_level, (" ACPI" ) );
- }
- if ( (buf.edx >> 23) & 1 ) {
- /* MMX - Multimedia Extensions */
- KA_TRACE( trace_level, (" MMX" ) );
- }
- if ( (buf.edx >> 25) & 1 ) {
- /* SSE - SSE Instructions */
- KA_TRACE( trace_level, (" SSE" ) );
- }
- if ( (buf.edx >> 26) & 1 ) {
- /* SSE2 - SSE2 Instructions */
- KA_TRACE( trace_level, (" SSE2" ) );
- }
- if ( (buf.edx >> 27) & 1 ) {
- /* SLFSNP - Self-Snooping Cache */
- KA_TRACE( trace_level, (" SLFSNP" ) );
- }
-#endif /* KMP_DEBUG */
-
- if ( (buf.edx >> 28) & 1 ) {
- /* Bits 23-16: Logical Processors per Physical Processor (1 for P4) */
- log_per_phy = data[ 2 ];
- p->apic_id = data[ 3 ]; /* Bits 31-24: Processor Initial APIC ID (X) */
- KA_TRACE( trace_level, (" HT(%d TPUs)", log_per_phy ) );
-
- if( log_per_phy > 1 ) {
- /* default to 1k FOR JT-enabled processors (4k on OS X*) */
-#if KMP_OS_DARWIN
- p->cpu_stackoffset = 4 * 1024;
-#else
- p->cpu_stackoffset = 1 * 1024;
-#endif
- }
-
- p->physical_id = __kmp_get_physical_id( log_per_phy, p->apic_id );
- p->logical_id = __kmp_get_logical_id( log_per_phy, p->apic_id );
- }
-#ifdef KMP_DEBUG
- if ( (buf.edx >> 29) & 1 ) {
- /* ATHROTL - Automatic Throttle Control */
- KA_TRACE( trace_level, (" ATHROTL" ) );
- }
- KA_TRACE( trace_level, (" ]\n" ) );
-
- for (i = 2; i <= max_arg; ++i) {
- __kmp_x86_cpuid( i, 0, &buf );
- KA_TRACE( trace_level,
- ( "INFO: CPUID %d: EAX=0x%08X EBX=0x%08X ECX=0x%08X EDX=0x%08X\n",
- i, buf.eax, buf.ebx, buf.ecx, buf.edx ) );
- }
-#endif
-#if KMP_USE_ADAPTIVE_LOCKS
- p->rtm = 0;
- if (max_arg > 7)
- {
- /* RTM bit CPUID.07:EBX, bit 11 */
- __kmp_x86_cpuid(7, 0, &buf);
- p->rtm = (buf.ebx >> 11) & 1;
- KA_TRACE( trace_level, (" RTM" ) );
- }
-#endif
- }; // if
-
- { // Parse CPU brand string for frequency, saving the string for later.
- int i;
- kmp_cpuid_t * base = (kmp_cpuid_t *)&p->name[0];
-
- // Get CPU brand string.
- for ( i = 0; i < 3; ++ i ) {
- __kmp_x86_cpuid( 0x80000002 + i, 0, base+i );
- }; // for
- p->name[ sizeof(p->name) - 1 ] = 0; // Just in case. ;-)
- KA_TRACE( trace_level, ( "cpu brand string: \"%s\"\n", &p->name[0] ) );
-
- // Parse frequency.
- p->frequency = __kmp_parse_frequency( strrchr( &p->name[0], ' ' ) );
- KA_TRACE( trace_level, ( "cpu frequency from brand string: %" KMP_UINT64_SPEC "\n", p->frequency ) );
- }
-}
-
-#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
-
-/* ------------------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------------------ */
-
-void
-__kmp_expand_host_name( char *buffer, size_t size )
-{
- KMP_DEBUG_ASSERT(size >= sizeof(unknown));
-#if KMP_OS_WINDOWS
- {
- DWORD s = size;
-
- if (! GetComputerNameA( buffer, & s ))
- KMP_STRCPY_S( buffer, size, unknown );
- }
-#else
- buffer[size - 2] = 0;
- if (gethostname( buffer, size ) || buffer[size - 2] != 0)
- KMP_STRCPY_S( buffer, size, unknown );
-#endif
-}
-
-/* Expand the meta characters in the filename:
- *
- * Currently defined characters are:
- *
- * %H the hostname
- * %P the number of threads used.
- * %I the unique identifier for this run.
- */
-
-void
-__kmp_expand_file_name( char *result, size_t rlen, char *pattern )
-{
- char *pos = result, *end = result + rlen - 1;
- char buffer[256];
- int default_cpu_width = 1;
- int snp_result;
-
- KMP_DEBUG_ASSERT(rlen > 0);
- *end = 0;
- {
- int i;
- for(i = __kmp_xproc; i >= 10; i /= 10, ++default_cpu_width);
- }
-
- if (pattern != NULL) {
- while (*pattern != '\0' && pos < end) {
- if (*pattern != '%') {
- *pos++ = *pattern++;
- } else {
- char *old_pattern = pattern;
- int width = 1;
- int cpu_width = default_cpu_width;
-
- ++pattern;
-
- if (*pattern >= '0' && *pattern <= '9') {
- width = 0;
- do {
- width = (width * 10) + *pattern++ - '0';
- } while (*pattern >= '0' && *pattern <= '9');
- if (width < 0 || width > 1024)
- width = 1;
-
- cpu_width = width;
- }
-
- switch (*pattern) {
- case 'H':
- case 'h':
- {
- __kmp_expand_host_name( buffer, sizeof( buffer ) );
- KMP_STRNCPY( pos, buffer, end - pos + 1);
- if(*end == 0) {
- while ( *pos )
- ++pos;
- ++pattern;
- } else
- pos = end;
- }
- break;
- case 'P':
- case 'p':
- {
- snp_result = KMP_SNPRINTF( pos, end - pos + 1, "%0*d", cpu_width, __kmp_dflt_team_nth );
- if(snp_result >= 0 && snp_result <= end - pos) {
- while ( *pos )
- ++pos;
- ++pattern;
- } else
- pos = end;
- }
- break;
- case 'I':
- case 'i':
- {
- pid_t id = getpid();
- snp_result = KMP_SNPRINTF( pos, end - pos + 1, "%0*d", width, id );
- if(snp_result >= 0 && snp_result <= end - pos) {
- while ( *pos )
- ++pos;
- ++pattern;
- } else
- pos = end;
- break;
- }
- case '%':
- {
- *pos++ = '%';
- ++pattern;
- break;
- }
- default:
- {
- *pos++ = '%';
- pattern = old_pattern + 1;
- break;
- }
- }
- }
- }
- /* TODO: How do we get rid of this? */
- if(*pattern != '\0')
- KMP_FATAL( FileNameTooLong );
- }
-
- *pos = '\0';
-}
-
Removed: openmp/trunk/runtime/src/kmp_version.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/kmp_version.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/kmp_version.c (original)
+++ openmp/trunk/runtime/src/kmp_version.c (removed)
@@ -1,214 +0,0 @@
-/*
- * kmp_version.c
- */
-
-
-//===----------------------------------------------------------------------===//
-//
-// 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_io.h"
-#include "kmp_version.h"
-
-// Replace with snapshot date YYYYMMDD for promotion build.
-#define KMP_VERSION_BUILD 20140926
-
-// Helper macros to convert value of macro to string literal.
-#define _stringer( x ) #x
-#define stringer( x ) _stringer( x )
-
-// Detect compiler.
-#if KMP_COMPILER_ICC
- #if __INTEL_COMPILER == 1010
- #define KMP_COMPILER "Intel C++ Compiler 10.1"
- #elif __INTEL_COMPILER == 1100
- #define KMP_COMPILER "Intel C++ Compiler 11.0"
- #elif __INTEL_COMPILER == 1110
- #define KMP_COMPILER "Intel C++ Compiler 11.1"
- #elif __INTEL_COMPILER == 1200
- #define KMP_COMPILER "Intel C++ Compiler 12.0"
- #elif __INTEL_COMPILER == 1210
- #define KMP_COMPILER "Intel C++ Compiler 12.1"
- #elif __INTEL_COMPILER == 1300
- #define KMP_COMPILER "Intel C++ Compiler 13.0"
- #elif __INTEL_COMPILER == 1310
- #define KMP_COMPILER "Intel C++ Compiler 13.1"
- #elif __INTEL_COMPILER == 1400
- #define KMP_COMPILER "Intel C++ Compiler 14.0"
- #elif __INTEL_COMPILER == 1410
- #define KMP_COMPILER "Intel C++ Compiler 14.1"
- #elif __INTEL_COMPILER == 1500
- #define KMP_COMPILER "Intel C++ Compiler 15.0"
- #elif __INTEL_COMPILER == 1600
- #define KMP_COMPILER "Intel C++ Compiler 16.0"
- #elif __INTEL_COMPILER == 1700
- #define KMP_COMPILER "Intel C++ Compiler 17.0"
- #elif __INTEL_COMPILER == 9998
- #define KMP_COMPILER "Intel C++ Compiler mainline"
- #elif __INTEL_COMPILER == 9999
- #define KMP_COMPILER "Intel C++ Compiler mainline"
- #endif
-#elif KMP_COMPILER_CLANG
- #define KMP_COMPILER "Clang " stringer( __clang_major__ ) "." stringer( __clang_minor__ )
-#elif KMP_COMPILER_GCC
- #define KMP_COMPILER "GCC " stringer( __GNUC__ ) "." stringer( __GNUC_MINOR__ )
-#elif KMP_COMPILER_MSVC
- #define KMP_COMPILER "MSVC " stringer( _MSC_FULL_VER )
-#endif
-#ifndef KMP_COMPILER
- #warning "Unknown compiler"
- #define KMP_COMPILER "unknown compiler"
-#endif
-
-// Detect librray type (perf, stub).
-#ifdef KMP_STUB
- #define KMP_LIB_TYPE "stub"
-#else
- #define KMP_LIB_TYPE "performance"
-#endif // KMP_LIB_TYPE
-
-// Detect link type (static, dynamic).
-#ifdef KMP_DYNAMIC_LIB
- #define KMP_LINK_TYPE "dynamic"
-#else
- #define KMP_LINK_TYPE "static"
-#endif // KMP_LINK_TYPE
-
-// Finally, define strings.
-#define KMP_LIBRARY KMP_LIB_TYPE " library (" KMP_LINK_TYPE ")"
-#define KMP_COPYRIGHT ""
-
-int const __kmp_version_major = KMP_VERSION_MAJOR;
-int const __kmp_version_minor = KMP_VERSION_MINOR;
-int const __kmp_version_build = KMP_VERSION_BUILD;
-int const __kmp_openmp_version =
- #if OMP_45_ENABLED
- 201511;
- #elif OMP_40_ENABLED
- 201307;
- #else
- 201107;
- #endif
-
-/* Do NOT change the format of this string! Intel(R) Thread Profiler checks for a
- specific format some changes in the recognition routine there need to
- be made before this is changed.
-*/
-char const __kmp_copyright[] =
- KMP_VERSION_PREFIX KMP_LIBRARY
- " ver. " stringer( KMP_VERSION_MAJOR ) "." stringer( KMP_VERSION_MINOR )
- "." stringer( KMP_VERSION_BUILD ) " "
- KMP_COPYRIGHT;
-
-char const __kmp_version_copyright[] = KMP_VERSION_PREFIX KMP_COPYRIGHT;
-char const __kmp_version_lib_ver[] = KMP_VERSION_PREFIX "version: " stringer( KMP_VERSION_MAJOR ) "." stringer( KMP_VERSION_MINOR ) "." stringer( KMP_VERSION_BUILD );
-char const __kmp_version_lib_type[] = KMP_VERSION_PREFIX "library type: " KMP_LIB_TYPE;
-char const __kmp_version_link_type[] = KMP_VERSION_PREFIX "link type: " KMP_LINK_TYPE;
-char const __kmp_version_build_time[] = KMP_VERSION_PREFIX "build time: " "no_timestamp";
-#if KMP_MIC2
- char const __kmp_version_target_env[] = KMP_VERSION_PREFIX "target environment: MIC2";
-#endif
-char const __kmp_version_build_compiler[] = KMP_VERSION_PREFIX "build compiler: " KMP_COMPILER;
-
-//
-// Called at serial initialization time.
-//
-static int __kmp_version_1_printed = FALSE;
-
-void
-__kmp_print_version_1( void )
-{
- if ( __kmp_version_1_printed ) {
- return;
- }; // if
- __kmp_version_1_printed = TRUE;
-
- #ifndef KMP_STUB
- kmp_str_buf_t buffer;
- __kmp_str_buf_init( & buffer );
- // Print version strings skipping initial magic.
- __kmp_str_buf_print( & buffer, "%s\n", & __kmp_version_lib_ver[ KMP_VERSION_MAGIC_LEN ] );
- __kmp_str_buf_print( & buffer, "%s\n", & __kmp_version_lib_type[ KMP_VERSION_MAGIC_LEN ] );
- __kmp_str_buf_print( & buffer, "%s\n", & __kmp_version_link_type[ KMP_VERSION_MAGIC_LEN ] );
- __kmp_str_buf_print( & buffer, "%s\n", & __kmp_version_build_time[ KMP_VERSION_MAGIC_LEN ] );
- #if KMP_MIC
- __kmp_str_buf_print( & buffer, "%s\n", & __kmp_version_target_env[ KMP_VERSION_MAGIC_LEN ] );
- #endif
- __kmp_str_buf_print( & buffer, "%s\n", & __kmp_version_build_compiler[ KMP_VERSION_MAGIC_LEN ] );
- #if defined(KMP_GOMP_COMPAT)
- __kmp_str_buf_print( & buffer, "%s\n", & __kmp_version_alt_comp[ KMP_VERSION_MAGIC_LEN ] );
- #endif /* defined(KMP_GOMP_COMPAT) */
- __kmp_str_buf_print( & buffer, "%s\n", & __kmp_version_omp_api[ KMP_VERSION_MAGIC_LEN ] );
- __kmp_str_buf_print( & buffer, "%sdynamic error checking: %s\n", KMP_VERSION_PREF_STR, ( __kmp_env_consistency_check ? "yes" : "no" ) );
- #ifdef KMP_DEBUG
- for ( int i = bs_plain_barrier; i < bs_last_barrier; ++ i ) {
- __kmp_str_buf_print(
- & buffer,
- "%s%s barrier branch bits: gather=%u, release=%u\n",
- KMP_VERSION_PREF_STR,
- __kmp_barrier_type_name[ i ],
- __kmp_barrier_gather_branch_bits[ i ],
- __kmp_barrier_release_branch_bits[ i ]
- ); // __kmp_str_buf_print
- }; // for i
- for ( int i = bs_plain_barrier; i < bs_last_barrier; ++ i ) {
- __kmp_str_buf_print(
- & buffer,
- "%s%s barrier pattern: gather=%s, release=%s\n",
- KMP_VERSION_PREF_STR,
- __kmp_barrier_type_name[ i ],
- __kmp_barrier_pattern_name[ __kmp_barrier_gather_pattern[ i ] ],
- __kmp_barrier_pattern_name[ __kmp_barrier_release_pattern[ i ] ]
- ); // __kmp_str_buf_print
- }; // for i
- __kmp_str_buf_print( & buffer, "%s\n", & __kmp_version_lock[ KMP_VERSION_MAGIC_LEN ] );
- #endif
- __kmp_str_buf_print(
- & buffer,
- "%sthread affinity support: %s\n",
- KMP_VERSION_PREF_STR,
- #if KMP_AFFINITY_SUPPORTED
- (
- KMP_AFFINITY_CAPABLE()
- ?
- (
- __kmp_affinity_type == affinity_none
- ?
- "not used"
- :
- "yes"
- )
- :
- "no"
- )
- #else
- "no"
- #endif
- );
- __kmp_printf( "%s", buffer.str );
- __kmp_str_buf_free( & buffer );
- K_DIAG( 1, ( "KMP_VERSION is true\n" ) );
- #endif // KMP_STUB
-} // __kmp_print_version_1
-
-//
-// Called at parallel initialization time.
-//
-static int __kmp_version_2_printed = FALSE;
-
-void
-__kmp_print_version_2( void ) {
- if ( __kmp_version_2_printed ) {
- return;
- }; // if
- __kmp_version_2_printed = TRUE;
-} // __kmp_print_version_2
-
-// end of file //
Removed: openmp/trunk/runtime/src/ompt-general.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/ompt-general.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/ompt-general.c (original)
+++ openmp/trunk/runtime/src/ompt-general.c (removed)
@@ -1,535 +0,0 @@
-/*****************************************************************************
- * system include files
- ****************************************************************************/
-
-#include <assert.h>
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-
-/*****************************************************************************
- * ompt include files
- ****************************************************************************/
-
-#include "ompt-specific.c"
-
-
-
-/*****************************************************************************
- * macros
- ****************************************************************************/
-
-#define ompt_get_callback_success 1
-#define ompt_get_callback_failure 0
-
-#define no_tool_present 0
-
-#define OMPT_API_ROUTINE static
-
-#ifndef OMPT_STR_MATCH
-#define OMPT_STR_MATCH(haystack, needle) (!strcasecmp(haystack, needle))
-#endif
-
-
-/*****************************************************************************
- * types
- ****************************************************************************/
-
-typedef struct {
- const char *state_name;
- ompt_state_t state_id;
-} ompt_state_info_t;
-
-
-enum tool_setting_e {
- omp_tool_error,
- omp_tool_unset,
- omp_tool_disabled,
- omp_tool_enabled
-};
-
-
-typedef void (*ompt_initialize_t) (
- ompt_function_lookup_t ompt_fn_lookup,
- const char *version,
- unsigned int ompt_version
-);
-
-
-
-/*****************************************************************************
- * global variables
- ****************************************************************************/
-
-int ompt_enabled = 0;
-
-ompt_state_info_t ompt_state_info[] = {
-#define ompt_state_macro(state, code) { # state, state },
- FOREACH_OMPT_STATE(ompt_state_macro)
-#undef ompt_state_macro
-};
-
-ompt_callbacks_t ompt_callbacks;
-
-static ompt_initialize_t ompt_initialize_fn = NULL;
-
-
-
-/*****************************************************************************
- * forward declarations
- ****************************************************************************/
-
-static ompt_interface_fn_t ompt_fn_lookup(const char *s);
-
-OMPT_API_ROUTINE ompt_thread_id_t ompt_get_thread_id(void);
-
-
-/*****************************************************************************
- * initialization and finalization (private operations)
- ****************************************************************************/
-
-/* On Unix-like systems that support weak symbols the following implementation
- * of ompt_tool() will be used in case no tool-supplied implementation of
- * this function is present in the address space of a process.
- *
- * On Windows, the ompt_tool_windows function is used to find the
- * ompt_tool symbol across all modules loaded by a process. If ompt_tool is
- * found, ompt_tool's return value is used to initialize the tool. Otherwise,
- * NULL is returned and OMPT won't be enabled */
-#if OMPT_HAVE_WEAK_ATTRIBUTE
-_OMP_EXTERN
-__attribute__ (( weak ))
-ompt_initialize_t ompt_tool()
-{
-#if OMPT_DEBUG
- printf("ompt_tool() is called from the RTL\n");
-#endif
- return NULL;
-}
-
-#elif OMPT_HAVE_PSAPI
-
-#include <psapi.h>
-#pragma comment(lib, "psapi.lib")
-#define ompt_tool ompt_tool_windows
-
-// The number of loaded modules to start enumeration with EnumProcessModules()
-#define NUM_MODULES 128
-
-static
-ompt_initialize_t ompt_tool_windows()
-{
- int i;
- DWORD needed, new_size;
- HMODULE *modules;
- HANDLE process = GetCurrentProcess();
- modules = (HMODULE*)malloc( NUM_MODULES * sizeof(HMODULE) );
- ompt_initialize_t (*ompt_tool_p)() = NULL;
-
-#if OMPT_DEBUG
- printf("ompt_tool_windows(): looking for ompt_tool\n");
-#endif
- if (!EnumProcessModules( process, modules, NUM_MODULES * sizeof(HMODULE),
- &needed)) {
- // Regardless of the error reason use the stub initialization function
- free(modules);
- return NULL;
- }
- // Check if NUM_MODULES is enough to list all modules
- new_size = needed / sizeof(HMODULE);
- if (new_size > NUM_MODULES) {
-#if OMPT_DEBUG
- printf("ompt_tool_windows(): resize buffer to %d bytes\n", needed);
-#endif
- modules = (HMODULE*)realloc( modules, needed );
- // If resizing failed use the stub function.
- if (!EnumProcessModules(process, modules, needed, &needed)) {
- free(modules);
- return NULL;
- }
- }
- for (i = 0; i < new_size; ++i) {
- (FARPROC &)ompt_tool_p = GetProcAddress(modules[i], "ompt_tool");
- if (ompt_tool_p) {
-#if OMPT_DEBUG
- TCHAR modName[MAX_PATH];
- if (GetModuleFileName(modules[i], modName, MAX_PATH))
- printf("ompt_tool_windows(): ompt_tool found in module %s\n",
- modName);
-#endif
- free(modules);
- return ompt_tool_p();
- }
-#if OMPT_DEBUG
- else {
- TCHAR modName[MAX_PATH];
- if (GetModuleFileName(modules[i], modName, MAX_PATH))
- printf("ompt_tool_windows(): ompt_tool not found in module %s\n",
- modName);
- }
-#endif
- }
- free(modules);
- return NULL;
-}
-#else
-# error Either __attribute__((weak)) or psapi.dll are required for OMPT support
-#endif // OMPT_HAVE_WEAK_ATTRIBUTE
-
-void ompt_pre_init()
-{
- //--------------------------------------------------
- // Execute the pre-initialization logic only once.
- //--------------------------------------------------
- static int ompt_pre_initialized = 0;
-
- if (ompt_pre_initialized) return;
-
- ompt_pre_initialized = 1;
-
- //--------------------------------------------------
- // Use a tool iff a tool is enabled and available.
- //--------------------------------------------------
- const char *ompt_env_var = getenv("OMP_TOOL");
- tool_setting_e tool_setting = omp_tool_error;
-
- if (!ompt_env_var || !strcmp(ompt_env_var, ""))
- tool_setting = omp_tool_unset;
- else if (OMPT_STR_MATCH(ompt_env_var, "disabled"))
- tool_setting = omp_tool_disabled;
- else if (OMPT_STR_MATCH(ompt_env_var, "enabled"))
- tool_setting = omp_tool_enabled;
-
-#if OMPT_DEBUG
- printf("ompt_pre_init(): tool_setting = %d\n", tool_setting);
-#endif
- switch(tool_setting) {
- case omp_tool_disabled:
- break;
-
- case omp_tool_unset:
- case omp_tool_enabled:
- ompt_initialize_fn = ompt_tool();
- if (ompt_initialize_fn) {
- ompt_enabled = 1;
- }
- break;
-
- case omp_tool_error:
- fprintf(stderr,
- "Warning: OMP_TOOL has invalid value \"%s\".\n"
- " legal values are (NULL,\"\",\"disabled\","
- "\"enabled\").\n", ompt_env_var);
- break;
- }
-#if OMPT_DEBUG
- printf("ompt_pre_init(): ompt_enabled = %d\n", ompt_enabled);
-#endif
-}
-
-
-void ompt_post_init()
-{
- //--------------------------------------------------
- // Execute the post-initialization logic only once.
- //--------------------------------------------------
- static int ompt_post_initialized = 0;
-
- if (ompt_post_initialized) return;
-
- ompt_post_initialized = 1;
-
- //--------------------------------------------------
- // Initialize the tool if so indicated.
- //--------------------------------------------------
- if (ompt_enabled) {
- ompt_initialize_fn(ompt_fn_lookup, ompt_get_runtime_version(),
- OMPT_VERSION);
-
- ompt_thread_t *root_thread = ompt_get_thread();
-
- ompt_set_thread_state(root_thread, ompt_state_overhead);
-
- if (ompt_callbacks.ompt_callback(ompt_event_thread_begin)) {
- ompt_callbacks.ompt_callback(ompt_event_thread_begin)
- (ompt_thread_initial, ompt_get_thread_id());
- }
-
- ompt_set_thread_state(root_thread, ompt_state_work_serial);
- }
-}
-
-
-void ompt_fini()
-{
- if (ompt_enabled) {
- if (ompt_callbacks.ompt_callback(ompt_event_runtime_shutdown)) {
- ompt_callbacks.ompt_callback(ompt_event_runtime_shutdown)();
- }
- }
-
- ompt_enabled = 0;
-}
-
-
-/*****************************************************************************
- * interface operations
- ****************************************************************************/
-
-/*****************************************************************************
- * state
- ****************************************************************************/
-
-OMPT_API_ROUTINE int ompt_enumerate_state(int current_state, int *next_state,
- const char **next_state_name)
-{
- const static int len = sizeof(ompt_state_info) / sizeof(ompt_state_info_t);
- int i = 0;
-
- for (i = 0; i < len - 1; i++) {
- if (ompt_state_info[i].state_id == current_state) {
- *next_state = ompt_state_info[i+1].state_id;
- *next_state_name = ompt_state_info[i+1].state_name;
- return 1;
- }
- }
-
- return 0;
-}
-
-
-
-/*****************************************************************************
- * callbacks
- ****************************************************************************/
-
-OMPT_API_ROUTINE int ompt_set_callback(ompt_event_t evid, ompt_callback_t cb)
-{
- switch (evid) {
-
-#define ompt_event_macro(event_name, callback_type, event_id) \
- case event_name: \
- if (ompt_event_implementation_status(event_name)) { \
- ompt_callbacks.ompt_callback(event_name) = (callback_type) cb; \
- } \
- return ompt_event_implementation_status(event_name);
-
- FOREACH_OMPT_EVENT(ompt_event_macro)
-
-#undef ompt_event_macro
-
- default: return ompt_set_result_registration_error;
- }
-}
-
-
-OMPT_API_ROUTINE int ompt_get_callback(ompt_event_t evid, ompt_callback_t *cb)
-{
- switch (evid) {
-
-#define ompt_event_macro(event_name, callback_type, event_id) \
- case event_name: \
- if (ompt_event_implementation_status(event_name)) { \
- ompt_callback_t mycb = \
- (ompt_callback_t) ompt_callbacks.ompt_callback(event_name); \
- if (mycb) { \
- *cb = mycb; \
- return ompt_get_callback_success; \
- } \
- } \
- return ompt_get_callback_failure;
-
- FOREACH_OMPT_EVENT(ompt_event_macro)
-
-#undef ompt_event_macro
-
- default: return ompt_get_callback_failure;
- }
-}
-
-
-/*****************************************************************************
- * parallel regions
- ****************************************************************************/
-
-OMPT_API_ROUTINE ompt_parallel_id_t ompt_get_parallel_id(int ancestor_level)
-{
- return __ompt_get_parallel_id_internal(ancestor_level);
-}
-
-
-OMPT_API_ROUTINE int ompt_get_parallel_team_size(int ancestor_level)
-{
- return __ompt_get_parallel_team_size_internal(ancestor_level);
-}
-
-
-OMPT_API_ROUTINE void *ompt_get_parallel_function(int ancestor_level)
-{
- return __ompt_get_parallel_function_internal(ancestor_level);
-}
-
-
-OMPT_API_ROUTINE ompt_state_t ompt_get_state(ompt_wait_id_t *ompt_wait_id)
-{
- ompt_state_t thread_state = __ompt_get_state_internal(ompt_wait_id);
-
- if (thread_state == ompt_state_undefined) {
- thread_state = ompt_state_work_serial;
- }
-
- return thread_state;
-}
-
-
-
-/*****************************************************************************
- * threads
- ****************************************************************************/
-
-
-OMPT_API_ROUTINE void *ompt_get_idle_frame()
-{
- return __ompt_get_idle_frame_internal();
-}
-
-
-
-/*****************************************************************************
- * tasks
- ****************************************************************************/
-
-
-OMPT_API_ROUTINE ompt_thread_id_t ompt_get_thread_id(void)
-{
- return __ompt_get_thread_id_internal();
-}
-
-OMPT_API_ROUTINE ompt_task_id_t ompt_get_task_id(int depth)
-{
- return __ompt_get_task_id_internal(depth);
-}
-
-
-OMPT_API_ROUTINE ompt_frame_t *ompt_get_task_frame(int depth)
-{
- return __ompt_get_task_frame_internal(depth);
-}
-
-
-OMPT_API_ROUTINE void *ompt_get_task_function(int depth)
-{
- return __ompt_get_task_function_internal(depth);
-}
-
-
-/*****************************************************************************
- * placeholders
- ****************************************************************************/
-
-// Don't define this as static. The loader may choose to eliminate the symbol
-// even though it is needed by tools.
-#define OMPT_API_PLACEHOLDER
-
-// Ensure that placeholders don't have mangled names in the symbol table.
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-OMPT_API_PLACEHOLDER void ompt_idle(void)
-{
- // This function is a placeholder used to represent the calling context of
- // idle OpenMP worker threads. It is not meant to be invoked.
- assert(0);
-}
-
-
-OMPT_API_PLACEHOLDER void ompt_overhead(void)
-{
- // This function is a placeholder used to represent the OpenMP context of
- // threads working in the OpenMP runtime. It is not meant to be invoked.
- assert(0);
-}
-
-
-OMPT_API_PLACEHOLDER void ompt_barrier_wait(void)
-{
- // This function is a placeholder used to represent the OpenMP context of
- // threads waiting for a barrier in the OpenMP runtime. It is not meant
- // to be invoked.
- assert(0);
-}
-
-
-OMPT_API_PLACEHOLDER void ompt_task_wait(void)
-{
- // This function is a placeholder used to represent the OpenMP context of
- // threads waiting for a task in the OpenMP runtime. It is not meant
- // to be invoked.
- assert(0);
-}
-
-
-OMPT_API_PLACEHOLDER void ompt_mutex_wait(void)
-{
- // This function is a placeholder used to represent the OpenMP context of
- // threads waiting for a mutex in the OpenMP runtime. It is not meant
- // to be invoked.
- assert(0);
-}
-
-#ifdef __cplusplus
-};
-#endif
-
-
-/*****************************************************************************
- * compatability
- ****************************************************************************/
-
-OMPT_API_ROUTINE int ompt_get_ompt_version()
-{
- return OMPT_VERSION;
-}
-
-
-
-/*****************************************************************************
- * application-facing API
- ****************************************************************************/
-
-
-/*----------------------------------------------------------------------------
- | control
- ---------------------------------------------------------------------------*/
-
-_OMP_EXTERN void ompt_control(uint64_t command, uint64_t modifier)
-{
- if (ompt_enabled && ompt_callbacks.ompt_callback(ompt_event_control)) {
- ompt_callbacks.ompt_callback(ompt_event_control)(command, modifier);
- }
-}
-
-
-
-/*****************************************************************************
- * API inquiry for tool
- ****************************************************************************/
-
-static ompt_interface_fn_t ompt_fn_lookup(const char *s)
-{
-
-#define ompt_interface_fn(fn) \
- if (strcmp(s, #fn) == 0) return (ompt_interface_fn_t) fn;
-
- FOREACH_OMPT_INQUIRY_FN(ompt_interface_fn)
-
- FOREACH_OMPT_PLACEHOLDER_FN(ompt_interface_fn)
-
- return (ompt_interface_fn_t) 0;
-}
Copied: openmp/trunk/runtime/src/ompt-general.cpp (from r289725, openmp/trunk/runtime/src/ompt-general.c)
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/ompt-general.cpp?p2=openmp/trunk/runtime/src/ompt-general.cpp&p1=openmp/trunk/runtime/src/ompt-general.c&r1=289725&r2=289732&rev=289732&view=diff
==============================================================================
--- openmp/trunk/runtime/src/ompt-general.c (original)
+++ openmp/trunk/runtime/src/ompt-general.cpp Wed Dec 14 16:39:11 2016
@@ -15,7 +15,7 @@
* ompt include files
****************************************************************************/
-#include "ompt-specific.c"
+#include "ompt-specific.cpp"
Removed: openmp/trunk/runtime/src/ompt-specific.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/ompt-specific.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/ompt-specific.c (original)
+++ openmp/trunk/runtime/src/ompt-specific.c (removed)
@@ -1,337 +0,0 @@
-//******************************************************************************
-// include files
-//******************************************************************************
-
-#include "kmp.h"
-#include "ompt-internal.h"
-#include "ompt-specific.h"
-
-//******************************************************************************
-// macros
-//******************************************************************************
-
-#define GTID_TO_OMPT_THREAD_ID(id) ((ompt_thread_id_t) (id >=0) ? id + 1: 0)
-
-#define LWT_FROM_TEAM(team) (team)->t.ompt_serialized_team_info;
-
-#define OMPT_THREAD_ID_BITS 16
-
-// 2013 08 24 - John Mellor-Crummey
-// ideally, a thread should assign its own ids based on thread private data.
-// however, the way the intel runtime reinitializes thread data structures
-// when it creates teams makes it difficult to maintain persistent thread
-// data. using a shared variable instead is simple. I leave it to intel to
-// sort out how to implement a higher performance version in their runtime.
-
-// when using fetch_and_add to generate the IDs, there isn't any reason to waste
-// bits for thread id.
-#if 0
-#define NEXT_ID(id_ptr,tid) \
- ((KMP_TEST_THEN_INC64(id_ptr) << OMPT_THREAD_ID_BITS) | (tid))
-#else
-#define NEXT_ID(id_ptr,tid) (KMP_TEST_THEN_INC64((volatile kmp_int64 *)id_ptr))
-#endif
-
-//******************************************************************************
-// private operations
-//******************************************************************************
-
-//----------------------------------------------------------
-// traverse the team and task hierarchy
-// note: __ompt_get_teaminfo and __ompt_get_taskinfo
-// traverse the hierarchy similarly and need to be
-// kept consistent
-//----------------------------------------------------------
-
-ompt_team_info_t *
-__ompt_get_teaminfo(int depth, int *size)
-{
- kmp_info_t *thr = ompt_get_thread();
-
- if (thr) {
- kmp_team *team = thr->th.th_team;
- if (team == NULL) return NULL;
-
- ompt_lw_taskteam_t *lwt = LWT_FROM_TEAM(team);
-
- while(depth > 0) {
- // next lightweight team (if any)
- if (lwt) lwt = lwt->parent;
-
- // next heavyweight team (if any) after
- // lightweight teams are exhausted
- if (!lwt && team) {
- team=team->t.t_parent;
- if (team) {
- lwt = LWT_FROM_TEAM(team);
- }
- }
-
- depth--;
- }
-
- if (lwt) {
- // lightweight teams have one task
- if (size) *size = 1;
-
- // return team info for lightweight team
- return &lwt->ompt_team_info;
- } else if (team) {
- // extract size from heavyweight team
- if (size) *size = team->t.t_nproc;
-
- // return team info for heavyweight team
- return &team->t.ompt_team_info;
- }
- }
-
- return NULL;
-}
-
-
-ompt_task_info_t *
-__ompt_get_taskinfo(int depth)
-{
- ompt_task_info_t *info = NULL;
- kmp_info_t *thr = ompt_get_thread();
-
- if (thr) {
- kmp_taskdata_t *taskdata = thr->th.th_current_task;
- ompt_lw_taskteam_t *lwt = LWT_FROM_TEAM(taskdata->td_team);
-
- while (depth > 0) {
- // next lightweight team (if any)
- if (lwt) lwt = lwt->parent;
-
- // next heavyweight team (if any) after
- // lightweight teams are exhausted
- if (!lwt && taskdata) {
- taskdata = taskdata->td_parent;
- if (taskdata) {
- lwt = LWT_FROM_TEAM(taskdata->td_team);
- }
- }
- depth--;
- }
-
- if (lwt) {
- info = &lwt->ompt_task_info;
- } else if (taskdata) {
- info = &taskdata->ompt_task_info;
- }
- }
-
- return info;
-}
-
-
-
-//******************************************************************************
-// interface operations
-//******************************************************************************
-
-//----------------------------------------------------------
-// thread support
-//----------------------------------------------------------
-
-ompt_parallel_id_t
-__ompt_thread_id_new()
-{
- static uint64_t ompt_thread_id = 1;
- return NEXT_ID(&ompt_thread_id, 0);
-}
-
-void
-__ompt_thread_begin(ompt_thread_type_t thread_type, int gtid)
-{
- ompt_callbacks.ompt_callback(ompt_event_thread_begin)(
- thread_type, GTID_TO_OMPT_THREAD_ID(gtid));
-}
-
-
-void
-__ompt_thread_end(ompt_thread_type_t thread_type, int gtid)
-{
- ompt_callbacks.ompt_callback(ompt_event_thread_end)(
- thread_type, GTID_TO_OMPT_THREAD_ID(gtid));
-}
-
-
-ompt_thread_id_t
-__ompt_get_thread_id_internal()
-{
- // FIXME
- // until we have a better way of assigning ids, use __kmp_get_gtid
- // since the return value might be negative, we need to test that before
- // assigning it to an ompt_thread_id_t, which is unsigned.
- int id = __kmp_get_gtid();
- assert(id >= 0);
-
- return GTID_TO_OMPT_THREAD_ID(id);
-}
-
-//----------------------------------------------------------
-// state support
-//----------------------------------------------------------
-
-void
-__ompt_thread_assign_wait_id(void *variable)
-{
- int gtid = __kmp_gtid_get_specific();
- kmp_info_t *ti = ompt_get_thread_gtid(gtid);
-
- ti->th.ompt_thread_info.wait_id = (ompt_wait_id_t) variable;
-}
-
-ompt_state_t
-__ompt_get_state_internal(ompt_wait_id_t *ompt_wait_id)
-{
- kmp_info_t *ti = ompt_get_thread();
-
- if (ti) {
- if (ompt_wait_id)
- *ompt_wait_id = ti->th.ompt_thread_info.wait_id;
- return ti->th.ompt_thread_info.state;
- }
- return ompt_state_undefined;
-}
-
-//----------------------------------------------------------
-// idle frame support
-//----------------------------------------------------------
-
-void *
-__ompt_get_idle_frame_internal(void)
-{
- kmp_info_t *ti = ompt_get_thread();
- return ti ? ti->th.ompt_thread_info.idle_frame : NULL;
-}
-
-
-//----------------------------------------------------------
-// parallel region support
-//----------------------------------------------------------
-
-ompt_parallel_id_t
-__ompt_parallel_id_new(int gtid)
-{
- static uint64_t ompt_parallel_id = 1;
- return gtid >= 0 ? NEXT_ID(&ompt_parallel_id, gtid) : 0;
-}
-
-
-void *
-__ompt_get_parallel_function_internal(int depth)
-{
- ompt_team_info_t *info = __ompt_get_teaminfo(depth, NULL);
- void *function = info ? info->microtask : NULL;
- return function;
-}
-
-
-ompt_parallel_id_t
-__ompt_get_parallel_id_internal(int depth)
-{
- ompt_team_info_t *info = __ompt_get_teaminfo(depth, NULL);
- ompt_parallel_id_t id = info ? info->parallel_id : 0;
- return id;
-}
-
-
-int
-__ompt_get_parallel_team_size_internal(int depth)
-{
- // initialize the return value with the error value.
- // if there is a team at the specified depth, the default
- // value will be overwritten the size of that team.
- int size = -1;
- (void) __ompt_get_teaminfo(depth, &size);
- return size;
-}
-
-
-//----------------------------------------------------------
-// lightweight task team support
-//----------------------------------------------------------
-
-void
-__ompt_lw_taskteam_init(ompt_lw_taskteam_t *lwt, kmp_info_t *thr,
- int gtid, void *microtask,
- ompt_parallel_id_t ompt_pid)
-{
- lwt->ompt_team_info.parallel_id = ompt_pid;
- lwt->ompt_team_info.microtask = microtask;
- lwt->ompt_task_info.task_id = 0;
- lwt->ompt_task_info.frame.reenter_runtime_frame = NULL;
- lwt->ompt_task_info.frame.exit_runtime_frame = NULL;
- lwt->ompt_task_info.function = NULL;
- lwt->parent = 0;
-}
-
-
-void
-__ompt_lw_taskteam_link(ompt_lw_taskteam_t *lwt, kmp_info_t *thr)
-{
- ompt_lw_taskteam_t *my_parent = thr->th.th_team->t.ompt_serialized_team_info;
- lwt->parent = my_parent;
- thr->th.th_team->t.ompt_serialized_team_info = lwt;
-}
-
-
-ompt_lw_taskteam_t *
-__ompt_lw_taskteam_unlink(kmp_info_t *thr)
-{
- ompt_lw_taskteam_t *lwtask = thr->th.th_team->t.ompt_serialized_team_info;
- if (lwtask) thr->th.th_team->t.ompt_serialized_team_info = lwtask->parent;
- return lwtask;
-}
-
-
-//----------------------------------------------------------
-// task support
-//----------------------------------------------------------
-
-ompt_task_id_t
-__ompt_task_id_new(int gtid)
-{
- static uint64_t ompt_task_id = 1;
- return NEXT_ID(&ompt_task_id, gtid);
-}
-
-
-ompt_task_id_t
-__ompt_get_task_id_internal(int depth)
-{
- ompt_task_info_t *info = __ompt_get_taskinfo(depth);
- ompt_task_id_t task_id = info ? info->task_id : 0;
- return task_id;
-}
-
-
-void *
-__ompt_get_task_function_internal(int depth)
-{
- ompt_task_info_t *info = __ompt_get_taskinfo(depth);
- void *function = info ? info->function : NULL;
- return function;
-}
-
-
-ompt_frame_t *
-__ompt_get_task_frame_internal(int depth)
-{
- ompt_task_info_t *info = __ompt_get_taskinfo(depth);
- ompt_frame_t *frame = info ? frame = &info->frame : NULL;
- return frame;
-}
-
-
-//----------------------------------------------------------
-// team support
-//----------------------------------------------------------
-
-void
-__ompt_team_assign_id(kmp_team_t *team, ompt_parallel_id_t ompt_pid)
-{
- team->t.ompt_team_info.parallel_id = ompt_pid;
-}
Removed: openmp/trunk/runtime/src/tsan_annotations.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/tsan_annotations.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/tsan_annotations.c (original)
+++ openmp/trunk/runtime/src/tsan_annotations.c (removed)
@@ -1,63 +0,0 @@
-/*
- * tsan_annotations.c -- ThreadSanitizer annotations to support data
- * race detection in OpenMP programs.
- */
-
-
-//===----------------------------------------------------------------------===//
-//
-// 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 "tsan_annotations.h"
-
-#include <stdio.h>
-
-typedef unsigned long uptr;
-typedef signed long sptr;
-
-extern "C" __attribute__((weak)) void AnnotateHappensBefore(const char *f, int l, uptr addr) {}
-extern "C" __attribute__((weak)) void AnnotateHappensAfter(const char *f, int l, uptr addr) {}
-extern "C" __attribute__((weak)) void AnnotateCondVarSignal(const char *f, int l, uptr cv) {}
-extern "C" __attribute__((weak)) void AnnotateCondVarSignalAll(const char *f, int l, uptr cv) {}
-extern "C" __attribute__((weak)) void AnnotateMutexIsNotPHB(const char *f, int l, uptr mu) {}
-extern "C" __attribute__((weak)) void AnnotateCondVarWait(const char *f, int l, uptr cv, uptr lock) {}
-extern "C" __attribute__((weak)) void AnnotateRWLockCreate(const char *f, int l, uptr m) {}
-extern "C" __attribute__((weak)) void AnnotateRWLockCreateStatic(const char *f, int l, uptr m) {}
-extern "C" __attribute__((weak)) void AnnotateRWLockDestroy(const char *f, int l, uptr m) {}
-extern "C" __attribute__((weak)) void AnnotateRWLockAcquired(const char *f, int l, uptr m, uptr is_w) {}
-extern "C" __attribute__((weak)) void AnnotateRWLockReleased(const char *f, int l, uptr m, uptr is_w) {}
-extern "C" __attribute__((weak)) void AnnotateTraceMemory(const char *f, int l, uptr mem) {}
-extern "C" __attribute__((weak)) void AnnotateFlushState(const char *f, int l) {}
-extern "C" __attribute__((weak)) void AnnotateNewMemory(const char *f, int l, uptr mem, uptr size) {}
-extern "C" __attribute__((weak)) void AnnotateNoOp(const char *f, int l, uptr mem) {}
-extern "C" __attribute__((weak)) void AnnotateFlushExpectedRaces(const char *f, int l) {}
-extern "C" __attribute__((weak)) void AnnotateEnableRaceDetection( const char *f, int l, int enable) {}
-extern "C" __attribute__((weak)) void AnnotateMutexIsUsedAsCondVar( const char *f, int l, uptr mu) {}
-extern "C" __attribute__((weak)) void AnnotatePCQGet( const char *f, int l, uptr pcq) {}
-extern "C" __attribute__((weak)) void AnnotatePCQPut( const char *f, int l, uptr pcq) {}
-extern "C" __attribute__((weak)) void AnnotatePCQDestroy( const char *f, int l, uptr pcq) {}
-extern "C" __attribute__((weak)) void AnnotatePCQCreate( const char *f, int l, uptr pcq) {}
-extern "C" __attribute__((weak)) void AnnotateExpectRace( const char *f, int l, uptr mem, char *desc) {}
-extern "C" __attribute__((weak)) void AnnotateBenignRaceSized( const char *f, int l, uptr mem, uptr size, char *desc) {}
-extern "C" __attribute__((weak)) void AnnotateBenignRace( const char *f, int l, uptr mem, char *desc) {}
-extern "C" __attribute__((weak)) void AnnotateIgnoreReadsBegin(const char *f, int l) {}
-extern "C" __attribute__((weak)) void AnnotateIgnoreReadsEnd(const char *f, int l) {}
-extern "C" __attribute__((weak)) void AnnotateIgnoreWritesBegin(const char *f, int l) {}
-extern "C" __attribute__((weak)) void AnnotateIgnoreWritesEnd(const char *f, int l) {}
-extern "C" __attribute__((weak)) void AnnotateIgnoreSyncBegin(const char *f, int l) {}
-extern "C" __attribute__((weak)) void AnnotateIgnoreSyncEnd(const char *f, int l) {}
-extern "C" __attribute__((weak)) void AnnotatePublishMemoryRange( const char *f, int l, uptr addr, uptr size) {}
-extern "C" __attribute__((weak)) void AnnotateUnpublishMemoryRange( const char *f, int l, uptr addr, uptr size) {}
-extern "C" __attribute__((weak)) void AnnotateThreadName( const char *f, int l, char *name) {}
-extern "C" __attribute__((weak)) void WTFAnnotateHappensBefore(const char *f, int l, uptr addr) {}
-extern "C" __attribute__((weak)) void WTFAnnotateHappensAfter(const char *f, int l, uptr addr) {}
-extern "C" __attribute__((weak)) void WTFAnnotateBenignRaceSized( const char *f, int l, uptr mem, uptr sz, char *desc) {}
-extern "C" __attribute__((weak)) int RunningOnValgrind() {return 0;}
-extern "C" __attribute__((weak)) double ValgrindSlowdown(void) {return 0;}
-extern "C" __attribute__((weak)) const char __attribute__((weak))* ThreadSanitizerQuery(const char *query) {return 0;}
-extern "C" __attribute__((weak)) void AnnotateMemoryIsInitialized(const char *f, int l, uptr mem, uptr sz) {}
Removed: openmp/trunk/runtime/src/z_Linux_util.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/z_Linux_util.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/z_Linux_util.c (original)
+++ openmp/trunk/runtime/src/z_Linux_util.c (removed)
@@ -1,2612 +0,0 @@
-/*
- * z_Linux_util.c -- platform specific routines.
- */
-
-
-//===----------------------------------------------------------------------===//
-//
-// 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_wrapper_getpid.h"
-#include "kmp_itt.h"
-#include "kmp_str.h"
-#include "kmp_i18n.h"
-#include "kmp_lock.h"
-#include "kmp_io.h"
-#include "kmp_stats.h"
-#include "kmp_wait_release.h"
-#include "kmp_affinity.h"
-
-#if !KMP_OS_FREEBSD && !KMP_OS_NETBSD
-# include <alloca.h>
-#endif
-#include <unistd.h>
-#include <math.h> // HUGE_VAL.
-#include <sys/time.h>
-#include <sys/times.h>
-#include <sys/resource.h>
-#include <sys/syscall.h>
-
-#if KMP_OS_LINUX && !KMP_OS_CNK
-# include <sys/sysinfo.h>
-# if KMP_USE_FUTEX
-// We should really include <futex.h>, but that causes compatibility problems on different
-// Linux* OS distributions that either require that you include (or break when you try to include)
-// <pci/types.h>.
-// Since all we need is the two macros below (which are part of the kernel ABI, so can't change)
-// we just define the constants here and don't include <futex.h>
-# ifndef FUTEX_WAIT
-# define FUTEX_WAIT 0
-# endif
-# ifndef FUTEX_WAKE
-# define FUTEX_WAKE 1
-# endif
-# endif
-#elif KMP_OS_DARWIN
-# include <sys/sysctl.h>
-# include <mach/mach.h>
-#elif KMP_OS_FREEBSD
-# include <pthread_np.h>
-#endif
-
-#include <dirent.h>
-#include <ctype.h>
-#include <fcntl.h>
-
-#include "tsan_annotations.h"
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-struct kmp_sys_timer {
- struct timespec start;
-};
-
-// Convert timespec to nanoseconds.
-#define TS2NS(timespec) (((timespec).tv_sec * 1e9) + (timespec).tv_nsec)
-
-static struct kmp_sys_timer __kmp_sys_timer_data;
-
-#if KMP_HANDLE_SIGNALS
- typedef void (* sig_func_t )( int );
- STATIC_EFI2_WORKAROUND struct sigaction __kmp_sighldrs[ NSIG ];
- static sigset_t __kmp_sigset;
-#endif
-
-static int __kmp_init_runtime = FALSE;
-
-static int __kmp_fork_count = 0;
-
-static pthread_condattr_t __kmp_suspend_cond_attr;
-static pthread_mutexattr_t __kmp_suspend_mutex_attr;
-
-static kmp_cond_align_t __kmp_wait_cv;
-static kmp_mutex_align_t __kmp_wait_mx;
-
-double __kmp_ticks_per_nsec;
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-#ifdef DEBUG_SUSPEND
-static void
-__kmp_print_cond( char *buffer, kmp_cond_align_t *cond )
-{
- KMP_SNPRINTF( buffer, 128, "(cond (lock (%ld, %d)), (descr (%p)))",
- cond->c_cond.__c_lock.__status, cond->c_cond.__c_lock.__spinlock,
- cond->c_cond.__c_waiting );
-}
-#endif
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-#if ( KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED)
-
-/*
- * Affinity support
- */
-
-void
-__kmp_affinity_bind_thread( int which )
-{
- KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
- "Illegal set affinity operation when not capable");
-
- kmp_affin_mask_t *mask;
- KMP_CPU_ALLOC_ON_STACK(mask);
- KMP_CPU_ZERO(mask);
- KMP_CPU_SET(which, mask);
- __kmp_set_system_affinity(mask, TRUE);
- KMP_CPU_FREE_FROM_STACK(mask);
-}
-
-/*
- * Determine if we can access affinity functionality on this version of
- * Linux* OS by checking __NR_sched_{get,set}affinity system calls, and set
- * __kmp_affin_mask_size to the appropriate value (0 means not capable).
- */
-void
-__kmp_affinity_determine_capable(const char *env_var)
-{
- //
- // Check and see if the OS supports thread affinity.
- //
-
-# define KMP_CPU_SET_SIZE_LIMIT (1024*1024)
-
- int gCode;
- int sCode;
- unsigned char *buf;
- buf = ( unsigned char * ) KMP_INTERNAL_MALLOC( KMP_CPU_SET_SIZE_LIMIT );
-
- // If Linux* OS:
- // If the syscall fails or returns a suggestion for the size,
- // then we don't have to search for an appropriate size.
- gCode = syscall( __NR_sched_getaffinity, 0, KMP_CPU_SET_SIZE_LIMIT, buf );
- KA_TRACE(30, ( "__kmp_affinity_determine_capable: "
- "initial getaffinity call returned %d errno = %d\n",
- gCode, errno));
-
- //if ((gCode < 0) && (errno == ENOSYS))
- if (gCode < 0) {
- //
- // System call not supported
- //
- if (__kmp_affinity_verbose || (__kmp_affinity_warnings
- && (__kmp_affinity_type != affinity_none)
- && (__kmp_affinity_type != affinity_default)
- && (__kmp_affinity_type != affinity_disabled))) {
- int error = errno;
- kmp_msg_t err_code = KMP_ERR( error );
- __kmp_msg(
- kmp_ms_warning,
- KMP_MSG( GetAffSysCallNotSupported, env_var ),
- err_code,
- __kmp_msg_null
- );
- if (__kmp_generate_warnings == kmp_warnings_off) {
- __kmp_str_free(&err_code.str);
- }
- }
- KMP_AFFINITY_DISABLE();
- KMP_INTERNAL_FREE(buf);
- return;
- }
- if (gCode > 0) { // Linux* OS only
- // The optimal situation: the OS returns the size of the buffer
- // it expects.
- //
- // A verification of correct behavior is that Isetaffinity on a NULL
- // buffer with the same size fails with errno set to EFAULT.
- sCode = syscall( __NR_sched_setaffinity, 0, gCode, NULL );
- KA_TRACE(30, ( "__kmp_affinity_determine_capable: "
- "setaffinity for mask size %d returned %d errno = %d\n",
- gCode, sCode, errno));
- if (sCode < 0) {
- if (errno == ENOSYS) {
- if (__kmp_affinity_verbose || (__kmp_affinity_warnings
- && (__kmp_affinity_type != affinity_none)
- && (__kmp_affinity_type != affinity_default)
- && (__kmp_affinity_type != affinity_disabled))) {
- int error = errno;
- kmp_msg_t err_code = KMP_ERR( error );
- __kmp_msg(
- kmp_ms_warning,
- KMP_MSG( SetAffSysCallNotSupported, env_var ),
- err_code,
- __kmp_msg_null
- );
- if (__kmp_generate_warnings == kmp_warnings_off) {
- __kmp_str_free(&err_code.str);
- }
- }
- KMP_AFFINITY_DISABLE();
- KMP_INTERNAL_FREE(buf);
- }
- if (errno == EFAULT) {
- KMP_AFFINITY_ENABLE(gCode);
- KA_TRACE(10, ( "__kmp_affinity_determine_capable: "
- "affinity supported (mask size %d)\n",
- (int)__kmp_affin_mask_size));
- KMP_INTERNAL_FREE(buf);
- return;
- }
- }
- }
-
- //
- // Call the getaffinity system call repeatedly with increasing set sizes
- // until we succeed, or reach an upper bound on the search.
- //
- KA_TRACE(30, ( "__kmp_affinity_determine_capable: "
- "searching for proper set size\n"));
- int size;
- for (size = 1; size <= KMP_CPU_SET_SIZE_LIMIT; size *= 2) {
- gCode = syscall( __NR_sched_getaffinity, 0, size, buf );
- KA_TRACE(30, ( "__kmp_affinity_determine_capable: "
- "getaffinity for mask size %d returned %d errno = %d\n", size,
- gCode, errno));
-
- if (gCode < 0) {
- if ( errno == ENOSYS )
- {
- //
- // We shouldn't get here
- //
- KA_TRACE(30, ( "__kmp_affinity_determine_capable: "
- "inconsistent OS call behavior: errno == ENOSYS for mask size %d\n",
- size));
- if (__kmp_affinity_verbose || (__kmp_affinity_warnings
- && (__kmp_affinity_type != affinity_none)
- && (__kmp_affinity_type != affinity_default)
- && (__kmp_affinity_type != affinity_disabled))) {
- int error = errno;
- kmp_msg_t err_code = KMP_ERR( error );
- __kmp_msg(
- kmp_ms_warning,
- KMP_MSG( GetAffSysCallNotSupported, env_var ),
- err_code,
- __kmp_msg_null
- );
- if (__kmp_generate_warnings == kmp_warnings_off) {
- __kmp_str_free(&err_code.str);
- }
- }
- KMP_AFFINITY_DISABLE();
- KMP_INTERNAL_FREE(buf);
- return;
- }
- continue;
- }
-
- sCode = syscall( __NR_sched_setaffinity, 0, gCode, NULL );
- KA_TRACE(30, ( "__kmp_affinity_determine_capable: "
- "setaffinity for mask size %d returned %d errno = %d\n",
- gCode, sCode, errno));
- if (sCode < 0) {
- if (errno == ENOSYS) { // Linux* OS only
- //
- // We shouldn't get here
- //
- KA_TRACE(30, ( "__kmp_affinity_determine_capable: "
- "inconsistent OS call behavior: errno == ENOSYS for mask size %d\n",
- size));
- if (__kmp_affinity_verbose || (__kmp_affinity_warnings
- && (__kmp_affinity_type != affinity_none)
- && (__kmp_affinity_type != affinity_default)
- && (__kmp_affinity_type != affinity_disabled))) {
- int error = errno;
- kmp_msg_t err_code = KMP_ERR( error );
- __kmp_msg(
- kmp_ms_warning,
- KMP_MSG( SetAffSysCallNotSupported, env_var ),
- err_code,
- __kmp_msg_null
- );
- if (__kmp_generate_warnings == kmp_warnings_off) {
- __kmp_str_free(&err_code.str);
- }
- }
- KMP_AFFINITY_DISABLE();
- KMP_INTERNAL_FREE(buf);
- return;
- }
- if (errno == EFAULT) {
- KMP_AFFINITY_ENABLE(gCode);
- KA_TRACE(10, ( "__kmp_affinity_determine_capable: "
- "affinity supported (mask size %d)\n",
- (int)__kmp_affin_mask_size));
- KMP_INTERNAL_FREE(buf);
- return;
- }
- }
- }
- //int error = errno; // save uncaught error code
- KMP_INTERNAL_FREE(buf);
- // errno = error; // restore uncaught error code, will be printed at the next KMP_WARNING below
-
- //
- // Affinity is not supported
- //
- KMP_AFFINITY_DISABLE();
- KA_TRACE(10, ( "__kmp_affinity_determine_capable: "
- "cannot determine mask size - affinity not supported\n"));
- if (__kmp_affinity_verbose || (__kmp_affinity_warnings
- && (__kmp_affinity_type != affinity_none)
- && (__kmp_affinity_type != affinity_default)
- && (__kmp_affinity_type != affinity_disabled))) {
- KMP_WARNING( AffCantGetMaskSize, env_var );
- }
-}
-
-#endif // KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-#if KMP_USE_FUTEX
-
-int
-__kmp_futex_determine_capable()
-{
- int loc = 0;
- int rc = syscall( __NR_futex, &loc, FUTEX_WAKE, 1, NULL, NULL, 0 );
- int retval = ( rc == 0 ) || ( errno != ENOSYS );
-
- KA_TRACE(10, ( "__kmp_futex_determine_capable: rc = %d errno = %d\n", rc,
- errno ) );
- KA_TRACE(10, ( "__kmp_futex_determine_capable: futex syscall%s supported\n",
- retval ? "" : " not" ) );
-
- return retval;
-}
-
-#endif // KMP_USE_FUTEX
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-#if (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (! KMP_ASM_INTRINS)
-/*
- * Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to
- * use compare_and_store for these routines
- */
-
-kmp_int8
-__kmp_test_then_or8( volatile kmp_int8 *p, kmp_int8 d )
-{
- kmp_int8 old_value, new_value;
-
- old_value = TCR_1( *p );
- new_value = old_value | d;
-
- while ( ! KMP_COMPARE_AND_STORE_REL8 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_1( *p );
- new_value = old_value | d;
- }
- return old_value;
-}
-
-kmp_int8
-__kmp_test_then_and8( volatile kmp_int8 *p, kmp_int8 d )
-{
- kmp_int8 old_value, new_value;
-
- old_value = TCR_1( *p );
- new_value = old_value & d;
-
- while ( ! KMP_COMPARE_AND_STORE_REL8 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_1( *p );
- new_value = old_value & d;
- }
- return old_value;
-}
-
-kmp_int32
-__kmp_test_then_or32( volatile kmp_int32 *p, kmp_int32 d )
-{
- kmp_int32 old_value, new_value;
-
- old_value = TCR_4( *p );
- new_value = old_value | d;
-
- while ( ! KMP_COMPARE_AND_STORE_REL32 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_4( *p );
- new_value = old_value | d;
- }
- return old_value;
-}
-
-kmp_int32
-__kmp_test_then_and32( volatile kmp_int32 *p, kmp_int32 d )
-{
- kmp_int32 old_value, new_value;
-
- old_value = TCR_4( *p );
- new_value = old_value & d;
-
- while ( ! KMP_COMPARE_AND_STORE_REL32 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_4( *p );
- new_value = old_value & d;
- }
- return old_value;
-}
-
-# if KMP_ARCH_X86 || KMP_ARCH_PPC64 || (KMP_OS_LINUX && KMP_ARCH_AARCH64)
-kmp_int8
-__kmp_test_then_add8( volatile kmp_int8 *p, kmp_int8 d )
-{
- kmp_int8 old_value, new_value;
-
- old_value = TCR_1( *p );
- new_value = old_value + d;
-
- while ( ! KMP_COMPARE_AND_STORE_REL8 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_1( *p );
- new_value = old_value + d;
- }
- return old_value;
-}
-
-kmp_int64
-__kmp_test_then_add64( volatile kmp_int64 *p, kmp_int64 d )
-{
- kmp_int64 old_value, new_value;
-
- old_value = TCR_8( *p );
- new_value = old_value + d;
-
- while ( ! KMP_COMPARE_AND_STORE_REL64 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_8( *p );
- new_value = old_value + d;
- }
- return old_value;
-}
-# endif /* KMP_ARCH_X86 || KMP_ARCH_PPC64 || (KMP_OS_LINUX && KMP_ARCH_AARCH64) */
-
-kmp_int64
-__kmp_test_then_or64( volatile kmp_int64 *p, kmp_int64 d )
-{
- kmp_int64 old_value, new_value;
-
- old_value = TCR_8( *p );
- new_value = old_value | d;
- while ( ! KMP_COMPARE_AND_STORE_REL64 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_8( *p );
- new_value = old_value | d;
- }
- return old_value;
-}
-
-kmp_int64
-__kmp_test_then_and64( volatile kmp_int64 *p, kmp_int64 d )
-{
- kmp_int64 old_value, new_value;
-
- old_value = TCR_8( *p );
- new_value = old_value & d;
- while ( ! KMP_COMPARE_AND_STORE_REL64 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_8( *p );
- new_value = old_value & d;
- }
- return old_value;
-}
-
-#endif /* (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (! KMP_ASM_INTRINS) */
-
-void
-__kmp_terminate_thread( int gtid )
-{
- int status;
- kmp_info_t *th = __kmp_threads[ gtid ];
-
- if ( !th ) return;
-
- #ifdef KMP_CANCEL_THREADS
- KA_TRACE( 10, ("__kmp_terminate_thread: kill (%d)\n", gtid ) );
- status = pthread_cancel( th->th.th_info.ds.ds_thread );
- if ( status != 0 && status != ESRCH ) {
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( CantTerminateWorkerThread ),
- KMP_ERR( status ),
- __kmp_msg_null
- );
- }; // if
- #endif
- __kmp_yield( TRUE );
-} //
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-/*
- * Set thread stack info according to values returned by
- * pthread_getattr_np().
- * If values are unreasonable, assume call failed and use
- * incremental stack refinement method instead.
- * Returns TRUE if the stack parameters could be determined exactly,
- * FALSE if incremental refinement is necessary.
- */
-static kmp_int32
-__kmp_set_stack_info( int gtid, kmp_info_t *th )
-{
- int stack_data;
-#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD
- /* Linux* OS only -- no pthread_getattr_np support on OS X* */
- pthread_attr_t attr;
- int status;
- size_t size = 0;
- void * addr = 0;
-
- /* Always do incremental stack refinement for ubermaster threads since the initial
- thread stack range can be reduced by sibling thread creation so pthread_attr_getstack
- may cause thread gtid aliasing */
- if ( ! KMP_UBER_GTID(gtid) ) {
-
- /* Fetch the real thread attributes */
- status = pthread_attr_init( &attr );
- KMP_CHECK_SYSFAIL( "pthread_attr_init", status );
-#if KMP_OS_FREEBSD || KMP_OS_NETBSD
- status = pthread_attr_get_np( pthread_self(), &attr );
- KMP_CHECK_SYSFAIL( "pthread_attr_get_np", status );
-#else
- status = pthread_getattr_np( pthread_self(), &attr );
- KMP_CHECK_SYSFAIL( "pthread_getattr_np", status );
-#endif
- status = pthread_attr_getstack( &attr, &addr, &size );
- KMP_CHECK_SYSFAIL( "pthread_attr_getstack", status );
- KA_TRACE( 60, ( "__kmp_set_stack_info: T#%d pthread_attr_getstack returned size: %lu, "
- "low addr: %p\n",
- gtid, size, addr ));
-
- status = pthread_attr_destroy( &attr );
- KMP_CHECK_SYSFAIL( "pthread_attr_destroy", status );
- }
-
- if ( size != 0 && addr != 0 ) { /* was stack parameter determination successful? */
- /* Store the correct base and size */
- TCW_PTR(th->th.th_info.ds.ds_stackbase, (((char *)addr) + size));
- TCW_PTR(th->th.th_info.ds.ds_stacksize, size);
- TCW_4(th->th.th_info.ds.ds_stackgrow, FALSE);
- return TRUE;
- }
-#endif /* KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD */
- /* Use incremental refinement starting from initial conservative estimate */
- TCW_PTR(th->th.th_info.ds.ds_stacksize, 0);
- TCW_PTR(th -> th.th_info.ds.ds_stackbase, &stack_data);
- TCW_4(th->th.th_info.ds.ds_stackgrow, TRUE);
- return FALSE;
-}
-
-static void*
-__kmp_launch_worker( void *thr )
-{
- int status, old_type, old_state;
-#ifdef KMP_BLOCK_SIGNALS
- sigset_t new_set, old_set;
-#endif /* KMP_BLOCK_SIGNALS */
- void *exit_val;
-#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD
- void * volatile padding = 0;
-#endif
- int gtid;
-
- gtid = ((kmp_info_t*)thr) -> th.th_info.ds.ds_gtid;
- __kmp_gtid_set_specific( gtid );
-#ifdef KMP_TDATA_GTID
- __kmp_gtid = gtid;
-#endif
-#if KMP_STATS_ENABLED
- // set __thread local index to point to thread-specific stats
- __kmp_stats_thread_ptr = ((kmp_info_t*)thr)->th.th_stats;
- KMP_START_EXPLICIT_TIMER(OMP_worker_thread_life);
- KMP_SET_THREAD_STATE(IDLE);
- KMP_INIT_PARTITIONED_TIMERS(OMP_idle);
-#endif
-
-#if USE_ITT_BUILD
- __kmp_itt_thread_name( gtid );
-#endif /* USE_ITT_BUILD */
-
-#if KMP_AFFINITY_SUPPORTED
- __kmp_affinity_set_init_mask( gtid, FALSE );
-#endif
-
-#ifdef KMP_CANCEL_THREADS
- status = pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, & old_type );
- KMP_CHECK_SYSFAIL( "pthread_setcanceltype", status );
- /* josh todo: isn't PTHREAD_CANCEL_ENABLE default for newly-created threads? */
- status = pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, & old_state );
- KMP_CHECK_SYSFAIL( "pthread_setcancelstate", status );
-#endif
-
-#if KMP_ARCH_X86 || KMP_ARCH_X86_64
- //
- // Set the FP control regs to be a copy of
- // the parallel initialization thread's.
- //
- __kmp_clear_x87_fpu_status_word();
- __kmp_load_x87_fpu_control_word( &__kmp_init_x87_fpu_control_word );
- __kmp_load_mxcsr( &__kmp_init_mxcsr );
-#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
-
-#ifdef KMP_BLOCK_SIGNALS
- status = sigfillset( & new_set );
- KMP_CHECK_SYSFAIL_ERRNO( "sigfillset", status );
- status = pthread_sigmask( SIG_BLOCK, & new_set, & old_set );
- KMP_CHECK_SYSFAIL( "pthread_sigmask", status );
-#endif /* KMP_BLOCK_SIGNALS */
-
-#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD
- if ( __kmp_stkoffset > 0 && gtid > 0 ) {
- padding = KMP_ALLOCA( gtid * __kmp_stkoffset );
- }
-#endif
-
- KMP_MB();
- __kmp_set_stack_info( gtid, (kmp_info_t*)thr );
-
- __kmp_check_stack_overlap( (kmp_info_t*)thr );
-
- exit_val = __kmp_launch_thread( (kmp_info_t *) thr );
-
-#ifdef KMP_BLOCK_SIGNALS
- status = pthread_sigmask( SIG_SETMASK, & old_set, NULL );
- KMP_CHECK_SYSFAIL( "pthread_sigmask", status );
-#endif /* KMP_BLOCK_SIGNALS */
-
- return exit_val;
-}
-
-#if KMP_USE_MONITOR
-/* The monitor thread controls all of the threads in the complex */
-
-static void*
-__kmp_launch_monitor( void *thr )
-{
- int status, old_type, old_state;
-#ifdef KMP_BLOCK_SIGNALS
- sigset_t new_set;
-#endif /* KMP_BLOCK_SIGNALS */
- struct timespec interval;
- int yield_count;
- int yield_cycles = 0;
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- KA_TRACE( 10, ("__kmp_launch_monitor: #1 launched\n" ) );
-
- /* register us as the monitor thread */
- __kmp_gtid_set_specific( KMP_GTID_MONITOR );
-#ifdef KMP_TDATA_GTID
- __kmp_gtid = KMP_GTID_MONITOR;
-#endif
-
- KMP_MB();
-
-#if USE_ITT_BUILD
- __kmp_itt_thread_ignore(); // Instruct Intel(R) Threading Tools to ignore monitor thread.
-#endif /* USE_ITT_BUILD */
-
- __kmp_set_stack_info( ((kmp_info_t*)thr)->th.th_info.ds.ds_gtid, (kmp_info_t*)thr );
-
- __kmp_check_stack_overlap( (kmp_info_t*)thr );
-
-#ifdef KMP_CANCEL_THREADS
- status = pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, & old_type );
- KMP_CHECK_SYSFAIL( "pthread_setcanceltype", status );
- /* josh todo: isn't PTHREAD_CANCEL_ENABLE default for newly-created threads? */
- status = pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, & old_state );
- KMP_CHECK_SYSFAIL( "pthread_setcancelstate", status );
-#endif
-
- #if KMP_REAL_TIME_FIX
- // This is a potential fix which allows application with real-time scheduling policy work.
- // However, decision about the fix is not made yet, so it is disabled by default.
- { // Are program started with real-time scheduling policy?
- int sched = sched_getscheduler( 0 );
- if ( sched == SCHED_FIFO || sched == SCHED_RR ) {
- // Yes, we are a part of real-time application. Try to increase the priority of the
- // monitor.
- struct sched_param param;
- int max_priority = sched_get_priority_max( sched );
- int rc;
- KMP_WARNING( RealTimeSchedNotSupported );
- sched_getparam( 0, & param );
- if ( param.sched_priority < max_priority ) {
- param.sched_priority += 1;
- rc = sched_setscheduler( 0, sched, & param );
- if ( rc != 0 ) {
- int error = errno;
- kmp_msg_t err_code = KMP_ERR( error );
- __kmp_msg(
- kmp_ms_warning,
- KMP_MSG( CantChangeMonitorPriority ),
- err_code,
- KMP_MSG( MonitorWillStarve ),
- __kmp_msg_null
- );
- if (__kmp_generate_warnings == kmp_warnings_off) {
- __kmp_str_free(&err_code.str);
- }
- }; // if
- } else {
- // We cannot abort here, because number of CPUs may be enough for all the threads,
- // including the monitor thread, so application could potentially work...
- __kmp_msg(
- kmp_ms_warning,
- KMP_MSG( RunningAtMaxPriority ),
- KMP_MSG( MonitorWillStarve ),
- KMP_HNT( RunningAtMaxPriority ),
- __kmp_msg_null
- );
- }; // if
- }; // if
- TCW_4( __kmp_global.g.g_time.dt.t_value, 0 ); // AC: free thread that waits for monitor started
- }
- #endif // KMP_REAL_TIME_FIX
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- if ( __kmp_monitor_wakeups == 1 ) {
- interval.tv_sec = 1;
- interval.tv_nsec = 0;
- } else {
- interval.tv_sec = 0;
- interval.tv_nsec = (KMP_NSEC_PER_SEC / __kmp_monitor_wakeups);
- }
-
- KA_TRACE( 10, ("__kmp_launch_monitor: #2 monitor\n" ) );
-
- if (__kmp_yield_cycle) {
- __kmp_yielding_on = 0; /* Start out with yielding shut off */
- yield_count = __kmp_yield_off_count;
- } else {
- __kmp_yielding_on = 1; /* Yielding is on permanently */
- }
-
- while( ! TCR_4( __kmp_global.g.g_done ) ) {
- struct timespec now;
- struct timeval tval;
-
- /* This thread monitors the state of the system */
-
- KA_TRACE( 15, ( "__kmp_launch_monitor: update\n" ) );
-
- status = gettimeofday( &tval, NULL );
- KMP_CHECK_SYSFAIL_ERRNO( "gettimeofday", status );
- TIMEVAL_TO_TIMESPEC( &tval, &now );
-
- now.tv_sec += interval.tv_sec;
- now.tv_nsec += interval.tv_nsec;
-
- if (now.tv_nsec >= KMP_NSEC_PER_SEC) {
- now.tv_sec += 1;
- now.tv_nsec -= KMP_NSEC_PER_SEC;
- }
-
- status = pthread_mutex_lock( & __kmp_wait_mx.m_mutex );
- KMP_CHECK_SYSFAIL( "pthread_mutex_lock", status );
- // AC: the monitor should not fall asleep if g_done has been set
- if ( !TCR_4(__kmp_global.g.g_done) ) { // check once more under mutex
- status = pthread_cond_timedwait( &__kmp_wait_cv.c_cond, &__kmp_wait_mx.m_mutex, &now );
- if ( status != 0 ) {
- if ( status != ETIMEDOUT && status != EINTR ) {
- KMP_SYSFAIL( "pthread_cond_timedwait", status );
- };
- };
- };
- status = pthread_mutex_unlock( & __kmp_wait_mx.m_mutex );
- KMP_CHECK_SYSFAIL( "pthread_mutex_unlock", status );
-
- if (__kmp_yield_cycle) {
- yield_cycles++;
- if ( (yield_cycles % yield_count) == 0 ) {
- if (__kmp_yielding_on) {
- __kmp_yielding_on = 0; /* Turn it off now */
- yield_count = __kmp_yield_off_count;
- } else {
- __kmp_yielding_on = 1; /* Turn it on now */
- yield_count = __kmp_yield_on_count;
- }
- yield_cycles = 0;
- }
- } else {
- __kmp_yielding_on = 1;
- }
-
- TCW_4( __kmp_global.g.g_time.dt.t_value,
- TCR_4( __kmp_global.g.g_time.dt.t_value ) + 1 );
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
- }
-
- KA_TRACE( 10, ("__kmp_launch_monitor: #3 cleanup\n" ) );
-
-#ifdef KMP_BLOCK_SIGNALS
- status = sigfillset( & new_set );
- KMP_CHECK_SYSFAIL_ERRNO( "sigfillset", status );
- status = pthread_sigmask( SIG_UNBLOCK, & new_set, NULL );
- KMP_CHECK_SYSFAIL( "pthread_sigmask", status );
-#endif /* KMP_BLOCK_SIGNALS */
-
- KA_TRACE( 10, ("__kmp_launch_monitor: #4 finished\n" ) );
-
- if( __kmp_global.g.g_abort != 0 ) {
- /* now we need to terminate the worker threads */
- /* the value of t_abort is the signal we caught */
-
- int gtid;
-
- KA_TRACE( 10, ("__kmp_launch_monitor: #5 terminate sig=%d\n", __kmp_global.g.g_abort ) );
-
- /* terminate the OpenMP worker threads */
- /* TODO this is not valid for sibling threads!!
- * the uber master might not be 0 anymore.. */
- for (gtid = 1; gtid < __kmp_threads_capacity; ++gtid)
- __kmp_terminate_thread( gtid );
-
- __kmp_cleanup();
-
- KA_TRACE( 10, ("__kmp_launch_monitor: #6 raise sig=%d\n", __kmp_global.g.g_abort ) );
-
- if (__kmp_global.g.g_abort > 0)
- raise( __kmp_global.g.g_abort );
-
- }
-
- KA_TRACE( 10, ("__kmp_launch_monitor: #7 exit\n" ) );
-
- return thr;
-}
-#endif // KMP_USE_MONITOR
-
-void
-__kmp_create_worker( int gtid, kmp_info_t *th, size_t stack_size )
-{
- pthread_t handle;
- pthread_attr_t thread_attr;
- int status;
-
-
- th->th.th_info.ds.ds_gtid = gtid;
-
-#if KMP_STATS_ENABLED
- // sets up worker thread stats
- __kmp_acquire_tas_lock(&__kmp_stats_lock, gtid);
-
- // th->th.th_stats is used to transfer thread specific stats-pointer to __kmp_launch_worker
- // So when thread is created (goes into __kmp_launch_worker) it will
- // set it's __thread local pointer to th->th.th_stats
- if(!KMP_UBER_GTID(gtid)) {
- th->th.th_stats = __kmp_stats_list->push_back(gtid);
- } else {
- // For root threads, the __kmp_stats_thread_ptr is set in __kmp_register_root(), so
- // set the th->th.th_stats field to it.
- th->th.th_stats = __kmp_stats_thread_ptr;
- }
- __kmp_release_tas_lock(&__kmp_stats_lock, gtid);
-
-#endif // KMP_STATS_ENABLED
-
- if ( KMP_UBER_GTID(gtid) ) {
- KA_TRACE( 10, ("__kmp_create_worker: uber thread (%d)\n", gtid ) );
- th -> th.th_info.ds.ds_thread = pthread_self();
- __kmp_set_stack_info( gtid, th );
- __kmp_check_stack_overlap( th );
- return;
- }; // if
-
- KA_TRACE( 10, ("__kmp_create_worker: try to create thread (%d)\n", gtid ) );
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
-#ifdef KMP_THREAD_ATTR
- status = pthread_attr_init( &thread_attr );
- if ( status != 0 ) {
- __kmp_msg(kmp_ms_fatal, KMP_MSG( CantInitThreadAttrs ), KMP_ERR( status ), __kmp_msg_null);
- }; // if
- status = pthread_attr_setdetachstate( & thread_attr, PTHREAD_CREATE_JOINABLE );
- if ( status != 0 ) {
- __kmp_msg(kmp_ms_fatal, KMP_MSG( CantSetWorkerState ), KMP_ERR( status ), __kmp_msg_null);
- }; // if
-
- /* Set stack size for this thread now.
- * The multiple of 2 is there because on some machines, requesting an unusual stacksize
- * causes the thread to have an offset before the dummy alloca() takes place to create the
- * offset. Since we want the user to have a sufficient stacksize AND support a stack offset, we
- * alloca() twice the offset so that the upcoming alloca() does not eliminate any premade
- * offset, and also gives the user the stack space they requested for all threads */
- stack_size += gtid * __kmp_stkoffset * 2;
-
- KA_TRACE( 10, ( "__kmp_create_worker: T#%d, default stacksize = %lu bytes, "
- "__kmp_stksize = %lu bytes, final stacksize = %lu bytes\n",
- gtid, KMP_DEFAULT_STKSIZE, __kmp_stksize, stack_size ) );
-
-# ifdef _POSIX_THREAD_ATTR_STACKSIZE
- status = pthread_attr_setstacksize( & thread_attr, stack_size );
-# ifdef KMP_BACKUP_STKSIZE
- if ( status != 0 ) {
- if ( ! __kmp_env_stksize ) {
- stack_size = KMP_BACKUP_STKSIZE + gtid * __kmp_stkoffset;
- __kmp_stksize = KMP_BACKUP_STKSIZE;
- KA_TRACE( 10, ("__kmp_create_worker: T#%d, default stacksize = %lu bytes, "
- "__kmp_stksize = %lu bytes, (backup) final stacksize = %lu "
- "bytes\n",
- gtid, KMP_DEFAULT_STKSIZE, __kmp_stksize, stack_size )
- );
- status = pthread_attr_setstacksize( &thread_attr, stack_size );
- }; // if
- }; // if
-# endif /* KMP_BACKUP_STKSIZE */
- if ( status != 0 ) {
- __kmp_msg(kmp_ms_fatal, KMP_MSG( CantSetWorkerStackSize, stack_size ), KMP_ERR( status ),
- KMP_HNT( ChangeWorkerStackSize ), __kmp_msg_null);
- }; // if
-# endif /* _POSIX_THREAD_ATTR_STACKSIZE */
-
-#endif /* KMP_THREAD_ATTR */
-
- status = pthread_create( & handle, & thread_attr, __kmp_launch_worker, (void *) th );
- if ( status != 0 || ! handle ) { // ??? Why do we check handle??
-#ifdef _POSIX_THREAD_ATTR_STACKSIZE
- if ( status == EINVAL ) {
- __kmp_msg(kmp_ms_fatal, KMP_MSG( CantSetWorkerStackSize, stack_size ), KMP_ERR( status ),
- KMP_HNT( IncreaseWorkerStackSize ), __kmp_msg_null);
- };
- if ( status == ENOMEM ) {
- __kmp_msg(kmp_ms_fatal, KMP_MSG( CantSetWorkerStackSize, stack_size ), KMP_ERR( status ),
- KMP_HNT( DecreaseWorkerStackSize ), __kmp_msg_null);
- };
-#endif /* _POSIX_THREAD_ATTR_STACKSIZE */
- if ( status == EAGAIN ) {
- __kmp_msg(kmp_ms_fatal, KMP_MSG( NoResourcesForWorkerThread ), KMP_ERR( status ),
- KMP_HNT( Decrease_NUM_THREADS ), __kmp_msg_null);
- }; // if
- KMP_SYSFAIL( "pthread_create", status );
- }; // if
-
- th->th.th_info.ds.ds_thread = handle;
-
-#ifdef KMP_THREAD_ATTR
- status = pthread_attr_destroy( & thread_attr );
- if ( status ) {
- kmp_msg_t err_code = KMP_ERR( status );
- __kmp_msg(kmp_ms_warning, KMP_MSG( CantDestroyThreadAttrs ), err_code, __kmp_msg_null);
- if (__kmp_generate_warnings == kmp_warnings_off) {
- __kmp_str_free(&err_code.str);
- }
- }; // if
-#endif /* KMP_THREAD_ATTR */
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- KA_TRACE( 10, ("__kmp_create_worker: done creating thread (%d)\n", gtid ) );
-
-} // __kmp_create_worker
-
-
-#if KMP_USE_MONITOR
-void
-__kmp_create_monitor( kmp_info_t *th )
-{
- pthread_t handle;
- pthread_attr_t thread_attr;
- size_t size;
- int status;
- int auto_adj_size = FALSE;
-
- if( __kmp_dflt_blocktime == KMP_MAX_BLOCKTIME ) {
- // We don't need monitor thread in case of MAX_BLOCKTIME
- KA_TRACE( 10, ("__kmp_create_monitor: skipping monitor thread because of MAX blocktime\n" ) );
- th->th.th_info.ds.ds_tid = 0; // this makes reap_monitor no-op
- th->th.th_info.ds.ds_gtid = 0;
- return;
- }
- KA_TRACE( 10, ("__kmp_create_monitor: try to create monitor\n" ) );
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- th->th.th_info.ds.ds_tid = KMP_GTID_MONITOR;
- th->th.th_info.ds.ds_gtid = KMP_GTID_MONITOR;
- #if KMP_REAL_TIME_FIX
- TCW_4( __kmp_global.g.g_time.dt.t_value, -1 ); // Will use it for synchronization a bit later.
- #else
- TCW_4( __kmp_global.g.g_time.dt.t_value, 0 );
- #endif // KMP_REAL_TIME_FIX
-
- #ifdef KMP_THREAD_ATTR
- if ( __kmp_monitor_stksize == 0 ) {
- __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
- auto_adj_size = TRUE;
- }
- status = pthread_attr_init( &thread_attr );
- if ( status != 0 ) {
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( CantInitThreadAttrs ),
- KMP_ERR( status ),
- __kmp_msg_null
- );
- }; // if
- status = pthread_attr_setdetachstate( & thread_attr, PTHREAD_CREATE_JOINABLE );
- if ( status != 0 ) {
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( CantSetMonitorState ),
- KMP_ERR( status ),
- __kmp_msg_null
- );
- }; // if
-
- #ifdef _POSIX_THREAD_ATTR_STACKSIZE
- status = pthread_attr_getstacksize( & thread_attr, & size );
- KMP_CHECK_SYSFAIL( "pthread_attr_getstacksize", status );
- #else
- size = __kmp_sys_min_stksize;
- #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
- #endif /* KMP_THREAD_ATTR */
-
- if ( __kmp_monitor_stksize == 0 ) {
- __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
- }
- if ( __kmp_monitor_stksize < __kmp_sys_min_stksize ) {
- __kmp_monitor_stksize = __kmp_sys_min_stksize;
- }
-
- KA_TRACE( 10, ( "__kmp_create_monitor: default stacksize = %lu bytes,"
- "requested stacksize = %lu bytes\n",
- size, __kmp_monitor_stksize ) );
-
- retry:
-
- /* Set stack size for this thread now. */
-
- #ifdef _POSIX_THREAD_ATTR_STACKSIZE
- KA_TRACE( 10, ( "__kmp_create_monitor: setting stacksize = %lu bytes,",
- __kmp_monitor_stksize ) );
- status = pthread_attr_setstacksize( & thread_attr, __kmp_monitor_stksize );
- if ( status != 0 ) {
- if ( auto_adj_size ) {
- __kmp_monitor_stksize *= 2;
- goto retry;
- }
- kmp_msg_t err_code = KMP_ERR( status );
- __kmp_msg(
- kmp_ms_warning, // should this be fatal? BB
- KMP_MSG( CantSetMonitorStackSize, (long int) __kmp_monitor_stksize ),
- err_code,
- KMP_HNT( ChangeMonitorStackSize ),
- __kmp_msg_null
- );
- if (__kmp_generate_warnings == kmp_warnings_off) {
- __kmp_str_free(&err_code.str);
- }
- }; // if
- #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
-
- status = pthread_create( &handle, & thread_attr, __kmp_launch_monitor, (void *) th );
-
- if ( status != 0 ) {
- #ifdef _POSIX_THREAD_ATTR_STACKSIZE
- if ( status == EINVAL ) {
- if ( auto_adj_size && ( __kmp_monitor_stksize < (size_t)0x40000000 ) ) {
- __kmp_monitor_stksize *= 2;
- goto retry;
- }
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( CantSetMonitorStackSize, __kmp_monitor_stksize ),
- KMP_ERR( status ),
- KMP_HNT( IncreaseMonitorStackSize ),
- __kmp_msg_null
- );
- }; // if
- if ( status == ENOMEM ) {
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( CantSetMonitorStackSize, __kmp_monitor_stksize ),
- KMP_ERR( status ),
- KMP_HNT( DecreaseMonitorStackSize ),
- __kmp_msg_null
- );
- }; // if
- #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
- if ( status == EAGAIN ) {
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( NoResourcesForMonitorThread ),
- KMP_ERR( status ),
- KMP_HNT( DecreaseNumberOfThreadsInUse ),
- __kmp_msg_null
- );
- }; // if
- KMP_SYSFAIL( "pthread_create", status );
- }; // if
-
- th->th.th_info.ds.ds_thread = handle;
-
- #if KMP_REAL_TIME_FIX
- // Wait for the monitor thread is really started and set its *priority*.
- KMP_DEBUG_ASSERT( sizeof( kmp_uint32 ) == sizeof( __kmp_global.g.g_time.dt.t_value ) );
- __kmp_wait_yield_4(
- (kmp_uint32 volatile *) & __kmp_global.g.g_time.dt.t_value, -1, & __kmp_neq_4, NULL
- );
- #endif // KMP_REAL_TIME_FIX
-
- #ifdef KMP_THREAD_ATTR
- status = pthread_attr_destroy( & thread_attr );
- if ( status != 0 ) {
- kmp_msg_t err_code = KMP_ERR( status );
- __kmp_msg(
- kmp_ms_warning,
- KMP_MSG( CantDestroyThreadAttrs ),
- err_code,
- __kmp_msg_null
- );
- if (__kmp_generate_warnings == kmp_warnings_off) {
- __kmp_str_free(&err_code.str);
- }
- }; // if
- #endif
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- KA_TRACE( 10, ( "__kmp_create_monitor: monitor created %#.8lx\n", th->th.th_info.ds.ds_thread ) );
-
-} // __kmp_create_monitor
-#endif // KMP_USE_MONITOR
-
-void
-__kmp_exit_thread(
- int exit_status
-) {
- pthread_exit( (void *)(intptr_t) exit_status );
-} // __kmp_exit_thread
-
-#if KMP_USE_MONITOR
-void __kmp_resume_monitor();
-
-void
-__kmp_reap_monitor( kmp_info_t *th )
-{
- int status;
- void *exit_val;
-
- KA_TRACE( 10, ("__kmp_reap_monitor: try to reap monitor thread with handle %#.8lx\n",
- th->th.th_info.ds.ds_thread ) );
-
- // If monitor has been created, its tid and gtid should be KMP_GTID_MONITOR.
- // If both tid and gtid are 0, it means the monitor did not ever start.
- // If both tid and gtid are KMP_GTID_DNE, the monitor has been shut down.
- KMP_DEBUG_ASSERT( th->th.th_info.ds.ds_tid == th->th.th_info.ds.ds_gtid );
- if ( th->th.th_info.ds.ds_gtid != KMP_GTID_MONITOR ) {
- KA_TRACE( 10, ("__kmp_reap_monitor: monitor did not start, returning\n") );
- return;
- }; // if
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
-
- /* First, check to see whether the monitor thread exists to wake it up. This is
- to avoid performance problem when the monitor sleeps during blocktime-size
- interval */
-
- status = pthread_kill( th->th.th_info.ds.ds_thread, 0 );
- if (status != ESRCH) {
- __kmp_resume_monitor(); // Wake up the monitor thread
- }
- KA_TRACE( 10, ("__kmp_reap_monitor: try to join with monitor\n") );
- status = pthread_join( th->th.th_info.ds.ds_thread, & exit_val);
- if (exit_val != th) {
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( ReapMonitorError ),
- KMP_ERR( status ),
- __kmp_msg_null
- );
- }
-
- th->th.th_info.ds.ds_tid = KMP_GTID_DNE;
- th->th.th_info.ds.ds_gtid = KMP_GTID_DNE;
-
- KA_TRACE( 10, ("__kmp_reap_monitor: done reaping monitor thread with handle %#.8lx\n",
- th->th.th_info.ds.ds_thread ) );
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
-}
-#endif // KMP_USE_MONITOR
-
-void
-__kmp_reap_worker( kmp_info_t *th )
-{
- int status;
- void *exit_val;
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- KA_TRACE( 10, ("__kmp_reap_worker: try to reap T#%d\n", th->th.th_info.ds.ds_gtid ) );
-
- status = pthread_join( th->th.th_info.ds.ds_thread, & exit_val);
-#ifdef KMP_DEBUG
- /* Don't expose these to the user until we understand when they trigger */
- if ( status != 0 ) {
- __kmp_msg(kmp_ms_fatal, KMP_MSG( ReapWorkerError ), KMP_ERR( status ), __kmp_msg_null);
- }
- if ( exit_val != th ) {
- KA_TRACE( 10, ( "__kmp_reap_worker: worker T#%d did not reap properly, exit_val = %p\n",
- th->th.th_info.ds.ds_gtid, exit_val ) );
- }
-#endif /* KMP_DEBUG */
-
- KA_TRACE( 10, ("__kmp_reap_worker: done reaping T#%d\n", th->th.th_info.ds.ds_gtid ) );
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-#if KMP_HANDLE_SIGNALS
-
-
-static void
-__kmp_null_handler( int signo )
-{
- // Do nothing, for doing SIG_IGN-type actions.
-} // __kmp_null_handler
-
-
-static void
-__kmp_team_handler( int signo )
-{
- if ( __kmp_global.g.g_abort == 0 ) {
- /* Stage 1 signal handler, let's shut down all of the threads */
- #ifdef KMP_DEBUG
- __kmp_debug_printf( "__kmp_team_handler: caught signal = %d\n", signo );
- #endif
- switch ( signo ) {
- case SIGHUP :
- case SIGINT :
- case SIGQUIT :
- case SIGILL :
- case SIGABRT :
- case SIGFPE :
- case SIGBUS :
- case SIGSEGV :
- #ifdef SIGSYS
- case SIGSYS :
- #endif
- case SIGTERM :
- if ( __kmp_debug_buf ) {
- __kmp_dump_debug_buffer( );
- }; // if
- KMP_MB(); // Flush all pending memory write invalidates.
- TCW_4( __kmp_global.g.g_abort, signo );
- KMP_MB(); // Flush all pending memory write invalidates.
- TCW_4( __kmp_global.g.g_done, TRUE );
- KMP_MB(); // Flush all pending memory write invalidates.
- break;
- default:
- #ifdef KMP_DEBUG
- __kmp_debug_printf( "__kmp_team_handler: unknown signal type" );
- #endif
- break;
- }; // switch
- }; // if
-} // __kmp_team_handler
-
-
-static
-void __kmp_sigaction( int signum, const struct sigaction * act, struct sigaction * oldact ) {
- int rc = sigaction( signum, act, oldact );
- KMP_CHECK_SYSFAIL_ERRNO( "sigaction", rc );
-}
-
-
-static void
-__kmp_install_one_handler( int sig, sig_func_t handler_func, int parallel_init )
-{
- KMP_MB(); // Flush all pending memory write invalidates.
- KB_TRACE( 60, ( "__kmp_install_one_handler( %d, ..., %d )\n", sig, parallel_init ) );
- if ( parallel_init ) {
- struct sigaction new_action;
- struct sigaction old_action;
- new_action.sa_handler = handler_func;
- new_action.sa_flags = 0;
- sigfillset( & new_action.sa_mask );
- __kmp_sigaction( sig, & new_action, & old_action );
- if ( old_action.sa_handler == __kmp_sighldrs[ sig ].sa_handler ) {
- sigaddset( & __kmp_sigset, sig );
- } else {
- // Restore/keep user's handler if one previously installed.
- __kmp_sigaction( sig, & old_action, NULL );
- }; // if
- } else {
- // Save initial/system signal handlers to see if user handlers installed.
- __kmp_sigaction( sig, NULL, & __kmp_sighldrs[ sig ] );
- }; // if
- KMP_MB(); // Flush all pending memory write invalidates.
-} // __kmp_install_one_handler
-
-
-static void
-__kmp_remove_one_handler( int sig )
-{
- KB_TRACE( 60, ( "__kmp_remove_one_handler( %d )\n", sig ) );
- if ( sigismember( & __kmp_sigset, sig ) ) {
- struct sigaction old;
- KMP_MB(); // Flush all pending memory write invalidates.
- __kmp_sigaction( sig, & __kmp_sighldrs[ sig ], & old );
- if ( ( old.sa_handler != __kmp_team_handler ) && ( old.sa_handler != __kmp_null_handler ) ) {
- // Restore the users signal handler.
- KB_TRACE( 10, ( "__kmp_remove_one_handler: oops, not our handler, restoring: sig=%d\n", sig ) );
- __kmp_sigaction( sig, & old, NULL );
- }; // if
- sigdelset( & __kmp_sigset, sig );
- KMP_MB(); // Flush all pending memory write invalidates.
- }; // if
-} // __kmp_remove_one_handler
-
-
-void
-__kmp_install_signals( int parallel_init )
-{
- KB_TRACE( 10, ( "__kmp_install_signals( %d )\n", parallel_init ) );
- if ( __kmp_handle_signals || ! parallel_init ) {
- // If ! parallel_init, we do not install handlers, just save original handlers.
- // Let us do it even __handle_signals is 0.
- sigemptyset( & __kmp_sigset );
- __kmp_install_one_handler( SIGHUP, __kmp_team_handler, parallel_init );
- __kmp_install_one_handler( SIGINT, __kmp_team_handler, parallel_init );
- __kmp_install_one_handler( SIGQUIT, __kmp_team_handler, parallel_init );
- __kmp_install_one_handler( SIGILL, __kmp_team_handler, parallel_init );
- __kmp_install_one_handler( SIGABRT, __kmp_team_handler, parallel_init );
- __kmp_install_one_handler( SIGFPE, __kmp_team_handler, parallel_init );
- __kmp_install_one_handler( SIGBUS, __kmp_team_handler, parallel_init );
- __kmp_install_one_handler( SIGSEGV, __kmp_team_handler, parallel_init );
- #ifdef SIGSYS
- __kmp_install_one_handler( SIGSYS, __kmp_team_handler, parallel_init );
- #endif // SIGSYS
- __kmp_install_one_handler( SIGTERM, __kmp_team_handler, parallel_init );
- #ifdef SIGPIPE
- __kmp_install_one_handler( SIGPIPE, __kmp_team_handler, parallel_init );
- #endif // SIGPIPE
- }; // if
-} // __kmp_install_signals
-
-
-void
-__kmp_remove_signals( void )
-{
- int sig;
- KB_TRACE( 10, ( "__kmp_remove_signals()\n" ) );
- for ( sig = 1; sig < NSIG; ++ sig ) {
- __kmp_remove_one_handler( sig );
- }; // for sig
-} // __kmp_remove_signals
-
-
-#endif // KMP_HANDLE_SIGNALS
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-void
-__kmp_enable( int new_state )
-{
- #ifdef KMP_CANCEL_THREADS
- int status, old_state;
- status = pthread_setcancelstate( new_state, & old_state );
- KMP_CHECK_SYSFAIL( "pthread_setcancelstate", status );
- KMP_DEBUG_ASSERT( old_state == PTHREAD_CANCEL_DISABLE );
- #endif
-}
-
-void
-__kmp_disable( int * old_state )
-{
- #ifdef KMP_CANCEL_THREADS
- int status;
- status = pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, old_state );
- KMP_CHECK_SYSFAIL( "pthread_setcancelstate", status );
- #endif
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-static void
-__kmp_atfork_prepare (void)
-{
- /* nothing to do */
-}
-
-static void
-__kmp_atfork_parent (void)
-{
- /* nothing to do */
-}
-
-/*
- Reset the library so execution in the child starts "all over again" with
- clean data structures in initial states. Don't worry about freeing memory
- allocated by parent, just abandon it to be safe.
-*/
-static void
-__kmp_atfork_child (void)
-{
- /* TODO make sure this is done right for nested/sibling */
- // ATT: Memory leaks are here? TODO: Check it and fix.
- /* KMP_ASSERT( 0 ); */
-
- ++__kmp_fork_count;
-
- __kmp_init_runtime = FALSE;
-#if KMP_USE_MONITOR
- __kmp_init_monitor = 0;
-#endif
- __kmp_init_parallel = FALSE;
- __kmp_init_middle = FALSE;
- __kmp_init_serial = FALSE;
- TCW_4(__kmp_init_gtid, FALSE);
- __kmp_init_common = FALSE;
-
- TCW_4(__kmp_init_user_locks, FALSE);
-#if ! KMP_USE_DYNAMIC_LOCK
- __kmp_user_lock_table.used = 1;
- __kmp_user_lock_table.allocated = 0;
- __kmp_user_lock_table.table = NULL;
- __kmp_lock_blocks = NULL;
-#endif
-
- __kmp_all_nth = 0;
- TCW_4(__kmp_nth, 0);
-
- /* Must actually zero all the *cache arguments passed to __kmpc_threadprivate here
- so threadprivate doesn't use stale data */
- KA_TRACE( 10, ( "__kmp_atfork_child: checking cache address list %p\n",
- __kmp_threadpriv_cache_list ) );
-
- while ( __kmp_threadpriv_cache_list != NULL ) {
-
- if ( *__kmp_threadpriv_cache_list -> addr != NULL ) {
- KC_TRACE( 50, ( "__kmp_atfork_child: zeroing cache at address %p\n",
- &(*__kmp_threadpriv_cache_list -> addr) ) );
-
- *__kmp_threadpriv_cache_list -> addr = NULL;
- }
- __kmp_threadpriv_cache_list = __kmp_threadpriv_cache_list -> next;
- }
-
- __kmp_init_runtime = FALSE;
-
- /* reset statically initialized locks */
- __kmp_init_bootstrap_lock( &__kmp_initz_lock );
- __kmp_init_bootstrap_lock( &__kmp_stdio_lock );
- __kmp_init_bootstrap_lock( &__kmp_console_lock );
-
- /* This is necessary to make sure no stale data is left around */
- /* AC: customers complain that we use unsafe routines in the atfork
- handler. Mathworks: dlsym() is unsafe. We call dlsym and dlopen
- in dynamic_link when check the presence of shared tbbmalloc library.
- Suggestion is to make the library initialization lazier, similar
- to what done for __kmpc_begin(). */
- // TODO: synchronize all static initializations with regular library
- // startup; look at kmp_global.c and etc.
- //__kmp_internal_begin ();
-
-}
-
-void
-__kmp_register_atfork(void) {
- if ( __kmp_need_register_atfork ) {
- int status = pthread_atfork( __kmp_atfork_prepare, __kmp_atfork_parent, __kmp_atfork_child );
- KMP_CHECK_SYSFAIL( "pthread_atfork", status );
- __kmp_need_register_atfork = FALSE;
- }
-}
-
-void
-__kmp_suspend_initialize( void )
-{
- int status;
- status = pthread_mutexattr_init( &__kmp_suspend_mutex_attr );
- KMP_CHECK_SYSFAIL( "pthread_mutexattr_init", status );
- status = pthread_condattr_init( &__kmp_suspend_cond_attr );
- KMP_CHECK_SYSFAIL( "pthread_condattr_init", status );
-}
-
-static void
-__kmp_suspend_initialize_thread( kmp_info_t *th )
-{
- ANNOTATE_HAPPENS_AFTER(&th->th.th_suspend_init_count);
- if ( th->th.th_suspend_init_count <= __kmp_fork_count ) {
- /* this means we haven't initialized the suspension pthread objects for this thread
- in this instance of the process */
- int status;
- status = pthread_cond_init( &th->th.th_suspend_cv.c_cond, &__kmp_suspend_cond_attr );
- KMP_CHECK_SYSFAIL( "pthread_cond_init", status );
- status = pthread_mutex_init( &th->th.th_suspend_mx.m_mutex, & __kmp_suspend_mutex_attr );
- KMP_CHECK_SYSFAIL( "pthread_mutex_init", status );
- *(volatile int*)&th->th.th_suspend_init_count = __kmp_fork_count + 1;
- ANNOTATE_HAPPENS_BEFORE(&th->th.th_suspend_init_count);
- };
-}
-
-void
-__kmp_suspend_uninitialize_thread( kmp_info_t *th )
-{
- if(th->th.th_suspend_init_count > __kmp_fork_count) {
- /* this means we have initialize the suspension pthread objects for this thread
- in this instance of the process */
- int status;
-
- status = pthread_cond_destroy( &th->th.th_suspend_cv.c_cond );
- if ( status != 0 && status != EBUSY ) {
- KMP_SYSFAIL( "pthread_cond_destroy", status );
- };
- status = pthread_mutex_destroy( &th->th.th_suspend_mx.m_mutex );
- if ( status != 0 && status != EBUSY ) {
- KMP_SYSFAIL( "pthread_mutex_destroy", status );
- };
- --th->th.th_suspend_init_count;
- KMP_DEBUG_ASSERT(th->th.th_suspend_init_count == __kmp_fork_count);
- }
-}
-
-/* This routine puts the calling thread to sleep after setting the
- * sleep bit for the indicated flag variable to true.
- */
-template <class C>
-static inline void __kmp_suspend_template( int th_gtid, C *flag )
-{
- KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_suspend);
- kmp_info_t *th = __kmp_threads[th_gtid];
- int status;
- typename C::flag_t old_spin;
-
- KF_TRACE( 30, ("__kmp_suspend_template: T#%d enter for flag = %p\n", th_gtid, flag->get() ) );
-
- __kmp_suspend_initialize_thread( th );
-
- status = pthread_mutex_lock( &th->th.th_suspend_mx.m_mutex );
- KMP_CHECK_SYSFAIL( "pthread_mutex_lock", status );
-
- KF_TRACE( 10, ( "__kmp_suspend_template: T#%d setting sleep bit for spin(%p)\n",
- th_gtid, flag->get() ) );
-
- /* TODO: shouldn't this use release semantics to ensure that __kmp_suspend_initialize_thread
- gets called first?
- */
- old_spin = flag->set_sleeping();
-
- KF_TRACE( 5, ( "__kmp_suspend_template: T#%d set sleep bit for spin(%p)==%x, was %x\n",
- th_gtid, flag->get(), *(flag->get()), old_spin ) );
-
- if ( flag->done_check_val(old_spin) ) {
- old_spin = flag->unset_sleeping();
- KF_TRACE( 5, ( "__kmp_suspend_template: T#%d false alarm, reset sleep bit for spin(%p)\n",
- th_gtid, flag->get()) );
- } else {
- /* Encapsulate in a loop as the documentation states that this may
- * "with low probability" return when the condition variable has
- * not been signaled or broadcast
- */
- int deactivated = FALSE;
- TCW_PTR(th->th.th_sleep_loc, (void *)flag);
- while ( flag->is_sleeping() ) {
-#ifdef DEBUG_SUSPEND
- char buffer[128];
- __kmp_suspend_count++;
- __kmp_print_cond( buffer, &th->th.th_suspend_cv );
- __kmp_printf( "__kmp_suspend_template: suspending T#%d: %s\n", th_gtid, buffer );
-#endif
- // Mark the thread as no longer active (only in the first iteration of the loop).
- if ( ! deactivated ) {
- th->th.th_active = FALSE;
- if ( th->th.th_active_in_pool ) {
- th->th.th_active_in_pool = FALSE;
- KMP_TEST_THEN_DEC32(
- (kmp_int32 *) &__kmp_thread_pool_active_nth );
- KMP_DEBUG_ASSERT( TCR_4(__kmp_thread_pool_active_nth) >= 0 );
- }
- deactivated = TRUE;
- }
-
-#if USE_SUSPEND_TIMEOUT
- struct timespec now;
- struct timeval tval;
- int msecs;
-
- status = gettimeofday( &tval, NULL );
- KMP_CHECK_SYSFAIL_ERRNO( "gettimeofday", status );
- TIMEVAL_TO_TIMESPEC( &tval, &now );
-
- msecs = (4*__kmp_dflt_blocktime) + 200;
- now.tv_sec += msecs / 1000;
- now.tv_nsec += (msecs % 1000)*1000;
-
- KF_TRACE( 15, ( "__kmp_suspend_template: T#%d about to perform pthread_cond_timedwait\n",
- th_gtid ) );
- status = pthread_cond_timedwait( &th->th.th_suspend_cv.c_cond, &th->th.th_suspend_mx.m_mutex, & now );
-#else
- KF_TRACE( 15, ( "__kmp_suspend_template: T#%d about to perform pthread_cond_wait\n",
- th_gtid ) );
- status = pthread_cond_wait( &th->th.th_suspend_cv.c_cond, &th->th.th_suspend_mx.m_mutex );
-#endif
-
- if ( (status != 0) && (status != EINTR) && (status != ETIMEDOUT) ) {
- KMP_SYSFAIL( "pthread_cond_wait", status );
- }
-#ifdef KMP_DEBUG
- if (status == ETIMEDOUT) {
- if ( flag->is_sleeping() ) {
- KF_TRACE( 100, ( "__kmp_suspend_template: T#%d timeout wakeup\n", th_gtid ) );
- } else {
- KF_TRACE( 2, ( "__kmp_suspend_template: T#%d timeout wakeup, sleep bit not set!\n",
- th_gtid ) );
- }
- } else if ( flag->is_sleeping() ) {
- KF_TRACE( 100, ( "__kmp_suspend_template: T#%d spurious wakeup\n", th_gtid ) );
- }
-#endif
- } // while
-
- // Mark the thread as active again (if it was previous marked as inactive)
- if ( deactivated ) {
- th->th.th_active = TRUE;
- if ( TCR_4(th->th.th_in_pool) ) {
- KMP_TEST_THEN_INC32( (kmp_int32 *) &__kmp_thread_pool_active_nth );
- th->th.th_active_in_pool = TRUE;
- }
- }
- }
-
-#ifdef DEBUG_SUSPEND
- {
- char buffer[128];
- __kmp_print_cond( buffer, &th->th.th_suspend_cv);
- __kmp_printf( "__kmp_suspend_template: T#%d has awakened: %s\n", th_gtid, buffer );
- }
-#endif
-
- status = pthread_mutex_unlock( &th->th.th_suspend_mx.m_mutex );
- KMP_CHECK_SYSFAIL( "pthread_mutex_unlock", status );
-
- KF_TRACE( 30, ("__kmp_suspend_template: T#%d exit\n", th_gtid ) );
-}
-
-void __kmp_suspend_32(int th_gtid, kmp_flag_32 *flag) {
- __kmp_suspend_template(th_gtid, flag);
-}
-void __kmp_suspend_64(int th_gtid, kmp_flag_64 *flag) {
- __kmp_suspend_template(th_gtid, flag);
-}
-void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag) {
- __kmp_suspend_template(th_gtid, flag);
-}
-
-
-/* This routine signals the thread specified by target_gtid to wake up
- * after setting the sleep bit indicated by the flag argument to FALSE.
- * The target thread must already have called __kmp_suspend_template()
- */
-template <class C>
-static inline void __kmp_resume_template( int target_gtid, C *flag )
-{
- KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_resume);
- kmp_info_t *th = __kmp_threads[target_gtid];
- int status;
-
-#ifdef KMP_DEBUG
- int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
-#endif
-
- KF_TRACE( 30, ( "__kmp_resume_template: T#%d wants to wakeup T#%d enter\n", gtid, target_gtid ) );
- KMP_DEBUG_ASSERT( gtid != target_gtid );
-
- __kmp_suspend_initialize_thread( th );
-
- status = pthread_mutex_lock( &th->th.th_suspend_mx.m_mutex );
- KMP_CHECK_SYSFAIL( "pthread_mutex_lock", status );
-
- if (!flag) { // coming from __kmp_null_resume_wrapper
- flag = (C *)th->th.th_sleep_loc;
- }
-
- // First, check if the flag is null or its type has changed. If so, someone else woke it up.
- if (!flag || flag->get_type() != flag->get_ptr_type()) { // get_ptr_type simply shows what flag was cast to
- KF_TRACE( 5, ( "__kmp_resume_template: T#%d exiting, thread T#%d already awake: flag(%p)\n",
- gtid, target_gtid, NULL ) );
- status = pthread_mutex_unlock( &th->th.th_suspend_mx.m_mutex );
- KMP_CHECK_SYSFAIL( "pthread_mutex_unlock", status );
- return;
- }
- else { // if multiple threads are sleeping, flag should be internally referring to a specific thread here
- typename C::flag_t old_spin = flag->unset_sleeping();
- if ( ! flag->is_sleeping_val(old_spin) ) {
- KF_TRACE( 5, ( "__kmp_resume_template: T#%d exiting, thread T#%d already awake: flag(%p): "
- "%u => %u\n",
- gtid, target_gtid, flag->get(), old_spin, *flag->get() ) );
- status = pthread_mutex_unlock( &th->th.th_suspend_mx.m_mutex );
- KMP_CHECK_SYSFAIL( "pthread_mutex_unlock", status );
- return;
- }
- KF_TRACE( 5, ( "__kmp_resume_template: T#%d about to wakeup T#%d, reset sleep bit for flag's loc(%p): "
- "%u => %u\n",
- gtid, target_gtid, flag->get(), old_spin, *flag->get() ) );
- }
- TCW_PTR(th->th.th_sleep_loc, NULL);
-
-
-#ifdef DEBUG_SUSPEND
- {
- char buffer[128];
- __kmp_print_cond( buffer, &th->th.th_suspend_cv );
- __kmp_printf( "__kmp_resume_template: T#%d resuming T#%d: %s\n", gtid, target_gtid, buffer );
- }
-#endif
-
- status = pthread_cond_signal( &th->th.th_suspend_cv.c_cond );
- KMP_CHECK_SYSFAIL( "pthread_cond_signal", status );
- status = pthread_mutex_unlock( &th->th.th_suspend_mx.m_mutex );
- KMP_CHECK_SYSFAIL( "pthread_mutex_unlock", status );
- KF_TRACE( 30, ( "__kmp_resume_template: T#%d exiting after signaling wake up for T#%d\n",
- gtid, target_gtid ) );
-}
-
-void __kmp_resume_32(int target_gtid, kmp_flag_32 *flag) {
- __kmp_resume_template(target_gtid, flag);
-}
-void __kmp_resume_64(int target_gtid, kmp_flag_64 *flag) {
- __kmp_resume_template(target_gtid, flag);
-}
-void __kmp_resume_oncore(int target_gtid, kmp_flag_oncore *flag) {
- __kmp_resume_template(target_gtid, flag);
-}
-
-#if KMP_USE_MONITOR
-void
-__kmp_resume_monitor()
-{
- KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_resume);
- int status;
-#ifdef KMP_DEBUG
- int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
- KF_TRACE( 30, ( "__kmp_resume_monitor: T#%d wants to wakeup T#%d enter\n",
- gtid, KMP_GTID_MONITOR ) );
- KMP_DEBUG_ASSERT( gtid != KMP_GTID_MONITOR );
-#endif
- status = pthread_mutex_lock( &__kmp_wait_mx.m_mutex );
- KMP_CHECK_SYSFAIL( "pthread_mutex_lock", status );
-#ifdef DEBUG_SUSPEND
- {
- char buffer[128];
- __kmp_print_cond( buffer, &__kmp_wait_cv.c_cond );
- __kmp_printf( "__kmp_resume_monitor: T#%d resuming T#%d: %s\n", gtid, KMP_GTID_MONITOR, buffer );
- }
-#endif
- status = pthread_cond_signal( &__kmp_wait_cv.c_cond );
- KMP_CHECK_SYSFAIL( "pthread_cond_signal", status );
- status = pthread_mutex_unlock( &__kmp_wait_mx.m_mutex );
- KMP_CHECK_SYSFAIL( "pthread_mutex_unlock", status );
- KF_TRACE( 30, ( "__kmp_resume_monitor: T#%d exiting after signaling wake up for T#%d\n",
- gtid, KMP_GTID_MONITOR ) );
-}
-#endif // KMP_USE_MONITOR
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-void
-__kmp_yield( int cond )
-{
- if (cond
-#if KMP_USE_MONITOR
- && __kmp_yielding_on
-#endif
- ) {
- sched_yield();
- }
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-void
-__kmp_gtid_set_specific( int gtid )
-{
- if( __kmp_init_gtid ) {
- int status;
- status = pthread_setspecific( __kmp_gtid_threadprivate_key, (void*)(intptr_t)(gtid+1) );
- KMP_CHECK_SYSFAIL( "pthread_setspecific", status );
- } else {
- KA_TRACE( 50, ("__kmp_gtid_set_specific: runtime shutdown, returning\n" ) );
- }
-}
-
-int
-__kmp_gtid_get_specific()
-{
- int gtid;
- if ( !__kmp_init_gtid ) {
- KA_TRACE( 50, ("__kmp_gtid_get_specific: runtime shutdown, returning KMP_GTID_SHUTDOWN\n" ) );
- return KMP_GTID_SHUTDOWN;
- }
- gtid = (int)(size_t)pthread_getspecific( __kmp_gtid_threadprivate_key );
- if ( gtid == 0 ) {
- gtid = KMP_GTID_DNE;
- }
- else {
- gtid--;
- }
- KA_TRACE( 50, ("__kmp_gtid_get_specific: key:%d gtid:%d\n",
- __kmp_gtid_threadprivate_key, gtid ));
- return gtid;
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-double
-__kmp_read_cpu_time( void )
-{
- /*clock_t t;*/
- struct tms buffer;
-
- /*t =*/ times( & buffer );
-
- return (buffer.tms_utime + buffer.tms_cutime) / (double) CLOCKS_PER_SEC;
-}
-
-int
-__kmp_read_system_info( struct kmp_sys_info *info )
-{
- int status;
- struct rusage r_usage;
-
- memset( info, 0, sizeof( *info ) );
-
- status = getrusage( RUSAGE_SELF, &r_usage);
- KMP_CHECK_SYSFAIL_ERRNO( "getrusage", status );
-
- info->maxrss = r_usage.ru_maxrss; /* the maximum resident set size utilized (in kilobytes) */
- info->minflt = r_usage.ru_minflt; /* the number of page faults serviced without any I/O */
- info->majflt = r_usage.ru_majflt; /* the number of page faults serviced that required I/O */
- info->nswap = r_usage.ru_nswap; /* the number of times a process was "swapped" out of memory */
- info->inblock = r_usage.ru_inblock; /* the number of times the file system had to perform input */
- info->oublock = r_usage.ru_oublock; /* the number of times the file system had to perform output */
- info->nvcsw = r_usage.ru_nvcsw; /* the number of times a context switch was voluntarily */
- info->nivcsw = r_usage.ru_nivcsw; /* the number of times a context switch was forced */
-
- return (status != 0);
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-void
-__kmp_read_system_time( double *delta )
-{
- double t_ns;
- struct timeval tval;
- struct timespec stop;
- int status;
-
- status = gettimeofday( &tval, NULL );
- KMP_CHECK_SYSFAIL_ERRNO( "gettimeofday", status );
- TIMEVAL_TO_TIMESPEC( &tval, &stop );
- t_ns = TS2NS(stop) - TS2NS(__kmp_sys_timer_data.start);
- *delta = (t_ns * 1e-9);
-}
-
-void
-__kmp_clear_system_time( void )
-{
- struct timeval tval;
- int status;
- status = gettimeofday( &tval, NULL );
- KMP_CHECK_SYSFAIL_ERRNO( "gettimeofday", status );
- TIMEVAL_TO_TIMESPEC( &tval, &__kmp_sys_timer_data.start );
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-#ifdef BUILD_TV
-
-void
-__kmp_tv_threadprivate_store( kmp_info_t *th, void *global_addr, void *thread_addr )
-{
- struct tv_data *p;
-
- p = (struct tv_data *) __kmp_allocate( sizeof( *p ) );
-
- p->u.tp.global_addr = global_addr;
- p->u.tp.thread_addr = thread_addr;
-
- p->type = (void *) 1;
-
- p->next = th->th.th_local.tv_data;
- th->th.th_local.tv_data = p;
-
- if ( p->next == 0 ) {
- int rc = pthread_setspecific( __kmp_tv_key, p );
- KMP_CHECK_SYSFAIL( "pthread_setspecific", rc );
- }
-}
-
-#endif /* BUILD_TV */
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-static int
-__kmp_get_xproc( void ) {
-
- int r = 0;
-
- #if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD
-
- r = sysconf( _SC_NPROCESSORS_ONLN );
-
- #elif KMP_OS_DARWIN
-
- // Bug C77011 High "OpenMP Threads and number of active cores".
-
- // Find the number of available CPUs.
- kern_return_t rc;
- host_basic_info_data_t info;
- mach_msg_type_number_t num = HOST_BASIC_INFO_COUNT;
- rc = host_info( mach_host_self(), HOST_BASIC_INFO, (host_info_t) & info, & num );
- if ( rc == 0 && num == HOST_BASIC_INFO_COUNT ) {
- // Cannot use KA_TRACE() here because this code works before trace support is
- // initialized.
- r = info.avail_cpus;
- } else {
- KMP_WARNING( CantGetNumAvailCPU );
- KMP_INFORM( AssumedNumCPU );
- }; // if
-
- #else
-
- #error "Unknown or unsupported OS."
-
- #endif
-
- return r > 0 ? r : 2; /* guess value of 2 if OS told us 0 */
-
-} // __kmp_get_xproc
-
-int
-__kmp_read_from_file( char const *path, char const *format, ... )
-{
- int result;
- va_list args;
-
- va_start(args, format);
- FILE *f = fopen(path, "rb");
- if ( f == NULL )
- return 0;
- result = vfscanf(f, format, args);
- fclose(f);
-
- return result;
-}
-
-void
-__kmp_runtime_initialize( void )
-{
- int status;
- pthread_mutexattr_t mutex_attr;
- pthread_condattr_t cond_attr;
-
- if ( __kmp_init_runtime ) {
- return;
- }; // if
-
- #if ( KMP_ARCH_X86 || KMP_ARCH_X86_64 )
- if ( ! __kmp_cpuinfo.initialized ) {
- __kmp_query_cpuid( &__kmp_cpuinfo );
- }; // if
- #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
-
- __kmp_xproc = __kmp_get_xproc();
-
- if ( sysconf( _SC_THREADS ) ) {
-
- /* Query the maximum number of threads */
- __kmp_sys_max_nth = sysconf( _SC_THREAD_THREADS_MAX );
- if ( __kmp_sys_max_nth == -1 ) {
- /* Unlimited threads for NPTL */
- __kmp_sys_max_nth = INT_MAX;
- }
- else if ( __kmp_sys_max_nth <= 1 ) {
- /* Can't tell, just use PTHREAD_THREADS_MAX */
- __kmp_sys_max_nth = KMP_MAX_NTH;
- }
-
- /* Query the minimum stack size */
- __kmp_sys_min_stksize = sysconf( _SC_THREAD_STACK_MIN );
- if ( __kmp_sys_min_stksize <= 1 ) {
- __kmp_sys_min_stksize = KMP_MIN_STKSIZE;
- }
- }
-
- /* Set up minimum number of threads to switch to TLS gtid */
- __kmp_tls_gtid_min = KMP_TLS_GTID_MIN;
-
- #ifdef BUILD_TV
- {
- int rc = pthread_key_create( & __kmp_tv_key, 0 );
- KMP_CHECK_SYSFAIL( "pthread_key_create", rc );
- }
- #endif
-
- status = pthread_key_create( &__kmp_gtid_threadprivate_key, __kmp_internal_end_dest );
- KMP_CHECK_SYSFAIL( "pthread_key_create", status );
- status = pthread_mutexattr_init( & mutex_attr );
- KMP_CHECK_SYSFAIL( "pthread_mutexattr_init", status );
- status = pthread_mutex_init( & __kmp_wait_mx.m_mutex, & mutex_attr );
- KMP_CHECK_SYSFAIL( "pthread_mutex_init", status );
- status = pthread_condattr_init( & cond_attr );
- KMP_CHECK_SYSFAIL( "pthread_condattr_init", status );
- status = pthread_cond_init( & __kmp_wait_cv.c_cond, & cond_attr );
- KMP_CHECK_SYSFAIL( "pthread_cond_init", status );
-#if USE_ITT_BUILD
- __kmp_itt_initialize();
-#endif /* USE_ITT_BUILD */
-
- __kmp_init_runtime = TRUE;
-}
-
-void
-__kmp_runtime_destroy( void )
-{
- int status;
-
- if ( ! __kmp_init_runtime ) {
- return; // Nothing to do.
- };
-
-#if USE_ITT_BUILD
- __kmp_itt_destroy();
-#endif /* USE_ITT_BUILD */
-
- status = pthread_key_delete( __kmp_gtid_threadprivate_key );
- KMP_CHECK_SYSFAIL( "pthread_key_delete", status );
- #ifdef BUILD_TV
- status = pthread_key_delete( __kmp_tv_key );
- KMP_CHECK_SYSFAIL( "pthread_key_delete", status );
- #endif
-
- status = pthread_mutex_destroy( & __kmp_wait_mx.m_mutex );
- if ( status != 0 && status != EBUSY ) {
- KMP_SYSFAIL( "pthread_mutex_destroy", status );
- }
- status = pthread_cond_destroy( & __kmp_wait_cv.c_cond );
- if ( status != 0 && status != EBUSY ) {
- KMP_SYSFAIL( "pthread_cond_destroy", status );
- }
- #if KMP_AFFINITY_SUPPORTED
- __kmp_affinity_uninitialize();
- #endif
-
- __kmp_init_runtime = FALSE;
-}
-
-
-/* Put the thread to sleep for a time period */
-/* NOTE: not currently used anywhere */
-void
-__kmp_thread_sleep( int millis )
-{
- sleep( ( millis + 500 ) / 1000 );
-}
-
-/* Calculate the elapsed wall clock time for the user */
-void
-__kmp_elapsed( double *t )
-{
- int status;
-# ifdef FIX_SGI_CLOCK
- struct timespec ts;
-
- status = clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &ts );
- KMP_CHECK_SYSFAIL_ERRNO( "clock_gettime", status );
- *t = (double) ts.tv_nsec * (1.0 / (double) KMP_NSEC_PER_SEC) +
- (double) ts.tv_sec;
-# else
- struct timeval tv;
-
- status = gettimeofday( & tv, NULL );
- KMP_CHECK_SYSFAIL_ERRNO( "gettimeofday", status );
- *t = (double) tv.tv_usec * (1.0 / (double) KMP_USEC_PER_SEC) +
- (double) tv.tv_sec;
-# endif
-}
-
-/* Calculate the elapsed wall clock tick for the user */
-void
-__kmp_elapsed_tick( double *t )
-{
- *t = 1 / (double) CLOCKS_PER_SEC;
-}
-
-/* Return the current time stamp in nsec */
-kmp_uint64
-__kmp_now_nsec()
-{
- struct timeval t;
- gettimeofday(&t, NULL);
- return KMP_NSEC_PER_SEC*t.tv_sec + 1000*t.tv_usec;
-}
-
-#if KMP_ARCH_X86 || KMP_ARCH_X86_64
-/* Measure clock tick per nanosecond */
-void
-__kmp_initialize_system_tick()
-{
- kmp_uint64 delay = 100000; // 50~100 usec on most machines.
- kmp_uint64 nsec = __kmp_now_nsec();
- kmp_uint64 goal = __kmp_hardware_timestamp() + delay;
- kmp_uint64 now;
- while ((now = __kmp_hardware_timestamp()) < goal);
- __kmp_ticks_per_nsec = 1.0 * (delay + (now - goal)) / (__kmp_now_nsec() - nsec);
-}
-#endif
-
-/*
- Determine whether the given address is mapped into the current address space.
-*/
-
-int
-__kmp_is_address_mapped( void * addr ) {
-
- int found = 0;
- int rc;
-
- #if KMP_OS_LINUX || KMP_OS_FREEBSD
-
- /*
- On Linux* OS, read the /proc/<pid>/maps pseudo-file to get all the address ranges mapped
- into the address space.
- */
-
- char * name = __kmp_str_format( "/proc/%d/maps", getpid() );
- FILE * file = NULL;
-
- file = fopen( name, "r" );
- KMP_ASSERT( file != NULL );
-
- for ( ; ; ) {
-
- void * beginning = NULL;
- void * ending = NULL;
- char perms[ 5 ];
-
- rc = fscanf( file, "%p-%p %4s %*[^\n]\n", & beginning, & ending, perms );
- if ( rc == EOF ) {
- break;
- }; // if
- KMP_ASSERT( rc == 3 && KMP_STRLEN( perms ) == 4 ); // Make sure all fields are read.
-
- // Ending address is not included in the region, but beginning is.
- if ( ( addr >= beginning ) && ( addr < ending ) ) {
- perms[ 2 ] = 0; // 3th and 4th character does not matter.
- if ( strcmp( perms, "rw" ) == 0 ) {
- // Memory we are looking for should be readable and writable.
- found = 1;
- }; // if
- break;
- }; // if
-
- }; // forever
-
- // Free resources.
- fclose( file );
- KMP_INTERNAL_FREE( name );
-
- #elif KMP_OS_DARWIN
-
- /*
- On OS X*, /proc pseudo filesystem is not available. Try to read memory using vm
- interface.
- */
-
- int buffer;
- vm_size_t count;
- rc =
- vm_read_overwrite(
- mach_task_self(), // Task to read memory of.
- (vm_address_t)( addr ), // Address to read from.
- 1, // Number of bytes to be read.
- (vm_address_t)( & buffer ), // Address of buffer to save read bytes in.
- & count // Address of var to save number of read bytes in.
- );
- if ( rc == 0 ) {
- // Memory successfully read.
- found = 1;
- }; // if
-
- #elif KMP_OS_FREEBSD || KMP_OS_NETBSD
-
- // FIXME(FreeBSD, NetBSD): Implement this
- found = 1;
-
- #else
-
- #error "Unknown or unsupported OS"
-
- #endif
-
- return found;
-
-} // __kmp_is_address_mapped
-
-#ifdef USE_LOAD_BALANCE
-
-
-# if KMP_OS_DARWIN
-
-// The function returns the rounded value of the system load average
-// during given time interval which depends on the value of
-// __kmp_load_balance_interval variable (default is 60 sec, other values
-// may be 300 sec or 900 sec).
-// It returns -1 in case of error.
-int
-__kmp_get_load_balance( int max )
-{
- double averages[3];
- int ret_avg = 0;
-
- int res = getloadavg( averages, 3 );
-
- //Check __kmp_load_balance_interval to determine which of averages to use.
- // getloadavg() may return the number of samples less than requested that is
- // less than 3.
- if ( __kmp_load_balance_interval < 180 && ( res >= 1 ) ) {
- ret_avg = averages[0];// 1 min
- } else if ( ( __kmp_load_balance_interval >= 180
- && __kmp_load_balance_interval < 600 ) && ( res >= 2 ) ) {
- ret_avg = averages[1];// 5 min
- } else if ( ( __kmp_load_balance_interval >= 600 ) && ( res == 3 ) ) {
- ret_avg = averages[2];// 15 min
- } else {// Error occurred
- return -1;
- }
-
- return ret_avg;
-}
-
-# else // Linux* OS
-
-// The fuction returns number of running (not sleeping) threads, or -1 in case of error.
-// Error could be reported if Linux* OS kernel too old (without "/proc" support).
-// Counting running threads stops if max running threads encountered.
-int
-__kmp_get_load_balance( int max )
-{
- static int permanent_error = 0;
-
- static int glb_running_threads = 0; /* Saved count of the running threads for the thread balance algortihm */
- static double glb_call_time = 0; /* Thread balance algorithm call time */
-
- int running_threads = 0; // Number of running threads in the system.
-
- DIR * proc_dir = NULL; // Handle of "/proc/" directory.
- struct dirent * proc_entry = NULL;
-
- kmp_str_buf_t task_path; // "/proc/<pid>/task/<tid>/" path.
- DIR * task_dir = NULL; // Handle of "/proc/<pid>/task/<tid>/" directory.
- struct dirent * task_entry = NULL;
- int task_path_fixed_len;
-
- kmp_str_buf_t stat_path; // "/proc/<pid>/task/<tid>/stat" path.
- int stat_file = -1;
- int stat_path_fixed_len;
-
- int total_processes = 0; // Total number of processes in system.
- int total_threads = 0; // Total number of threads in system.
-
- double call_time = 0.0;
-
- __kmp_str_buf_init( & task_path );
- __kmp_str_buf_init( & stat_path );
-
- __kmp_elapsed( & call_time );
-
- if ( glb_call_time &&
- ( call_time - glb_call_time < __kmp_load_balance_interval ) ) {
- running_threads = glb_running_threads;
- goto finish;
- }
-
- glb_call_time = call_time;
-
- // Do not spend time on scanning "/proc/" if we have a permanent error.
- if ( permanent_error ) {
- running_threads = -1;
- goto finish;
- }; // if
-
- if ( max <= 0 ) {
- max = INT_MAX;
- }; // if
-
- // Open "/proc/" directory.
- proc_dir = opendir( "/proc" );
- if ( proc_dir == NULL ) {
- // Cannot open "/prroc/". Probably the kernel does not support it. Return an error now and
- // in subsequent calls.
- running_threads = -1;
- permanent_error = 1;
- goto finish;
- }; // if
-
- // Initialize fixed part of task_path. This part will not change.
- __kmp_str_buf_cat( & task_path, "/proc/", 6 );
- task_path_fixed_len = task_path.used; // Remember number of used characters.
-
- proc_entry = readdir( proc_dir );
- while ( proc_entry != NULL ) {
- // Proc entry is a directory and name starts with a digit. Assume it is a process'
- // directory.
- if ( proc_entry->d_type == DT_DIR && isdigit( proc_entry->d_name[ 0 ] ) ) {
-
- ++ total_processes;
- // Make sure init process is the very first in "/proc", so we can replace
- // strcmp( proc_entry->d_name, "1" ) == 0 with simpler total_processes == 1.
- // We are going to check that total_processes == 1 => d_name == "1" is true (where
- // "=>" is implication). Since C++ does not have => operator, let us replace it with its
- // equivalent: a => b == ! a || b.
- KMP_DEBUG_ASSERT( total_processes != 1 || strcmp( proc_entry->d_name, "1" ) == 0 );
-
- // Construct task_path.
- task_path.used = task_path_fixed_len; // Reset task_path to "/proc/".
- __kmp_str_buf_cat( & task_path, proc_entry->d_name, KMP_STRLEN( proc_entry->d_name ) );
- __kmp_str_buf_cat( & task_path, "/task", 5 );
-
- task_dir = opendir( task_path.str );
- if ( task_dir == NULL ) {
- // Process can finish between reading "/proc/" directory entry and opening process'
- // "task/" directory. So, in general case we should not complain, but have to skip
- // this process and read the next one.
- // But on systems with no "task/" support we will spend lot of time to scan "/proc/"
- // tree again and again without any benefit. "init" process (its pid is 1) should
- // exist always, so, if we cannot open "/proc/1/task/" directory, it means "task/"
- // is not supported by kernel. Report an error now and in the future.
- if ( strcmp( proc_entry->d_name, "1" ) == 0 ) {
- running_threads = -1;
- permanent_error = 1;
- goto finish;
- }; // if
- } else {
- // Construct fixed part of stat file path.
- __kmp_str_buf_clear( & stat_path );
- __kmp_str_buf_cat( & stat_path, task_path.str, task_path.used );
- __kmp_str_buf_cat( & stat_path, "/", 1 );
- stat_path_fixed_len = stat_path.used;
-
- task_entry = readdir( task_dir );
- while ( task_entry != NULL ) {
- // It is a directory and name starts with a digit.
- if ( proc_entry->d_type == DT_DIR && isdigit( task_entry->d_name[ 0 ] ) ) {
-
- ++ total_threads;
-
- // Consruct complete stat file path. Easiest way would be:
- // __kmp_str_buf_print( & stat_path, "%s/%s/stat", task_path.str, task_entry->d_name );
- // but seriae of __kmp_str_buf_cat works a bit faster.
- stat_path.used = stat_path_fixed_len; // Reset stat path to its fixed part.
- __kmp_str_buf_cat( & stat_path, task_entry->d_name, KMP_STRLEN( task_entry->d_name ) );
- __kmp_str_buf_cat( & stat_path, "/stat", 5 );
-
- // Note: Low-level API (open/read/close) is used. High-level API
- // (fopen/fclose) works ~ 30 % slower.
- stat_file = open( stat_path.str, O_RDONLY );
- if ( stat_file == -1 ) {
- // We cannot report an error because task (thread) can terminate just
- // before reading this file.
- } else {
- /*
- Content of "stat" file looks like:
-
- 24285 (program) S ...
-
- It is a single line (if program name does not include fanny
- symbols). First number is a thread id, then name of executable file
- name in paretheses, then state of the thread. We need just thread
- state.
-
- Good news: Length of program name is 15 characters max. Longer
- names are truncated.
-
- Thus, we need rather short buffer: 15 chars for program name +
- 2 parenthesis, + 3 spaces + ~7 digits of pid = 37.
-
- Bad news: Program name may contain special symbols like space,
- closing parenthesis, or even new line. This makes parsing "stat"
- file not 100 % reliable. In case of fanny program names parsing
- may fail (report incorrect thread state).
-
- Parsing "status" file looks more promissing (due to different
- file structure and escaping special symbols) but reading and
- parsing of "status" file works slower.
-
- -- ln
- */
- char buffer[ 65 ];
- int len;
- len = read( stat_file, buffer, sizeof( buffer ) - 1 );
- if ( len >= 0 ) {
- buffer[ len ] = 0;
- // Using scanf:
- // sscanf( buffer, "%*d (%*s) %c ", & state );
- // looks very nice, but searching for a closing parenthesis works a
- // bit faster.
- char * close_parent = strstr( buffer, ") " );
- if ( close_parent != NULL ) {
- char state = * ( close_parent + 2 );
- if ( state == 'R' ) {
- ++ running_threads;
- if ( running_threads >= max ) {
- goto finish;
- }; // if
- }; // if
- }; // if
- }; // if
- close( stat_file );
- stat_file = -1;
- }; // if
- }; // if
- task_entry = readdir( task_dir );
- }; // while
- closedir( task_dir );
- task_dir = NULL;
- }; // if
- }; // if
- proc_entry = readdir( proc_dir );
- }; // while
-
- //
- // There _might_ be a timing hole where the thread executing this
- // code get skipped in the load balance, and running_threads is 0.
- // Assert in the debug builds only!!!
- //
- KMP_DEBUG_ASSERT( running_threads > 0 );
- if ( running_threads <= 0 ) {
- running_threads = 1;
- }
-
- finish: // Clean up and exit.
- if ( proc_dir != NULL ) {
- closedir( proc_dir );
- }; // if
- __kmp_str_buf_free( & task_path );
- if ( task_dir != NULL ) {
- closedir( task_dir );
- }; // if
- __kmp_str_buf_free( & stat_path );
- if ( stat_file != -1 ) {
- close( stat_file );
- }; // if
-
- glb_running_threads = running_threads;
-
- return running_threads;
-
-} // __kmp_get_load_balance
-
-# endif // KMP_OS_DARWIN
-
-#endif // USE_LOAD_BALANCE
-
-#if !(KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_MIC || (KMP_OS_LINUX && KMP_ARCH_AARCH64) || KMP_ARCH_PPC64)
-
-// we really only need the case with 1 argument, because CLANG always build
-// a struct of pointers to shared variables referenced in the outlined function
-int
-__kmp_invoke_microtask( microtask_t pkfn,
- int gtid, int tid,
- int argc, void *p_argv[]
-#if OMPT_SUPPORT
- , void **exit_frame_ptr
-#endif
-)
-{
-#if OMPT_SUPPORT
- *exit_frame_ptr = __builtin_frame_address(0);
-#endif
-
- switch (argc) {
- default:
- fprintf(stderr, "Too many args to microtask: %d!\n", argc);
- fflush(stderr);
- exit(-1);
- case 0:
- (*pkfn)(>id, &tid);
- break;
- case 1:
- (*pkfn)(>id, &tid, p_argv[0]);
- break;
- case 2:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1]);
- break;
- case 3:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2]);
- break;
- case 4:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3]);
- break;
- case 5:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4]);
- break;
- case 6:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
- p_argv[5]);
- break;
- case 7:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
- p_argv[5], p_argv[6]);
- break;
- case 8:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
- p_argv[5], p_argv[6], p_argv[7]);
- break;
- case 9:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
- p_argv[5], p_argv[6], p_argv[7], p_argv[8]);
- break;
- case 10:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
- p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9]);
- break;
- case 11:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
- p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10]);
- break;
- case 12:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
- p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
- p_argv[11]);
- break;
- case 13:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
- p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
- p_argv[11], p_argv[12]);
- break;
- case 14:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
- p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
- p_argv[11], p_argv[12], p_argv[13]);
- break;
- case 15:
- (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
- p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
- p_argv[11], p_argv[12], p_argv[13], p_argv[14]);
- break;
- }
-
-#if OMPT_SUPPORT
- *exit_frame_ptr = 0;
-#endif
-
- return 1;
-}
-
-#endif
-
-// end of file //
-
Removed: openmp/trunk/runtime/src/z_Windows_NT-586_util.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/z_Windows_NT-586_util.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/z_Windows_NT-586_util.c (original)
+++ openmp/trunk/runtime/src/z_Windows_NT-586_util.c (removed)
@@ -1,163 +0,0 @@
-/*
- * z_Windows_NT-586_util.c -- platform specific routines.
- */
-
-
-//===----------------------------------------------------------------------===//
-//
-// 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"
-
-#if (KMP_ARCH_X86 || KMP_ARCH_X86_64)
-/* Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to
- * use compare_and_store for these routines
- */
-
-kmp_int8
-__kmp_test_then_or8( volatile kmp_int8 *p, kmp_int8 d )
-{
- kmp_int8 old_value, new_value;
-
- old_value = TCR_1( *p );
- new_value = old_value | d;
-
- while ( ! __kmp_compare_and_store8 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_1( *p );
- new_value = old_value | d;
- }
- return old_value;
-}
-
-kmp_int8
-__kmp_test_then_and8( volatile kmp_int8 *p, kmp_int8 d )
-{
- kmp_int8 old_value, new_value;
-
- old_value = TCR_1( *p );
- new_value = old_value & d;
-
- while ( ! __kmp_compare_and_store8 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_1( *p );
- new_value = old_value & d;
- }
- return old_value;
-}
-
-kmp_int32
-__kmp_test_then_or32( volatile kmp_int32 *p, kmp_int32 d )
-{
- kmp_int32 old_value, new_value;
-
- old_value = TCR_4( *p );
- new_value = old_value | d;
-
- while ( ! __kmp_compare_and_store32 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_4( *p );
- new_value = old_value | d;
- }
- return old_value;
-}
-
-kmp_int32
-__kmp_test_then_and32( volatile kmp_int32 *p, kmp_int32 d )
-{
- kmp_int32 old_value, new_value;
-
- old_value = TCR_4( *p );
- new_value = old_value & d;
-
- while ( ! __kmp_compare_and_store32 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_4( *p );
- new_value = old_value & d;
- }
- return old_value;
-}
-
-kmp_int8
-__kmp_test_then_add8( volatile kmp_int8 *p, kmp_int8 d )
-{
- kmp_int64 old_value, new_value;
-
- old_value = TCR_1( *p );
- new_value = old_value + d;
- while ( ! __kmp_compare_and_store8 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_1( *p );
- new_value = old_value + d;
- }
- return old_value;
-}
-
-#if KMP_ARCH_X86
-kmp_int64
-__kmp_test_then_add64( volatile kmp_int64 *p, kmp_int64 d )
-{
- kmp_int64 old_value, new_value;
-
- old_value = TCR_8( *p );
- new_value = old_value + d;
- while ( ! __kmp_compare_and_store64 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_8( *p );
- new_value = old_value + d;
- }
- return old_value;
-}
-#endif /* KMP_ARCH_X86 */
-
-kmp_int64
-__kmp_test_then_or64( volatile kmp_int64 *p, kmp_int64 d )
-{
- kmp_int64 old_value, new_value;
-
- old_value = TCR_8( *p );
- new_value = old_value | d;
- while ( ! __kmp_compare_and_store64 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_8( *p );
- new_value = old_value | d;
- }
-
- return old_value;
-}
-
-kmp_int64
-__kmp_test_then_and64( volatile kmp_int64 *p, kmp_int64 d )
-{
- kmp_int64 old_value, new_value;
-
- old_value = TCR_8( *p );
- new_value = old_value & d;
- while ( ! __kmp_compare_and_store64 ( p, old_value, new_value ) )
- {
- KMP_CPU_PAUSE();
- old_value = TCR_8( *p );
- new_value = old_value & d;
- }
-
- return old_value;
-}
-
-#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
Removed: openmp/trunk/runtime/src/z_Windows_NT_util.c
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/z_Windows_NT_util.c?rev=289731&view=auto
==============================================================================
--- openmp/trunk/runtime/src/z_Windows_NT_util.c (original)
+++ openmp/trunk/runtime/src/z_Windows_NT_util.c (removed)
@@ -1,1772 +0,0 @@
-/*
- * z_Windows_NT_util.c -- platform specific routines.
- */
-
-
-//===----------------------------------------------------------------------===//
-//
-// 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_itt.h"
-#include "kmp_i18n.h"
-#include "kmp_io.h"
-#include "kmp_wait_release.h"
-#include "kmp_affinity.h"
-
-/* This code is related to NtQuerySystemInformation() function. This function
- is used in the Load balance algorithm for OMP_DYNAMIC=true to find the
- number of running threads in the system. */
-
-#include <ntstatus.h>
-#include <ntsecapi.h> // UNICODE_STRING
-
-enum SYSTEM_INFORMATION_CLASS {
- SystemProcessInformation = 5
-}; // SYSTEM_INFORMATION_CLASS
-
-struct CLIENT_ID {
- HANDLE UniqueProcess;
- HANDLE UniqueThread;
-}; // struct CLIENT_ID
-
-enum THREAD_STATE {
- StateInitialized,
- StateReady,
- StateRunning,
- StateStandby,
- StateTerminated,
- StateWait,
- StateTransition,
- StateUnknown
-}; // enum THREAD_STATE
-
-struct VM_COUNTERS {
- SIZE_T PeakVirtualSize;
- SIZE_T VirtualSize;
- ULONG PageFaultCount;
- SIZE_T PeakWorkingSetSize;
- SIZE_T WorkingSetSize;
- SIZE_T QuotaPeakPagedPoolUsage;
- SIZE_T QuotaPagedPoolUsage;
- SIZE_T QuotaPeakNonPagedPoolUsage;
- SIZE_T QuotaNonPagedPoolUsage;
- SIZE_T PagefileUsage;
- SIZE_T PeakPagefileUsage;
- SIZE_T PrivatePageCount;
-}; // struct VM_COUNTERS
-
-struct SYSTEM_THREAD {
- LARGE_INTEGER KernelTime;
- LARGE_INTEGER UserTime;
- LARGE_INTEGER CreateTime;
- ULONG WaitTime;
- LPVOID StartAddress;
- CLIENT_ID ClientId;
- DWORD Priority;
- LONG BasePriority;
- ULONG ContextSwitchCount;
- THREAD_STATE State;
- ULONG WaitReason;
-}; // SYSTEM_THREAD
-
-KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, KernelTime ) == 0 );
-#if KMP_ARCH_X86
- KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, StartAddress ) == 28 );
- KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, State ) == 52 );
-#else
- KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, StartAddress ) == 32 );
- KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, State ) == 68 );
-#endif
-
-struct SYSTEM_PROCESS_INFORMATION {
- ULONG NextEntryOffset;
- ULONG NumberOfThreads;
- LARGE_INTEGER Reserved[ 3 ];
- LARGE_INTEGER CreateTime;
- LARGE_INTEGER UserTime;
- LARGE_INTEGER KernelTime;
- UNICODE_STRING ImageName;
- DWORD BasePriority;
- HANDLE ProcessId;
- HANDLE ParentProcessId;
- ULONG HandleCount;
- ULONG Reserved2[ 2 ];
- VM_COUNTERS VMCounters;
- IO_COUNTERS IOCounters;
- SYSTEM_THREAD Threads[ 1 ];
-}; // SYSTEM_PROCESS_INFORMATION
-typedef SYSTEM_PROCESS_INFORMATION * PSYSTEM_PROCESS_INFORMATION;
-
-KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, NextEntryOffset ) == 0 );
-KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, CreateTime ) == 32 );
-KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, ImageName ) == 56 );
-#if KMP_ARCH_X86
- KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, ProcessId ) == 68 );
- KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, HandleCount ) == 76 );
- KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, VMCounters ) == 88 );
- KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, IOCounters ) == 136 );
- KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, Threads ) == 184 );
-#else
- KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, ProcessId ) == 80 );
- KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, HandleCount ) == 96 );
- KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, VMCounters ) == 112 );
- KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, IOCounters ) == 208 );
- KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, Threads ) == 256 );
-#endif
-
-typedef NTSTATUS (NTAPI *NtQuerySystemInformation_t)( SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG );
-NtQuerySystemInformation_t NtQuerySystemInformation = NULL;
-
-HMODULE ntdll = NULL;
-
-/* End of NtQuerySystemInformation()-related code */
-
-static HMODULE kernel32 = NULL;
-
-/* ----------------------------------------------------------------------------------- */
-/* ----------------------------------------------------------------------------------- */
-
-#if KMP_HANDLE_SIGNALS
- typedef void (* sig_func_t )( int );
- static sig_func_t __kmp_sighldrs[ NSIG ];
- static int __kmp_siginstalled[ NSIG ];
-#endif
-
-#if KMP_USE_MONITOR
-static HANDLE __kmp_monitor_ev;
-#endif
-static kmp_int64 __kmp_win32_time;
-double __kmp_win32_tick;
-
-int __kmp_init_runtime = FALSE;
-CRITICAL_SECTION __kmp_win32_section;
-
-void
-__kmp_win32_mutex_init( kmp_win32_mutex_t *mx )
-{
- InitializeCriticalSection( & mx->cs );
-#if USE_ITT_BUILD
- __kmp_itt_system_object_created( & mx->cs, "Critical Section" );
-#endif /* USE_ITT_BUILD */
-}
-
-void
-__kmp_win32_mutex_destroy( kmp_win32_mutex_t *mx )
-{
- DeleteCriticalSection( & mx->cs );
-}
-
-void
-__kmp_win32_mutex_lock( kmp_win32_mutex_t *mx )
-{
- EnterCriticalSection( & mx->cs );
-}
-
-void
-__kmp_win32_mutex_unlock( kmp_win32_mutex_t *mx )
-{
- LeaveCriticalSection( & mx->cs );
-}
-
-void
-__kmp_win32_cond_init( kmp_win32_cond_t *cv )
-{
- cv->waiters_count_ = 0;
- cv->wait_generation_count_ = 0;
- cv->release_count_ = 0;
-
- /* Initialize the critical section */
- __kmp_win32_mutex_init( & cv->waiters_count_lock_ );
-
- /* Create a manual-reset event. */
- cv->event_ = CreateEvent( NULL, // no security
- TRUE, // manual-reset
- FALSE, // non-signaled initially
- NULL ); // unnamed
-#if USE_ITT_BUILD
- __kmp_itt_system_object_created( cv->event_, "Event" );
-#endif /* USE_ITT_BUILD */
-}
-
-void
-__kmp_win32_cond_destroy( kmp_win32_cond_t *cv )
-{
- __kmp_win32_mutex_destroy( & cv->waiters_count_lock_ );
- __kmp_free_handle( cv->event_ );
- memset( cv, '\0', sizeof( *cv ) );
-}
-
-/* TODO associate cv with a team instead of a thread so as to optimize
- * the case where we wake up a whole team */
-
-void
-__kmp_win32_cond_wait( kmp_win32_cond_t *cv, kmp_win32_mutex_t *mx, kmp_info_t *th, int need_decrease_load )
-{
- int my_generation;
- int last_waiter;
-
- /* Avoid race conditions */
- __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
-
- /* Increment count of waiters */
- cv->waiters_count_++;
-
- /* Store current generation in our activation record. */
- my_generation = cv->wait_generation_count_;
-
- __kmp_win32_mutex_unlock( &cv->waiters_count_lock_ );
- __kmp_win32_mutex_unlock( mx );
-
- for (;;) {
- int wait_done;
-
- /* Wait until the event is signaled */
- WaitForSingleObject( cv->event_, INFINITE );
-
- __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
-
- /* Exit the loop when the <cv->event_> is signaled and
- * there are still waiting threads from this <wait_generation>
- * that haven't been released from this wait yet. */
- wait_done = ( cv->release_count_ > 0 ) &&
- ( cv->wait_generation_count_ != my_generation );
-
- __kmp_win32_mutex_unlock( &cv->waiters_count_lock_);
-
- /* there used to be a semicolon after the if statement,
- * it looked like a bug, so i removed it */
- if( wait_done )
- break;
- }
-
- __kmp_win32_mutex_lock( mx );
- __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
-
- cv->waiters_count_--;
- cv->release_count_--;
-
- last_waiter = ( cv->release_count_ == 0 );
-
- __kmp_win32_mutex_unlock( &cv->waiters_count_lock_ );
-
- if( last_waiter ) {
- /* We're the last waiter to be notified, so reset the manual event. */
- ResetEvent( cv->event_ );
- }
-}
-
-void
-__kmp_win32_cond_broadcast( kmp_win32_cond_t *cv )
-{
- __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
-
- if( cv->waiters_count_ > 0 ) {
- SetEvent( cv->event_ );
- /* Release all the threads in this generation. */
-
- cv->release_count_ = cv->waiters_count_;
-
- /* Start a new generation. */
- cv->wait_generation_count_++;
- }
-
- __kmp_win32_mutex_unlock( &cv->waiters_count_lock_ );
-}
-
-void
-__kmp_win32_cond_signal( kmp_win32_cond_t *cv )
-{
- __kmp_win32_cond_broadcast( cv );
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-void
-__kmp_enable( int new_state )
-{
- if (__kmp_init_runtime)
- LeaveCriticalSection( & __kmp_win32_section );
-}
-
-void
-__kmp_disable( int *old_state )
-{
- *old_state = 0;
-
- if (__kmp_init_runtime)
- EnterCriticalSection( & __kmp_win32_section );
-}
-
-void
-__kmp_suspend_initialize( void )
-{
- /* do nothing */
-}
-
-static void
-__kmp_suspend_initialize_thread( kmp_info_t *th )
-{
- if ( ! TCR_4( th->th.th_suspend_init ) ) {
- /* this means we haven't initialized the suspension pthread objects for this thread
- in this instance of the process */
- __kmp_win32_cond_init( &th->th.th_suspend_cv );
- __kmp_win32_mutex_init( &th->th.th_suspend_mx );
- TCW_4( th->th.th_suspend_init, TRUE );
- }
-}
-
-void
-__kmp_suspend_uninitialize_thread( kmp_info_t *th )
-{
- if ( TCR_4( th->th.th_suspend_init ) ) {
- /* this means we have initialize the suspension pthread objects for this thread
- in this instance of the process */
- __kmp_win32_cond_destroy( & th->th.th_suspend_cv );
- __kmp_win32_mutex_destroy( & th->th.th_suspend_mx );
- TCW_4( th->th.th_suspend_init, FALSE );
- }
-}
-
-/* This routine puts the calling thread to sleep after setting the
- * sleep bit for the indicated flag variable to true.
- */
-template <class C>
-static inline void __kmp_suspend_template( int th_gtid, C *flag )
-{
- kmp_info_t *th = __kmp_threads[th_gtid];
- int status;
- typename C::flag_t old_spin;
-
- KF_TRACE( 30, ("__kmp_suspend_template: T#%d enter for flag's loc(%p)\n", th_gtid, flag->get() ) );
-
- __kmp_suspend_initialize_thread( th );
- __kmp_win32_mutex_lock( &th->th.th_suspend_mx );
-
- KF_TRACE( 10, ( "__kmp_suspend_template: T#%d setting sleep bit for flag's loc(%p)\n",
- th_gtid, flag->get() ) );
-
- /* TODO: shouldn't this use release semantics to ensure that __kmp_suspend_initialize_thread
- gets called first?
- */
- old_spin = flag->set_sleeping();
-
- KF_TRACE( 5, ( "__kmp_suspend_template: T#%d set sleep bit for flag's loc(%p)==%d\n",
- th_gtid, flag->get(), *(flag->get()) ) );
-
- if ( flag->done_check_val(old_spin) ) {
- old_spin = flag->unset_sleeping();
- KF_TRACE( 5, ( "__kmp_suspend_template: T#%d false alarm, reset sleep bit for flag's loc(%p)\n",
- th_gtid, flag->get()) );
- } else {
-#ifdef DEBUG_SUSPEND
- __kmp_suspend_count++;
-#endif
- /* Encapsulate in a loop as the documentation states that this may
- * "with low probability" return when the condition variable has
- * not been signaled or broadcast
- */
- int deactivated = FALSE;
- TCW_PTR(th->th.th_sleep_loc, (void *)flag);
- while ( flag->is_sleeping() ) {
- KF_TRACE( 15, ("__kmp_suspend_template: T#%d about to perform kmp_win32_cond_wait()\n",
- th_gtid ) );
- // Mark the thread as no longer active (only in the first iteration of the loop).
- if ( ! deactivated ) {
- th->th.th_active = FALSE;
- if ( th->th.th_active_in_pool ) {
- th->th.th_active_in_pool = FALSE;
- KMP_TEST_THEN_DEC32(
- (kmp_int32 *) &__kmp_thread_pool_active_nth );
- KMP_DEBUG_ASSERT( TCR_4(__kmp_thread_pool_active_nth) >= 0 );
- }
- deactivated = TRUE;
-
- __kmp_win32_cond_wait( &th->th.th_suspend_cv, &th->th.th_suspend_mx, 0, 0 );
- }
- else {
- __kmp_win32_cond_wait( &th->th.th_suspend_cv, &th->th.th_suspend_mx, 0, 0 );
- }
-
-#ifdef KMP_DEBUG
- if( flag->is_sleeping() ) {
- KF_TRACE( 100, ("__kmp_suspend_template: T#%d spurious wakeup\n", th_gtid ));
- }
-#endif /* KMP_DEBUG */
-
- } // while
-
- // Mark the thread as active again (if it was previous marked as inactive)
- if ( deactivated ) {
- th->th.th_active = TRUE;
- if ( TCR_4(th->th.th_in_pool) ) {
- KMP_TEST_THEN_INC32(
- (kmp_int32 *) &__kmp_thread_pool_active_nth );
- th->th.th_active_in_pool = TRUE;
- }
- }
- }
-
- __kmp_win32_mutex_unlock( &th->th.th_suspend_mx );
-
- KF_TRACE( 30, ("__kmp_suspend_template: T#%d exit\n", th_gtid ) );
-}
-
-void __kmp_suspend_32(int th_gtid, kmp_flag_32 *flag) {
- __kmp_suspend_template(th_gtid, flag);
-}
-void __kmp_suspend_64(int th_gtid, kmp_flag_64 *flag) {
- __kmp_suspend_template(th_gtid, flag);
-}
-void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag) {
- __kmp_suspend_template(th_gtid, flag);
-}
-
-
-/* This routine signals the thread specified by target_gtid to wake up
- * after setting the sleep bit indicated by the flag argument to FALSE
- */
-template <class C>
-static inline void __kmp_resume_template( int target_gtid, C *flag )
-{
- kmp_info_t *th = __kmp_threads[target_gtid];
- int status;
-
-#ifdef KMP_DEBUG
- int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
-#endif
-
- KF_TRACE( 30, ( "__kmp_resume_template: T#%d wants to wakeup T#%d enter\n", gtid, target_gtid ) );
-
- __kmp_suspend_initialize_thread( th );
- __kmp_win32_mutex_lock( &th->th.th_suspend_mx );
-
- if (!flag) { // coming from __kmp_null_resume_wrapper
- flag = (C *)th->th.th_sleep_loc;
- }
-
- // First, check if the flag is null or its type has changed. If so, someone else woke it up.
- if (!flag || flag->get_type() != flag->get_ptr_type()) { // get_ptr_type simply shows what flag was cast to
- KF_TRACE( 5, ( "__kmp_resume_template: T#%d exiting, thread T#%d already awake: flag's loc(%p)\n",
- gtid, target_gtid, NULL ) );
- __kmp_win32_mutex_unlock( &th->th.th_suspend_mx );
- return;
- }
- else {
- typename C::flag_t old_spin = flag->unset_sleeping();
- if ( !flag->is_sleeping_val(old_spin) ) {
- KF_TRACE( 5, ( "__kmp_resume_template: T#%d exiting, thread T#%d already awake: flag's loc(%p): "
- "%u => %u\n",
- gtid, target_gtid, flag->get(), old_spin, *(flag->get()) ) );
- __kmp_win32_mutex_unlock( &th->th.th_suspend_mx );
- return;
- }
- }
- TCW_PTR(th->th.th_sleep_loc, NULL);
-
- KF_TRACE( 5, ( "__kmp_resume_template: T#%d about to wakeup T#%d, reset sleep bit for flag's loc(%p)\n",
- gtid, target_gtid, flag->get() ) );
-
- __kmp_win32_cond_signal( &th->th.th_suspend_cv );
- __kmp_win32_mutex_unlock( &th->th.th_suspend_mx );
-
- KF_TRACE( 30, ( "__kmp_resume_template: T#%d exiting after signaling wake up for T#%d\n",
- gtid, target_gtid ) );
-}
-
-void __kmp_resume_32(int target_gtid, kmp_flag_32 *flag) {
- __kmp_resume_template(target_gtid, flag);
-}
-void __kmp_resume_64(int target_gtid, kmp_flag_64 *flag) {
- __kmp_resume_template(target_gtid, flag);
-}
-void __kmp_resume_oncore(int target_gtid, kmp_flag_oncore *flag) {
- __kmp_resume_template(target_gtid, flag);
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-void
-__kmp_yield( int cond )
-{
- if (cond)
- Sleep(0);
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-void
-__kmp_gtid_set_specific( int gtid )
-{
- if( __kmp_init_gtid ) {
- KA_TRACE( 50, ("__kmp_gtid_set_specific: T#%d key:%d\n",
- gtid, __kmp_gtid_threadprivate_key ));
- if( ! TlsSetValue( __kmp_gtid_threadprivate_key, (LPVOID)(gtid+1)) )
- KMP_FATAL( TLSSetValueFailed );
- } else {
- KA_TRACE( 50, ("__kmp_gtid_set_specific: runtime shutdown, returning\n" ) );
- }
-}
-
-int
-__kmp_gtid_get_specific()
-{
- int gtid;
- if( !__kmp_init_gtid ) {
- KA_TRACE( 50, ("__kmp_gtid_get_specific: runtime shutdown, returning KMP_GTID_SHUTDOWN\n" ) );
- return KMP_GTID_SHUTDOWN;
- }
- gtid = (int)(kmp_intptr_t)TlsGetValue( __kmp_gtid_threadprivate_key );
- if ( gtid == 0 ) {
- gtid = KMP_GTID_DNE;
- }
- else {
- gtid--;
- }
- KA_TRACE( 50, ("__kmp_gtid_get_specific: key:%d gtid:%d\n",
- __kmp_gtid_threadprivate_key, gtid ));
- return gtid;
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-void
-__kmp_affinity_bind_thread( int proc )
-{
- if (__kmp_num_proc_groups > 1) {
- //
- // Form the GROUP_AFFINITY struct directly, rather than filling
- // out a bit vector and calling __kmp_set_system_affinity().
- //
- GROUP_AFFINITY ga;
- KMP_DEBUG_ASSERT((proc >= 0) && (proc < (__kmp_num_proc_groups
- * CHAR_BIT * sizeof(DWORD_PTR))));
- ga.Group = proc / (CHAR_BIT * sizeof(DWORD_PTR));
- ga.Mask = (unsigned long long)1 << (proc % (CHAR_BIT * sizeof(DWORD_PTR)));
- ga.Reserved[0] = ga.Reserved[1] = ga.Reserved[2] = 0;
-
- KMP_DEBUG_ASSERT(__kmp_SetThreadGroupAffinity != NULL);
- if (__kmp_SetThreadGroupAffinity(GetCurrentThread(), &ga, NULL) == 0) {
- DWORD error = GetLastError();
- if (__kmp_affinity_verbose) { // AC: continue silently if not verbose
- kmp_msg_t err_code = KMP_ERR( error );
- __kmp_msg(
- kmp_ms_warning,
- KMP_MSG( CantSetThreadAffMask ),
- err_code,
- __kmp_msg_null
- );
- if (__kmp_generate_warnings == kmp_warnings_off) {
- __kmp_str_free(&err_code.str);
- }
- }
- }
- } else {
- kmp_affin_mask_t *mask;
- KMP_CPU_ALLOC_ON_STACK(mask);
- KMP_CPU_ZERO(mask);
- KMP_CPU_SET(proc, mask);
- __kmp_set_system_affinity(mask, TRUE);
- KMP_CPU_FREE_FROM_STACK(mask);
- }
-}
-
-void
-__kmp_affinity_determine_capable( const char *env_var )
-{
- //
- // All versions of Windows* OS (since Win '95) support SetThreadAffinityMask().
- //
-
-#if KMP_GROUP_AFFINITY
- KMP_AFFINITY_ENABLE(__kmp_num_proc_groups*sizeof(DWORD_PTR));
-#else
- KMP_AFFINITY_ENABLE(sizeof(DWORD_PTR));
-#endif
-
- KA_TRACE( 10, (
- "__kmp_affinity_determine_capable: "
- "Windows* OS affinity interface functional (mask size = %" KMP_SIZE_T_SPEC ").\n",
- __kmp_affin_mask_size
- ) );
-}
-
-double
-__kmp_read_cpu_time( void )
-{
- FILETIME CreationTime, ExitTime, KernelTime, UserTime;
- int status;
- double cpu_time;
-
- cpu_time = 0;
-
- status = GetProcessTimes( GetCurrentProcess(), &CreationTime,
- &ExitTime, &KernelTime, &UserTime );
-
- if (status) {
- double sec = 0;
-
- sec += KernelTime.dwHighDateTime;
- sec += UserTime.dwHighDateTime;
-
- /* Shift left by 32 bits */
- sec *= (double) (1 << 16) * (double) (1 << 16);
-
- sec += KernelTime.dwLowDateTime;
- sec += UserTime.dwLowDateTime;
-
- cpu_time += (sec * 100.0) / KMP_NSEC_PER_SEC;
- }
-
- return cpu_time;
-}
-
-int
-__kmp_read_system_info( struct kmp_sys_info *info )
-{
- info->maxrss = 0; /* the maximum resident set size utilized (in kilobytes) */
- info->minflt = 0; /* the number of page faults serviced without any I/O */
- info->majflt = 0; /* the number of page faults serviced that required I/O */
- info->nswap = 0; /* the number of times a process was "swapped" out of memory */
- info->inblock = 0; /* the number of times the file system had to perform input */
- info->oublock = 0; /* the number of times the file system had to perform output */
- info->nvcsw = 0; /* the number of times a context switch was voluntarily */
- info->nivcsw = 0; /* the number of times a context switch was forced */
-
- return 1;
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-
-void
-__kmp_runtime_initialize( void )
-{
- SYSTEM_INFO info;
- kmp_str_buf_t path;
- UINT path_size;
-
- if ( __kmp_init_runtime ) {
- return;
- };
-
-#if KMP_DYNAMIC_LIB
- /* Pin dynamic library for the lifetime of application */
- {
- // First, turn off error message boxes
- UINT err_mode = SetErrorMode (SEM_FAILCRITICALERRORS);
- HMODULE h;
- BOOL ret = GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
- |GET_MODULE_HANDLE_EX_FLAG_PIN,
- (LPCTSTR)&__kmp_serial_initialize, &h);
- KMP_DEBUG_ASSERT2(h && ret, "OpenMP RTL cannot find itself loaded");
- SetErrorMode (err_mode); // Restore error mode
- KA_TRACE( 10, ("__kmp_runtime_initialize: dynamic library pinned\n") );
- }
-#endif
-
- InitializeCriticalSection( & __kmp_win32_section );
-#if USE_ITT_BUILD
- __kmp_itt_system_object_created( & __kmp_win32_section, "Critical Section" );
-#endif /* USE_ITT_BUILD */
- __kmp_initialize_system_tick();
-
- #if (KMP_ARCH_X86 || KMP_ARCH_X86_64)
- if ( ! __kmp_cpuinfo.initialized ) {
- __kmp_query_cpuid( & __kmp_cpuinfo );
- }; // if
- #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
-
- /* Set up minimum number of threads to switch to TLS gtid */
- #if KMP_OS_WINDOWS && ! defined KMP_DYNAMIC_LIB
- // Windows* OS, static library.
- /*
- New thread may use stack space previously used by another thread, currently terminated.
- On Windows* OS, in case of static linking, we do not know the moment of thread termination,
- and our structures (__kmp_threads and __kmp_root arrays) are still keep info about dead
- threads. This leads to problem in __kmp_get_global_thread_id() function: it wrongly
- finds gtid (by searching through stack addresses of all known threads) for unregistered
- foreign tread.
-
- Setting __kmp_tls_gtid_min to 0 workarounds this problem: __kmp_get_global_thread_id()
- does not search through stacks, but get gtid from TLS immediately.
-
- --ln
- */
- __kmp_tls_gtid_min = 0;
- #else
- __kmp_tls_gtid_min = KMP_TLS_GTID_MIN;
- #endif
-
- /* for the static library */
- if ( !__kmp_gtid_threadprivate_key ) {
- __kmp_gtid_threadprivate_key = TlsAlloc();
- if( __kmp_gtid_threadprivate_key == TLS_OUT_OF_INDEXES ) {
- KMP_FATAL( TLSOutOfIndexes );
- }
- }
-
-
- //
- // Load ntdll.dll.
- //
- /*
- Simple
- GetModuleHandle( "ntdll.dl" )
- is not suitable due to security issue (see
- http://www.microsoft.com/technet/security/advisory/2269637.mspx). We have to specify full
- path to the library.
- */
- __kmp_str_buf_init( & path );
- path_size = GetSystemDirectory( path.str, path.size );
- KMP_DEBUG_ASSERT( path_size > 0 );
- if ( path_size >= path.size ) {
- //
- // Buffer is too short. Expand the buffer and try again.
- //
- __kmp_str_buf_reserve( & path, path_size );
- path_size = GetSystemDirectory( path.str, path.size );
- KMP_DEBUG_ASSERT( path_size > 0 );
- }; // if
- if ( path_size > 0 && path_size < path.size ) {
- //
- // Now we have system directory name in the buffer.
- // Append backslash and name of dll to form full path,
- //
- path.used = path_size;
- __kmp_str_buf_print( & path, "\\%s", "ntdll.dll" );
-
- //
- // Now load ntdll using full path.
- //
- ntdll = GetModuleHandle( path.str );
- }
-
- KMP_DEBUG_ASSERT( ntdll != NULL );
- if ( ntdll != NULL ) {
- NtQuerySystemInformation = (NtQuerySystemInformation_t) GetProcAddress( ntdll, "NtQuerySystemInformation" );
- }
- KMP_DEBUG_ASSERT( NtQuerySystemInformation != NULL );
-
-#if KMP_GROUP_AFFINITY
- //
- // Load kernel32.dll.
- // Same caveat - must use full system path name.
- //
- if ( path_size > 0 && path_size < path.size ) {
- //
- // Truncate the buffer back to just the system path length,
- // discarding "\\ntdll.dll", and replacing it with "kernel32.dll".
- //
- path.used = path_size;
- __kmp_str_buf_print( & path, "\\%s", "kernel32.dll" );
-
- //
- // Load kernel32.dll using full path.
- //
- kernel32 = GetModuleHandle( path.str );
- KA_TRACE( 10, ("__kmp_runtime_initialize: kernel32.dll = %s\n", path.str ) );
-
- //
- // Load the function pointers to kernel32.dll routines
- // that may or may not exist on this system.
- //
- if ( kernel32 != NULL ) {
- __kmp_GetActiveProcessorCount = (kmp_GetActiveProcessorCount_t) GetProcAddress( kernel32, "GetActiveProcessorCount" );
- __kmp_GetActiveProcessorGroupCount = (kmp_GetActiveProcessorGroupCount_t) GetProcAddress( kernel32, "GetActiveProcessorGroupCount" );
- __kmp_GetThreadGroupAffinity = (kmp_GetThreadGroupAffinity_t) GetProcAddress( kernel32, "GetThreadGroupAffinity" );
- __kmp_SetThreadGroupAffinity = (kmp_SetThreadGroupAffinity_t) GetProcAddress( kernel32, "SetThreadGroupAffinity" );
-
- KA_TRACE( 10, ("__kmp_runtime_initialize: __kmp_GetActiveProcessorCount = %p\n", __kmp_GetActiveProcessorCount ) );
- KA_TRACE( 10, ("__kmp_runtime_initialize: __kmp_GetActiveProcessorGroupCount = %p\n", __kmp_GetActiveProcessorGroupCount ) );
- KA_TRACE( 10, ("__kmp_runtime_initialize:__kmp_GetThreadGroupAffinity = %p\n", __kmp_GetThreadGroupAffinity ) );
- KA_TRACE( 10, ("__kmp_runtime_initialize: __kmp_SetThreadGroupAffinity = %p\n", __kmp_SetThreadGroupAffinity ) );
- KA_TRACE( 10, ("__kmp_runtime_initialize: sizeof(kmp_affin_mask_t) = %d\n", sizeof(kmp_affin_mask_t) ) );
-
- //
- // See if group affinity is supported on this system.
- // If so, calculate the #groups and #procs.
- //
- // Group affinity was introduced with Windows* 7 OS and
- // Windows* Server 2008 R2 OS.
- //
- if ( ( __kmp_GetActiveProcessorCount != NULL )
- && ( __kmp_GetActiveProcessorGroupCount != NULL )
- && ( __kmp_GetThreadGroupAffinity != NULL )
- && ( __kmp_SetThreadGroupAffinity != NULL )
- && ( ( __kmp_num_proc_groups
- = __kmp_GetActiveProcessorGroupCount() ) > 1 ) ) {
- //
- // Calculate the total number of active OS procs.
- //
- int i;
-
- KA_TRACE( 10, ("__kmp_runtime_initialize: %d processor groups detected\n", __kmp_num_proc_groups ) );
-
- __kmp_xproc = 0;
-
- for ( i = 0; i < __kmp_num_proc_groups; i++ ) {
- DWORD size = __kmp_GetActiveProcessorCount( i );
- __kmp_xproc += size;
- KA_TRACE( 10, ("__kmp_runtime_initialize: proc group %d size = %d\n", i, size ) );
- }
- }
- else {
- KA_TRACE( 10, ("__kmp_runtime_initialize: %d processor groups detected\n", __kmp_num_proc_groups ) );
- }
- }
- }
- if ( __kmp_num_proc_groups <= 1 ) {
- GetSystemInfo( & info );
- __kmp_xproc = info.dwNumberOfProcessors;
- }
-#else
- GetSystemInfo( & info );
- __kmp_xproc = info.dwNumberOfProcessors;
-#endif /* KMP_GROUP_AFFINITY */
-
- //
- // If the OS said there were 0 procs, take a guess and use a value of 2.
- // This is done for Linux* OS, also. Do we need error / warning?
- //
- if ( __kmp_xproc <= 0 ) {
- __kmp_xproc = 2;
- }
-
- KA_TRACE( 5, ("__kmp_runtime_initialize: total processors = %d\n", __kmp_xproc) );
-
- __kmp_str_buf_free( & path );
-
-#if USE_ITT_BUILD
- __kmp_itt_initialize();
-#endif /* USE_ITT_BUILD */
-
- __kmp_init_runtime = TRUE;
-} // __kmp_runtime_initialize
-
-void
-__kmp_runtime_destroy( void )
-{
- if ( ! __kmp_init_runtime ) {
- return;
- }
-
-#if USE_ITT_BUILD
- __kmp_itt_destroy();
-#endif /* USE_ITT_BUILD */
-
- /* we can't DeleteCriticalsection( & __kmp_win32_section ); */
- /* due to the KX_TRACE() commands */
- KA_TRACE( 40, ("__kmp_runtime_destroy\n" ));
-
- if( __kmp_gtid_threadprivate_key ) {
- TlsFree( __kmp_gtid_threadprivate_key );
- __kmp_gtid_threadprivate_key = 0;
- }
-
- __kmp_affinity_uninitialize();
- DeleteCriticalSection( & __kmp_win32_section );
-
- ntdll = NULL;
- NtQuerySystemInformation = NULL;
-
-#if KMP_ARCH_X86_64
- kernel32 = NULL;
- __kmp_GetActiveProcessorCount = NULL;
- __kmp_GetActiveProcessorGroupCount = NULL;
- __kmp_GetThreadGroupAffinity = NULL;
- __kmp_SetThreadGroupAffinity = NULL;
-#endif // KMP_ARCH_X86_64
-
- __kmp_init_runtime = FALSE;
-}
-
-
-void
-__kmp_terminate_thread( int gtid )
-{
- kmp_info_t *th = __kmp_threads[ gtid ];
-
- if( !th ) return;
-
- KA_TRACE( 10, ("__kmp_terminate_thread: kill (%d)\n", gtid ) );
-
- if (TerminateThread( th->th.th_info.ds.ds_thread, (DWORD) -1) == FALSE) {
- /* It's OK, the thread may have exited already */
- }
- __kmp_free_handle( th->th.th_info.ds.ds_thread );
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-void
-__kmp_clear_system_time( void )
-{
- BOOL status;
- LARGE_INTEGER time;
- status = QueryPerformanceCounter( & time );
- __kmp_win32_time = (kmp_int64) time.QuadPart;
-}
-
-void
-__kmp_initialize_system_tick( void )
-{
- {
- BOOL status;
- LARGE_INTEGER freq;
-
- status = QueryPerformanceFrequency( & freq );
- if (! status) {
- DWORD error = GetLastError();
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( FunctionError, "QueryPerformanceFrequency()" ),
- KMP_ERR( error ),
- __kmp_msg_null
- );
-
- }
- else {
- __kmp_win32_tick = ((double) 1.0) / (double) freq.QuadPart;
- }
- }
-}
-
-/* Calculate the elapsed wall clock time for the user */
-
-void
-__kmp_elapsed( double *t )
-{
- BOOL status;
- LARGE_INTEGER now;
- status = QueryPerformanceCounter( & now );
- *t = ((double) now.QuadPart) * __kmp_win32_tick;
-}
-
-/* Calculate the elapsed wall clock tick for the user */
-
-void
-__kmp_elapsed_tick( double *t )
-{
- *t = __kmp_win32_tick;
-}
-
-void
-__kmp_read_system_time( double *delta )
-{
- if (delta != NULL) {
- BOOL status;
- LARGE_INTEGER now;
-
- status = QueryPerformanceCounter( & now );
-
- *delta = ((double) (((kmp_int64) now.QuadPart) - __kmp_win32_time))
- * __kmp_win32_tick;
- }
-}
-
-/* Return the current time stamp in nsec */
-kmp_uint64
-__kmp_now_nsec()
-{
- LARGE_INTEGER now;
- QueryPerformanceCounter(&now);
- return 1e9 * __kmp_win32_tick * now.QuadPart;
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-void * __stdcall
-__kmp_launch_worker( void *arg )
-{
- volatile void *stack_data;
- void *exit_val;
- void *padding = 0;
- kmp_info_t *this_thr = (kmp_info_t *) arg;
- int gtid;
-
- gtid = this_thr->th.th_info.ds.ds_gtid;
- __kmp_gtid_set_specific( gtid );
-#ifdef KMP_TDATA_GTID
- #error "This define causes problems with LoadLibrary() + declspec(thread) " \
- "on Windows* OS. See CQ50564, tests kmp_load_library*.c and this MSDN " \
- "reference: http://support.microsoft.com/kb/118816"
- //__kmp_gtid = gtid;
-#endif
-
-#if USE_ITT_BUILD
- __kmp_itt_thread_name( gtid );
-#endif /* USE_ITT_BUILD */
-
- __kmp_affinity_set_init_mask( gtid, FALSE );
-
-#if KMP_ARCH_X86 || KMP_ARCH_X86_64
- //
- // Set the FP control regs to be a copy of
- // the parallel initialization thread's.
- //
- __kmp_clear_x87_fpu_status_word();
- __kmp_load_x87_fpu_control_word( &__kmp_init_x87_fpu_control_word );
- __kmp_load_mxcsr( &__kmp_init_mxcsr );
-#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
-
- if ( __kmp_stkoffset > 0 && gtid > 0 ) {
- padding = KMP_ALLOCA( gtid * __kmp_stkoffset );
- }
-
- KMP_FSYNC_RELEASING( &this_thr -> th.th_info.ds.ds_alive );
- this_thr -> th.th_info.ds.ds_thread_id = GetCurrentThreadId();
- TCW_4( this_thr -> th.th_info.ds.ds_alive, TRUE );
-
- if ( TCR_4(__kmp_gtid_mode) < 2 ) { // check stack only if it is used to get gtid
- TCW_PTR(this_thr->th.th_info.ds.ds_stackbase, &stack_data);
- KMP_ASSERT( this_thr -> th.th_info.ds.ds_stackgrow == FALSE );
- __kmp_check_stack_overlap( this_thr );
- }
- KMP_MB();
- exit_val = __kmp_launch_thread( this_thr );
- KMP_FSYNC_RELEASING( &this_thr -> th.th_info.ds.ds_alive );
- TCW_4( this_thr -> th.th_info.ds.ds_alive, FALSE );
- KMP_MB();
- return exit_val;
-}
-
-#if KMP_USE_MONITOR
-/* The monitor thread controls all of the threads in the complex */
-
-void * __stdcall
-__kmp_launch_monitor( void *arg )
-{
- DWORD wait_status;
- kmp_thread_t monitor;
- int status;
- int interval;
- kmp_info_t *this_thr = (kmp_info_t *) arg;
-
- KMP_DEBUG_ASSERT(__kmp_init_monitor);
- TCW_4( __kmp_init_monitor, 2 ); // AC: Signal the library that monitor has started
- // TODO: hide "2" in enum (like {true,false,started})
- this_thr -> th.th_info.ds.ds_thread_id = GetCurrentThreadId();
- TCW_4( this_thr -> th.th_info.ds.ds_alive, TRUE );
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
- KA_TRACE( 10, ("__kmp_launch_monitor: launched\n" ) );
-
- monitor = GetCurrentThread();
-
- /* set thread priority */
- status = SetThreadPriority( monitor, THREAD_PRIORITY_HIGHEST );
- if (! status) {
- DWORD error = GetLastError();
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( CantSetThreadPriority ),
- KMP_ERR( error ),
- __kmp_msg_null
- );
- }
-
- /* register us as monitor */
- __kmp_gtid_set_specific( KMP_GTID_MONITOR );
-#ifdef KMP_TDATA_GTID
- #error "This define causes problems with LoadLibrary() + declspec(thread) " \
- "on Windows* OS. See CQ50564, tests kmp_load_library*.c and this MSDN " \
- "reference: http://support.microsoft.com/kb/118816"
- //__kmp_gtid = KMP_GTID_MONITOR;
-#endif
-
-#if USE_ITT_BUILD
- __kmp_itt_thread_ignore(); // Instruct Intel(R) Threading Tools to ignore monitor thread.
-#endif /* USE_ITT_BUILD */
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- interval = ( 1000 / __kmp_monitor_wakeups ); /* in milliseconds */
-
- while (! TCR_4(__kmp_global.g.g_done)) {
- /* This thread monitors the state of the system */
-
- KA_TRACE( 15, ( "__kmp_launch_monitor: update\n" ) );
-
- wait_status = WaitForSingleObject( __kmp_monitor_ev, interval );
-
- if (wait_status == WAIT_TIMEOUT) {
- TCW_4( __kmp_global.g.g_time.dt.t_value,
- TCR_4( __kmp_global.g.g_time.dt.t_value ) + 1 );
- }
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
- }
-
- KA_TRACE( 10, ("__kmp_launch_monitor: finished\n" ) );
-
- status = SetThreadPriority( monitor, THREAD_PRIORITY_NORMAL );
- if (! status) {
- DWORD error = GetLastError();
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( CantSetThreadPriority ),
- KMP_ERR( error ),
- __kmp_msg_null
- );
- }
-
- if (__kmp_global.g.g_abort != 0) {
- /* now we need to terminate the worker threads */
- /* the value of t_abort is the signal we caught */
-
- int gtid;
-
- KA_TRACE( 10, ("__kmp_launch_monitor: terminate sig=%d\n", (__kmp_global.g.g_abort) ) );
-
- /* terminate the OpenMP worker threads */
- /* TODO this is not valid for sibling threads!!
- * the uber master might not be 0 anymore.. */
- for (gtid = 1; gtid < __kmp_threads_capacity; ++gtid)
- __kmp_terminate_thread( gtid );
-
- __kmp_cleanup();
-
- Sleep( 0 );
-
- KA_TRACE( 10, ("__kmp_launch_monitor: raise sig=%d\n", (__kmp_global.g.g_abort) ) );
-
- if (__kmp_global.g.g_abort > 0) {
- raise( __kmp_global.g.g_abort );
- }
- }
-
- TCW_4( this_thr -> th.th_info.ds.ds_alive, FALSE );
-
- KMP_MB();
- return arg;
-}
-#endif
-
-void
-__kmp_create_worker( int gtid, kmp_info_t *th, size_t stack_size )
-{
- kmp_thread_t handle;
- DWORD idThread;
-
- KA_TRACE( 10, ("__kmp_create_worker: try to create thread (%d)\n", gtid ) );
-
- th->th.th_info.ds.ds_gtid = gtid;
-
- if ( KMP_UBER_GTID(gtid) ) {
- int stack_data;
-
- /* TODO: GetCurrentThread() returns a pseudo-handle that is unsuitable for other threads to use.
- Is it appropriate to just use GetCurrentThread? When should we close this handle? When
- unregistering the root?
- */
- {
- BOOL rc;
- rc = DuplicateHandle(
- GetCurrentProcess(),
- GetCurrentThread(),
- GetCurrentProcess(),
- &th->th.th_info.ds.ds_thread,
- 0,
- FALSE,
- DUPLICATE_SAME_ACCESS
- );
- KMP_ASSERT( rc );
- KA_TRACE( 10, (" __kmp_create_worker: ROOT Handle duplicated, th = %p, handle = %" KMP_UINTPTR_SPEC "\n",
- (LPVOID)th,
- th->th.th_info.ds.ds_thread ) );
- th->th.th_info.ds.ds_thread_id = GetCurrentThreadId();
- }
- if ( TCR_4(__kmp_gtid_mode) < 2 ) { // check stack only if it is used to get gtid
- /* we will dynamically update the stack range if gtid_mode == 1 */
- TCW_PTR(th->th.th_info.ds.ds_stackbase, &stack_data);
- TCW_PTR(th->th.th_info.ds.ds_stacksize, 0);
- TCW_4(th->th.th_info.ds.ds_stackgrow, TRUE);
- __kmp_check_stack_overlap( th );
- }
- }
- else {
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- /* Set stack size for this thread now. */
- KA_TRACE( 10, ( "__kmp_create_worker: stack_size = %" KMP_SIZE_T_SPEC
- " bytes\n", stack_size ) );
-
- stack_size += gtid * __kmp_stkoffset;
-
- TCW_PTR(th->th.th_info.ds.ds_stacksize, stack_size);
- TCW_4(th->th.th_info.ds.ds_stackgrow, FALSE);
-
- KA_TRACE( 10, ( "__kmp_create_worker: (before) stack_size = %"
- KMP_SIZE_T_SPEC
- " bytes, &__kmp_launch_worker = %p, th = %p, "
- "&idThread = %p\n",
- (SIZE_T) stack_size,
- (LPTHREAD_START_ROUTINE) & __kmp_launch_worker,
- (LPVOID) th, &idThread ) );
-
- handle = CreateThread( NULL, (SIZE_T) stack_size,
- (LPTHREAD_START_ROUTINE) __kmp_launch_worker,
- (LPVOID) th, STACK_SIZE_PARAM_IS_A_RESERVATION, &idThread );
-
- KA_TRACE( 10, ( "__kmp_create_worker: (after) stack_size = %"
- KMP_SIZE_T_SPEC
- " bytes, &__kmp_launch_worker = %p, th = %p, "
- "idThread = %u, handle = %" KMP_UINTPTR_SPEC "\n",
- (SIZE_T) stack_size,
- (LPTHREAD_START_ROUTINE) & __kmp_launch_worker,
- (LPVOID) th, idThread, handle ) );
-
- if ( handle == 0 ) {
- DWORD error = GetLastError();
- __kmp_msg(kmp_ms_fatal, KMP_MSG( CantCreateThread ), KMP_ERR( error ), __kmp_msg_null);
- } else {
- th->th.th_info.ds.ds_thread = handle;
- }
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
- }
-
- KA_TRACE( 10, ("__kmp_create_worker: done creating thread (%d)\n", gtid ) );
-}
-
-int
-__kmp_still_running(kmp_info_t *th) {
- return (WAIT_TIMEOUT == WaitForSingleObject( th->th.th_info.ds.ds_thread, 0));
-}
-
-#if KMP_USE_MONITOR
-void
-__kmp_create_monitor( kmp_info_t *th )
-{
- kmp_thread_t handle;
- DWORD idThread;
- int ideal, new_ideal;
-
- if( __kmp_dflt_blocktime == KMP_MAX_BLOCKTIME ) {
- // We don't need monitor thread in case of MAX_BLOCKTIME
- KA_TRACE( 10, ("__kmp_create_monitor: skipping monitor thread because of MAX blocktime\n" ) );
- th->th.th_info.ds.ds_tid = 0; // this makes reap_monitor no-op
- th->th.th_info.ds.ds_gtid = 0;
- TCW_4( __kmp_init_monitor, 2 ); // Signal to stop waiting for monitor creation
- return;
- }
- KA_TRACE( 10, ("__kmp_create_monitor: try to create monitor\n" ) );
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- __kmp_monitor_ev = CreateEvent( NULL, TRUE, FALSE, NULL );
- if ( __kmp_monitor_ev == NULL ) {
- DWORD error = GetLastError();
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( CantCreateEvent ),
- KMP_ERR( error ),
- __kmp_msg_null
- );
- }; // if
-#if USE_ITT_BUILD
- __kmp_itt_system_object_created( __kmp_monitor_ev, "Event" );
-#endif /* USE_ITT_BUILD */
-
- th->th.th_info.ds.ds_tid = KMP_GTID_MONITOR;
- th->th.th_info.ds.ds_gtid = KMP_GTID_MONITOR;
-
- // FIXME - on Windows* OS, if __kmp_monitor_stksize = 0, figure out how
- // to automatically expand stacksize based on CreateThread error code.
- if ( __kmp_monitor_stksize == 0 ) {
- __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
- }
- if ( __kmp_monitor_stksize < __kmp_sys_min_stksize ) {
- __kmp_monitor_stksize = __kmp_sys_min_stksize;
- }
-
- KA_TRACE( 10, ("__kmp_create_monitor: requested stacksize = %d bytes\n",
- (int) __kmp_monitor_stksize ) );
-
- TCW_4( __kmp_global.g.g_time.dt.t_value, 0 );
-
- handle = CreateThread( NULL, (SIZE_T) __kmp_monitor_stksize,
- (LPTHREAD_START_ROUTINE) __kmp_launch_monitor,
- (LPVOID) th, STACK_SIZE_PARAM_IS_A_RESERVATION, &idThread );
- if (handle == 0) {
- DWORD error = GetLastError();
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( CantCreateThread ),
- KMP_ERR( error ),
- __kmp_msg_null
- );
- }
- else
- th->th.th_info.ds.ds_thread = handle;
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- KA_TRACE( 10, ("__kmp_create_monitor: monitor created %p\n",
- (void *) th->th.th_info.ds.ds_thread ) );
-}
-#endif
-
-/*
- Check to see if thread is still alive.
-
- NOTE: The ExitProcess(code) system call causes all threads to Terminate
- with a exit_val = code. Because of this we can not rely on
- exit_val having any particular value. So this routine may
- return STILL_ALIVE in exit_val even after the thread is dead.
-*/
-
-int
-__kmp_is_thread_alive( kmp_info_t * th, DWORD *exit_val )
-{
- DWORD rc;
- rc = GetExitCodeThread( th->th.th_info.ds.ds_thread, exit_val );
- if ( rc == 0 ) {
- DWORD error = GetLastError();
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( FunctionError, "GetExitCodeThread()" ),
- KMP_ERR( error ),
- __kmp_msg_null
- );
- }; // if
- return ( *exit_val == STILL_ACTIVE );
-}
-
-
-void
-__kmp_exit_thread(
- int exit_status
-) {
- ExitThread( exit_status );
-} // __kmp_exit_thread
-
-/*
- This is a common part for both __kmp_reap_worker() and __kmp_reap_monitor().
-*/
-static void
-__kmp_reap_common( kmp_info_t * th )
-{
- DWORD exit_val;
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- KA_TRACE( 10, ( "__kmp_reap_common: try to reap (%d)\n", th->th.th_info.ds.ds_gtid ) );
-
- /*
- 2006-10-19:
-
- There are two opposite situations:
-
- 1. Windows* OS keep thread alive after it resets ds_alive flag and exits from thread
- function. (For example, see C70770/Q394281 "unloading of dll based on OMP is very
- slow".)
- 2. Windows* OS may kill thread before it resets ds_alive flag.
-
- Right solution seems to be waiting for *either* thread termination *or* ds_alive resetting.
-
- */
-
- {
- // TODO: This code is very similar to KMP_WAIT_YIELD. Need to generalize KMP_WAIT_YIELD to
- // cover this usage also.
- void * obj = NULL;
- register kmp_uint32 spins;
-#if USE_ITT_BUILD
- KMP_FSYNC_SPIN_INIT( obj, (void*) & th->th.th_info.ds.ds_alive );
-#endif /* USE_ITT_BUILD */
- KMP_INIT_YIELD( spins );
- do {
-#if USE_ITT_BUILD
- KMP_FSYNC_SPIN_PREPARE( obj );
-#endif /* USE_ITT_BUILD */
- __kmp_is_thread_alive( th, &exit_val );
- KMP_YIELD( TCR_4(__kmp_nth) > __kmp_avail_proc );
- KMP_YIELD_SPIN( spins );
- } while ( exit_val == STILL_ACTIVE && TCR_4( th->th.th_info.ds.ds_alive ) );
-#if USE_ITT_BUILD
- if ( exit_val == STILL_ACTIVE ) {
- KMP_FSYNC_CANCEL( obj );
- } else {
- KMP_FSYNC_SPIN_ACQUIRED( obj );
- }; // if
-#endif /* USE_ITT_BUILD */
- }
-
- __kmp_free_handle( th->th.th_info.ds.ds_thread );
-
- /*
- * NOTE: The ExitProcess(code) system call causes all threads to Terminate
- * with a exit_val = code. Because of this we can not rely on
- * exit_val having any particular value.
- */
- if ( exit_val == STILL_ACTIVE ) {
- KA_TRACE( 1, ( "__kmp_reap_common: thread still active.\n" ) );
- } else if ( (void *) exit_val != (void *) th) {
- KA_TRACE( 1, ( "__kmp_reap_common: ExitProcess / TerminateThread used?\n" ) );
- }; // if
-
- KA_TRACE( 10,
- (
- "__kmp_reap_common: done reaping (%d), handle = %" KMP_UINTPTR_SPEC "\n",
- th->th.th_info.ds.ds_gtid,
- th->th.th_info.ds.ds_thread
- )
- );
-
- th->th.th_info.ds.ds_thread = 0;
- th->th.th_info.ds.ds_tid = KMP_GTID_DNE;
- th->th.th_info.ds.ds_gtid = KMP_GTID_DNE;
- th->th.th_info.ds.ds_thread_id = 0;
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-}
-
-#if KMP_USE_MONITOR
-void
-__kmp_reap_monitor( kmp_info_t *th )
-{
- int status;
-
- KA_TRACE( 10, ("__kmp_reap_monitor: try to reap %p\n",
- (void *) th->th.th_info.ds.ds_thread ) );
-
- // If monitor has been created, its tid and gtid should be KMP_GTID_MONITOR.
- // If both tid and gtid are 0, it means the monitor did not ever start.
- // If both tid and gtid are KMP_GTID_DNE, the monitor has been shut down.
- KMP_DEBUG_ASSERT( th->th.th_info.ds.ds_tid == th->th.th_info.ds.ds_gtid );
- if ( th->th.th_info.ds.ds_gtid != KMP_GTID_MONITOR ) {
- KA_TRACE( 10, ("__kmp_reap_monitor: monitor did not start, returning\n") );
- return;
- }; // if
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-
- status = SetEvent( __kmp_monitor_ev );
- if ( status == FALSE ) {
- DWORD error = GetLastError();
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( CantSetEvent ),
- KMP_ERR( error ),
- __kmp_msg_null
- );
- }
- KA_TRACE( 10, ( "__kmp_reap_monitor: reaping thread (%d)\n", th->th.th_info.ds.ds_gtid ) );
- __kmp_reap_common( th );
-
- __kmp_free_handle( __kmp_monitor_ev );
-
- KMP_MB(); /* Flush all pending memory write invalidates. */
-}
-#endif
-
-void
-__kmp_reap_worker( kmp_info_t * th )
-{
- KA_TRACE( 10, ( "__kmp_reap_worker: reaping thread (%d)\n", th->th.th_info.ds.ds_gtid ) );
- __kmp_reap_common( th );
-}
-
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------ */
-
-#if KMP_HANDLE_SIGNALS
-
-
-static void
-__kmp_team_handler( int signo )
-{
- if ( __kmp_global.g.g_abort == 0 ) {
- // Stage 1 signal handler, let's shut down all of the threads.
- if ( __kmp_debug_buf ) {
- __kmp_dump_debug_buffer();
- }; // if
- KMP_MB(); // Flush all pending memory write invalidates.
- TCW_4( __kmp_global.g.g_abort, signo );
- KMP_MB(); // Flush all pending memory write invalidates.
- TCW_4( __kmp_global.g.g_done, TRUE );
- KMP_MB(); // Flush all pending memory write invalidates.
- }
-} // __kmp_team_handler
-
-
-
-static
-sig_func_t __kmp_signal( int signum, sig_func_t handler ) {
- sig_func_t old = signal( signum, handler );
- if ( old == SIG_ERR ) {
- int error = errno;
- __kmp_msg( kmp_ms_fatal, KMP_MSG( FunctionError, "signal" ), KMP_ERR( error ), __kmp_msg_null );
- }; // if
- return old;
-}
-
-static void
-__kmp_install_one_handler(
- int sig,
- sig_func_t handler,
- int parallel_init
-) {
- sig_func_t old;
- KMP_MB(); /* Flush all pending memory write invalidates. */
- KB_TRACE( 60, ("__kmp_install_one_handler: called: sig=%d\n", sig ) );
- if ( parallel_init ) {
- old = __kmp_signal( sig, handler );
- // SIG_DFL on Windows* OS in NULL or 0.
- if ( old == __kmp_sighldrs[ sig ] ) {
- __kmp_siginstalled[ sig ] = 1;
- } else {
- // Restore/keep user's handler if one previously installed.
- old = __kmp_signal( sig, old );
- }; // if
- } else {
- // Save initial/system signal handlers to see if user handlers installed.
- // 2009-09-23: It is a dead code. On Windows* OS __kmp_install_signals called once with
- // parallel_init == TRUE.
- old = __kmp_signal( sig, SIG_DFL );
- __kmp_sighldrs[ sig ] = old;
- __kmp_signal( sig, old );
- }; // if
- KMP_MB(); /* Flush all pending memory write invalidates. */
-} // __kmp_install_one_handler
-
-static void
-__kmp_remove_one_handler( int sig ) {
- if ( __kmp_siginstalled[ sig ] ) {
- sig_func_t old;
- KMP_MB(); // Flush all pending memory write invalidates.
- KB_TRACE( 60, ( "__kmp_remove_one_handler: called: sig=%d\n", sig ) );
- old = __kmp_signal( sig, __kmp_sighldrs[ sig ] );
- if ( old != __kmp_team_handler ) {
- KB_TRACE( 10, ( "__kmp_remove_one_handler: oops, not our handler, restoring: sig=%d\n", sig ) );
- old = __kmp_signal( sig, old );
- }; // if
- __kmp_sighldrs[ sig ] = NULL;
- __kmp_siginstalled[ sig ] = 0;
- KMP_MB(); // Flush all pending memory write invalidates.
- }; // if
-} // __kmp_remove_one_handler
-
-
-void
-__kmp_install_signals( int parallel_init )
-{
- KB_TRACE( 10, ( "__kmp_install_signals: called\n" ) );
- if ( ! __kmp_handle_signals ) {
- KB_TRACE( 10, ( "__kmp_install_signals: KMP_HANDLE_SIGNALS is false - handlers not installed\n" ) );
- return;
- }; // if
- __kmp_install_one_handler( SIGINT, __kmp_team_handler, parallel_init );
- __kmp_install_one_handler( SIGILL, __kmp_team_handler, parallel_init );
- __kmp_install_one_handler( SIGABRT, __kmp_team_handler, parallel_init );
- __kmp_install_one_handler( SIGFPE, __kmp_team_handler, parallel_init );
- __kmp_install_one_handler( SIGSEGV, __kmp_team_handler, parallel_init );
- __kmp_install_one_handler( SIGTERM, __kmp_team_handler, parallel_init );
-} // __kmp_install_signals
-
-
-void
-__kmp_remove_signals( void )
-{
- int sig;
- KB_TRACE( 10, ("__kmp_remove_signals: called\n" ) );
- for ( sig = 1; sig < NSIG; ++ sig ) {
- __kmp_remove_one_handler( sig );
- }; // for sig
-} // __kmp_remove_signals
-
-
-#endif // KMP_HANDLE_SIGNALS
-
-/* Put the thread to sleep for a time period */
-void
-__kmp_thread_sleep( int millis )
-{
- DWORD status;
-
- status = SleepEx( (DWORD) millis, FALSE );
- if ( status ) {
- DWORD error = GetLastError();
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( FunctionError, "SleepEx()" ),
- KMP_ERR( error ),
- __kmp_msg_null
- );
- }
-}
-
-/* Determine whether the given address is mapped into the current address space. */
-int
-__kmp_is_address_mapped( void * addr )
-{
- DWORD status;
- MEMORY_BASIC_INFORMATION lpBuffer;
- SIZE_T dwLength;
-
- dwLength = sizeof(MEMORY_BASIC_INFORMATION);
-
- status = VirtualQuery( addr, &lpBuffer, dwLength );
-
- return !((( lpBuffer.State == MEM_RESERVE) || ( lpBuffer.State == MEM_FREE )) ||
- (( lpBuffer.Protect == PAGE_NOACCESS ) || ( lpBuffer.Protect == PAGE_EXECUTE )));
-}
-
-kmp_uint64
-__kmp_hardware_timestamp(void)
-{
- kmp_uint64 r = 0;
-
- QueryPerformanceCounter((LARGE_INTEGER*) &r);
- return r;
-}
-
-/* Free handle and check the error code */
-void
-__kmp_free_handle( kmp_thread_t tHandle )
-{
-/* called with parameter type HANDLE also, thus suppose kmp_thread_t defined as HANDLE */
- BOOL rc;
- rc = CloseHandle( tHandle );
- if ( !rc ) {
- DWORD error = GetLastError();
- __kmp_msg(
- kmp_ms_fatal,
- KMP_MSG( CantCloseHandle ),
- KMP_ERR( error ),
- __kmp_msg_null
- );
- }
-}
-
-int
-__kmp_get_load_balance( int max ) {
-
- static ULONG glb_buff_size = 100 * 1024;
-
- static int glb_running_threads = 0; /* Saved count of the running threads for the thread balance algortihm */
- static double glb_call_time = 0; /* Thread balance algorithm call time */
-
- int running_threads = 0; // Number of running threads in the system.
- NTSTATUS status = 0;
- ULONG buff_size = 0;
- ULONG info_size = 0;
- void * buffer = NULL;
- PSYSTEM_PROCESS_INFORMATION spi = NULL;
- int first_time = 1;
-
- double call_time = 0.0; //start, finish;
-
- __kmp_elapsed( & call_time );
-
- if ( glb_call_time &&
- ( call_time - glb_call_time < __kmp_load_balance_interval ) ) {
- running_threads = glb_running_threads;
- goto finish;
- }
- glb_call_time = call_time;
-
- // Do not spend time on running algorithm if we have a permanent error.
- if ( NtQuerySystemInformation == NULL ) {
- running_threads = -1;
- goto finish;
- }; // if
-
- if ( max <= 0 ) {
- max = INT_MAX;
- }; // if
-
- do {
-
- if ( first_time ) {
- buff_size = glb_buff_size;
- } else {
- buff_size = 2 * buff_size;
- }
-
- buffer = KMP_INTERNAL_REALLOC( buffer, buff_size );
- if ( buffer == NULL ) {
- running_threads = -1;
- goto finish;
- }; // if
- status = NtQuerySystemInformation( SystemProcessInformation, buffer, buff_size, & info_size );
- first_time = 0;
-
- } while ( status == STATUS_INFO_LENGTH_MISMATCH );
- glb_buff_size = buff_size;
-
- #define CHECK( cond ) \
- { \
- KMP_DEBUG_ASSERT( cond ); \
- if ( ! ( cond ) ) { \
- running_threads = -1; \
- goto finish; \
- } \
- }
-
- CHECK( buff_size >= info_size );
- spi = PSYSTEM_PROCESS_INFORMATION( buffer );
- for ( ; ; ) {
- ptrdiff_t offset = uintptr_t( spi ) - uintptr_t( buffer );
- CHECK( 0 <= offset && offset + sizeof( SYSTEM_PROCESS_INFORMATION ) < info_size );
- HANDLE pid = spi->ProcessId;
- ULONG num = spi->NumberOfThreads;
- CHECK( num >= 1 );
- size_t spi_size = sizeof( SYSTEM_PROCESS_INFORMATION ) + sizeof( SYSTEM_THREAD ) * ( num - 1 );
- CHECK( offset + spi_size < info_size ); // Make sure process info record fits the buffer.
- if ( spi->NextEntryOffset != 0 ) {
- CHECK( spi_size <= spi->NextEntryOffset ); // And do not overlap with the next record.
- }; // if
- // pid == 0 corresponds to the System Idle Process. It always has running threads
- // on all cores. So, we don't consider the running threads of this process.
- if ( pid != 0 ) {
- for ( int i = 0; i < num; ++ i ) {
- THREAD_STATE state = spi->Threads[ i ].State;
- // Count threads that have Ready or Running state.
- // !!! TODO: Why comment does not match the code???
- if ( state == StateRunning ) {
- ++ running_threads;
- // Stop counting running threads if the number is already greater than
- // the number of available cores
- if ( running_threads >= max ) {
- goto finish;
- }
- } // if
- }; // for i
- } // if
- if ( spi->NextEntryOffset == 0 ) {
- break;
- }; // if
- spi = PSYSTEM_PROCESS_INFORMATION( uintptr_t( spi ) + spi->NextEntryOffset );
- }; // forever
-
- #undef CHECK
-
- finish: // Clean up and exit.
-
- if ( buffer != NULL ) {
- KMP_INTERNAL_FREE( buffer );
- }; // if
-
- glb_running_threads = running_threads;
-
- return running_threads;
-
-} //__kmp_get_load_balance()
-
More information about the Openmp-commits
mailing list