5 * LTT_FLAG_TRACE : first arg contains trace to write into.
6 * (type : struct ltt_trace_struct *)
7 * LTT_FLAG_CHANNEL : following arg contains channel index to write into.
9 * LTT_FLAG_FORCE : Force write in disabled traces (internal ltt use)
12 #define _LTT_FLAG_TRACE 0
13 #define _LTT_FLAG_CHANNEL 1
14 #define _LTT_FLAG_FORCE 2
16 #define LTT_FLAG_TRACE (1 << _LTT_FLAG_TRACE)
17 #define LTT_FLAG_CHANNEL (1 << _LTT_FLAG_CHANNEL)
18 #define LTT_FLAG_FORCE (1 << _LTT_FLAG_FORCE)
21 char *(*ltt_serialize_cb
)(char *buffer
, const char *fmt
, va_list args
);
24 static int skip_atoi(const char **s
)
29 i
= i
*10 + *((*s
)++) - '0';
33 /* Inspired from vsnprintf */
35 * %r : serialized pointer.
37 static inline __attribute__((no_instrument_function
))
38 char *ltt_serialize_data(char *buffer
, const char *fmt
, va_list args
)
42 int elem_size
; /* Size of the integer for 'b' */
43 /* Size of the data contained by 'r' */
44 int elem_alignment
; /* Element alignment for 'r' */
45 int qualifier
; /* 'h', 'l', or 'L' for integer fields */
46 /* 'z' support added 23/7/1999 S.H. */
47 /* 'z' changed to 'Z' --davidm 1/25/99 */
48 /* 't' added for ptrdiff_t */
49 char *str
; /* Pointer to write to */
54 for (; *fmt
; ++fmt
) {
60 /* process flags : ignore standard print formats for now. */
62 ++fmt
; /* this also skips first '%' */
68 case '0': goto repeat
;
71 /* get element size */
74 elem_size
= skip_atoi(&fmt
);
75 else if (*fmt
== '*') {
77 /* it's the next argument */
78 elem_size
= va_arg(args
, int);
81 /* get the alignment */
86 elem_alignment
= skip_atoi(&fmt
);
87 else if (*fmt
== '*') {
89 /* it's the next argument */
90 elem_alignment
= va_arg(args
, int);
94 /* get the conversion qualifier */
96 if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L' ||
97 *fmt
=='Z' || *fmt
== 'z' || *fmt
== 't') {
100 if (qualifier
== 'l' && *fmt
== 'l') {
109 *str
= (char) va_arg(args
, int);
114 s
= va_arg(args
, char *);
115 if ((unsigned long)s
< PAGE_SIZE
)
123 str
+= ltt_align(str
, sizeof(void*));
125 *(void**)str
= va_arg(args
, void *);
129 /* For array, struct, union */
130 if (elem_alignment
< 0)
131 elem_alignment
= sizeof(void*);
132 str
+= ltt_align(str
, elem_alignment
);
134 const char *src
= va_arg(args
,
137 memcpy(str
, src
, elem_size
);
144 str
+= ltt_align(str
, sizeof(int));
146 *(int*)str
= elem_size
;
148 if (elem_alignment
> 0)
149 str
+= ltt_align(str
, elem_alignment
);
151 const char *src
= va_arg(args
,
154 memcpy(str
, src
, elem_size
);
161 cb
= va_arg(args
, ltt_serialize_cb
);
162 /* The callback will take as many arguments
163 * as it needs from args. They won't be
165 str
= cb(str
, fmt
, args
);
170 * What does C99 say about the overflow case here? */
171 if (qualifier
== 'l') {
172 long * ip
= va_arg(args
, long *);
174 } else if (qualifier
== 'Z' || qualifier
== 'z') {
175 size_t * ip
= va_arg(args
, size_t *);
178 int * ip
= va_arg(args
, int *);
201 str
+= ltt_align(str
, sizeof(long long));
203 *(long long*)str
= va_arg(args
, long long);
204 str
+= sizeof(long long);
207 str
+= ltt_align(str
, sizeof(long));
209 *(long*)str
= va_arg(args
, long);
214 str
+= ltt_align(str
, sizeof(size_t));
216 *(size_t*)str
= va_arg(args
, size_t);
217 str
+= sizeof(size_t);
220 str
+= ltt_align(str
, sizeof(ptrdiff_t));
222 *(ptrdiff_t*)str
= va_arg(args
, ptrdiff_t);
223 str
+= sizeof(ptrdiff_t);
226 str
+= ltt_align(str
, sizeof(short));
228 *(short*)str
= (short) va_arg(args
, int);
229 str
+= sizeof(short);
233 str
+= ltt_align(str
, elem_size
);
237 *(int8_t*)str
= (int8_t)va_arg(args
, int);
240 *(int16_t*)str
= (int16_t)va_arg(args
, int);
243 *(int32_t*)str
= va_arg(args
, int32_t);
246 *(int64_t*)str
= va_arg(args
, int64_t);
251 str
+= ltt_align(str
, sizeof(int));
253 *(int*)str
= va_arg(args
, int);
260 /* Calculate data size */
261 /* Assume that the padding for alignment starts at a
262 * sizeof(void *) address. */
263 static inline __attribute__((no_instrument_function
))
264 size_t ltt_get_data_size(ltt_facility_t fID
, uint8_t eID
,
265 const char *fmt
, va_list args
)
267 return (size_t)ltt_serialize_data(NULL
, fmt
, args
);
270 static inline __attribute__((no_instrument_function
))
271 void ltt_write_event_data(char *buffer
,
272 ltt_facility_t fID
, uint8_t eID
,
273 const char *fmt
, va_list args
)
275 ltt_serialize_data(buffer
, fmt
, args
);
279 __attribute__((no_instrument_function
))
280 void _vtrace(ltt_facility_t fID
, uint8_t eID
, long flags
,
281 const char *fmt
, va_list args
)
283 size_t data_size
, slot_size
;
285 struct ltt_channel_struct
*channel
;
286 struct ltt_trace_struct
*trace
, *dest_trace
;
287 void *transport_data
;
292 /* This test is useful for quickly exiting static tracing when no
293 * trace is active. */
294 if (likely(ltt_traces
.num_active_traces
== 0 && !(flags
& LTT_FLAG_FORCE
)))
298 ltt_nesting
[smp_processor_id()]++;
300 if (unlikely(flags
& LTT_FLAG_TRACE
))
301 dest_trace
= va_arg(args
, struct ltt_trace_struct
*);
302 if (unlikely(flags
& LTT_FLAG_CHANNEL
))
303 channel_index
= va_arg(args
, int);
305 channel_index
= ltt_get_channel_index(fID
, eID
);
307 va_copy(args_copy
, args
); /* Check : skip 2 st args if trace/ch */
308 data_size
= ltt_get_data_size(fID
, eID
, fmt
, args_copy
);
311 /* Iterate on each traces */
312 list_for_each_entry_rcu(trace
, <t_traces
.head
, list
) {
313 if (unlikely(!trace
->active
&& !(flags
& LTT_FLAG_FORCE
)))
315 if (unlikely(flags
& LTT_FLAG_TRACE
&& trace
!= dest_trace
))
317 channel
= ltt_get_channel_from_index(trace
, channel_index
);
318 /* reserve space : header and data */
319 buffer
= ltt_reserve_slot(trace
, channel
, &transport_data
,
320 data_size
, &slot_size
, &tsc
);
321 if (unlikely(!buffer
))
322 continue; /* buffer full */
323 /* Out-of-order write : header and data */
324 buffer
= ltt_write_event_header(trace
, channel
, buffer
,
325 fID
, eID
, data_size
, tsc
);
326 va_copy(args_copy
, args
);
327 ltt_write_event_data(buffer
, fID
, eID
, fmt
, args_copy
);
329 /* Out-of-order commit */
330 ltt_commit_slot(channel
, &transport_data
, buffer
, slot_size
);
333 ltt_nesting
[smp_processor_id()]--;
337 __attribute__((no_instrument_function
))
338 void _trace(ltt_facility_t fID
, uint8_t eID
, long flags
, const char *fmt
, ...)
343 _vtrace(fID
, eID
, flags
, fmt
, args
);
This page took 0.041008 seconds and 5 git commands to generate.