Description

Counter data and
sampling results are sampled into CPC buffers, which
are represented by the opaque data type cpc_buf_t.
A CPC buffer is created with cpc_buf_create() to
hold the data for a specific CPC set. Once a CPC buffer has been created,
it can only be used to store and manipulate the data of the CPC set
for which it was created.

Once a set has been successfully bound, the counter values and the sampling results are retrieved using cpc_set_sample(). For the CPC request, the cpc_set_sample
() function takes a snapshot of the hardware performance
counters counting on behalf of the CPC requests in set and
stores the 64-bit virtualized software representations of the counters
in the supplied CPC buffer. For the SMPL request, the cpc_set_sample() function
retrieves the sampling results collected by the hardware on behalf
of the SMPL requests in set and stores the
results in the supplied CPC buffer as a form of SMPL records. If a set was bound with cpc_bind_curlwp(3CPC) or cpc_bind_curlwp(3CPC), the set can only be sampled by the LWP that
bound it.

The kernel maintains 64-bit virtual software counters to hold
the counts accumulated for each CPC request in the set, thereby
allowing applications to count past the limits of the underlying physical
counter, which can be significantly smaller than 64 bits. The kernel
attempts to maintain the full 64-bit counter values even in the face
of physical counter overflow on architectures and processors that
can automatically detect overflow. If the processor is not capable
of overflow detection, the caller must ensure that the counters are
sampled often enough to avoid the physical counters wrapping. The
events most prone to wrap are those that count processor clock cycles.
If such an event is of interest, sampling should occur frequently
so that the counter does not wrap between samples.

The cpc_buf_get() function retrieves the
last sampled value of a particular CPC request in buf.
The index argument specifies which CPC request value
in the set to retrieve. The index for each request is returned during
set configuration by cpc_set_add_request(3CPC).
The 64-bit virtualized software counter value is stored in the location
pointed to by the val argument. If index does
not specify the CPC request but the SMPL request in buf,
cpc_buf_get() function sets errno to
indicate error and returns -1. To retrieve the results for SMPL requests
in buf, cpc_buf_smpl_get_item() and
cpc_buf_smpl_get_record() should be used.

The cpc_buf_set() function stores a 64-bit
value to a specific CPC request in the supplied buffer. This operation can be useful
for performing calculations with CPC buffers, but it does not affect
the value of the hardware counter (and thus will not affect the next
sample). If
index does not specify the CPC request but the SMPL request
in buf, the cpc_buf_set() function
sets errno to indicate error and returns -1.
The operation to store values to a specific SMPL request in the specified
buffer is not supported.

The cpc_buf_hrtime() function returns a high-resolution
timestamp indicating exactly when the set was last sampled by the
kernel.

The cpc_buf_tick() function returns a 64-bit
virtualized cycle counter indicating how long the set has been programmed
into the counter since it was bound. The units of the values returned
by cpc_buf_tick() are CPU clock cycles.

The cpc_buf_sub() function calculates the
difference between each CPC request in sets a and
b, storing the result in the corresponding request within
set ds. More specifically, for each CPC request index
n, this function performs ds[
n] = a[n]
- b[n]. Similarly, cpc_buf_add() adds
each CPC request in sets a and b and
stores the result in the corresponding request within set ds. If the specified buffer
a and b also contain the results
of the SMPL requests, cpc_buf_sub() and cpc_buf_add
() skip the results of the SMPL requests and handle only
the results of the CPC requests.

The cpc_buf_copy() function copies each value
from buffer src into buffer ds.
Both buffers must have been created from the same cpc_set_t.

The cpc_buf_zero() function sets each request's
value in the buffer to zero.

The cpc_buf_destroy() function frees all
resources associated with the CPC buffer.

The
cpc_buf_smpl_rec_count() function returns the number of available
SMPL records that are found in buf, for the
SMPL request specified by request_index, into
the uint_t object pointed to by rec_count
.

The cpc_buf_smpl_get_item() function
retrieves one record item specified by record_item_index in
the SMPL record specified by record_index for
the SMPL request specified by request_index,
into the uint64_t object pointed to by val.
record_item_index is the index to an item found in the
SMPL record, which should be obtained by using cpc_walk_smpl_recitems
() and cpc_walk_smpl_recitems_req(). Also,
the following special macros can be used to specify generic record
items for record_item_index:

SMPL_REC_ITEM_PC

Index to the program counter associated with he monitoring
event; for example, this will be internally mapped to the index to
the RIP item on Intel PEBS.

SMPL_REC_ITEM_DLINA

Index to the data linear address associated with the
monitoring event; for example, this will be internally mapped to the
index to the data linear address item on Intel PEBS.

SMPL_REC_ITEM_LAT

Index to the latency value associated with the monitoring
event; for example, this will be internally mapped to the index to
the latency value item on Intel PEBS.

SMPL_REC_ITEM_DSRC

Index to the data source description associated with
the monitoring event; for example, this will be internally mapped
to the index to the data source encoding item on Intel PEBS.

Calling cpc_buf_smpl_get_item() will
not invalidate the sampling results in buf.

The cpc_buf_smpl_get_record() function returns
on SMPL record specified by record_index for
the SMPL request specified by request_index,
as the pointer to an array of uint64_t objects.
Each record item in the SMPL record should be accessed using the index
to the desired SMPL record item, obtained by using cpc_walk_smpl_recitems
() and cpc_walk_smpl_recitems_req(). The
application must not alter the array of uint64_t objects
returned by cpc_buf_smpl_get_record(). Calling
cpc_buf_smpl_get_record() will not invalidate the sampling
results in buf.

Return Values

Upon successful completion, cpc_buf_create() returns
a pointer to a CPC buffer which can be used to hold data for the set
argument. Otherwise, this function returns NULL and
sets errno to indicate the error.

Upon successful completion, cpc_set_sample(),
cpc_buf_get(), and cpc_buf_set() return
0. Otherwise, they return -1 and set errno to indicate
the error.

cpc_buf_smpl_get_item
() function sets errno to EINVAL and returns
-1 if the system does not support the SMPL record item corresponding
to the special macro. If cpc was not successfully
opened for SMPL, or if the request specified by request_index is
not for SMPL, or if record_index does not
point to a record entry available in buf, or
if record_item_index does not point to an available
record item, the cpc_buf_smpl_get_item() function
sets errno to EINVAL and
returns -1.

cpc_buf_smpl_get_record() function
sets errno to EINVAL and
returns -1 if cpc was not successfully opened
for SMPL, or if the request specified by request_index is
not for SMPL, or if record_index does not
point to a record entry available in buf.

Errors

These functions will fail if:

EINVAL

For cpc_set_sample(), the set is
not bound, the set and/or CPC buffer were not created with the given
cpc handle, or the CPC buffer was not created with the
supplied set.

For
cpc_buf_get() and cpc_buf_set() functions,
the request specified by index is not for CPC
but for SMPL.

For cpc_buf_smpl_rec_count() functions,
the request specified by request_index is not
for SMPL.

For cpc_buf_smpl_get_item(),
the system does not support the SMPL record item corresponding to
the specified special macro, cpc was not successfully
opened for SMPL, the request specified by request_index is
not for SMPL, record_index does not point to
a record entry available in buf, or record_item_index
does not point to an available record item.

For
cpc_buf_smpl_get_record(), cpc was
not successfully opened for SMPL, the request specified by request_index
is not for SMPL, or record_index does
not point to a record entry available in buf.

EAGAIN

When using cpc_set_sample() to
sample a CPU-bound set, the LWP has been unbound from the processor
it is measuring.

ENOMEM

The library could not allocate enough memory for its
internal data structures.

See also

Notes

Often the overhead of performing a system call can be too disruptive
to the events being measured. Once a cpc_bind_curlwp(3CPC) call
has been issued, it is possible to access directly the performance
hardware registers from within the application. If the performance
counter context is active, the counters will count on behalf of the
current LWP.

Not all processors support this type of access. On processors
where direct access is not possible, cpc_set_sample() must
be used to read the counters.

If the counter context is not active or has been invalidated,
the %pic register (SPARC), and the rdpmc instruction
(Pentium) becomes unavailable.

Pentium II and III processors support the non-privileged rdpmc
instruction that requires that the counter of interest be specified
in %ecx and return a 40-bit value in the %edx
:%eax register pair. There is no non-privileged
access mechanism for Pentium I processors.