CC=gcc
-all: sample-thread sample sample-highspeed
+all: sample-thread sample sample-highspeed sample-printf
sample-thread: sample-thread.c ltt-facility-loader-user_generic.c
$(CC) $(CFLAGS) -I. -lpthread -o $@ $^
sample-highspeed: sample-highspeed.c ltt-facility-loader-user_generic.c
$(CC) $(CFLAGS) -I. -o $@ $^
+sample-printf: sample-printf.c ltt-facility-loader-user_generic.c
+ $(CC) $(CFLAGS) -I. -o $@ $^
+
.PHONY : clean
clean:
- rm -fr *.o *~ sample-thread sample
+ rm -fr *.o *~ sample-thread sample sample-highspeed sample-printf
#include <ltt/ltt-facility-id-user_generic.h>
ltt_facility_t ltt_facility_user_generic;
-ltt_facility_t ltt_facility_user_generic_411B0F83;
+ltt_facility_t ltt_facility_user_generic_FB850A80;
#define LTT_FACILITY_SYMBOL ltt_facility_user_generic
-#define LTT_FACILITY_CHECKSUM_SYMBOL ltt_facility_user_generic_411B0F83
-#define LTT_FACILITY_CHECKSUM 0x411B0F83
+#define LTT_FACILITY_CHECKSUM_SYMBOL ltt_facility_user_generic_FB850A80
+#define LTT_FACILITY_CHECKSUM 0xFB850A80
#define LTT_FACILITY_NAME "user_generic"
#define LTT_FACILITY_NUM_EVENTS facility_user_generic_num_events
--- /dev/null
+#ifndef _LTT_FACILITY_CUSTOM_USER_GENERIC_H_
+#define _LTT_FACILITY_CUSTOM_USER_GENERIC_H_
+
+#include <sys/types.h>
+#include <ltt/ltt-facility-id-user_generic.h>
+#include <ltt/ltt-generic.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+static inline int trace_user_generic_slow_printf(
+ const char *fmt, ...)
+#ifndef LTT_TRACE
+{
+}
+#else
+{
+ /* Guess we need no more than 100 bytes. */
+ int n, size = 100;
+ char *p, *np;
+ va_list ap;
+ int ret;
+
+ if ((p = malloc (size)) == NULL)
+ return -1;
+
+ while (1) {
+ /* Try to print in the allocated space. */
+ va_start(ap, fmt);
+ n = vsnprintf (p, size, fmt, ap);
+ va_end(ap);
+ /* If that worked, trace the string. */
+ if (n > -1 && n < size) {
+ ret = trace_user_generic_slow_printf_param_buffer(p, n+1);
+ free(p);
+ return ret;
+ }
+ /* Else try again with more space. */
+ if (n > -1) /* glibc 2.1 */
+ size = n+1; /* precisely what is needed */
+ else /* glibc 2.0 */
+ size *= 2; /* twice the old size */
+ if ((np = realloc (p, size)) == NULL) {
+ free(p);
+ return -1;
+ } else {
+ p = np;
+ }
+ }
+}
+#endif //LTT_TRACE
+
+#endif //_LTT_FACILITY_CUSTOM_USER_GENERIC_H_
/**** facility handle ****/
-extern ltt_facility_t ltt_facility_user_generic_411B0F83;
+extern ltt_facility_t ltt_facility_user_generic_FB850A80;
extern ltt_facility_t ltt_facility_user_generic;
enum user_generic_event {
event_user_generic_string,
event_user_generic_string_pointer,
+ event_user_generic_slow_printf,
facility_user_generic_num_events
};
}
#else
{
+ int ret = 0;
void *buffer = NULL;
size_t real_to_base = 0; /* The buffer is allocated on arch_size alignment */
size_t *to_base = &real_to_base;
size_t *len = &real_len;
size_t reserve_size;
size_t slot_size;
- int ret = 0;
const void *real_from;
const void **from = &real_from;
/* For each field, calculate the field size. */
*len = 0;
}
- ret = ltt_trace_generic(ltt_facility_user_generic_411B0F83, event_user_generic_string, stack_buffer, sizeof(stack_buffer), LTT_BLOCKING);
+ ret = ltt_trace_generic(ltt_facility_user_generic_FB850A80, event_user_generic_string, buffer, reserve_size, LTT_BLOCKING);
}
return ret;
}
#else
{
+ int ret = 0;
void *buffer = NULL;
size_t real_to_base = 0; /* The buffer is allocated on arch_size alignment */
size_t *to_base = &real_to_base;
size_t *len = &real_len;
size_t reserve_size;
size_t slot_size;
- int ret = 0;
size_t align;
const void *real_from;
const void **from = &real_from;
*len = 0;
}
- ret = ltt_trace_generic(ltt_facility_user_generic_411B0F83, event_user_generic_string_pointer, stack_buffer, sizeof(stack_buffer), LTT_BLOCKING);
+ ret = ltt_trace_generic(ltt_facility_user_generic_FB850A80, event_user_generic_string_pointer, buffer, reserve_size, LTT_BLOCKING);
+ }
+
+ return ret;
+
+}
+#endif //LTT_TRACE
+
+/* Event slow_printf structures */
+static inline void lttng_write_string_user_generic_slow_printf_string(
+ void *buffer,
+ size_t *to_base,
+ size_t *to,
+ const void **from,
+ size_t *len,
+ const char * obj)
+{
+ size_t size;
+ size_t align;
+
+ /* Flush pending memcpy */
+ if(*len != 0) {
+ if(buffer != NULL)
+ memcpy(buffer+*to_base+*to, *from, *len);
+ }
+ *to += *len;
+ *len = 0;
+
+ align = sizeof(char);
+
+ if(*len == 0) {
+ *to += ltt_align(*to, align); /* align output */
+ } else {
+ *len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */
+ }
+
+ /* Contains variable sized fields : must explode the structure */
+
+ size = strlen(obj) + 1; /* Include final NULL char. */
+ if(buffer != NULL)
+ memcpy(buffer+*to_base+*to, obj, size);
+ *to += size;
+
+ /* Realign the *to_base on arch size, set *to to 0 */
+ *to += ltt_align(*to, sizeof(void *));
+ *to_base = *to_base+*to;
+ *to = 0;
+
+ /* Put source *from just after the C string */
+ *from += size;
+}
+
+
+/* Event slow_printf logging function */
+static inline int trace_user_generic_slow_printf_param_buffer(
+ void *buffer,
+ size_t reserve_size)
+#ifndef LTT_TRACE
+{
+}
+#else
+{
+ int ret = 0;
+ reserve_size += ltt_align(reserve_size, sizeof(void *));
+ {
+ ret = ltt_trace_generic(ltt_facility_user_generic_FB850A80, event_user_generic_slow_printf, buffer, reserve_size, LTT_BLOCKING);
}
return ret;
--- /dev/null
+
+#include <stdio.h>
+#include <unistd.h>
+
+#define LTT_TRACE
+#define LTT_BLOCKING 1
+#include <ltt/ltt-facility-user_generic.h>
+#include <ltt/ltt-facility-custom-user_generic.h>
+
+
+int main(int argc, char **argv)
+{
+ printf("Will trace a printf of an incrementing counter.\n");
+ unsigned int count = 0;
+
+ while(1) {
+ trace_user_generic_slow_printf("Counter value is : %u.", count);
+ count++;
+ sleep(1);
+ }
+
+ return 0;
+}
+
<field name="pointer"><pointer/></field>
</event>
+ <event name=slow_printf param_buffer>
+ <description>Takes a buffer of variable size (written by printf) and log it.</description>
+ <field name="string"><string/></field>
+ </event>
+
</facility>