Hi,
I am very new to DTrace, so I don''t know if this has been discussed
before.
I am trying to determine the last message issued by a proprietary event
dispatching library, to narrow down some code that appears to be hanging within
a new feature.
The message will be stored in a static unsigned character array in the event
dispatching library, but the address of this array is passed into a shared queue
reading function (thus the predicate in the ''get_message''
clauses. The queue I am interested in, is the only one, in the code, greater
than 200,000 bytes), so I can record the address on function entry and read it
on function return, as is recommended in the documentation.
However, I do not wish to display the message unless the dispatcher function has
not executed in the last second, so I need DTrace to store the data beyond the
end of a clause.
I record the size of the last message and the pointers to the data buffers, I am
interested in, in global variables, the values of which, can be displayed/used
in later clauses or even other probes, but the copied in data is all zeroes
outside the clause it was copied in.
I have read in the discussions, that the copyin uses scratch storage which is
cleared upon exiting the probe clause it was executed within and that bcopy will
only copy into scratch space, so to the question(s) I have been leading up to-
"Is it possible, for DTrace, to store data, between probes/clauses, that it
has read from user space, since it is likely that when I would actually need to
copyin the data, the address would be ''faulted''? If so, what
kind of storage should I use, global, thread, other?"
"If not, is it possible to copy a portion of scratch space into the area
that ''bcopy'' will copy out of, so that data is copied in from
user space and moved to this non-scratch space, then when you need it, it can be
copied back to scratch space and traced, otherwise it can be overwritten by the
next copyin"
Essentially, my current script is as follows (less all the printf''s
& tracemem''s I put in to track down why the data was always zero):
#!/usr/sbin/dtrace -qCs
struct M_QUEUE {
unsigned int first;
unsigned int next;
unsigned int size;
unsigned char *buffer;
};
dtrace:::BEGIN
{
printf("You can terminate the script by pressing ^C");
startup = timestamp;
}
pid$target::x_schedule:entry,
pid$target::x_schedule:return
{
called[probefunc, probename]++;
}
pid$target::get_message:entry
/ ((struct M_QUEUE *)copyin(arg0,sizeof(struct M_QUEUE)))->size >= 200000
/
{
self->queue = arg0;
self->grabCM = arg1;
}
pid$target::get_message:return
/ (((struct M_QUEUE *)copyin(self->queue,sizeof(struct M_QUEUE)))->size
>= 200000) && (arg1!=0) /
{
msgLength = arg1;
msgEntire = (unsigned char *)copyin(self->grabCM, sizeof(unsigned
char)*(msgLength));
}
profile:::tick-1sec
/ (called["x_schedule", "return"] == 0) /
{
printf("Event Dispatcher not called: script running for %d
seconds\n", (timestamp - startup)/1000000000 );
tracemem( msgEntire, 300 );
ustack();
exit(0);
}
profile:::tick-1sec
/ (called["x_schedule", "return"] != 0 ) /
{
called["x_schedule", "entry"] = 0;
called["x_schedule", "return"] = 0;
}
dtrace:::END
{
printf("DTracing terminated, after %d seconds\n", (timestamp -
startup)/1000000000 );
}
Also, I realise (now) that I could probably do the ''has the x_schedule
function executed'' using a count aggregation, but this is my first
DTrace script, so I will stick to the plain C forms I know :-)
Thanks,
Michael.
--
This message posted from opensolaris.org