dtrace_consume, dtrace_status - DTrace data consumption interface
cc [ flag... ] file... -ldtrace [ library... ] #include <dtrace.h> typedef int dtrace_consume_probe_f(const dtrace_probedata_t *, void *); typedef int dtrace_consume_rec_f(const dtrace_probedata_t *, const dtrace_recdesc_t *, void *); int dtrace_consume(dtrace_hdl_t *dtp, FILE *fp, dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg) int dtrace_status(dtrace_hdl_t *dtp)
The dtrace_consume() function is called to consume data from the principal buffers. This function takes the following arguments:
DTrace handle returned by the dtrace_open(3DTRACE) function.
File pointer where output is written.
Pointer to a function that processes an enabling control block (ECB). An ECB is a clause from a D program associated with the enabled probe.
Pointer to a function that processes individual records from the ECB.
User-defined argument to be passed to the pf and rf pointers. See the Usage section for more information on these two callback functions.
The dtrace_status() function is called to determine the status of the running DTrace instance. This function takes the following argument:
DTrace handle returned by the dtrace_open(3DTRACE) function.
The dtrace_consume() function returns 0.
On successful completion, the dtrace_status() function returns one of the following values:
No status; not yet time
Status okay
exit() function was called; tracing stopped
Fill buffer filled; tracing stopped
Tracing already stopped
Otherwise the functions return -1 and set the DTrace error number to indicate the reason for the failure. See the dtrace_errno(3DTRACE) man page for more information.
The dtrace_consume() function will fail if:
The dtp argument is NULL.
The system is unable to copy data out of the kernel.
If the buffer policy is ring, the dtrace_consume() function was called before the D program exited.
The DTrace handle is not active because the dtrace_go(3DTRACE) function has not been called yet.
The system is unable to allocate memory to hold the data being copied out of the kernel.
The pf or rf pointer returned DTRACE_CONSUME_ABORT. See the Usage section for more information.
The pf or rf pointer returned a value other than DTRACE_CONSUME_THIS, DTRACE_CONSUME_NEXT, or DTRACE_CONSUME_ABORT.
The fp argument is NULL, and the libdtrace(3LIB) probe and record processing routines are being used, which means that pf and rf are returning DTRACE_CONSUME_THIS.
The dtrace_status() function will fail if:
dtp is NULL.
The system encountered an error in copying the status out of the kernel.
The callback function pf processes the data from an enabling control block (ECB). An ECB is a clause from a D program associated with the enabled probe. The information pertaining to this ECB is contained in the dtrace_probedata_t data structure. The dtpda_data member of this structure points to the raw data for the probe firing, while the dtpda_edesc member describes the probe firing.
typedef struct dtrace_probedata { dtrace_hdl_t *dtpda_handle; /* handle to DTrace library */ dtrace_eprobedesc_t *dtpda_edesc; /* enabled probe description */ dtrace_probedesc_t *dtpda_pdesc; /* probe description */ processorid_t dtpda_cpu; /* CPU for data */ caddr_t dtpda_data; /* pointer to raw data */ dtrace_flowkind_t dtpda_flow; /* flow kind */ const char *dtpda_prefix; /* recommended flow prefix */ int dtpda_indent; /* recommended flow indent */ } dtrace_probedata_t;
typedef struct dtrace_eprobedesc { dtrace_epid_t dtepd_epid; /* enabled probe ID */ dtrace_id_t dtepd_probeid; /* probe ID */ uint64_t dtepd_uarg; /* library argument */ uint32_t dtepd_size; /* total size */ int dtepd_nrecs; /* number of records */ dtrace_recdesc_t dtepd_rec[1]; /* records themselves */ } dtrace_eprobedesc_t;
The dtepd_rec array contains descriptions of the records in this ECB. The dtrace_recdesc_t structure describes each individual record in the dtepd_rec array.
typedef struct dtrace_recdesc { dtrace_actkind_t dtrd_action; /* kind of action */ uint32_t dtrd_size; /* size of record */ uint32_t dtrd_offset; /* offset in ECB's data */ uint16_t dtrd_alignment; /* required alignment */ uint16_t dtrd_format; /* format, if any */ uint64_t dtrd_arg; /* action argument */ uint64_t dtrd_uarg; /* user argument */ } dtrace_recdesc_t;
The callback function rf processes the data from an individual record. The arguments to rf include both the dtrace_probedata_t and the dtrace_recdesc_t data types for this individual record.
The callback functions pf and rf return one of the following values:
Error while processing
Consume this probe or record
Advance to next probe or record
Abort consumption
If the callback function returns the value, DTRACE_CONSUME_THIS, the libdtrace(3LIB) function processes the ECB or the record internally. If the callback function returns the value, DTRACE_CONSUME_NEXT, the libdtrace(3LIB) function does not process the ECB or record.
The following example demonstrates how you can use the dtrace_consume() and dtrace_status() functions, and consume individual records with the dtrace_consume_rec_f() callback function. See the dtrace_printf_create(3DTRACE) man page for an example of consuming an ECB with the dtrace_consume_probe_f() argument.
#include <dtrace.h> #include <stdio.h> #include <stdlib.h> static dtrace_hdl_t *g_dtp; static uint32_t g_status; static char *g_prog = "" "BEGIN" "{" " trace(\"Hello, world!\\n\");" " exit(0);" "}"; static void fatal(const char *fmt, ...) { va_list ap; va_start(ap, fmt); (void) vfprintf(stderr, fmt, ap); if (fmt[strlen(fmt) - 1] != '\n') (void) fprintf(stderr, ": %s\n", dtrace_errmsg(g_dtp, dtrace_errno(g_dtp))); exit(EXIT_FAILURE); } static int chewrec(const dtrace_probedata_t *data, const dtrace_recdesc_t *rec, void *arg) { dtrace_actkind_t act; uintptr_t addr; if (rec == NULL) return (DTRACE_CONSUME_NEXT); act = rec->dtrd_action; addr = (uintptr_t)data->dtpda_data; if (act == DTRACEACT_DIFEXPR) { /* * g_prog only traces a string, so this is not * generic. */ printf("%s\n", (char *)addr); return (DTRACE_CONSUME_NEXT); } if (act == DTRACEACT_EXIT) { g_status = *((uint32_t *)addr); return (DTRACE_CONSUME_NEXT); } return (DTRACE_CONSUME_THIS); } static int chew(const dtrace_probedata_t *data, void *arg) { return (DTRACE_CONSUME_THIS); } int main() { dtrace_prog_t *prog; dtrace_proginfo_t info; int err; if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) fatal("cannot open dtrace library: %s\n", dtrace_errmsg(NULL, err)); if ((prog = dtrace_program_strcompile(g_dtp, g_prog, DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) fatal("invalid program"); if (dtrace_program_exec(g_dtp, prog, &info) == -1) fatal("failed to enable probes"); if (dtrace_setopt(g_dtp, "bufsize", "512k") == -1) fatal("failed to set bufsize"); if (dtrace_go(g_dtp) != 0) fatal("dtrace_go()"); while (1) { int done = 0; dtrace_sleep(g_dtp); switch (dtrace_status(g_dtp)) { case DTRACE_STATUS_EXITED: case DTRACE_STATUS_FILLED: case DTRACE_STATUS_STOPPED: done = 1; break; case DTRACE_STATUS_NONE: case DTRACE_STATUS_OKAY: break; default: fatal("processing aborted"); } if (dtrace_consume(g_dtp, stdout, chew, chewrec, NULL) == -1) fatal("dtrace_consume()"); if (done) break; } if (dtrace_stop(g_dtp) == -1) fatal("dtrace_stop()"); dtrace_close(g_dtp); printf("D program exited with status %d\n", g_status); return (0); }
See attributes(7) for descriptions of the following attributes:
|
libdtrace(3LIB), dtrace_errno(3DTRACE), dtrace_sleep(3DTRACE)