extern struct chan_info_struct chan_infos[];
-static struct cds_list_head open_buffers_list = CDS_LIST_HEAD_INIT(open_buffers_list);
-
static struct cds_list_head ust_socks = CDS_LIST_HEAD_INIT(ust_socks);
/* volatile because shared between the listener and the main thread */
CMM_STORE_SHARED(buffers_to_export, CMM_LOAD_SHARED(buffers_to_export)-1);
}
- /* The buffer has been exported, ergo, we can add it to the
- * list of open buffers
- */
- cds_list_add(&buf->open_buffers_list, &open_buffers_list);
-
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);
pthread_mutex_unlock(&listen_sock_mutex);
}
-static void force_subbuf_switch()
+static int force_subbuf_switch(const char *trace_name)
{
- struct ust_buffer *buf;
-
- cds_list_for_each_entry(buf, &open_buffers_list,
- open_buffers_list) {
- ltt_force_switch(buf, FORCE_FLUSH);
- }
-}
+ struct ust_trace *trace;
+ int i, j, retval = 0;
-/* Simple commands are those which need only respond with a return value. */
-static int process_simple_client_cmd(int command, char *recv_buf)
-{
- int result;
+ 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;
+ }
- switch(command) {
- 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) {
- return result;
+ 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);
}
- return setenv("UST_DAEMON_SOCKET", sock_msg->field, 1);
}
- case FORCE_SUBBUF_SWITCH:
- /* FIXME: return codes? */
- force_subbuf_switch();
-
- break;
-
- default:
- return -EINVAL;
- }
+unlock_traces:
+ ltt_unlock_traces();
- return 0;
+ return retval;
}
-
static int process_trace_cmd(int command, char *trace_name)
{
int result;
return result;
}
return 0;
+ case FORCE_SUBBUF_SWITCH:
+ DBG("force switch");
+
+ result = force_subbuf_switch(trace_name);
+ if (result < 0) {
+ ERR("force_subbuf_switch failed");
+ return result;
+ }
+ return 0;
}
return 0;
print_markers(fp);
fclose(fp);
- reply_header->size = size;
+ reply_header->size = size + 1; /* Include final \0 */
result = ustcomm_send(sock, reply_header, ptr);
print_trace_events(fp);
fclose(fp);
- reply_header->size = size;
+ reply_header->size = size + 1; /* Include final \0 */
result = ustcomm_send(sock, reply_header, ptr);
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;
+ }
+
+ reply_header->result = setenv("UST_DAEMON_SOCKET",
+ sock_msg->field, 1);
+
+ goto send_response;
+ }
case START:
case SETUP_TRACE:
case ALLOC_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;
}
default:
- reply_header->result =
- process_simple_client_cmd(recv_header->command,
- recv_buf);
- goto send_response;
+ reply_header->result = -EINVAL;
+ goto send_response;
}
return;
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);
epoll_sock->fd);
}
}
- pthread_mutex_unlock(&listener_thread_data_mutex);
+ pthread_cleanup_pop(1); /* release listener mutex */
}
}
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;
+
+ dir_name = ustcomm_user_sock_dir();
+ if (!dir_name)
+ return NULL;
- result = asprintf(&name, "%s/%d", SOCK_DIR, (int)getpid());
+ result = asprintf(&sock_name, "%s/%d", dir_name, (int)getpid());
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()
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;
ustcomm_del_sock(sock, 1);
}
- /* Delete all blocked consumers */
- cds_list_for_each_entry_safe(buf, buf_tmp, &open_buffers_list,
- open_buffers_list) {
- cds_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
* 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 */
void ust_after_fork_parent(ust_fork_info_t *fork_info)
{
+ 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 release mutexes and reenable signals */
ust_after_fork_common(fork_info);
-
- /*
- * Make sure we clean up the urcu-bp thread list in the child by running
- * the garbage collection before any pthread_create can be called.
- * Failure to do so could lead to a deadlock caused by reuse of a thread
- * ID before urcu-bp garbage collection is performed.
- */
- synchronize_rcu();
}