Dynamic Probe Class Library Programming Guide

Chapter 8, Creating probes describes how to define a probe that can execute as part of
a target application process. The manor in which the probe is installed
and executed within one or more target application processes distinguishes the
probe as a particular probe type -- either a point probe, a phase probe,
or a one-shot probe.

point probes are installed at particular locations in the target
application code, and, when in an activated state, are triggered whenever
execution reaches that location in the code. See Installing and activating point probes for instructions on executing probes of this type.
For an overview of point probes, see What is a point probe?.

Phase probes are triggered by expiration of a timer and are executed
regardless of what code the target application is executing. See Executing phase probes for instructions on executing probes of this type.
For an overview of phase probes, see What is a phase probe?.

One-shot probes are executed immediately and regardless of what code the
target application is executing. See Executing one-shot probes for instructions on executing probes of this type.
For an overview of one-shot probes, see What is a one-shot probe?.

Point probes are probes installed at particular locations in the target
application code that, when in an activated state, are triggered whenever
execution reaches that location in the code. To install and activate a
point probe in one or more target application processes, the analysis tool
must:

A probe is a probe expression that may optionally call
functions. The first step in installing and activating a point probe is
to build the actual probe expression that will serve as the point
probe. See Chapter 8, Creating probes for detailed instructions on how to do this.

Instrumentation points (InstPoint objects) are locations within
a target application process where an analysis tool can install point
probes. Before the analysis tool can install a point probe in a target
application process, it must get a reference to the InstPoint
object where it wishes to place the probe. To get such a reference, the
analysis tool must navigate the target application's source structure by
means of source objects (SourceObj objects). Each
SourceObj object represents part of the source code structure
associated with the target application process, and a group of such objects
provide the hierarchical representation of the source code structure which the
analysis tool can navigate. For an overview of instrumentation points,
see What are instrumentation points?. For an overview of source objects, see What are source objects?.

To navigate an application's source structure to get an
instrumentation point, the analysis tool must:

Get a reference to a target application process (Process
object) associated with the source code structure to navigate. If the
analysis tool is instrumenting a serial application, then this is simply the
Process object that represents the target application. If
the analysis tool is instrumenting a parallel application, however, this would
be just one of the Process class objects managed by the
Application class object. Note that while this initial
source code navigation must be performed using a single Process
object, the analysis tool can later use member functions of the
Application class to install, activate, and remove the point probe
in all processes managed by the application (assuming these are like processes
compiled from the same source as in an SPMD application).

Get a reference to the top-level source object (called the "program
object") for the process. The analysis tool does this by calling the
Process::get_program_object function.

Navigate one level down into the source hierarchy to get a reference to
the source object representing the module where the analysis tool will install
the point probe.

Expand the target module source object so the analysis tool can navigate
further down into its source hierarchy.

Navigate one level further down into its source hierarchy to get a
reference to the source object that represents the function where the analysis
tool will install the point probe.

Navigate one level further down into the source hierarchy to get a
reference to the instrumentation point where the analysis tool will install
the point probe.

Note:

For reusable, general-purpose, analysis tools, it is helpful to provide the
end user with some way of searching the target application for functions that
match a user-supplied search string. The analysis tool can provide this
functionality using the SourceObj::bget_function_list
function, the SourceObj::get_function_list function,
and member functions of the FunctionList and FunctionId
classes. After learning the information that follows, refer to Chapter 15, Searching for, and listing, functions in the target application for information on providing a function-searching capability
to the analysis tool's end user.

If the analysis tool is instrumenting a serial application, it doesn't
need to perform this step, and you can skip ahead to Step 2b: Get program object. If the analysis tool is instrumenting a parallel
application, however, it must first get a reference to a single process
(Process object) that is managed by the Application
class object. This is because a source hierarchy is associated with a
particular process only. If multiple processes in the parallel
application were compiled from the same source code (such as a SPMD program),
the analysis tool can later use member functions of the Application
class to install, activate, and remove the point probe for all the
Process objects managed by the Application. To
navigate the source hierarchy, however, the analysis tool must identify a
single representative Process in the Application.
To do this, the analysis tool uses the
Application::get_process function. The following
line of code, for example, returns the first Process object in the
Application object app1.

Process p = app1.get_process(0);

For more information on the Application::get_process
function, refer to its UNIX man page, or its entry in the DPCL Class
Reference.

To navigate the source code structure associated with a particular process,
the analysis tool first needs to get a reference to the source object
(SourceObj object) that represents the top of the process source
hierarchy. This top level SourceObj object is called the
"program object" and is returned by the
Process::get_program_object function. The
following line of code stores the program object in a new SourceObj
object named myprog.

SourceObj myprog = P.get_program_object();

For more information on the
Application::get_program_object function, refer to its
UNIX man page, or its entry in the DPCL Class Reference.

Once the analysis tool has a reference to the program object, it needs to
navigate one level down into the source hierarchy to get a reference to the
SourceObj object that represents the module where the analysis tool
will install the point probe. To do this, the analysis tool can use the
SourceObj::child_count,
SourceObj::child, and
SourceObj::module_name functions

The SourceObj::child_count function returns the
number of child SourceObj objects associated with the
SourceObj object; in the case of a program object, these child
SourceObj objects represent the program modules. The
SourceObj::child function returns a specific child
SourceObj. Once it has a reference to the module level
SourceObj object, the analysis tool can use the
SourceObj::module_name function to identify the name of
the module.

This code example uses the SourceObj::child_count
function to initialize a for loop, and then, within the
for loop, uses the SourceObj::child and
SourceObj::module_name functions to identify the target
module. This sample code assumes a specialized analysis tool designed
for a particular program, and so the name of the target module is already
known. For a general-purpose analysis tool, where the target
application is not known at design time, these same functions could be used,
for example, to populate a scrolled list to show the module names.
Here's the specialized analysis tool example that identifies
hello.c as the target module.

Once the analysis tool identifies the target module source object, it must
expand it in order to navigate further down into the source hierarchy.
To do this, the analysis tool can use either the blocking function
SourceObj::bexpand, or the asynchronous function
SourceObj::expand.

Once the analysis tool has expanded the target module, it can navigate one
more level down into the source hierarchy to get a reference to the
SourceObj that represents the function where the analysis tool will
install the point probe. Once again, the analysis tool can navigate
down into the hierarchy using the
SourceObj::child_count and
SourceObj::child functions. The
SourceObj::child_count function returns the number of
child SourceObj objects associated with the SourceObj
object; in the case of a module source object, these child
SourceObj objects represent the module's functions. The
SourceObj::child function returns a specific child
SourceObj object. Once it has a reference to the function
level SourceObj object, the analysis tool can use the
SourceObj::get_demangled_name function (to identify the
demangled name of the function) or the
SourceObj::get_mangled_name function (to identify the
mangled name of the function).

This code example uses the SourceObj::child_count
function to initialize a for loop, and then, within the loop, uses
SourceObj::child and
SourceObj::get_demangled_name functions to identify the
target function. This sample code assumes a specialized analysis tool
designed for a particular program, and so the name of the target function is
already known. For a general purpose analysis tool, where the target
application is not known at design time, these same functions could be used,
for example, to populate a scrolled list to show the function names.
Here's the specialized example that identifies the module
hello as the target function.

For more information on the SourceObj::child_count,
SourceObj::child,
SourceObj::get_demangled_name, and
SourceObj::get_mangled_name functions, refer to their
UNIX man pages or their entries in the DPCL Class Reference.

Once the analysis tool identifies the target function source object, it can
identify the actual instrumentation point (InstPoint object) where
it will install the point probe. To do this, the analysis tool can use
the SourceObj::exclusive_point_count,
SourceObj::exclusive_point, and
InstPoint::get_type functions. The
SourceObj::exclusive_point_count function returns the
number of instrumentation points in the function, and the
SourceObj::exclusive_point function returns a specific
InstPoint object. The
InstPoint::get_type function enables the analysis tool
to determine whether the instrumentation point represents a function entry,
function exit, or function call site.

This code example uses the
SourceObj::exclusive_point_count function to initialize
a for loop, and then, within the for loop, uses the
SourceObj::exclusive_point and
InstPoint::get_type functions to identify the function
entry site.

Once the analysis tool has defined its probes (as described in Chapter 8, Creating probes) and identified an instrumentation point (as described in Step 2: Navigate application source structure to get instrumentation point), it can install the probe at the
instrumentation point. To do this on a single process basis, the
analysis tool can use the asynchronous function
Process::install_probe or its blocking equivalent
Process::binstall_probe. To do this on an
application-wide basis, the analysis tool can use the functions
Application::install_probe or
Application::binstall_probe. Note that all of
these functions accept an array of probes. This means that the analysis
tool can install multiple point probes using a single call.

For more information on the Process::install_probe,
Process::binstall_probe,
Application::install_probe, or
Application::binstall_probe, refer to their UNIX man
pages or their entries in the DPCL Class Reference

Once you have installed a point probe in one or more target application
processes, you must activate it so that it will execute as part of the target
application process whenever execution reaches its installed location in the
target application code. To do this on a single process basis, the
analysis tool can use the asynchronous function
Process::activate_probe or its blocking equivalent
Process::bactivate_probe. To do this on an
application-wide basis (for all Process objects managed by an
Application object), the analysis tool can use the function
Application::activate_probe or
Application::bactivate_probe. Note that all of
these functions accept an array of probe handles. This means that the
analysis tool can activate more than one point probe using a single
call.

For more information on the Process::activate_probe,
Process::bactivate_probe,
Application::activate_probe, or
Application::bactivate_probe functions, refer to their
UNIX man pages or their entries in the DPCL Class Reference.

Phase probes are probes that are executed periodically upon execution of a
timer, regardless of what part of the target application's code is
executing. The interval at which the probes are executed is measured in
CPU time (as opposed to wall-clock time), and is called the phase
period. The control mechanism for invoking phase probes at these
set CPU-time intervals is called a "phase". Represented by
instances of the Phase class, phases enable your analysis tool code
to specify the particular phase probe(s) to be invoked and the interval at
which their execution is triggered. Note that the DPCL system uses a
SIGPROF signal to activate a phase; target applications that themselves
use the SIGPROF signal cannot be instrumented with phases. For more
information on phase probes and phases, refer to What is a phase probe?.

To add a phase to one or more target application processes in order to have
it call its associated phase probes (probe module functions) at set CPU-time
intervals, the analysis tool:

Creates one or more probe modules containing the function(s) to be
triggered by the phase. A phase can, each time its interval expires,
call up to three probe module functions -- a phase begin function, a
phase data function, and a phase end function. In addition to these
probes module functions that are executed each time the phase is activated,
the analysis tool can also create:

an initialization function to be executed only when the phase is first
added to a target application process.

Up to three phase exit functions (the phase exit begin function, the phase
exit data function, and the phase exit end function) to be executed when the
phase is removed from the target application process. Upon phase
removal, the phase exit begin function will execute, followed by the phase
exit data function (which will execute once for each datum associated with the
phase), followed by the phase exit end function.

If using a data function, allocates and associates data with the
phase's data function. Each time the phase is triggered, the data
function executes once per datum that the analysis tool has previously
allocated and associated with the phase.

For each of the phase probes (probe module functions) to be used by the
phase, creates a probe expression that represents a reference to the desired
function. This not only includes the phase begin function, phase data
function, and phase end function, but also any initialization function or
phase exit functions.

Creates a Phase class object that defines the phase probe(s)
(probe module function(s)) to be executed by the phase, and the interval
between successive invocations of the phase.

Calls a function to add the phase to one or more target application
processes. If you want an initialization function to be executed when
the phase is first added to the target application process, you supply the
function that adds the phase with a probe expression that represents a
reference to the initialization function.

Calls a function that specifies up to three exit functions (begin, data,
and end) to be executed when the phase is removed from the target application
process. You supply this function with probe expressions representing
the desired phase exit functions.

If desired, modifies the phase period (the CPU-time interval at which the
installed phase is activated to execute its probes).

The first step in creating a phase structure to execute phase probes is to
create one or more probe modules that contain the functions to be triggered by
the phase. A phase can, each time its interval expires, call up to
three probe module functions -- a begin function, a data function, and an
end function. While the phase must, in order to be useful, call at
least one of these functions, any one of them is optional. At the very
least, an analysis tool will usually supply a data function.

Once the phase is activated, it will call the phase probe module functions
that have been associated with it. The first phase probe it calls is
the one identifying the begin function (provided one has been
specified). Typically, the begin function will perform any setup tasks
that may be required. When the begin function completes, the phase
calls the phase probe that identifies the data function (provided one has been
specified). The data function executes once per datum that the analysis
tool will have previously allocated and associated with this phase.
When the data function finishes executing for the last datum, the phase calls
the phase probe that identifies the end function (provided one has been
specified). Typically, the end function performs any clean up chores
that may be required.

In addition to these probes module functions that are executed each time
the phase is activated, the analysis tool can also create:

an initialization function to be executed only when the phase is first
added to a target application process.

Up to three phase exit functions (the phase exit begin function, the phase
exit data function, and the phase exit end function) to be executed when the
phase is removed from the target application process. These functions
will be executed when:

the analysis tool explicitly sends a request to have the phase removed
(using the Process::remove_phase,
Process::bremove_phase,
Application::remove_phase, or
Application::bremove_phase function).

the analysis tool disconnects from the target application process (using
the Process::disconnect,
Process::bdisconnect,
Application::disconnect, or
Application::bdisconnect function) without first
explicitly requesting to have the phase removed.

The target application process finishes executing while the indicated
phase is still active.

When the phase exit functions are triggered, the first phase probe it
calls is the one identifying the phase exit begin function (provided one has
been specified). Like the phase begin function, the phase exit begin
function will perform any setup tasks that may be required for the data and
end functions to follow. When the phase exit begin function completes,
the DPCL system executes the phase probe that identifies the phase exit data
function (provided one has been specified). The phase exit data
function, like the phase data function, executes once per datum that the
analysis tool will have previously allocated and associated with this
phase. When the phase exit data function finishes executing for the
last datum, the DPCL system calls the phase probe that identifies the phase
exit end function (provided one has been specified). Typically, the end
function performs any final clean up chores that may be required. Like
the phase functions, however, any of these phase exit functions is
optional.

The following example code shows a probe module that defines the phase
begin function, the phase data function, and the phase end function. It
also defines an initialization function to be executed when the phase is first
added to a target application process. In order to execute this
module's functions in one or more target application process, the module
will need to be compiled and then loaded into the target application
process. For more information on how to do this, refer to Creating and calling probe module functions.

When creating an instance of the Phase class (as described next
in Step 3: Create phase), the analysis tool must, for each phase probe (module
function) that the Phase will trigger, create a probe expression
that represents a reference to the function. In order to have loaded
the probe module into the target application process(es), the analysis tool
will have already created a ProbeModule class object to represent
the probe module. (For more information, see Creating and calling probe module functions.) To create a probe expression that represents a
reference to one of the probe module's functions, the analysis tool can
call the Probe_Module::get_reference function.
The analysis tool code provides this function with the index of the function
within the probe module. To determine the number of functions in the
module, the analysis tool can call the
ProbeModule::get_count function. To determine
the name of a particular function, the analysis tool can call the
ProbeModule::get_name function.

This following code example uses the
ProbeModule::get_count,
ProbeModule::get_name, and
ProbeModule::get_reference functions to create probe
expressions that represent references to all the probe module functions shown
in the example code in Step 1: Create probe module(s). The phase begin function (begin_func),
the phase data function (data_func) and the phase end function
(end_func) will all be used when instantiating the Phase class in
the next step. The initialization function (init_func) is
the one to be executed only when the phase is first added to a target
application process; the probe expression that represents a reference to
this function will be used as a function parameter to the
Process::add_phase,
Process::badd_phase,
Application::add_phase, or
Application::badd_phase. These functions are
described in Step 4: Add phase to the target application process(es).

A phase structure (Phase class object) defines the phase
probe(s) (probe module function(s)) to be executed and the interval between
successive invocations of these probes. The Phase class is
defined in the header file Phase.h. This following
example code creates a phase object that specifies the phase should be
activated every second of CPU time to execute the phase begin function
(begin_func), the phase data function (data_func) and
the phase end function (end_func).

Although the phase period (the CPU-time interval at which the phase is
activated to execute its probes) is initially set when the analysis tool
defines the phase, note that the analysis tool can later lengthen or shorted
this interval as desired. Refer to Step 7: Modify phase period for more information.

For more information on the Phase class and its constructors,
refer to the DPCL Class Reference.

Once the analysis tool has created the Phase object (as
described in Step 3: Create phase), it can add it to one or more target application
processes. To add a phase on a single process basis, the analysis tool
can use the asynchronous function Process::add_phase or
its blocking equivalent Process::badd_phase. To
add a phase on an application-wide basis (for all Process class
objects managed by an Application object), the analysis tool can
use the functions Application::add_phase or
Application::badd_phase. Optional parameters of
these four functions enable you to specify an initialization function to be
executed when the phase is added to a target application process, as well as a
data callback routine and callback tag for handling message data generated by
the initialization function. The following code example uses the
Process::badd_phase function to add the phase we
created in Step 3: Create phase to a single target application process. The
initialization function shown in the probe module in Step 1: Create probe module(s) will execute when the Phase is added to the
process. The probe expression init_func represents a
reference to the probe module function; we created this probe expression
in Step 5: Create probe expression(s) to allocate and associate data with the phase.

For more information on the Process::add_phase,
Process::badd_phase,
Application::add_phase, or
Application::badd_phase functions, refer to their UNIX
man pages or their entries in the DPCL Class Reference.

If using a phase data function, the analysis tool code will need to create
a probe expression to allocate and associate data with the phase. Each
time the phase is triggered, the data function executes once per datum that
the analysis tool has previously allocated and associated with the
phase. Executing once per datum enables the data function to perform
the same actions on the different data. Each datum, for example, could
be a separate counter -- each incremented by the same data
function. If the analysis tool does not associate any data with the
phase, then the data function will not execute.

Creating probe expressions to represent persistent data describes how you can use the
Process::alloc_mem,
Process::balloc_mem,
Application::alloc_mem, and
Application::balloc_mem to allocated memory in target
application processes. What this earlier section did not state,
however, is the an optional parameter of these functions enables the analysis
tool to associate the data allocated in the process(es) with a particular
phase. In this following example of the
Process::balloc_mem function, the probe expression
phase_da is created to represent a persistent integer variable with
the initial value of 1000. This probe expression also associates the
allocated data with the Phase object myphase created in Step 3: Create phase. Each time this phase is activated, this data value
will be passed to the phase data function data_func. Since
there is only this one datum associated with the phase, the phase data
function will execute only once each time the phase is activated.

For more information on the Process::alloc_mem,
Process::balloc_mem,
Application::alloc_mem, and
Application::balloc_mem functions, refer to their UNIX
man pages or their entries in the DPCL Class Reference.

If the analysis tool code created one or more phase exit functions in Step 1: Create probe module(s), it needs to associate them with the Phase on one
or more target application processes. To do this, the analysis tool
code calls the Process::set_phase_exit,
Process::bset_phase_exit,
Application::set_phase_exit, or
Application::bset_phase_exit function. The
analysis tool code must supply these functions with probe expressions that
represent references to the actual probe module functions. The analysis
tool code must, therefore, have already created probe expressions for the exit
functions as described in Step 5: Create probe expression(s) to allocate and associate data with the phase. The set_phase_exit and
bset_phase_exit functions also allow the analysis tool to specify a
callback routine and callback tag for each of the phase exit functions.
The following code uses the Process::bset_phase_exit
function call to associate a phase exit begin function, a phase exit data
function, and a phase exit end function with the Phase object
phase1 on one particular target application process. The
three phase exit functions are represented by the probe expressions
exit_begin_func, exit_data_func, and
exit_end_func previously created by calling the
ProbeModule::get_reference. The procedure for
creating a probe expression using the
ProbeModule::get_reference function is described in Step 5: Create probe expression(s) to allocate and associate data with the phase.

For more information on the Process::set_phase_exit,
Process::bset_phase_exit,
Application::set_phase_exit, or
Application::bset_phase_exit functions, refer to their
UNIX man pages or their entries in the DPCL Class Reference.

A phase period specifies the interval of CPU time at which
a phase is activated. When the phase is activated, it then executes its
phase probes (phase begin, phase data, and phase end functions). The
analysis tool initially sets the phase period when defining the
Phase class object as described in Step 3: Create phase. The analysis tool can also, once the
Phase class object has been added to one or more target application
processes, modify the phase period so that the phase is activated at longer or
shorter intervals of CPU time. The analysis tool can reset a phase
period within a single target application process by calling the
Process::set_phase_period function or its blocking
equivalent -- Process::bset_phase_period.
The analysis tool can also reset a phase period on an application-wide basis
(for each Process object managed by an Application
object) by calling the Application::set_phase_period or
Application::bset_phase_period function.

One use of the Process::set_phase_period,
Process::bset_phase_period,
Application::set_phase_period, and
Application::bset_phase_period functions is to control
when a phase will first execute. For example, say you do not want a
phase to be activated until after the analysis tool has allocated and
associated data with the phase. Unfortunately, you have to add the
phase to one or more processes (as described in Step 4: Add phase to the target application process(es)) before you can allocate data for it (as described in Step 5: Create probe expression(s) to allocate and associate data with the phase). In the example code below, the
analysis tool adds a phase whose phase period is 999.0 to a particular
process. The long phase period effectively places the phase in a
suspended state while the analysis tool allocates and associates data with the
phase. Once the data allocation step is complete, the analysis tool
calls the Process::set_phase_period function to set the
phase period to the intended CPU-time interval of 0.1 seconds

In addition to being able to set a phase period, the analysis tool can also
ascertain the value of a phase period by calling the
Process::get_phase_period function. For more
information on the Process::set_phase_period,
Process::bset_phase_period,
Application::set_phase_period,
Application::bset_phase_period, or
Process::get_phase_period functions, refer to their
UNIX man pages, or their entries in the DPCL Class Reference.

Creates probe expressions that reference functions in the probe
module.

Creates a phase using the probe expressions that represent probe module
functions. The phase period is initially set to a high number
(999.0) to effectively suspend activation of the phase until data has
been allocated for it.

Adds the phase to the target application process.

Allocates data variables for the phase.

Resets the phase period so that the phase is executed every 0.1
second of CPU time.

A one-shot probe is a type of probe that is executed by the DPCL system
immediately upon request, regardless of what the application happens to be
doing. To execute a one-shot probe in one or more target application
processes, the analysis tool must:

A probe is a probe expression that may optionally call
functions. The first step in executing a one-shot probe is to build the
actual probe expression that will serve as the one-shot probe. Since a
one-shot probe is executed immediately upon request, regardless of what the
target application happens to be doing, your probe expression should be
"signal safe".

Once the analysis tool has defined the probe expression that will serve as
the one-shot probe, it can execute it in one or more target application
processes. To execute a one-shot probe in a single process, the
analysis tool can use the asynchronous function
Process::execute or its blocking equivalent
Process::bexecute. To execute a one-shot probe
on an application-wide basis (for all Process objects managed by an
Application object), the analysis tool can use the function
Application::execute or
Application::bexecute.