Update version to 0.16
[ust.git] / libust / tracectl.c
index 2e9436520e099947817825741928192958a7d9d3..410b1c72e75cb52a2fd24a2898c590f31c011455 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #define _GNU_SOURCE
+#define _LGPL_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <fcntl.h>
 #include <poll.h>
 #include <regex.h>
-#include <urcu/uatomic_arch.h>
+#include <urcu/uatomic.h>
 #include <urcu/list.h>
 
 #include <ust/marker.h>
 #include <ust/tracepoint.h>
+#include <ust/tracepoint-internal.h>
 #include <ust/tracectl.h>
+#include <ust/clock.h>
 #include "tracer.h"
-#include "usterr.h"
+#include "usterr_signal_safe.h"
 #include "ustcomm.h"
 #include "buffers.h"
 #include "marker-control.h"
 
-#define USTSIGNAL SIGIO
-
-#define MAX_MSG_SIZE (100)
-#define MSG_NOTIF 1
-#define MSG_REGISTER_NOTIF 2
-
 /* This should only be accessed by the constructor, before the creation
  * of the listener, and then only by the listener.
  */
 s64 pidunique = -1LL;
 
+/* The process pid is used to detect a non-traceable fork
+ * and allow the non-traceable fork to be ignored
+ * by destructor sequences in libust
+ */
+static pid_t processpid = 0;
+
+static struct ustcomm_header _receive_header;
+static struct ustcomm_header *receive_header = &_receive_header;
+static char receive_buffer[USTCOMM_BUFFER_SIZE];
+static char send_buffer[USTCOMM_BUFFER_SIZE];
+
 static int epoll_fd;
+
+/*
+ * Listener thread data vs fork() protection mechanism. Ensures that no listener
+ * thread mutexes and data structures are being concurrently modified or held by
+ * other threads when fork() is executed.
+ */
+static pthread_mutex_t listener_thread_data_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* Mutex protecting listen_sock. Nests inside listener_thread_data_mutex. */
+static pthread_mutex_t listen_sock_mutex = PTHREAD_MUTEX_INITIALIZER;
 static struct ustcomm_sock *listen_sock;
 
 extern struct chan_info_struct chan_infos[];
 
-static struct list_head open_buffers_list = LIST_HEAD_INIT(open_buffers_list);
-
-static struct list_head ust_socks = LIST_HEAD_INIT(ust_socks);
+static struct cds_list_head ust_socks = CDS_LIST_HEAD_INIT(ust_socks);
 
 /* volatile because shared between the listener and the main thread */
 int buffers_to_export = 0;
 
+int ust_clock_source;
+
 static long long make_pidunique(void)
 {
        s64 retval;
        struct timeval tv;
-       
+
        gettimeofday(&tv, NULL);
 
        retval = tv.tv_sec;
@@ -82,39 +100,99 @@ static long long make_pidunique(void)
        return retval;
 }
 
-static void print_markers(FILE *fp)
+static void print_ust_marker(FILE *fp)
 {
-       struct marker_iter iter;
-
-       lock_markers();
-       marker_iter_reset(&iter);
-       marker_iter_start(&iter);
-
-       while (iter.marker) {
-               fprintf(fp, "marker: %s/%s %d \"%s\" %p\n",
-                       iter.marker->channel,
-                       iter.marker->name,
-                       (int)imv_read(iter.marker->state),
-                       iter.marker->format,
-                       iter.marker->location);
-               marker_iter_next(&iter);
-       }
-       unlock_markers();
+       struct ust_marker_iter iter;
+
+       ust_marker_iter_reset(&iter);
+       ust_marker_iter_start(&iter);
+
+       while (iter.ust_marker) {
+               fprintf(fp, "ust_marker: %s/%s %d \"%s\" %p\n",
+                       (*iter.ust_marker)->channel,
+                       (*iter.ust_marker)->name,
+                       (int)(*iter.ust_marker)->state,
+                       (*iter.ust_marker)->format,
+                       NULL);  /*
+                                * location is null for now, will be added
+                                * to a different table.
+                                */
+               ust_marker_iter_next(&iter);
+       }
+       ust_marker_iter_stop(&iter);
 }
 
 static void print_trace_events(FILE *fp)
 {
        struct trace_event_iter iter;
 
-       lock_trace_events();
        trace_event_iter_reset(&iter);
        trace_event_iter_start(&iter);
 
        while (iter.trace_event) {
-               fprintf(fp, "trace_event: %s\n", iter.trace_event->name);
+               fprintf(fp, "trace_event: %s\n", (*iter.trace_event)->name);
                trace_event_iter_next(&iter);
        }
-       unlock_trace_events();
+       trace_event_iter_stop(&iter);
+}
+
+static int connect_ustconsumer(void)
+{
+       int result, fd;
+       char default_daemon_path[] = SOCK_DIR "/ustconsumer";
+       char *explicit_daemon_path, *daemon_path;
+
+       explicit_daemon_path = getenv("UST_DAEMON_SOCKET");
+       if (explicit_daemon_path) {
+               daemon_path = explicit_daemon_path;
+       } else {
+               daemon_path = default_daemon_path;
+       }
+
+       DBG("Connecting to daemon_path %s", daemon_path);
+
+       result = ustcomm_connect_path(daemon_path, &fd);
+       if (result < 0) {
+               WARN("connect_ustconsumer failed, daemon_path: %s",
+                    daemon_path);
+               return result;
+       }
+
+       return fd;
+}
+
+
+static void request_buffer_consumer(int sock,
+                                   const char *trace,
+                                   const char *channel,
+                                   int cpu)
+{
+       struct ustcomm_header send_header, recv_header;
+       struct ustcomm_buffer_info buf_inf;
+       int result = 0;
+
+       result = ustcomm_pack_buffer_info(&send_header,
+                                         &buf_inf,
+                                         trace,
+                                         channel,
+                                         cpu);
+
+       if (result < 0) {
+               ERR("failed to pack buffer info message %s_%d",
+                   channel, cpu);
+               return;
+       }
+
+       buf_inf.pid = getpid();
+       send_header.command = CONSUME_BUFFER;
+
+       result = ustcomm_req(sock, &send_header, (char *) &buf_inf,
+                            &recv_header, NULL);
+       if (result <= 0) {
+               PERROR("request for buffer consumer failed, is the daemon online?");
+       }
+
+       return;
 }
 
 /* Ask the daemon to collect a trace called trace_name and being
@@ -126,171 +204,69 @@ static void print_trace_events(FILE *fp)
 
 static void inform_consumer_daemon(const char *trace_name)
 {
-       int i,j;
+       int sock, i,j;
        struct ust_trace *trace;
-       pid_t pid = getpid();
-       int result;
+       const char *ch_name;
+
+       sock = connect_ustconsumer();
+       if (sock < 0) {
+               return;
+       }
+
+       DBG("Connected to ustconsumer");
 
        ltt_lock_traces();
 
        trace = _ltt_trace_find(trace_name);
        if (trace == NULL) {
                WARN("inform_consumer_daemon: could not find trace \"%s\"; it is probably already destroyed", trace_name);
-               goto finish;
+               goto unlock_traces;
        }
 
        for (i=0; i < trace->nr_channels; i++) {
                if (trace->channels[i].request_collection) {
                        /* iterate on all cpus */
                        for (j=0; j<trace->channels[i].n_cpus; j++) {
-                               char *buf;
-                               if (asprintf(&buf, "%s_%d", trace->channels[i].channel_name, j) < 0) {
-                                       ERR("inform_consumer_daemon : asprintf failed (%s_%d)",
-                                          trace->channels[i].channel_name, j);
-                                       goto finish;
-                               }
-                               result = ustcomm_request_consumer(pid, buf);
-                               if (result == -1) {
-                                       WARN("Failed to request collection for channel %s. Is the daemon available?",
-                                            trace->channels[i].channel_name);
-                                       /* continue even if fail */
-                               }
-                               free(buf);
-                               STORE_SHARED(buffers_to_export, LOAD_SHARED(buffers_to_export)+1);
+                               ch_name = trace->channels[i].channel_name;
+                               request_buffer_consumer(sock, trace_name,
+                                                       ch_name, j);
+                               CMM_STORE_SHARED(buffers_to_export,
+                                            CMM_LOAD_SHARED(buffers_to_export)+1);
                        }
                }
        }
 
-       finish:
+unlock_traces:
        ltt_unlock_traces();
-}
-
-void seperate_channel_cpu(const char *channel_and_cpu, char **channel, int *cpu)
-{
-       const char *sep;
 
-       sep = rindex(channel_and_cpu, '_');
-       if (sep == NULL) {
-               *cpu = -1;
-               sep = channel_and_cpu + strlen(channel_and_cpu);
-       } else {
-               *cpu = atoi(sep+1);
-       }
-
-       if (asprintf(channel, "%.*s", (int)(sep-channel_and_cpu), channel_and_cpu) < 0) {
-               ERR("seperate_channel_cpu : asprintf failed (%.*s)",
-                   (int)(sep-channel_and_cpu), channel_and_cpu);
-               return;
-       }
+       close(sock);
 }
 
-static int do_cmd_get_shmid(const char *recvbuf, int sock)
+static struct ust_channel *find_channel(const char *ch_name,
+                                       struct ust_trace *trace)
 {
-       int retval = 0;
-       struct ust_trace *trace;
-       char trace_name[] = "auto";
        int i;
-       char *channel_and_cpu;
-       int found = 0;
-       int result;
-       char *ch_name;
-       int ch_cpu;
-
-       DBG("get_shmid");
-
-       channel_and_cpu = nth_token(recvbuf, 1);
-       if (channel_and_cpu == NULL) {
-               ERR("cannot parse channel");
-               retval = -1;
-               goto end;
-       }
-
-       seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
-       if (ch_cpu == -1) {
-               ERR("problem parsing channel name");
-               retval = -1;
-               goto free_short_chan_name;
-       }
-
-       ltt_lock_traces();
-       trace = _ltt_trace_find(trace_name);
-       ltt_unlock_traces();
-
-       if (trace == NULL) {
-               ERR("cannot find trace!");
-               retval = -1;
-               goto free_short_chan_name;
-       }
 
        for (i=0; i<trace->nr_channels; i++) {
-               struct ust_channel *channel = &trace->channels[i];
-               struct ust_buffer *buf = channel->buf[ch_cpu];
-
                if (!strcmp(trace->channels[i].channel_name, ch_name)) {
-                       char *reply;
-
-//                     DBG("the shmid for the requested channel is %d", buf->shmid);
-//                     DBG("the shmid for its buffer structure is %d", channel->buf_struct_shmids);
-                       if (asprintf(&reply, "%d %d", buf->shmid, channel->buf_struct_shmids[ch_cpu]) < 0) {
-                               ERR("do_cmd_get_shmid : asprintf failed (%d %d)",
-                                   buf->shmid, channel->buf_struct_shmids[ch_cpu]);
-                               retval = -1;
-                               goto free_short_chan_name;
-                       }
-
-                       result = ustcomm_send_reply(reply, sock);
-                       if (result) {
-                               ERR("ustcomm_send_reply failed");
-                               free(reply);
-                               retval = -1;
-                               goto free_short_chan_name;
-                       }
-
-                       free(reply);
-
-                       found = 1;
-                       break;
+                       return &trace->channels[i];
                }
        }
 
-       if (!found) {
-               ERR("channel not found (%s)", channel_and_cpu);
-       }
-
-       free_short_chan_name:
-       free(ch_name);
-
-       end:
-       return retval;
+       return NULL;
 }
 
-static int do_cmd_get_n_subbufs(const char *recvbuf, int sock)
+static int get_buffer_shmid_pipe_fd(const char *trace_name, const char *ch_name,
+                                   int ch_cpu,
+                                   int *buf_shmid,
+                                   int *buf_struct_shmid,
+                                   int *buf_pipe_fd)
 {
-       int retval = 0;
        struct ust_trace *trace;
-       char trace_name[] = "auto";
-       int i;
-       char *channel_and_cpu;
-       int found = 0;
-       int result;
-       char *ch_name;
-       int ch_cpu;
-
-       DBG("get_n_subbufs");
-
-       channel_and_cpu = nth_token(recvbuf, 1);
-       if (channel_and_cpu == NULL) {
-               ERR("cannot parse channel");
-               retval = -1;
-               goto end;
-       }
+       struct ust_channel *channel;
+       struct ust_buffer *buf;
 
-       seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
-       if (ch_cpu == -1) {
-               ERR("problem parsing channel name");
-               retval = -1;
-               goto free_short_chan_name;
-       }
+       DBG("get_buffer_shmid_pipe_fd");
 
        ltt_lock_traces();
        trace = _ltt_trace_find(trace_name);
@@ -298,122 +274,51 @@ static int do_cmd_get_n_subbufs(const char *recvbuf, int sock)
 
        if (trace == NULL) {
                ERR("cannot find trace!");
-               retval = -1;
-               goto free_short_chan_name;
+               return -ENODATA;
        }
 
-       for (i=0; i<trace->nr_channels; i++) {
-               struct ust_channel *channel = &trace->channels[i];
-
-               if (!strcmp(trace->channels[i].channel_name, ch_name)) {
-                       char *reply;
-
-                       DBG("the n_subbufs for the requested channel is %d", channel->subbuf_cnt);
-                       if (asprintf(&reply, "%d", channel->subbuf_cnt) < 0) {
-                               ERR("do_cmd_get_n_subbufs : asprintf failed (%d)",
-                                   channel->subbuf_cnt);
-                               retval = -1;
-                               goto free_short_chan_name;
-                       }
-
-                       result = ustcomm_send_reply(reply, sock);
-                       if (result) {
-                               ERR("ustcomm_send_reply failed");
-                               free(reply);
-                               retval = -1;
-                               goto free_short_chan_name;
-                       }
-
-                       free(reply);
-                       found = 1;
-                       break;
-               }
-       }
-       if (found == 0) {
-               ERR("unable to find channel");
+       channel = find_channel(ch_name, trace);
+       if (!channel) {
+               ERR("cannot find channel %s!", ch_name);
+               return -ENODATA;
        }
 
-       free_short_chan_name:
-       free(ch_name);
+       buf = channel->buf[ch_cpu];
 
-       end:
-       return retval;
+       *buf_shmid = buf->shmid;
+       *buf_struct_shmid = channel->buf_struct_shmids[ch_cpu];
+       *buf_pipe_fd = buf->data_ready_fd_read;
+
+       return 0;
 }
 
-static int do_cmd_get_subbuf_size(const char *recvbuf, int sock)
+static int get_subbuf_num_size(const char *trace_name, const char *ch_name,
+                              int *num, int *size)
 {
-       int retval = 0;
        struct ust_trace *trace;
-       char trace_name[] = "auto";
-       int i;
-       char *channel_and_cpu;
-       int found = 0;
-       int result;
-       char *ch_name;
-       int ch_cpu;
+       struct ust_channel *channel;
 
        DBG("get_subbuf_size");
 
-       channel_and_cpu = nth_token(recvbuf, 1);
-       if (channel_and_cpu == NULL) {
-               ERR("cannot parse channel");
-               retval = -1;
-               goto end;
-       }
-
-       seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
-       if (ch_cpu == -1) {
-               ERR("problem parsing channel name");
-               retval = -1;
-               goto free_short_chan_name;
-       }
-
        ltt_lock_traces();
        trace = _ltt_trace_find(trace_name);
        ltt_unlock_traces();
 
-       if (trace == NULL) {
+       if (!trace) {
                ERR("cannot find trace!");
-               retval = -1;
-               goto free_short_chan_name;
+               return -ENODATA;
        }
 
-       for (i=0; i<trace->nr_channels; i++) {
-               struct ust_channel *channel = &trace->channels[i];
-
-               if (!strcmp(trace->channels[i].channel_name, ch_name)) {
-                       char *reply;
-
-                       DBG("the subbuf_size for the requested channel is %zd", channel->subbuf_size);
-                       if (asprintf(&reply, "%zd", channel->subbuf_size) < 0) {
-                               ERR("do_cmd_get_subbuf_size : asprintf failed (%zd)",
-                                   channel->subbuf_size);
-                               retval = -1;
-                               goto free_short_chan_name;
-                       }
-
-                       result = ustcomm_send_reply(reply, sock);
-                       if (result) {
-                               ERR("ustcomm_send_reply failed");
-                               free(reply);
-                               retval = -1;
-                               goto free_short_chan_name;
-                       }
-
-                       free(reply);
-                       found = 1;
-                       break;
-               }
-       }
-       if (found == 0) {
+       channel = find_channel(ch_name, trace);
+       if (!channel) {
                ERR("unable to find channel");
+               return -ENODATA;
        }
 
-       free_short_chan_name:
-       free(ch_name);
+       *num = channel->subbuf_cnt;
+       *size = channel->subbuf_size;
 
-       end:
-       return retval;
+       return 0;
 }
 
 /* Return the power of two which is equal or higher to v */
@@ -429,508 +334,276 @@ static unsigned int pow2_higher_or_eq(unsigned int v)
                return retval<<1;
 }
 
-static int do_cmd_set_subbuf_size(const char *recvbuf, int sock)
+static int set_subbuf_size(const char *trace_name, const char *ch_name,
+                          unsigned int size)
 {
-       char *channel_slash_size;
-       char *ch_name = NULL;
-       unsigned int size, power;
+       unsigned int power;
        int retval = 0;
        struct ust_trace *trace;
-       char trace_name[] = "auto";
-       int i;
-       int found = 0;
+       struct ust_channel *channel;
 
        DBG("set_subbuf_size");
 
-       channel_slash_size = nth_token(recvbuf, 1);
-       sscanf(channel_slash_size, "%a[^/]/%u", &ch_name, &size);
-
-       if (ch_name == NULL) {
-               ERR("cannot parse channel");
-               retval = -1;
-               goto end;
-       }
-
        power = pow2_higher_or_eq(size);
        power = max_t(unsigned int, 2u, power);
-       if (power != size)
+       if (power != size) {
                WARN("using the next power of two for buffer size = %u\n", power);
+       }
 
        ltt_lock_traces();
        trace = _ltt_trace_find_setup(trace_name);
        if (trace == NULL) {
                ERR("cannot find trace!");
-               retval = -1;
-               goto end;
+               retval = -ENODATA;
+               goto unlock_traces;
        }
 
-       for (i = 0; i < trace->nr_channels; i++) {
-               struct ust_channel *channel = &trace->channels[i];
-
-               if (!strcmp(trace->channels[i].channel_name, ch_name)) {
-
-                       channel->subbuf_size = power;
-                       DBG("the set_subbuf_size for the requested channel is %zd", channel->subbuf_size);
-
-                       found = 1;
-                       break;
-               }
-       }
-       if (found == 0) {
+       channel = find_channel(ch_name, trace);
+       if (!channel) {
                ERR("unable to find channel");
+               retval = -ENODATA;
+               goto unlock_traces;
        }
 
-       end:
+       channel->subbuf_size = power;
+       DBG("the set_subbuf_size for the requested channel is %zu", channel->subbuf_size);
+
+unlock_traces:
        ltt_unlock_traces();
-       free(ch_name);
+
        return retval;
 }
 
-static int do_cmd_set_subbuf_num(const char *recvbuf, int sock)
+static int set_subbuf_num(const char *trace_name, const char *ch_name,
+                                unsigned int num)
 {
-       char *channel_slash_num;
-       char *ch_name = NULL;
-       unsigned int num;
-       int retval = 0;
        struct ust_trace *trace;
-       char trace_name[] = "auto";
-       int i;
-       int found = 0;
+       struct ust_channel *channel;
+       int retval = 0;
 
        DBG("set_subbuf_num");
 
-       channel_slash_num = nth_token(recvbuf, 1);
-       sscanf(channel_slash_num, "%a[^/]/%u", &ch_name, &num);
-
-       if (ch_name == NULL) {
-               ERR("cannot parse channel");
-               retval = -1;
-               goto end;
-       }
        if (num < 2) {
                ERR("subbuffer count should be greater than 2");
-               retval = -1;
-               goto end;
+               return -EINVAL;
        }
 
        ltt_lock_traces();
        trace = _ltt_trace_find_setup(trace_name);
        if (trace == NULL) {
                ERR("cannot find trace!");
-               retval = -1;
-               goto end;
+               retval = -ENODATA;
+               goto unlock_traces;
        }
 
-       for (i = 0; i < trace->nr_channels; i++) {
-               struct ust_channel *channel = &trace->channels[i];
-
-               if (!strcmp(trace->channels[i].channel_name, ch_name)) {
-
-                       channel->subbuf_cnt = num;
-                       DBG("the set_subbuf_cnt for the requested channel is %zd", channel->subbuf_cnt);
-
-                       found = 1;
-                       break;
-               }
-       }
-       if (found == 0) {
+       channel = find_channel(ch_name, trace);
+       if (!channel) {
                ERR("unable to find channel");
+               retval = -ENODATA;
+               goto unlock_traces;
        }
 
-       end:
+       channel->subbuf_cnt = num;
+       DBG("the set_subbuf_cnt for the requested channel is %u", channel->subbuf_cnt);
+
+unlock_traces:
        ltt_unlock_traces();
-       free(ch_name);
        return retval;
 }
 
-static int do_cmd_get_subbuffer(const char *recvbuf, int sock)
+static int get_subbuffer(const char *trace_name, const char *ch_name,
+                        int ch_cpu, long *consumed_old)
 {
-       int retval = 0, found = 0;;
-       int i, ch_cpu, result;
-       long consumed_old = 0;
+       int retval = 0;
        struct ust_trace *trace;
-       char trace_name[] = "auto";
-       char *channel_and_cpu;
-       char *ch_name;
+       struct ust_channel *channel;
+       struct ust_buffer *buf;
 
        DBG("get_subbuf");
 
-       channel_and_cpu = nth_token(recvbuf, 1);
-       if(channel_and_cpu == NULL) {
-               ERR("cannot parse channel");
-               retval = -1;
-               goto end;
-       }
-
-       seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
-       if(ch_cpu == -1) {
-               ERR("problem parsing channel name");
-               retval = -1;
-               goto free_short_chan_name;
-       }
+       *consumed_old = 0;
 
        ltt_lock_traces();
        trace = _ltt_trace_find(trace_name);
 
-       if(trace == NULL) {
-               int result;
-
+       if (!trace) {
                DBG("Cannot find trace. It was likely destroyed by the user.");
-               result = ustcomm_send_reply("NOTFOUND", sock);
-               if(result) {
-                       ERR("ustcomm_send_reply failed");
-                       retval = -1;
-                       goto unlock_traces;
-               }
-
+               retval = -ENODATA;
                goto unlock_traces;
        }
 
-       for(i=0; i<trace->nr_channels; i++) {
-               struct ust_channel *channel = &trace->channels[i];
-
-               if(!strcmp(trace->channels[i].channel_name, ch_name)) {
-                       struct ust_buffer *buf = channel->buf[ch_cpu];
-                       char *reply;
-
-                       found = 1;
-
-                       result = ust_buffers_get_subbuf(buf, &consumed_old);
-                       if(result == -EAGAIN) {
-                               WARN("missed buffer?");
-                               retval = 0;
-
-                               goto unlock_traces;
-                       } else if (result < 0) {
-                               ERR("ust_buffers_get_subbuf: error: %s", strerror(-result));
-                               retval = -1;
-
-                               goto unlock_traces;
-                       }
-                       if (asprintf(&reply, "%s %ld", "OK", consumed_old) < 0) {
-                               ERR("do_cmd_get_subbuffer: asprintf failed (OK %ld)",
-                                   consumed_old);
-                               retval = -1;
-
-                               goto unlock_traces;
-                       }
-                       result = ustcomm_send_reply(reply, sock);
-                       if (result < 0) {
-                               ERR("ustcomm_send_reply failed");
-                               free(reply);
-                               retval = -1;
-
-                               goto unlock_traces;
-                       }
-                       free(reply);
-
-                       break;
-               }
+       channel = find_channel(ch_name, trace);
+       if (!channel) {
+               ERR("unable to find channel");
+               retval = -ENODATA;
+               goto unlock_traces;
        }
-       if(found == 0) {
-               result = ustcomm_send_reply("NOTFOUND", sock);
-               if (result <= 0) {
-                       ERR("ustcomm_send_reply failed");
-                       retval = -1;
 
-                       goto unlock_traces;
-               }
-               ERR("unable to find channel");
+       buf = channel->buf[ch_cpu];
+
+       retval = ust_buffers_get_subbuf(buf, consumed_old);
+       if (retval < 0) {
+               WARN("missed buffer?");
        }
 
-       unlock_traces:
+unlock_traces:
        ltt_unlock_traces();
 
-       free_short_chan_name:
-       free(ch_name);
-
-       end:
        return retval;
 }
 
 
-static int do_cmd_get_buffer_fd(const char *recvbuf, int sock)
+static int notify_buffer_mapped(const char *trace_name,
+                               const char *ch_name,
+                               int ch_cpu)
 {
        int retval = 0;
        struct ust_trace *trace;
-       char trace_name[] = "auto";
-       int i;
-       char *channel_and_cpu;
-       int found = 0;
-       char *ch_name;
-       int ch_cpu;
-       struct ustcomm_header header;
+       struct ust_channel *channel;
+       struct ust_buffer *buf;
 
        DBG("get_buffer_fd");
 
-       channel_and_cpu = nth_token(recvbuf, 1);
-       if (channel_and_cpu == NULL) {
-               ERR("cannot parse channel");
-               retval = -1;
-               goto end;
-       }
-
-       seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
-       if (ch_cpu == -1) {
-               ERR("problem parsing channel name");
-               retval = -1;
-               goto free_short_chan_name;
-       }
-
        ltt_lock_traces();
        trace = _ltt_trace_find(trace_name);
 
-       if (trace == NULL) {
-               int result;
-
+       if (!trace) {
+               retval = -ENODATA;
                DBG("Cannot find trace. It was likely destroyed by the user.");
-               result = ustcomm_send_reply("NOTFOUND", sock);
-               if (result) {
-                       ERR("ustcomm_send_reply failed");
-                       retval = -1;
-                       goto unlock_traces;
-               }
-
                goto unlock_traces;
        }
 
-       for (i=0; i<trace->nr_channels; i++) {
-               struct ust_channel *channel = &trace->channels[i];
-
-               if (!strcmp(trace->channels[i].channel_name, ch_name)) {
-                       struct ust_buffer *buf = channel->buf[ch_cpu];
-
-                       found = 1;
-
-                       header.size = 0;
-                       header.fd_included = 1;
-                       if (ustcomm_send_fd(sock, &header, NULL,
-                                           &buf->data_ready_fd_read) <= 0) {
-                               ERR("ustcomm_send_fd failed\n");
-                               goto unlock_traces;
-                       }
+       channel = find_channel(ch_name, trace);
+       if (!channel) {
+               retval = -ENODATA;
+               ERR("unable to find channel");
+               goto unlock_traces;
+       }
 
-                       /* Being here is the proof the daemon has mapped the buffer in its
-                        * memory. We may now decrement buffers_to_export.
-                        */
-                       if (uatomic_read(&buf->consumed) == 0) {
-                               DBG("decrementing buffers_to_export");
-                               STORE_SHARED(buffers_to_export, LOAD_SHARED(buffers_to_export)-1);
-                       }
+       buf = channel->buf[ch_cpu];
 
-                       /* The buffer has been exported, ergo, we can add it to the
-                        * list of open buffers
-                        */
-                       list_add(&buf->open_buffers_list, &open_buffers_list);
-                       break;
-               }
-       }
-       if (found == 0) {
-               ERR("unable to find channel");
+       /* Being here is the proof the daemon has mapped the buffer in its
+        * memory. We may now decrement buffers_to_export.
+        */
+       if (uatomic_read(&buf->consumed) == 0) {
+               DBG("decrementing buffers_to_export");
+               CMM_STORE_SHARED(buffers_to_export, CMM_LOAD_SHARED(buffers_to_export)-1);
        }
 
-       unlock_traces:
+unlock_traces:
        ltt_unlock_traces();
 
-       free_short_chan_name:
-       free(ch_name);
-
-       end:
        return retval;
 }
 
-static int do_cmd_put_subbuffer(const char *recvbuf, int sock)
+static int put_subbuffer(const char *trace_name, const char *ch_name,
+                        int ch_cpu, long consumed_old)
 {
        int retval = 0;
        struct ust_trace *trace;
-       char trace_name[] = "auto";
-       int i;
-       char *channel_and_cpu;
-       int found = 0;
-       int result;
-       char *ch_name;
-       int ch_cpu;
-       long consumed_old;
-       char *consumed_old_str;
-       char *endptr;
-       char *reply = NULL;
+       struct ust_channel *channel;
+       struct ust_buffer *buf;
 
        DBG("put_subbuf");
 
-       channel_and_cpu = strdup(nth_token(recvbuf, 1));
-       if (channel_and_cpu == NULL) {
-               ERR("cannot parse channel");
-               retval = -1;
-               goto end;
-       }
-
-       consumed_old_str = strdup(nth_token(recvbuf, 2));
-       if (consumed_old_str == NULL) {
-               ERR("cannot parse consumed_old");
-               retval = -1;
-               goto free_channel_and_cpu;
-       }
-       consumed_old = strtol(consumed_old_str, &endptr, 10);
-       if (*endptr != '\0') {
-               ERR("invalid value for consumed_old");
-               retval = -1;
-               goto free_consumed_old_str;
-       }
-
-       seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
-       if (ch_cpu == -1) {
-               ERR("problem parsing channel name");
-               retval = -1;
-               goto free_short_chan_name;
-       }
-
        ltt_lock_traces();
        trace = _ltt_trace_find(trace_name);
 
-       if (trace == NULL) {
+       if (!trace) {
+               retval = -ENODATA;
                DBG("Cannot find trace. It was likely destroyed by the user.");
-               result = ustcomm_send_reply("NOTFOUND", sock);
-               if (result) {
-                       ERR("ustcomm_send_reply failed");
-                       retval = -1;
-                       goto unlock_traces;
-               }
-
                goto unlock_traces;
        }
 
-       for (i=0; i<trace->nr_channels; i++) {
-               struct ust_channel *channel = &trace->channels[i];
-
-               if (!strcmp(trace->channels[i].channel_name, ch_name)) {
-                       struct ust_buffer *buf = channel->buf[ch_cpu];
-
-                       found = 1;
+       channel = find_channel(ch_name, trace);
+       if (!channel) {
+               retval = -ENODATA;
+               ERR("unable to find channel");
+               goto unlock_traces;
+       }
 
-                       result = ust_buffers_put_subbuf(buf, consumed_old);
-                       if (result < 0) {
-                               WARN("ust_buffers_put_subbuf: error (subbuf=%s)", channel_and_cpu);
-                               if (asprintf(&reply, "%s", "ERROR") < 0) {
-                                       ERR("do_cmd_put_subbuffer : asprintf failed (ERROR)");
-                                       retval = -1;
-                                       goto unlock_traces;
-                               }
-                       } else {
-                               DBG("ust_buffers_put_subbuf: success (subbuf=%s)", channel_and_cpu);
-                               if (asprintf(&reply, "%s", "OK") < 0) {
-                                       ERR("do_cmd_put_subbuffer : asprintf failed (OK)");
-                                       retval = -1;
-                                       goto unlock_traces;
-                               }
-                       }
+       buf = channel->buf[ch_cpu];
 
-                       result = ustcomm_send_reply(reply, sock);
-                       if (result) {
-                               ERR("ustcomm_send_reply failed");
-                               free(reply);
-                               retval = -1;
-                               goto unlock_traces;
-                       }
-
-                       free(reply);
-                       break;
-               }
-       }
-       if (found == 0) {
-               ERR("unable to find channel");
+       retval = ust_buffers_put_subbuf(buf, consumed_old);
+       if (retval < 0) {
+               WARN("ust_buffers_put_subbuf: error (subbuf=%s_%d)",
+                    ch_name, ch_cpu);
+       } else {
+               DBG("ust_buffers_put_subbuf: success (subbuf=%s_%d)",
+                   ch_name, ch_cpu);
        }
 
-       unlock_traces:
+unlock_traces:
        ltt_unlock_traces();
-       free_short_chan_name:
-       free(ch_name);
-       free_consumed_old_str:
-       free(consumed_old_str);
-       free_channel_and_cpu:
-       free(channel_and_cpu);
-
-       end:
+
        return retval;
 }
 
-static void listener_cleanup(void *ptr)
+static void release_listener_mutex(void *ptr)
 {
-       ustcomm_del_named_sock(listen_sock, 0);
+       pthread_mutex_unlock(&listener_thread_data_mutex);
 }
 
-static void do_cmd_force_switch()
+static void listener_cleanup(void *ptr)
 {
-       struct ust_buffer *buf;
-
-       list_for_each_entry(buf, &open_buffers_list,
-                           open_buffers_list) {
-               ltt_force_switch(buf, FORCE_FLUSH);
+       pthread_mutex_lock(&listen_sock_mutex);
+       if (listen_sock) {
+               ustcomm_del_named_sock(listen_sock, 0);
+               listen_sock = NULL;
        }
+       pthread_mutex_unlock(&listen_sock_mutex);
 }
 
-static int process_client_cmd(char *recvbuf, int sock)
+static int force_subbuf_switch(const char *trace_name)
 {
-       int result;
-       char trace_name[] = "auto";
-       char trace_type[] = "ustrelay";
-       int len;
-
-       len = strlen(recvbuf);
-
-       if (!strcmp(recvbuf, "print_markers")) {
-               print_markers(stderr);
-       } else if (!strcmp(recvbuf, "list_markers")) {
-               char *ptr;
-               size_t size;
-               FILE *fp;
+       struct ust_trace *trace;
+       int i, j, retval = 0;
 
-               fp = open_memstream(&ptr, &size);
-               print_markers(fp);
-               fclose(fp);
+       ltt_lock_traces();
+       trace = _ltt_trace_find(trace_name);
+       if (!trace) {
+                retval = -ENODATA;
+                DBG("Cannot find trace. It was likely destroyed by the user.");
+                goto unlock_traces;
+        }
 
-               result = ustcomm_send_reply(ptr, sock);
+       for (i = 0; i < trace->nr_channels; i++) {
+               for (j = 0; j < trace->channels[i].n_cpus; j++) {
+                       ltt_force_switch(trace->channels[i].buf[j],
+                                        FORCE_FLUSH);
+               }
+       }
 
-               free(ptr);
-       } else if (!strcmp(recvbuf, "print_trace_events")) {
-               print_trace_events(stderr);
+unlock_traces:
+       ltt_unlock_traces();
 
-       } else if (!strcmp(recvbuf, "list_trace_events")) {
-               char *ptr;
-               size_t size;
-               FILE *fp;
+       return retval;
+}
 
-               fp = open_memstream(&ptr, &size);
-               if (fp == NULL) {
-                       ERR("opening memstream failed");
-                       return -1;
-               }
-               print_trace_events(fp);
-               fclose(fp);
+static int process_trace_cmd(int command, char *trace_name)
+{
+       int result;
+       char trace_type[] = "ustrelay";
 
-               result = ustcomm_send_reply(ptr, sock);
-               if (result < 0) {
-                       ERR("list_trace_events failed");
-                       return -1;
-               }
-               free(ptr);
-       } else if (!strcmp(recvbuf, "start")) {
+       switch(command) {
+       case START:
                /* start is an operation that setups the trace, allocates it and starts it */
                result = ltt_trace_setup(trace_name);
                if (result < 0) {
                        ERR("ltt_trace_setup failed");
-                       return -1;
+                       return result;
                }
 
                result = ltt_trace_set_type(trace_name, trace_type);
                if (result < 0) {
                        ERR("ltt_trace_set_type failed");
-                       return -1;
+                       return result;
                }
 
                result = ltt_trace_alloc(trace_name);
                if (result < 0) {
                        ERR("ltt_trace_alloc failed");
-                       return -1;
+                       return result;
                }
 
                inform_consumer_daemon(trace_name);
@@ -938,52 +611,61 @@ static int process_client_cmd(char *recvbuf, int sock)
                result = ltt_trace_start(trace_name);
                if (result < 0) {
                        ERR("ltt_trace_start failed");
-                       return -1;
+                       return result;
                }
-       } else if (!strcmp(recvbuf, "trace_setup")) {
+
+               return 0;
+       case SETUP_TRACE:
                DBG("trace setup");
 
                result = ltt_trace_setup(trace_name);
                if (result < 0) {
                        ERR("ltt_trace_setup failed");
-                       return -1;
+                       return result;
                }
 
                result = ltt_trace_set_type(trace_name, trace_type);
                if (result < 0) {
                        ERR("ltt_trace_set_type failed");
-                       return -1;
+                       return result;
                }
-       } else if (!strcmp(recvbuf, "trace_alloc")) {
+
+               return 0;
+       case ALLOC_TRACE:
                DBG("trace alloc");
 
                result = ltt_trace_alloc(trace_name);
                if (result < 0) {
                        ERR("ltt_trace_alloc failed");
-                       return -1;
+                       return result;
                }
                inform_consumer_daemon(trace_name);
-       } else if (!strcmp(recvbuf, "trace_create")) {
+
+               return 0;
+
+       case CREATE_TRACE:
                DBG("trace create");
 
                result = ltt_trace_setup(trace_name);
                if (result < 0) {
                        ERR("ltt_trace_setup failed");
-                       return -1;
+                       return result;
                }
 
                result = ltt_trace_set_type(trace_name, trace_type);
                if (result < 0) {
                        ERR("ltt_trace_set_type failed");
-                       return -1;
+                       return result;
                }
-       } else if (!strcmp(recvbuf, "trace_start")) {
+
+               return 0;
+       case START_TRACE:
                DBG("trace start");
 
                result = ltt_trace_alloc(trace_name);
                if (result < 0) {
                        ERR("ltt_trace_alloc failed");
-                       return -1;
+                       return result;
                }
                if (!result) {
                        inform_consumer_daemon(trace_name);
@@ -992,138 +674,413 @@ static int process_client_cmd(char *recvbuf, int sock)
                result = ltt_trace_start(trace_name);
                if (result < 0) {
                        ERR("ltt_trace_start failed");
-                       return -1;
+                       return result;
                }
-       } else if (!strcmp(recvbuf, "trace_stop")) {
+
+               return 0;
+       case STOP_TRACE:
                DBG("trace stop");
 
                result = ltt_trace_stop(trace_name);
                if (result < 0) {
                        ERR("ltt_trace_stop failed");
-                       return -1;
+                       return result;
                }
-       } else if (!strcmp(recvbuf, "trace_destroy")) {
 
+               return 0;
+       case DESTROY_TRACE:
                DBG("trace destroy");
 
                result = ltt_trace_destroy(trace_name, 0);
                if (result < 0) {
                        ERR("ltt_trace_destroy failed");
-                       return -1;
+                       return result;
                }
-       } else if (nth_token_is(recvbuf, "get_shmid", 0) == 1) {
-               do_cmd_get_shmid(recvbuf, sock);
-       } else if (nth_token_is(recvbuf, "get_n_subbufs", 0) == 1) {
-               do_cmd_get_n_subbufs(recvbuf, sock);
-       } else if (nth_token_is(recvbuf, "get_subbuf_size", 0) == 1) {
-               do_cmd_get_subbuf_size(recvbuf, sock);
-       } else if (nth_token_is(recvbuf, "load_probe_lib", 0) == 1) {
-               char *libfile;
+               return 0;
+       case FORCE_SUBBUF_SWITCH:
+               DBG("force switch");
 
-               libfile = nth_token(recvbuf, 1);
+               result = force_subbuf_switch(trace_name);
+               if (result < 0) {
+                       ERR("force_subbuf_switch failed");
+                       return result;
+               }
+               return 0;
+       }
+
+       return 0;
+}
 
-               DBG("load_probe_lib loading %s", libfile);
 
-               free(libfile);
-       } else if (nth_token_is(recvbuf, "get_subbuffer", 0) == 1) {
-               do_cmd_get_subbuffer(recvbuf, sock);
-       }
-       else if(nth_token_is(recvbuf, "get_buffer_fd", 0) == 1) {
-               do_cmd_get_buffer_fd(recvbuf, sock);
-       }
-       else if(nth_token_is(recvbuf, "put_subbuffer", 0) == 1) {
-               do_cmd_put_subbuffer(recvbuf, sock);
-       } else if (nth_token_is(recvbuf, "set_subbuf_size", 0) == 1) {
-               do_cmd_set_subbuf_size(recvbuf, sock);
-       } else if (nth_token_is(recvbuf, "set_subbuf_num", 0) == 1) {
-               do_cmd_set_subbuf_num(recvbuf, sock);
-       } else if (nth_token_is(recvbuf, "enable_marker", 0) == 1) {
-               char *channel_slash_name = nth_token(recvbuf, 1);
-               char *channel_name = NULL;
-               char *marker_name = NULL;
-
-               result = sscanf(channel_slash_name, "%a[^/]/%as", &channel_name, &marker_name);
-
-               if (channel_name == NULL || marker_name == NULL) {
-                       WARN("invalid marker name");
-                       free(channel_name);
-                       free(marker_name);
-                       goto next_cmd;
+static void process_channel_cmd(int sock, int command,
+                               struct ustcomm_channel_info *ch_inf)
+{
+       struct ustcomm_header _reply_header;
+       struct ustcomm_header *reply_header = &_reply_header;
+       struct ustcomm_channel_info *reply_msg =
+               (struct ustcomm_channel_info *)send_buffer;
+       int result, offset = 0, num, size;
+
+       memset(reply_header, 0, sizeof(*reply_header));
+
+       switch (command) {
+       case GET_SUBBUF_NUM_SIZE:
+               result = get_subbuf_num_size(ch_inf->trace,
+                                            ch_inf->channel,
+                                            &num, &size);
+               if (result < 0) {
+                       reply_header->result = result;
+                       break;
                }
 
-               result = ltt_marker_connect(channel_name, marker_name, "default");
+               reply_msg->channel = USTCOMM_POISON_PTR;
+               reply_msg->subbuf_num = num;
+               reply_msg->subbuf_size = size;
+
+
+               reply_header->size = COMPUTE_MSG_SIZE(reply_msg, offset);
+
+               break;
+       case SET_SUBBUF_NUM:
+               reply_header->result = set_subbuf_num(ch_inf->trace,
+                                                     ch_inf->channel,
+                                                     ch_inf->subbuf_num);
+
+               break;
+       case SET_SUBBUF_SIZE:
+               reply_header->result = set_subbuf_size(ch_inf->trace,
+                                                      ch_inf->channel,
+                                                      ch_inf->subbuf_size);
+
+
+               break;
+       }
+       if (ustcomm_send(sock, reply_header, (char *)reply_msg) < 0) {
+               ERR("ustcomm_send failed");
+       }
+}
+
+static void process_buffer_cmd(int sock, int command,
+                              struct ustcomm_buffer_info *buf_inf)
+{
+       struct ustcomm_header _reply_header;
+       struct ustcomm_header *reply_header = &_reply_header;
+       struct ustcomm_buffer_info *reply_msg =
+               (struct ustcomm_buffer_info *)send_buffer;
+       int result, offset = 0, buf_shmid, buf_struct_shmid, buf_pipe_fd;
+       long consumed_old;
+
+       memset(reply_header, 0, sizeof(*reply_header));
+
+       switch (command) {
+       case GET_BUF_SHMID_PIPE_FD:
+               result = get_buffer_shmid_pipe_fd(buf_inf->trace,
+                                                 buf_inf->channel,
+                                                 buf_inf->ch_cpu,
+                                                 &buf_shmid,
+                                                 &buf_struct_shmid,
+                                                 &buf_pipe_fd);
+               if (result < 0) {
+                       reply_header->result = result;
+                       break;
+               }
+
+               reply_msg->channel = USTCOMM_POISON_PTR;
+               reply_msg->buf_shmid = buf_shmid;
+               reply_msg->buf_struct_shmid = buf_struct_shmid;
+
+               reply_header->size = COMPUTE_MSG_SIZE(reply_msg, offset);
+               reply_header->fd_included = 1;
+
+               if (ustcomm_send_fd(sock, reply_header, (char *)reply_msg,
+                                   &buf_pipe_fd) < 0) {
+                       ERR("ustcomm_send failed");
+               }
+               return;
+
+       case NOTIFY_BUF_MAPPED:
+               reply_header->result =
+                       notify_buffer_mapped(buf_inf->trace,
+                                            buf_inf->channel,
+                                            buf_inf->ch_cpu);
+               break;
+       case GET_SUBBUFFER:
+               result = get_subbuffer(buf_inf->trace, buf_inf->channel,
+                                      buf_inf->ch_cpu, &consumed_old);
+               if (result < 0) {
+                       reply_header->result = result;
+                       break;
+               }
+
+               reply_msg->channel = USTCOMM_POISON_PTR;
+               reply_msg->consumed_old = consumed_old;
+
+               reply_header->size = COMPUTE_MSG_SIZE(reply_msg, offset);
+
+               break;
+       case PUT_SUBBUFFER:
+               result = put_subbuffer(buf_inf->trace, buf_inf->channel,
+                                      buf_inf->ch_cpu,
+                                      buf_inf->consumed_old);
+               reply_header->result = result;
+
+               break;
+       }
+
+       if (ustcomm_send(sock, reply_header, (char *)reply_msg) < 0) {
+               ERR("ustcomm_send failed");
+       }
+
+}
+
+static void process_ust_marker_cmd(int sock, int command,
+                              struct ustcomm_ust_marker_info *ust_marker_inf)
+{
+       struct ustcomm_header _reply_header;
+       struct ustcomm_header *reply_header = &_reply_header;
+       int result = 0;
+
+       memset(reply_header, 0, sizeof(*reply_header));
+
+       switch(command) {
+       case ENABLE_MARKER:
+
+               result = ltt_ust_marker_connect(ust_marker_inf->channel,
+                                           ust_marker_inf->ust_marker,
+                                           "default");
+               if (result < 0) {
+                       WARN("could not enable ust_marker; channel=%s,"
+                            " name=%s",
+                            ust_marker_inf->channel,
+                            ust_marker_inf->ust_marker);
+
+               }
+               break;
+       case DISABLE_MARKER:
+               result = ltt_ust_marker_disconnect(ust_marker_inf->channel,
+                                              ust_marker_inf->ust_marker,
+                                              "default");
                if (result < 0) {
-                       WARN("could not enable marker; channel=%s, name=%s", channel_name, marker_name);
+                       WARN("could not disable ust_marker; channel=%s,"
+                            " name=%s",
+                            ust_marker_inf->channel,
+                            ust_marker_inf->ust_marker);
                }
+               break;
+       }
 
-               free(channel_name);
-               free(marker_name);
-       } else if (nth_token_is(recvbuf, "disable_marker", 0) == 1) {
-               char *channel_slash_name = nth_token(recvbuf, 1);
-               char *marker_name = NULL;
-               char *channel_name = NULL;
+       reply_header->result = result;
 
-               result = sscanf(channel_slash_name, "%a[^/]/%as", &channel_name, &marker_name);
+       if (ustcomm_send(sock, reply_header, NULL) < 0) {
+               ERR("ustcomm_send failed");
+       }
 
-               if (channel_name == NULL || marker_name == NULL) {
-                       WARN("invalid marker name");
-                       free(channel_name);
-                       free(marker_name);
-                       goto next_cmd;
+}
+static void process_client_cmd(struct ustcomm_header *recv_header,
+                              char *recv_buf, int sock)
+{
+       int result;
+       struct ustcomm_header _reply_header;
+       struct ustcomm_header *reply_header = &_reply_header;
+       char *send_buf = send_buffer;
+
+       memset(reply_header, 0, sizeof(*reply_header));
+       memset(send_buf, 0, sizeof(send_buffer));
+
+       switch(recv_header->command) {
+       case GET_SUBBUF_NUM_SIZE:
+       case SET_SUBBUF_NUM:
+       case SET_SUBBUF_SIZE:
+       {
+               struct ustcomm_channel_info *ch_inf;
+               ch_inf = (struct ustcomm_channel_info *)recv_buf;
+               result = ustcomm_unpack_channel_info(ch_inf);
+               if (result < 0) {
+                       ERR("couldn't unpack channel info");
+                       reply_header->result = -EINVAL;
+                       goto send_response;
+               }
+               process_channel_cmd(sock, recv_header->command, ch_inf);
+               return;
+       }
+       case GET_BUF_SHMID_PIPE_FD:
+       case NOTIFY_BUF_MAPPED:
+       case GET_SUBBUFFER:
+       case PUT_SUBBUFFER:
+       {
+               struct ustcomm_buffer_info *buf_inf;
+               buf_inf = (struct ustcomm_buffer_info *)recv_buf;
+               result = ustcomm_unpack_buffer_info(buf_inf);
+               if (result < 0) {
+                       ERR("couldn't unpack buffer info");
+                       reply_header->result = -EINVAL;
+                       goto send_response;
+               }
+               process_buffer_cmd(sock, recv_header->command, buf_inf);
+               return;
+       }
+       case ENABLE_MARKER:
+       case DISABLE_MARKER:
+       {
+               struct ustcomm_ust_marker_info *ust_marker_inf;
+               ust_marker_inf = (struct ustcomm_ust_marker_info *)recv_buf;
+               result = ustcomm_unpack_ust_marker_info(ust_marker_inf);
+               if (result < 0) {
+                       ERR("couldn't unpack ust_marker info");
+                       reply_header->result = -EINVAL;
+                       goto send_response;
                }
+               process_ust_marker_cmd(sock, recv_header->command, ust_marker_inf);
+               return;
+       }
+       case LIST_MARKERS:
+       {
+               char *ptr;
+               size_t size;
+               FILE *fp;
+
+               fp = open_memstream(&ptr, &size);
+               if (fp == NULL) {
+                       ERR("opening memstream failed");
+                       return;
+               }
+               print_ust_marker(fp);
+               fclose(fp);
+
+               reply_header->size = size + 1;  /* Include final \0 */
+
+               result = ustcomm_send(sock, reply_header, ptr);
+
+               free(ptr);
 
-               result = ltt_marker_disconnect(channel_name, marker_name, "default");
                if (result < 0) {
-                       WARN("could not disable marker; channel=%s, name=%s", channel_name, marker_name);
+                       PERROR("failed to send ust_marker list");
                }
 
-               free(channel_name);
-               free(marker_name);
-       } else if (nth_token_is(recvbuf, "get_pidunique", 0) == 1) {
-               char *reply;
+               break;
+       }
+       case LIST_TRACE_EVENTS:
+       {
+               char *ptr;
+               size_t size;
+               FILE *fp;
 
-               if (asprintf(&reply, "%lld", pidunique) < 0) {
-                       ERR("process_client_cmd : asprintf failed (%lld)",
-                           pidunique);
-                       goto next_cmd;
+               fp = open_memstream(&ptr, &size);
+               if (fp == NULL) {
+                       ERR("opening memstream failed");
+                       return;
                }
+               print_trace_events(fp);
+               fclose(fp);
 
-               result = ustcomm_send_reply(reply, sock);
-               if (result) {
-                       ERR("listener: get_pidunique: ustcomm_send_reply failed");
-                       goto next_cmd;
+               reply_header->size = size + 1;  /* Include final \0 */
+
+               result = ustcomm_send(sock, reply_header, ptr);
+
+               free(ptr);
+
+               if (result < 0) {
+                       ERR("list_trace_events failed");
+                       return;
                }
 
-               free(reply);
-       } else if (nth_token_is(recvbuf, "get_sock_path", 0) == 1) {
-               char *reply = getenv("UST_DAEMON_SOCKET");
-               if (!reply) {
-                       if (asprintf(&reply, "%s/%s", SOCK_DIR, "ustd") < 0) {
-                               ERR("process_client_cmd : asprintf failed (%s/ustd)",
-                                   SOCK_DIR);
-                               goto next_cmd;
-                       }
-                       result = ustcomm_send_reply(reply, sock);
-                       free(reply);
+               break;
+       }
+       case LOAD_PROBE_LIB:
+       {
+               char *libfile;
+
+               /* FIXME: No functionality at all... */
+               libfile = recv_buf;
+
+               DBG("load_probe_lib loading %s", libfile);
+
+               break;
+       }
+       case GET_PIDUNIQUE:
+       {
+               struct ustcomm_pidunique *pid_msg;
+               pid_msg = (struct ustcomm_pidunique *)send_buf;
+
+               pid_msg->pidunique = pidunique;
+               reply_header->size = sizeof(pid_msg);
+
+               goto send_response;
+
+       }
+       case GET_SOCK_PATH:
+       {
+               struct ustcomm_single_field *sock_msg;
+               char *sock_path_env;
+
+               sock_msg = (struct ustcomm_single_field *)send_buf;
+
+               sock_path_env = getenv("UST_DAEMON_SOCKET");
+
+               if (!sock_path_env) {
+                       result = ustcomm_pack_single_field(reply_header,
+                                                          sock_msg,
+                                                          SOCK_DIR "/ustconsumer");
+
                } else {
-                       result = ustcomm_send_reply(reply, sock);
+                       result = ustcomm_pack_single_field(reply_header,
+                                                          sock_msg,
+                                                          sock_path_env);
                }
-               if (result)
-                       ERR("ustcomm_send_reply failed");
-       } else if (nth_token_is(recvbuf, "set_sock_path", 0) == 1) {
-               char *sock_path = nth_token(recvbuf, 1);
-               result = setenv("UST_DAEMON_SOCKET", sock_path, 1);
-               if (result)
-                       ERR("cannot set UST_DAEMON_SOCKET environment variable");
-       } else if (nth_token_is(recvbuf, "force_switch", 0) == 1) {
-               do_cmd_force_switch();
-       } else {
-               ERR("unable to parse message: %s", recvbuf);
+               reply_header->result = result;
+
+               goto send_response;
        }
+       case SET_SOCK_PATH:
+       {
+               struct ustcomm_single_field *sock_msg;
+               sock_msg = (struct ustcomm_single_field *)recv_buf;
+               result = ustcomm_unpack_single_field(sock_msg);
+               if (result < 0) {
+                       reply_header->result = -EINVAL;
+                       goto send_response;
+               }
 
-next_cmd:
+               reply_header->result = setenv("UST_DAEMON_SOCKET",
+                                             sock_msg->field, 1);
 
-       return 0;
+               goto send_response;
+       }
+       case START:
+       case SETUP_TRACE:
+       case ALLOC_TRACE:
+       case CREATE_TRACE:
+       case START_TRACE:
+       case STOP_TRACE:
+       case DESTROY_TRACE:
+       case FORCE_SUBBUF_SWITCH:
+       {
+               struct ustcomm_single_field *trace_inf =
+                       (struct ustcomm_single_field *)recv_buf;
+
+               result = ustcomm_unpack_single_field(trace_inf);
+               if (result < 0) {
+                       ERR("couldn't unpack trace info");
+                       reply_header->result = -EINVAL;
+                       goto send_response;
+               }
+
+               reply_header->result =
+                       process_trace_cmd(recv_header->command,
+                                         trace_inf->field);
+               goto send_response;
+
+       }
+       default:
+               reply_header->result = -EINVAL;
+
+               goto send_response;
+       }
+
+       return;
+
+send_response:
+       ustcomm_send(sock, reply_header, send_buf);
 }
 
 #define MAX_EVENTS 10
@@ -1147,6 +1104,8 @@ void *listener_main(void *p)
                }
 
                for (i = 0; i < nfds; i++) {
+                       pthread_mutex_lock(&listener_thread_data_mutex);
+                       pthread_cleanup_push(release_listener_mutex, NULL);
                        epoll_sock = (struct ustcomm_sock *)events[i].data.ptr;
                        if (epoll_sock == listen_sock) {
                                addr_size = sizeof(struct sockaddr);
@@ -1160,15 +1119,22 @@ void *listener_main(void *p)
                                ustcomm_init_sock(accept_fd, epoll_fd,
                                                 &ust_socks);
                        } else {
-                               char *msg = NULL;
-                               result = recv_message_conn(epoll_sock->fd, &msg);
+                               memset(receive_header, 0,
+                                      sizeof(*receive_header));
+                               memset(receive_buffer, 0,
+                                      sizeof(receive_buffer));
+                               result = ustcomm_recv(epoll_sock->fd,
+                                                     receive_header,
+                                                     receive_buffer);
                                if (result == 0) {
                                        ustcomm_del_sock(epoll_sock, 0);
-                               } else if (msg) {
-                                       process_client_cmd(msg, epoll_sock->fd);
-                                       free(msg);
+                               } else {
+                                       process_client_cmd(receive_header,
+                                                          receive_buffer,
+                                                          epoll_sock->fd);
                                }
                        }
+                       pthread_cleanup_pop(1); /* release listener mutex */
                }
        }
 
@@ -1225,7 +1191,7 @@ void create_listener(void)
 static int autoprobe_method = AUTOPROBE_DISABLED;
 static regex_t autoprobe_regex;
 
-static void auto_probe_connect(struct marker *m)
+static void auto_probe_connect(struct ust_marker *m)
 {
        int result;
 
@@ -1237,7 +1203,7 @@ static void auto_probe_connect(struct marker *m)
        } else if (autoprobe_method == AUTOPROBE_ENABLE_REGEX) {
                result = asprintf(&concat_name, "%s/%s", m->channel, m->name);
                if (result == -1) {
-                       ERR("auto_probe_connect: asprintf failed (marker %s/%s)",
+                       ERR("auto_probe_connect: asprintf failed (ust_marker %s/%s)",
                                m->channel, m->name);
                        return;
                }
@@ -1248,51 +1214,63 @@ static void auto_probe_connect(struct marker *m)
                free(concat_name);
        }
 
-       result = ltt_marker_connect(m->channel, m->name, probe_name);
+       result = ltt_ust_marker_connect(m->channel, m->name, probe_name);
        if (result && result != -EEXIST)
-               ERR("ltt_marker_connect (marker = %s/%s, errno = %d)", m->channel, m->name, -result);
+               ERR("ltt_ust_marker_connect (ust_marker = %s/%s, errno = %d)", m->channel, m->name, -result);
 
-       DBG("auto connected marker %s (addr: %p) %s to probe default", m->channel, m, m->name);
+       DBG("auto connected ust_marker %s (addr: %p) %s to probe default", m->channel, m, m->name);
 
 }
 
 static struct ustcomm_sock * init_app_socket(int epoll_fd)
 {
-       char *name;
+       char *dir_name, *sock_name;
        int result;
-       struct ustcomm_sock *sock;
+       struct ustcomm_sock *sock = NULL;
+       time_t mtime;
+
+       dir_name = ustcomm_user_sock_dir();
+       if (!dir_name)
+               return NULL;
 
-       result = asprintf(&name, "%s/%d", SOCK_DIR, (int)getpid());
+       mtime = ustcomm_pid_st_mtime(getpid());
+       if (!mtime) {
+               goto free_dir_name;
+       }
+
+       result = asprintf(&sock_name, "%s/%d.%ld", dir_name,
+                         (int) getpid(), (long) mtime);
        if (result < 0) {
                ERR("string overflow allocating socket name, "
                    "UST thread bailing");
-               return NULL;
+               goto free_dir_name;
        }
 
-       result = ensure_dir_exists(SOCK_DIR);
+       result = ensure_dir_exists(dir_name, S_IRWXU);
        if (result == -1) {
                ERR("Unable to create socket directory %s, UST thread bailing",
-                   SOCK_DIR);
-               goto free_name;
+                   dir_name);
+               goto free_sock_name;
        }
 
-       sock = ustcomm_init_named_socket(name, epoll_fd);
+       sock = ustcomm_init_named_socket(sock_name, epoll_fd);
        if (!sock) {
                ERR("Error initializing named socket (%s). Check that directory"
-                   "exists and that it is writable. UST thread bailing", name);
-               goto free_name;
+                   "exists and that it is writable. UST thread bailing", sock_name);
+               goto free_sock_name;
        }
 
-       free(name);
-       return sock;
+free_sock_name:
+       free(sock_name);
+free_dir_name:
+       free(dir_name);
 
-free_name:
-       free(name);
-       return NULL;
+       return sock;
 }
 
 static void __attribute__((constructor)) init()
 {
+       struct timespec ts;
        int result;
        char* autoprobe_val = NULL;
        char* subbuffer_size_val = NULL;
@@ -1305,6 +1283,7 @@ static void __attribute__((constructor)) init()
         * pid, (before and after an exec).
         */
        pidunique = make_pidunique();
+       processpid = getpid();
 
        DBG("Tracectl constructor");
 
@@ -1325,20 +1304,28 @@ static void __attribute__((constructor)) init()
 
        create_listener();
 
+       /* Get clock the clock source type */
+
+       /* Default clock source */
+       ust_clock_source = CLOCK_TRACE;
+       if (clock_gettime(ust_clock_source, &ts) != 0) {
+               ust_clock_source = CLOCK_MONOTONIC;
+               DBG("UST traces will not be synchronized with LTTng traces");
+       }
+
+       if (getenv("UST_TRACE") || getenv("UST_AUTOPROBE")) {
+               /* Ensure ust_marker control is initialized */
+               init_ust_marker_control();
+       }
+
        autoprobe_val = getenv("UST_AUTOPROBE");
        if (autoprobe_val) {
-               struct marker_iter iter;
+               struct ust_marker_iter iter;
 
                DBG("Autoprobe enabled.");
 
-               /* Ensure markers are initialized */
-               //init_markers();
-
-               /* Ensure marker control is initialized, for the probe */
-               init_marker_control();
-
                /* first, set the callback that will connect the
-                * probe on new markers
+                * probe on new ust_marker
                 */
                if (autoprobe_val[0] == '/') {
                        result = regcomp(&autoprobe_regex, autoprobe_val+1, 0);
@@ -1356,24 +1343,25 @@ static void __attribute__((constructor)) init()
                        autoprobe_method = AUTOPROBE_ENABLE_ALL;
                }
 
-               marker_set_new_marker_cb(auto_probe_connect);
+               ust_marker_set_new_ust_marker_cb(auto_probe_connect);
 
                /* Now, connect the probes that were already registered. */
-               marker_iter_reset(&iter);
-               marker_iter_start(&iter);
-
-               DBG("now iterating on markers already registered");
-               while (iter.marker) {
-                       DBG("now iterating on marker %s", iter.marker->name);
-                       auto_probe_connect(iter.marker);
-                       marker_iter_next(&iter);
+               ust_marker_iter_reset(&iter);
+               ust_marker_iter_start(&iter);
+
+               DBG("now iterating on ust_marker already registered");
+               while (iter.ust_marker) {
+                       DBG("now iterating on ust_marker %s", (*iter.ust_marker)->name);
+                       auto_probe_connect(*iter.ust_marker);
+                       ust_marker_iter_next(&iter);
                }
+               ust_marker_iter_stop(&iter);
        }
 
        if (getenv("UST_OVERWRITE")) {
                int val = atoi(getenv("UST_OVERWRITE"));
                if (val == 0 || val == 1) {
-                       STORE_SHARED(ust_channels_overwrite_by_default, val);
+                       CMM_STORE_SHARED(ust_channels_overwrite_by_default, val);
                } else {
                        WARN("invalid value for UST_OVERWRITE");
                }
@@ -1382,7 +1370,7 @@ static void __attribute__((constructor)) init()
        if (getenv("UST_AUTOCOLLECT")) {
                int val = atoi(getenv("UST_AUTOCOLLECT"));
                if (val == 0 || val == 1) {
-                       STORE_SHARED(ust_channels_request_collection_by_default, val);
+                       CMM_STORE_SHARED(ust_channels_request_collection_by_default, val);
                } else {
                        WARN("invalid value for UST_AUTOCOLLECT");
                }
@@ -1411,19 +1399,13 @@ static void __attribute__((constructor)) init()
 
                DBG("starting early tracing");
 
-               /* Ensure marker control is initialized */
-               init_marker_control();
-
-               /* Ensure markers are initialized */
-               init_markers();
-
                /* Ensure buffers are initialized, for the transport to be available.
                 * We are about to set a trace type and it will fail without this.
                 */
                init_ustrelay_transport();
 
                /* FIXME: When starting early tracing (here), depending on the
-                * order of constructors, it is very well possible some marker
+                * order of constructors, it is very well possible some ust_marker
                 * sections are not yet registered. Because of this, some
                 * channels may not be registered. Yet, we are about to ask the
                 * daemon to collect the channels. Channels which are not yet
@@ -1514,7 +1496,7 @@ static int trace_recording(void)
 
        ltt_lock_traces();
 
-       list_for_each_entry(trace, &ltt_traces.head, list) {
+       cds_list_for_each_entry(trace, &ltt_traces.head, list) {
                if (trace->active) {
                        retval = 1;
                        break;
@@ -1528,13 +1510,13 @@ static int trace_recording(void)
 
 int restarting_usleep(useconds_t usecs)
 {
-        struct timespec tv; 
-        int result; 
-        tv.tv_sec = 0; 
-        tv.tv_nsec = usecs * 1000; 
-        do { 
+        struct timespec tv;
+        int result;
+
+        tv.tv_sec = 0;
+        tv.tv_nsec = usecs * 1000;
+
+        do {
                 result = nanosleep(&tv, &tv);
         } while (result == -1 && errno == EINTR);
 
@@ -1559,7 +1541,7 @@ static void stop_listener(void)
 }
 
 /* This destructor keeps the process alive for a few seconds in order
- * to leave time to ustd to connect to its buffers. This is necessary
+ * to leave time for ustconsumer to connect to its buffers. This is necessary
  * for programs whose execution is very short. It is also useful in all
  * programs when tracing is started close to the end of the program
  * execution.
@@ -1570,10 +1552,14 @@ static void stop_listener(void)
 
 static void __attribute__((destructor)) keepalive()
 {
-       if (trace_recording() && LOAD_SHARED(buffers_to_export)) {
+       if (processpid != getpid()) {
+               return;
+       }
+
+       if (trace_recording() && CMM_LOAD_SHARED(buffers_to_export)) {
                int total = 0;
                DBG("Keeping process alive for consumer daemon...");
-               while (LOAD_SHARED(buffers_to_export)) {
+               while (CMM_LOAD_SHARED(buffers_to_export)) {
                        const int interv = 200000;
                        restarting_usleep(interv);
                        total += interv;
@@ -1594,7 +1580,7 @@ static void __attribute__((destructor)) keepalive()
 
 void ust_potential_exec(void)
 {
-       trace_mark(ust, potential_exec, MARK_NOARGS);
+       ust_marker(potential_exec, UST_MARKER_NOARGS);
 
        DBG("test");
 
@@ -1613,43 +1599,46 @@ void ust_potential_exec(void)
 
 static void ust_fork(void)
 {
-       struct ust_buffer *buf, *buf_tmp;
        struct ustcomm_sock *sock, *sock_tmp;
+       struct ust_trace *trace, *trace_tmp;
        int result;
 
        /* FIXME: technically, the locks could have been taken before the fork */
        DBG("ust: forking");
 
-       /* break lock if necessary */
-       ltt_unlock_traces();
+       /* Get the pid of the new process */
+       processpid = getpid();
+
+       /*
+        * FIXME: This could be prettier, we loop over the list twice and
+        * following good locking practice should lock around the loop
+        */
+       cds_list_for_each_entry_safe(trace, trace_tmp, &ltt_traces.head, list) {
+               ltt_trace_stop(trace->trace_name);
+       }
 
-       ltt_trace_stop("auto");
-       ltt_trace_destroy("auto", 1);
        /* Delete all active connections, but leave them in the epoll set */
-       list_for_each_entry_safe(sock, sock_tmp, &ust_socks, list) {
+       cds_list_for_each_entry_safe(sock, sock_tmp, &ust_socks, list) {
                ustcomm_del_sock(sock, 1);
        }
 
-       /* Delete all blocked consumers */
-       list_for_each_entry_safe(buf, buf_tmp, &open_buffers_list,
-                                open_buffers_list) {
-               result = close(buf->data_ready_fd_read);
-               if(result == -1) {
-                       PERROR("close");
-               }
-               result = close(buf->data_ready_fd_write);
-               if(result == -1) {
-                       PERROR("close");
-               }
-               list_del(&buf->open_buffers_list);
+       /*
+        * FIXME: This could be prettier, we loop over the list twice and
+        * following good locking practice should lock around the loop
+        */
+       cds_list_for_each_entry_safe(trace, trace_tmp, &ltt_traces.head, list) {
+               ltt_trace_destroy(trace->trace_name, 1);
        }
 
-       /* Clean up the listener socket and epoll, keeping the scoket file */
-       ustcomm_del_named_sock(listen_sock, 1);
+       /* Clean up the listener socket and epoll, keeping the socket file */
+       if (listen_sock) {
+               ustcomm_del_named_sock(listen_sock, 1);
+               listen_sock = NULL;
+       }
        close(epoll_fd);
 
        /* Re-start the launch sequence */
-       STORE_SHARED(buffers_to_export, 0);
+       CMM_STORE_SHARED(buffers_to_export, 0);
        have_listener = 0;
 
        /* Set up epoll */
@@ -1700,6 +1689,17 @@ void ust_before_fork(ust_fork_info_t *fork_info)
                 PERROR("sigprocmask");
                 return;
         }
+
+       /*
+        * Take the fork lock to make sure we are not in the middle of
+        * something in the listener thread.
+        */
+       pthread_mutex_lock(&listener_thread_data_mutex);
+       /*
+        * Hold listen_sock_mutex to protect from listen_sock teardown.
+        */
+       pthread_mutex_lock(&listen_sock_mutex);
+       rcu_bp_before_fork();
 }
 
 /* Don't call this function directly in a traced program */
@@ -1707,6 +1707,8 @@ static void ust_after_fork_common(ust_fork_info_t *fork_info)
 {
        int result;
 
+       pthread_mutex_unlock(&listen_sock_mutex);
+       pthread_mutex_unlock(&listener_thread_data_mutex);
         /* Restore signals */
         result = sigprocmask(SIG_SETMASK, &fork_info->orig_sigs, NULL);
         if (result == -1) {
@@ -1717,16 +1719,20 @@ static void ust_after_fork_common(ust_fork_info_t *fork_info)
 
 void ust_after_fork_parent(ust_fork_info_t *fork_info)
 {
-       /* Reenable signals */
+       rcu_bp_after_fork_parent();
+       /* Release mutexes and reenable signals */
        ust_after_fork_common(fork_info);
 }
 
 void ust_after_fork_child(ust_fork_info_t *fork_info)
 {
-       /* First sanitize the child */
+       /* Release urcu mutexes */
+       rcu_bp_after_fork_child();
+
+       /* Sanitize the child */
        ust_fork();
 
-       /* Then reenable interrupts */
+       /* Release mutexes and reenable signals */
        ust_after_fork_common(fork_info);
 }
 
This page took 0.048398 seconds and 4 git commands to generate.