|
Packit |
577717 |
/****************************/
|
|
Packit |
577717 |
/* THIS IS OPEN SOURCE CODE */
|
|
Packit |
577717 |
/****************************/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* File: threads.c
|
|
Packit |
577717 |
* Author: Philip Mucci
|
|
Packit |
577717 |
* mucci@cs.utk.edu
|
|
Packit |
577717 |
* Mods: Kevin London
|
|
Packit |
577717 |
* london@cs.utk.edu
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* This file contains thread allocation and bookkeeping functions */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include "papi.h"
|
|
Packit |
577717 |
#include "papi_internal.h"
|
|
Packit |
577717 |
#include "papi_vector.h"
|
|
Packit |
577717 |
#include "papi_memory.h"
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <unistd.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*****************/
|
|
Packit |
577717 |
/* BEGIN GLOBALS */
|
|
Packit |
577717 |
/*****************/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* The following globals get initialized and cleared by:
|
|
Packit |
577717 |
extern int _papi_hwi_init_global_threads(void);
|
|
Packit |
577717 |
extern int _papi_hwi_shutdown_thread(ThreadInfo_t *thread); */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* list of threads, gets initialized to master process with TID of getpid() */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
volatile ThreadInfo_t *_papi_hwi_thread_head;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* If we have TLS, this variable ALWAYS points to our thread descriptor. It's like magic! */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if defined(HAVE_THREAD_LOCAL_STORAGE)
|
|
Packit |
577717 |
THREAD_LOCAL_STORAGE_KEYWORD ThreadInfo_t *_papi_hwi_my_thread;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Function that returns and unsigned long thread identifier */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
unsigned long ( *_papi_hwi_thread_id_fn ) ( void );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Function that sends a signal to other threads */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef ANY_THREAD_GETS_SIGNAL
|
|
Packit |
577717 |
int ( *_papi_hwi_thread_kill_fn ) ( int, int );
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*****************/
|
|
Packit |
577717 |
/* END GLOBALS */
|
|
Packit |
577717 |
/*****************/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
lookup_and_set_thread_symbols( void )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
#if defined(ANY_THREAD_GETS_SIGNAL)
|
|
Packit |
577717 |
int retval;
|
|
Packit |
577717 |
char *error_ptc = NULL, *error_ptk = NULL;
|
|
Packit |
577717 |
void *symbol_ptc = NULL, *symbol_ptk = NULL, *handle = NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
handle = dlopen( NULL, RTLD_LAZY );
|
|
Packit |
577717 |
if ( handle == NULL ) {
|
|
Packit |
577717 |
PAPIERROR( "Error from dlopen(NULL, RTLD_LAZY): %d %s", errno,
|
|
Packit |
577717 |
dlerror( ) );
|
|
Packit |
577717 |
return ( PAPI_ESYS );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
symbol_ptc = dlsym( handle, "pthread_self" );
|
|
Packit |
577717 |
if ( symbol_ptc == NULL ) {
|
|
Packit |
577717 |
error_ptc = dlerror( );
|
|
Packit |
577717 |
THRDBG( "dlsym(%p,pthread_self) returned NULL: %s\n",
|
|
Packit |
577717 |
( error_ptc ? error_ptc : "No error, NULL symbol!" ) );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
symbol_ptk = dlsym( handle, "pthread_kill" );
|
|
Packit |
577717 |
if ( symbol_ptk == NULL ) {
|
|
Packit |
577717 |
error_ptk = dlerror( );
|
|
Packit |
577717 |
THRDBG( "dlsym(%p,pthread_kill) returned NULL: %s\n",
|
|
Packit |
577717 |
( error_ptk ? error_ptk : "No error, NULL symbol!" ) );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
dlclose( handle );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( !( ( _papi_hwi_thread_kill_fn && _papi_hwi_thread_id_fn ) ||
|
|
Packit |
577717 |
( !_papi_hwi_thread_kill_fn && !_papi_hwi_thread_id_fn ) ) )
|
|
Packit |
577717 |
return ( PAPI_EMISC );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_thread_kill_fn = ( int ( * )( int, int ) ) symbol_ptk;
|
|
Packit |
577717 |
_papi_hwi_thread_id_fn = ( unsigned long ( * )( void ) ) symbol_ptc;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
return ( PAPI_OK );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static ThreadInfo_t *
|
|
Packit |
577717 |
allocate_thread( int tid )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
ThreadInfo_t *thread;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* The Thread EventSet is special. It is not in the EventSet list, but is pointed
|
|
Packit |
577717 |
to by each EventSet of that particular thread. */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
thread = ( ThreadInfo_t * ) papi_malloc( sizeof ( ThreadInfo_t ) );
|
|
Packit |
577717 |
if ( thread == NULL )
|
|
Packit |
577717 |
return ( NULL );
|
|
Packit |
577717 |
memset( thread, 0x00, sizeof ( ThreadInfo_t ) );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
thread->context =
|
|
Packit |
577717 |
( hwd_context_t ** ) papi_malloc( sizeof ( hwd_context_t * ) *
|
|
Packit |
577717 |
( size_t ) papi_num_components );
|
|
Packit |
577717 |
if ( !thread->context ) {
|
|
Packit |
577717 |
papi_free( thread );
|
|
Packit |
577717 |
return ( NULL );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
thread->running_eventset =
|
|
Packit |
577717 |
( EventSetInfo_t ** ) papi_malloc( sizeof ( EventSetInfo_t * ) *
|
|
Packit |
577717 |
( size_t ) papi_num_components );
|
|
Packit |
577717 |
if ( !thread->running_eventset ) {
|
|
Packit |
577717 |
papi_free( thread->context );
|
|
Packit |
577717 |
papi_free( thread );
|
|
Packit |
577717 |
return ( NULL );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( i = 0; i < papi_num_components; i++ ) {
|
|
Packit |
577717 |
thread->context[i] =
|
|
Packit |
577717 |
( void * ) papi_malloc( ( size_t ) _papi_hwd[i]->size.context );
|
|
Packit |
577717 |
thread->running_eventset[i] = NULL;
|
|
Packit |
577717 |
if ( thread->context[i] == NULL ) {
|
|
Packit |
577717 |
for ( i--; i >= 0; i-- )
|
|
Packit |
577717 |
papi_free( thread->context[i] );
|
|
Packit |
577717 |
papi_free( thread->context );
|
|
Packit |
577717 |
papi_free( thread );
|
|
Packit |
577717 |
return ( NULL );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
memset( thread->context[i], 0x00,
|
|
Packit |
577717 |
( size_t ) _papi_hwd[i]->size.context );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( _papi_hwi_thread_id_fn ) {
|
|
Packit |
577717 |
thread->tid = ( *_papi_hwi_thread_id_fn ) ( );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
else {
|
|
Packit |
577717 |
thread->tid = ( unsigned long ) getpid( );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
thread->allocator_tid=thread->tid;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (tid == 0 ) {
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
else {
|
|
Packit |
577717 |
thread->tid=tid;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
THRDBG( "Allocated thread %ld at %p, allocator: %ld\n", thread->tid,
|
|
Packit |
577717 |
thread,
|
|
Packit |
577717 |
thread->allocator_tid );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return thread;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
free_thread( ThreadInfo_t ** thread )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
THRDBG( "Freeing thread %ld at %p\n", ( *thread )->tid, *thread );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( i = 0; i < papi_num_components; i++ ) {
|
|
Packit |
577717 |
if ( ( *thread )->context[i] )
|
|
Packit |
577717 |
papi_free( ( *thread )->context[i] );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( ( *thread )->context )
|
|
Packit |
577717 |
papi_free( ( *thread )->context );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( ( *thread )->running_eventset )
|
|
Packit |
577717 |
papi_free( ( *thread )->running_eventset );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset( *thread, 0x00, sizeof ( ThreadInfo_t ) );
|
|
Packit |
577717 |
papi_free( *thread );
|
|
Packit |
577717 |
*thread = NULL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
insert_thread( ThreadInfo_t * entry, int tid )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
_papi_hwi_lock( THREADS_LOCK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( _papi_hwi_thread_head == NULL ) { /* 0 elements */
|
|
Packit |
577717 |
THRDBG( "_papi_hwi_thread_head is NULL\n" );
|
|
Packit |
577717 |
entry->next = entry;
|
|
Packit |
577717 |
} else if ( _papi_hwi_thread_head->next == _papi_hwi_thread_head ) { /* 1 elements */
|
|
Packit |
577717 |
THRDBG( "_papi_hwi_thread_head was thread %ld at %p\n",
|
|
Packit |
577717 |
_papi_hwi_thread_head->tid, _papi_hwi_thread_head );
|
|
Packit |
577717 |
_papi_hwi_thread_head->next = entry;
|
|
Packit |
577717 |
entry->next = ( ThreadInfo_t * ) _papi_hwi_thread_head;
|
|
Packit |
577717 |
} else { /* 2+ elements */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
THRDBG( "_papi_hwi_thread_head was thread %ld at %p\n",
|
|
Packit |
577717 |
_papi_hwi_thread_head->tid, _papi_hwi_thread_head );
|
|
Packit |
577717 |
entry->next = _papi_hwi_thread_head->next;
|
|
Packit |
577717 |
_papi_hwi_thread_head->next = entry;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_thread_head = entry;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
THRDBG( "_papi_hwi_thread_head now thread %ld at %p\n",
|
|
Packit |
577717 |
_papi_hwi_thread_head->tid, _papi_hwi_thread_head );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_unlock( THREADS_LOCK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if defined(HAVE_THREAD_LOCAL_STORAGE)
|
|
Packit |
577717 |
/* Don't set the current local thread if we are a fake attach thread */
|
|
Packit |
577717 |
if (tid==0) {
|
|
Packit |
577717 |
_papi_hwi_my_thread = entry;
|
|
Packit |
577717 |
THRDBG( "TLS for thread %ld is now %p\n", entry->tid,
|
|
Packit |
577717 |
_papi_hwi_my_thread );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
( void ) tid;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
remove_thread( ThreadInfo_t * entry )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
ThreadInfo_t *tmp = NULL, *prev = NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_lock( THREADS_LOCK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
THRDBG( "_papi_hwi_thread_head was thread %ld at %p\n",
|
|
Packit |
577717 |
_papi_hwi_thread_head->tid, _papi_hwi_thread_head );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Find the preceding element and the matched element,
|
|
Packit |
577717 |
short circuit if we've seen the head twice */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( tmp = ( ThreadInfo_t * ) _papi_hwi_thread_head;
|
|
Packit |
577717 |
( entry != tmp ) || ( prev == NULL ); tmp = tmp->next ) {
|
|
Packit |
577717 |
prev = tmp;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( tmp != entry ) {
|
|
Packit |
577717 |
THRDBG( "Thread %ld at %p was not found in the thread list!\n",
|
|
Packit |
577717 |
entry->tid, entry );
|
|
Packit |
577717 |
return ( PAPI_EBUG );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Only 1 element in list */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( prev == tmp ) {
|
|
Packit |
577717 |
_papi_hwi_thread_head = NULL;
|
|
Packit |
577717 |
tmp->next = NULL;
|
|
Packit |
577717 |
THRDBG( "_papi_hwi_thread_head now NULL\n" );
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
prev->next = tmp->next;
|
|
Packit |
577717 |
/* If we're removing the head, better advance it! */
|
|
Packit |
577717 |
if ( _papi_hwi_thread_head == tmp ) {
|
|
Packit |
577717 |
_papi_hwi_thread_head = tmp->next;
|
|
Packit |
577717 |
THRDBG( "_papi_hwi_thread_head now thread %ld at %p\n",
|
|
Packit |
577717 |
_papi_hwi_thread_head->tid, _papi_hwi_thread_head );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
THRDBG( "Removed thread %p from list\n", tmp );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_unlock( THREADS_LOCK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if defined(HAVE_THREAD_LOCAL_STORAGE)
|
|
Packit |
577717 |
_papi_hwi_my_thread = NULL;
|
|
Packit |
577717 |
THRDBG( "TLS for thread %ld is now %p\n", entry->tid,
|
|
Packit |
577717 |
_papi_hwi_my_thread );
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
_papi_hwi_initialize_thread( ThreadInfo_t ** dest, int tid )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int retval;
|
|
Packit |
577717 |
ThreadInfo_t *thread;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( ( thread = allocate_thread( tid ) ) == NULL ) {
|
|
Packit |
577717 |
*dest = NULL;
|
|
Packit |
577717 |
return PAPI_ENOMEM;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Call the component to fill in anything special. */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( i = 0; i < papi_num_components; i++ ) {
|
|
Packit |
577717 |
if (_papi_hwd[i]->cmp_info.disabled) continue;
|
|
Packit |
577717 |
retval = _papi_hwd[i]->init_thread( thread->context[i] );
|
|
Packit |
577717 |
if ( retval ) {
|
|
Packit |
577717 |
free_thread( &thread );
|
|
Packit |
577717 |
*dest = NULL;
|
|
Packit |
577717 |
return retval;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
insert_thread( thread, tid );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*dest = thread;
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if defined(ANY_THREAD_GETS_SIGNAL)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* This is ONLY defined for systems that enable ANY_THREAD_GETS_SIGNAL
|
|
Packit |
577717 |
since we must forward signals sent to non-PAPI threads.
|
|
Packit |
577717 |
|
|
Packit |
577717 |
This is NOT compatible with thread local storage, since to broadcast
|
|
Packit |
577717 |
the signal, we need a list of threads. */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
_papi_hwi_broadcast_signal( unsigned int mytid )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i, retval, didsomething = 0;
|
|
Packit |
577717 |
volatile ThreadInfo_t *foo = NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_lock( THREADS_LOCK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( foo = _papi_hwi_thread_head; foo != NULL; foo = foo->next ) {
|
|
Packit |
577717 |
/* xxxx Should this be hardcoded to index 0 or walk the list or what? */
|
|
Packit |
577717 |
for ( i = 0; i < papi_num_components; i++ ) {
|
|
Packit |
577717 |
if ( ( foo->tid != mytid ) && ( foo->running_eventset[i] ) &&
|
|
Packit |
577717 |
( foo->running_eventset[i]->
|
|
Packit |
577717 |
state & ( PAPI_OVERFLOWING | PAPI_MULTIPLEXING ) ) ) {
|
|
Packit |
577717 |
/* xxxx mpx_info inside _papi_mdi_t _papi_hwi_system_info is commented out.
|
|
Packit |
577717 |
See papi_internal.h for details. The multiplex_timer_sig value is now part of that structure */
|
|
Packit |
577717 |
THRDBG("Thread %ld sending signal %d to thread %ld\n",mytid,foo->tid,
|
|
Packit |
577717 |
(foo->running_eventset[i]->state & PAPI_OVERFLOWING ? _papi_hwd[i]->cmp_info.hardware_intr_sig : _papi_os_info.itimer_sig));
|
|
Packit |
577717 |
retval = (*_papi_hwi_thread_kill_fn)(foo->tid,
|
|
Packit |
577717 |
(foo->running_eventset[i]->state & PAPI_OVERFLOWING ? _papi_hwd[i]->cmp_info.hardware_intr_sig : _papi_os_info.itimer_sig));
|
|
Packit |
577717 |
if (retval != 0)
|
|
Packit |
577717 |
return(PAPI_EMISC);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if ( foo->next == _papi_hwi_thread_head )
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
_papi_hwi_unlock( THREADS_LOCK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ( PAPI_OK );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* This is undefined for systems that enable ANY_THREAD_GETS_SIGNAL
|
|
Packit |
577717 |
since we always must enable threads for safety. */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
_papi_hwi_set_thread_id_fn( unsigned long ( *id_fn ) ( void ) )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
#if !defined(ANY_THREAD_GETS_SIGNAL)
|
|
Packit |
577717 |
/* Check for multiple threads still in the list, if so, we can't change it */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( _papi_hwi_thread_head->next != _papi_hwi_thread_head )
|
|
Packit |
577717 |
return ( PAPI_EINVAL );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* We can't change the thread id function from one to another,
|
|
Packit |
577717 |
only NULL to non-NULL and vice versa. */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( ( id_fn != NULL ) && ( _papi_hwi_thread_id_fn != NULL ) )
|
|
Packit |
577717 |
return ( PAPI_EINVAL );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_thread_id_fn = id_fn;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
THRDBG( "Set new thread id function to %p\n", id_fn );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( id_fn )
|
|
Packit |
577717 |
_papi_hwi_thread_head->tid = ( *_papi_hwi_thread_id_fn ) ( );
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
_papi_hwi_thread_head->tid = ( unsigned long ) getpid( );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
THRDBG( "New master tid is %ld\n", _papi_hwi_thread_head->tid );
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
THRDBG( "Skipping set of thread id function\n" );
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int _papi_hwi_thread_free_eventsets(long tid) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
EventSetInfo_t *ESI;
|
|
Packit |
577717 |
ThreadInfo_t *master;
|
|
Packit |
577717 |
DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
master = _papi_hwi_lookup_thread( tid );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_lock( INTERNAL_LOCK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for( i = 0; i < map->totalSlots; i++ ) {
|
|
Packit |
577717 |
ESI = map->dataSlotArray[i];
|
|
Packit |
577717 |
if ( ( ESI ) && (ESI->master!=NULL) ) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( ESI->master == master ) {
|
|
Packit |
577717 |
THRDBG("Attempting to remove %d from tid %ld\n",ESI->EventSetIndex,tid);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Code copied from _papi_hwi_remove_EventSet(ESI); */
|
|
Packit |
577717 |
_papi_hwi_free_EventSet( ESI );
|
|
Packit |
577717 |
map->dataSlotArray[i] = NULL;
|
|
Packit |
577717 |
map->availSlots++;
|
|
Packit |
577717 |
map->fullSlots--;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_unlock( INTERNAL_LOCK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
_papi_hwi_shutdown_thread( ThreadInfo_t * thread, int force_shutdown )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int retval = PAPI_OK;
|
|
Packit |
577717 |
unsigned long tid;
|
|
Packit |
577717 |
int i, failure = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( _papi_hwi_thread_id_fn )
|
|
Packit |
577717 |
tid = ( *_papi_hwi_thread_id_fn ) ( );
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
tid = ( unsigned long ) getpid( );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
THRDBG("Want to shutdown thread %ld, alloc %ld, our_tid: %ld\n",
|
|
Packit |
577717 |
thread->tid,
|
|
Packit |
577717 |
thread->allocator_tid,
|
|
Packit |
577717 |
tid);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((thread->tid==tid) || ( thread->allocator_tid == tid ) || force_shutdown) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_thread_free_eventsets(tid);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
remove_thread( thread );
|
|
Packit |
577717 |
THRDBG( "Shutting down thread %ld at %p\n", thread->tid, thread );
|
|
Packit |
577717 |
for( i = 0; i < papi_num_components; i++ ) {
|
|
Packit |
577717 |
if (_papi_hwd[i]->cmp_info.disabled) continue;
|
|
Packit |
577717 |
retval = _papi_hwd[i]->shutdown_thread( thread->context[i]);
|
|
Packit |
577717 |
if ( retval != PAPI_OK ) failure = retval;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
free_thread( &thread );
|
|
Packit |
577717 |
return ( failure );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
THRDBG( "Skipping shutdown thread %ld at %p, thread %ld not allocator!\n",
|
|
Packit |
577717 |
thread->tid, thread, tid );
|
|
Packit |
577717 |
return PAPI_EBUG;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* THESE MUST BE CALLED WITH A GLOBAL LOCK */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
_papi_hwi_shutdown_global_threads( void )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int err,num_threads,i;
|
|
Packit |
577717 |
ThreadInfo_t *tmp,*next;
|
|
Packit |
577717 |
unsigned long our_tid;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
tmp = _papi_hwi_lookup_thread( 0 );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( tmp == NULL ) {
|
|
Packit |
577717 |
THRDBG( "Did not find my thread for shutdown!\n" );
|
|
Packit |
577717 |
err = PAPI_EBUG;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
else {
|
|
Packit |
577717 |
our_tid=tmp->tid;
|
|
Packit |
577717 |
(void)our_tid;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
THRDBG("Shutting down %ld\n",our_tid);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
err = _papi_hwi_shutdown_thread( tmp, 1 );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* count threads */
|
|
Packit |
577717 |
tmp = ( ThreadInfo_t * ) _papi_hwi_thread_head;
|
|
Packit |
577717 |
num_threads=0;
|
|
Packit |
577717 |
while(tmp!=NULL) {
|
|
Packit |
577717 |
num_threads++;
|
|
Packit |
577717 |
if (tmp->next==_papi_hwi_thread_head) break;
|
|
Packit |
577717 |
tmp=tmp->next;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Shut down all threads allocated by this thread */
|
|
Packit |
577717 |
/* Urgh it's a circular list where we removed in the loop */
|
|
Packit |
577717 |
/* so the only sane way to do it is get a count in advance */
|
|
Packit |
577717 |
tmp = ( ThreadInfo_t * ) _papi_hwi_thread_head;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0;i
|
|
Packit |
577717 |
|
|
Packit |
577717 |
next=tmp->next;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
THRDBG("looking at #%d %ld our_tid: %ld alloc_tid: %ld\n",
|
|
Packit |
577717 |
i,tmp->tid,our_tid,tmp->allocator_tid);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
THRDBG("Also removing thread %ld\n",tmp->tid);
|
|
Packit |
577717 |
err = _papi_hwi_shutdown_thread( tmp, 1 );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
tmp=next;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef DEBUG
|
|
Packit |
577717 |
if ( ISLEVEL( DEBUG_THREADS ) ) {
|
|
Packit |
577717 |
if ( _papi_hwi_thread_head ) {
|
|
Packit |
577717 |
THRDBG( "Thread head %p still exists!\n", _papi_hwi_thread_head );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if defined(HAVE_THREAD_LOCAL_STORAGE)
|
|
Packit |
577717 |
_papi_hwi_my_thread = NULL;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
_papi_hwi_thread_head = NULL;
|
|
Packit |
577717 |
_papi_hwi_thread_id_fn = NULL;
|
|
Packit |
577717 |
#if defined(ANY_THREAD_GETS_SIGNAL)
|
|
Packit |
577717 |
_papi_hwi_thread_kill_fn = NULL;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return err;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
_papi_hwi_init_global_threads( void )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int retval;
|
|
Packit |
577717 |
ThreadInfo_t *tmp;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_lock( GLOBAL_LOCK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if defined(HAVE_THREAD_LOCAL_STORAGE)
|
|
Packit |
577717 |
_papi_hwi_my_thread = NULL;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
_papi_hwi_thread_head = NULL;
|
|
Packit |
577717 |
_papi_hwi_thread_id_fn = NULL;
|
|
Packit |
577717 |
#if defined(ANY_THREAD_GETS_SIGNAL)
|
|
Packit |
577717 |
_papi_hwi_thread_kill_fn = NULL;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
retval = _papi_hwi_initialize_thread( &tmp , 0);
|
|
Packit |
577717 |
if ( retval == PAPI_OK ) {
|
|
Packit |
577717 |
retval = lookup_and_set_thread_symbols( );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_unlock( GLOBAL_LOCK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ( retval );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
_papi_hwi_gather_all_thrspec_data( int tag, PAPI_all_thr_spec_t * where )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int didsomething = 0;
|
|
Packit |
577717 |
ThreadInfo_t *foo = NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
_papi_hwi_lock( THREADS_LOCK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( foo = ( ThreadInfo_t * ) _papi_hwi_thread_head; foo != NULL;
|
|
Packit |
577717 |
foo = foo->next ) {
|
|
Packit |
577717 |
/* If we want thread ID's */
|
|
Packit |
577717 |
if ( where->id )
|
|
Packit |
577717 |
memcpy( &where->id[didsomething], &foo->tid,
|
|
Packit |
577717 |
sizeof ( where->id[didsomething] ) );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* If we want data pointers */
|
|
Packit |
577717 |
if ( where->data )
|
|
Packit |
577717 |
where->data[didsomething] = foo->thread_storage[tag];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
didsomething++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( ( where->id ) || ( where->data ) ) {
|
|
Packit |
577717 |
if ( didsomething >= where->num )
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( foo->next == _papi_hwi_thread_head )
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
where->num = didsomething;
|
|
Packit |
577717 |
_papi_hwi_unlock( THREADS_LOCK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ( PAPI_OK );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|