From: Pierre-Marc Fournier Date: Mon, 23 Feb 2009 17:56:11 +0000 (-0500) Subject: ust: cleanup: move tracing control to tracectl.c X-Git-Tag: v0.1~278 X-Git-Url: http://git.lttng.org/?a=commitdiff_plain;h=a584bc4edb73e3f4c0023c42f2fdbc816fb6eab0;hp=cf49034025d46568a4db4aab3f09dfe912349bb8;p=ust.git ust: cleanup: move tracing control to tracectl.c --- diff --git a/hello/hello.c b/hello/hello.c index 67b9ef3..88087df 100644 --- a/hello/hello.c +++ b/hello/hello.c @@ -13,145 +13,6 @@ #include "relay.h" -char consumer_stack[10000]; - -#define CPRINTF(fmt, args...) safe_printf(fmt "\n", ## args) - -int safe_printf(const char *fmt, ...) -{ - static char buf[500]; - va_list ap; - int n; - - va_start(ap, fmt); - - n = vsnprintf(buf, sizeof(buf), fmt, ap); - - write(STDOUT_FILENO, buf, n); - - va_end(ap); -} - -struct consumer_channel { - int fd; - struct ltt_channel_struct *chan; -}; - -int consumer(void *arg) -{ - int result; - int fd; - char str[] = "Hello, this is the consumer.\n"; - struct ltt_trace_struct *trace; - struct consumer_channel *consumer_channels; - int i; - char trace_name[] = "auto"; - - ltt_lock_traces(); - trace = _ltt_trace_find(trace_name); - ltt_unlock_traces(); - - if(trace == NULL) { - CPRINTF("cannot find trace!"); - return 1; - } - - consumer_channels = (struct consumer_channel *) malloc(trace->nr_channels * sizeof(struct consumer_channel)); -if(consumer_channels == NULL) { - ERR("malloc returned NULL"); - return 1; - } - - CPRINTF("opening trace files"); - for(i=0; inr_channels; i++) { - char tmp[100]; - struct ltt_channel_struct *chan = &trace->channels[i]; - - consumer_channels[i].chan = chan; - - snprintf(tmp, sizeof(tmp), "trace/%s", chan->channel_name); - result = consumer_channels[i].fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 00644); - if(result == -1) { - perror("open"); - return -1; - } - CPRINTF("\topened trace file %s", tmp); - - } - CPRINTF("done opening trace files"); - - for(;;) { - /*wait*/ - - for(i=0; inr_channels; i++) { - struct rchan *rchan = consumer_channels[i].chan->trans_channel_data; - struct rchan_buf *rbuf = rchan->buf; - struct ltt_channel_buf_struct *lttbuf = consumer_channels[i].chan->buf; - long consumed_old; - - result = ltt_do_get_subbuf(rbuf, lttbuf, &consumed_old); - if(result < 0) { - CPRINTF("ltt_do_get_subbuf: error: %s", strerror(-result)); - } - else { - CPRINTF("success!"); - - result = write(consumer_channels[i].fd, rbuf->buf_data + (consumed_old & (2 * 4096-1)), 4096); - ltt_do_put_subbuf(rbuf, lttbuf, consumed_old); - } - } - - sleep(1); - } - -// CPRINTF("consumer: got a trace: %s with %d channels\n", trace_name, trace->nr_channels); -// -// struct ltt_channel_struct *chan = &trace->channels[0]; -// -// CPRINTF("channel 1 (%s) active=%u", chan->channel_name, chan->active & 1); - -// struct rchan *rchan = chan->trans_channel_data; -// struct rchan_buf *rbuf = rchan->buf; -// struct ltt_channel_buf_struct *lttbuf = chan->buf; -// long consumed_old; -// -// result = fd = open("trace.out", O_WRONLY | O_CREAT | O_TRUNC, 00644); -// if(result == -1) { -// perror("open"); -// return -1; -// } - -// for(;;) { -// write(STDOUT_FILENO, str, sizeof(str)); -// -// result = ltt_do_get_subbuf(rbuf, lttbuf, &consumed_old); -// if(result < 0) { -// CPRINTF("ltt_do_get_subbuf: error: %s", strerror(-result)); -// } -// else { -// CPRINTF("success!"); -// -// result = write(fd, rbuf->buf_data + (consumed_old & (2 * 4096-1)), 4096); -// ltt_do_put_subbuf(rbuf, lttbuf, consumed_old); -// } -// -// //CPRINTF("There seems to be %ld bytes available", SUBBUF_TRUNC(local_read(<tbuf->offset), rbuf->chan) - consumed_old); -// CPRINTF("Commit count %ld", local_read(<tbuf->commit_count[0])); -// -// -// sleep(1); -// } -} - -void start_consumer(void) -{ - int result; - - result = clone(consumer, consumer_stack+sizeof(consumer_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL); - if(result == -1) { - perror("clone"); - } -} void probe(const struct marker *mdata, void *probe_private, void *call_private, @@ -199,7 +60,6 @@ int main() init_int_handler(); - start_consumer(); printf("Hello, World!\n"); sleep(1); diff --git a/libtracectl/Makefile b/libtracectl/Makefile index 27803da..e304097 100644 --- a/libtracectl/Makefile +++ b/libtracectl/Makefile @@ -1,7 +1,9 @@ all: libtracectl.so libtracectl.so: tracectl.c - gcc -g -shared -fPIC -I../libmarkers -I../share $(CFLAGS) -o libtracectl.so tracectl.c + gcc -g -shared -fPIC -I../libmarkers -I../libtracing -I../share $(CFLAGS) -o libtracectl.so tracectl.c marker-control.c ../share/usterr.c clean: rm -rf *.so *.o + +.PHONY: libtracectl.so diff --git a/libtracectl/marker-control.c b/libtracectl/marker-control.c new file mode 100644 index 0000000..ab5413d --- /dev/null +++ b/libtracectl/marker-control.c @@ -0,0 +1,461 @@ +/* + * Copyright (C) 2007 Mathieu Desnoyers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * LTT marker control module over /proc + */ + +//ust// #include +//ust// #include +//ust// #include +//ust// #include +//ust// #include +//ust// #include +//ust// #include +//ust// #include +//ust// #include +//ust// #include +//ust// #include +//ust// #include +//ust// #include +#include "kernelcompat.h" +#include "list.h" +#include "tracer.h" +#include "usterr.h" + +#define DEFAULT_CHANNEL "cpu" +#define DEFAULT_PROBE "default" + +LIST_HEAD(probes_list); + +/* + * Mutex protecting the probe slab cache. + * Nests inside the traces mutex. + */ +DEFINE_MUTEX(probes_mutex); + +struct ltt_available_probe default_probe = { + .name = "default", + .format = NULL, + .probe_func = ltt_vtrace, + .callbacks[0] = ltt_serialize_data, +}; + +//ust//static struct kmem_cache *markers_loaded_cachep; +static LIST_HEAD(markers_loaded_list); +/* + * List sorted by name strcmp order. + */ +static LIST_HEAD(probes_registered_list); + +//ust// static struct proc_dir_entry *pentry; + +//ust// static struct file_operations ltt_fops; + +static struct ltt_available_probe *get_probe_from_name(const char *pname) +{ + struct ltt_available_probe *iter; + int comparison, found = 0; + + if (!pname) + pname = DEFAULT_PROBE; + list_for_each_entry(iter, &probes_registered_list, node) { + comparison = strcmp(pname, iter->name); + if (!comparison) + found = 1; + if (comparison <= 0) + break; + } + if (found) + return iter; + else + return NULL; +} + +static char *skip_spaces(char *buf) +{ + while (*buf != '\0' && isspace(*buf)) + buf++; + return buf; +} + +static char *skip_nonspaces(char *buf) +{ + while (*buf != '\0' && !isspace(*buf)) + buf++; + return buf; +} + +static void get_marker_string(char *buf, char **start, + char **end) +{ + *start = skip_spaces(buf); + *end = skip_nonspaces(*start); + **end = '\0'; +} + +int ltt_probe_register(struct ltt_available_probe *pdata) +{ + int ret = 0; + int comparison; + struct ltt_available_probe *iter; + + mutex_lock(&probes_mutex); + list_for_each_entry_reverse(iter, &probes_registered_list, node) { + comparison = strcmp(pdata->name, iter->name); + if (!comparison) { + ret = -EBUSY; + goto end; + } else if (comparison > 0) { + /* We belong to the location right after iter. */ + list_add(&pdata->node, &iter->node); + goto end; + } + } + /* Should be added at the head of the list */ + list_add(&pdata->node, &probes_registered_list); +end: + mutex_unlock(&probes_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(ltt_probe_register); + +/* + * Called when a probe does not want to be called anymore. + */ +int ltt_probe_unregister(struct ltt_available_probe *pdata) +{ + int ret = 0; + struct ltt_active_marker *amark, *tmp; + + mutex_lock(&probes_mutex); + list_for_each_entry_safe(amark, tmp, &markers_loaded_list, node) { + if (amark->probe == pdata) { + ret = marker_probe_unregister_private_data( + pdata->probe_func, amark); + if (ret) + goto end; + list_del(&amark->node); + free(amark); + } + } + list_del(&pdata->node); +end: + mutex_unlock(&probes_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(ltt_probe_unregister); + +/* + * Connect marker "mname" to probe "pname". + * Only allow _only_ probe instance to be connected to a marker. + */ +int ltt_marker_connect(const char *channel, const char *mname, + const char *pname) + +{ + int ret; + struct ltt_active_marker *pdata; + struct ltt_available_probe *probe; + + ltt_lock_traces(); + mutex_lock(&probes_mutex); + probe = get_probe_from_name(pname); + if (!probe) { + ret = -ENOENT; + goto end; + } + pdata = marker_get_private_data(channel, mname, probe->probe_func, 0); + if (pdata && !IS_ERR(pdata)) { + ret = -EEXIST; + goto end; + } + pdata = zmalloc(sizeof(struct ltt_active_marker)); + if (!pdata) { + ret = -ENOMEM; + goto end; + } + pdata->probe = probe; + /* + * ID has priority over channel in case of conflict. + */ + ret = marker_probe_register(channel, mname, NULL, + probe->probe_func, pdata); + if (ret) + free(pdata); + else + list_add(&pdata->node, &markers_loaded_list); +end: + mutex_unlock(&probes_mutex); + ltt_unlock_traces(); + return ret; +} +EXPORT_SYMBOL_GPL(ltt_marker_connect); + +/* + * Disconnect marker "mname", probe "pname". + */ +int ltt_marker_disconnect(const char *channel, const char *mname, + const char *pname) +{ + struct ltt_active_marker *pdata; + struct ltt_available_probe *probe; + int ret = 0; + + mutex_lock(&probes_mutex); + probe = get_probe_from_name(pname); + if (!probe) { + ret = -ENOENT; + goto end; + } + pdata = marker_get_private_data(channel, mname, probe->probe_func, 0); + if (IS_ERR(pdata)) { + ret = PTR_ERR(pdata); + goto end; + } else if (!pdata) { + /* + * Not registered by us. + */ + ret = -EPERM; + goto end; + } + ret = marker_probe_unregister(channel, mname, probe->probe_func, pdata); + if (ret) + goto end; + else { + list_del(&pdata->node); + free(pdata); + } +end: + mutex_unlock(&probes_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(ltt_marker_disconnect); + +/* + * function handling proc entry write. + * + * connect []] + * disconnect [] + */ +//ust// static ssize_t ltt_write(struct file *file, const char __user *buffer, +//ust// size_t count, loff_t *offset) +//ust// { +//ust// char *kbuf; +//ust// char *iter, *marker_action, *arg[4]; +//ust// ssize_t ret; +//ust// int i; +//ust// +//ust// if (!count) +//ust// return -EINVAL; +//ust// +//ust// kbuf = vmalloc(count + 1); +//ust// kbuf[count] = '\0'; /* Transform into a string */ +//ust// ret = copy_from_user(kbuf, buffer, count); +//ust// if (ret) { +//ust// ret = -EINVAL; +//ust// goto end; +//ust// } +//ust// get_marker_string(kbuf, &marker_action, &iter); +//ust// if (!marker_action || marker_action == iter) { +//ust// ret = -EINVAL; +//ust// goto end; +//ust// } +//ust// for (i = 0; i < 4; i++) { +//ust// arg[i] = NULL; +//ust// if (iter < kbuf + count) { +//ust// iter++; /* skip the added '\0' */ +//ust// get_marker_string(iter, &arg[i], &iter); +//ust// if (arg[i] == iter) +//ust// arg[i] = NULL; +//ust// } +//ust// } +//ust// +//ust// if (!arg[0] || !arg[1]) { +//ust// ret = -EINVAL; +//ust// goto end; +//ust// } +//ust// +//ust// if (!strcmp(marker_action, "connect")) { +//ust// ret = ltt_marker_connect(arg[0], arg[1], arg[2]); +//ust// if (ret) +//ust// goto end; +//ust// } else if (!strcmp(marker_action, "disconnect")) { +//ust// ret = ltt_marker_disconnect(arg[0], arg[1], arg[2]); +//ust// if (ret) +//ust// goto end; +//ust// } +//ust// ret = count; +//ust// end: +//ust// vfree(kbuf); +//ust// return ret; +//ust// } +//ust// +//ust// static void *s_next(struct seq_file *m, void *p, loff_t *pos) +//ust// { +//ust// struct marker_iter *iter = m->private; +//ust// +//ust// marker_iter_next(iter); +//ust// if (!iter->marker) { +//ust// /* +//ust// * Setting the iter module to -1UL will make sure +//ust// * that no module can possibly hold the current marker. +//ust// */ +//ust// iter->module = (void *)-1UL; +//ust// return NULL; +//ust// } +//ust// return iter->marker; +//ust// } +//ust// +//ust// static void *s_start(struct seq_file *m, loff_t *pos) +//ust// { +//ust// struct marker_iter *iter = m->private; +//ust// +//ust// if (!*pos) +//ust// marker_iter_reset(iter); +//ust// marker_iter_start(iter); +//ust// if (!iter->marker) { +//ust// /* +//ust// * Setting the iter module to -1UL will make sure +//ust// * that no module can possibly hold the current marker. +//ust// */ +//ust// iter->module = (void *)-1UL; +//ust// return NULL; +//ust// } +//ust// return iter->marker; +//ust// } +//ust// +//ust// static void s_stop(struct seq_file *m, void *p) +//ust// { +//ust// marker_iter_stop(m->private); +//ust// } +//ust// +//ust// static int s_show(struct seq_file *m, void *p) +//ust// { +//ust// struct marker_iter *iter = m->private; +//ust// +//ust// seq_printf(m, "channel: %s marker: %s format: \"%s\" state: %d " +//ust// "event_id: %hu call: 0x%p probe %s : 0x%p\n", +//ust// iter->marker->channel, +//ust// iter->marker->name, iter->marker->format, +//ust// _imv_read(iter->marker->state), +//ust// iter->marker->event_id, +//ust// iter->marker->call, +//ust// iter->marker->ptype ? "multi" : "single", +//ust// iter->marker->ptype ? +//ust// (void*)iter->marker->multi : (void*)iter->marker->single.func); +//ust// return 0; +//ust// } +//ust// +//ust// static const struct seq_operations ltt_seq_op = { +//ust// .start = s_start, +//ust// .next = s_next, +//ust// .stop = s_stop, +//ust// .show = s_show, +//ust// }; +//ust// +//ust// static int ltt_open(struct inode *inode, struct file *file) +//ust// { +//ust// /* +//ust// * Iterator kept in m->private. +//ust// * Restart iteration on all modules between reads because we do not lock +//ust// * the module mutex between those. +//ust// */ +//ust// int ret; +//ust// struct marker_iter *iter; +//ust// +//ust// iter = kzalloc(sizeof(*iter), GFP_KERNEL); +//ust// if (!iter) +//ust// return -ENOMEM; +//ust// +//ust// ret = seq_open(file, <t_seq_op); +//ust// if (ret == 0) +//ust// ((struct seq_file *)file->private_data)->private = iter; +//ust// else +//ust// kfree(iter); +//ust// return ret; +//ust// } +//ust// +//ust// static struct file_operations ltt_fops = { +//ust// .write = ltt_write, +//ust// .open = ltt_open, +//ust// .read = seq_read, +//ust// .llseek = seq_lseek, +//ust// .release = seq_release_private, +//ust// }; + +static void disconnect_all_markers(void) +{ + struct ltt_active_marker *pdata, *tmp; + + list_for_each_entry_safe(pdata, tmp, &markers_loaded_list, node) { + marker_probe_unregister_private_data(pdata->probe->probe_func, + pdata); + list_del(&pdata->node); + free(pdata); + } +} + +static char initialized = 0; + +void __attribute__((constructor)) init_marker_control(void) +{ + if(!initialized) { + int ret; + +//ust// pentry = create_proc_entry("ltt", S_IRUSR|S_IWUSR, NULL); +//ust// if (!pentry) +//ust// return -EBUSY; +//ust// markers_loaded_cachep = KMEM_CACHE(ltt_active_marker, 0); + + ret = ltt_probe_register(&default_probe); + BUG_ON(ret); + ret = ltt_marker_connect("metadata", "core_marker_format", + DEFAULT_PROBE); + BUG_ON(ret); + ret = ltt_marker_connect("metadata", "core_marker_id", DEFAULT_PROBE); + BUG_ON(ret); +//ust// pentry->proc_fops = <t_fops; + + initialized = 1; + } + + return 0; +} +//ust// module_init(marker_control_init); + +static void __exit marker_control_exit(void) +{ + int ret; + +//ust// remove_proc_entry("ltt", NULL); + ret = ltt_marker_disconnect("metadata", "core_marker_format", + DEFAULT_PROBE); + BUG_ON(ret); + ret = ltt_marker_disconnect("metadata", "core_marker_id", + DEFAULT_PROBE); + BUG_ON(ret); + ret = ltt_probe_unregister(&default_probe); + BUG_ON(ret); + disconnect_all_markers(); +//ust// kmem_cache_destroy(markers_loaded_cachep); +//ust// marker_synchronize_unregister(); +} +//ust// module_exit(marker_control_exit); + +//ust// MODULE_LICENSE("GPL"); +//ust// MODULE_AUTHOR("Mathieu Desnoyers"); +//ust// MODULE_DESCRIPTION("Linux Trace Toolkit Marker Control"); diff --git a/libtracectl/tracectl.c b/libtracectl/tracectl.c index ab62adf..1725bca 100644 --- a/libtracectl/tracectl.c +++ b/libtracectl/tracectl.c @@ -5,8 +5,11 @@ #include #include #include +#include #include "marker.h" +#include "tracer.h" +#include "usterr.h" #define UNIX_PATH_MAX 108 @@ -17,13 +20,15 @@ #define DBG(fmt, args...) fprintf(stderr, fmt "\n", ## args) #define WARN(fmt, args...) fprintf(stderr, "usertrace: WARNING: " fmt "\n", ## args) -#define ERR(fmt, args...) fprintf(stderr, "usertrace: ERROR: " fmt "\n", ## args) +#define ERR(fmt, args...) fprintf(stderr, "usertrace: ERROR: " fmt "\n", ## args); fflush(stderr) #define PERROR(call) perror("usertrace: ERROR: " call) #define MAX_MSG_SIZE (100) #define MSG_NOTIF 1 #define MSG_REGISTER_NOTIF 2 +char consumer_stack[10000]; + struct tracecmd { /* no padding */ uint32_t size; uint16_t command; @@ -47,6 +52,126 @@ pid_t mypid; char mysocketfile[UNIX_PATH_MAX] = ""; int pfd = -1; +struct consumer_channel { + int fd; + struct ltt_channel_struct *chan; +}; + +int consumer(void *arg) +{ + int result; + int fd; + char str[] = "Hello, this is the consumer.\n"; + struct ltt_trace_struct *trace; + struct consumer_channel *consumer_channels; + int i; + char trace_name[] = "auto"; + + ltt_lock_traces(); + trace = _ltt_trace_find(trace_name); + ltt_unlock_traces(); + + if(trace == NULL) { + CPRINTF("cannot find trace!"); + return 1; + } + + consumer_channels = (struct consumer_channel *) malloc(trace->nr_channels * sizeof(struct consumer_channel)); + if(consumer_channels == NULL) { + ERR("malloc returned NULL"); + return 1; + } + + CPRINTF("opening trace files"); + for(i=0; inr_channels; i++) { + char tmp[100]; + struct ltt_channel_struct *chan = &trace->channels[i]; + + consumer_channels[i].chan = chan; + + snprintf(tmp, sizeof(tmp), "trace/%s", chan->channel_name); + result = consumer_channels[i].fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 00644); + if(result == -1) { + perror("open"); + return -1; + } + CPRINTF("\topened trace file %s", tmp); + + } + CPRINTF("done opening trace files"); + + for(;;) { + /*wait*/ + + for(i=0; inr_channels; i++) { + struct rchan *rchan = consumer_channels[i].chan->trans_channel_data; + struct rchan_buf *rbuf = rchan->buf; + struct ltt_channel_buf_struct *lttbuf = consumer_channels[i].chan->buf; + long consumed_old; + + result = ltt_do_get_subbuf(rbuf, lttbuf, &consumed_old); + if(result < 0) { + CPRINTF("ltt_do_get_subbuf: error: %s", strerror(-result)); + } + else { + CPRINTF("success!"); + + result = write(consumer_channels[i].fd, rbuf->buf_data + (consumed_old & (2 * 4096-1)), 4096); + ltt_do_put_subbuf(rbuf, lttbuf, consumed_old); + } + } + + sleep(1); + } + +// CPRINTF("consumer: got a trace: %s with %d channels\n", trace_name, trace->nr_channels); +// +// struct ltt_channel_struct *chan = &trace->channels[0]; +// +// CPRINTF("channel 1 (%s) active=%u", chan->channel_name, chan->active & 1); + +// struct rchan *rchan = chan->trans_channel_data; +// struct rchan_buf *rbuf = rchan->buf; +// struct ltt_channel_buf_struct *lttbuf = chan->buf; +// long consumed_old; +// +// result = fd = open("trace.out", O_WRONLY | O_CREAT | O_TRUNC, 00644); +// if(result == -1) { +// perror("open"); +// return -1; +// } + +// for(;;) { +// write(STDOUT_FILENO, str, sizeof(str)); +// +// result = ltt_do_get_subbuf(rbuf, lttbuf, &consumed_old); +// if(result < 0) { +// CPRINTF("ltt_do_get_subbuf: error: %s", strerror(-result)); +// } +// else { +// CPRINTF("success!"); +// +// result = write(fd, rbuf->buf_data + (consumed_old & (2 * 4096-1)), 4096); +// ltt_do_put_subbuf(rbuf, lttbuf, consumed_old); +// } +// +// //CPRINTF("There seems to be %ld bytes available", SUBBUF_TRUNC(local_read(<tbuf->offset), rbuf->chan) - consumed_old); +// CPRINTF("Commit count %ld", local_read(<tbuf->commit_count[0])); +// +// +// sleep(1); +// } +} + +void start_consumer(void) +{ + int result; + + result = clone(consumer, consumer_stack+sizeof(consumer_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL); + if(result == -1) { + perror("clone"); + } +} static void print_markers(void) { @@ -310,6 +435,8 @@ static void __attribute__((constructor(101))) init0() } } +static void fini(void); + static void __attribute__((constructor(1000))) init() { int result; @@ -359,6 +486,7 @@ static void __attribute__((constructor(1000))) init() ERR("ltt_trace_start failed"); return; } + start_consumer(); } /* Must create socket before signal handler to prevent races @@ -386,5 +514,24 @@ static void __attribute__((constructor(1000))) init() static void __attribute__((destructor)) fini() { + int result; + + /* if trace running, finish it */ + + DBG("destructor stopping traces"); + + result = ltt_trace_stop("auto"); + if(result == -1) { + ERR("ltt_trace_stop error"); + } + + result = ltt_trace_destroy("auto"); + if(result == -1) { + ERR("ltt_trace_destroy error"); + } + + /* FIXME: wait for the consumer to be done */ + sleep(10); + destroy_socket(); } diff --git a/libtracing/marker-control.c b/libtracing/marker-control.c deleted file mode 100644 index ab5413d..0000000 --- a/libtracing/marker-control.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (C) 2007 Mathieu Desnoyers - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * LTT marker control module over /proc - */ - -//ust// #include -//ust// #include -//ust// #include -//ust// #include -//ust// #include -//ust// #include -//ust// #include -//ust// #include -//ust// #include -//ust// #include -//ust// #include -//ust// #include -//ust// #include -#include "kernelcompat.h" -#include "list.h" -#include "tracer.h" -#include "usterr.h" - -#define DEFAULT_CHANNEL "cpu" -#define DEFAULT_PROBE "default" - -LIST_HEAD(probes_list); - -/* - * Mutex protecting the probe slab cache. - * Nests inside the traces mutex. - */ -DEFINE_MUTEX(probes_mutex); - -struct ltt_available_probe default_probe = { - .name = "default", - .format = NULL, - .probe_func = ltt_vtrace, - .callbacks[0] = ltt_serialize_data, -}; - -//ust//static struct kmem_cache *markers_loaded_cachep; -static LIST_HEAD(markers_loaded_list); -/* - * List sorted by name strcmp order. - */ -static LIST_HEAD(probes_registered_list); - -//ust// static struct proc_dir_entry *pentry; - -//ust// static struct file_operations ltt_fops; - -static struct ltt_available_probe *get_probe_from_name(const char *pname) -{ - struct ltt_available_probe *iter; - int comparison, found = 0; - - if (!pname) - pname = DEFAULT_PROBE; - list_for_each_entry(iter, &probes_registered_list, node) { - comparison = strcmp(pname, iter->name); - if (!comparison) - found = 1; - if (comparison <= 0) - break; - } - if (found) - return iter; - else - return NULL; -} - -static char *skip_spaces(char *buf) -{ - while (*buf != '\0' && isspace(*buf)) - buf++; - return buf; -} - -static char *skip_nonspaces(char *buf) -{ - while (*buf != '\0' && !isspace(*buf)) - buf++; - return buf; -} - -static void get_marker_string(char *buf, char **start, - char **end) -{ - *start = skip_spaces(buf); - *end = skip_nonspaces(*start); - **end = '\0'; -} - -int ltt_probe_register(struct ltt_available_probe *pdata) -{ - int ret = 0; - int comparison; - struct ltt_available_probe *iter; - - mutex_lock(&probes_mutex); - list_for_each_entry_reverse(iter, &probes_registered_list, node) { - comparison = strcmp(pdata->name, iter->name); - if (!comparison) { - ret = -EBUSY; - goto end; - } else if (comparison > 0) { - /* We belong to the location right after iter. */ - list_add(&pdata->node, &iter->node); - goto end; - } - } - /* Should be added at the head of the list */ - list_add(&pdata->node, &probes_registered_list); -end: - mutex_unlock(&probes_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(ltt_probe_register); - -/* - * Called when a probe does not want to be called anymore. - */ -int ltt_probe_unregister(struct ltt_available_probe *pdata) -{ - int ret = 0; - struct ltt_active_marker *amark, *tmp; - - mutex_lock(&probes_mutex); - list_for_each_entry_safe(amark, tmp, &markers_loaded_list, node) { - if (amark->probe == pdata) { - ret = marker_probe_unregister_private_data( - pdata->probe_func, amark); - if (ret) - goto end; - list_del(&amark->node); - free(amark); - } - } - list_del(&pdata->node); -end: - mutex_unlock(&probes_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(ltt_probe_unregister); - -/* - * Connect marker "mname" to probe "pname". - * Only allow _only_ probe instance to be connected to a marker. - */ -int ltt_marker_connect(const char *channel, const char *mname, - const char *pname) - -{ - int ret; - struct ltt_active_marker *pdata; - struct ltt_available_probe *probe; - - ltt_lock_traces(); - mutex_lock(&probes_mutex); - probe = get_probe_from_name(pname); - if (!probe) { - ret = -ENOENT; - goto end; - } - pdata = marker_get_private_data(channel, mname, probe->probe_func, 0); - if (pdata && !IS_ERR(pdata)) { - ret = -EEXIST; - goto end; - } - pdata = zmalloc(sizeof(struct ltt_active_marker)); - if (!pdata) { - ret = -ENOMEM; - goto end; - } - pdata->probe = probe; - /* - * ID has priority over channel in case of conflict. - */ - ret = marker_probe_register(channel, mname, NULL, - probe->probe_func, pdata); - if (ret) - free(pdata); - else - list_add(&pdata->node, &markers_loaded_list); -end: - mutex_unlock(&probes_mutex); - ltt_unlock_traces(); - return ret; -} -EXPORT_SYMBOL_GPL(ltt_marker_connect); - -/* - * Disconnect marker "mname", probe "pname". - */ -int ltt_marker_disconnect(const char *channel, const char *mname, - const char *pname) -{ - struct ltt_active_marker *pdata; - struct ltt_available_probe *probe; - int ret = 0; - - mutex_lock(&probes_mutex); - probe = get_probe_from_name(pname); - if (!probe) { - ret = -ENOENT; - goto end; - } - pdata = marker_get_private_data(channel, mname, probe->probe_func, 0); - if (IS_ERR(pdata)) { - ret = PTR_ERR(pdata); - goto end; - } else if (!pdata) { - /* - * Not registered by us. - */ - ret = -EPERM; - goto end; - } - ret = marker_probe_unregister(channel, mname, probe->probe_func, pdata); - if (ret) - goto end; - else { - list_del(&pdata->node); - free(pdata); - } -end: - mutex_unlock(&probes_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(ltt_marker_disconnect); - -/* - * function handling proc entry write. - * - * connect []] - * disconnect [] - */ -//ust// static ssize_t ltt_write(struct file *file, const char __user *buffer, -//ust// size_t count, loff_t *offset) -//ust// { -//ust// char *kbuf; -//ust// char *iter, *marker_action, *arg[4]; -//ust// ssize_t ret; -//ust// int i; -//ust// -//ust// if (!count) -//ust// return -EINVAL; -//ust// -//ust// kbuf = vmalloc(count + 1); -//ust// kbuf[count] = '\0'; /* Transform into a string */ -//ust// ret = copy_from_user(kbuf, buffer, count); -//ust// if (ret) { -//ust// ret = -EINVAL; -//ust// goto end; -//ust// } -//ust// get_marker_string(kbuf, &marker_action, &iter); -//ust// if (!marker_action || marker_action == iter) { -//ust// ret = -EINVAL; -//ust// goto end; -//ust// } -//ust// for (i = 0; i < 4; i++) { -//ust// arg[i] = NULL; -//ust// if (iter < kbuf + count) { -//ust// iter++; /* skip the added '\0' */ -//ust// get_marker_string(iter, &arg[i], &iter); -//ust// if (arg[i] == iter) -//ust// arg[i] = NULL; -//ust// } -//ust// } -//ust// -//ust// if (!arg[0] || !arg[1]) { -//ust// ret = -EINVAL; -//ust// goto end; -//ust// } -//ust// -//ust// if (!strcmp(marker_action, "connect")) { -//ust// ret = ltt_marker_connect(arg[0], arg[1], arg[2]); -//ust// if (ret) -//ust// goto end; -//ust// } else if (!strcmp(marker_action, "disconnect")) { -//ust// ret = ltt_marker_disconnect(arg[0], arg[1], arg[2]); -//ust// if (ret) -//ust// goto end; -//ust// } -//ust// ret = count; -//ust// end: -//ust// vfree(kbuf); -//ust// return ret; -//ust// } -//ust// -//ust// static void *s_next(struct seq_file *m, void *p, loff_t *pos) -//ust// { -//ust// struct marker_iter *iter = m->private; -//ust// -//ust// marker_iter_next(iter); -//ust// if (!iter->marker) { -//ust// /* -//ust// * Setting the iter module to -1UL will make sure -//ust// * that no module can possibly hold the current marker. -//ust// */ -//ust// iter->module = (void *)-1UL; -//ust// return NULL; -//ust// } -//ust// return iter->marker; -//ust// } -//ust// -//ust// static void *s_start(struct seq_file *m, loff_t *pos) -//ust// { -//ust// struct marker_iter *iter = m->private; -//ust// -//ust// if (!*pos) -//ust// marker_iter_reset(iter); -//ust// marker_iter_start(iter); -//ust// if (!iter->marker) { -//ust// /* -//ust// * Setting the iter module to -1UL will make sure -//ust// * that no module can possibly hold the current marker. -//ust// */ -//ust// iter->module = (void *)-1UL; -//ust// return NULL; -//ust// } -//ust// return iter->marker; -//ust// } -//ust// -//ust// static void s_stop(struct seq_file *m, void *p) -//ust// { -//ust// marker_iter_stop(m->private); -//ust// } -//ust// -//ust// static int s_show(struct seq_file *m, void *p) -//ust// { -//ust// struct marker_iter *iter = m->private; -//ust// -//ust// seq_printf(m, "channel: %s marker: %s format: \"%s\" state: %d " -//ust// "event_id: %hu call: 0x%p probe %s : 0x%p\n", -//ust// iter->marker->channel, -//ust// iter->marker->name, iter->marker->format, -//ust// _imv_read(iter->marker->state), -//ust// iter->marker->event_id, -//ust// iter->marker->call, -//ust// iter->marker->ptype ? "multi" : "single", -//ust// iter->marker->ptype ? -//ust// (void*)iter->marker->multi : (void*)iter->marker->single.func); -//ust// return 0; -//ust// } -//ust// -//ust// static const struct seq_operations ltt_seq_op = { -//ust// .start = s_start, -//ust// .next = s_next, -//ust// .stop = s_stop, -//ust// .show = s_show, -//ust// }; -//ust// -//ust// static int ltt_open(struct inode *inode, struct file *file) -//ust// { -//ust// /* -//ust// * Iterator kept in m->private. -//ust// * Restart iteration on all modules between reads because we do not lock -//ust// * the module mutex between those. -//ust// */ -//ust// int ret; -//ust// struct marker_iter *iter; -//ust// -//ust// iter = kzalloc(sizeof(*iter), GFP_KERNEL); -//ust// if (!iter) -//ust// return -ENOMEM; -//ust// -//ust// ret = seq_open(file, <t_seq_op); -//ust// if (ret == 0) -//ust// ((struct seq_file *)file->private_data)->private = iter; -//ust// else -//ust// kfree(iter); -//ust// return ret; -//ust// } -//ust// -//ust// static struct file_operations ltt_fops = { -//ust// .write = ltt_write, -//ust// .open = ltt_open, -//ust// .read = seq_read, -//ust// .llseek = seq_lseek, -//ust// .release = seq_release_private, -//ust// }; - -static void disconnect_all_markers(void) -{ - struct ltt_active_marker *pdata, *tmp; - - list_for_each_entry_safe(pdata, tmp, &markers_loaded_list, node) { - marker_probe_unregister_private_data(pdata->probe->probe_func, - pdata); - list_del(&pdata->node); - free(pdata); - } -} - -static char initialized = 0; - -void __attribute__((constructor)) init_marker_control(void) -{ - if(!initialized) { - int ret; - -//ust// pentry = create_proc_entry("ltt", S_IRUSR|S_IWUSR, NULL); -//ust// if (!pentry) -//ust// return -EBUSY; -//ust// markers_loaded_cachep = KMEM_CACHE(ltt_active_marker, 0); - - ret = ltt_probe_register(&default_probe); - BUG_ON(ret); - ret = ltt_marker_connect("metadata", "core_marker_format", - DEFAULT_PROBE); - BUG_ON(ret); - ret = ltt_marker_connect("metadata", "core_marker_id", DEFAULT_PROBE); - BUG_ON(ret); -//ust// pentry->proc_fops = <t_fops; - - initialized = 1; - } - - return 0; -} -//ust// module_init(marker_control_init); - -static void __exit marker_control_exit(void) -{ - int ret; - -//ust// remove_proc_entry("ltt", NULL); - ret = ltt_marker_disconnect("metadata", "core_marker_format", - DEFAULT_PROBE); - BUG_ON(ret); - ret = ltt_marker_disconnect("metadata", "core_marker_id", - DEFAULT_PROBE); - BUG_ON(ret); - ret = ltt_probe_unregister(&default_probe); - BUG_ON(ret); - disconnect_all_markers(); -//ust// kmem_cache_destroy(markers_loaded_cachep); -//ust// marker_synchronize_unregister(); -} -//ust// module_exit(marker_control_exit); - -//ust// MODULE_LICENSE("GPL"); -//ust// MODULE_AUTHOR("Mathieu Desnoyers"); -//ust// MODULE_DESCRIPTION("Linux Trace Toolkit Marker Control"); diff --git a/share/usterr.h b/share/usterr.h index 366718d..83b3222 100644 --- a/share/usterr.h +++ b/share/usterr.h @@ -10,4 +10,7 @@ #define BUG_ON(condition) do { if (unlikely(condition)) ERR("condition not respected (BUG)"); } while(0) #define WARN_ON(condition) do { if (unlikely(condition)) WARN("condition not respected on line %s:%d", __FILE__, __LINE__); } while(0) +#define CPRINTF(fmt, args...) safe_printf(fmt "\n", ## args) + + #endif /* USTERR_H */