--- /dev/null
+
+
+CC=gcc
+
+all: sample-thread sample
+
+sample-thread: sample-thread.c ltt-facility-loader-user_generic.c
+ $(CC) $(CFLAGS) -I. -lpthread -o $@ $^
+
+sample: sample.c ltt-facility-loader-user_generic.c
+ $(CC) $(CFLAGS) -I. -o $@ $^
+
+.PHONY : clean
+
+clean:
+ rm -fr *.o *~ sample-thread sample
+
--- /dev/null
+/*
+ * ltt-facility-loader-user_generic.c
+ *
+ * (C) Copyright 2005 -
+ * Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca)
+ *
+ * Contains the LTT user space facility loader.
+ *
+ */
+
+
+#define LTT_TRACE
+#include <error.h>
+#include <stdio.h>
+#include <ltt/ltt-generic.h>
+#include "ltt-facility-loader-user_generic.h"
+
+static struct user_facility_info facility = {
+ .name = LTT_FACILITY_NAME,
+ .num_events = LTT_FACILITY_NUM_EVENTS,
+#ifndef LTT_PACK
+ .alignment = sizeof(void*),
+#else
+ .alignment = 0,
+#endif //LTT_PACK
+ .checksum = LTT_FACILITY_CHECKSUM,
+ .int_size = sizeof(int),
+ .long_size = sizeof(long),
+ .pointer_size = sizeof(void*),
+ .size_t_size = sizeof(size_t)
+};
+
+static void __attribute__((constructor)) __ltt_user_init(void)
+{
+ int err;
+ printf("LTT : ltt-facility-user_generic init in userspace\n");
+
+ err = ltt_register_generic(<T_FACILITY_SYMBOL, &facility);
+ LTT_FACILITY_CHECKSUM_SYMBOL = LTT_FACILITY_SYMBOL;
+
+ if(err) {
+ perror("Error in ltt_register_generic");
+ }
+}
+
--- /dev/null
+#ifndef _LTT_FACILITY_LOADER_USER_GENERIC_H_
+#define _LTT_FACILITY_LOADER_USER_GENERIC_H_
+
+#include <ltt/ltt-generic.h>
+#include <ltt/ltt-facility-id-user_generic.h>
+
+ltt_facility_t ltt_facility_user_generic;
+ltt_facility_t ltt_facility_user_generic_411B0F83;
+
+#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_NAME "user_generic"
+#define LTT_FACILITY_NUM_EVENTS facility_user_generic_num_events
+
+#endif //_LTT_FACILITY_LOADER_USER_GENERIC_H_
--- /dev/null
+#ifndef _LTT_FACILITY_ID_USER_GENERIC_H_
+#define _LTT_FACILITY_ID_USER_GENERIC_H_
+
+#ifdef LTT_TRACE
+#include <ltt/ltt-generic.h>
+
+/**** facility handle ****/
+
+extern ltt_facility_t ltt_facility_user_generic_411B0F83;
+extern ltt_facility_t ltt_facility_user_generic;
+
+
+/**** event index ****/
+
+enum user_generic_event {
+ event_user_generic_string,
+ event_user_generic_string_pointer,
+ facility_user_generic_num_events
+};
+
+#endif //LTT_TRACE
+#endif //_LTT_FACILITY_ID_USER_GENERIC_H_
--- /dev/null
+#ifndef _LTT_FACILITY_USER_GENERIC_H_
+#define _LTT_FACILITY_USER_GENERIC_H_
+
+#include <sys/types.h>
+#include <ltt/ltt-facility-id-user_generic.h>
+#include <ltt/ltt-generic.h>
+
+/* Named types */
+
+/* Event string structures */
+static inline void lttng_write_string_user_generic_string_data(
+ 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 string logging function */
+static inline int trace_user_generic_string(
+ const char * lttng_param_data)
+#ifndef LTT_TRACE
+{
+}
+#else
+{
+ 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 real_to = 0;
+ size_t *to = &real_to;
+ size_t real_len = 0;
+ 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. */
+ /* size = *to_base + *to + *len */
+ /* Assume that the padding for alignment starts at a
+ * sizeof(void *) address. */
+
+ *from = lttng_param_data;
+ lttng_write_string_user_generic_string_data(buffer, to_base, to, from, len, lttng_param_data);
+
+ reserve_size = *to_base + *to + *len;
+ {
+ char stack_buffer[reserve_size];
+ buffer = stack_buffer;
+
+ *to_base = *to = *len = 0;
+
+ *from = lttng_param_data;
+ lttng_write_string_user_generic_string_data(buffer, to_base, to, from, len, lttng_param_data);
+
+ /* Flush pending memcpy */
+ if(*len != 0) {
+ memcpy(buffer+*to_base+*to, *from, *len);
+ *to += *len;
+ *len = 0;
+ }
+
+ ret = ltt_trace_generic(ltt_facility_user_generic_411B0F83, event_user_generic_string, stack_buffer, sizeof(stack_buffer));
+ }
+
+ return ret;
+
+}
+#endif //LTT_TRACE
+
+/* Event string_pointer structures */
+static inline void lttng_write_string_user_generic_string_pointer_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 string_pointer logging function */
+static inline int trace_user_generic_string_pointer(
+ const char * lttng_param_string,
+ const void * lttng_param_pointer)
+#ifndef LTT_TRACE
+{
+}
+#else
+{
+ 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 real_to = 0;
+ size_t *to = &real_to;
+ size_t real_len = 0;
+ 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;
+ /* For each field, calculate the field size. */
+ /* size = *to_base + *to + *len */
+ /* Assume that the padding for alignment starts at a
+ * sizeof(void *) address. */
+
+ *from = lttng_param_string;
+ lttng_write_string_user_generic_string_pointer_string(buffer, to_base, to, from, len, lttng_param_string);
+
+ *from = <tng_param_pointer;
+ align = sizeof(const void *);
+
+ 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 */
+ }
+
+ *len += sizeof(const void *);
+
+ reserve_size = *to_base + *to + *len;
+ {
+ char stack_buffer[reserve_size];
+ buffer = stack_buffer;
+
+ *to_base = *to = *len = 0;
+
+ *from = lttng_param_string;
+ lttng_write_string_user_generic_string_pointer_string(buffer, to_base, to, from, len, lttng_param_string);
+
+ /* Flush pending memcpy */
+ if(*len != 0) {
+ memcpy(buffer+*to_base+*to, *from, *len);
+ *to += *len;
+ *len = 0;
+ }
+
+ *from = <tng_param_pointer;
+ align = sizeof(const void *);
+
+ 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 */
+ }
+
+ *len += sizeof(const void *);
+
+ /* Flush pending memcpy */
+ if(*len != 0) {
+ memcpy(buffer+*to_base+*to, *from, *len);
+ *to += *len;
+ *len = 0;
+ }
+
+ ret = ltt_trace_generic(ltt_facility_user_generic_411B0F83, event_user_generic_string_pointer, stack_buffer, sizeof(stack_buffer));
+ }
+
+ return ret;
+
+}
+#endif //LTT_TRACE
+
+#endif //_LTT_FACILITY_USER_GENERIC_H_
--- /dev/null
+/*****************************************************************************
+ * ltt-generic.h
+ *
+ * LTT generic userspace tracing header
+ *
+ * Mathieu Desnoyers, March 2006
+ */
+
+#ifndef _LTT_GENERIC_H
+#define _LTT_GENERIC_H
+
+#include <errno.h>
+#include <syscall.h>
+#include <linux/unistd.h>
+#include <asm/atomic.h>
+#include <string.h>
+#include <sys/types.h>
+#include <stdint.h>
+
+#ifndef min
+#define min(a,b) ((a)<(b)?(a):(b))
+#endif
+
+//Put in asm-i486/unistd.h
+#define __NR_ltt_trace_generic 294
+#define __NR_ltt_register_generic 295
+
+#undef NR_syscalls
+#define NR_syscalls 296
+
+//FIXME : setup for ARM
+//FIXME : setup for MIPS
+
+#ifndef _LIBC
+// Put in bits/syscall.h
+#define SYS_ltt_trace_generic __NR_ltt_trace_generic
+#define SYS_ltt_register_generic __NR_ltt_register_generic
+#endif
+
+#define FACNAME_LEN 32
+
+typedef unsigned int ltt_facility_t;
+
+struct user_facility_info {
+ char name[FACNAME_LEN];
+ unsigned int num_events;
+ size_t alignment;
+ uint32_t checksum;
+ size_t int_size;
+ size_t long_size;
+ size_t pointer_size;
+ size_t size_t_size;
+};
+
+static inline _syscall4(int, ltt_trace_generic, unsigned int, facility_id,
+ unsigned int, event_id, void *, data, size_t, data_size)
+static inline _syscall2(int, ltt_register_generic, unsigned int *, facility_id, const struct user_facility_info *, info)
+
+#ifndef LTT_PACK
+/* Calculate the offset needed to align the type */
+static inline unsigned int ltt_align(size_t align_drift,
+ size_t size_of_type)
+{
+ size_t alignment = min(sizeof(void*), size_of_type);
+
+ return ((alignment - align_drift) & (alignment-1));
+}
+#else
+static inline unsigned int ltt_align(size_t align_drift,
+ size_t size_of_type)
+{
+ return 0;
+}
+#endif //LTT_PACK
+
+#endif //_LTT_GENERIC_H
+
+
--- /dev/null
+
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#define LTT_TRACE
+#include <ltt/ltt-facility-user_generic.h>
+
+
+void *thr1(void *arg)
+{
+ printf("thread 1, thread id : %lu, pid %lu\n", pthread_self(), getpid());
+
+ while(1) {
+ trace_user_generic_string("Hello world! Have a nice day.");
+ sleep(2);
+ }
+
+ return ((void*)1);
+
+}
+
+void *thr2(void *arg)
+{
+ printf("thread 2, thread id : %lu, pid %lu\n", pthread_self(), getpid());
+ sleep(1);
+ while(1) {
+ trace_user_generic_string("Hello world! Have a nice day.");
+ sleep(2);
+ }
+ return ((void*)2);
+}
+
+
+int main()
+{
+ int err;
+ pthread_t tid1, tid2;
+ void *tret;
+
+ printf("Will trace the following string : Hello world! Have a nice day.\n");
+ printf("Press CTRL-C to stop.\n");
+ printf("thread main, thread id : %lu, pid %lu\n", pthread_self(), getpid());
+ err = pthread_create(&tid1, NULL, thr1, NULL);
+ if(err!=0) exit(1);
+
+ err = pthread_create(&tid2, NULL, thr2, NULL);
+ if(err!=0) exit(1);
+
+ err = pthread_join(tid1, &tret);
+ if(err!= 0) exit(1);
+
+ err = pthread_join(tid2, &tret);
+ if(err!= 0) exit(1);
+
+ return 0;
+}
--- /dev/null
+
+#include <stdio.h>
+#include <unistd.h>
+
+#define LTT_TRACE
+#include <ltt/ltt-facility-user_generic.h>
+
+
+int main(int argc, char **argv)
+{
+ printf("Will trace the following string : Hello world! Have a nice day.\n");
+
+ while(1) {
+ trace_user_generic_string("Hello world! Have a nice day.");
+ sleep(1);
+ }
+
+ return 0;
+}
+
--- /dev/null
+<facility name=user_generic>
+ <description>Generic user space facility</description>
+
+ <event name=string>
+ <description>Takes a string from user space</description>
+ <field name="data"><string/></field>
+ </event>
+
+ <event name=string_pointer>
+ <description>Takes a string and pointer from user space</description>
+ <field name="string"><string/></field>
+ <field name="pointer"><pointer/></field>
+ </event>
+
+</facility>