Is it possible to write a dtrace script which can tell me the number of mblks, and total chain length, upon entry to a function (gldv3 nic driver''s xmit function). I naively tried to iterate over mp->b_cont, but there is no while or for in dtrace.. Eg, what I want to do is: for (pkt_size=0, count=0,bp = mp; bp != NULL; bp = bp->b_cont) { pkt_size += (int)(bp->b_wptr - bp->b_rptr); count++; } (if it makes any difference I''m using a mix of snv_b86 and snv_b90) Thanks, Drew -- This message posted from opensolaris.org
Andrew Gallatin writes:> Is it possible to write a dtrace script which can tell me the number of mblks, and total chain length, upon entry to a function (gldv3 nic driver''s xmit function). I naively tried to iterate over mp->b_cont, but there is no while or for in dtrace..Dtrace intentionally doesn''t have looping -- for safety reasons.> Eg, what I want to do is: > > for (pkt_size=0, count=0,bp = mp; bp != NULL; bp = bp->b_cont) {You could do something like this: fbt:mymodule:myfunc:entry /arg1 != 0/ { this->mp = (mblk_t *)arg1; this->size = this->mp->b_wptr - this->mp->b_rptr; } fbt:mymodule:myfunc:entry /this->mp && this->mp->b_cont/ { this->mp2 = this->mp->b_cont; this->size += this->mp2->b_wptr - this->mp2->b_rptr; } fbt:mymodule:myfunc:entry /this->mp2 && this->mp2->b_cont/ { this->mp3 = this->mp2->b_cont; this->size += this->mp3->b_wptr - this->mp3->b_rptr; } .... and repeat a few times to catch as many cases as you feel is necessary. (Perhaps add an assertion at the end to make sure you run out of b_conts in all of the cases of interest.) -- James Carlson, Solaris Networking <james.d.carlson at sun.com> Sun Microsystems / 35 Network Drive 71.232W Vox +1 781 442 2084 MS UBUR02-212 / Burlington MA 01803-2757 42.496N Fax +1 781 442 1677
Thanks! That seems to work. FWIW, recursion also seems to work. Eg: fbt::driver_send:entry /arg1 != 0/ { this->mp = (mblk_t *)arg1; this->size = this->mp->b_wptr - this->mp->b_rptr; this->count=1; } fbt::driver_send:entry /this->mp && this->mp->b_cont/ { this->mp = this->mp->b_cont; this->size += this->mp->b_wptr - this->mp->b_rptr; this->count++; } Thanks again, Drew -- This message posted from opensolaris.org
Andrew Gallatin writes:> Thanks! That seems to work.That''s cool. I didn''t even test it. ;-}> FWIW, recursion also seems to work. Eg:I don''t see the recursion here. Those two probe points will fire sequentially. The second one will _not_ loop, so what you''ve created with those two entries is something that''ll handle chains of length 1 and 2, but nothing longer. (Note that it''s customary to check for the first M_DATA message in the chain before counting up bytes, and I didn''t do that ...) -- James Carlson, Solaris Networking <james.d.carlson at sun.com> Sun Microsystems / 35 Network Drive 71.232W Vox +1 781 442 2084 MS UBUR02-212 / Burlington MA 01803-2757 42.496N Fax +1 781 442 1677
Andrew Gallatin wrote:> Thanks! That seems to work. > > FWIW, recursion also seems to work. Eg:can you explain a little what you mean by that? As I understand both DTrace and recursion, they don''t really mix. Michael> fbt::driver_send:entry > /arg1 != 0/ > { > this->mp = (mblk_t *)arg1; > this->size = this->mp->b_wptr - this->mp->b_rptr; > this->count=1; > } > > fbt::driver_send:entry > /this->mp && this->mp->b_cont/ > { > this->mp = this->mp->b_cont; > this->size += this->mp->b_wptr - this->mp->b_rptr; > this->count++; > }-- Michael Schuster http://blogs.sun.com/recursion Recursion, n.: see ''Recursion''
Just that that the second snippet seems to be rather recursive (this->mp = this->mp->b_cont) and it seems to work, and is a nice alternative to enumerating all the potential chains as was suggested. Maybe I''m thinking of things incorrectly.. Drew -- This message posted from opensolaris.org
Andrew Gallatin wrote:> Michael Schuster wrote: >> Andrew Gallatin wrote: >>> Thanks! That seems to work. >>> >>> FWIW, recursion also seems to work. Eg: >> >> can you explain a little what you mean by that? As I understand both >> DTrace and recursion, they don''t really mix. >> >> Michael >>> fbt::driver_send:entry >>> /arg1 != 0/ >>> { >>> this->mp = (mblk_t *)arg1; >>> this->size = this->mp->b_wptr - this->mp->b_rptr; >>> this->count=1; >>> } >>> >>> fbt::driver_send:entry >>> /this->mp && this->mp->b_cont/ >>> { >>> this->mp = this->mp->b_cont; >>> this->size += this->mp->b_wptr - this->mp->b_rptr; >>> this->count++; >>> } > > Just that that the second snippet seems to be rather > recursive (this->mp = this->mp->b_cont) and it seems > to work, and is a nice alternative to enumerating > all the potential chains as was suggested.can you show a concrete example, please? how do you know what this->size and this->count look like? Michael -- Michael Schuster http://blogs.sun.com/recursion Recursion, n.: see ''Recursion''
Andrew Gallatin writes:> Just that that the second snippet seems to be rather > recursive (this->mp = this->mp->b_cont) and it seems > to work, and is a nice alternative to enumerating > all the potential chains as was suggested. > > Maybe I''m thinking of things incorrectly..It''s not recursive; it''s sequential. The instructions are executed in the order they appear. There are no places where it jumps "backwards" or reconsiders an earlier probe point based on what a later one says. -- James Carlson, Solaris Networking <james.d.carlson at sun.com> Sun Microsystems / 35 Network Drive 71.232W Vox +1 781 442 2084 MS UBUR02-212 / Burlington MA 01803-2757 42.496N Fax +1 781 442 1677
OK, so recursion does not work, and the probe will fire only once. Drat. I''ll just have to put up with a script that looks like something I''d have flunked as a CS1 TA.. But if the language doesn''t support it, I guess there''s not much to do. Thanks again for your help, Drew -- This message posted from opensolaris.org
Andrew Gallatin writes:> OK, so recursion does not work, and the probe will fire only once. > Drat. I''ll just have to put up with a script that looks like something > I''d have flunked as a CS1 TA.. But if the language doesn''t support > it, I guess there''s not much to do.The thing to remember is that it''s intentional. The TA who passed remembers that the halting problem is undecidable (and also NP-hard but not NP-complete), and therefore it''s not possible to know whether a given D script (a program) containing loops would be safe (would ever halt). Since one of the fundamental rules of dtrace is that it''s safe to use, scripts that run forever cannot be allowed. -- James Carlson, Solaris Networking <james.d.carlson at sun.com> Sun Microsystems / 35 Network Drive 71.232W Vox +1 781 442 2084 MS UBUR02-212 / Burlington MA 01803-2757 42.496N Fax +1 781 442 1677
On Wed, Jun 11, 2008 at 08:31:45AM -0700, Andrew Gallatin wrote:> Just that that the second snippet seems to be rather > recursive (this->mp = this->mp->b_cont) and it seems > to work, and is a nice alternative to enumerating > all the potential chains as was suggested.Romantic notion, but no, it''s not. Your enabling control blocks (ECBs) are not reevaluated after the action is taken -- when you set this->mp to be this->mp->b_cont, it doesn''t mean that the predicate is reevaluated and the action re-taken. (After all, were the predicate reevaulated, just having a predicate that always evaluates to true would cause an infinite loop.) So you will have to manually unroll any such iteration that you wish to have -- which can still be made quite effective if the number of elements tends to be small... - Bryan -------------------------------------------------------------------------- Bryan Cantrill, Sun Microsystems Fishworks. http://blogs.sun.com/bmc
On Wed, Jun 11, 2008 at 11:45:05AM -0400, James Carlson wrote:> Andrew Gallatin writes: > > Just that that the second snippet seems to be rather > > recursive (this->mp = this->mp->b_cont) and it seems > > to work, and is a nice alternative to enumerating > > all the potential chains as was suggested. > > > > Maybe I''m thinking of things incorrectly.. > > It''s not recursive; it''s sequential. The instructions are executed in > the order they appear. There are no places where it jumps "backwards" > or reconsiders an earlier probe point based on what a later one says.What might seem recursive is that the same variable names work in each case. Think of this as "unrolled recursion."
> Since one of the fundamental rules of dtrace is that > it''s safe to use, > scripts that run forever cannot be allowed.I think there''s an arguable case for a flag to dtrace to allow loops. After all, if I''m root, there are plenty of things I can do to hose a box from the command line ( cat /dev/random | mdb -kw). Dtrace should be one of them :) Drew -- This message posted from opensolaris.org
Andrew Gallatin writes:> > Since one of the fundamental rules of dtrace is that > > it''s safe to use, > > scripts that run forever cannot be allowed. > > I think there''s an arguable case for a flag to dtrace to > allow loops. After all, if I''m root, there are plenty > of things I can do to hose a box from the command > line ( cat /dev/random | mdb -kw). Dtrace should > be one of them :)I think there''d have to be a new privilege constructed (not just "I''m root"), and the entire design of the internal representation would change, and the algorithms would change. It''d be a substantial undertaking ... but, well, it''s open source, so ... A much better approach, I think, would be to identify those cases that need special loop-like support, and add extensions to the language that allow you to express things in a safe way. In other words, add something like msgdsize(9F) (but using a known-safe implementation). -- James Carlson, Solaris Networking <james.d.carlson at sun.com> Sun Microsystems / 35 Network Drive 71.232W Vox +1 781 442 2084 MS UBUR02-212 / Burlington MA 01803-2757 42.496N Fax +1 781 442 1677