|
PAPI
5.0.1.0
|

Go to the source code of this file.
Functions | |
| static int | lookup_and_set_thread_symbols (void) |
| static ThreadInfo_t * | allocate_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) |
| int _papi_hwi_gather_all_thrspec_data | ( | int | tag, |
| PAPI_all_thr_spec_t * | where | ||
| ) |
< 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 );
}


| int _papi_hwi_init_global_threads | ( | void | ) |
< 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 );
}


| 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;
}


| 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;
}

| int _papi_hwi_shutdown_global_threads | ( | void | ) |
< 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;
}


| int _papi_hwi_shutdown_thread | ( | ThreadInfo_t * | thread | ) |
< 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;
}


| 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;
}


| 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;
}


| 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;
}

| 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
}


| 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 );
}


| 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;
}


| __thread ThreadInfo_t* _papi_hwi_my_thread |
| volatile ThreadInfo_t* _papi_hwi_thread_head |
| unsigned long( * _papi_hwi_thread_id_fn)(void) |