The following information is a summary of each of the DPCL classes that your analysis tool can use to instrument a target application. Before reading this information, you should first understand the concepts introduced in Chapter 1, What is DPCL? (which provides a high-level description of the DPCL system and shows how its various parts work together to enable analysis tools to instrument one or more target application processes). The following DPCL class summary builds on this earlier description of the DPCL system by describing the DPCL classes that represent the elements of the DPCL system (target application processes, probes, instrumentation points, and so on). In doing so, it provides an overview of the purpose of each class, along with information on its supporting data types and functions. For complete reference information on any of the classes, data types, and functions summarized here, refer to DPCL's UNIX man pages or the DPCL Class Reference.
The following summary of the DPCL classes and functions is divided into the following sections:
This section describes the three classes that an analysis tool can use to represent, and act upon, the target application process(es). These are the Process class (described in What is the Process class? and used to represent a single UNIX process), the Application class (described in What is the Application class? and used to represent a group of related UNIX processes), and the PoeAppl class (described in What is the PoeAppl class?, this class is derived from the Application class, and used to represent POE applications).
The Process class (defined in the header file Process.h) is the most fundamental of all the DPCL classes. Instances of this class represent a single target application process. The analysis tool can use objects of this class to connect to an existing target application process, or create a new process. First, the analysis tool creates an instance of the Process class. Depending on the constructor used, the Process object may, or may not, have values that identify a particular UNIX process by host name and process ID.
Once connected to the process, member functions of this class enable the analysis tool to:
For additional process control, an analysis tool can also attach to the process. By attaching to the process, the analysis tool can control its execution. Specifically, once attached to the process, the analysis tool can call member functions of the Process class to:
In order to manipulate processes, you must understand the concept of process connect states. A Process object's connect state reflects the relationship between the Process class object in the analysis tool and the actual UNIX process it represents. The various Process connect states are enumerated in the ConnectState type; the Process::query_state function returns one of the enumeration constants of the ConnectState type to indicate the Process object's connect state.
A Process object's connect state reflects what actions can be performed on the actual UNIX process through DPCL function calls. For example, your analysis tool cannot execute probes within a target application process unless the analysis tool is "connected" or "attached" to that process. The "connected" state is represented by the enumeration constant PRC_connected of the ConnectState enumeration type, and the "attached" state is represented by the constant PRC_attached. When the analysis tool calls certain functions to act upon a process, the DPCL system checks the Process object's connect state to determine if the action is allowed. If it is not allowed, the operation fails.
Certain member functions of the Process class serve to move the Process object from one state to another. For example, the analysis tool can establish a communication connection to a UNIX process by calling the Process::connect function, or its blocking equivalent Process::bconnect. In addition to establishing the communication connection that allows the analysis tool to install probes into the target application process, these functions also move the Process object's connect state from PRC_unconnected to PRC_connected.
As already mentioned, the analysis tool can query a Process object's connect state by calling the Process::query_state function. This enables the analysis tool to check a process' state before making a DPCL service request that may not be allowed.
Figure 7. Process connect state diagram
View figure. |
The preceding figure illustrates the various process connect states and shows the enumeration constants of the ConnectState enumeration type. It also shows the constructors, operations, and functions that place a Process object into a particular connect state. For additional explanation of this figure, refer to the following key:
Table 3 summarizes the various functions of the Process class. Since many of the actions carried out by the functions can occur on remote hosts, note that blocking and nonblocking versions of the same functionality are usually provided. As described in What are blocking and nonblocking API calls?, blocking calls do not return control to the analysis tool until they either succeed or fail in carrying out the requisite service, while the nonblocking calls return immediately, enabling the analysis tool to continue with other work. Since the nonblocking calls return immediately, however, that returned status indicates only whether or not the request was successfully made; it does not indicate whether or not the request succeeded. For this reason, when calling a nonblocking function, the analysis tool can specify an acknowledgment callback routine. Once the operation succeeds or fails, the DPCL system will trigger execution of this callback routine and pass it the status information in the form of an AisStatus object (described in What is the AisStatus class?). An acknowledgment callback not only enables the analysis tool to perform status error checking, but also enables the analysis tool to be structured in a more event-driven manner. For example, the acknowledgment callback for the Process::connect function could check that the operation succeeded, and then could call the Process::attach function to attach to the process. Similarly, the acknowledgment callback for the Process::attach function could contain code for the next piece of work. While the nonblocking calls enable you to structure your analysis tool program in this sort of event driven manner, the blocking calls enable you to structure your analysis tool program in a more traditional way that is more straightforward and, therefore, easier to code.
For complete information on any of the functions summarized in this table,
refer to the function's UNIX man page or the DPCL Class
Reference.
Table 3. Process class function summary
The Application class (defined in the header file Application.h) is a grouping of related Process class objects. By grouping a number of Process objects under an Application object, the analysis tool is able to manipulate a set of related UNIX processes (represented by the Process objects) as a single unit. For example, say the target application is a parallel program that follows the Single Program Multiple Data (SPMD) model. To connect to its processes, your analysis tool could make a separate call to the Process::connect or Process::bconnect function for each process. A more convenient approach, however, is to group the Process objects under an Application object; the analysis tool can then connect to all the processes managed by the Application object by making a single call to the Application::connect or Application::bconnect function. The Application class function makes the individual service requests for each process managed by the Application object. The analysis tool uses the Application::add_process function to group processes under the Application object.
Figure 8. Process objects grouped under an Application object. In this figure, six Process objects are grouped under an Application object. Here, the analysis tool is trying to connect to the UNIX processes represented by the Process objects. It can do this either by making a separate Process::connect or Process::bconnect call for each process, or by making a single call to Application::connect or Application::bconnect.
View figure. |
It is important to understand that an Application object can be any grouping of Process objects, and not necessarily all the processes in a parallel application. It may, for example, be only a subset of the parallel application's processes, or, in fact, any set of UNIX processes. What's more, a single Process object may be grouped under several different Application objects. For example, say you have a parallel program that follows the Multiple Program Multiple Data (MPMD) model and solves a particular problem using functional parallelism. In this case, let's say that three separate programs were created to perform specific work; at run time, multiple processes for each executable program will run. For certain actions, it will be convenient to have a single Application object that manages all of the target application processes. This would enable the analysis tool to, using a single function call, perform certain actions on all processes (such as connecting to, suspending, resuming, terminating, or disconnecting from the processes). On the other hand, because the analysis tool is dealing with a target application composed from multiple programs, there are certain actions that it should not perform globally on all processes. It would not, for example, make sense to install a point probe in all the processes globally because a valid instrumentation point for some processes would not be valid for others. In this case, your analysis tool might organize the processes under four separate Application objects. One Application object could contain all the Process objects and be used by global operations. Each of the other three Application objects could contain just the Process objects associated with one of the three source programs. Figure 9 illustrates this situation; to simplify the figure, only six processes are illustrated.
Figure 9. Process objects grouped under multiple Application objects. In this figure, the Process objects are grouped under four separate Application objects. This enables the analysis tool to call an Application class function to manipulate all, or only a select subset, of the target application processes.
View figure. |
By comparing Table 3 and Table 4, you can clearly see that most of the Process class functions have equivalent functions in the Application class. The difference between a Process and an Application version of a function is that the Application class version of the function carries out the request for all of the processes managed by the Application object. Therefore, member functions of the Application class enable the analysis tool to:
Additional functions of the Application class enable the analysis tool to:
Table 4 summarizes the various functions of the Application class. Since many of the actions carried out by these functions can occur on remote hosts, note that, as in the Process class, blocking and nonblocking versions of the same functionality is usually provided. Also note that the majority of the Application class functions carry out some service request for all of the Process objects managed by the Application object, and the action requested may succeed on certain processes while failing on others. This adds additional complexity to error status checking. Specifically:
The AisStatus object is described in What is the AisStatus class?. Error checking considerations for Application functions are described in Chapter 4, Performing status error checking.
For more information on the Process object connect state
information shown in this table, refer to Figure 7. For complete information on any of the functions
summarized in this table, refer to the function's UNIX man page or the
DPCL Class
Reference.
Table 4. Application class function summary
The PoeAppl class (defined in the header file PoeAppl.h) is derived from the Application class; its purpose is to provide additional convenience functions for connecting to or starting a job in the Parallel Operation Environment (POE). POE (which is fully described in the manual IBM Parallel Environment for AIX: Operation and Use, Volume 1) is an execution environment designed to hide, or at least smooth, the differences between serial and parallel execution. In POE, you execute a program from a "home node" (which can be any workstation on the LAN), and POE will, sometimes in conjunction with IBM LoadLeveler, allocate host machines on which the various processes of your POE job will run. A number of POE environment variables enable you to control such things as how the system resources are allocated and how standard I/O between the home node and the processes of your program should be handled.
Table 5 summarizes the various functions of the PoeAppl class. As already stated, the purpose of this class is simply to provide additional convenience functions for either connecting to or starting a POE job. Since this class is derived from the Application class, all of the Application class functions are available to objects of the PoeAppl class. For complete information on any of the functions summarized in the table, refer to the function's UNIX man page or the DPCL Class Reference.
Table 5. PoeAppl class function summary
This section describes the three classes that an analysis tool can use to represent, and act upon, probes. These are:
The ProbeExp class (defined in the header file ProbeExp.h) is used to represent probe expressions to be executed within one or more target application processes. As described in What is a probe expression?, probe expressions are "abstract syntax trees" -- data structures that represent logic removed from any particular syntactic representation. The term "abstract syntax tree" is one we have borrowed from compiler technology. Compilers create abstract syntax trees from a program's source code as an intermediary stage before manipulating and converting them into executable instructions. The DPCL system needs to create these abstract syntax tree data structures for the same reason that compilers do -- freed from a particular syntactic representation, they can be more easily converted into executable instructions. This is because a compiler (or, in this case, the DPCL system) only has to translate the abstract logic into executable instructions, and does not need to parse a particular language.
A probe expression could be a simple one that represents, for example, a persistent data value or a variable data value. In this case, the abstract syntax tree would be a very simple one consisting of a single node. These simple probe expressions, however, could be combined into more complex ones representing such things as operations, conditional statements, sequences of expressions, and function calls. For example, Figure 10 illustrates how an analysis tool could create the abstract syntax tree to represent the expression a + (b * c).
Figure 10. Building an abstract syntax tree. This figure builds an abstract syntax tree to represent the expression a + (b * c). First, in (1), three separate probe expressions are created to represent the variable values a, b, and c. These will be the abstract syntax tree's end, or "terminal" nodes. Next, in (2), the probe expressions representing the variables b and c are combined into a single probe expression representing the multiplication operation b * c. Finally, in (3), the probe expression representing the variable x is combined with the probe expression representing the multiplication operation to form the probe expression representing the operation a + (b * c). Figure 11 expands on this abstract syntax tree to create a probe expression representing conditional logic.
View figure. |
The following figure builds further on the abstract syntax tree created in Figure 10 to form a more complex abstract syntax tree to represent the conditional expression:
if (x == a + (b * c)) my_function();
Figure 11. Building a more complex abstract syntax tree. This figure builds on the probe expression created in Figure 10 to create a more complex probe expression representing a conditional expression in which a function is called if the condition tests true. First, in (4) and (5), the existing probe expression is expanded to form the test condition x == a + (b * c). Then, in (6) and (7), the probe expression representing the function call is built. Finally, in (8), these two separate probe expressions are combined to form a probe expression representing the conditional statement.
View figure. |
The member functions of the ProbeExp class are divided into two types -- those that the analysis tool can use to create probe expressions and so build abstract syntax trees, and those that the analysis tool can use to query and return values from probe expressions, and so navigate an abstract syntax tree. In addition to the member functions of the ProbeExp class, certain functions of other DPCL classes (such as the Process::alloc_mem, ProbeHandle::get_expression, and ProbeModule::get_reference functions) also return probe expressions.
First, let's discuss how an analysis tool goes about creating probe
expressions and building the abstract syntax tree. The simplest probe
expressions are those that consist of a single abstract syntax tree
node. These, if combined into a larger probe expression, are referred
to as "terminal nodes" because they have no child probe expression. In
DPCL, terminal nodes can represent a persistent data value, a variable data
value, or a reference to a function.
The analysis tool can create a probe expression representing a: | By: |
---|---|
persistent data value |
|
variable data value |
|
reference to a function |
|
These simple probe expressions do not need to be combined into more complex
ones. (Even a probe expression representing a reference to a probe
module function does not need to be combined into a probe expression
representing a function call since it can be specified as a phase probe when
instantiating a Phase class object.) As already stated,
however, these simple probe expressions can be combined into more complex
ones. These more complex probe expressions can represent an operation,
a function call, a sequence of instructions, and conditional
logic.
The analysis tool can create a probe expression to represent: | By: |
---|---|
an operation | Using any of the regular operators (such as +, *, !=, and so on) which have been overloaded so that, within the context of a probe expression, they do not execute locally, but instead create a probe expression representing the operation. Since the assignment (=) and address (&) operators could not be easily overloaded, the ProbeExp class provides explicit member functions (ProbeExp::assign and ProbeExp::address) to perform these operations. |
a function call | calling the ProbeExp::call function. |
a sequence of instructions | calling the ProbeExp::sequence function. |
conditional logic | calling the ProbeExp::ifelse function. |
Now let's discuss the ProbeExp class functions that enable the analysis tool to query and return information from probe expressions. In order to understand these functions, you should understand how DPCL represents operations, function calls, instruction sequences, and conditional logic as abstract syntax trees. The following figures illustrate these abstract syntax trees. In these figures, note that, for each node in the tree, the node type is shown. A probe expression's node type (as represented by one of the enumeration constants of the CodeExpNodeType enumeration type) represents the various operators and operands that may be found in a probe expression. For example, the enumeration constant CEN_mult_op indicates that the probe expression node represents a multiplication operation, and the enumeration constant CEN_call_op indicates that the probe expression node represents a function call. An analysis tool can ascertain a probe expression node type by calling the ProbeExp::get_node_type function.
Figure 12 shows probe expression abstract syntax trees representing the operations 8 * 2 and 10 + (8 * 2).
Figure 12. Probe expression abstract syntax trees representing operations
View figure. |
Figure 13 shows probe expression abstract syntax trees representing the function calls my_function(x); and my_function(x, y, z);. Note that the function call node (CEN_call_op) cannot have more than two children. When there are more than two function call arguments, the CEN_list_item nodes are used to organize them into a deeper tree.
Figure 13. Probe expression abstract syntax trees representing function calls
View figure. |
Figure 14 shows a probe expression abstract syntax tree that represents the instruction sequence x++; my_function(x);.
Figure 14. Probe expression abstract syntax tree representing an instruction sequence
View figure. |
Figure 15 shows probe expression abstract syntax trees that represent the conditional statements if (x != 4) my_function(x); and if (x != 4) my_function(x); else my_other_function();. Note that both the "if..." and if... else" conditional statements are created using the same function call -- ProbeExp::ifelse. Note also that the "if... else" statement node (CEN_if_else_stmt) is the only node type that has three children.
Figure 15. Probe expression abstract syntax trees representing conditional statements
View figure. |
To navigate and query a probe expression abstract syntax tree, the analysis tool uses member functions of the ProbeExp class designed for this purpose. The analysis tool can determine:
Table 6 summarizes the various functions of the ProbeExp
class. For complete information on any of the functions summarized in
the table, refer to the function's UNIX man page or the DPCL Class
Reference.
Table 6. ProbeExp class function summary
Calling the function: | Does this: | ||
---|---|---|---|
address | Creates a probe expression that represents the referencing of another probe expression. This function is provided because the & operator could not be easily overloaded since it is used in passing arguments to functions that use call-by-reference. | ||
assign | Creates a probe expression that represents the assignment of a value represented by one probe expression into a storage location represented by another probe expression. This function is provided because the = operator could not be easily overloaded without causing simple expression manipulation to become unwieldy. | ||
call | Creates a probe expression that represents a function call. | ||
get_data_type | Returns the data type (ProbeType object) of this probe expression. (For more information on ProbeType objects, refer to What is the ProbeType class?.) | ||
get_node_type | Returns the type of node at the root of this probe expression's abstract syntax tree. | ||
has_int8 has_int16 has_int32 has_int64 has_int has_uint8 has_uint16 has_uint32 has_uint64 has_uint | Returns a Boolean value indicating whether or not this probe expression represents a datum with the data type in question. | ||
has_string | Returns a Boolean value indicating whether or not the probe expression has a string data type. | ||
has_children has_left has_right has_center | Returns a Boolean value indicating whether or not the probe expression's node has child probe expression nodes (has_children), has a left-hand child node (has_left), has a right-hand child node (has_right), or has a center node (has_center). | ||
ifelse | Creates a probe expression that represents a conditional statement. | ||
is_same_as | Compares two probe expressions for equivalence. | ||
operator + (binary or unary) operator += operator - (binary or unary) operator -= operator * (binary or unary) operator *= operator / operator /= operator % operator %= operator == operator ! operator != operator < operator <= operator << operator <<= operator > operator >= operator >> operator >>= operator & (binary or unary) operator &= operator && operator | operator |= operator || operator ^ operator ^= operator ~ operator [] | Creates probe expressions to represent particular operations.
These common operators have been overloaded so that, when used within the
context of the ProbeExp class, they do not execute locally but
instead create a probe expression that represent the operation.
| ||
operator = | Assigns values to the ProbeExp object. | ||
sequence | Creates a probe expression that represents the sequence of two probe expressions. | ||
value_int8 value_int16 value_int32 value_int64 value_uint8 value_uint16 value_uint32 value_uint64 | Returns the value, of the indicated type, contained within this probe expression. | ||
value_left value_right value_center | Returns the value contained within a child probe expression of the calling probe expression. | ||
value_text | Copies, into a specified buffer, a string representing the value contained within this probe expression node. | ||
value_text_length | Returns the length of the text string contained within this probe expression node. This enables the analysis tool to determine the size of the buffer into which the value_text function will copy the text string. |
Objects of the ProbeHandle class (which is defined in the header file ProbeHandle.h) represent identifying handles to installed point probes. When the analysis tool installs one or more probes as point probes (using the Process::install_probe, Process::binstall_probe, Application::install_probe, or Application::binstall_probe function), the function called will return an output array containing ProbeHandle objects representing each of the installed point probes. Using these probe handles, the analysis tool can make subsequent DPCL function calls to manipulate the installed point probes. Specifically, the analysis tool can:
The following table summarizes the various functions of the
ProbeHandle class. For complete information on any of these
functions, refer to the function's UNIX man page or the DPCL Class
Reference.
Table 7. ProbeHandle class function summary
Calling the function: | Does this: |
---|---|
get_expression | Returns a copy of the probe expression (ProbeExp object) for the point probe represented by this ProbeHandle object. Using member functions of the ProbeExp object (described in What is the ProbeExp class?), the analysis tool can navigate this probe expression's abstract syntax tree to get information about the probe expression. |
get_point | Returns the instrumentation point (InstPoint object) at which the point probe represented by this ProbeHandle object was installed. Using member functions of the InstPoint object (described in What is the InstPoint class?), the analysis tool can get information about the instrumentation point at which the point probe has been installed. |
operator = | Assigns values to the ProbeHandle object. |
Objects of the ProbeModule class (which is defined in the header file ProbeModule.h) represent probe modules that the analysis tool can load into one or more target application processes using the Process::load_module, Process::bload_module, Application::load_module, or Application::bload_module function. A probe module is a compiled object file containing one or more functions written in C. Once a probe module is loaded into a target application process, its functions are available to the analysis tool as if they were native to the target application.
To invoke a probe module function, the analysis tool can first get a reference to the function by calling the ProbeModule::get_reference function. This returns a probe expression (ProbeExp object) that represents a reference to the probe module function. This simple probe expression can be specified as a phase probe when instantiating or assigning values to a Phase class object (described in What is the Phase class?), or it can be combined (using the ProbeExp::call function) into a probe expression representing a function call. The probe expression representing a function call can then be installed as a point probe (using the Process::install_probe, Process::binstall_probe, Application::install_probe, or Application::binstall_probe) or executed as a one-shot probe (using the Process::execute, Process::bexecute, Application::execute, or Application::bexecute function).
The following table summarizes the various functions of the
ProbeModule class. For complete information on any of these
functions, refer to the function's UNIX man page or the DPCL Class
Reference.
Table 8. ProbeModule class function summary
This section describes two classes that the analysis tool can use to examine the source code associated with a target application process and identify locations, called "instrumentation points", where point probes can be installed. These are the SourceObj class (described in What is the SourceObj class? and used to represent the source code structure of a target application process) and InstPoint class (described in What is the InstPoint class? and used to represent instrumentation points).
Objects of the SourceObj class (which is defined in the header file SourceObj.h) are called "source objects" and are used by the DPCL system to represent the source code structure associated with a target application process (Process object). The source code structure associated with a process is represented as a hierarchical tree of SourceObj objects -- with each SourceObj object in the tree representing a particular type of source object -- a program-level source object, a module-level source object, a function-level source object, or a data-level source object. The analysis tool can navigate and query this hierarchy of source objects to:
To get the top, program-level, source object associated with a process, the analysis tool calls the Process::get_program_object function. Since applications may be very large and the analysis tool (or the analysis tool user) may be interested only in a particular module (compilation unit) within the program, the hierarchy of SourceObj objects under the initial program-level source object does not represent the full source code structure. Instead, for performance reasons, the hierarchy of SourceObj objects reaches down only as far as the module level. The module-level source objects are children of the program-level source object. By calling the SourceObj::child function for the program-level source object, the analysis tool can get any of its child (module-level) source objects, and so navigate one level down the source code hierarchy. To navigate further down into the source hierarchy to examine additional program structure, the analysis tool can then call the SourceObj::expand or SourceObj::bexpand function for the module-level source object. The SourceObj::expand or SourceObj::bexpand functions expand the tree to include the low-level source objects.
The following figure illustrates how an analysis tool can obtain a program-level source object and expand one of its module level source objects so that the source object hierarchy then contains SourceObj object nodes for functions and global data variables. This figure shows the enumeration constants of the SourceType enumeration type. These enumeration constants are returned by the SourceObj::src_type function and identify the particular SourceObj node in the source hierarchy as either a program-level, module-level, function-level, or data-level source object.
Figure 16. Navigating and expanding a source hierarchy. First, in (1), the analysis tool calls the Process::get_program_object function to get the initial source hierarchy down to the module level. Then, in (2), the analysis tool calls the SourceObj::child function to navigate down one level in the source hierarchy. Then, in (3), the analysis tool calls the SourceObj::expand function to expand the particular module's hierarchy of function-level and data-level source objects.
View figure. |
Once the source hierarchy has been expanded below a particular module-level source object, the analysis tool can navigate further down the hierarchy to obtain information about the module's functions and global data variables. In particular, if the source object is a function-level or data-level source object, the analysis tool can call the SourceObj::reference function to get a probe expression that represents a reference to that function or global data variable. Note that the SourceObj object representing a global data variable will only be found under the SourceObj object representing the module where the global data variable was defined.
The analysis tool can also identify instrumentation points (by calling the SourceObj::inclusive_point or SourceObj::exclusive_point functions) at which it can install probe expressions as point probes. These functions are described in greater detail next in What is the InstPoint class?.
The following table summarizes the various functions of the
SourceObj class. For complete information on any of these
functions, refer to the function's UNIX man page or the DPCL Class
Reference.
Table 9. SourceObj class function summary
Objects of the InstPoint class (which is defined in the header file InstPoint.h) represent instrumentation points -- locations within the target process(es) where the analysis tool can install point probes by calling the Process::install_probe, Process::binstall_probe, Application::install_probe, or Application::binstall_probe functions. All four of these functions must, for each probe expression being installed as a point probe, be passed an InstPoint object that indicates where the probe should be installed. To get an InstPoint object, the analysis tool calls the SourceObj::exclusive_point or SourceObj::inclusive_point function. (Note that in order for these functions to return an InstPoint object, at least one of the module-level source objects in the source object hierarchy must have been expanded by the SourceObj::expand or SourceObj::bexpand function.) To determine the number of instrumentation points under a particular source object, the analysis tool can call the SourceObj::exclusive_point_count or SourceObj::inclusive_point_count function. The SourceObj::exclusive_point_count function returns the number of InstPoint objects associated with the particular source object, while the SourceObj::inclusive_point_count function returns the number of InstPoint objects associated with a particular source object and all of its child source objects.
Figure 17 illustrates the difference between exclusive and inclusive point counts.
Figure 17. Exclusive and inclusive instrumentation point counts for source objects. Exclusive instrumentation points refer to those instrumentation points associated with the source object itself. Inclusive instrumentation points refer to those instrumentation points associated with the source object, and all of its children. Note that the two unexpanded module-level source objects show no instrumentation points. That is because the instrumentation point information is only available once the module-level source object has been expanded.
View figure. |
When calling either the SourceObj::exclusive_point or the SourceObj::inclusive_point function, the analysis tool identifies a particular InstPoint object by supplying the function with an index value. The SourceObj::exclusive_point_count and SourceObj::inclusive_point_count functions can be used to initialize a loop that will cycle though the InstPoint objects and examine each in turn to determine if it represents a suitable location at which to install a particular probe expression as a point probe.
The analysis tool can also get the InstPoint object for a point probe that has already been installed by calling the ProbeModule::get_point function.
Once the analysis tool has a particular InstPoint object, it can call InstPoint class functions to get information about the instrumentation point. If the analysis tool is examining the instrumentation point to determine if a point probe should be installed there, it will want to know whether the instrumentation point represents a function entry, function exit, or function call site. To get this information, it can call the InstPoint::get_type function, which returns one of the enumeration constants (IPT_function_entry, IPT_function_exit, or IPT_function_call) of the InstPtType enumeration type. If the instrumentation point represents a function call site, the analysis tool can also get the location where the point probe will be placed relative to the instrumentation point. To get this information, the analysis tool can call the InstPoint::get_location function which returns one of the enumeration constants (IPL_before or IPL_after) of the InstPtLocation enumeration type. Figure 18 illustrates the various instrumentation point type and location information that the analysis tool can get by calling the InstPoint::get_type and InstPoint::get_location functions.
Figure 18. Instrumentation point types and locations
View figure. |
In addition to the instrumentation point type and location information, the analysis tool can:
The following table summarizes the various functions of the
InstPoint class. For complete information on any of these
functions, refer to the function's UNIX man page or the DPCL Class
Reference.
Table 10. InstPoint class function summary
Objects of the ProbeType class (which is defined in the header file ProbeType.h) represent data types associated with either a source object (SourceObj object), or a probe expression (ProbeExp object). The member and friend functions of this class are of two types -- those that enable the analysis tool to create a ProbeType object to represent a data type, and those that enable the analysis tool to query information about a ProbeType object.
The functions that create ProbeType objects to represent a particular data type are used by the analysis tool primarily for allocating memory for probes. When allocating memory for use by probes (using the Process::alloc_mem, Process::balloc_mem, Application::alloc_mem, and Application::balloc_mem function), the analysis tool supplies a ProbeType object as a function parameter in order to indicate the type of memory to allocate.
The functions that query ProbeType objects enable the analysis tool to ascertain the data type associated with a particular source object (SourceObj object) or probe expression (ProbeExp object). The ProbeType object associated with a source object is returned by the SourceObj::get_data_type function, while the ProbeType object associated with a probe expression is returned by the ProbeExp::get_data_type function. The ability to get the data type of a source object or probe expression enables the analysis tool to use the source object or probe expression value correctly.
One particularly useful ability of the ProbeType class is to return actual integer and pointer values of function parameters. To do this, the analysis tool first creates a ProbeType object that represents the function prototype (by calling the ProbeType::function_type function). Then, it can create a probe expression by calling the ProbeType::get_actual function (an index value supplied to the ProbeType::get_actual function indicates the particular function parameter). When the probe expression returned by the ProbeType::get_actual function is executed within the target application process, it will get the actual parameter value. Note that the ProbeType::get_actual function can only return an actual parameter value if it represents a 32-bit integer or a pointer.
One important thing you should understand about ProbeType objects is that they are expression trees. While in many cases (such as ProbeType objects representing an integer) it is not necessary to represent the ProbeType object as a tree, we have structured ProbeType objects as trees in order to have ProbeType objects that represent pointers and function prototypes. (See Figure 19).
The data type information for each ProbeType object is represented by an enumeration constant of the DataExpNodeType enumeration type. The analysis tool can query this constant by calling the ProbeType::get_node_type function. The analysis tool can also determine how many child ProbeType objects are under a particular ProbeType object by calling the ProbeType::child_count function. To get a particular child ProbeType object of a parent ProbeType object, the analysis tool can call the ProbeType::child function. For example, if calling the ProbeType::get_node_type function returns the enumeration constant DEN_pointer_type (indicating a pointer to a pointee), the analysis tool can get the ProbeType object for the pointee by calling the ProbeType::child function.
Figure 19. Probe type trees. This figure illustrates the two situations (data types representing pointers and function prototypes) in which a ProbeType expression tree will be more complex than a single node. The analysis tool can call the ProbeType::get_node_type function to determine the type represented by the ProbeType object's node in the expression tree. To navigate down into the tree, the analysis tool can call the ProbeType::child function to get a ProbeType object that represents one of the child ProbeType object nodes of the current ProbeType object's node. In the case of a ProbeType object that represents a function prototype, its leftmost subtree will represent the function return type and its right subtrees will represent any function parameters.
View figure. |
The following table summarizes the various functions of the
ProbeType class. For complete information on any of these
functions, refer to the function's UNIX man page or the DPCL Class
Reference.
Table 11. ProbeType class function summary
Objects of the Phase class (which is defined in the header file Phase.h) represent the control mechanism for invoking phase probes at set intervals. The phase probes themselves are probe expressions (ProbeExp objects) that represent references to probe module functions. Before instantiating a Phase object, the analysis tool will:
When instantiating the Phase class object, the analysis tool can specify up to three phase probes (ProbeExp objects that reference probe module functions) to be invoked and the CPU-time interval at which their execution will be triggered. The three phase probes that can be invoked represent 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 analysis tool has instantiated a Phase class object, it can:
As you can see from the preceding list, most of the functions that act upon
a Phase class object are actually member functions of other
classes. The Phase class itself contains member functions
only for assignment and equivalence comparison as shown in the following
table. For complete information on any of the functions described in
the preceding list or the following table, refer to the function's UNIX
man page or the DPCL Class Reference.
Table 12. Phase class function summary
Calling the function: | Does this: |
---|---|
operator = | Assigns values to the Phase object. |
operator == operator != | Compares two Phase objects for equivalence. |
This section describes two classes that the analysis tool can use to list functions that match a regular expression search string supplied by the analysis tool's end user. These are the FunctionList class (described in What is the FunctionList class? and used to represent the list of functions that match the supplied search string) and the FunctionId class (described in What is the FunctionId class? and used to represent individual functions in the function list).
Objects of the FunctionList class (which is defined in the header file FunctionList.h) are returned by the SourceObj::bget_function_list and SourceObj::get_function_list functions, and contain a list of functions that match a regular expression search pattern that the analysis tool has supplied. Using member functions of the FunctionList class, the analysis tool can:
Typically, objects of the FunctionList class will be used in conjunction with objects of the FunctionId class to list functions in a particular source object that match a supplied regular expression search pattern. This enables an analysis tool to locate a function without having to expand multiple source objects, which would be much more resource intensive. Instead, the FunctionList and FunctionId classes could be used to locate the desired function, and then only the SourceObj object that contains the function would need to be expanded. For example, the analysis tool's user interface could prompt the end user for a function search string and source object to search. The analysis tool would pass the search string to either the SourceObj::bget_function_list or SourceObj::get_function_list function which would return the FunctionList object containing the list of individual functions (FunctionId objects) that match the search string. The analysis tool could then initialize a loop using the FunctionList::get_count function and, cycling through the loop, use the FunctionList::get_entry function and functions of the FunctionId class to list the function names for the user.
The following table summarizes the various functions of the
FunctionList class. For complete information on any of these
functions, refer to the function's UNIX man page or the DPCL Class
Reference.
Table 13. FunctionList class function summary
Objects of the FunctionId class (which is defined in the header file FunctionId.h) represents a single entry in a function list (FunctionList object). The analysis tool can get a reference to a FunctionId object by calling the FunctionList::get_entry function. Once it has a reference to a FunctionId object, the analysis tool can:
Typically, objects of the FunctionId class will be used in conjunction with objects of the FunctionList class to list functions in a particular source object that match a supplied regular expression search pattern. For more information on FunctionList objects, refer to What is the FunctionList class?.
The following table summarizes the various functions of the
FunctionId class. For complete information on any of these
functions, refer to the function's UNIX man page or the DPCL Class
Reference.
Table 14. Phase class function summary
Objects of the AisStatus class (which is defined in the header file AisStatus.h) store status and severity codes (and, in some cases, data associated with the status) returned by other DPCL functions, and can also be used by the analysis tool to store status values for its own purposes. When a DPCL function call returns an AisStatus object, the analysis tool can check its status code by calling the AisStatus::status function, and its severity by calling the AisStatus::severity function. The AisStatus::status function returns one of the constants enumerated in the AisStatusCode enumeration type, and the AisStatus::severity function returns one of the constants enumerated in the AisSteverityCode enumeration type. For a complete listing and description of these constants, refer to the DPCL Class Reference.
In some situations, the AisStatus object returned by the DPCL system will contain one or more data values associated with the particular status. To determine if an AisStatus object has any additional data values, the analysis tool can call the AisStatus::data_count function. If there are, it can use the AisStatus::data_value and AisStatus::data_value_length functions to get the value.
The analysis tool can also create AisStatus objects for its own status reporting. The AisStatus class constructor enables the analysis tool to specify a status and severity value and the AisStatus::add_data function enables it to associate data with the status.
The following table summarizes the various functions of the
AisStatus class. For complete information on any of these
functions, refer to the function's UNIX man page or the DPCL Class
Reference.
Table 15. AisStatus class function summary