Beispiel #1
0
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
static
void
___kmp_env_blk_parse_string(
    kmp_env_blk_t * block,   // M: Env block to fill.
    char const *    env      // I: String to parse.
) {

    char const chr_delimiter   = '|';
    char const str_delimiter[] = { chr_delimiter, 0 };

    char *          bulk       = NULL;
    kmp_env_var_t * vars       = NULL;
    int             count      = 0;  // Number of used elements in vars array.
    int             delimiters = 0;  // Number of delimiters in input string.

    // Copy original string, we will modify the copy.
    bulk = __kmp_str_format( "%s", env );

    // Loop thru all the vars in environment block. Count delimiters (maximum number of variables
    // is number of delimiters plus one).
    {
        char const * ptr = bulk;
        for ( ; ; ) {
            ptr = strchr( ptr, chr_delimiter );
            if ( ptr == NULL ) {
                break;
            }; // if
            ++ delimiters;
            ptr += 1;
        }; // forever
    }

    // Allocate vars array.
    vars = (kmp_env_var_t *) allocate( ( delimiters + 1 ) * sizeof( kmp_env_var_t ) );

    // Loop thru all the variables.
    {
        char * var;     // Pointer to variable (both name and value).
        char * name;    // Pointer to name of variable.
        char * value;   // Pointer to value.
        char * buf;     // Buffer for __kmp_str_token() function.
        var = __kmp_str_token( bulk, str_delimiter, & buf );      // Get the first var.
        while ( var != NULL ) {
            // Save found variable in vars array.
            __kmp_str_split( var, '=', & name, & value );
            KMP_DEBUG_ASSERT( count < delimiters + 1 );
            vars[ count ].name  = name;
            vars[ count ].value = value;
            ++ count;
            // Get the next var.
            var = __kmp_str_token( NULL, str_delimiter, & buf );
        }; // while
    }

    // Fill out result.
    block->bulk  = bulk;
    block->vars  = vars;
    block->count = count;

}; // ___kmp_env_blk_parse_string
Beispiel #3
0
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
Beispiel #4
0
kmp_msg_t
__kmp_msg_error_mesg(
    char const * mesg
) {

    kmp_msg_t      msg;
    msg.type = kmp_mt_syserr;
    msg.num  = 0;
    msg.str  = __kmp_str_format( "%s", mesg );
    msg.len  = KMP_STRLEN( msg.str );
    return msg;

} // __kmp_msg_error_mesg
Beispiel #5
0
static void
__kmp_for_static_init(
    ident_t                          *loc,
    kmp_int32                         global_tid,
    kmp_int32                         schedtype,
    kmp_int32                        *plastiter,
    T                                *plower,
    T                                *pupper,
    typename traits_t< T >::signed_t *pstride,
    typename traits_t< T >::signed_t  incr,
    typename traits_t< T >::signed_t  chunk
) {
    KMP_COUNT_BLOCK(OMP_FOR_static);
    typedef typename traits_t< T >::unsigned_t  UT;
    typedef typename traits_t< T >::signed_t    ST;
    /*  this all has to be changed back to TID and such.. */
    register kmp_int32   gtid = global_tid;
    register kmp_uint32  tid;
    register kmp_uint32  nth;
    register UT          trip_count;
    register kmp_team_t *team;
    register kmp_info_t *th = __kmp_threads[ gtid ];

#if OMPT_SUPPORT && OMPT_TRACE
    ompt_team_info_t *team_info = __ompt_get_teaminfo(0, NULL);
    ompt_task_info_t *task_info = __ompt_get_taskinfo(0);
#endif

    KMP_DEBUG_ASSERT( plastiter && plower && pupper && pstride );
    KE_TRACE( 10, ("__kmpc_for_static_init called (%d)\n", global_tid));
    #ifdef KMP_DEBUG
    {
        const char * buff;
        // create format specifiers before the debug output
        buff = __kmp_str_format(
            "__kmpc_for_static_init: T#%%d sched=%%d liter=%%d iter=(%%%s," \
            " %%%s, %%%s) incr=%%%s chunk=%%%s signed?<%s>\n",
            traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec,
            traits_t< ST >::spec, traits_t< ST >::spec, traits_t< T >::spec );
        KD_TRACE(100, ( buff, global_tid, schedtype, *plastiter,
            *plower, *pupper, *pstride, incr, chunk ) );
        __kmp_str_free( &buff );
    }
    #endif

    if ( __kmp_env_consistency_check ) {
        __kmp_push_workshare( global_tid, ct_pdo, loc );
        if ( incr == 0 ) {
            __kmp_error_construct( kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo, loc );
        }
    }
    /* special handling for zero-trip loops */
    if ( incr > 0 ? (*pupper < *plower) : (*plower < *pupper) ) {
        if( plastiter != NULL )
            *plastiter = FALSE;
        /* leave pupper and plower set to entire iteration space */
        *pstride = incr;   /* value should never be used */
	//        *plower = *pupper - incr;   // let compiler bypass the illegal loop (like for(i=1;i<10;i--))  THIS LINE CAUSED shape2F/h_tests_1.f TO HAVE A FAILURE ON A ZERO-TRIP LOOP (lower=1,\
	  upper=0,stride=1) - JPH June 23, 2009.
        #ifdef KMP_DEBUG
        {
            const char * buff;
            // create format specifiers before the debug output
            buff = __kmp_str_format(
                "__kmpc_for_static_init:(ZERO TRIP) liter=%%d lower=%%%s upper=%%%s stride = %%%s signed?<%s>, loc = %%s\n",
                traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec, traits_t< T >::spec );
            KD_TRACE(100, ( buff, *plastiter, *plower, *pupper, *pstride, loc->psource ) );
            __kmp_str_free( &buff );
        }
        #endif
        KE_TRACE( 10, ("__kmpc_for_static_init: T#%d return\n", global_tid ) );

#if OMPT_SUPPORT && OMPT_TRACE
        if ((ompt_status == ompt_status_track_callback) &&
            ompt_callbacks.ompt_callback(ompt_event_loop_begin)) {
            ompt_callbacks.ompt_callback(ompt_event_loop_begin)(
                team_info->parallel_id, task_info->task_id,
                team_info->microtask);
        }
#endif
        return;
    }

    #if OMP_40_ENABLED
    if ( schedtype > kmp_ord_upper ) {
        // we are in DISTRIBUTE construct
        schedtype += kmp_sch_static - kmp_distribute_static;      // AC: convert to usual schedule type
        tid  = th->th.th_team->t.t_master_tid;
        team = th->th.th_team->t.t_parent;
    } else
    #endif
    {
        tid  = __kmp_tid_from_gtid( global_tid );
        team = th->th.th_team;
    }

    /* determine if "for" loop is an active worksharing construct */
    if ( team -> t.t_serialized ) {
        /* serialized parallel, each thread executes whole iteration space */
        if( plastiter != NULL )
            *plastiter = TRUE;
        /* leave pupper and plower set to entire iteration space */
        *pstride = (incr > 0) ? (*pupper - *plower + 1) : (-(*plower - *pupper + 1));

        #ifdef KMP_DEBUG
        {
            const char * buff;
            // create format specifiers before the debug output
            buff = __kmp_str_format(
                "__kmpc_for_static_init: (serial) liter=%%d lower=%%%s upper=%%%s stride = %%%s\n",
                traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec );
            KD_TRACE(100, ( buff, *plastiter, *plower, *pupper, *pstride ) );
            __kmp_str_free( &buff );
        }
        #endif
        KE_TRACE( 10, ("__kmpc_for_static_init: T#%d return\n", global_tid ) );

#if OMPT_SUPPORT && OMPT_TRACE
        if ((ompt_status == ompt_status_track_callback) &&
            ompt_callbacks.ompt_callback(ompt_event_loop_begin)) {
            ompt_callbacks.ompt_callback(ompt_event_loop_begin)(
                team_info->parallel_id, task_info->task_id,
                team_info->microtask);
        }
#endif
        return;
    }
    nth = team->t.t_nproc;
    if ( nth == 1 ) {
        if( plastiter != NULL )
            *plastiter = TRUE;
        *pstride = (incr > 0) ? (*pupper - *plower + 1) : (-(*plower - *pupper + 1));
        #ifdef KMP_DEBUG
        {
            const char * buff;
            // create format specifiers before the debug output
            buff = __kmp_str_format(
                "__kmpc_for_static_init: (serial) liter=%%d lower=%%%s upper=%%%s stride = %%%s\n",
                traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec );
            KD_TRACE(100, ( buff, *plastiter, *plower, *pupper, *pstride ) );
            __kmp_str_free( &buff );
        }
        #endif
        KE_TRACE( 10, ("__kmpc_for_static_init: T#%d return\n", global_tid ) );

#if OMPT_SUPPORT && OMPT_TRACE
        if ((ompt_status == ompt_status_track_callback) &&
            ompt_callbacks.ompt_callback(ompt_event_loop_begin)) {
            ompt_callbacks.ompt_callback(ompt_event_loop_begin)(
                team_info->parallel_id, task_info->task_id,
                team_info->microtask);
        }
#endif
        return;
    }

    /* compute trip count */
    if ( incr == 1 ) {
        trip_count = *pupper - *plower + 1;
    } else if (incr == -1) {
        trip_count = *plower - *pupper + 1;
    } else {
        if ( incr > 1 ) {  // the check is needed for unsigned division when incr < 0
            trip_count = (*pupper - *plower) / incr + 1;
        } else {
            trip_count = (*plower - *pupper) / ( -incr ) + 1;
        }
    }

    if ( __kmp_env_consistency_check ) {
        /* tripcount overflow? */
        if ( trip_count == 0 && *pupper != *plower ) {
            __kmp_error_construct( kmp_i18n_msg_CnsIterationRangeTooLarge, ct_pdo, loc );
        }
    }

    /* compute remaining parameters */
    switch ( schedtype ) {
    case kmp_sch_static:
        {
            if ( trip_count < nth ) {
                KMP_DEBUG_ASSERT(
                    __kmp_static == kmp_sch_static_greedy || \
                    __kmp_static == kmp_sch_static_balanced
                ); // Unknown static scheduling type.
                if ( tid < trip_count ) {
                    *pupper = *plower = *plower + tid * incr;
                } else {
                    *plower = *pupper + incr;
                }
                if( plastiter != NULL )
                    *plastiter = ( tid == trip_count - 1 );
            } else {
                if ( __kmp_static == kmp_sch_static_balanced ) {
                    register UT small_chunk = trip_count / nth;
                    register UT extras = trip_count % nth;
                    *plower += incr * ( tid * small_chunk + ( tid < extras ? tid : extras ) );
                    *pupper = *plower + small_chunk * incr - ( tid < extras ? 0 : incr );
                    if( plastiter != NULL )
                        *plastiter = ( tid == nth - 1 );
                } else {
                    register T big_chunk_inc_count = ( trip_count/nth +
                                                     ( ( trip_count % nth ) ? 1 : 0) ) * incr;
                    register T old_upper = *pupper;

                    KMP_DEBUG_ASSERT( __kmp_static == kmp_sch_static_greedy );
                        // Unknown static scheduling type.

                    *plower += tid * big_chunk_inc_count;
                    *pupper = *plower + big_chunk_inc_count - incr;
                    if ( incr > 0 ) {
                        if( *pupper < *plower )
                            *pupper = i_maxmin< T >::mx;
                        if( plastiter != NULL )
                            *plastiter = *plower <= old_upper && *pupper > old_upper - incr;
                        if ( *pupper > old_upper ) *pupper = old_upper; // tracker C73258
                    } else {
                        if( *pupper > *plower )
                            *pupper = i_maxmin< T >::mn;
                        if( plastiter != NULL )
                            *plastiter = *plower >= old_upper && *pupper < old_upper - incr;
                        if ( *pupper < old_upper ) *pupper = old_upper; // tracker C73258
                    }
                }
            }
            break;
        }
    case kmp_sch_static_chunked:
        {
            register ST span;
            if ( chunk < 1 ) {
                chunk = 1;
            }
            span = chunk * incr;
            *pstride = span * nth;
            *plower = *plower + (span * tid);
            *pupper = *plower + span - incr;
            if( plastiter != NULL )
                *plastiter = (tid == ((trip_count - 1)/( UT )chunk) % nth);
            break;
        }
    default:
        KMP_ASSERT2( 0, "__kmpc_for_static_init: unknown scheduling type" );
        break;
    }

#if USE_ITT_BUILD
    // Report loop metadata
    if ( KMP_MASTER_TID(tid) && __itt_metadata_add_ptr && __kmp_forkjoin_frames_mode == 3 &&
#if OMP_40_ENABLED
        th->th.th_teams_microtask == NULL &&
#endif
        team->t.t_active_level == 1 )
    {
        kmp_uint64 cur_chunk = chunk;
        // Calculate chunk in case it was not specified; it is specified for kmp_sch_static_chunked
        if ( schedtype == kmp_sch_static ) {
            cur_chunk = trip_count / nth + ( ( trip_count % nth ) ? 1 : 0);
        }
        // 0 - "static" schedule
        __kmp_itt_metadata_loop(loc, 0, trip_count, cur_chunk);
    }
#endif
    #ifdef KMP_DEBUG
    {
        const char * buff;
        // create format specifiers before the debug output
        buff = __kmp_str_format(
            "__kmpc_for_static_init: liter=%%d lower=%%%s upper=%%%s stride = %%%s signed?<%s>\n",
            traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec, traits_t< T >::spec );
        KD_TRACE(100, ( buff, *plastiter, *plower, *pupper, *pstride ) );
        __kmp_str_free( &buff );
    }
    #endif
    KE_TRACE( 10, ("__kmpc_for_static_init: T#%d return\n", global_tid ) );

#if OMPT_SUPPORT && OMPT_TRACE
    if ((ompt_status == ompt_status_track_callback) &&
        ompt_callbacks.ompt_callback(ompt_event_loop_begin)) {
        ompt_callbacks.ompt_callback(ompt_event_loop_begin)(
            team_info->parallel_id, task_info->task_id, team_info->microtask);
    }
#endif

    return;
}
Beispiel #6
0
static void
__kmp_team_static_init(
    ident_t                          *loc,
    kmp_int32                         gtid,
    kmp_int32                        *p_last,
    T                                *p_lb,
    T                                *p_ub,
    typename traits_t< T >::signed_t *p_st,
    typename traits_t< T >::signed_t  incr,
    typename traits_t< T >::signed_t  chunk
) {
    // The routine returns the first chunk distributed to the team and
    // stride for next chunks calculation.
    // Last iteration flag set for the team that will execute
    // the last iteration of the loop.
    // The routine is called for dist_schedue(static,chunk) only.
    typedef typename traits_t< T >::unsigned_t  UT;
    typedef typename traits_t< T >::signed_t    ST;
    kmp_uint32  team_id;
    kmp_uint32  nteams;
    UT          trip_count;
    T           lower;
    T           upper;
    ST          span;
    kmp_team_t *team;
    kmp_info_t *th;

    KMP_DEBUG_ASSERT( p_last && p_lb && p_ub && p_st );
    KE_TRACE( 10, ("__kmp_team_static_init called (%d)\n", gtid));
    #ifdef KMP_DEBUG
    {
        const char * buff;
        // create format specifiers before the debug output
        buff = __kmp_str_format( "__kmp_team_static_init enter: T#%%d liter=%%d "\
            "iter=(%%%s, %%%s, %%%s) chunk %%%s; signed?<%s>\n",
            traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec,
            traits_t< ST >::spec, traits_t< T >::spec );
        KD_TRACE(100, ( buff, gtid, *p_last, *p_lb, *p_ub, *p_st, chunk ) );
        __kmp_str_free( &buff );
    }
    #endif

    lower = *p_lb;
    upper = *p_ub;
    if( __kmp_env_consistency_check ) {
        if( incr == 0 ) {
            __kmp_error_construct( kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo, loc );
        }
        if( incr > 0 ? (upper < lower) : (lower < upper) ) {
            // The loop is illegal.
            // Some zero-trip loops maintained by compiler, e.g.:
            //   for(i=10;i<0;++i) // lower >= upper - run-time check
            //   for(i=0;i>10;--i) // lower <= upper - run-time check
            //   for(i=0;i>10;++i) // incr > 0       - compile-time check
            //   for(i=10;i<0;--i) // incr < 0       - compile-time check
            // Compiler does not check the following illegal loops:
            //   for(i=0;i<10;i+=incr) // where incr<0
            //   for(i=10;i>0;i-=incr) // where incr<0
            __kmp_error_construct( kmp_i18n_msg_CnsLoopIncrIllegal, ct_pdo, loc );
        }
    }
    th = __kmp_threads[gtid];
    KMP_DEBUG_ASSERT(th->th.th_teams_microtask);   // we are in the teams construct
    team = th->th.th_team;
    #if OMP_40_ENABLED
    nteams = th->th.th_teams_size.nteams;
    #endif
    team_id = team->t.t_master_tid;
    KMP_DEBUG_ASSERT(nteams == team->t.t_parent->t.t_nproc);

    // compute trip count
    if( incr == 1 ) {
        trip_count = upper - lower + 1;
    } else if(incr == -1) {
        trip_count = lower - upper + 1;
    } else {
        trip_count = (ST)(upper - lower) / incr + 1; // cast to signed to cover incr<0 case
    }
    if( chunk < 1 )
        chunk = 1;
    span = chunk * incr;
    *p_st = span * nteams;
    *p_lb = lower + (span * team_id);
    *p_ub = *p_lb + span - incr;
    if ( p_last != NULL )
        *p_last = (team_id == ((trip_count - 1)/(UT)chunk) % nteams);
    // Correct upper bound if needed
    if( incr > 0 ) {
        if( *p_ub < *p_lb ) // overflow?
            *p_ub = i_maxmin< T >::mx;
        if( *p_ub > upper )
            *p_ub = upper; // tracker C73258
    } else {   // incr < 0
        if( *p_ub > *p_lb )
            *p_ub = i_maxmin< T >::mn;
        if( *p_ub < upper )
            *p_ub = upper; // tracker C73258
    }
    #ifdef KMP_DEBUG
    {
        const char * buff;
        // create format specifiers before the debug output
        buff = __kmp_str_format( "__kmp_team_static_init exit: T#%%d team%%u liter=%%d "\
            "iter=(%%%s, %%%s, %%%s) chunk %%%s\n",
            traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec,
            traits_t< ST >::spec );
        KD_TRACE(100, ( buff, gtid, team_id, *p_last, *p_lb, *p_ub, *p_st, chunk ) );
        __kmp_str_free( &buff );
    }
    #endif
}
Beispiel #7
0
static void
__kmp_dist_for_static_init(
    ident_t                          *loc,
    kmp_int32                         gtid,
    kmp_int32                         schedule,
    kmp_int32                        *plastiter,
    T                                *plower,
    T                                *pupper,
    T                                *pupperDist,
    typename traits_t< T >::signed_t *pstride,
    typename traits_t< T >::signed_t  incr,
    typename traits_t< T >::signed_t  chunk
) {
    KMP_COUNT_BLOCK(OMP_DISTR_FOR_static);
    typedef typename traits_t< T >::unsigned_t  UT;
    typedef typename traits_t< T >::signed_t    ST;
    register kmp_uint32  tid;
    register kmp_uint32  nth;
    register kmp_uint32  team_id;
    register kmp_uint32  nteams;
    register UT          trip_count;
    register kmp_team_t *team;
    kmp_info_t * th;

    KMP_DEBUG_ASSERT( plastiter && plower && pupper && pupperDist && pstride );
    KE_TRACE( 10, ("__kmpc_dist_for_static_init called (%d)\n", gtid));
    #ifdef KMP_DEBUG
    {
        const char * buff;
        // create format specifiers before the debug output
        buff = __kmp_str_format(
            "__kmpc_dist_for_static_init: T#%%d schedLoop=%%d liter=%%d "\
            "iter=(%%%s, %%%s, %%%s) chunk=%%%s signed?<%s>\n",
            traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec,
            traits_t< ST >::spec, traits_t< T >::spec );
        KD_TRACE(100, ( buff, gtid, schedule, *plastiter,
                       *plower, *pupper, incr, chunk ) );
        __kmp_str_free( &buff );
    }
    #endif

    if( __kmp_env_consistency_check ) {
        __kmp_push_workshare( gtid, ct_pdo, loc );
        if( incr == 0 ) {
            __kmp_error_construct( kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo, loc );
        }
        if( incr > 0 ? (*pupper < *plower) : (*plower < *pupper) ) {
            // The loop is illegal.
            // Some zero-trip loops maintained by compiler, e.g.:
            //   for(i=10;i<0;++i) // lower >= upper - run-time check
            //   for(i=0;i>10;--i) // lower <= upper - run-time check
            //   for(i=0;i>10;++i) // incr > 0       - compile-time check
            //   for(i=10;i<0;--i) // incr < 0       - compile-time check
            // Compiler does not check the following illegal loops:
            //   for(i=0;i<10;i+=incr) // where incr<0
            //   for(i=10;i>0;i-=incr) // where incr<0
            __kmp_error_construct( kmp_i18n_msg_CnsLoopIncrIllegal, ct_pdo, loc );
        }
    }
    tid = __kmp_tid_from_gtid( gtid );
    th = __kmp_threads[gtid];
    KMP_DEBUG_ASSERT(th->th.th_teams_microtask);   // we are in the teams construct
    nth = th->th.th_team_nproc;
    team = th->th.th_team;
    #if OMP_40_ENABLED
    nteams = th->th.th_teams_size.nteams;
    #endif
    team_id = team->t.t_master_tid;
    KMP_DEBUG_ASSERT(nteams == team->t.t_parent->t.t_nproc);

    // compute global trip count
    if( incr == 1 ) {
        trip_count = *pupper - *plower + 1;
    } else if(incr == -1) {
        trip_count = *plower - *pupper + 1;
    } else {
        trip_count = (ST)(*pupper - *plower) / incr + 1; // cast to signed to cover incr<0 case
    }
    *pstride = *pupper - *plower;  // just in case (can be unused)
    if( trip_count <= nteams ) {
        KMP_DEBUG_ASSERT(
            __kmp_static == kmp_sch_static_greedy || \
            __kmp_static == kmp_sch_static_balanced
        ); // Unknown static scheduling type.
        // only masters of some teams get single iteration, other threads get nothing
        if( team_id < trip_count && tid == 0 ) {
            *pupper = *pupperDist = *plower = *plower + team_id * incr;
        } else {
            *pupperDist = *pupper;
            *plower = *pupper + incr; // compiler should skip loop body
        }
        if( plastiter != NULL )
            *plastiter = ( tid == 0 && team_id == trip_count - 1 );
    } else {
        // Get the team's chunk first (each team gets at most one chunk)
        if( __kmp_static == kmp_sch_static_balanced ) {
            register UT chunkD = trip_count / nteams;
            register UT extras = trip_count % nteams;
            *plower += incr * ( team_id * chunkD + ( team_id < extras ? team_id : extras ) );
            *pupperDist = *plower + chunkD * incr - ( team_id < extras ? 0 : incr );
            if( plastiter != NULL )
                *plastiter = ( team_id == nteams - 1 );
        } else {
            register T chunk_inc_count =
                ( trip_count / nteams + ( ( trip_count % nteams ) ? 1 : 0) ) * incr;
            register T upper = *pupper;
            KMP_DEBUG_ASSERT( __kmp_static == kmp_sch_static_greedy );
                // Unknown static scheduling type.
            *plower += team_id * chunk_inc_count;
            *pupperDist = *plower + chunk_inc_count - incr;
            // Check/correct bounds if needed
            if( incr > 0 ) {
                if( *pupperDist < *plower )
                    *pupperDist = i_maxmin< T >::mx;
                if( plastiter != NULL )
                    *plastiter = *plower <= upper && *pupperDist > upper - incr;
                if( *pupperDist > upper )
                    *pupperDist = upper; // tracker C73258
                if( *plower > *pupperDist ) {
                    *pupper = *pupperDist;  // no iterations available for the team
                    goto end;
                }
            } else {
                if( *pupperDist > *plower )
                    *pupperDist = i_maxmin< T >::mn;
                if( plastiter != NULL )
                    *plastiter = *plower >= upper && *pupperDist < upper - incr;
                if( *pupperDist < upper )
                    *pupperDist = upper; // tracker C73258
                if( *plower < *pupperDist ) {
                    *pupper = *pupperDist;  // no iterations available for the team
                    goto end;
                }
            }
        }
        // Get the parallel loop chunk now (for thread)
        // compute trip count for team's chunk
        if( incr == 1 ) {
            trip_count = *pupperDist - *plower + 1;
        } else if(incr == -1) {
            trip_count = *plower - *pupperDist + 1;
        } else {
            trip_count = (ST)(*pupperDist - *plower) / incr + 1;
        }
        KMP_DEBUG_ASSERT( trip_count );
        switch( schedule ) {
        case kmp_sch_static:
        {
            if( trip_count <= nth ) {
                KMP_DEBUG_ASSERT(
                    __kmp_static == kmp_sch_static_greedy || \
                    __kmp_static == kmp_sch_static_balanced
                ); // Unknown static scheduling type.
                if( tid < trip_count )
                    *pupper = *plower = *plower + tid * incr;
                else
                    *plower = *pupper + incr; // no iterations available
                if( plastiter != NULL )
                    if( *plastiter != 0 && !( tid == trip_count - 1 ) )
                        *plastiter = 0;
            } else {
                if( __kmp_static == kmp_sch_static_balanced ) {
                    register UT chunkL = trip_count / nth;
                    register UT extras = trip_count % nth;
                    *plower += incr * (tid * chunkL + (tid < extras ? tid : extras));
                    *pupper = *plower + chunkL * incr - (tid < extras ? 0 : incr);
                    if( plastiter != NULL )
                        if( *plastiter != 0 && !( tid == nth - 1 ) )
                            *plastiter = 0;
                } else {
                    register T chunk_inc_count =
                        ( trip_count / nth + ( ( trip_count % nth ) ? 1 : 0) ) * incr;
                    register T upper = *pupperDist;
                    KMP_DEBUG_ASSERT( __kmp_static == kmp_sch_static_greedy );
                        // Unknown static scheduling type.
                    *plower += tid * chunk_inc_count;
                    *pupper = *plower + chunk_inc_count - incr;
                    if( incr > 0 ) {
                        if( *pupper < *plower )
                            *pupper = i_maxmin< T >::mx;
                        if( plastiter != NULL )
                            if( *plastiter != 0 && !(*plower <= upper && *pupper > upper - incr) )
                                *plastiter = 0;
                        if( *pupper > upper )
                            *pupper = upper;//tracker C73258
                    } else {
                        if( *pupper > *plower )
                            *pupper = i_maxmin< T >::mn;
                        if( plastiter != NULL )
                            if( *plastiter != 0 && !(*plower >= upper && *pupper < upper - incr) )
                                *plastiter = 0;
                        if( *pupper < upper )
                            *pupper = upper;//tracker C73258
                    }
                }
            }
            break;
        }
        case kmp_sch_static_chunked:
        {
            register ST span;
            if( chunk < 1 )
                chunk = 1;
            span = chunk * incr;
            *pstride = span * nth;
            *plower = *plower + (span * tid);
            *pupper = *plower + span - incr;
            if( plastiter != NULL )
                if( *plastiter != 0 && !(tid == ((trip_count - 1) / ( UT )chunk) % nth) )
                    *plastiter = 0;
            break;
        }
        default:
            KMP_ASSERT2( 0, "__kmpc_dist_for_static_init: unknown loop scheduling type" );
            break;
        }
    }
    end:;
    #ifdef KMP_DEBUG
    {
        const char * buff;
        // create format specifiers before the debug output
        buff = __kmp_str_format(
            "__kmpc_dist_for_static_init: last=%%d lo=%%%s up=%%%s upDist=%%%s "\
            "stride=%%%s signed?<%s>\n",
            traits_t< T >::spec, traits_t< T >::spec, traits_t< T >::spec,
            traits_t< ST >::spec, traits_t< T >::spec );
        KD_TRACE(100, ( buff, *plastiter, *plower, *pupper, *pupperDist, *pstride ) );
        __kmp_str_free( &buff );
    }
    #endif
    KE_TRACE( 10, ("__kmpc_dist_for_static_init: T#%d return\n", gtid ) );
    return;
}
Beispiel #8
0
static
char *
sys_error(
    int err
) {

    char * message = NULL;

    #if KMP_OS_WINDOWS

        LPVOID  buffer = NULL;
        int     len;
        DWORD   rc;
        rc =
            FormatMessage(
                FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                NULL,
                err,
                MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language.
                (LPTSTR) & buffer,
                0,
                NULL
            );
        if ( rc > 0 ) {
            // Message formatted. Copy it (so we can free it later with normal free().
            message = __kmp_str_format( "%s", (char *) buffer );
            len = ___strip_crs( message ); // Delete carriage returns if any.
            // Strip trailing newlines.
            while ( len > 0 && message[ len - 1 ] == '\n' ) {
                -- len;
            }; // while
            message[ len ] = 0;
        } else {
            // FormatMessage() failed to format system error message. GetLastError() would give us
            // error code, which we would convert to message... this it dangerous recursion, which
            // cannot clarify original error, so we will not even start it.
        }; // if
        if ( buffer != NULL ) {
            LocalFree( buffer );
        }; // if

    #else // Non-Windows* OS: Linux* OS or OS X*

        /*
            There are 2 incompatible versions of strerror_r:

                char * strerror_r( int, char *, size_t );  // GNU version
                int    strerror_r( int, char *, size_t );  // XSI version
        */

        #if defined(__GLIBC__) && defined(_GNU_SOURCE)

            // GNU version of strerror_r.

            char   buffer[ 2048 ];
            char * const err_msg = strerror_r( err, buffer, sizeof( buffer ) );
                // Do not eliminate this assignment to temporary variable, otherwise compiler would
                // not issue warning if strerror_r() returns `int' instead of expected `char *'.
            message = __kmp_str_format( "%s", err_msg );

        #else // OS X*, FreeBSD* etc.

            // XSI version of strerror_r.

            int    size   = 2048;
            // TODO: Add checking result of malloc().
            char * buffer = (char *) KMP_INTERNAL_MALLOC( size );
            int    rc;
            if (buffer == NULL) {
                KMP_FATAL(MemoryAllocFailed);
            }
            rc = strerror_r( err, buffer, size );
            if ( rc == -1 ) {
                rc = errno;            // XSI version sets errno.
            }; // if
            while ( rc == ERANGE ) {   // ERANGE means the buffer is too small.
                KMP_INTERNAL_FREE( buffer );
                size *= 2;
                buffer = (char *) KMP_INTERNAL_MALLOC( size );
                if (buffer == NULL) {
                    KMP_FATAL(MemoryAllocFailed);
                }
                rc = strerror_r( err, buffer, size );
                if ( rc == -1 ) {
                    rc = errno;        // XSI version sets errno.
                }; // if
            }; // while
            if ( rc == 0 ) {
                message = buffer;
            } else {
                // Buffer is unused. Free it.
                KMP_INTERNAL_FREE( buffer );
            }; // if

        #endif

    #endif /* KMP_OS_WINDOWS */

    if ( message == NULL ) {
        // TODO: I18n this message.
        message = __kmp_str_format( "%s", "(No system error message available)" );
    }; // if
    return message;

} // sys_error
static void
__kmp_for_static_init(
    ident_t                          *loc,
    kmp_int32                         global_tid,
    kmp_int32                         schedtype,
    kmp_int32                        *plastiter,
    T                                *plower,
    T                                *pupper,
    typename traits_t< T >::signed_t *pstride,
    typename traits_t< T >::signed_t  incr,
    typename traits_t< T >::signed_t  chunk
) {
    typedef typename traits_t< T >::unsigned_t  UT;
    typedef typename traits_t< T >::signed_t    ST;
    /*  this all has to be changed back to TID and such.. */
    register kmp_int32   gtid = global_tid;
    register kmp_uint32  tid;
    register kmp_uint32  nth;
    register UT          trip_count;
    register kmp_team_t *team;

    KE_TRACE( 10, ("__kmpc_for_static_init called (%d)\n", global_tid));
    #ifdef KMP_DEBUG
    {
        const char * buff;
        // create format specifiers before the debug output
        buff = __kmp_str_format(
            "__kmpc_for_static_init: T#%%d sched=%%d liter=%%d iter=(%%%s," \
            " %%%s, %%%s) incr=%%%s chunk=%%%s signed?<%s>\n",
            traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec,
            traits_t< ST >::spec, traits_t< ST >::spec, traits_t< T >::spec );
        KD_TRACE(100, ( buff, global_tid, schedtype, *plastiter,
            *plower, *pupper, *pstride, incr, chunk ) );
        __kmp_str_free( &buff );
    }
    #endif

    if ( __kmp_env_consistency_check ) {
        __kmp_push_workshare( global_tid, ct_pdo, loc );
        if ( incr == 0 ) {
            __kmp_error_construct( kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo, loc );

        }
    }
    /* special handling for zero-trip loops */
    if ( incr > 0 ? (*pupper < *plower) : (*plower < *pupper) ) {
        *plastiter = FALSE;
        /* leave pupper and plower set to entire iteration space */
        *pstride = incr;   /* value should never be used */
	//        *plower = *pupper - incr;   // let compiler bypass the illegal loop (like for(i=1;i<10;i--))  THIS LINE CAUSED shape2F/h_tests_1.f TO HAVE A FAILURE ON A ZERO-TRIP LOOP (lower=1,\
	  upper=0,stride=1) - JPH June 23, 2009.
        #ifdef KMP_DEBUG
        {
            const char * buff;
            // create format specifiers before the debug output
            buff = __kmp_str_format(
                "__kmpc_for_static_init:(ZERO TRIP) liter=%%d lower=%%%s upper=%%%s stride = %%%s signed?<%s>, loc = %%s\n",
                traits_t< T >::spec, traits_t< T >::spec, traits_t< ST >::spec, traits_t< T >::spec );
            KD_TRACE(100, ( buff, *plastiter, *plower, *pupper, *pstride, loc->psource ) );
            __kmp_str_free( &buff );
        }
        #endif
        KE_TRACE( 10, ("__kmpc_for_static_init: T#%d return\n", global_tid ) );
        return;
    }
static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid,
                                  kmp_int32 schedtype, kmp_int32 *plastiter,
                                  T *plower, T *pupper,
                                  typename traits_t<T>::signed_t *pstride,
                                  typename traits_t<T>::signed_t incr,
                                  typename traits_t<T>::signed_t chunk
#if OMPT_SUPPORT && OMPT_OPTIONAL
                                  ,
                                  void *codeptr
#endif
                                  ) {
  KMP_COUNT_BLOCK(OMP_FOR_static);
  KMP_TIME_PARTITIONED_BLOCK(FOR_static_scheduling);

  typedef typename traits_t<T>::unsigned_t UT;
  typedef typename traits_t<T>::signed_t ST;
  /*  this all has to be changed back to TID and such.. */
  kmp_int32 gtid = global_tid;
  kmp_uint32 tid;
  kmp_uint32 nth;
  UT trip_count;
  kmp_team_t *team;
  kmp_info_t *th = __kmp_threads[gtid];

#if OMPT_SUPPORT && OMPT_OPTIONAL
  ompt_team_info_t *team_info = NULL;
  ompt_task_info_t *task_info = NULL;
  ompt_work_type_t ompt_work_type = ompt_work_loop;

  static kmp_int8 warn = 0;

  if (ompt_enabled.ompt_callback_work) {
    // Only fully initialize variables needed by OMPT if OMPT is enabled.
    team_info = __ompt_get_teaminfo(0, NULL);
    task_info = __ompt_get_task_info_object(0);
    // Determine workshare type
    if (loc != NULL) {
      if ((loc->flags & KMP_IDENT_WORK_LOOP) != 0) {
        ompt_work_type = ompt_work_loop;
      } else if ((loc->flags & KMP_IDENT_WORK_SECTIONS) != 0) {
        ompt_work_type = ompt_work_sections;
      } else if ((loc->flags & KMP_IDENT_WORK_DISTRIBUTE) != 0) {
        ompt_work_type = ompt_work_distribute;
      } else {
        kmp_int8 bool_res =
            KMP_COMPARE_AND_STORE_ACQ8(&warn, (kmp_int8)0, (kmp_int8)1);
        if (bool_res)
          KMP_WARNING(OmptOutdatedWorkshare);
      }
      KMP_DEBUG_ASSERT(ompt_work_type);
    }
  }
#endif

  KMP_DEBUG_ASSERT(plastiter && plower && pupper && pstride);
  KE_TRACE(10, ("__kmpc_for_static_init called (%d)\n", global_tid));
#ifdef KMP_DEBUG
  {
    char *buff;
    // create format specifiers before the debug output
    buff = __kmp_str_format(
        "__kmpc_for_static_init: T#%%d sched=%%d liter=%%d iter=(%%%s,"
        " %%%s, %%%s) incr=%%%s chunk=%%%s signed?<%s>\n",
        traits_t<T>::spec, traits_t<T>::spec, traits_t<ST>::spec,
        traits_t<ST>::spec, traits_t<ST>::spec, traits_t<T>::spec);
    KD_TRACE(100, (buff, global_tid, schedtype, *plastiter, *plower, *pupper,
                   *pstride, incr, chunk));
    __kmp_str_free(&buff);
  }
#endif

  if (__kmp_env_consistency_check) {
    __kmp_push_workshare(global_tid, ct_pdo, loc);
    if (incr == 0) {
      __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo,
                            loc);
    }
  }
  /* special handling for zero-trip loops */
  if (incr > 0 ? (*pupper < *plower) : (*plower < *pupper)) {
    if (plastiter != NULL)
      *plastiter = FALSE;
    /* leave pupper and plower set to entire iteration space */
    *pstride = incr; /* value should never be used */
// *plower = *pupper - incr;
// let compiler bypass the illegal loop (like for(i=1;i<10;i--))
// THE LINE COMMENTED ABOVE CAUSED shape2F/h_tests_1.f TO HAVE A FAILURE
// ON A ZERO-TRIP LOOP (lower=1, upper=0,stride=1) - JPH June 23, 2009.
#ifdef KMP_DEBUG
    {
      char *buff;
      // create format specifiers before the debug output
      buff = __kmp_str_format("__kmpc_for_static_init:(ZERO TRIP) liter=%%d "
                              "lower=%%%s upper=%%%s stride = %%%s "
                              "signed?<%s>, loc = %%s\n",
                              traits_t<T>::spec, traits_t<T>::spec,
                              traits_t<ST>::spec, traits_t<T>::spec);
      KD_TRACE(100,
               (buff, *plastiter, *plower, *pupper, *pstride, loc->psource));
      __kmp_str_free(&buff);
    }
#endif
    KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));

#if OMPT_SUPPORT && OMPT_OPTIONAL
    if (ompt_enabled.ompt_callback_work) {
      ompt_callbacks.ompt_callback(ompt_callback_work)(
          ompt_work_type, ompt_scope_begin, &(team_info->parallel_data),
          &(task_info->task_data), 0, codeptr);
    }
#endif
    KMP_COUNT_VALUE(FOR_static_iterations, 0);
    return;
  }

#if OMP_40_ENABLED
  // Although there are schedule enumerations above kmp_ord_upper which are not
  // schedules for "distribute", the only ones which are useful are dynamic, so
  // cannot be seen here, since this codepath is only executed for static
  // schedules.
  if (schedtype > kmp_ord_upper) {
    // we are in DISTRIBUTE construct
    schedtype += kmp_sch_static -
                 kmp_distribute_static; // AC: convert to usual schedule type
    tid = th->th.th_team->t.t_master_tid;
    team = th->th.th_team->t.t_parent;
  } else
#endif
  {
    tid = __kmp_tid_from_gtid(global_tid);
    team = th->th.th_team;
  }

  /* determine if "for" loop is an active worksharing construct */
  if (team->t.t_serialized) {
    /* serialized parallel, each thread executes whole iteration space */
    if (plastiter != NULL)
      *plastiter = TRUE;
    /* leave pupper and plower set to entire iteration space */
    *pstride =
        (incr > 0) ? (*pupper - *plower + 1) : (-(*plower - *pupper + 1));

#ifdef KMP_DEBUG
    {
      char *buff;
      // create format specifiers before the debug output
      buff = __kmp_str_format("__kmpc_for_static_init: (serial) liter=%%d "
                              "lower=%%%s upper=%%%s stride = %%%s\n",
                              traits_t<T>::spec, traits_t<T>::spec,
                              traits_t<ST>::spec);
      KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pstride));
      __kmp_str_free(&buff);
    }
#endif
    KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));

#if OMPT_SUPPORT && OMPT_OPTIONAL
    if (ompt_enabled.ompt_callback_work) {
      ompt_callbacks.ompt_callback(ompt_callback_work)(
          ompt_work_type, ompt_scope_begin, &(team_info->parallel_data),
          &(task_info->task_data), *pstride, codeptr);
    }
#endif
    return;
  }
  nth = team->t.t_nproc;
  if (nth == 1) {
    if (plastiter != NULL)
      *plastiter = TRUE;
    *pstride =
        (incr > 0) ? (*pupper - *plower + 1) : (-(*plower - *pupper + 1));
#ifdef KMP_DEBUG
    {
      char *buff;
      // create format specifiers before the debug output
      buff = __kmp_str_format("__kmpc_for_static_init: (serial) liter=%%d "
                              "lower=%%%s upper=%%%s stride = %%%s\n",
                              traits_t<T>::spec, traits_t<T>::spec,
                              traits_t<ST>::spec);
      KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pstride));
      __kmp_str_free(&buff);
    }
#endif
    KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));

#if OMPT_SUPPORT && OMPT_OPTIONAL
    if (ompt_enabled.ompt_callback_work) {
      ompt_callbacks.ompt_callback(ompt_callback_work)(
          ompt_work_type, ompt_scope_begin, &(team_info->parallel_data),
          &(task_info->task_data), *pstride, codeptr);
    }
#endif
    return;
  }

  /* compute trip count */
  if (incr == 1) {
    trip_count = *pupper - *plower + 1;
  } else if (incr == -1) {
    trip_count = *plower - *pupper + 1;
  } else if (incr > 0) {
    // upper-lower can exceed the limit of signed type
    trip_count = (UT)(*pupper - *plower) / incr + 1;
  } else {
    trip_count = (UT)(*plower - *pupper) / (-incr) + 1;
  }

  if (__kmp_env_consistency_check) {
    /* tripcount overflow? */
    if (trip_count == 0 && *pupper != *plower) {
      __kmp_error_construct(kmp_i18n_msg_CnsIterationRangeTooLarge, ct_pdo,
                            loc);
    }
  }
  KMP_COUNT_VALUE(FOR_static_iterations, trip_count);

  /* compute remaining parameters */
  switch (schedtype) {
  case kmp_sch_static: {
    if (trip_count < nth) {
      KMP_DEBUG_ASSERT(
          __kmp_static == kmp_sch_static_greedy ||
          __kmp_static ==
              kmp_sch_static_balanced); // Unknown static scheduling type.
      if (tid < trip_count) {
        *pupper = *plower = *plower + tid * incr;
      } else {
        *plower = *pupper + incr;
      }
      if (plastiter != NULL)
        *plastiter = (tid == trip_count - 1);
    } else {
      if (__kmp_static == kmp_sch_static_balanced) {
        UT small_chunk = trip_count / nth;
        UT extras = trip_count % nth;
        *plower += incr * (tid * small_chunk + (tid < extras ? tid : extras));
        *pupper = *plower + small_chunk * incr - (tid < extras ? 0 : incr);
        if (plastiter != NULL)
          *plastiter = (tid == nth - 1);
      } else {
        T big_chunk_inc_count =
            (trip_count / nth + ((trip_count % nth) ? 1 : 0)) * incr;
        T old_upper = *pupper;

        KMP_DEBUG_ASSERT(__kmp_static == kmp_sch_static_greedy);
        // Unknown static scheduling type.

        *plower += tid * big_chunk_inc_count;
        *pupper = *plower + big_chunk_inc_count - incr;
        if (incr > 0) {
          if (*pupper < *plower)
            *pupper = traits_t<T>::max_value;
          if (plastiter != NULL)
            *plastiter = *plower <= old_upper && *pupper > old_upper - incr;
          if (*pupper > old_upper)
            *pupper = old_upper; // tracker C73258
        } else {
          if (*pupper > *plower)
            *pupper = traits_t<T>::min_value;
          if (plastiter != NULL)
            *plastiter = *plower >= old_upper && *pupper < old_upper - incr;
          if (*pupper < old_upper)
            *pupper = old_upper; // tracker C73258
        }
      }
    }
    *pstride = trip_count;
    break;
  }
  case kmp_sch_static_chunked: {
    ST span;
    if (chunk < 1) {
      chunk = 1;
    }
    span = chunk * incr;
    *pstride = span * nth;
    *plower = *plower + (span * tid);
    *pupper = *plower + span - incr;
    if (plastiter != NULL)
      *plastiter = (tid == ((trip_count - 1) / (UT)chunk) % nth);
    break;
  }
#if OMP_45_ENABLED
  case kmp_sch_static_balanced_chunked: {
    T old_upper = *pupper;
    // round up to make sure the chunk is enough to cover all iterations
    UT span = (trip_count + nth - 1) / nth;

    // perform chunk adjustment
    chunk = (span + chunk - 1) & ~(chunk - 1);

    span = chunk * incr;
    *plower = *plower + (span * tid);
    *pupper = *plower + span - incr;
    if (incr > 0) {
      if (*pupper > old_upper)
        *pupper = old_upper;
    } else if (*pupper < old_upper)
      *pupper = old_upper;

    if (plastiter != NULL)
      *plastiter = (tid == ((trip_count - 1) / (UT)chunk));
    break;
  }
#endif
  default:
    KMP_ASSERT2(0, "__kmpc_for_static_init: unknown scheduling type");
    break;
  }

#if USE_ITT_BUILD
  // Report loop metadata
  if (KMP_MASTER_TID(tid) && __itt_metadata_add_ptr &&
      __kmp_forkjoin_frames_mode == 3 &&
#if OMP_40_ENABLED
      th->th.th_teams_microtask == NULL &&
#endif
      team->t.t_active_level == 1) {
    kmp_uint64 cur_chunk = chunk;
    // Calculate chunk in case it was not specified; it is specified for
    // kmp_sch_static_chunked
    if (schedtype == kmp_sch_static) {
      cur_chunk = trip_count / nth + ((trip_count % nth) ? 1 : 0);
    }
    // 0 - "static" schedule
    __kmp_itt_metadata_loop(loc, 0, trip_count, cur_chunk);
  }
#endif
#ifdef KMP_DEBUG
  {
    char *buff;
    // create format specifiers before the debug output
    buff = __kmp_str_format("__kmpc_for_static_init: liter=%%d lower=%%%s "
                            "upper=%%%s stride = %%%s signed?<%s>\n",
                            traits_t<T>::spec, traits_t<T>::spec,
                            traits_t<ST>::spec, traits_t<T>::spec);
    KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pstride));
    __kmp_str_free(&buff);
  }
#endif
  KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));

#if OMPT_SUPPORT && OMPT_OPTIONAL
  if (ompt_enabled.ompt_callback_work) {
    ompt_callbacks.ompt_callback(ompt_callback_work)(
        ompt_work_type, ompt_scope_begin, &(team_info->parallel_data),
        &(task_info->task_data), trip_count, codeptr);
  }
#endif

  return;
}
static ompt_start_tool_result_t *
ompt_try_start_tool(unsigned int omp_version, const char *runtime_version) {
  ompt_start_tool_result_t *ret = NULL;
  ompt_start_tool_t start_tool = NULL;
#if KMP_OS_WINDOWS
  // Cannot use colon to describe a list of absolute paths on Windows
  const char *sep = ";";
#else
  const char *sep = ":";
#endif

#if KMP_OS_DARWIN
  // Try in the current address space
  ret = ompt_tool_darwin(omp_version, runtime_version);
#elif OMPT_HAVE_WEAK_ATTRIBUTE
  ret = ompt_start_tool(omp_version, runtime_version);
#elif OMPT_HAVE_PSAPI
  ret = ompt_tool_windows(omp_version, runtime_version);
#else
#error Activation of OMPT is not supported on this platform.
#endif
  if (ret)
    return ret;

  // Try tool-libraries-var ICV
  const char *tool_libs = getenv("OMP_TOOL_LIBRARIES");
  if (tool_libs) {
    char *libs = __kmp_str_format("%s", tool_libs);
    char *buf;
    char *fname = __kmp_str_token(libs, sep, &buf);
    while (fname) {
#if KMP_OS_UNIX
      void *h = dlopen(fname, RTLD_LAZY);
      if (h) {
        start_tool = (ompt_start_tool_t)dlsym(h, "ompt_start_tool");
#elif KMP_OS_WINDOWS
      HMODULE h = LoadLibrary(fname);
      if (h) {
        start_tool = (ompt_start_tool_t)GetProcAddress(h, "ompt_start_tool");
#else
#error Activation of OMPT is not supported on this platform.
#endif
        if (start_tool && (ret = (*start_tool)(omp_version, runtime_version)))
          break;
      }
      fname = __kmp_str_token(NULL, sep, &buf);
    }
    __kmp_str_free(&libs);
  }
  return ret;
}

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:

    //--------------------------------------------------
    // Load tool iff specified in environment variable
    //--------------------------------------------------
    ompt_start_tool_result =
        ompt_try_start_tool(__kmp_openmp_version, ompt_get_runtime_version());

    memset(&ompt_enabled, 0, sizeof(ompt_enabled));
    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_start_tool_result) {
    ompt_enabled.enabled = !!ompt_start_tool_result->initialize(
        ompt_fn_lookup, &(ompt_start_tool_result->tool_data));

    if (!ompt_enabled.enabled) {
      // tool not enabled, zero out the bitmap, and done
      memset(&ompt_enabled, 0, sizeof(ompt_enabled));
      return;
    }

    ompt_thread_t *root_thread = ompt_get_thread();

    ompt_set_thread_state(root_thread, omp_state_overhead);

    if (ompt_enabled.ompt_callback_thread_begin) {
      ompt_callbacks.ompt_callback(ompt_callback_thread_begin)(
          ompt_thread_initial, __ompt_get_thread_data_internal());
    }
    ompt_data_t *task_data;
    __ompt_get_task_info_internal(0, NULL, &task_data, NULL, NULL, NULL);
    if (ompt_enabled.ompt_callback_task_create) {
      ompt_callbacks.ompt_callback(ompt_callback_task_create)(
          NULL, NULL, task_data, ompt_task_initial, 0, NULL);
    }

    ompt_set_thread_state(root_thread, omp_state_work_serial);
  }
}

void ompt_fini() {
  if (ompt_enabled.enabled) {
    ompt_start_tool_result->finalize(&(ompt_start_tool_result->tool_data));
  }

  memset(&ompt_enabled, 0, sizeof(ompt_enabled));
}

/*****************************************************************************
 * interface operations
 ****************************************************************************/

/*****************************************************************************
 * state
 ****************************************************************************/

OMPT_API_ROUTINE int ompt_enumerate_states(int current_state, int *next_state,
                                           const char **next_state_name) {
  const static int len = sizeof(omp_state_info) / sizeof(omp_state_info_t);
  int i = 0;

  for (i = 0; i < len - 1; i++) {
    if (omp_state_info[i].state_id == current_state) {
      *next_state = omp_state_info[i + 1].state_id;
      *next_state_name = omp_state_info[i + 1].state_name;
      return 1;
    }
  }

  return 0;
}

OMPT_API_ROUTINE int ompt_enumerate_mutex_impls(int current_impl,
                                                int *next_impl,
                                                const char **next_impl_name) {
  const static int len =
      sizeof(kmp_mutex_impl_info) / sizeof(kmp_mutex_impl_info_t);
  int i = 0;
  for (i = 0; i < len - 1; i++) {
    if (kmp_mutex_impl_info[i].id != current_impl)
      continue;
    *next_impl = kmp_mutex_impl_info[i + 1].id;
    *next_impl_name = kmp_mutex_impl_info[i + 1].name;
    return 1;
  }
  return 0;
}

/*****************************************************************************
 * callbacks
 ****************************************************************************/

OMPT_API_ROUTINE int ompt_set_callback(ompt_callbacks_t which,
                                       ompt_callback_t callback) {
  switch (which) {

#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)callback;      \
      ompt_enabled.event_name = (callback != 0);                               \
    }                                                                          \
    if (callback)                                                              \
      return ompt_event_implementation_status(event_name);                     \
    else                                                                       \
      return ompt_set_always;

    FOREACH_OMPT_EVENT(ompt_event_macro)

#undef ompt_event_macro

  default:
    return ompt_set_error;
  }
}

OMPT_API_ROUTINE int ompt_get_callback(ompt_callbacks_t which,
                                       ompt_callback_t *callback) {
  switch (which) {

#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) {                                                              \
        *callback = 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 int ompt_get_parallel_info(int ancestor_level,
                                            ompt_data_t **parallel_data,
                                            int *team_size) {
  return __ompt_get_parallel_info_internal(ancestor_level, parallel_data,
                                           team_size);
}

OMPT_API_ROUTINE omp_state_t ompt_get_state(omp_wait_id_t *wait_id) {
  omp_state_t thread_state = __ompt_get_state_internal(wait_id);

  if (thread_state == omp_state_undefined) {
    thread_state = omp_state_work_serial;
  }

  return thread_state;
}