Insert probe points in your code to:
Trace the values of variables in your program.
Provide internal state information that is not available through the exported interface. This is useful for debugging or for performance analysis.
For example, use probe points to show performance relevant information hidden in C++ private classes, or to show operational data such as the collision rate in a hash table. By placing a probe point in the hash table code, the probe point can write to the trace file each time a collision is detected.
The interface for inserting probes is defined by the TNF_PROBE macros TNF_PROBE_0 through TNF_PROBE_5. The numbers 0 through 5 are the number of variables being traced by the macro.
With these macros, you can insert probe points anywhere in your code to get the values of variables and to trace program execution. The libtnfprobe library defines the standard scalar types (ints, longs, floats, and so on), but you can define more complex structures with the TNF_DECLARE_RECORD and TNF_DEFINE_RECORD macros. See "Defining User Types for Probe Points".
In the simplest case, TNF_PROBE_0, you give no argument types:
TNF_PROBE_0 (name, keys, detail);
The variables are:
name -- The name of the probe, following all the syntax guidelines for identifiers in ANSI C. The use of name declares it, so no separate declaration is necessary. This is a block scope declaration, so it does not affect the name space of the program.
keys -- A list of groups to which the probe belongs. The list is a string containing space-separated keywords and cannot contain a semicolon, an equal sign, or a single quotation mark.( ;= ` ). When any of the groups are enabled, the probe point is enabled. keys cannot be a variable--it must be an in-line string.
detail -- Provides a way for you to define your own attributes and values. The detail string is made up of attribute-value pairs separated from each other by semicolons, although the value is optional. The first word (up to a space) is considered to be the attribute and the rest of the string (up to the semicolon) is considered to be the value. Spaces around the semicolon delimiter are allowed. Single quotation marks and the equal sign are not allowed in the detail statement.
Prefix the attribute name with a vendor stock symbol followed by the % character to avoid name collisions. In the following example, four attributes are defined: sunw%debug, comX%exception, comY%func_entry, and comY%color. Since prex tokenizes the value on spaces, multiword values can be matched on any of the words, but not on the entire string. For example:
sunw%debug entering function A; comX%exception no file; comY%func_entry; comY%color red blue
Table 1-8 gives the values that are matched on for the command shown above:
Table 1-8 Examples of User-Defined Attributes
Attribute |
Value |
Values prex matches on |
---|---|---|
sunw%debug |
entering function A |
entering or function or A |
comX%exception |
no file |
no or file |
comY%func_entry |
|
/.*/ (regular expression) |
comY%color |
red blue |
red or blue |
libtnfprobe reserves all attribute names that are not prefixed by a vendor symbol (it reserves all attributes that do not have the % character in them). The code for cookie.c in "A Sample C Program" contains the following use of TNF_PROBE_0:
TNF_PROBE_0(start, "cookie main", "sunw%debug starting main");
Compiling with the preprocessor option -DNPROBE (see cc(1)), or with the preprocessor control statement #define NPROBE ahead of the #include <tnf/probe.h> statement, stops probe points as well as TNF type extension code from being compiled into the program.
The numbers 1 through 5 in the argument names are used here to illustrate the number of variables you give to the probe point. For example, the syntax for TNF_PROBE_1 is:
TNF_PROBE_1(name, keys, detail, arg_type_1, arg_name_1, arg_value_1);
and the syntax for TNF_PROBE_5 is:
TNF_PROBE_5(name, keys, detail, arg_type_1, arg_name_1, arg_value_1 arg_type_2, arg_name_2, arg_value_2 arg_type_3, arg_name_3, arg_value_3 arg_type_4, arg_name_4, arg_value_4 arg_type_5, arg_name_5, arg_value_5);
The arguments are:
arg_type_n--The type of the nth argument. n is a number from 1 through 5. The predefined types are listed in Table 1-9. See "Defining User Types for Probe Points" for information about defining your own types.
arg_name_n--The name you give the nth argument. Follow the ANSI C rules for identifiers, and do not use quotation marks around the argument name. (Note that the slots attribute mentioned on "Attributes " contains a string version of this name.)
arg_value_n--The expression that is evaluated to a value that is included in the trace file. A read access is done on any variables that are mentioned in value_n. In a multithreaded program, place locks around the TNF_PROBE_n macro if value_n contains data that should be read protected.
Type |
Associated C Type and Semantics |
---|---|
tnf_long |
int, long |
tnf_ulong |
unsigned int, unsigned long |
tnf_longlong |
long long (if implemented in compilation system) |
tnf_ulonglong |
unsigned long long (if implemented in compilation system) |
tnf_float |
float |
tnf_double |
double |
tnf_string |
char * |
tnf_opaque |
void * |
For example, the cookie.c program on "A Sample C Program" uses TNF_PROBE_2 as follows:
TNF_PROBE_2(inloop, "cookie main loop","sunw%debug in the loop", tnf_long, loop_count, i, tnf_long, total_iterations, sum);
Table 1-10 explains some of the macro definitions in cookie.c.
Table 1-10 TNF Macro Definitions in cookie.c
TNF_PROBE_0 ( |
A probe with no argument types |
start, |
The name of the probe |
"cookie main", |
The list of groups the probe belongs to cookie and main (the values of the keys attribute) |
"sunw%debug starting main"); |
User-defined attribute=sunw%debug; value=starting main (used by debug probe function) |
TNF_PROBE_2 ( |
A probe with two variables |
inloop, |
The name of the probe |
"cookie main loop", |
The keys - cookie, main, and loop |
"sunw%debug in the loop", |
Values for the debug probe function |
tnf_long, |
The type of the first variable |
loop_count, |
The name of the first variable (value of the slots attribute) |
i, |
The first variable |
tnf_long, |
The type of the second variable |
total_iterations, |
The name of the second variable (value of the slots attribute) |
sum); |
The second variable |
""); |
In Example 1-4, probe points are placed at the entry and exit of a function to see how much time is spent in the function. The probe at the function entry also logs the arguments to the function.
When prex encounters a probe point at run time that is enabled for tracing, it writes a record to the trace file. Each probe point logs the time when it was encountered and also references a tag record containing information like the file name, line number, name, keys, and detail of the probe point. These tag records are written only once, and are never overwritten in the trace file.
The first probe point, work_args, also logs the value of the two arguments of the probe point (state and message).
#include <tnf/probe.h> int work(int state, char *message) { TNF_PROBE_2(work_start, "work_module work" "sunw%debug in function work", tnf_long, int_input, state, tnf_string, string_input, message); ... TNF_PROBE_0(work_end, "work_module work", ""); }