PAPI  5.0.1.0
threads.c File Reference
Include dependency graph for threads.c:

Go to the source code of this file.

Functions

static int lookup_and_set_thread_symbols (void)
static ThreadInfo_tallocate_thread (int tid)
static void free_thread (ThreadInfo_t **thread)
static void insert_thread (ThreadInfo_t *entry, int tid)
static int remove_thread (ThreadInfo_t *entry)
int _papi_hwi_initialize_thread (ThreadInfo_t **dest, int tid)
int _papi_hwi_set_thread_id_fn (unsigned long(*id_fn)(void))
static int _papi_hwi_thread_free_eventsets (long tid)
int _papi_hwi_shutdown_thread (ThreadInfo_t *thread)
int _papi_hwi_shutdown_global_threads (void)
int _papi_hwi_init_global_threads (void)
int _papi_hwi_gather_all_thrspec_data (int tag, PAPI_all_thr_spec_t *where)

Variables

volatile ThreadInfo_t_papi_hwi_thread_head
__thread ThreadInfo_t_papi_hwi_my_thread
unsigned long(* _papi_hwi_thread_id_fn )(void)

Function Documentation

< Used with setting up array

< Used with setting up array

< No error

Definition at line 557 of file threads.c.

{
    int didsomething = 0;
    ThreadInfo_t *foo = NULL;

    _papi_hwi_lock( THREADS_LOCK );

    for ( foo = ( ThreadInfo_t * ) _papi_hwi_thread_head; foo != NULL;
          foo = foo->next ) {
        /* If we want thread ID's */
        if ( where->id )
            memcpy( &where->id[didsomething], &foo->tid,
                    sizeof ( where->id[didsomething] ) );

        /* If we want data pointers */
        if ( where->data )
            where->data[didsomething] = foo->thread_storage[tag];

        didsomething++;

        if ( ( where->id ) || ( where->data ) ) {
            if ( didsomething >= where->num )
                break;
        }

        if ( foo->next == _papi_hwi_thread_head )
            break;
    }

    where->num = didsomething;
    _papi_hwi_unlock( THREADS_LOCK );

    return ( PAPI_OK );

}

Here is the call graph for this function:

Here is the caller graph for this function:

< Used with setting up array

< No error

< Used with setting up array

Definition at line 530 of file threads.c.

{
    int retval;
    ThreadInfo_t *tmp;

    _papi_hwi_lock( GLOBAL_LOCK );

#if defined(HAVE_THREAD_LOCAL_STORAGE)
    _papi_hwi_my_thread = NULL;
#endif
    _papi_hwi_thread_head = NULL;
    _papi_hwi_thread_id_fn = NULL;
#if defined(ANY_THREAD_GETS_SIGNAL)
    _papi_hwi_thread_kill_fn = NULL;
#endif

    retval = _papi_hwi_initialize_thread( &tmp , 0);
    if ( retval == PAPI_OK ) {
       retval = lookup_and_set_thread_symbols(  );
    }

    _papi_hwi_unlock( GLOBAL_LOCK );

    return ( retval );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int _papi_hwi_initialize_thread ( ThreadInfo_t **  dest,
int  tid 
)

< Insufficient memory

< No error

Definition at line 276 of file threads.c.

{
    int retval;
    ThreadInfo_t *thread;
    int i;

    if ( ( thread = allocate_thread( tid  ) ) == NULL ) {
        *dest = NULL;
        return PAPI_ENOMEM;
    }

    /* Call the component to fill in anything special. */

    for ( i = 0; i < papi_num_components; i++ ) {
        if (_papi_hwd[i]->cmp_info.disabled) continue;
        retval = _papi_hwd[i]->init_thread( thread->context[i] );
        if ( retval ) {
           free_thread( &thread );
           *dest = NULL;
           return retval;
        }
    }

    insert_thread( thread, tid );

    *dest = thread;
    return PAPI_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int _papi_hwi_set_thread_id_fn ( unsigned long(*)(void)  id_fn)

< Invalid argument

< Invalid argument

< No error

Definition at line 350 of file threads.c.

{
#if !defined(ANY_THREAD_GETS_SIGNAL)
    /* Check for multiple threads still in the list, if so, we can't change it */

    if ( _papi_hwi_thread_head->next != _papi_hwi_thread_head )
        return ( PAPI_EINVAL );

    /* We can't change the thread id function from one to another, 
       only NULL to non-NULL and vice versa. */

    if ( ( id_fn != NULL ) && ( _papi_hwi_thread_id_fn != NULL ) )
        return ( PAPI_EINVAL );

    _papi_hwi_thread_id_fn = id_fn;

    THRDBG( "Set new thread id function to %p\n", id_fn );

    if ( id_fn )
        _papi_hwi_thread_head->tid = ( *_papi_hwi_thread_id_fn ) (  );
    else
        _papi_hwi_thread_head->tid = ( unsigned long ) getpid(  );

    THRDBG( "New master tid is %ld\n", _papi_hwi_thread_head->tid );
#else
    THRDBG( "Skipping set of thread id function\n" );
#endif

    return PAPI_OK;
}

Here is the caller graph for this function:

< Internal error, please send mail to the developers

Definition at line 457 of file threads.c.

{
        int err,num_threads,i;
    ThreadInfo_t *tmp,*next;
    unsigned long our_tid;

    tmp = _papi_hwi_lookup_thread( 0 );

    if ( tmp == NULL ) {
       THRDBG( "Did not find my thread for shutdown!\n" );
       err = PAPI_EBUG;
    }
    else {
       our_tid=tmp->tid;

       THRDBG("Shutting down %ld\n",our_tid);

       err = _papi_hwi_shutdown_thread( tmp );


       /* count threads */
       tmp = ( ThreadInfo_t * ) _papi_hwi_thread_head;
       num_threads=0;
       while(tmp!=NULL) {
          num_threads++;
          if (tmp->next==_papi_hwi_thread_head) break;
          tmp=tmp->next;
       }

       /* Shut down all threads allocated by this thread */
       /* Urgh it's a circular list where we removed in the loop  */
       /* so the only sane way to do it is get a count in advance */
       tmp = ( ThreadInfo_t * ) _papi_hwi_thread_head;

       for(i=0;i<num_threads;i++) {

          next=tmp->next;

          THRDBG("looking at #%d %ld our_tid: %ld alloc_tid: %ld\n",
             i,tmp->tid,our_tid,tmp->allocator_tid);
        
          if (tmp->allocator_tid==our_tid) {
         THRDBG("Also removing thread %ld\n",tmp->tid);
             err = _papi_hwi_shutdown_thread( tmp );
          }
  
          tmp=next;

       }
    }


#ifdef DEBUG
    if ( ISLEVEL( DEBUG_THREADS ) ) {
        if ( _papi_hwi_thread_head ) {
            THRDBG( "Thread head %p still exists!\n", _papi_hwi_thread_head );
        }
    }
#endif

#if defined(HAVE_THREAD_LOCAL_STORAGE)
    _papi_hwi_my_thread = NULL;
#endif
    _papi_hwi_thread_head = NULL;
    _papi_hwi_thread_id_fn = NULL;
#if defined(ANY_THREAD_GETS_SIGNAL)
    _papi_hwi_thread_kill_fn = NULL;
#endif

    return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

< No error

< No error

< Internal error, please send mail to the developers

Definition at line 418 of file threads.c.

{
    int retval = PAPI_OK;
    unsigned long tid;
    int i, failure = 0;

    if ( _papi_hwi_thread_id_fn )
        tid = ( *_papi_hwi_thread_id_fn ) (  );
    else
        tid = ( unsigned long ) getpid(  );

        THRDBG("Want to shutdown thread %ld, alloc %ld, our_tid: %ld\n",
           thread->tid,
           thread->allocator_tid,
           tid);

    if ((thread->tid==tid) || ( thread->allocator_tid == tid )) {

                _papi_hwi_thread_free_eventsets(tid);

        remove_thread( thread );
        THRDBG( "Shutting down thread %ld at %p\n", thread->tid, thread );
        for( i = 0; i < papi_num_components; i++ ) {
           if (_papi_hwd[i]->cmp_info.disabled) continue;
           retval = _papi_hwd[i]->shutdown_thread( thread->context[i]);
           if ( retval != PAPI_OK ) failure = retval;
        }
        free_thread( &thread );
        return ( failure );
    }

    THRDBG( "Skipping shutdown thread %ld at %p, thread %ld not allocator!\n",
            thread->tid, thread, tid );
    return PAPI_EBUG;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int _papi_hwi_thread_free_eventsets ( long  tid) [static]

< Used with setting up array

< Used with setting up array

< No error

Definition at line 382 of file threads.c.

                                                     {

   EventSetInfo_t *ESI;
   ThreadInfo_t *master;
   DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
   int i;

   master = _papi_hwi_lookup_thread( tid );

   _papi_hwi_lock( INTERNAL_LOCK );

   for( i = 0; i < map->totalSlots; i++ ) {
      ESI = map->dataSlotArray[i];
      if ( ( ESI ) && (ESI->master!=NULL) ) {

     if ( ESI->master == master ) {
        THRDBG("Attempting to remove %d from tid %ld\n",ESI->EventSetIndex,tid);

        /* Code copied from _papi_hwi_remove_EventSet(ESI);      */
        _papi_hwi_free_EventSet( ESI );
        map->dataSlotArray[i] = NULL;
        map->availSlots++;
        map->fullSlots--;
     } 
      }
   }

   _papi_hwi_unlock( INTERNAL_LOCK );

   return PAPI_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static ThreadInfo_t* allocate_thread ( int  tid) [static]

Definition at line 96 of file threads.c.

{
    ThreadInfo_t *thread;
    int i;

    /* The Thread EventSet is special. It is not in the EventSet list, but is pointed
       to by each EventSet of that particular thread. */

    thread = ( ThreadInfo_t * ) papi_malloc( sizeof ( ThreadInfo_t ) );
    if ( thread == NULL )
        return ( NULL );
    memset( thread, 0x00, sizeof ( ThreadInfo_t ) );

    thread->context =
        ( hwd_context_t ** ) papi_malloc( sizeof ( hwd_context_t * ) *
                                          ( size_t ) papi_num_components );
    if ( !thread->context ) {
        papi_free( thread );
        return ( NULL );
    }

    thread->running_eventset =
        ( EventSetInfo_t ** ) papi_malloc( sizeof ( EventSetInfo_t * ) *
                                           ( size_t ) papi_num_components );
    if ( !thread->running_eventset ) {
        papi_free( thread->context );
        papi_free( thread );
        return ( NULL );
    }

    for ( i = 0; i < papi_num_components; i++ ) {
        thread->context[i] =
            ( void * ) papi_malloc( ( size_t ) _papi_hwd[i]->size.context );
        thread->running_eventset[i] = NULL;
        if ( thread->context[i] == NULL ) {
            for ( i--; i >= 0; i-- )
                papi_free( thread->context[i] );
            papi_free( thread->context );
            papi_free( thread );
            return ( NULL );
        }
        memset( thread->context[i], 0x00,
                ( size_t ) _papi_hwd[i]->size.context );
    }

    if ( _papi_hwi_thread_id_fn ) {
           thread->tid = ( *_papi_hwi_thread_id_fn ) (  );
    }
    else {
       thread->tid = ( unsigned long ) getpid(  );
    }

    thread->allocator_tid=thread->tid;

    if (tid == 0 ) {
    }
    else {
      thread->tid=tid;
    }

    THRDBG( "Allocated thread %ld at %p, allocator: %ld\n", thread->tid, 
        thread,
        thread->allocator_tid );

    return thread;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void free_thread ( ThreadInfo_t **  thread) [static]

Definition at line 164 of file threads.c.

{
    int i;
    THRDBG( "Freeing thread %ld at %p\n", ( *thread )->tid, *thread );

    for ( i = 0; i < papi_num_components; i++ ) {
        if ( ( *thread )->context[i] )
            papi_free( ( *thread )->context[i] );
    }

    if ( ( *thread )->context )
        papi_free( ( *thread )->context );

    if ( ( *thread )->running_eventset )
        papi_free( ( *thread )->running_eventset );

    memset( *thread, 0x00, sizeof ( ThreadInfo_t ) );
    papi_free( *thread );
    *thread = NULL;
}

Here is the caller graph for this function:

static void insert_thread ( ThreadInfo_t entry,
int  tid 
) [static]

< Used with setting up array

< Used with setting up array

Definition at line 186 of file threads.c.

{
    _papi_hwi_lock( THREADS_LOCK );

    if ( _papi_hwi_thread_head == NULL ) {  /* 0 elements */
        THRDBG( "_papi_hwi_thread_head is NULL\n" );
        entry->next = entry;
    } else if ( _papi_hwi_thread_head->next == _papi_hwi_thread_head ) {    /* 1 elements */
        THRDBG( "_papi_hwi_thread_head was thread %ld at %p\n",
                _papi_hwi_thread_head->tid, _papi_hwi_thread_head );
        _papi_hwi_thread_head->next = entry;
        entry->next = ( ThreadInfo_t * ) _papi_hwi_thread_head;
    } else {                 /* 2+ elements */

        THRDBG( "_papi_hwi_thread_head was thread %ld at %p\n",
                _papi_hwi_thread_head->tid, _papi_hwi_thread_head );
        entry->next = _papi_hwi_thread_head->next;
        _papi_hwi_thread_head->next = entry;
    }

    _papi_hwi_thread_head = entry;

    THRDBG( "_papi_hwi_thread_head now thread %ld at %p\n",
            _papi_hwi_thread_head->tid, _papi_hwi_thread_head );

    _papi_hwi_unlock( THREADS_LOCK );

#if defined(HAVE_THREAD_LOCAL_STORAGE)
    /* Don't set the current local thread if we are a fake attach thread */
        if (tid==0) {
       _papi_hwi_my_thread = entry;
       THRDBG( "TLS for thread %ld is now %p\n", entry->tid,
            _papi_hwi_my_thread );
    }
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int lookup_and_set_thread_symbols ( void  ) [static]

< No error

Definition at line 55 of file threads.c.

{
#if defined(ANY_THREAD_GETS_SIGNAL)
    int retval;
    char *error_ptc = NULL, *error_ptk = NULL;
    void *symbol_ptc = NULL, *symbol_ptk = NULL, *handle = NULL;

    handle = dlopen( NULL, RTLD_LAZY );
    if ( handle == NULL ) {
        PAPIERROR( "Error from dlopen(NULL, RTLD_LAZY): %d %s", errno,
                   dlerror(  ) );
        return ( PAPI_ESYS );
    }

    symbol_ptc = dlsym( handle, "pthread_self" );
    if ( symbol_ptc == NULL ) {
        error_ptc = dlerror(  );
        THRDBG( "dlsym(%p,pthread_self) returned NULL: %s\n",
                ( error_ptc ? error_ptc : "No error, NULL symbol!" ) );
    }

    symbol_ptk = dlsym( handle, "pthread_kill" );
    if ( symbol_ptk == NULL ) {
        error_ptk = dlerror(  );
        THRDBG( "dlsym(%p,pthread_kill) returned NULL: %s\n",
                ( error_ptk ? error_ptk : "No error, NULL symbol!" ) );
    }

    dlclose( handle );

    if ( !( ( _papi_hwi_thread_kill_fn && _papi_hwi_thread_id_fn ) ||
            ( !_papi_hwi_thread_kill_fn && !_papi_hwi_thread_id_fn ) ) )
        return ( PAPI_EMISC );

    _papi_hwi_thread_kill_fn = ( int ( * )( int, int ) ) symbol_ptk;
    _papi_hwi_thread_id_fn = ( unsigned long ( * )( void ) ) symbol_ptc;
#endif
    return ( PAPI_OK );
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int remove_thread ( ThreadInfo_t entry) [static]

< Used with setting up array

< Internal error, please send mail to the developers

< Used with setting up array

< No error

Definition at line 224 of file threads.c.

{
    ThreadInfo_t *tmp = NULL, *prev = NULL;

    _papi_hwi_lock( THREADS_LOCK );

    THRDBG( "_papi_hwi_thread_head was thread %ld at %p\n",
            _papi_hwi_thread_head->tid, _papi_hwi_thread_head );

    /* Find the preceding element and the matched element,
       short circuit if we've seen the head twice */

    for ( tmp = ( ThreadInfo_t * ) _papi_hwi_thread_head;
          ( entry != tmp ) || ( prev == NULL ); tmp = tmp->next ) {
        prev = tmp;
    }

    if ( tmp != entry ) {
        THRDBG( "Thread %ld at %p was not found in the thread list!\n",
                entry->tid, entry );
        return ( PAPI_EBUG );
    }

    /* Only 1 element in list */

    if ( prev == tmp ) {
        _papi_hwi_thread_head = NULL;
        tmp->next = NULL;
        THRDBG( "_papi_hwi_thread_head now NULL\n" );
    } else {
        prev->next = tmp->next;
        /* If we're removing the head, better advance it! */
        if ( _papi_hwi_thread_head == tmp ) {
            _papi_hwi_thread_head = tmp->next;
            THRDBG( "_papi_hwi_thread_head now thread %ld at %p\n",
                    _papi_hwi_thread_head->tid, _papi_hwi_thread_head );
        }
        THRDBG( "Removed thread %p from list\n", tmp );
    }

    _papi_hwi_unlock( THREADS_LOCK );

#if defined(HAVE_THREAD_LOCAL_STORAGE)
    _papi_hwi_my_thread = NULL;
    THRDBG( "TLS for thread %ld is now %p\n", entry->tid,
            _papi_hwi_my_thread );
#endif

    return PAPI_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 37 of file threads.c.

The list of threads, gets initialized to master process with TID of getpid()

Definition at line 32 of file threads.c.

unsigned long( * _papi_hwi_thread_id_fn)(void)

Function that returns an unsigned long int thread identifier

Definition at line 42 of file threads.c.

 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines