From d06fc4d5d8bfacf1a2884185ca92152a2d5f902c Mon Sep 17 00:00:00 2001 From: compudj Date: Fri, 6 Apr 2007 23:00:47 +0000 Subject: [PATCH] add examples git-svn-id: http://ltt.polymtl.ca/svn@2482 04897980-b3bd-0310-b5e0-8ef037075253 --- tests/kernel/Makefile | 6 +- tests/kernel/marker-example.c | 56 +++++++++++++++++++ tests/kernel/probe-example.c | 102 ++++++++++++++++++++++++++++++++++ tests/kernel/test-compact.c | 47 ++++++++++++---- tests/kernel/trace-event.h | 46 +++++++++++---- 5 files changed, 233 insertions(+), 24 deletions(-) create mode 100644 tests/kernel/marker-example.c create mode 100644 tests/kernel/probe-example.c diff --git a/tests/kernel/Makefile b/tests/kernel/Makefile index 01259f55..5b943163 100644 --- a/tests/kernel/Makefile +++ b/tests/kernel/Makefile @@ -3,13 +3,17 @@ ifneq ($(CONFIG_LTT),) #obj-m += ltt-facility-loader-tests.o # #obj-m += test-time-probe.o #obj-m += test-time-probe2.o - #obj-m += test-compact.o + obj-m += test-compact.o # obj-m += ltt-facility-loader-compact.o # obj-m += test-instrument-size-small.o # obj-m += test-instrument-size-med.o # obj-m += test-instrument-size-big.o # obj-m += test-printk-effect.o + obj-m += ltt-probe-tests.o + obj-m += test-time-probe3.o endif + obj-m += probe-example.o + obj-m += marker-example.o # obj-m += test-async-tsc.o obj-m += test-tsc-sync.o obj-m += test-tsc.o diff --git a/tests/kernel/marker-example.c b/tests/kernel/marker-example.c new file mode 100644 index 00000000..9ae10d9e --- /dev/null +++ b/tests/kernel/marker-example.c @@ -0,0 +1,56 @@ +/* marker-example.c + * + * Executes a marker when /proc/marker-example is opened. + * + * (C) Copyright 2007 Mathieu Desnoyers + * + * This file is released under the GPLv2. + * See the file COPYING for more details. + */ + +#include +#include +#include +#include + +struct proc_dir_entry *pentry_example = NULL; + +static int my_open(struct inode *inode, struct file *file) +{ + int i; + + MARK(subsystem_event, "%d %s %*.*r", 123, "example string", + sizeof(current), __alignof__(current), current); + for (i=0; i<10; i++) { + MARK(subsystem_eventb, MARK_NOARGS); + } + return -EPERM; +} + +static struct file_operations mark_ops = { + .open = my_open, +}; + +static int example_init(void) +{ + printk(KERN_ALERT "example init\n"); + pentry_example = create_proc_entry("marker-example", 0444, NULL); + if (pentry_example) + pentry_example->proc_fops = &mark_ops; + else + return -EPERM; + return 0; +} + +static void example_exit(void) +{ + printk(KERN_ALERT "example exit\n"); + remove_proc_entry("marker-example", NULL); +} + +module_init(example_init) +module_exit(example_exit) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("Linux Trace Toolkit example"); diff --git a/tests/kernel/probe-example.c b/tests/kernel/probe-example.c new file mode 100644 index 00000000..5e7093c7 --- /dev/null +++ b/tests/kernel/probe-example.c @@ -0,0 +1,102 @@ +/* probe-example.c + * + * Connects a two functions to marker call sites. + * + * (C) Copyright 2007 Mathieu Desnoyers + * + * This file is released under the GPLv2. + * See the file COPYING for more details. + */ + +#include +#include +#include +#include +#include + +#define NUM_PROBES (sizeof(probe_array) / sizeof(struct probe_data)) + +struct probe_data { + const char *name; + const char *format; + marker_probe_func *probe_func; +}; + +void probe_subsystem_event(const struct __mark_marker_c *mdata, + const char *format, ...) +{ + va_list ap; + /* Declare args */ + unsigned int value; + const char *mystr; + int task_size, task_alignment; + struct task_struct *task; + + /* Assign args */ + va_start(ap, format); + value = va_arg(ap, typeof(value)); + mystr = va_arg(ap, typeof(mystr)); + task_size = va_arg(ap, typeof(task_size)); + task_alignment = va_arg(ap, typeof(task_alignment)); + task = va_arg(ap, typeof(task)); + + /* Call printk */ + printk("Value %u, string %s, current ptr %p\n", value, mystr, current); + + /* or count, check rights, serialize data in a buffer */ + + va_end(ap); +} + +atomic_t eventb_count = ATOMIC_INIT(0); + +void probe_subsystem_eventb(const struct __mark_marker_c *mdata, + const char *format, ...) +{ + /* Increment counter */ + atomic_inc(&eventb_count); +} + +static struct probe_data probe_array[] = +{ + { .name = "subsystem_event", + .format = "%d %s %*.*r", + .probe_func = probe_subsystem_event }, + { .name = "subsystem_eventb", + .format = MARK_NOARGS, + .probe_func = probe_subsystem_eventb }, +}; + +static int __init probe_init(void) +{ + int result; + uint8_t eID; + + for (eID = 0; eID < NUM_PROBES; eID++) { + result = marker_set_probe(probe_array[eID].name, + probe_array[eID].format, + probe_array[eID].probe_func, &probe_array[eID]); + if (!result) + printk(KERN_INFO "Unable to register probe %s\n", + probe_array[eID].name); + } + return 0; +} + +static void __exit probe_fini(void) +{ + uint8_t eID; + + for (eID = 0; eID < NUM_PROBES; eID++) { + marker_remove_probe(probe_array[eID].name); + } + synchronize_sched(); /* Wait for probes to finish */ + printk("Number of event b : %u\n", atomic_read(&eventb_count)); +} + +module_init(probe_init); +module_exit(probe_fini); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("SUBSYSTEM Probe"); diff --git a/tests/kernel/test-compact.c b/tests/kernel/test-compact.c index 5aed22fd..d3f4472e 100644 --- a/tests/kernel/test-compact.c +++ b/tests/kernel/test-compact.c @@ -4,14 +4,14 @@ */ -#include -#include - #include #include -#include +#include #include +#include +#include +struct proc_dir_entry *pentry_test = NULL; /* Event logged : 4 bytes. Let's use 1MB of * buffers. 1MB / 4bytes = 262144 (plus heartbeats). So, if we write 20000 @@ -19,21 +19,29 @@ #define NR_LOOPS 20000 -static int ltt_test_init(void) +static int my_open(struct inode *inode, struct file *file) { unsigned int i; cycles_t time1, time2, time; cycles_t tot_time = 0; unsigned long flags; - printk(KERN_ALERT "test init\n"); + printk(KERN_ALERT "test begin\n"); local_irq_save(flags); time1 = get_cycles(); for(i=0; iproc_fops = &mark_ops; + else + return -EPERM; + return 0; } static void ltt_test_exit(void) { printk(KERN_ALERT "test exit\n"); + remove_proc_entry("test-compact", NULL); } module_init(ltt_test_init) diff --git a/tests/kernel/trace-event.h b/tests/kernel/trace-event.h index 1f2eccac..bf5d9e5b 100644 --- a/tests/kernel/trace-event.h +++ b/tests/kernel/trace-event.h @@ -1,5 +1,8 @@ #include +/* Maximum number of callbacks per marker */ +#define LTT_NR_CALLBACKS 10 + /* LTT flags * * LTT_FLAG_TRACE : first arg contains trace to write into. @@ -18,7 +21,8 @@ #define LTT_FLAG_FORCE (1 << _LTT_FLAG_FORCE) -char *(*ltt_serialize_cb)(char *buffer, const char *fmt, va_list args); +char *(*ltt_serialize_cb)(char *buffer, int *cb_args, + const char *fmt, va_list args); static int skip_atoi(const char **s) @@ -32,10 +36,13 @@ static int skip_atoi(const char **s) /* Inspired from vsnprintf */ /* New types : - * %r : serialized pointer. + * %r : serialized fixed length struct, union, array. + * %v : serialized sequence + * %k : callback */ static inline __attribute__((no_instrument_function)) -char *ltt_serialize_data(char *buffer, const char *fmt, va_list args) +char *ltt_serialize_data(char *buffer, int *cb_args, + const char *fmt, va_list args) { int len; const char *s; @@ -48,6 +55,7 @@ char *ltt_serialize_data(char *buffer, const char *fmt, va_list args) /* 't' added for ptrdiff_t */ char *str; /* Pointer to write to */ ltt_serialize_cb cb; + int cb_arg_nr = 0; str = buf; @@ -117,6 +125,9 @@ char *ltt_serialize_data(char *buffer, const char *fmt, va_list args) if (buffer) strcpy(str, s); str += strlen(s); + /* Following alignment for genevent + * compatibility */ + str += ltt_align(str, sizeof(void*)); continue; case 'p': @@ -154,6 +165,9 @@ char *ltt_serialize_data(char *buffer, const char *fmt, va_list args) memcpy(str, src, elem_size); str += elem_size; } + /* Following alignment for genevent + * compatibility */ + str += ltt_align(str, sizeof(void*)); continue; case 'k': @@ -162,16 +176,20 @@ char *ltt_serialize_data(char *buffer, const char *fmt, va_list args) /* The callback will take as many arguments * as it needs from args. They won't be * type verified. */ - str = cb(str, fmt, args); + if (cb_arg_nr < LTT_NR_CALLBACKS) + str = cb(str, &cb_args[cb_arg_nr++], + fmt, args); continue; case 'n': /* FIXME: - * What does C99 say about the overflow case here? */ + * What does C99 say about the overflow case + * here? */ if (qualifier == 'l') { long * ip = va_arg(args, long *); *ip = (str - buf); - } else if (qualifier == 'Z' || qualifier == 'z') { + } else if (qualifier == 'Z' + || qualifier == 'z') { size_t * ip = va_arg(args, size_t *); *ip = (str - buf); } else { @@ -234,10 +252,12 @@ char *ltt_serialize_data(char *buffer, const char *fmt, va_list args) if (buffer) switch (elem_size) { case 1: - *(int8_t*)str = (int8_t)va_arg(args, int); + *(int8_t*)str = + (int8_t)va_arg(args, int); break; case 2: - *(int16_t*)str = (int16_t)va_arg(args, int); + *(int16_t*)str = + (int16_t)va_arg(args, int); break; case 4: *(int32_t*)str = va_arg(args, int32_t); @@ -262,6 +282,7 @@ char *ltt_serialize_data(char *buffer, const char *fmt, va_list args) * sizeof(void *) address. */ static inline __attribute__((no_instrument_function)) size_t ltt_get_data_size(ltt_facility_t fID, uint8_t eID, + int *cb_args, const char *fmt, va_list args) { return (size_t)ltt_serialize_data(NULL, fmt, args); @@ -270,6 +291,7 @@ size_t ltt_get_data_size(ltt_facility_t fID, uint8_t eID, static inline __attribute__((no_instrument_function)) void ltt_write_event_data(char *buffer, ltt_facility_t fID, uint8_t eID, + int *cb_args, const char *fmt, va_list args) { ltt_serialize_data(buffer, fmt, args); @@ -288,10 +310,12 @@ void _vtrace(ltt_facility_t fID, uint8_t eID, long flags, uint64_t tsc; char *buffer; va_list args_copy; + int cb_args[LTT_NR_CALLBACKS]; /* This test is useful for quickly exiting static tracing when no * trace is active. */ - if (likely(ltt_traces.num_active_traces == 0 && !(flags & LTT_FLAG_FORCE))) + if (likely(ltt_traces.num_active_traces == 0 + && !(flags & LTT_FLAG_FORCE))) return; preempt_disable(); @@ -305,7 +329,7 @@ void _vtrace(ltt_facility_t fID, uint8_t eID, long flags, channel_index = ltt_get_channel_index(fID, eID); va_copy(args_copy, args); /* Check : skip 2 st args if trace/ch */ - data_size = ltt_get_data_size(fID, eID, fmt, args_copy); + data_size = ltt_get_data_size(fID, eID, cb_args, fmt, args_copy); va_end(args_copy); /* Iterate on each traces */ @@ -324,7 +348,7 @@ void _vtrace(ltt_facility_t fID, uint8_t eID, long flags, buffer = ltt_write_event_header(trace, channel, buffer, fID, eID, data_size, tsc); va_copy(args_copy, args); - ltt_write_event_data(buffer, fID, eID, fmt, args_copy); + ltt_write_event_data(buffer, fID, eID, cb_args, fmt, args_copy); va_end(args_copy); /* Out-of-order commit */ ltt_commit_slot(channel, &transport_data, buffer, slot_size); -- 2.34.1