JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Oracle Solaris Dynamic Tracing Guide     Oracle Solaris 11 Information Library
search filter icon
search icon

Document Information

Preface

1.  About DTrace

2.  D Programming Language

D Program Structure

Probe Clauses and Declarations

Probe Descriptions

Predicates

Actions

Order of Execution

Use of the C Preprocessor

Compilation and Instrumentation

Variables and Arithmetic Expressions

Predicates

Output Formatting

Arrays

External Symbols and Types

Types, Operators, and Expressions

Identifier Names and Keywords

Data Types and Sizes

Constants

Arithmetic Operators

Relational Operators

Logical Operators

Bitwise Operators

Assignment Operators

Increment and Decrement Operators

Conditional Expressions

Type Conversions

Precedence

Variables

Scalar Variables

Associative Arrays

Thread-Local Variables

Clause-Local Variables

Built-in Variables

External Variables

Pointers and Arrays

Pointers and Addresses

Pointer Safety

Array Declarations and Storage

Pointer and Array Relationship

Pointer Arithmetic

Generic Pointers

Multi-Dimensional Arrays

Pointers to DTrace Objects

Pointers and Address Spaces

Strings

String Representation

String Constants

String Assignment

String Conversion

String Comparison

Structs and Unions

Structs

Pointers to Structs

Unions

Member Sizes and Offsets

Bit-Fields

Type and Constant Definitions

typedef

Enumerations

Inlines

Type Namespaces

3.  Aggregations

4.  Actions and Subroutines

5.  Buffers and Buffering

6.  Output Formatting

7.  Speculative Tracing

8.  dtrace(1M) Utility

9.  Scripting

10.  Options and Tunables

11.  Providers

12.  User Process Tracing

13.  Statically Defined Tracing for User Applications

14.  Security

15.  Anonymous Tracing

16.  Postmortem Tracing

17.  Performance Considerations

18.  Stability

19.  Translators

20.  Versioning

Variables and Arithmetic Expressions

Our next example program makes use of the DTrace profile provider to implement a simple time-based counter. The profile provider is able to create new probes based on the descriptions found in your D program. If you create a probe named profile:::tick- n sec for some integer n, the profile provider will create a probe that fires every n seconds. Type the following source code and save it in a file named counter.d:

/*
* Count off and report the number of seconds elapsed
*/
dtrace:::BEGIN
{
        i = 0;
}

profile:::tick-1sec
{
        i = i + 1;
        trace(i);
}

dtrace:::END
{
        trace(i);
}

When executed, the program counts off the number of elapsed seconds until you press Control-C, and then prints the total at the end:

# dtrace -s counter.d
dtrace: script 'counter.d' matched 3 probes
CPU     ID                    FUNCTION:NAME
0    25499                       :tick-1sec 1
0    25499                       :tick-1sec 2
0    25499                       :tick-1sec 3
0    25499                       :tick-1sec 4
0    25499                       :tick-1sec 5
0    25499                       :tick-1sec 6
^C
0    2                                        :END 6
#

The first three lines of the program are a comment to explain what the program does. Similar to C, C++, and the Java programming language, the D compiler ignores any characters between the /* and */ symbols. Comments can be used anywhere in a D program, including both inside and outside your probe clauses.

The BEGIN probe clause defines a new variable named i and assigns it the integer value zero using the statement:

i = 0;

Unlike C, C++, and the Java programming language, D variables can be created by simply using them in a program statement; explicit variable declarations are not required. When a variable is used for the first time in a program, the type of the variable is set based on the type of its first assignment. Each variable has only one type over the lifetime of the program, so subsequent references must conform to the same type as the initial assignment. In counter.d, the variable i is first assigned the integer constant zero, so its type is set to int. D provides the same basic integer data types as C, including:

char
Character or single byte integer
int
Default integer
short
Short integer
long
Long integer
long long
Extended long integer

The sizes of these types are dependent on the operating system kernel's data model, described in Types, Operators, and Expressions. D also provides built-in friendly names for signed and unsigned integer types of various fixed sizes, as well as thousands of other types that are defined by the operating system.

The central part of counter.d is the probe clause that increments the counter i:

profile:::tick-1sec
{
        i = i + 1;
        trace(i);
}

This clause names the probe profile:::tick-1sec, which tells the profile provider to create a new probe which fires once per second on an available processor. The clause contains two statements, the first assigning i to the previous value plus one, and the second tracing the new value of i. All the usual C arithmetic operators are available in D; the complete list is found in Types, Operators, and Expressions. Also as in C, the ++ operator can be used as shorthand for incrementing the corresponding variable by one. The trace function takes any D expression as its argument, so you could write counter.d more concisely as follows:

profile:::tick-1sec
{
        trace(++i);
}

If you want to explicitly control the type of the variable i, you can surround the desired type in parentheses when you assign it in order to cast the integer zero to a specific type. For example, if you wanted to determine the maximum size of a char in D, you could change the BEGIN clause as follows:

dtrace:::BEGIN
{
        i = (char)0;
}

After running counter.d for a while, you should see the traced value grow and then wrap around back to zero. If you grow impatient waiting for the value to wrap, try changing the profile probe name to profile:::tick-100msec to make a counter that increments once every 100 milliseconds, or 10 times per second.