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
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 );
An instrumentation time object file that has been built
but not yet written. 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
An instrumentation time procedure pointer. The
name of an analysis routine that is to be called
just before a thread terminates. The name of an
analysis routine that is to be called just before a
fork(2) or vfork(2) system call. 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. Suggested
number of threads that the thread table typically
needs to accommodate. Number of bytes of
data that the thread table needs to allocate per
thread. Pointer to a thread table previously allocated
by calling ThreadTableInit(). Unique identification
number for a thread, as provided by
ThreadGetId(). 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. A pointer to any data that the tool needs to
pass to the iteration callback function "proc" in
its third argument. A pointer to any data that the
tool needs to get back from the iteration callback
function "proc" via its fourth argument. 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.
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. Any unsigned long variable.
Any unsigned long value.
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 [Toc] [Back]
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 [Toc] [Back]
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 perthread
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, SMPsafe,
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 [Toc] [Back] 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); }
A NULL pointer, the null thread id ThreadNoId, or a
nonzero ThreadStatus error code indicates failure (or true
for logical functions), as described above.
Header file containing external definitions of Atom
instrumentation routines Header file containing external
definitions of Atom analysis routines 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
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
Thread(5)
[ Back ] |