+ *consumed_old = 0;
+
+ ltt_lock_traces();
+ trace = _ltt_trace_find(trace_name);
+
+ if (!trace) {
+ DBG("Cannot find trace. It was likely destroyed by the user.");
+ retval = -ENODATA;
+ goto unlock_traces;
+ }
+
+ channel = find_channel(ch_name, trace);
+ if (!channel) {
+ ERR("unable to find channel");
+ retval = -ENODATA;
+ goto unlock_traces;
+ }
+
+ buf = channel->buf[ch_cpu];
+
+ retval = ust_buffers_get_subbuf(buf, consumed_old);
+ if (retval < 0) {
+ WARN("missed buffer?");
+ }
+
+unlock_traces:
+ ltt_unlock_traces();
+
+ return retval;
+}
+
+
+static int notify_buffer_mapped(const char *trace_name,
+ const char *ch_name,
+ int ch_cpu)
+{
+ int retval = 0;
+ struct ust_trace *trace;
+ struct ust_channel *channel;
+ struct ust_buffer *buf;
+
+ DBG("get_buffer_fd");
+
+ 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;
+ }
+
+ channel = find_channel(ch_name, trace);
+ if (!channel) {
+ retval = -ENODATA;
+ ERR("unable to find channel");
+ goto unlock_traces;
+ }
+
+ buf = channel->buf[ch_cpu];
+
+ /* 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:
+ ltt_unlock_traces();
+
+ return retval;
+}
+
+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;
+ struct ust_channel *channel;
+ struct ust_buffer *buf;
+
+ DBG("put_subbuf");
+
+ 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;
+ }
+
+ channel = find_channel(ch_name, trace);
+ if (!channel) {
+ retval = -ENODATA;
+ ERR("unable to find channel");
+ goto unlock_traces;
+ }
+
+ buf = channel->buf[ch_cpu];
+
+ 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:
+ ltt_unlock_traces();
+
+ return retval;
+}
+
+static void release_listener_mutex(void *ptr)
+{
+ pthread_mutex_unlock(&listener_thread_data_mutex);
+}
+
+static void listener_cleanup(void *ptr)
+{
+ 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 force_subbuf_switch(const char *trace_name)
+{
+ struct ust_trace *trace;
+ int i, j, retval = 0;
+
+ 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;
+ }
+
+ 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);