Gaopeng Chen - Sun China
2007-Mar-30 09:00 UTC
[dtrace-discuss] How to monitor and dump a dynamic buffer?
Hi experts,
I''d like to use dtrace to monitor a buffer and dump it. But the
buffer''s
length is variable. The word "for" is not supported yet, so that I
have
to use the following workaround.
However, for multi-threads and large buffer, the output of data may be
out of order. that is, the data of two buffers will be printed with
overlap. I''ve ever tried to use a increasing buffer array(such as,
pdata[k++] = mblk for each entry) to record and print the buffers
sequentially. But it would eat up the dtrace buffer soon and it doesn''t
work for multi-core system since the callback entry is not protected.
Is there any way to lock the system when entering callback entry? Is it
possible to print the whole buffer in position (A)? Just like copyout,
it can copy a buffer to an address, can I write a similar function to
print the buffer to screen? Thanks.
::hid_interrupt_pipe_callback:entry
{
req = (usb_intr_req_t *)arg1;
mblk = req->intr_data;
lens = req->intr_len;
data = (uint8_t *)mblk->b_rptr;
i = 0;
/* what a pity that "for" is not supported. <= (A)
for (i = 0 ; i < lens; i++)
printf("%x ", mblk->b_rptr[i]);
*/
}
::hid_interrupt_pipe_callback:return
{
lens = 0;
printf("\n");
}
entry,return
/lens > 0 && i < lens/
{
printf("0x%02x ", mblk->b_rptr[i]);
i++;
}
--
Best Regards,
GaoPeng Chen
Call: +86-10-62673005
Ext: x82005
Sun Microsystem Inc. China
Chip Bennett
2007-Mar-30 17:10 UTC
[dtrace-discuss] How to monitor and dump a dynamic buffer?
Since the trace record for a single probe clause is fixed length, here
are the only ways that I know to record trace data that varies in length:
1. Use multiple probe clauses for the same probe, and check for the
presence of the variable portions with predicates. Since all of
the clauses for one probe execute in order, they should all be
strung together in one trace buffer. Multiple threads on
different processors will be recorded in different trace buffers,
and then displayed one at a time by the DTrace command.
2. Record the maximum length every time, but also record something
that tells you how much of the trace record is real data. You
could use tracemem to record the maximum. If storage for original
data is dynamic, and accessing the maximum could lead to access
violations, then you could declare a thread-local scalar array to
be the maximum length, and then copy your data to it using a bunch
of conditional operators in a creative fashion. This should be as
"order safe" as the previous method. BTW: you can change the
string lengths from the default 256 at the start of your DTrace
run, and then stuff a string with trace output one sub-string at a
time with a whole bunch of conditional expressions, put a NULL
character at the varying string-end, and then trace the string.
The whole string will get recorded in the buffer, but the DTrace
command will only display up to the NULL character.
3. Do something like what you are doing now and utilize other probe
events to get the data recorded. You''re still going to need to
know the maximum length, because you need to copy the data to a
DTrace variable, since the original data is vulnerable to being
overwritten. However, you might consider using a probe for which
you have control over the firing so that you are not causing a lot
of unnecessary probe events. For example, you could write a short
C program, one that is started with the -c option and receives
piped data from the other which you call using "system" to pass
the number of iterations of a subroutine to call. In your DTrace
script, you have a PID probe for that function which handles the
extended part of the buffer. This method is not the least bit
order safe, so you may need to tag each trace record with order
data, and then reconstruct it with a post-processing script.
I''m not sure what kind of lock you have in mind. You obviously
can''t
stop the system, because then your probe clauses wouldn''t be executing
any more to get things restarted. "chill" will pause the system
momentarily, but, again, nothing happens to get your data handling
completed while the system is chilled.
Chip
Gaopeng Chen - Sun China wrote:> Hi experts,
>
> I''d like to use dtrace to monitor a buffer and dump it. But the
buffer''s
> length is variable. The word "for" is not supported yet, so that
I have
> to use the following workaround.
>
> However, for multi-threads and large buffer, the output of data may be
> out of order. that is, the data of two buffers will be printed with
> overlap. I''ve ever tried to use a increasing buffer array(such as,
> pdata[k++] = mblk for each entry) to record and print the buffers
> sequentially. But it would eat up the dtrace buffer soon and it
doesn''t
> work for multi-core system since the callback entry is not protected.
>
> Is there any way to lock the system when entering callback entry? Is it
> possible to print the whole buffer in position (A)? Just like copyout,
> it can copy a buffer to an address, can I write a similar function to
> print the buffer to screen? Thanks.
>
>
> ::hid_interrupt_pipe_callback:entry
> {
> req = (usb_intr_req_t *)arg1;
> mblk = req->intr_data;
> lens = req->intr_len;
>
> data = (uint8_t *)mblk->b_rptr;
> i = 0;
>
> /* what a pity that "for" is not supported. <= (A)
> for (i = 0 ; i < lens; i++)
> printf("%x ", mblk->b_rptr[i]);
> */
> }
>
> ::hid_interrupt_pipe_callback:return
> {
> lens = 0;
> printf("\n");
> }
>
> entry,return
> /lens > 0 && i < lens/
> {
> printf("0x%02x ", mblk->b_rptr[i]);
> i++;
> }
>
>
>
>
Gaopeng Chen - Sun China
2007-Apr-02 03:00 UTC
[dtrace-discuss] How to monitor and dump a dynamic buffer?
Firstly, thanks for great help. I still have some questions. On Sat, 2007-03-31 at 01:10, Chip Bennett wrote:> Since the trace record for a single probe clause is fixed length, here > are the only ways that I know to record trace data that varies in length: > > 1. Use multiple probe clauses for the same probe, and check for theI don''t understand well about this. Since the buffer length is variable and the address is from args, how many probe clauses should be defined?> presence of the variable portions with predicates. Since all of > the clauses for one probe execute in order, they should all be > strung together in one trace buffer. Multiple threads on > different processors will be recorded in different trace buffers, > and then displayed one at a time by the DTrace command. > 2. Record the maximum length every time, but also record something > that tells you how much of the trace record is real data. You > could use tracemem to record the maximum. If storage for original > data is dynamic, and accessing the maximum could lead to access > violations, then you could declare a thread-local scalar array to > be the maximum length, and then copy your data to it using a bunch > of conditional operators in a creative fashion. This should be asThat may work. But the buffer I want to dump has a big range, from 0 to several KB. So it''s not convenient to use tracemem here. BTW, What I monitor is not a string buffer, it may includes many zeroes.> "order safe" as the previous method. BTW: you can change the > string lengths from the default 256 at the start of your DTrace > run, and then stuff a string with trace output one sub-string at a > time with a whole bunch of conditional expressions, put a NULL > character at the varying string-end, and then trace the string. > The whole string will get recorded in the buffer, but the DTrace > command will only display up to the NULL character. > 3. Do something like what you are doing now and utilize other probe > events to get the data recorded. You''re still going to need to > know the maximum length, because you need to copy the data to a > DTrace variable, since the original data is vulnerable to being > overwritten. However, you might consider using a probe for which > you have control over the firing so that you are not causing a lot > of unnecessary probe events. For example, you could write a short > C program, one that is started with the -c option and receives > piped data from the other which you call using "system" to pass > the number of iterations of a subroutine to call. In your DTrace > script, you have a PID probe for that function which handles the > extended part of the buffer. This method is not the least bit > order safe, so you may need to tag each trace record with order > data, and then reconstruct it with a post-processing script.Yes, this may be a good idea if dtrace copyout() can copy the buffer to user space. Thus the data can be processed in the application. I''ll have a try.> > I''m not sure what kind of lock you have in mind. You obviously can''t > stop the system, because then your probe clauses wouldn''t be executing > any more to get things restarted. "chill" will pause the system > momentarily, but, again, nothing happens to get your data handling > completed while the system is chilled.What I want is not lock the whole system , it''s just to make the probe called serially like the following. So that I have enough time to process the data buffer sequentially when there are multiple processors. ::hid_interrupt_pip_callback:entry { mutex_enter(...); ... mutex_exit(...); }> > Chip > > > Gaopeng Chen - Sun China wrote: > > Hi experts, > > > > I''d like to use dtrace to monitor a buffer and dump it. But the buffer''s > > length is variable. The word "for" is not supported yet, so that I have > > to use the following workaround. > > > > However, for multi-threads and large buffer, the output of data may be > > out of order. that is, the data of two buffers will be printed with > > overlap. I''ve ever tried to use a increasing buffer array(such as, > > pdata[k++] = mblk for each entry) to record and print the buffers > > sequentially. But it would eat up the dtrace buffer soon and it doesn''t > > work for multi-core system since the callback entry is not protected. > > > > Is there any way to lock the system when entering callback entry? Is it > > possible to print the whole buffer in position (A)? Just like copyout, > > it can copy a buffer to an address, can I write a similar function to > > print the buffer to screen? Thanks. > > > > > > ::hid_interrupt_pipe_callback:entry > > { > > req = (usb_intr_req_t *)arg1; > > mblk = req->intr_data; > > lens = req->intr_len; > > > > data = (uint8_t *)mblk->b_rptr; > > i = 0; > > > > /* what a pity that "for" is not supported. <= (A) > > for (i = 0 ; i < lens; i++) > > printf("%x ", mblk->b_rptr[i]); > > */ > > } > > > > ::hid_interrupt_pipe_callback:return > > { > > lens = 0; > > printf("\n"); > > } > > > > entry,return > > /lens > 0 && i < lens/ > > { > > printf("0x%02x ", mblk->b_rptr[i]); > > i++; > > } > > > > > > > >-- Best Regards, GaoPeng Chen Call: +86-10-62673005 Ext: x82005 Sun Microsystem Inc. China
Chip Bennett
2007-Apr-02 06:24 UTC
[dtrace-discuss] How to monitor and dump a dynamic buffer?
Gaopeng Chen - Sun China wrote:> > > I don''t understand well about this. Since the buffer length is variable > and the address is from args, how many probe clauses should be defined? >If you want to control the length down to the byte, you''d need a probe clause for every byte: probably not a good choice for you.> > That may work. But the buffer I want to dump has a big range, from 0 to > several KB. So it''s not convenient to use tracemem here. BTW, What I > monitor is not a string buffer, it may includes many zeroes. >How about a compromise between multiple clauses and tracemem. If you traced 128 bytes per probe clause, you could get by with around 16 clauses, right? Also, with regard to using printf, I was thinking you might convert the binary value to displayable hex, when you put it in the string. There''s no function to do that (I don''t think), but you could do it with a little base 16 math and a string constant with hex digits.> > What I want is not lock the whole system , it''s just to make the probe > called serially like the following. So that I have enough time to > process the data buffer sequentially when there are multiple processors. > > ::hid_interrupt_pip_callback:entry > { > mutex_enter(...); > > ... > > mutex_exit(...); > } >Probe clauses run in kernel mode with interrupts disabled. They run in the context of the probe that fired, so if the caller of "hid_interrupt_pip_callback" were allowed to block on a mutex, the results could be disastrous to the system. This is why probe clauses have no flow control, and I think the reason they have fixed length trace records: make it simple and fast. Chip
Gaopeng Chen - Sun China
2007-Apr-02 10:24 UTC
[dtrace-discuss] How to monitor and dump a dynamic buffer?
I just tried to using copyout() to copy the buffer to an external
application, but it failed because there''s a big latency between kernel
and user space. The buffer has been invalid when the probe falls into
the user space. Multiple tracemem() is not what I prefer, for I must
analyze and re-organize the data and display them. tracemem() will give
much extra workload. I''m considering to record the buffer in dtrace and
then copyout to the user process, but it doesn''t work.
char pdata[100];
::hid_interrupt_pipe_callback:entry
{
req = (usb_intr_req_t *)arg1; mblk = req->intr_data;
lens = req->intr_len;
bcopy((uintptr_t)req->intr_data->b_rptr, pdata, size);
}
the error message is,
dtrace: error on enabled probe ID 2 (ID 38953:
fbt:hid:hid_interrupt_pipe_callback:entry): invalid address (0x4) in
action #6 at DIF offset 7
The guide says, src should lie outside of scratch memory, and dst should
lie inside of it. I don''t understand why it fails here?
Oops.., does libdtrace help? Seems it provides private interfaces and
lack of manuals.
--
Best Regards,
GaoPeng Chen
Call: +86-10-62673005
Ext: x82005
Sun Microsystem Inc. China