One potential use for speculations is to highlight a particular
code path. The following example shows the entire code path under
the open()
system call when the call fails.
Type the following source code and save it in a file named
specopen.d
:
#!/usr/sbin/dtrace -Fs syscall::open:entry { /* * The call to speculation() creates a new speculation. If this fails, * dtrace will generate an error message indicating the reason for * the failed speculation(), but subsequent speculative tracing will be * silently discarded. */ self->spec = speculation(); speculate(self->spec); /* * Because this printf() follows the speculate(), it is being * speculatively traced; it will only appear in the data buffer if the * speculation is subsequently committed. */ printf("%s", copyinstr(arg0)); } syscall::open:return /self->spec/ { /* * To balance the output with the -F option, we want to be sure that * every entry has a matching return. Because we speculated the * open entry above, we want to also speculate the open return. * This is also a convenient time to trace the errno value. */ speculate(self->spec); trace(errno); } syscall::open:return /self->spec && errno != 0/ { /* * If errno is non-zero, we want to commit the speculation. */ commit(self->spec); self->spec = 0; } syscall::open:return /self->spec && errno == 0/ { /* * If errno is not set, we discard the speculation. */ discard(self->spec); self->spec = 0; }
Running the previous script produces output similar to the following:
# ./specopen.d
dtrace: script ’./specopen.d’ matched 4 probes
CPU FUNCTION
1 => open /var/ld/ld.config
1 <= open 2
1 => open /images/UnorderedList16.gif
1 <= open 4
...