Re: [RFC] New markers description without format strings
Mathieu Desnoyers <[email protected]>
| Newsgroups | gmane.linux.kernel.tracing |
|---|---|
| Message-ID | <20070508153014.GA26164@Krystal> |
Hi Christoph, * Christoph Hellwig ([email protected]) wrote: > On Mon, May 07, 2007 at 10:02:24AM -0400, Mathieu Desnoyers wrote: > > Hi, > > > > I'll skip the implementation details, but I am considering changing the > > current marker implementation, which uses format strings, for something > > that would look like : > > > > trace_mark(subsysname, eventname, mark_types(MARK_CHAR, MARK_ULLONG), > > mychar, myull); > > I don't like this at all. Lots of shouting and strange syntax. The nice > thing about format strings is that it's intuitive to any half-way experience > C programmer. We use format string all over and thus know how to parse > and write them. And our editors do the syntax highlighting for us :) > > What would the syntax above buy you? > Since I don't need to express anything else than the types expected (unlike printf, no text is required), the function that marshalls the variable arguments could be implemented more efficiently using a switch on a type enumeration rather that parsing the format string (which I currently do : it's inspired from vsnprintf). Since I have to extend the standard format strings with new types (telling explicitly how to expect a 32 or 64 bits integer in a portable manner in architecture independant code, or how to serialize an array, or a struct), I currently added the following tweaks to the format strings expected by the markers. (taken for ltt/ltt-serialize.c) /* Inspired from vsnprintf */ /* The serialization format string supports the basic printf format strings. * In addition, it also defines new formats that can be used to serialize * more complex/non portable data structures. * * Serialization specific formats : * * Fixed length struct, union or array. * %*r expects sizeof(*ptr), ptr * %*.*r expects sizeof(*ptr), __alignof__(*ptr), ptr * * Variable length sequence * %*.*:*v expects sizeof(*ptr), __alignof__(*ptr), elem_num, ptr * where elem_num is the number of elements in the sequence * * Callback * %k callback (taken from the probe data) * * Fixed size integers * %1b expects uint8_t * %2b expects uint16_t * %4b expects uint32_t * %8b expects uint64_t * %*b expects sizeof(data), data * where sizeof(data) is 1, 2, 4 or 8 */ I thought that it might be an improvement because of the following arguments : a- it provides a cleaner way to express expected types. I do not "need" to express text between the argument identifiers, so therefore users should not expect to be able to express text there. b- more efficient to parse : it becomes a simple for () on a switch statement on an enumeration bounded by the length of the enumeration array. c- since I do not follow the standard anyway (I cannot use gcc's format string verification as-is with my new types), I have an opportunity to design this "correctly" instead of using the format strings, which are very flexible and useful to express a printf statement (text mixed with data information), but becomes inefficient when it comes to specify only data types. I have seen examples of variable argument functions in other code. I remember having seen GTK using it like : function(TYPE1, arg1, TYPE2, arg2, END_OF_ARGUMENT);. I dislike this implementation because it forces the programmer to express the end of argument list by hand : if he forgets, the program crashes. Moreover, this implementation takes more stack space because it passes each type on the stack. My implementation overcomes these issues by declaring an array of enumeration and by using its size, known statically, to know how much var args to expect. Mathieu -- Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68