Esempio n. 1
0
char *__kmp_env_get(char const *name) {

  char *result = NULL;

#if KMP_OS_UNIX
  char const *value = getenv(name);
  if (value != NULL) {
    size_t len = KMP_STRLEN(value) + 1;
    result = (char *)KMP_INTERNAL_MALLOC(len);
    if (result == NULL) {
      KMP_FATAL(MemoryAllocFailed);
    }
    KMP_STRNCPY_S(result, len, value, len);
  }
#elif KMP_OS_WINDOWS
  /* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
     act of loading a DLL on Windows* OS makes any user-set environment
     variables (i.e. with putenv()) unavailable. getenv() apparently gets a
     clean copy of the env variables as they existed at the start of the run.
     JH 12/23/2002 */
  DWORD rc;
  rc = GetEnvironmentVariable(name, NULL, 0);
  if (!rc) {
    DWORD error = GetLastError();
    if (error != ERROR_ENVVAR_NOT_FOUND) {
      __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
    }
    // Variable is not found, it's ok, just continue.
  } else {
    DWORD len = rc;
    result = (char *)KMP_INTERNAL_MALLOC(len);
    if (result == NULL) {
      KMP_FATAL(MemoryAllocFailed);
    }
    rc = GetEnvironmentVariable(name, result, len);
    if (!rc) {
      // GetEnvironmentVariable() may return 0 if variable is empty.
      // In such a case GetLastError() returns ERROR_SUCCESS.
      DWORD error = GetLastError();
      if (error != ERROR_SUCCESS) {
        // Unexpected error. The variable should be in the environment,
        // and buffer should be large enough.
        __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error),
                    __kmp_msg_null);
        KMP_INTERNAL_FREE((void *)result);
        result = NULL;
      }
    }
  }
#else
#error Unknown or unsupported OS.
#endif

  return result;

} // func __kmp_env_get
Esempio n. 2
0
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;
}
Esempio n. 3
0
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 = vsnprintf( buffer, size, format, args );
        va_end( args );

        // No errors, string has been formatted.
        if ( rc >= 0 && rc < size ) {
            break;
        }; // if

        // Error occured, 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
Esempio n. 4
0
static inline void *allocate(size_t size) {
  void *ptr = KMP_INTERNAL_MALLOC(size);
  if (ptr == NULL) {
    KMP_FATAL(MemoryAllocFailed);
  }
  return ptr;
} // allocate
Esempio n. 5
0
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 < size ) {

        // Calculate buffer size.
        do {
            buffer->size *= 2;
        } while ( buffer->size < 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
            memcpy( buffer->str, 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 >= size );
    KMP_STR_BUF_INVARIANT( buffer );

} // __kmp_str_buf_reserve
Esempio n. 6
0
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
        memcpy( buffer->str, buffer->bulk, buffer->used + 1 );
    }; // if

} // __kmp_str_buf_detach
Esempio n. 7
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
Esempio n. 8
0
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;
}