 |
Index for Section 5 |
|
 |
Alphabetical listing for T |
|
 |
Bottom of page |
|
Thread(5)
NAME
Thread, ThreadExcludeObj, ThreadExcludeProc, ThreadCreationObj,
ThreadCreationProc, ThreadTerminationObj, ThreadTerminationProc,
ThreadGetId, ThreadIsInternal, ThreadTableInit, ThreadTableLock,
ThreadTableUnlock, ThreadTableFree, ThreadLookup, ThreadUnlock,
ThreadRemove, ThreadForeach, ThreadMutexPoll, ThreadMutexLock,
ThreadMutexUnlock, ThreadAddr, ThreadLockedAdd - Atom services used to
develop Thread-safe analysis routines
SYNOPSIS
The following interfaces are defined for use by Atom instrumentation
routines:
#include <cmplrs/atom.inst.h>
int ThreadExcludeObj(
Obj *object,
unsigned long i_flags );
int ThreadExcludeProc(
Obj *object,
Proc *procedure,
unsigned long i_flags );
extern Obj *ThreadCreationObj(
void );
extern Proc *ThreadCreationProc(
void );
extern Obj *ThreadTerminationObj(
void );
extern Proc *ThreadTerminationProc(
void );
The following instrumentation routines are retained only for compatibility:
int ThreadExitCall(
Obj *object,
unsigned long i_flags,
const char *exit_routine_name );
int ThreadForkCall(
Obj *object,
unsigned long i_flags,
const char *pre_fork_routine_name,
const char *post_fork_routine_name );
The following interfaces are defined for use by Atom analysis routines:
#include <cmplrs/atom.anal.h>
ThreadId ThreadGetId(
void );
int ThreadIsInternal(
ThreadId id );
ThreadTable *ThreadTableInit(
unsigned long size_hint,
unsigned long info_size );
ThreadStatus ThreadTableLock(
ThreadTable *table,
ThreadId id );
void ThreadTableUnlock(
ThreadTable *table,
ThreadId id );
void ThreadTableFree(
ThreadTable *table );
void *ThreadLookup(
ThreadTable *table,
ThreadId id,
unsigned long a_flags );
ThreadStatus ThreadUnlock(
ThreadTable *table,
ThreadId id );
ThreadStatus ThreadRemove(
ThreadTable *table,
ThreadId id );
ThreadStatus ThreadForeach(
ThreadTable *table,
ThreadId id,
unsigned long a_flags,
void *data,
void *result,
void (*proc)(ThreadId,void *,void *,void *) );
void ThreadMutexPoll(
int microseconds );
ThreadStatus ThreadMutexLock(
ThreadMutex *mutex,
ThreadId id );
void ThreadMutexUnlock(
ThreadMutex *mutex );
ThreadMutex *ThreadAddr(
ThreadTable *table,
ThreadId id );
unsigned long ThreadLockedAdd(
unsigned long *counter,
unsigned long increment );
PARAMETERS
object
An instrumentation time object file that has been built but not yet
written.
i_flags
Options to control the instrumentation-time services. The same value
may be passed to all such routines that use it. The value is a
bitwise-OR (|) of the following:
THREAD_PTHREAD = application calls pthread_* routines
THREAD_FORK = application may fork
THREAD_FLOAT = analysis routines use floating-point
procedure
An instrumentation time procedure pointer.
exit_routine_name
The name of an analysis routine that is to be called just before a
thread terminates.
pre_fork_routine_name
The name of an analysis routine that is to be called just before a
fork(2) or vfork(2) system call.
post_fork_routine_name
The name of an analysis routine that is to be called just after a
fork(2) or vfork(2) system call; it will be called in both the parent
and the child process.
size_hint
Suggested number of threads that the thread table typically needs to
accommodate.
info_size
Number of bytes of data that the thread table needs to allocate per
thread.
table
Pointer to a thread table previously allocated by calling
ThreadTableInit().
id Unique identification number for a thread, as provided by
ThreadGetId().
a_flags
If a_flags has the value THREAD_LOCK, a mutex will be claimed, to
serialize access to the data for the current thread; ThreadUnlock must
be called to release the mutex after use.
data
A pointer to any data that the tool needs to pass to the iteration
callback function "proc" in its third argument.
result
A pointer to any data that the tool needs to get back from the
iteration callback function "proc" via its fourth argument.
proc
Procedure to be called for each thread that has data in the specified
thread table. It should return non-zero if the iteration must stop,
zero if it must continue.
mutex
A mutual-exclusion lock, which contains the value ThreadNoId if no
thread holds the lock, or which contains the identification number of
the thread that does hold it.
counter
Any unsigned long variable.
increment
Any unsigned long value.
DESCRIPTION
Atom's Thread* routines help you write thread-safe analysis routines, for
applications that use pthread_create and other POSIX thread services. See
FILES below for a working example of a tool that uses these APIs.
Instrumentation Services
The ThreadExcludeObj routine returns a non-zero value if the procedures of
the specified object can not be safely instrumented with calls to analysis
routines. If ThreadExcludeObj returns a non-zero value, the specified
object may only be instrumented via ThreadExitCall or ThreadForkCall.
The ThreadExcludeProc routine returns a non-zero value if the specified
procedure can not be safely instrumented, in much the same way that
ThreadExcludeObj excludes whole objects. This routine acts as a more
fine-grained filter for procedures in shared-libraries, and it takes over
from ThreadExcludeObj programs that were linked with archive libraries.
The ThreadCreationProc routine returns a pointer to a procedure that can be
instrumented with AddCallProc's ProcBefore option, to call an analysis
routine whenever a thread is created. The returned Proc* can be used only
if the procedure is defined in an object that has been built by
BuildObj(5); otherwise the returned Proc* is NULL. The ThreadCreationObj
routine returns a pointer to the object that needs to be built. This helps
a tool build only the objects it really needs to build. The
ThreadTerminateProc and ThreadTerminateObj routines are similar but for
calling an analysis routine when a thread terminates.
Run-Time Analysis Services
The analysis routines of an Atom tool can not call pthread_* routines,
because only one copy of the libpthread library can be in control of a
process. So, the Thread* routines provided by Atom's analysis-services
library provide routines that support mutexes without using libpthread.
Services for analyzing threads individually (for example, per-thread
profiles) are also provided by this Atom library.
The ThreadGetId routine returns the unique identification number for the
thread that is executing this code. The value ThreadNoId is returned if the
current thread is one of the internal threads of the pthread library.
The ThreadIsInternal routine returns a non-zero value if the given thread
id is that of a thread-management thread created within DECthreads. Such
threads are usually not profiled.
The ThreadTableInit routine allocates and initializes a table that records
info_size bytes of per-thread data on any number of threads. A pointer to
the data for a given thread is returned by calling ThreadLookup with the id
of the thread. The first time ThreadLookup is called for a thread, its data
is allocated and set to zero, unless the THREAD_EXISTING flags value is
specified to prevent allocation for that call. ThreadLookup may become
progressively less efficient as the number of threads known to the table
exceeds the size_hint specified when the table was allocated with
ThreadTableInit.
ThreadLookup claims a mutex if the THREAD_LOCK flags value is specified;
this is necessary when Atom analysis routines are profiling threads
individually, but not if the table is being used in a non-threaded program
(such as one that monitors threaded programs with the /proc file system).
ThreadUnlock must be called to release the mutex after the thread has
finished modifying its per-thread data. Note that the table may use one
mutex to serialize access to more than one thread; optimally, each thread's
data will have its own mutex, but this cannot be relied on.
The ThreadRemove routine breaks the connection between the thread id and
its data in the thread table, for example when a thread terminates.
THREAD_NO_DATA is returned if no data was found for the specified thread.
If other code uses the THREAD_LOCK flags value to lock the table's per-
thread data, then ThreadRemove must be called between calls to ThreadLookup
(with THREAD_LOCK specified) and ThreadUnlock.
The ThreadForeach routine calls the specified procedure for every thread
known to the table, in no particular order. The callback procedure must
return zero to continue the iteration, or non-zero to stop it.
The ThreadTableLock routine locks every current and future thread
associated with the table, or it locks none if any was already locked by
the calling thread. The ThreadTableUnlock routine unlocks every thread
known to the table, except for threads that are locked by the calling
thread. These routines can be used to safeguard mutexes when an
instrumented application calls fork().
The ThreadTableFree routine deallocates the memory used by the table. You
must ensure that no thread is currently using the table or will use it.
The ThreadMutexPoll routine sets the period for which ThreadMutexLock and
ThreadLookup will sleep, between attempts to claim a mutex. Periods of zero
to 999999 microseconds are supported. If a negative period is specified
(and by default), ThreadMutexLock adopts a repeating and varying schedule
of intervals from 1 to 512K microseconds.
The ThreadMutexLock routine claims the specified mutex lock, in particular
a mutex that is not within a ThreadTable. New, independent mutexes can
simply be defined with a static or initialized declaration. For example:
ThreadMutex global_mutex = ThreadNoId;
ThreadMutexLock repeatedly polls and waits (with usleep()) until the claim
is successful, when zero is returned. THREAD_NO_ID is returned if the
specified thread id is ThreadNoId, and THREAD_LOCKED is returned if the
specified thread already holds the mutex lock. A memory barrier instruction
is executed after the mutex is claimed, so the program delays until all
store instructions have completed, so the critical section will be safe in
a Symmetric Multi-Processor (SMP) system. The ThreadMutexLock routine is
too intrusive when the procedures in some system libraries are
instrumented, because it calls usleep; so, it should not be used in objects
for which ThreadExcludeObj returns a non-zero value or in procedures for
which ThreadExcludeProc returns a non-zero value. The pthread_mutex_lock(3)
routine and the pthread_mutex_t type mutexes it supports should not be used
in analysis routines; neither should any other pthread_* routines.
The ThreadMutexUnLock routine releases the specified mutex lock and
executes a memory barrier to end the critical section.
The ThreadAddr routine returns the address of the mutex that protects the
per-thread data for the specified thread id in the specified table.
The ThreadLockedAdd routine provides a thread-safe, SMP-safe, add
operation. It returns the value that the counter had before the addition.
By casting to and from signed types, signed (for example, negative) values
and subtraction can be achieved. It ensures that attempts to increment the
counter are serialized. When an Atom tool's analysis routine only needs to
increment one counter (or a set of counters that can be allowed to become
out of sync), use of this procedure lets you avoid the need for the more
complex, slower, and more intrusive mutex locks around critical sections.
For example, it can be used for simple analysis of objects that
ThreadExcludeObj identifies as unsafe for analysis with the other Thread*
services.
THREAD-SAFE REPLACEMENT ROUTINES
Creating thread-safe replacement routines may also require the disabling of
pthread cancellation points. If the replacement routine calls any routine
that is a pthread cancellation point, then disabling of pthread
cancellation is recommended to avoid deadlock. All I/O calls are potential
cancellation points.
Hooks have been provided in libpthread.so to allow this disabling. The
libpthread initialization routines __pthreadAtomInit must be instrumented
to allow the application addresses of __pthreadAtomDisable and
__pthreadAtomRestore to be set up before any pthread is created, but after
libpthread is loaded.
Xlates are used to get the run-time application address of these routine.
At the beginning of an analysis routine, __pthreadAtomDisable is executed
by means of a function pointer. At the end of the analysis routine,
__pthreadAtomRestore is also executed by means of a function pointer. This
ensures that no thread will be cancelled while in an analysis routine and
waiting for a resource.
Sample instrumentation code for disabling pthread cancellation:
Xlate * xlate;
PlaceType place = ProcBefore;
Obj * disable_obj;
Entry * disable_entry=0;
Obj * restore_obj;
Entry * restore_entry=0;
Obj * init_obj;
Proc * init_proc=0;
xlate = CreateXlate(obj,2);
init_obj = FindObj("__pthreadAtomInit");
if (init_obj && IsObjBuilt(init_obj))
init_proc = FindProc(init_obj, "__pthreadAtomInit");
disable_obj = FindObj("__pthreadAtomDisable");
if (disable_obj && IsObjBuilt(disable_obj))
disable_entry = FindEntry(disable_obj, "__pthreadAtomDisable");
if (disable_entry) {
restore_obj = FindObj("__pthreadAtomRestore");
if (restore_obj && IsObjBuilt(restore_obj))
restore_entry = FindEntry(restore_obj,"__pthreadAtomRestore");
}
AddXlateEntry(xlate, disable_entry);
AddXlateEntry(xlate, restore_entry);
AddCallProc(init_proc, place, "set_repl_cancel_addr", xlate);
Sample analysis code for initialization of pthread cancellation disabling
and restoration:
void set_repl_cancel_addr(XLATE *xlate)
{
unsigned long func_addr;
func_addr = XlateAddr(xlate, 0);
repl_disable = (long (*)(void))func_addr;
func_addr = XlateAddr(xlate,1);
repl_restore = (void (*)(long))func_addr;
}
Sample replacement routine that disables and restores pthread cancellation:
void repl_routine(void)
{
long state;
if (repl_disable)
state = (*repl_disable)();
/*
* do something here.
*/
if (repl_restore)
(*repl_restore)(state);
}
RETURN VALUES
A NULL pointer, the null thread id ThreadNoId, or a nonzero ThreadStatus
error code indicates failure (or true for logical functions), as described
above.
FILES
/usr/include/cmplrs/atom.inst.h
Header file containing external definitions of Atom instrumentation
routines
/usr/include/cmplrs/atom.anal.h
Header file containing external definitions of Atom analysis routines
/usr/lib/cmplrs/atom/examples/prof.*
Annotated example sources for a simple Atom tool that demonstrates a
use of Atom's Thread routines to support analysis of applications that
fork and handle signals in either a threaded or a non-threaded
environment
SEE ALSO
Commands: atom(1)
Functions: atom_application_instrumentation(5),
atom_application_navigation(5), atom_application_query(5),
atom_application_symbols(5), atom_description_file(5),
atom_instrumentation_routines(5), atom_object_management(5),
AnalHeapBase(5), Xlate(5)
Programmer's Guide
 |
Index for Section 5 |
|
 |
Alphabetical listing for T |
|
 |
Top of page |
|