PAPI  5.1.0.2
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_LOCAL_STORAGE_KEYWORD
ThreadInfo_t
_papi_hwi_my_thread
unsigned long(* _papi_hwi_thread_id_fn )(void)

Function Documentation

Definition at line 559 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:

Definition at line 532 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 
)

Definition at line 278 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)

Definition at line 352 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:

Definition at line 459 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:

Definition at line 420 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]

Definition at line 384 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]

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 );
    }
#else
    ( void ) tid;
#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]

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]

Definition at line 226 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

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