Hi, some (way too long) time ago I asked about SDT in C++ applications (the thread is this one http://docs.sun.com/app/docs/doc/817-6223/6mlkidlms?a=view, if you''re interested). Back then I already had a rather messy script that could help in creating probe macros that work with C++ applications. Finally, I''ve came around to somewhat improve those scripts (hardly less messy ;-), but more general usable I hope), so I though I''d post them here if someone is interested or has any comments. As a quickstart, just extract the tar file and change into "dtcxx/test", there run "make test". More gibberish can be found in "dtcxx/README". Cheers, Christian This message posted from opensolaris.org -------------- next part -------------- A non-text attachment was scrubbed... Name: dtcxx.tar.bz2 Type: application/x-bzip2 Size: 6788 bytes Desc: not available URL: <http://mail.opensolaris.org/pipermail/dtrace-discuss/attachments/20060120/85a00fde/attachment.bin>
> http://docs.sun.com/app/docs/doc/817-6223/6mlkidlms?aDang, this is of course the wrong URL, it should have been: http://www.opensolaris.org/jive/thread.jspa?messageID=7191 Sorry about that. Cheers, Christian This message posted from opensolaris.org
Hey Christian, This is very cool and has inspired me to roll this functionality into dtrace(1M) (something I''ve actually been talking about for quiet a while). I''d like some input on what the generated header file should look like. I''ve attached the output of my DTrace changes as well as the output of Christian''s dtcxx script on usr/src/lib/libc/port/threads/plockstat.d and I''d welcome any comments. Here''s a taste of what I''m proposing in case you''re too lazy to examine the attachment: ---8<--- #ifndef _PLOCKSTAT_H #define _PLOCKSTAT_H #ifdef __cplusplus extern "C" { #endif #define PLOCKSTAT_MUTEX_ACQUIRE(arg0, arg1, arg2) \ plockstat_mutex__acquire(arg0, arg1, arg2) extern void __dtrace_plockstat___mutex__acquire(mutex_t *, int, int); #ifdef __cplusplus } #endif #endif /* _PLOCKSTAT_H */ ---8<--- Adam On Fri, Jan 20, 2006 at 07:31:34AM -0800, Christian Klutz wrote:> Back then I already had a rather messy script that could help in creating probe macros that work with C++ applications. Finally, I''ve came around to somewhat improve those scripts (hardly less messy ;-), but more general usable I hope), so I though I''d post them here if someone is interested or has any comments. > > As a quickstart, just extract the tar file and change into "dtcxx/test", there run "make test". More gibberish can be found in "dtcxx/README". > > Cheers, > Christian-- Adam Leventhal, Solaris Kernel Development http://blogs.sun.com/ahl -------------- next part -------------- /* * Generated by dtrace(1M). */ #ifndef _PLOCKSTAT_H #define _PLOCKSTAT_H #ifdef __cplusplus extern "C" { #endif #define PLOCKSTAT_MUTEX_ACQUIRE(arg0, arg1, arg2) \ plockstat_mutex__acquire(arg0, arg1, arg2) #define PLOCKSTAT_MUTEX_BLOCK(arg0) \ plockstat_mutex__block(arg0) #define PLOCKSTAT_MUTEX_BLOCKED(arg0, arg1) \ plockstat_mutex__blocked(arg0, arg1) #define PLOCKSTAT_MUTEX_ERROR(arg0, arg1) \ plockstat_mutex__error(arg0, arg1) #define PLOCKSTAT_MUTEX_RELEASE(arg0, arg1) \ plockstat_mutex__release(arg0, arg1) #define PLOCKSTAT_MUTEX_SPIN(arg0) \ plockstat_mutex__spin(arg0) #define PLOCKSTAT_MUTEX_SPUN(arg0, arg1, arg2) \ plockstat_mutex__spun(arg0, arg1, arg2) #define PLOCKSTAT_RW_ACQUIRE(arg0, arg1) \ plockstat_rw__acquire(arg0, arg1) #define PLOCKSTAT_RW_BLOCK(arg0, arg1) \ plockstat_rw__block(arg0, arg1) #define PLOCKSTAT_RW_BLOCKED(arg0, arg1, arg2) \ plockstat_rw__blocked(arg0, arg1, arg2) #define PLOCKSTAT_RW_ERROR(arg0, arg1, arg2) \ plockstat_rw__error(arg0, arg1, arg2) #define PLOCKSTAT_RW_RELEASE(arg0, arg1) \ plockstat_rw__release(arg0, arg1) extern void __dtrace_plockstat___mutex__acquire(mutex_t *, int, int); extern void __dtrace_plockstat___mutex__block(mutex_t *); extern void __dtrace_plockstat___mutex__blocked(mutex_t *, int); extern void __dtrace_plockstat___mutex__error(mutex_t *, int); extern void __dtrace_plockstat___mutex__release(mutex_t *, int); extern void __dtrace_plockstat___mutex__spin(mutex_t *); extern void __dtrace_plockstat___mutex__spun(mutex_t *, int, int); extern void __dtrace_plockstat___rw__acquire(rwlock_t *, int); extern void __dtrace_plockstat___rw__block(rwlock_t *, int); extern void __dtrace_plockstat___rw__blocked(rwlock_t *, int, int); extern void __dtrace_plockstat___rw__error(rwlock_t *, int, int); extern void __dtrace_plockstat___rw__release(rwlock_t *, int); #ifdef __cplusplus } #endif #endif /* _PLOCKSTAT_H */ -------------- next part -------------- /* * @(#) plockstat.hpp -- generated, do not edit. */ #ifndef DTRACE_CXX_PLOCKSTAT_43D8235F_HPP #define DTRACE_CXX_PLOCKSTAT_43D8235F_HPP extern "C" void __dtrace_plockstat___mutex__blocked( unsigned long, unsigned long); #define DTRACE_CXX_PROBE_plockstat_mutex__blocked(a0, a1) \ __dtrace_plockstat___mutex__blocked( \ (unsigned long)a0, \ (unsigned long)a1); extern "C" void __dtrace_plockstat___rw__error( unsigned long, unsigned long, unsigned long); #define DTRACE_CXX_PROBE_plockstat_rw__error(a0, a1, a2) \ __dtrace_plockstat___rw__error( \ (unsigned long)a0, \ (unsigned long)a1, \ (unsigned long)a2); extern "C" void __dtrace_plockstat___mutex__release( unsigned long, unsigned long); #define DTRACE_CXX_PROBE_plockstat_mutex__release(a0, a1) \ __dtrace_plockstat___mutex__release( \ (unsigned long)a0, \ (unsigned long)a1); extern "C" void __dtrace_plockstat___rw__block( unsigned long, unsigned long); #define DTRACE_CXX_PROBE_plockstat_rw__block(a0, a1) \ __dtrace_plockstat___rw__block( \ (unsigned long)a0, \ (unsigned long)a1); extern "C" void __dtrace_plockstat___mutex__spun( unsigned long, unsigned long, unsigned long); #define DTRACE_CXX_PROBE_plockstat_mutex__spun(a0, a1, a2) \ __dtrace_plockstat___mutex__spun( \ (unsigned long)a0, \ (unsigned long)a1, \ (unsigned long)a2); extern "C" void __dtrace_plockstat___rw__acquire( unsigned long, unsigned long); #define DTRACE_CXX_PROBE_plockstat_rw__acquire(a0, a1) \ __dtrace_plockstat___rw__acquire( \ (unsigned long)a0, \ (unsigned long)a1); extern "C" void __dtrace_plockstat___rw__blocked( unsigned long, unsigned long, unsigned long); #define DTRACE_CXX_PROBE_plockstat_rw__blocked(a0, a1, a2) \ __dtrace_plockstat___rw__blocked( \ (unsigned long)a0, \ (unsigned long)a1, \ (unsigned long)a2); extern "C" void __dtrace_plockstat___mutex__acquire( unsigned long, unsigned long, unsigned long); #define DTRACE_CXX_PROBE_plockstat_mutex__acquire(a0, a1, a2) \ __dtrace_plockstat___mutex__acquire( \ (unsigned long)a0, \ (unsigned long)a1, \ (unsigned long)a2); extern "C" void __dtrace_plockstat___mutex__spin( unsigned long); #define DTRACE_CXX_PROBE_plockstat_mutex__spin(a0) \ __dtrace_plockstat___mutex__spin( \ (unsigned long)a0); extern "C" void __dtrace_plockstat___mutex__block( unsigned long); #define DTRACE_CXX_PROBE_plockstat_mutex__block(a0) \ __dtrace_plockstat___mutex__block( \ (unsigned long)a0); extern "C" void __dtrace_plockstat___mutex__error( unsigned long, unsigned long); #define DTRACE_CXX_PROBE_plockstat_mutex__error(a0, a1) \ __dtrace_plockstat___mutex__error( \ (unsigned long)a0, \ (unsigned long)a1); extern "C" void __dtrace_plockstat___rw__release( unsigned long, unsigned long); #define DTRACE_CXX_PROBE_plockstat_rw__release(a0, a1) \ __dtrace_plockstat___rw__release( \ (unsigned long)a0, \ (unsigned long)a1); #endif
Hi, On 1/26/06, Adam Leventhal <ahl at eng.sun.com> wrote:> Hey Christian, > > This is very cool and has inspired me to roll this functionality into > dtrace(1M)Thanks. Although this was not the primary intent, I''m glad to see that happening :-)> (something I''ve actually been talking about for quiet a while).Which actually "inspired" me to put together my stuff ;-)> > I''d like some input on what the generated header file should look like. > I''ve attached the output of my DTrace changes as well as the output of > Christian''s dtcxx script on usr/src/lib/libc/port/threads/plockstat.d and > I''d welcome any comments. > > Here''s a taste of what I''m proposing in case you''re too lazy to examine the > attachment: > > ---8<--- > > #ifndef _PLOCKSTAT_H > #define _PLOCKSTAT_H > > #ifdef __cplusplus > extern "C" { > #endif > > #define PLOCKSTAT_MUTEX_ACQUIRE(arg0, arg1, arg2) \ > plockstat_mutex__acquire(arg0, arg1, arg2)Hmm, either you forgot the "__dtrace_" prefix here, or I didn''t quite understand it - which is entirely possible ;-) Then, concerning the name of the macro; wouldn''t you think it would be a good idea to use some prefix for that as well, like DTRACE_ or so [1]? Just in case you define your provider/probe names to be very close to existing stuff and thus would risk name collisions. Getting really fancy, one could even think of an option to dtrace(1M) to specify this prefix.> > extern void __dtrace_plockstat___mutex__acquire(mutex_t *, int, int);"Typed" parameters - this is a good idea I think. Concerning the leading underscores, I think some will argue that in C++ such names are reserved for the implementation [2] and should be avoided. Personally I wouldn''t think that this has much practical relevance, just to be "clean" you could maybe choose to strip the leading underscores - if that doesn''t break some compatibility with existing <sys/sdt.h> (the sdt_prefix variable?).> > #ifdef __cplusplus > } > #endif > > #endif /* _PLOCKSTAT_H */ > > ---8<---In general I think, not to say you hadn''t already intended that, it should also be possible to specify the name of the generated header file on dtrace(1M)''s command line (e.g. plockstat.d => gen_plockstat.h or whatever), again to avoid conflicts with other stuff or simply establish some build-scheme for generated vs. hand-crafted sources. Other than that I think it is pretty neat. Cheers, Christian [1] Granted my choice of "DTRACE_CXX_PROBE_" is a bit verbose ;-) [2] Can''t remember where, but I think Bryan Cantrill has already responded to this in some forum, arguing that DTrace is C++ anyway - rightfully so, back then.> > Adam > > On Fri, Jan 20, 2006 at 07:31:34AM -0800, Christian Klutz wrote: > > Back then I already had a rather messy script that could help in creating probe macros that work with C++ applications. Finally, I''ve came around to somewhat improve those scripts (hardly less messy ;-), but more general usable I hope), so I though I''d post them here if someone is interested or has any comments. > > > > As a quickstart, just extract the tar file and change into "dtcxx/test", there run "make test". More gibberish can be found in "dtcxx/README". > > > > Cheers, > > Christian > > -- > Adam Leventhal, Solaris Kernel Development http://blogs.sun.com/ahl > > >
On Thu, Jan 26, 2006 at 07:03:36AM +0100, cklutz at gmail.com wrote:> > #define PLOCKSTAT_MUTEX_ACQUIRE(arg0, arg1, arg2) \ > > plockstat_mutex__acquire(arg0, arg1, arg2) > > Hmm, either you forgot the "__dtrace_" prefix here, or I didn''t quite > understand it - which is entirely possible ;-)D''oh -- somehow I grabbed some old output. Indeed there should be an __dtrace_ prefix. I''ve attached the updated output.> Then, concerning the name of the macro; wouldn''t you think it would be > a good idea to use some prefix for that as well, like DTRACE_ or so > [1]? Just in case you define your provider/probe names to be very > close to existing stuff and thus would risk name collisions. Getting > really fancy, one could even think of an option to dtrace(1M) to > specify this prefix.I was debating about this and decided to go with the shorter form -- people can always redefine/undef to get exactly what they want. The specific problem I hit was that when I went to try this out in usr/src/lib/libc/port/threads/synch.c I found that the longer version ended up spilling me perilously close to 80 columns (around line 1535).> > extern void __dtrace_plockstat___mutex__acquire(mutex_t *, int, int); > > "Typed" parameters - this is a good idea I think.Agreed -- I found that it was helpful for detecting problems earlier, and helped to avoid mysterious D script failures.> Concerning the leading underscores, I think some will argue that in > C++ such names are reserved for the implementation [2] and should be > avoided. Personally I wouldn''t think that this has much practical > relevance, just to be "clean" you could maybe choose to strip the > leading underscores - if that doesn''t break some compatibility with > existing <sys/sdt.h> (the sdt_prefix variable?).We in the kernel group tend to think of that "reserved" namespace as being reserved for us :) That''s probably not scrictly the case, but I feel pretty comfortable with the prefix. The nice thing about this header generation stuff is that we can easily change the prefix and we just have to deliver a new libdtrace and not a new sdt.h (possibly).> In general I think, not to say you hadn''t already intended that, it > should also be possible to specify the name of the generated header > file on dtrace(1M)''s command line (e.g. plockstat.d => gen_plockstat.h > or whatever), again to avoid conflicts with other stuff or simply > establish some build-scheme for generated vs. hand-crafted sources.Right, it will use the -o <filename> option that already works for various other command modes.> Other than that I think it is pretty neat.Thanks for the feedback. Adam -- Adam Leventhal, Solaris Kernel Development http://blogs.sun.com/ahl -------------- next part -------------- /* * Generated by dtrace(1M). */ #ifndef _PLOCKSTAT_H #define _PLOCKSTAT_H #ifdef __cplusplus extern "C" { #endif #define PLOCKSTAT_MUTEX_ACQUIRE(arg0, arg1, arg2) \ __dtrace_plockstat___mutex__acquire(arg0, arg1, arg2) #define PLOCKSTAT_MUTEX_BLOCK(arg0) \ __dtrace_plockstat___mutex__block(arg0) #define PLOCKSTAT_MUTEX_BLOCKED(arg0, arg1) \ __dtrace_plockstat___mutex__blocked(arg0, arg1) #define PLOCKSTAT_MUTEX_ERROR(arg0, arg1) \ __dtrace_plockstat___mutex__error(arg0, arg1) #define PLOCKSTAT_MUTEX_RELEASE(arg0, arg1) \ __dtrace_plockstat___mutex__release(arg0, arg1) #define PLOCKSTAT_MUTEX_SPIN(arg0) \ __dtrace_plockstat___mutex__spin(arg0) #define PLOCKSTAT_MUTEX_SPUN(arg0, arg1, arg2) \ __dtrace_plockstat___mutex__spun(arg0, arg1, arg2) #define PLOCKSTAT_RW_ACQUIRE(arg0, arg1) \ __dtrace_plockstat___rw__acquire(arg0, arg1) #define PLOCKSTAT_RW_BLOCK(arg0, arg1) \ __dtrace_plockstat___rw__block(arg0, arg1) #define PLOCKSTAT_RW_BLOCKED(arg0, arg1, arg2) \ __dtrace_plockstat___rw__blocked(arg0, arg1, arg2) #define PLOCKSTAT_RW_ERROR(arg0, arg1, arg2) \ __dtrace_plockstat___rw__error(arg0, arg1, arg2) #define PLOCKSTAT_RW_RELEASE(arg0, arg1) \ __dtrace_plockstat___rw__release(arg0, arg1) extern void __dtrace_plockstat___mutex__acquire(mutex_t *, int, int); extern void __dtrace_plockstat___mutex__block(mutex_t *); extern void __dtrace_plockstat___mutex__blocked(mutex_t *, int); extern void __dtrace_plockstat___mutex__error(mutex_t *, int); extern void __dtrace_plockstat___mutex__release(mutex_t *, int); extern void __dtrace_plockstat___mutex__spin(mutex_t *); extern void __dtrace_plockstat___mutex__spun(mutex_t *, int, int); extern void __dtrace_plockstat___rw__acquire(rwlock_t *, int); extern void __dtrace_plockstat___rw__block(rwlock_t *, int); extern void __dtrace_plockstat___rw__blocked(rwlock_t *, int, int); extern void __dtrace_plockstat___rw__error(rwlock_t *, int, int); extern void __dtrace_plockstat___rw__release(rwlock_t *, int); #ifdef __cplusplus } #endif #endif /* _PLOCKSTAT_H */