From: Mathieu Desnoyers Date: Fri, 26 Aug 2011 10:30:56 +0000 (-0400) Subject: Remove deprecated/ subdirectory X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=091247493fb294dac5b326f6809ffd3b28cb4710;p=ust.git Remove deprecated/ subdirectory Signed-off-by: Mathieu Desnoyers --- diff --git a/deprecated/libust/channels.c b/deprecated/libust/channels.c deleted file mode 100644 index ab6afd7..0000000 --- a/deprecated/libust/channels.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * ltt/ltt-channels.c - * - * (C) Copyright 2008 - Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca) - * - * LTTng channel management. - * - * Author: - * Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include "channels.h" -#include "usterr_signal_safe.h" - -/* - * ltt_channel_mutex may be nested inside the LTT trace mutex. - * ltt_channel_mutex mutex may be nested inside markers mutex. - */ -static DEFINE_MUTEX(ltt_channel_mutex); -static CDS_LIST_HEAD(ltt_channels); -/* - * Index of next channel in array. Makes sure that as long as a trace channel is - * allocated, no array index will be re-used when a channel is freed and then - * another channel is allocated. This index is cleared and the array indexeds - * get reassigned when the index_urcu_ref goes back to 0, which indicates that no - * more trace channels are allocated. - */ -static unsigned int free_index; -static struct urcu_ref index_urcu_ref; /* Keeps track of allocated trace channels */ - -int ust_channels_overwrite_by_default = 0; -int ust_channels_request_collection_by_default = 1; - -static struct ltt_channel_setting *lookup_channel(const char *name) -{ - struct ltt_channel_setting *iter; - - cds_list_for_each_entry(iter, <t_channels, list) - if (strcmp(name, iter->name) == 0) - return iter; - return NULL; -} - -/* - * Must be called when channel refcount falls to 0 _and_ also when the last - * trace is freed. This function is responsible for compacting the channel and - * event IDs when no users are active. - * - * Called with lock_markers() and channels mutex held. - */ -static void release_channel_setting(struct urcu_ref *urcu_ref) -{ - struct ltt_channel_setting *setting = _ust_container_of(urcu_ref, - struct ltt_channel_setting, urcu_ref); - struct ltt_channel_setting *iter; - - if (uatomic_read(&index_urcu_ref.refcount) == 0 - && uatomic_read(&setting->urcu_ref.refcount) == 0) { - cds_list_del(&setting->list); - free(setting); - - free_index = 0; - cds_list_for_each_entry(iter, <t_channels, list) { - iter->index = free_index++; - iter->free_event_id = 0; - } - /* FIXME: why not run this? */ -//ust// markers_compact_event_ids(); - } -} - -/* - * Perform channel index compaction when the last trace channel is freed. - * - * Called with lock_markers() and channels mutex held. - */ -static void release_trace_channel(struct urcu_ref *urcu_ref) -{ - struct ltt_channel_setting *iter, *n; - - cds_list_for_each_entry_safe(iter, n, <t_channels, list) - release_channel_setting(&iter->urcu_ref); -} - -/** - * ltt_channels_register - Register a trace channel. - * @name: channel name - * - * Uses refcounting. - */ -int ltt_channels_register(const char *name) -{ - struct ltt_channel_setting *setting; - int ret = 0; - - pthread_mutex_lock(<t_channel_mutex); - setting = lookup_channel(name); - if (setting) { - if (uatomic_read(&setting->urcu_ref.refcount) == 0) - goto init_urcu_ref; - else { - urcu_ref_get(&setting->urcu_ref); - goto end; - } - } - setting = zmalloc(sizeof(*setting)); - if (!setting) { - ret = -ENOMEM; - goto end; - } - cds_list_add(&setting->list, <t_channels); - strncpy(setting->name, name, PATH_MAX-1); - setting->index = free_index++; -init_urcu_ref: - urcu_ref_init(&setting->urcu_ref); -end: - pthread_mutex_unlock(<t_channel_mutex); - return ret; -} - -/** - * ltt_channels_unregister - Unregister a trace channel. - * @name: channel name - * - * Must be called with markers mutex held. - */ -int ltt_channels_unregister(const char *name) -{ - struct ltt_channel_setting *setting; - int ret = 0; - - pthread_mutex_lock(<t_channel_mutex); - setting = lookup_channel(name); - if (!setting || uatomic_read(&setting->urcu_ref.refcount) == 0) { - ret = -ENOENT; - goto end; - } - urcu_ref_put(&setting->urcu_ref, release_channel_setting); -end: - pthread_mutex_unlock(<t_channel_mutex); - return ret; -} - -/** - * ltt_channels_set_default - Set channel default behavior. - * @name: default channel name - * @subbuf_size: size of the subbuffers - * @subbuf_cnt: number of subbuffers - */ -int ltt_channels_set_default(const char *name, - unsigned int subbuf_size, - unsigned int subbuf_cnt) -{ - struct ltt_channel_setting *setting; - int ret = 0; - - pthread_mutex_lock(<t_channel_mutex); - setting = lookup_channel(name); - if (!setting || uatomic_read(&setting->urcu_ref.refcount) == 0) { - ret = -ENOENT; - goto end; - } - setting->subbuf_size = subbuf_size; - setting->subbuf_cnt = subbuf_cnt; -end: - pthread_mutex_unlock(<t_channel_mutex); - return ret; -} - -/** - * ltt_channels_get_name_from_index - get channel name from channel index - * @index: channel index - * - * Allows to lookup the channel name given its index. Done to keep the name - * information outside of each trace channel instance. - */ -const char *ltt_channels_get_name_from_index(unsigned int index) -{ - struct ltt_channel_setting *iter; - - cds_list_for_each_entry(iter, <t_channels, list) - if (iter->index == index && uatomic_read(&iter->urcu_ref.refcount)) - return iter->name; - return NULL; -} - -static struct ltt_channel_setting * -ltt_channels_get_setting_from_name(const char *name) -{ - struct ltt_channel_setting *iter; - - cds_list_for_each_entry(iter, <t_channels, list) - if (!strcmp(iter->name, name) - && uatomic_read(&iter->urcu_ref.refcount)) - return iter; - return NULL; -} - -/** - * ltt_channels_get_index_from_name - get channel index from channel name - * @name: channel name - * - * Allows to lookup the channel index given its name. Done to keep the name - * information outside of each trace channel instance. - * Returns -1 if not found. - */ -int ltt_channels_get_index_from_name(const char *name) -{ - struct ltt_channel_setting *setting; - - setting = ltt_channels_get_setting_from_name(name); - if (setting) - return setting->index; - else - return -1; -} - -/** - * ltt_channels_trace_alloc - Allocate channel structures for a trace - * @subbuf_size: subbuffer size. 0 uses default. - * @subbuf_cnt: number of subbuffers per per-cpu buffers. 0 uses default. - * @flags: Default channel flags - * - * Use the current channel list to allocate the channels for a trace. - * Called with trace lock held. Does not perform the trace buffer allocation, - * because we must let the user overwrite specific channel sizes. - */ -struct ust_channel *ltt_channels_trace_alloc(unsigned int *nr_channels, - int overwrite, - int request_collection, - int active) -{ - struct ust_channel *channel = NULL; - struct ltt_channel_setting *iter; - - pthread_mutex_lock(<t_channel_mutex); - if (!free_index) { - WARN("ltt_channels_trace_alloc: no free_index; are there any probes connected?"); - goto end; - } - if (!uatomic_read(&index_urcu_ref.refcount)) - urcu_ref_init(&index_urcu_ref); - else - urcu_ref_get(&index_urcu_ref); - *nr_channels = free_index; - channel = zmalloc(sizeof(struct ust_channel) * free_index); - if (!channel) { - WARN("ltt_channel_struct: channel null after alloc"); - goto end; - } - cds_list_for_each_entry(iter, <t_channels, list) { - if (!uatomic_read(&iter->urcu_ref.refcount)) - continue; - channel[iter->index].subbuf_size = iter->subbuf_size; - channel[iter->index].subbuf_cnt = iter->subbuf_cnt; - channel[iter->index].overwrite = overwrite; - channel[iter->index].request_collection = request_collection; - channel[iter->index].active = active; - channel[iter->index].channel_name = iter->name; - } -end: - pthread_mutex_unlock(<t_channel_mutex); - return channel; -} - -/** - * ltt_channels_trace_free - Free one trace's channels - * @channels: channels to free - * - * Called with trace lock held. The actual channel buffers must be freed before - * this function is called. - */ -void ltt_channels_trace_free(struct ust_channel *channels) -{ - lock_ust_marker(); - pthread_mutex_lock(<t_channel_mutex); - free(channels); - urcu_ref_put(&index_urcu_ref, release_trace_channel); - pthread_mutex_unlock(<t_channel_mutex); - unlock_ust_marker(); -} - -/** - * _ltt_channels_get_event_id - get next event ID for a marker - * @channel: channel name - * @name: event name - * - * Returns a unique event ID (for this channel) or < 0 on error. - * Must be called with channels mutex held. - */ -int _ltt_channels_get_event_id(const char *channel, const char *name) -{ - struct ltt_channel_setting *setting; - int ret; - - setting = ltt_channels_get_setting_from_name(channel); - if (!setting) { - ret = -ENOENT; - goto end; - } - if (strcmp(channel, "metadata") == 0) { - if (strcmp(name, "core_marker_id") == 0) - ret = 0; - else if (strcmp(name, "core_marker_format") == 0) - ret = 1; - else if (strcmp(name, "testev") == 0) - ret = 2; - else - ret = -ENOENT; - goto end; - } - if (setting->free_event_id == EVENTS_PER_CHANNEL - 1) { - ret = -ENOSPC; - goto end; - } - ret = setting->free_event_id++; -end: - return ret; -} - -/** - * ltt_channels_get_event_id - get next event ID for a marker - * @channel: channel name - * @name: event name - * - * Returns a unique event ID (for this channel) or < 0 on error. - */ -int ltt_channels_get_event_id(const char *channel, const char *name) -{ - int ret; - - pthread_mutex_lock(<t_channel_mutex); - ret = _ltt_channels_get_event_id(channel, name); - pthread_mutex_unlock(<t_channel_mutex); - return ret; -} diff --git a/deprecated/libust/channels.h b/deprecated/libust/channels.h deleted file mode 100644 index eb9a11c..0000000 --- a/deprecated/libust/channels.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef UST_CHANNELS_H -#define UST_CHANNELS_H - -/* - * Copyright (C) 2008 Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca) - * - * Dynamic tracer channel allocation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define _LGPL_SOURCE -#include -#include -#include -#include -#include -#include - -#define EVENTS_PER_CHANNEL 65536 -#define MAX_CPUS 32 - -struct ust_trace; - -struct ust_buffer; - -struct ust_channel { - /* First 32 bytes cache-hot cacheline */ - struct ust_trace *trace; - int *buf_struct_shmids; - struct ust_buffer **buf; - int overwrite:1; - /* whether collection is requested upon trace start */ - int request_collection:1; - int active:1; - unsigned int n_subbufs_order; - unsigned long commit_count_mask; /* - * Commit count mask, removing - * the MSBs corresponding to - * bits used to represent the - * subbuffer index. - */ - /* End of first 32 bytes cacheline */ - - struct urcu_ref urcu_ref; /* Channel transport reference count */ - size_t subbuf_size; - int subbuf_size_order; - unsigned int subbuf_cnt; - const char *channel_name; - int n_cpus; - - u32 version; - size_t alloc_size; - struct cds_list_head list; -} ____cacheline_aligned; - -struct ltt_channel_setting { - unsigned int subbuf_size; - unsigned int subbuf_cnt; - struct urcu_ref urcu_ref; /* Number of references to structure content */ - struct cds_list_head list; - unsigned int index; /* index of channel in trace channel array */ - u16 free_event_id; /* Next event ID to allocate */ - char name[PATH_MAX]; -}; - -extern int ltt_channels_register(const char *name); -extern int ltt_channels_unregister(const char *name); -extern int ltt_channels_set_default(const char *name, - unsigned int subbuf_size, - unsigned int subbuf_cnt); -extern const char *ltt_channels_get_name_from_index(unsigned int index); -extern int ltt_channels_get_index_from_name(const char *name); -extern struct ust_channel *ltt_channels_trace_alloc(unsigned int *nr_channels, - int overwrite, - int request_collection, - int active); -extern void ltt_channels_trace_free(struct ust_channel *channels); -extern int _ltt_channels_get_event_id(const char *channel, const char *name); -extern int ltt_channels_get_event_id(const char *channel, const char *name); - -extern int ust_channels_overwrite_by_default; -extern int ust_channels_request_collection_by_default; - -#endif /* UST_CHANNELS_H */ diff --git a/deprecated/libust/marker-control.c b/deprecated/libust/marker-control.c deleted file mode 100644 index 0d3cb2c..0000000 --- a/deprecated/libust/marker-control.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2007 Mathieu Desnoyers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* This file contains a high-level API for activating and deactivating ust_markers, - * and making sure ust_markers in a given library can be released when the library - * is unloaded. - */ - -#include -#include - -#include "tracer.h" -#include "usterr_signal_safe.h" - -#define DEFAULT_CHANNEL "cpu" -#define DEFAULT_PROBE "default" - -static int initialized; - -CDS_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 *ust_markers_loaded_cachep; -static CDS_LIST_HEAD(ust_markers_loaded_list); -/* - * List sorted by name strcmp order. - */ -static CDS_LIST_HEAD(probes_registered_list); - -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; - cds_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; -} - -/* (unused) -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_ust_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; - - pthread_mutex_lock(&probes_mutex); - cds_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. */ - cds_list_add(&pdata->node, &iter->node); - goto end; - } - } - /* Should be added at the head of the list */ - cds_list_add(&pdata->node, &probes_registered_list); -end: - pthread_mutex_unlock(&probes_mutex); - return ret; -} - -/* - * 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_ust_marker *amark, *tmp; - - pthread_mutex_lock(&probes_mutex); - cds_list_for_each_entry_safe(amark, tmp, &ust_markers_loaded_list, node) { - if (amark->probe == pdata) { - ret = ust_marker_probe_unregister_private_data( - pdata->probe_func, amark); - if (ret) - goto end; - cds_list_del(&amark->node); - free(amark); - } - } - cds_list_del(&pdata->node); -end: - pthread_mutex_unlock(&probes_mutex); - return ret; -} - -/* - * Connect ust_marker "mname" to probe "pname". - * Only allow _only_ probe instance to be connected to a ust_marker. - */ -int ltt_ust_marker_connect(const char *channel, const char *mname, - const char *pname) - -{ - int ret; - struct ltt_active_ust_marker *pdata; - struct ltt_available_probe *probe; - - ltt_lock_traces(); - pthread_mutex_lock(&probes_mutex); - probe = get_probe_from_name(pname); - if (!probe) { - ret = -ENOENT; - goto end; - } - pdata = ust_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_ust_marker)); - if (!pdata) { - ret = -ENOMEM; - goto end; - } - pdata->probe = probe; - /* - * ID has priority over channel in case of conflict. - */ - ret = ust_marker_probe_register(channel, mname, NULL, - probe->probe_func, pdata); - if (ret) - free(pdata); - else - cds_list_add(&pdata->node, &ust_markers_loaded_list); -end: - pthread_mutex_unlock(&probes_mutex); - ltt_unlock_traces(); - return ret; -} - -/* - * Disconnect ust_marker "mname", probe "pname". - */ -int ltt_ust_marker_disconnect(const char *channel, const char *mname, - const char *pname) -{ - struct ltt_active_ust_marker *pdata; - struct ltt_available_probe *probe; - int ret = 0; - - pthread_mutex_lock(&probes_mutex); - probe = get_probe_from_name(pname); - if (!probe) { - ret = -ENOENT; - goto end; - } - pdata = ust_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 = ust_marker_probe_unregister(channel, mname, probe->probe_func, pdata); - if (ret) - goto end; - else { - cds_list_del(&pdata->node); - free(pdata); - } -end: - pthread_mutex_unlock(&probes_mutex); - return ret; -} - -static void disconnect_all_ust_markers(void) -{ - struct ltt_active_ust_marker *pdata, *tmp; - - cds_list_for_each_entry_safe(pdata, tmp, &ust_markers_loaded_list, node) { - ust_marker_probe_unregister_private_data(pdata->probe->probe_func, - pdata); - cds_list_del(&pdata->node); - free(pdata); - } -} - -void __attribute__((constructor)) init_ust_marker_control(void) -{ - if (!initialized) { - int ret; - - init_ust_marker(); - ret = ltt_probe_register(&default_probe); - BUG_ON(ret); - ret = ltt_ust_marker_connect("metadata", "core_marker_format", - DEFAULT_PROBE); - BUG_ON(ret); - ret = ltt_ust_marker_connect("metadata", "core_marker_id", DEFAULT_PROBE); - BUG_ON(ret); - initialized = 1; - } -} - -static void __attribute__((destructor)) ust_marker_control_exit(void) -{ - int ret; - - ret = ltt_ust_marker_disconnect("metadata", "core_marker_format", - DEFAULT_PROBE); - BUG_ON(ret); - ret = ltt_ust_marker_disconnect("metadata", "core_marker_id", - DEFAULT_PROBE); - BUG_ON(ret); - ret = ltt_probe_unregister(&default_probe); - BUG_ON(ret); - disconnect_all_ust_markers(); - ust_marker_synchronize_unregister(); -} diff --git a/deprecated/libust/marker-control.h b/deprecated/libust/marker-control.h deleted file mode 100644 index a1b65a1..0000000 --- a/deprecated/libust/marker-control.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2009 - Pierre-Marc Fournier (pierre-marc dot fournier at polymtl dot ca) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef MARKER_CONTROL_H -#define MARKER_CONTROL_H - -int init_ust_marker_control(void); -int ltt_probe_register(struct ltt_available_probe *pdata); - -#endif /* MARKER_CONTROL_H */ diff --git a/deprecated/libust/marker.c b/deprecated/libust/marker.c deleted file mode 100644 index a497f06..0000000 --- a/deprecated/libust/marker.c +++ /dev/null @@ -1,1202 +0,0 @@ -/* - * Copyright (C) 2007-2011 Mathieu Desnoyers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define _LGPL_SOURCE -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "usterr_signal_safe.h" -#include "channels.h" -#include "tracercore.h" -#include "tracer.h" - -extern struct ust_marker * const __start___ust_marker_ptrs[] __attribute__((visibility("hidden"))); -extern struct ust_marker * const __stop___ust_marker_ptrs[] __attribute__((visibility("hidden"))); - -/* Set to 1 to enable ust_marker debug output */ -static const int ust_marker_debug; -static int initialized; -static void (*new_ust_marker_cb)(struct ust_marker *); - -/* - * ust_marker mutex protects the builtin and module ust_marker and the - * hash table, as well as the ust_marker_libs list. - */ -static DEFINE_MUTEX(ust_marker_mutex); -static CDS_LIST_HEAD(ust_marker_libs); - -/* - * Allow nested mutex for mutex listing and nested enable. - */ -static __thread int nested_mutex; - -void lock_ust_marker(void) -{ - if (!(nested_mutex++)) - pthread_mutex_lock(&ust_marker_mutex); -} - -void unlock_ust_marker(void) -{ - if (!(--nested_mutex)) - pthread_mutex_unlock(&ust_marker_mutex); -} - -/* - * ust_marker hash table, containing the active ust_marker. - * Protected by ust_marker mutex. - */ -#define UST_MARKER_HASH_BITS 6 -#define UST_MARKER_TABLE_SIZE (1 << UST_MARKER_HASH_BITS) -static struct cds_hlist_head ust_marker_table[UST_MARKER_TABLE_SIZE]; - -struct ust_marker_probe_array { - struct rcu_head rcu; - struct ust_marker_probe_closure c[0]; -}; - -/* - * Note about RCU : - * It is used to make sure every handler has finished using its private - * data between two consecutive operation (add or remove) on a given - * ust_marker. It is also used to delay the free of multiple probes - * array until a quiescent state is reached. ust_marker entries - * modifications are protected by the ust_marker_mutex. - */ -struct ust_marker_entry { - struct cds_hlist_node hlist; - char *format; - char *name; - /* Probe wrapper */ - void (*call)(const struct ust_marker *mdata, void *call_private, ...); - struct ust_marker_probe_closure single; - struct ust_marker_probe_array *multi; - int refcount; /* Number of times armed. 0 if disarmed. */ - u16 channel_id; - u16 event_id; - unsigned char ptype:1; - unsigned char format_allocated:1; - char channel[0]; /* Contains channel'\0'name'\0'format'\0' */ -}; - -/** - * __ust_marker_empty_function - Empty probe callback - * @mdata: ust_marker data - * @probe_private: probe private data - * @call_private: call site private data - * @fmt: format string - * @...: variable argument list - * - * Empty callback provided as a probe to the ust_marker. By providing - * this to a disabled ust_marker, we make sure the execution flow is - * always valid even though the function pointer change and the - * ust_marker enabling are two distinct operations that modifies the - * execution flow of preemptible code. - */ -notrace void __ust_marker_empty_function(const struct ust_marker *mdata, - void *probe_private, void *call_private, const char *fmt, va_list *args) -{ -} - -/* - * ust_marker_probe_cb Callback that prepares the variable argument list for probes. - * @mdata: pointer of type struct ust_marker - * @call_private: caller site private data - * @...: Variable argument list. - * - * Since we do not use "typical" pointer based RCU in the 1 argument case, we - * need to put a full cmm_smp_rmb() in this branch. This is why we do not use - * rcu_dereference() for the pointer read. - */ -notrace void ust_marker_probe_cb(const struct ust_marker *mdata, - void *call_private, ...) -{ - va_list args; - char ptype; - - /* - * rcu_read_lock_sched does two things : disabling preemption to make - * sure the teardown of the callbacks can be done correctly when they - * are in modules and they insure RCU read coherency. - */ - rcu_read_lock(); - ptype = mdata->ptype; - if (likely(!ptype)) { - ust_marker_probe_func *func; - /* Must read the ptype before ptr. They are not data dependant, - * so we put an explicit cmm_smp_rmb() here. */ - cmm_smp_rmb(); - func = mdata->single.func; - /* Must read the ptr before private data. They are not data - * dependant, so we put an explicit cmm_smp_rmb() here. */ - cmm_smp_rmb(); - va_start(args, call_private); - func(mdata, mdata->single.probe_private, call_private, - mdata->format, &args); - va_end(args); - } else { - struct ust_marker_probe_array *multi; - int i; - /* - * Read mdata->ptype before mdata->multi. - */ - cmm_smp_rmb(); - multi = mdata->multi; - /* - * multi points to an array, therefore accessing the array - * depends on reading multi. However, even in this case, - * we must insure that the pointer is read _before_ the array - * data. Same as rcu_dereference, but we need a full cmm_smp_rmb() - * in the fast path, so put the explicit cmm_barrier here. - */ - cmm_smp_read_barrier_depends(); - for (i = 0; multi->c[i].func; i++) { - va_start(args, call_private); - multi->c[i].func(mdata, multi->c[i].probe_private, - call_private, mdata->format, &args); - va_end(args); - } - } - rcu_read_unlock(); -} - -/* - * ust_marker_probe_cb Callback that does not prepare the variable argument list. - * @mdata: pointer of type struct ust_marker - * @call_private: caller site private data - * @...: Variable argument list. - * - * Should be connected to ust_marker "UST_MARKER_NOARGS". - */ -static notrace void ust_marker_probe_cb_noarg(const struct ust_marker *mdata, - void *call_private, ...) -{ - va_list args; /* not initialized */ - char ptype; - - rcu_read_lock(); - ptype = mdata->ptype; - if (likely(!ptype)) { - ust_marker_probe_func *func; - /* Must read the ptype before ptr. They are not data dependant, - * so we put an explicit cmm_smp_rmb() here. */ - cmm_smp_rmb(); - func = mdata->single.func; - /* Must read the ptr before private data. They are not data - * dependant, so we put an explicit cmm_smp_rmb() here. */ - cmm_smp_rmb(); - func(mdata, mdata->single.probe_private, call_private, - mdata->format, &args); - } else { - struct ust_marker_probe_array *multi; - int i; - /* - * Read mdata->ptype before mdata->multi. - */ - cmm_smp_rmb(); - multi = mdata->multi; - /* - * multi points to an array, therefore accessing the array - * depends on reading multi. However, even in this case, - * we must insure that the pointer is read _before_ the array - * data. Same as rcu_dereference, but we need a full cmm_smp_rmb() - * in the fast path, so put the explicit cmm_barrier here. - */ - cmm_smp_read_barrier_depends(); - for (i = 0; multi->c[i].func; i++) - multi->c[i].func(mdata, multi->c[i].probe_private, - call_private, mdata->format, &args); - } - rcu_read_unlock(); -} - -static void free_old_closure(struct rcu_head *head) -{ - struct ust_marker_probe_array *multi = - _ust_container_of(head, struct ust_marker_probe_array, rcu); - free(multi); -} - -static void debug_print_probes(struct ust_marker_entry *entry) -{ - int i; - - if (!ust_marker_debug) - return; - - if (!entry->ptype) { - DBG("Single probe : %p %p", - entry->single.func, - entry->single.probe_private); - } else { - for (i = 0; entry->multi->c[i].func; i++) - DBG("Multi probe %d : %p %p", i, - entry->multi->c[i].func, - entry->multi->c[i].probe_private); - } -} - -static struct ust_marker_probe_array * -ust_marker_entry_add_probe(struct ust_marker_entry *entry, - ust_marker_probe_func *probe, void *probe_private) -{ - int nr_probes = 0; - struct ust_marker_probe_array *old, *new; - - WARN_ON(!probe); - - debug_print_probes(entry); - old = entry->multi; - if (!entry->ptype) { - if (entry->single.func == probe && - entry->single.probe_private == probe_private) - return ERR_PTR(-EBUSY); - if (entry->single.func == __ust_marker_empty_function) { - /* 0 -> 1 probes */ - entry->single.func = probe; - entry->single.probe_private = probe_private; - entry->refcount = 1; - entry->ptype = 0; - debug_print_probes(entry); - return NULL; - } else { - /* 1 -> 2 probes */ - nr_probes = 1; - old = NULL; - } - } else { - /* (N -> N+1), (N != 0, 1) probes */ - for (nr_probes = 0; old->c[nr_probes].func; nr_probes++) - if (old->c[nr_probes].func == probe - && old->c[nr_probes].probe_private - == probe_private) - return ERR_PTR(-EBUSY); - } - /* + 2 : one for new probe, one for NULL func */ - new = zmalloc(sizeof(struct ust_marker_probe_array) - + ((nr_probes + 2) * sizeof(struct ust_marker_probe_closure))); - if (new == NULL) - return ERR_PTR(-ENOMEM); - if (!old) - new->c[0] = entry->single; - else - memcpy(&new->c[0], &old->c[0], - nr_probes * sizeof(struct ust_marker_probe_closure)); - new->c[nr_probes].func = probe; - new->c[nr_probes].probe_private = probe_private; - entry->refcount = nr_probes + 1; - entry->multi = new; - entry->ptype = 1; - debug_print_probes(entry); - return old; -} - -static struct ust_marker_probe_array * -ust_marker_entry_remove_probe(struct ust_marker_entry *entry, - ust_marker_probe_func *probe, void *probe_private) -{ - int nr_probes = 0, nr_del = 0, i; - struct ust_marker_probe_array *old, *new; - - old = entry->multi; - - debug_print_probes(entry); - if (!entry->ptype) { - /* 0 -> N is an error */ - WARN_ON(entry->single.func == __ust_marker_empty_function); - /* 1 -> 0 probes */ - WARN_ON(probe && entry->single.func != probe); - WARN_ON(entry->single.probe_private != probe_private); - entry->single.func = __ust_marker_empty_function; - entry->refcount = 0; - entry->ptype = 0; - debug_print_probes(entry); - return NULL; - } else { - /* (N -> M), (N > 1, M >= 0) probes */ - for (nr_probes = 0; old->c[nr_probes].func; nr_probes++) { - if ((!probe || old->c[nr_probes].func == probe) - && old->c[nr_probes].probe_private - == probe_private) - nr_del++; - } - } - - if (nr_probes - nr_del == 0) { - /* N -> 0, (N > 1) */ - entry->single.func = __ust_marker_empty_function; - entry->refcount = 0; - entry->ptype = 0; - } else if (nr_probes - nr_del == 1) { - /* N -> 1, (N > 1) */ - for (i = 0; old->c[i].func; i++) - if ((probe && old->c[i].func != probe) || - old->c[i].probe_private != probe_private) - entry->single = old->c[i]; - entry->refcount = 1; - entry->ptype = 0; - } else { - int j = 0; - /* N -> M, (N > 1, M > 1) */ - /* + 1 for NULL */ - new = zmalloc(sizeof(struct ust_marker_probe_array) - + ((nr_probes - nr_del + 1) * sizeof(struct ust_marker_probe_closure))); - if (new == NULL) - return ERR_PTR(-ENOMEM); - for (i = 0; old->c[i].func; i++) - if ((probe && old->c[i].func != probe) || - old->c[i].probe_private != probe_private) - new->c[j++] = old->c[i]; - entry->refcount = nr_probes - nr_del; - entry->ptype = 1; - entry->multi = new; - } - debug_print_probes(entry); - return old; -} - -/* - * Get ust_marker if the ust_marker is present in the ust_marker hash table. - * Must be called with ust_marker_mutex held. - * Returns NULL if not present. - */ -static struct ust_marker_entry *get_ust_marker(const char *channel, const char *name) -{ - struct cds_hlist_head *head; - struct cds_hlist_node *node; - struct ust_marker_entry *e; - size_t channel_len = strlen(channel) + 1; - size_t name_len = strlen(name) + 1; - u32 hash; - - hash = jhash(channel, channel_len-1, 0) ^ jhash(name, name_len-1, 0); - head = &ust_marker_table[hash & ((1 << UST_MARKER_HASH_BITS)-1)]; - cds_hlist_for_each_entry(e, node, head, hlist) { - if (!strcmp(channel, e->channel) && !strcmp(name, e->name)) - return e; - } - return NULL; -} - -/* - * Add the ust_marker to the ust_marker hash table. Must be called with - * ust_marker_mutex held. - */ -static struct ust_marker_entry *add_ust_marker(const char *channel, const char *name, - const char *format) -{ - struct cds_hlist_head *head; - struct cds_hlist_node *node; - struct ust_marker_entry *e; - size_t channel_len = strlen(channel) + 1; - size_t name_len = strlen(name) + 1; - size_t format_len = 0; - u32 hash; - - hash = jhash(channel, channel_len-1, 0) ^ jhash(name, name_len-1, 0); - if (format) - format_len = strlen(format) + 1; - head = &ust_marker_table[hash & ((1 << UST_MARKER_HASH_BITS)-1)]; - cds_hlist_for_each_entry(e, node, head, hlist) { - if (!strcmp(channel, e->channel) && !strcmp(name, e->name)) { - DBG("ust_marker %s.%s busy", channel, name); - return ERR_PTR(-EBUSY); /* Already there */ - } - } - /* - * Using zmalloc here to allocate a variable length element. Could - * cause some memory fragmentation if overused. - */ - e = zmalloc(sizeof(struct ust_marker_entry) - + channel_len + name_len + format_len); - if (!e) - return ERR_PTR(-ENOMEM); - memcpy(e->channel, channel, channel_len); - e->name = &e->channel[channel_len]; - memcpy(e->name, name, name_len); - if (format) { - e->format = &e->name[name_len]; - memcpy(e->format, format, format_len); - if (strcmp(e->format, UST_MARKER_NOARGS) == 0) - e->call = ust_marker_probe_cb_noarg; - else - e->call = ust_marker_probe_cb; - __ust_marker(metadata, core_marker_format, NULL, - "channel %s name %s format %s", - e->channel, e->name, e->format); - } else { - e->format = NULL; - e->call = ust_marker_probe_cb; - } - e->single.func = __ust_marker_empty_function; - e->single.probe_private = NULL; - e->multi = NULL; - e->ptype = 0; - e->format_allocated = 0; - e->refcount = 0; - cds_hlist_add_head(&e->hlist, head); - return e; -} - -/* - * Remove the ust_marker from the ust_marker hash table. Must be called with mutex_lock - * held. - */ -static int remove_ust_marker(const char *channel, const char *name) -{ - struct cds_hlist_head *head; - struct cds_hlist_node *node; - struct ust_marker_entry *e; - int found = 0; - size_t channel_len = strlen(channel) + 1; - size_t name_len = strlen(name) + 1; - u32 hash; - int ret; - - hash = jhash(channel, channel_len-1, 0) ^ jhash(name, name_len-1, 0); - head = &ust_marker_table[hash & ((1 << UST_MARKER_HASH_BITS)-1)]; - cds_hlist_for_each_entry(e, node, head, hlist) { - if (!strcmp(channel, e->channel) && !strcmp(name, e->name)) { - found = 1; - break; - } - } - if (!found) - return -ENOENT; - if (e->single.func != __ust_marker_empty_function) - return -EBUSY; - cds_hlist_del(&e->hlist); - if (e->format_allocated) - free(e->format); - ret = ltt_channels_unregister(e->channel); - WARN_ON(ret); - free(e); - return 0; -} - -/* - * Set the mark_entry format to the format found in the element. - */ -static int ust_marker_set_format(struct ust_marker_entry *entry, const char *format) -{ - entry->format = strdup(format); - if (!entry->format) - return -ENOMEM; - entry->format_allocated = 1; - - __ust_marker(metadata, core_marker_format, NULL, - "channel %s name %s format %s", - entry->channel, entry->name, entry->format); - return 0; -} - -/* - * Sets the probe callback corresponding to one ust_marker. - */ -static int set_ust_marker(struct ust_marker_entry *entry, struct ust_marker *elem, - int active) -{ - int ret = 0; - WARN_ON(strcmp(entry->name, elem->name) != 0); - - if (entry->format) { - if (strcmp(entry->format, elem->format) != 0) { - ERR("Format mismatch for probe %s (%s), ust_marker (%s)", - entry->name, - entry->format, - elem->format); - return -EPERM; - } - } else { - ret = ust_marker_set_format(entry, elem->format); - if (ret) - return ret; - } - - /* - * probe_cb setup (statically known) is done here. It is - * asynchronous with the rest of execution, therefore we only - * pass from a "safe" callback (with argument) to an "unsafe" - * callback (does not set arguments). - */ - elem->call = entry->call; - elem->channel_id = entry->channel_id; - elem->event_id = entry->event_id; - /* - * Sanity check : - * We only update the single probe private data when the ptr is - * set to a _non_ single probe! (0 -> 1 and N -> 1, N != 1) - */ - WARN_ON(elem->single.func != __ust_marker_empty_function - && elem->single.probe_private != entry->single.probe_private - && !elem->ptype); - elem->single.probe_private = entry->single.probe_private; - /* - * Make sure the private data is valid when we update the - * single probe ptr. - */ - cmm_smp_wmb(); - elem->single.func = entry->single.func; - /* - * We also make sure that the new probe callbacks array is consistent - * before setting a pointer to it. - */ - rcu_assign_pointer(elem->multi, entry->multi); - /* - * Update the function or multi probe array pointer before setting the - * ptype. - */ - cmm_smp_wmb(); - elem->ptype = entry->ptype; - - if (elem->tp_name && (active ^ elem->state)) { - WARN_ON(!elem->tp_cb); - /* - * It is ok to directly call the probe registration because type - * checking has been done in the __ust_marker_tp() macro. - */ - - if (active) { - ret = tracepoint_probe_register_noupdate( - elem->tp_name, - elem->tp_cb, NULL); - } else { - /* - * tracepoint_probe_update_all() must be called - * before the library containing tp_cb is unloaded. - */ - ret = tracepoint_probe_unregister_noupdate( - elem->tp_name, - elem->tp_cb, NULL); - } - } - elem->state = active; - - return ret; -} - -/* - * Disable a ust_marker and its probe callback. - * Note: only waiting an RCU period after setting elem->call to the empty - * function insures that the original callback is not used anymore. This insured - * by rcu_read_lock around the call site. - */ -static void disable_ust_marker(struct ust_marker *elem) -{ - int ret; - - /* leave "call" as is. It is known statically. */ - if (elem->tp_name && elem->state) { - WARN_ON(!elem->tp_cb); - /* - * It is ok to directly call the probe registration because type - * checking has been done in the __ust_marker_tp() macro. - */ - /* - * tracepoint_probe_update_all() must be called - * before the module containing tp_cb is unloaded. - */ - ret = tracepoint_probe_unregister_noupdate(elem->tp_name, - elem->tp_cb, NULL); - WARN_ON(ret); - } - elem->state = 0; - elem->single.func = __ust_marker_empty_function; - /* Update the function before setting the ptype */ - cmm_smp_wmb(); - elem->ptype = 0; /* single probe */ - /* - * Leave the private data and channel_id/event_id there, because removal - * is racy and should be done only after an RCU period. These are never - * used until the next initialization anyway. - */ -} - -/* - * is_ust_marker_enabled - Check if a ust_marker is enabled - * @channel: channel name - * @name: ust_marker name - * - * Returns 1 if the ust_marker is enabled, 0 if disabled. - */ -int is_ust_marker_enabled(const char *channel, const char *name) -{ - struct ust_marker_entry *entry; - - lock_ust_marker(); - entry = get_ust_marker(channel, name); - unlock_ust_marker(); - - return entry && !!entry->refcount; -} - -/** - * ust_marker_update_probe_range - Update a probe range - * @begin: beginning of the range - * @end: end of the range - * - * Updates the probe callback corresponding to a range of ust_marker. - */ -static -void ust_marker_update_probe_range(struct ust_marker * const *begin, - struct ust_marker * const *end) -{ - struct ust_marker * const *iter; - struct ust_marker_entry *mark_entry; - - for (iter = begin; iter < end; iter++) { - if (!*iter) - continue; /* skip dummy */ - mark_entry = get_ust_marker((*iter)->channel, (*iter)->name); - if (mark_entry) { - set_ust_marker(mark_entry, *iter, !!mark_entry->refcount); - /* - * ignore error, continue - */ - } else { - disable_ust_marker(*iter); - } - } -} - -static void lib_update_ust_marker(void) -{ - struct ust_marker_lib *lib; - - lock_ust_marker(); - cds_list_for_each_entry(lib, &ust_marker_libs, list) - ust_marker_update_probe_range(lib->ust_marker_start, - lib->ust_marker_start + lib->ust_marker_count); - unlock_ust_marker(); -} - -/* - * Update probes, removing the faulty probes. - * - * Internal callback only changed before the first probe is connected to it. - * Single probe private data can only be changed on 0 -> 1 and 2 -> 1 - * transitions. All other transitions will leave the old private data valid. - * This makes the non-atomicity of the callback/private data updates valid. - * - * "special case" updates : - * 0 -> 1 callback - * 1 -> 0 callback - * 1 -> 2 callbacks - * 2 -> 1 callbacks - * Other updates all behave the same, just like the 2 -> 3 or 3 -> 2 updates. - * Site effect : ust_marker_set_format may delete the ust_marker entry (creating a - * replacement). - */ -static void ust_marker_update_probes(void) -{ - lib_update_ust_marker(); - tracepoint_probe_update_all(); -} - -/** - * ust_marker_probe_register - Connect a probe to a ust_marker - * @channel: ust_marker channel - * @name: ust_marker name - * @format: format string - * @probe: probe handler - * @probe_private: probe private data - * - * private data must be a valid allocated memory address, or NULL. - * Returns 0 if ok, error value on error. - * The probe address must at least be aligned on the architecture pointer size. - */ -int ust_marker_probe_register(const char *channel, const char *name, - const char *format, ust_marker_probe_func *probe, - void *probe_private) -{ - struct ust_marker_entry *entry; - int ret = 0, ret_err; - struct ust_marker_probe_array *old; - int first_probe = 0; - - lock_ust_marker(); - entry = get_ust_marker(channel, name); - if (!entry) { - first_probe = 1; - entry = add_ust_marker(channel, name, format); - if (IS_ERR(entry)) - ret = PTR_ERR(entry); - if (ret) - goto end; - ret = ltt_channels_register(channel); - if (ret) - goto error_remove_ust_marker; - ret = ltt_channels_get_index_from_name(channel); - if (ret < 0) - goto error_unregister_channel; - entry->channel_id = ret; - ret = ltt_channels_get_event_id(channel, name); - if (ret < 0) - goto error_unregister_channel; - entry->event_id = ret; - ret = 0; - __ust_marker(metadata, core_marker_id, NULL, - "channel %s name %s event_id %hu " - "int #1u%zu long #1u%zu pointer #1u%zu " - "size_t #1u%zu alignment #1u%u", - channel, name, entry->event_id, - sizeof(int), sizeof(long), sizeof(void *), - sizeof(size_t), ltt_get_alignment()); - } else if (format) { - if (!entry->format) - ret = ust_marker_set_format(entry, format); - else if (strcmp(entry->format, format)) - ret = -EPERM; - if (ret) - goto end; - } - - old = ust_marker_entry_add_probe(entry, probe, probe_private); - if (IS_ERR(old)) { - ret = PTR_ERR(old); - if (first_probe) - goto error_unregister_channel; - else - goto end; - } - unlock_ust_marker(); - - /* Activate ust_marker if necessary */ - ust_marker_update_probes(); - - if (old) { - synchronize_rcu(); - free_old_closure(&old->rcu); - } - return ret; - -error_unregister_channel: - ret_err = ltt_channels_unregister(channel); - WARN_ON(ret_err); -error_remove_ust_marker: - ret_err = remove_ust_marker(channel, name); - WARN_ON(ret_err); -end: - unlock_ust_marker(); - return ret; -} - -/** - * ust_marker_probe_unregister - Disconnect a probe from a ust_marker - * @channel: ust_marker channel - * @name: ust_marker name - * @probe: probe function pointer - * @probe_private: probe private data - * - * Returns the private data given to ust_marker_probe_register, or an ERR_PTR(). - * We do not need to call a synchronize_sched to make sure the probes have - * finished running before doing a module unload, because the module unload - * itself uses stop_machine(), which insures that every preempt disabled section - * have finished. - */ -int ust_marker_probe_unregister(const char *channel, const char *name, - ust_marker_probe_func *probe, void *probe_private) -{ - struct ust_marker_entry *entry; - struct ust_marker_probe_array *old; - int ret = 0; - - lock_ust_marker(); - entry = get_ust_marker(channel, name); - if (!entry) { - ret = -ENOENT; - goto end; - } - old = ust_marker_entry_remove_probe(entry, probe, probe_private); - unlock_ust_marker(); - - ust_marker_update_probes(); - - if (old) { - synchronize_rcu(); - free_old_closure(&old->rcu); - } - return ret; - -end: - unlock_ust_marker(); - return ret; -} - -static struct ust_marker_entry * -get_ust_marker_from_private_data(ust_marker_probe_func *probe, - void *probe_private) -{ - struct ust_marker_entry *entry; - unsigned int i; - struct cds_hlist_head *head; - struct cds_hlist_node *node; - - for (i = 0; i < UST_MARKER_TABLE_SIZE; i++) { - head = &ust_marker_table[i]; - cds_hlist_for_each_entry(entry, node, head, hlist) { - if (!entry->ptype) { - if (entry->single.func == probe - && entry->single.probe_private - == probe_private) - return entry; - } else { - struct ust_marker_probe_array *closure; - closure = entry->multi; - for (i = 0; closure->c[i].func; i++) { - if (closure->c[i].func == probe && - closure->c[i].probe_private - == probe_private) - return entry; - } - } - } - } - return NULL; -} - -/** - * ust_marker_probe_unregister_private_data - Disconnect a probe from a ust_marker - * @probe: probe function - * @probe_private: probe private data - * - * Unregister a probe by providing the registered private data. - * Only removes the first ust_marker found in hash table. - * Return 0 on success or error value. - * We do not need to call a synchronize_sched to make sure the probes have - * finished running before doing a module unload, because the module unload - * itself uses stop_machine(), which insures that every preempt disabled section - * have finished. - */ -int ust_marker_probe_unregister_private_data(ust_marker_probe_func *probe, - void *probe_private) -{ - struct ust_marker_entry *entry; - int ret = 0; - struct ust_marker_probe_array *old; - char *channel = NULL, *name = NULL; - - lock_ust_marker(); - entry = get_ust_marker_from_private_data(probe, probe_private); - if (!entry) { - ret = -ENOENT; - goto unlock; - } - old = ust_marker_entry_remove_probe(entry, NULL, probe_private); - channel = strdup(entry->channel); - name = strdup(entry->name); - /* Ignore busy error message */ - remove_ust_marker(channel, name); - unlock_ust_marker(); - - ust_marker_update_probes(); - - if (old) { - synchronize_rcu(); - free_old_closure(&old->rcu); - } - goto end; - -unlock: - unlock_ust_marker(); -end: - free(channel); - free(name); - return ret; -} - -/** - * ust_marker_get_private_data - Get a ust_marker's probe private data - * @channel: ust_marker channel - * @name: ust_marker name - * @probe: probe to match - * @num: get the nth matching probe's private data - * - * Returns the nth private data pointer (starting from 0) matching, or an - * ERR_PTR. - * Returns the private data pointer, or an ERR_PTR. - * The private data pointer should _only_ be dereferenced if the caller is the - * owner of the data, or its content could vanish. This is mostly used to - * confirm that a caller is the owner of a registered probe. - */ -void *ust_marker_get_private_data(const char *channel, const char *name, - ust_marker_probe_func *probe, int num) -{ - struct cds_hlist_head *head; - struct cds_hlist_node *node; - struct ust_marker_entry *e; - size_t channel_len = strlen(channel) + 1; - size_t name_len = strlen(name) + 1; - int i; - u32 hash; - - hash = jhash(channel, channel_len-1, 0) ^ jhash(name, name_len-1, 0); - head = &ust_marker_table[hash & ((1 << UST_MARKER_HASH_BITS)-1)]; - cds_hlist_for_each_entry(e, node, head, hlist) { - if (!strcmp(channel, e->channel) && !strcmp(name, e->name)) { - if (!e->ptype) { - if (num == 0 && e->single.func == probe) - return e->single.probe_private; - } else { - struct ust_marker_probe_array *closure; - int match = 0; - closure = e->multi; - for (i = 0; closure->c[i].func; i++) { - if (closure->c[i].func != probe) - continue; - if (match++ == num) - return closure->c[i].probe_private; - } - } - break; - } - } - return ERR_PTR(-ENOENT); -} - -/** - * ust_marker_get_iter_range - Get a next ust_marker iterator given a range. - * @ust_marker: current ust_marker (in), next ust_marker (out) - * @begin: beginning of the range - * @end: end of the range - * - * Returns whether a next ust_marker has been found (1) or not (0). - * Will return the first ust_marker in the range if the input ust_marker is NULL. - * Called with markers mutex held. - */ -static -int ust_marker_get_iter_range(struct ust_marker * const **ust_marker, - struct ust_marker * const *begin, - struct ust_marker * const *end) -{ - if (!*ust_marker && begin != end) - *ust_marker = begin; - while (*ust_marker >= begin && *ust_marker < end) { - if (!**ust_marker) - (*ust_marker)++; /* skip dummy */ - else - return 1; - } - return 0; -} - -/* - * Returns 0 if current not found. - * Returns 1 if current found. - * Called with markers mutex held. - */ -static -int lib_get_iter_ust_marker(struct ust_marker_iter *iter) -{ - struct ust_marker_lib *iter_lib; - int found = 0; - - cds_list_for_each_entry(iter_lib, &ust_marker_libs, list) { - if (iter_lib < iter->lib) - continue; - else if (iter_lib > iter->lib) - iter->ust_marker = NULL; - found = ust_marker_get_iter_range(&iter->ust_marker, - iter_lib->ust_marker_start, - iter_lib->ust_marker_start + iter_lib->ust_marker_count); - if (found) { - iter->lib = iter_lib; - break; - } - } - return found; -} - -/* Called with markers mutex held. */ -static void ust_marker_get_iter(struct ust_marker_iter *iter) -{ - int found = 0; - - found = lib_get_iter_ust_marker(iter); - if (!found) - ust_marker_iter_reset(iter); -} - -void ust_marker_iter_start(struct ust_marker_iter *iter) -{ - lock_ust_marker(); - ust_marker_get_iter(iter); -} - -/* Called with markers mutex held. */ -void ust_marker_iter_next(struct ust_marker_iter *iter) -{ - iter->ust_marker++; - /* - * iter->ust_marker may be invalid because we blindly incremented it. - * Make sure it is valid by marshalling on the ust_marker, getting the - * ust_marker from following modules if necessary. - */ - ust_marker_get_iter(iter); -} - -void ust_marker_iter_stop(struct ust_marker_iter *iter) -{ - unlock_ust_marker(); -} - -void ust_marker_iter_reset(struct ust_marker_iter *iter) -{ - iter->lib = NULL; - iter->ust_marker = NULL; -} - -void ltt_dump_ust_marker_state(struct ust_trace *trace) -{ - struct ust_marker_entry *entry; - struct ltt_probe_private_data call_data; - struct cds_hlist_head *head; - struct cds_hlist_node *node; - unsigned int i; - - lock_ust_marker(); - call_data.trace = trace; - call_data.serializer = NULL; - - for (i = 0; i < UST_MARKER_TABLE_SIZE; i++) { - head = &ust_marker_table[i]; - cds_hlist_for_each_entry(entry, node, head, hlist) { - __ust_marker(metadata, core_marker_id, - &call_data, - "channel %s name %s event_id %hu " - "int #1u%zu long #1u%zu pointer #1u%zu " - "size_t #1u%zu alignment #1u%u", - entry->channel, - entry->name, - entry->event_id, - sizeof(int), sizeof(long), - sizeof(void *), sizeof(size_t), - ltt_get_alignment()); - if (entry->format) - __ust_marker(metadata, - core_marker_format, - &call_data, - "channel %s name %s format %s", - entry->channel, - entry->name, - entry->format); - } - } - unlock_ust_marker(); -} - -void ust_marker_set_new_ust_marker_cb(void (*cb)(struct ust_marker *)) -{ - new_ust_marker_cb = cb; -} - -static void new_ust_marker(struct ust_marker * const *start, - struct ust_marker * const *end) -{ - if (new_ust_marker_cb) { - struct ust_marker * const *m; - - for (m = start; m < end; m++) { - if (*m) - new_ust_marker_cb(*m); - } - } -} - -int ust_marker_register_lib(struct ust_marker * const *ust_marker_start, - int ust_marker_count) -{ - struct ust_marker_lib *pl, *iter; - - pl = (struct ust_marker_lib *) zmalloc(sizeof(struct ust_marker_lib)); - - pl->ust_marker_start = ust_marker_start; - pl->ust_marker_count = ust_marker_count; - - lock_ust_marker(); - - /* - * We sort the libs by struct lib pointer address. - */ - cds_list_for_each_entry_reverse(iter, &ust_marker_libs, list) { - BUG_ON(iter == pl); /* Should never be in the list twice */ - if (iter < pl) { - /* We belong to the location right after iter. */ - cds_list_add(&pl->list, &iter->list); - goto lib_added; - } - } - /* We should be added at the head of the list */ - cds_list_add(&pl->list, &ust_marker_libs); -lib_added: - unlock_ust_marker(); - - new_ust_marker(ust_marker_start, ust_marker_start + ust_marker_count); - - /* TODO: update just the loaded lib */ - lib_update_ust_marker(); - - DBG("just registered a ust_marker section from %p and having %d ust_marker (minus dummy ust_marker)", ust_marker_start, ust_marker_count); - - return 0; -} - -int ust_marker_unregister_lib(struct ust_marker * const *ust_marker_start) -{ - struct ust_marker_lib *lib; - - lock_ust_marker(); - cds_list_for_each_entry(lib, &ust_marker_libs, list) { - if(lib->ust_marker_start == ust_marker_start) { - struct ust_marker_lib *lib2free = lib; - cds_list_del(&lib->list); - free(lib2free); - break; - } - } - unlock_ust_marker(); - - return 0; -} - -void __attribute__((constructor)) init_ust_marker(void) -{ - if (!initialized) { - init_tracepoint(); - ust_marker_register_lib(__start___ust_marker_ptrs, - __stop___ust_marker_ptrs - - __start___ust_marker_ptrs); - initialized = 1; - } -} - -void __attribute__((destructor)) destroy_ust_marker(void) -{ - ust_marker_unregister_lib(__start___ust_marker_ptrs); -} diff --git a/deprecated/libust/serialize.c b/deprecated/libust/serialize.c deleted file mode 100644 index 81f8e4c..0000000 --- a/deprecated/libust/serialize.c +++ /dev/null @@ -1,850 +0,0 @@ -/* - * LTTng serializing code. - * - * Copyright Mathieu Desnoyers, March 2007. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - * See this discussion about weirdness about passing va_list and then va_list to - * functions. (related to array argument passing). va_list seems to be - * implemented as an array on x86_64, but not on i386... This is why we pass a - * va_list * to ltt_vtrace. - */ - -#define _GNU_SOURCE -#define _LGPL_SOURCE -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include "buffers.h" -#include "tracer.h" -#include "usterr_signal_safe.h" -#include "ust_snprintf.h" - -/* - * Because UST core defines a non-const PAGE_SIZE, define PAGE_SIZE_STATIC here. - * It is just an approximation for the tracer stack. - */ -#define PAGE_SIZE_STATIC 4096 - -enum ltt_type { - LTT_TYPE_SIGNED_INT, - LTT_TYPE_UNSIGNED_INT, - LTT_TYPE_STRING, - LTT_TYPE_NONE, -}; - -/* - * Special stack for the tracer. Keeps serialization offsets for each field. - * Per-thread. Deals with reentrancy from signals by simply ensuring that - * interrupting signals put the stack back to its original position. - */ -#define TRACER_STACK_LEN (PAGE_SIZE_STATIC / sizeof(unsigned long)) -static unsigned long __thread tracer_stack[TRACER_STACK_LEN]; - -static unsigned int __thread tracer_stack_pos; - -#define LTT_ATTRIBUTE_NETWORK_BYTE_ORDER (1<<1) - -/* - * Inspired from vsnprintf - * - * The serialization format string supports the basic printf format strings. - * In addition, it defines new formats that can be used to serialize more - * complex/non portable data structures. - * - * Typical use: - * - * field_name %ctype - * field_name #tracetype %ctype - * field_name #tracetype %ctype1 %ctype2 ... - * - * A conversion is performed between format string types supported by GCC and - * the trace type requested. GCC type is used to perform type checking on format - * strings. Trace type is used to specify the exact binary representation - * in the trace. A mapping is done between one or more GCC types to one trace - * type. Sign extension, if required by the conversion, is performed following - * the trace type. - * - * If a gcc format is not declared with a trace format, the gcc format is - * also used as binary representation in the trace. - * - * Strings are supported with %s. - * A single tracetype (sequence) can take multiple c types as parameter. - * - * c types: - * - * see printf(3). - * - * Note: to write a uint32_t in a trace, the following expression is recommended - * si it can be portable: - * - * ("#4u%lu", (unsigned long)var) - * - * trace types: - * - * Serialization specific formats : - * - * Fixed size integers - * #1u writes uint8_t - * #2u writes uint16_t - * #4u writes uint32_t - * #8u writes uint64_t - * #1d writes int8_t - * #2d writes int16_t - * #4d writes int32_t - * #8d writes int64_t - * i.e.: - * #1u%lu #2u%lu #4d%lu #8d%lu #llu%hu #d%lu - * - * * Attributes: - * - * n: (for network byte order) - * #ntracetype%ctype - * is written in the trace in network byte order. - * - * i.e.: #bn4u%lu, #n%lu, #b%u - * - * TODO (eventually) - * Variable length sequence - * #a #tracetype1 #tracetype2 %array_ptr %elem_size %num_elems - * In the trace: - * #a specifies that this is a sequence - * #tracetype1 is the type of elements in the sequence - * #tracetype2 is the type of the element count - * GCC input: - * array_ptr is a pointer to an array that contains members of size - * elem_size. - * num_elems is the number of elements in the array. - * i.e.: #a #lu #lu %p %lu %u - * - * Callback - * #k callback (taken from the probe data) - * The following % arguments are exepected by the callback - * - * i.e.: #a #lu #lu #k %p - * - * Note: No conversion is done from floats to integers, nor from integers to - * floats between c types and trace types. float conversion from double to float - * or from float to double is also not supported. - * - * REMOVE - * %*b expects sizeof(data), data - * where sizeof(data) is 1, 2, 4 or 8 - * - * Fixed length struct, union or array. - * FIXME: unable to extract those sizes statically. - * %*r expects sizeof(*ptr), ptr - * %*.*r expects sizeof(*ptr), __alignof__(*ptr), ptr - * struct and unions removed. - * Fixed length array: - * [%p]#a[len #tracetype] - * i.e.: [%p]#a[12 #lu] - * - * Variable length sequence - * %*.*:*v expects sizeof(*ptr), __alignof__(*ptr), elem_num, ptr - * where elem_num is the number of elements in the sequence - */ -static inline const char *parse_trace_type(const char *fmt, - char *trace_size, enum ltt_type *trace_type, - unsigned long *attributes) -{ - int qualifier; /* 'h', 'l', or 'L' for integer fields */ - /* 'z' support added 23/7/1999 S.H. */ - /* 'z' changed to 'Z' --davidm 1/25/99 */ - /* 't' added for ptrdiff_t */ - - /* parse attributes. */ -repeat: - switch (*fmt) { - case 'n': - *attributes |= LTT_ATTRIBUTE_NETWORK_BYTE_ORDER; - ++fmt; - goto repeat; - } - - /* get the conversion qualifier */ - qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || - *fmt == 'Z' || *fmt == 'z' || *fmt == 't' || - *fmt == 'S' || *fmt == '1' || *fmt == '2' || - *fmt == '4' || *fmt == 8) { - qualifier = *fmt; - ++fmt; - if (qualifier == 'l' && *fmt == 'l') { - qualifier = 'L'; - ++fmt; - } - } - - switch (*fmt) { - case 'c': - *trace_type = LTT_TYPE_UNSIGNED_INT; - *trace_size = sizeof(unsigned char); - goto parse_end; - case 's': - *trace_type = LTT_TYPE_STRING; - goto parse_end; - case 'p': - *trace_type = LTT_TYPE_UNSIGNED_INT; - *trace_size = sizeof(void *); - goto parse_end; - case 'd': - case 'i': - *trace_type = LTT_TYPE_SIGNED_INT; - break; - case 'o': - case 'u': - case 'x': - case 'X': - *trace_type = LTT_TYPE_UNSIGNED_INT; - break; - default: - if (!*fmt) - --fmt; - goto parse_end; - } - switch (qualifier) { - case 'L': - *trace_size = sizeof(long long); - break; - case 'l': - *trace_size = sizeof(long); - break; - case 'Z': - case 'z': - *trace_size = sizeof(size_t); - break; -//ust// case 't': -//ust// *trace_size = sizeof(ptrdiff_t); -//ust// break; - case 'h': - *trace_size = sizeof(short); - break; - case '1': - *trace_size = sizeof(uint8_t); - break; - case '2': - *trace_size = sizeof(uint16_t); - break; - case '4': - *trace_size = sizeof(uint32_t); - break; - case '8': - *trace_size = sizeof(uint64_t); - break; - default: - *trace_size = sizeof(int); - } - -parse_end: - return fmt; -} - -/* - * Restrictions: - * Field width and precision are *not* supported. - * %n not supported. - */ -static inline -const char *parse_c_type(const char *fmt, char *c_size, enum ltt_type *c_type, - char *outfmt) -{ - int qualifier; /* 'h', 'l', or 'L' for integer fields */ - /* 'z' support added 23/7/1999 S.H. */ - /* 'z' changed to 'Z' --davidm 1/25/99 */ - /* 't' added for ptrdiff_t */ - - /* process flags : ignore standard print formats for now. */ -repeat: - switch (*fmt) { - case '-': - case '+': - case ' ': - case '#': - case '0': - ++fmt; - goto repeat; - } - - /* get the conversion qualifier */ - qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || - *fmt == 'Z' || *fmt == 'z' || *fmt == 't' || - *fmt == 'S') { - qualifier = *fmt; - ++fmt; - if (qualifier == 'l' && *fmt == 'l') { - qualifier = 'L'; - ++fmt; - } - } - - if (outfmt) { - if (qualifier != -1) - *outfmt++ = (char)qualifier; - *outfmt++ = *fmt; - *outfmt = 0; - } - - switch (*fmt) { - case 'c': - *c_type = LTT_TYPE_UNSIGNED_INT; - *c_size = sizeof(unsigned char); - goto parse_end; - case 's': - *c_type = LTT_TYPE_STRING; - goto parse_end; - case 'p': - *c_type = LTT_TYPE_UNSIGNED_INT; - *c_size = sizeof(void *); - goto parse_end; - case 'd': - case 'i': - *c_type = LTT_TYPE_SIGNED_INT; - break; - case 'o': - case 'u': - case 'x': - case 'X': - *c_type = LTT_TYPE_UNSIGNED_INT; - break; - default: - if (!*fmt) - --fmt; - goto parse_end; - } - switch (qualifier) { - case 'L': - *c_size = sizeof(long long); - break; - case 'l': - *c_size = sizeof(long); - break; - case 'Z': - case 'z': - *c_size = sizeof(size_t); - break; -//ust// case 't': -//ust// *c_size = sizeof(ptrdiff_t); -//ust// break; - case 'h': - *c_size = sizeof(short); - break; - default: - *c_size = sizeof(int); - } - -parse_end: - return fmt; -} - -static inline size_t serialize_trace_data(struct ust_buffer *buf, - size_t buf_offset, - char trace_size, enum ltt_type trace_type, - char c_size, enum ltt_type c_type, - unsigned int *stack_pos_ctx, - int *largest_align, - va_list *args) -{ - union { - unsigned long v_ulong; - uint64_t v_uint64; - struct { - const char *s; - size_t len; - } v_string; - } tmp; - - /* - * Be careful about sign extension here. - * Sign extension is done with the destination (trace) type. - */ - switch (trace_type) { - case LTT_TYPE_SIGNED_INT: - switch (c_size) { - case 1: - tmp.v_ulong = (long)(int8_t)va_arg(*args, int); - break; - case 2: - tmp.v_ulong = (long)(int16_t)va_arg(*args, int); - break; - case 4: - tmp.v_ulong = (long)(int32_t)va_arg(*args, int); - break; - case 8: - tmp.v_uint64 = va_arg(*args, int64_t); - break; - default: - BUG(); - } - break; - case LTT_TYPE_UNSIGNED_INT: - switch (c_size) { - case 1: - tmp.v_ulong = (unsigned long)(uint8_t)va_arg(*args, unsigned int); - break; - case 2: - tmp.v_ulong = (unsigned long)(uint16_t)va_arg(*args, unsigned int); - break; - case 4: - tmp.v_ulong = (unsigned long)(uint32_t)va_arg(*args, unsigned int); - break; - case 8: - tmp.v_uint64 = va_arg(*args, uint64_t); - break; - default: - BUG(); - } - break; - case LTT_TYPE_STRING: - tmp.v_string.s = va_arg(*args, const char *); - if ((unsigned long)tmp.v_string.s < PAGE_SIZE) - tmp.v_string.s = ""; - if (!buf) { - /* - * Reserve tracer stack entry. - */ - tracer_stack_pos++; - assert(tracer_stack_pos <= TRACER_STACK_LEN); - cmm_barrier(); - tracer_stack[*stack_pos_ctx] = - strlen(tmp.v_string.s) + 1; - } - tmp.v_string.len = tracer_stack[(*stack_pos_ctx)++]; - if (buf) - ust_buffers_strncpy(buf, buf_offset, tmp.v_string.s, - tmp.v_string.len); - buf_offset += tmp.v_string.len; - goto copydone; - default: - BUG(); - } - - /* - * If trace_size is lower or equal to 4 bytes, there is no sign - * extension to do because we are already encoded in a long. Therefore, - * we can combine signed and unsigned ops. 4 bytes float also works - * with this, because we do a simple copy of 4 bytes into 4 bytes - * without manipulation (and we do not support conversion from integers - * to floats). - * It is also the case if c_size is 8 bytes, which is the largest - * possible integer. - */ - if (ltt_get_alignment()) { - buf_offset += ltt_align(buf_offset, trace_size); - if (largest_align) - *largest_align = max_t(int, *largest_align, trace_size); - } - if (trace_size <= 4 || c_size == 8) { - if (buf) { - switch (trace_size) { - case 1: - if (c_size == 8) - ust_buffers_write(buf, buf_offset, - (uint8_t[]){ (uint8_t)tmp.v_uint64 }, - sizeof(uint8_t)); - else - ust_buffers_write(buf, buf_offset, - (uint8_t[]){ (uint8_t)tmp.v_ulong }, - sizeof(uint8_t)); - break; - case 2: - if (c_size == 8) - ust_buffers_write(buf, buf_offset, - (uint16_t[]){ (uint16_t)tmp.v_uint64 }, - sizeof(uint16_t)); - else - ust_buffers_write(buf, buf_offset, - (uint16_t[]){ (uint16_t)tmp.v_ulong }, - sizeof(uint16_t)); - break; - case 4: - if (c_size == 8) - ust_buffers_write(buf, buf_offset, - (uint32_t[]){ (uint32_t)tmp.v_uint64 }, - sizeof(uint32_t)); - else - ust_buffers_write(buf, buf_offset, - (uint32_t[]){ (uint32_t)tmp.v_ulong }, - sizeof(uint32_t)); - break; - case 8: - /* - * c_size cannot be other than 8 here because - * trace_size > 4. - */ - ust_buffers_write(buf, buf_offset, - (uint64_t[]){ (uint64_t)tmp.v_uint64 }, - sizeof(uint64_t)); - break; - default: - BUG(); - } - } - buf_offset += trace_size; - goto copydone; - } else { - /* - * Perform sign extension. - */ - if (buf) { - switch (trace_type) { - case LTT_TYPE_SIGNED_INT: - ust_buffers_write(buf, buf_offset, - (int64_t[]){ (int64_t)tmp.v_ulong }, - sizeof(int64_t)); - break; - case LTT_TYPE_UNSIGNED_INT: - ust_buffers_write(buf, buf_offset, - (uint64_t[]){ (uint64_t)tmp.v_ulong }, - sizeof(uint64_t)); - break; - default: - BUG(); - } - } - buf_offset += trace_size; - goto copydone; - } - -copydone: - return buf_offset; -} - -notrace size_t ltt_serialize_data(struct ust_buffer *buf, size_t buf_offset, - struct ltt_serialize_closure *closure, - void *serialize_private, - unsigned int stack_pos_ctx, - int *largest_align, - const char *fmt, va_list *args) -{ - char trace_size = 0, c_size = 0; /* - * 0 (unset), 1, 2, 4, 8 bytes. - */ - enum ltt_type trace_type = LTT_TYPE_NONE, c_type = LTT_TYPE_NONE; - unsigned long attributes = 0; - - for (; *fmt ; ++fmt) { - switch (*fmt) { - case '#': - /* tracetypes (#) */ - ++fmt; /* skip first '#' */ - if (*fmt == '#') /* Escaped ## */ - break; - attributes = 0; - fmt = parse_trace_type(fmt, &trace_size, &trace_type, - &attributes); - break; - case '%': - /* c types (%) */ - ++fmt; /* skip first '%' */ - if (*fmt == '%') /* Escaped %% */ - break; - fmt = parse_c_type(fmt, &c_size, &c_type, NULL); - /* - * Output c types if no trace types has been - * specified. - */ - if (!trace_size) - trace_size = c_size; - if (trace_type == LTT_TYPE_NONE) - trace_type = c_type; - if (c_type == LTT_TYPE_STRING) - trace_type = LTT_TYPE_STRING; - /* perform trace write */ - buf_offset = serialize_trace_data(buf, - buf_offset, trace_size, - trace_type, c_size, c_type, - &stack_pos_ctx, - largest_align, - args); - trace_size = 0; - c_size = 0; - trace_type = LTT_TYPE_NONE; - c_size = LTT_TYPE_NONE; - attributes = 0; - break; - /* default is to skip the text, doing nothing */ - } - } - return buf_offset; -} - -/* - * Calculate data size - * Assume that the padding for alignment starts at a sizeof(void *) address. - */ -static notrace size_t ltt_get_data_size(struct ltt_serialize_closure *closure, - void *serialize_private, - unsigned int stack_pos_ctx, int *largest_align, - const char *fmt, va_list *args) -{ - ltt_serialize_cb cb = closure->callbacks[0]; - closure->cb_idx = 0; - return (size_t)cb(NULL, 0, closure, serialize_private, - stack_pos_ctx, largest_align, fmt, args); -} - -static notrace -void ltt_write_event_data(struct ust_buffer *buf, size_t buf_offset, - struct ltt_serialize_closure *closure, - void *serialize_private, - unsigned int stack_pos_ctx, - int largest_align, - const char *fmt, va_list *args) -{ - ltt_serialize_cb cb = closure->callbacks[0]; - closure->cb_idx = 0; - buf_offset += ltt_align(buf_offset, largest_align); - cb(buf, buf_offset, closure, serialize_private, stack_pos_ctx, NULL, - fmt, args); -} - - -notrace void ltt_vtrace(const struct ust_marker *mdata, void *probe_data, - void *call_data, - const char *fmt, va_list *args) -{ - int largest_align, ret; - struct ltt_active_ust_marker *pdata; - uint16_t eID; - size_t data_size, slot_size; - unsigned int chan_index; - struct ust_channel *channel; - struct ust_trace *trace, *dest_trace = NULL; - struct ust_buffer *buf; - u64 tsc; - long buf_offset; - va_list args_copy; - struct ltt_serialize_closure closure; - struct ltt_probe_private_data *private_data = call_data; - void *serialize_private = NULL; - int cpu; - unsigned int rflags; - unsigned int stack_pos_ctx; - - /* - * This test is useful for quickly exiting static tracing when no trace - * is active. We expect to have an active trace when we get here. - */ - if (unlikely(ltt_traces.num_active_traces == 0)) - return; - - rcu_read_lock(); - cpu = ust_get_cpu(); - - /* Force volatile access. */ - CMM_STORE_SHARED(ltt_nesting, CMM_LOAD_SHARED(ltt_nesting) + 1); - stack_pos_ctx = tracer_stack_pos; - cmm_barrier(); - - pdata = (struct ltt_active_ust_marker *)probe_data; - eID = mdata->event_id; - chan_index = mdata->channel_id; - closure.callbacks = pdata->probe->callbacks; - - if (unlikely(private_data)) { - dest_trace = private_data->trace; - if (private_data->serializer) - closure.callbacks = &private_data->serializer; - serialize_private = private_data->serialize_private; - } - - va_copy(args_copy, *args); - /* - * Assumes event payload to start on largest_align alignment. - */ - largest_align = 1; /* must be non-zero for ltt_align */ - data_size = ltt_get_data_size(&closure, serialize_private, - stack_pos_ctx, &largest_align, - fmt, &args_copy); - largest_align = min_t(int, largest_align, sizeof(void *)); - va_end(args_copy); - - /* Iterate on each trace */ - cds_list_for_each_entry_rcu(trace, <t_traces.head, list) { - /* - * Expect the filter to filter out events. If we get here, - * we went through tracepoint activation as a first step. - */ - if (unlikely(dest_trace && trace != dest_trace)) - continue; - if (unlikely(!trace->active)) - continue; - if (unlikely(!ltt_run_filter(trace, eID))) - continue; -#ifdef CONFIG_LTT_DEBUG_EVENT_SIZE - rflags = LTT_RFLAG_ID_SIZE; -#else - if (unlikely(eID >= LTT_FREE_EVENTS)) - rflags = LTT_RFLAG_ID; - else - rflags = 0; -#endif - /* - * Skip channels added after trace creation. - */ - if (unlikely(chan_index >= trace->nr_channels)) - continue; - channel = &trace->channels[chan_index]; - if (!channel->active) - continue; - - /* - * If a new cpu was plugged since the trace was started, we did - * not add it to the trace, and therefore we write the event to - * cpu 0. - */ - if (cpu >= channel->n_cpus) { - cpu = 0; - } - - /* reserve space : header and data */ - ret = ltt_reserve_slot(channel, trace, data_size, largest_align, - cpu, &buf, &slot_size, &buf_offset, - &tsc, &rflags); - if (unlikely(ret < 0)) - continue; /* buffer full */ - - va_copy(args_copy, *args); - /* FIXME : could probably encapsulate transport better. */ - buf = channel->buf[cpu]; - /* Out-of-order write : header and data */ - buf_offset = ltt_write_event_header(channel, buf, buf_offset, - eID, data_size, tsc, rflags); - ltt_write_event_data(buf, buf_offset, &closure, - serialize_private, - stack_pos_ctx, largest_align, - fmt, &args_copy); - va_end(args_copy); - /* Out-of-order commit */ - ltt_commit_slot(channel, buf, buf_offset, data_size, slot_size); - DBG("just commited event (%s/%s) at offset %ld and size %zd", mdata->channel, mdata->name, buf_offset, slot_size); - } - - cmm_barrier(); - tracer_stack_pos = stack_pos_ctx; - CMM_STORE_SHARED(ltt_nesting, CMM_LOAD_SHARED(ltt_nesting) - 1); - - rcu_read_unlock(); -} - -notrace void ltt_trace(const struct ust_marker *mdata, void *probe_data, - void *call_data, - const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - ltt_vtrace(mdata, probe_data, call_data, fmt, &args); - va_end(args); -} - -static notrace void skip_space(const char **ps) -{ - while(**ps == ' ') - (*ps)++; -} - -static notrace void copy_token(char **out, const char **in) -{ - while (**in != ' ' && **in != '\0') { - **out = **in; - (*out)++; - (*in)++; - } -} - -/* serialize_to_text - * - * Given a format string and a va_list of arguments, convert them to a - * human-readable string. - * - * @outbuf: the buffer to output the string to - * @bufsize: the max size that can be used in outbuf - * @fmt: the marker format string - * @ap: a va_list that contains the arguments corresponding to fmt - * - * Return value: the number of chars that have been put in outbuf, excluding - * the final \0, or, if the buffer was too small, the number of chars that - * would have been written in outbuf if it had been large enough. - * - * outbuf may be NULL. The return value may then be used be allocate an - * appropriate outbuf. - * - */ - -notrace -int serialize_to_text(char *outbuf, int bufsize, const char *fmt, va_list ap) -{ - int fmt_len = strlen(fmt); - char *new_fmt = alloca(fmt_len + 1); - const char *orig_fmt_p = fmt; - char *new_fmt_p = new_fmt; - char false_buf; - int result; - enum { none, cfmt, tracefmt, argname } prev_token = none; - - while (*orig_fmt_p != '\0') { - if (*orig_fmt_p == '%') { - prev_token = cfmt; - copy_token(&new_fmt_p, &orig_fmt_p); - } - else if (*orig_fmt_p == '#') { - prev_token = tracefmt; - do { - orig_fmt_p++; - } while (*orig_fmt_p != ' ' && *orig_fmt_p != '\0'); - } - else if (*orig_fmt_p == ' ') { - if (prev_token == argname) { - *new_fmt_p = '='; - new_fmt_p++; - } - else if (prev_token == cfmt) { - *new_fmt_p = ' '; - new_fmt_p++; - } - - skip_space(&orig_fmt_p); - } - else { - prev_token = argname; - copy_token(&new_fmt_p, &orig_fmt_p); - } - } - - *new_fmt_p = '\0'; - - if (outbuf == NULL) { - /* use this false_buffer for compatibility with pre-C99 */ - outbuf = &false_buf; - bufsize = 1; - } - result = ust_safe_vsnprintf(outbuf, bufsize, new_fmt, ap); - - return result; -} diff --git a/deprecated/libust/tracectl.c b/deprecated/libust/tracectl.c deleted file mode 100644 index 410b1c7..0000000 --- a/deprecated/libust/tracectl.c +++ /dev/null @@ -1,1738 +0,0 @@ -/* Copyright (C) 2009 Pierre-Marc Fournier - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* This file contains the implementation of the UST listener thread, which - * receives trace control commands. It also coordinates the initialization of - * libust. - */ - -#define _GNU_SOURCE -#define _LGPL_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include "tracer.h" -#include "usterr_signal_safe.h" -#include "ustcomm.h" -#include "buffers.h" -#include "marker-control.h" - -/* 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 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; - retval <<= 32; - retval |= tv.tv_usec; - - return retval; -} - -static void print_ust_marker(FILE *fp) -{ - 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; - - trace_event_iter_reset(&iter); - trace_event_iter_start(&iter); - - while (iter.trace_event) { - fprintf(fp, "trace_event: %s\n", (*iter.trace_event)->name); - trace_event_iter_next(&iter); - } - 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 - * produced by this pid. - * - * The trace must be at least allocated. (It can also be started.) - * This is because _ltt_trace_find is used. - */ - -static void inform_consumer_daemon(const char *trace_name) -{ - int sock, i,j; - struct ust_trace *trace; - 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 unlock_traces; - } - - for (i=0; i < trace->nr_channels; i++) { - if (trace->channels[i].request_collection) { - /* iterate on all cpus */ - for (j=0; jchannels[i].n_cpus; j++) { - 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); - } - } - } - -unlock_traces: - ltt_unlock_traces(); - - close(sock); -} - -static struct ust_channel *find_channel(const char *ch_name, - struct ust_trace *trace) -{ - int i; - - for (i=0; inr_channels; i++) { - if (!strcmp(trace->channels[i].channel_name, ch_name)) { - return &trace->channels[i]; - } - } - - return NULL; -} - -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) -{ - struct ust_trace *trace; - struct ust_channel *channel; - struct ust_buffer *buf; - - DBG("get_buffer_shmid_pipe_fd"); - - ltt_lock_traces(); - trace = _ltt_trace_find(trace_name); - ltt_unlock_traces(); - - if (trace == NULL) { - ERR("cannot find trace!"); - return -ENODATA; - } - - channel = find_channel(ch_name, trace); - if (!channel) { - ERR("cannot find channel %s!", ch_name); - return -ENODATA; - } - - buf = channel->buf[ch_cpu]; - - *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 get_subbuf_num_size(const char *trace_name, const char *ch_name, - int *num, int *size) -{ - struct ust_trace *trace; - struct ust_channel *channel; - - DBG("get_subbuf_size"); - - ltt_lock_traces(); - trace = _ltt_trace_find(trace_name); - ltt_unlock_traces(); - - if (!trace) { - ERR("cannot find trace!"); - return -ENODATA; - } - - channel = find_channel(ch_name, trace); - if (!channel) { - ERR("unable to find channel"); - return -ENODATA; - } - - *num = channel->subbuf_cnt; - *size = channel->subbuf_size; - - return 0; -} - -/* Return the power of two which is equal or higher to v */ - -static unsigned int pow2_higher_or_eq(unsigned int v) -{ - int hb = fls(v); - int retval = 1<<(hb-1); - - if (v-retval == 0) - return retval; - else - return retval<<1; -} - -static int set_subbuf_size(const char *trace_name, const char *ch_name, - unsigned int size) -{ - unsigned int power; - int retval = 0; - struct ust_trace *trace; - struct ust_channel *channel; - - DBG("set_subbuf_size"); - - power = pow2_higher_or_eq(size); - power = max_t(unsigned int, 2u, power); - 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 = -ENODATA; - goto unlock_traces; - } - - channel = find_channel(ch_name, trace); - if (!channel) { - ERR("unable to find channel"); - retval = -ENODATA; - goto unlock_traces; - } - - channel->subbuf_size = power; - DBG("the set_subbuf_size for the requested channel is %zu", channel->subbuf_size); - -unlock_traces: - ltt_unlock_traces(); - - return retval; -} - -static int set_subbuf_num(const char *trace_name, const char *ch_name, - unsigned int num) -{ - struct ust_trace *trace; - struct ust_channel *channel; - int retval = 0; - - DBG("set_subbuf_num"); - - if (num < 2) { - ERR("subbuffer count should be greater than 2"); - return -EINVAL; - } - - ltt_lock_traces(); - trace = _ltt_trace_find_setup(trace_name); - if (trace == NULL) { - ERR("cannot find trace!"); - retval = -ENODATA; - goto unlock_traces; - } - - channel = find_channel(ch_name, trace); - if (!channel) { - ERR("unable to find channel"); - retval = -ENODATA; - goto unlock_traces; - } - - channel->subbuf_cnt = num; - DBG("the set_subbuf_cnt for the requested channel is %u", channel->subbuf_cnt); - -unlock_traces: - ltt_unlock_traces(); - return retval; -} - -static int get_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("get_subbuf"); - - *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); - } - } - -unlock_traces: - ltt_unlock_traces(); - - return retval; -} - -static int process_trace_cmd(int command, char *trace_name) -{ - int result; - char trace_type[] = "ustrelay"; - - 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 result; - } - - result = ltt_trace_set_type(trace_name, trace_type); - if (result < 0) { - ERR("ltt_trace_set_type failed"); - return result; - } - - result = ltt_trace_alloc(trace_name); - if (result < 0) { - ERR("ltt_trace_alloc failed"); - return result; - } - - inform_consumer_daemon(trace_name); - - result = ltt_trace_start(trace_name); - if (result < 0) { - ERR("ltt_trace_start failed"); - return result; - } - - return 0; - case SETUP_TRACE: - DBG("trace setup"); - - result = ltt_trace_setup(trace_name); - if (result < 0) { - ERR("ltt_trace_setup failed"); - return result; - } - - result = ltt_trace_set_type(trace_name, trace_type); - if (result < 0) { - ERR("ltt_trace_set_type failed"); - return result; - } - - return 0; - case ALLOC_TRACE: - DBG("trace alloc"); - - result = ltt_trace_alloc(trace_name); - if (result < 0) { - ERR("ltt_trace_alloc failed"); - return result; - } - inform_consumer_daemon(trace_name); - - return 0; - - case CREATE_TRACE: - DBG("trace create"); - - result = ltt_trace_setup(trace_name); - if (result < 0) { - ERR("ltt_trace_setup failed"); - return result; - } - - result = ltt_trace_set_type(trace_name, trace_type); - if (result < 0) { - ERR("ltt_trace_set_type failed"); - return result; - } - - return 0; - case START_TRACE: - DBG("trace start"); - - result = ltt_trace_alloc(trace_name); - if (result < 0) { - ERR("ltt_trace_alloc failed"); - return result; - } - if (!result) { - inform_consumer_daemon(trace_name); - } - - result = ltt_trace_start(trace_name); - if (result < 0) { - ERR("ltt_trace_start failed"); - return result; - } - - return 0; - case STOP_TRACE: - DBG("trace stop"); - - result = ltt_trace_stop(trace_name); - if (result < 0) { - ERR("ltt_trace_stop failed"); - return result; - } - - return 0; - case DESTROY_TRACE: - DBG("trace destroy"); - - result = ltt_trace_destroy(trace_name, 0); - if (result < 0) { - ERR("ltt_trace_destroy failed"); - 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; -} - - -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; - } - - 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 disable ust_marker; channel=%s," - " name=%s", - ust_marker_inf->channel, - ust_marker_inf->ust_marker); - } - break; - } - - reply_header->result = result; - - if (ustcomm_send(sock, reply_header, NULL) < 0) { - ERR("ustcomm_send failed"); - } - -} -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); - - if (result < 0) { - PERROR("failed to send ust_marker list"); - } - - break; - } - case LIST_TRACE_EVENTS: - { - char *ptr; - size_t size; - FILE *fp; - - fp = open_memstream(&ptr, &size); - if (fp == NULL) { - ERR("opening memstream failed"); - return; - } - print_trace_events(fp); - fclose(fp); - - 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; - } - - 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_pack_single_field(reply_header, - sock_msg, - sock_path_env); - } - 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; - } - - reply_header->result = setenv("UST_DAEMON_SOCKET", - sock_msg->field, 1); - - 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 - -void *listener_main(void *p) -{ - struct ustcomm_sock *epoll_sock; - struct epoll_event events[MAX_EVENTS]; - struct sockaddr addr; - int accept_fd, nfds, result, i, addr_size; - - DBG("LISTENER"); - - pthread_cleanup_push(listener_cleanup, NULL); - - for(;;) { - nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); - if (nfds == -1) { - PERROR("listener_main: epoll_wait failed"); - continue; - } - - 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); - accept_fd = accept(epoll_sock->fd, - &addr, - (socklen_t *)&addr_size); - if (accept_fd == -1) { - PERROR("listener_main: accept failed"); - continue; - } - ustcomm_init_sock(accept_fd, epoll_fd, - &ust_socks); - } else { - 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 { - process_client_cmd(receive_header, - receive_buffer, - epoll_sock->fd); - } - } - pthread_cleanup_pop(1); /* release listener mutex */ - } - } - - pthread_cleanup_pop(1); -} - -/* These should only be accessed in the parent thread, - * not the listener. - */ -static volatile sig_atomic_t have_listener = 0; -static pthread_t listener_thread; - -void create_listener(void) -{ - int result; - sigset_t sig_all_blocked; - sigset_t orig_parent_mask; - - if (have_listener) { - WARN("not creating listener because we already had one"); - return; - } - - /* A new thread created by pthread_create inherits the signal mask - * from the parent. To avoid any signal being received by the - * listener thread, we block all signals temporarily in the parent, - * while we create the listener thread. - */ - - sigfillset(&sig_all_blocked); - - result = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_parent_mask); - if (result) { - PERROR("pthread_sigmask: %s", strerror(result)); - } - - result = pthread_create(&listener_thread, NULL, listener_main, NULL); - if (result == -1) { - PERROR("pthread_create"); - } - - /* Restore original signal mask in parent */ - result = pthread_sigmask(SIG_SETMASK, &orig_parent_mask, NULL); - if (result) { - PERROR("pthread_sigmask: %s", strerror(result)); - } else { - have_listener = 1; - } -} - -#define AUTOPROBE_DISABLED 0 -#define AUTOPROBE_ENABLE_ALL 1 -#define AUTOPROBE_ENABLE_REGEX 2 -static int autoprobe_method = AUTOPROBE_DISABLED; -static regex_t autoprobe_regex; - -static void auto_probe_connect(struct ust_marker *m) -{ - int result; - - char* concat_name = NULL; - const char *probe_name = "default"; - - if (autoprobe_method == AUTOPROBE_DISABLED) { - return; - } 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 (ust_marker %s/%s)", - m->channel, m->name); - return; - } - if (regexec(&autoprobe_regex, concat_name, 0, NULL, 0)) { - free(concat_name); - return; - } - free(concat_name); - } - - result = ltt_ust_marker_connect(m->channel, m->name, probe_name); - if (result && result != -EEXIST) - ERR("ltt_ust_marker_connect (ust_marker = %s/%s, errno = %d)", m->channel, m->name, -result); - - 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 *dir_name, *sock_name; - int result; - struct ustcomm_sock *sock = NULL; - time_t mtime; - - dir_name = ustcomm_user_sock_dir(); - if (!dir_name) - return NULL; - - 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"); - goto free_dir_name; - } - - result = ensure_dir_exists(dir_name, S_IRWXU); - if (result == -1) { - ERR("Unable to create socket directory %s, UST thread bailing", - dir_name); - goto free_sock_name; - } - - 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", sock_name); - goto free_sock_name; - } - -free_sock_name: - free(sock_name); -free_dir_name: - free(dir_name); - - return sock; -} - -static void __attribute__((constructor)) init() -{ - struct timespec ts; - int result; - char* autoprobe_val = NULL; - char* subbuffer_size_val = NULL; - char* subbuffer_count_val = NULL; - unsigned int subbuffer_size; - unsigned int subbuffer_count; - unsigned int power; - - /* Assign the pidunique, to be able to differentiate the processes with same - * pid, (before and after an exec). - */ - pidunique = make_pidunique(); - processpid = getpid(); - - DBG("Tracectl constructor"); - - /* Set up epoll */ - epoll_fd = epoll_create(MAX_EVENTS); - if (epoll_fd == -1) { - ERR("epoll_create failed, tracing shutting down"); - return; - } - - /* Create the socket */ - listen_sock = init_app_socket(epoll_fd); - if (!listen_sock) { - ERR("failed to create application socket," - " tracing shutting down"); - return; - } - - 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 ust_marker_iter iter; - - DBG("Autoprobe enabled."); - - /* first, set the callback that will connect the - * probe on new ust_marker - */ - if (autoprobe_val[0] == '/') { - result = regcomp(&autoprobe_regex, autoprobe_val+1, 0); - if (result) { - char regexerr[150]; - - regerror(result, &autoprobe_regex, regexerr, sizeof(regexerr)); - ERR("cannot parse regex %s (%s), will ignore UST_AUTOPROBE", autoprobe_val, regexerr); - /* don't crash the application just for this */ - } else { - autoprobe_method = AUTOPROBE_ENABLE_REGEX; - } - } else { - /* just enable all instrumentation */ - autoprobe_method = AUTOPROBE_ENABLE_ALL; - } - - ust_marker_set_new_ust_marker_cb(auto_probe_connect); - - /* Now, connect the probes that were already registered. */ - 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) { - CMM_STORE_SHARED(ust_channels_overwrite_by_default, val); - } else { - WARN("invalid value for UST_OVERWRITE"); - } - } - - if (getenv("UST_AUTOCOLLECT")) { - int val = atoi(getenv("UST_AUTOCOLLECT")); - if (val == 0 || val == 1) { - CMM_STORE_SHARED(ust_channels_request_collection_by_default, val); - } else { - WARN("invalid value for UST_AUTOCOLLECT"); - } - } - - subbuffer_size_val = getenv("UST_SUBBUF_SIZE"); - if (subbuffer_size_val) { - sscanf(subbuffer_size_val, "%u", &subbuffer_size); - power = pow2_higher_or_eq(subbuffer_size); - if (power != subbuffer_size) - WARN("using the next power of two for buffer size = %u\n", power); - chan_infos[LTT_CHANNEL_UST].def_subbufsize = power; - } - - subbuffer_count_val = getenv("UST_SUBBUF_NUM"); - if (subbuffer_count_val) { - sscanf(subbuffer_count_val, "%u", &subbuffer_count); - if (subbuffer_count < 2) - subbuffer_count = 2; - chan_infos[LTT_CHANNEL_UST].def_subbufcount = subbuffer_count; - } - - if (getenv("UST_TRACE")) { - char trace_name[] = "auto"; - char trace_type[] = "ustrelay"; - - DBG("starting early tracing"); - - /* 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 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 - * registered will not be collected. - * - * Currently, in LTTng, there is no way to add a channel after - * trace start. The reason for this is that it induces complex - * concurrency issues on the trace structures, which can only - * be resolved using RCU. This has not been done yet. As a - * workaround, we are forcing the registration of the "ust" - * channel here. This is the only channel (apart from metadata) - * that can be reliably used in early tracing. - * - * Non-early tracing does not have this problem and can use - * arbitrary channel names. - */ - ltt_channels_register("ust"); - - result = ltt_trace_setup(trace_name); - if (result < 0) { - ERR("ltt_trace_setup failed"); - return; - } - - result = ltt_trace_set_type(trace_name, trace_type); - if (result < 0) { - ERR("ltt_trace_set_type failed"); - return; - } - - result = ltt_trace_alloc(trace_name); - if (result < 0) { - ERR("ltt_trace_alloc failed"); - return; - } - - result = ltt_trace_start(trace_name); - if (result < 0) { - ERR("ltt_trace_start failed"); - return; - } - - /* Do this after the trace is started in order to avoid creating confusion - * if the trace fails to start. */ - inform_consumer_daemon(trace_name); - } - - return; - - /* should decrementally destroy stuff if error */ - -} - -/* This is only called if we terminate normally, not with an unhandled signal, - * so we cannot rely on it. However, for now, LTTV requires that the header of - * the last sub-buffer contain a valid end time for the trace. This is done - * automatically only when the trace is properly stopped. - * - * If the traced program crashed, it is always possible to manually add the - * right value in the header, or to open the trace in text mode. - * - * FIXME: Fix LTTV so it doesn't need this. - */ - -static void destroy_traces(void) -{ - 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", 0); - if (result == -1) { - ERR("ltt_trace_destroy error"); - } -} - -static int trace_recording(void) -{ - int retval = 0; - struct ust_trace *trace; - - ltt_lock_traces(); - - cds_list_for_each_entry(trace, <t_traces.head, list) { - if (trace->active) { - retval = 1; - break; - } - } - - ltt_unlock_traces(); - - return retval; -} - -int restarting_usleep(useconds_t usecs) -{ - struct timespec tv; - int result; - - tv.tv_sec = 0; - tv.tv_nsec = usecs * 1000; - - do { - result = nanosleep(&tv, &tv); - } while (result == -1 && errno == EINTR); - - return result; -} - -static void stop_listener(void) -{ - int result; - - if (!have_listener) - return; - - result = pthread_cancel(listener_thread); - if (result != 0) { - ERR("pthread_cancel: %s", strerror(result)); - } - result = pthread_join(listener_thread, NULL); - if (result != 0) { - ERR("pthread_join: %s", strerror(result)); - } -} - -/* This destructor keeps the process alive for a few seconds in order - * 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. - * - * FIXME: For now, this only works for the first trace created in a - * process. - */ - -static void __attribute__((destructor)) keepalive() -{ - if (processpid != getpid()) { - return; - } - - if (trace_recording() && CMM_LOAD_SHARED(buffers_to_export)) { - int total = 0; - DBG("Keeping process alive for consumer daemon..."); - while (CMM_LOAD_SHARED(buffers_to_export)) { - const int interv = 200000; - restarting_usleep(interv); - total += interv; - - if (total >= 3000000) { - WARN("non-consumed buffers remaining after wait limit; not waiting anymore"); - break; - } - } - DBG("Finally dying..."); - } - - destroy_traces(); - - /* Ask the listener to stop and clean up. */ - stop_listener(); -} - -void ust_potential_exec(void) -{ - ust_marker(potential_exec, UST_MARKER_NOARGS); - - DBG("test"); - - keepalive(); -} - -/* Notify ust that there was a fork. This needs to be called inside - * the new process, anytime a process whose memory is not shared with - * the parent is created. If this function is not called, the events - * of the new process will not be collected. - * - * Signals should be disabled before the fork and reenabled only after - * this call in order to guarantee tracing is not started before ust_fork() - * sanitizes the new process. - */ - -static void ust_fork(void) -{ - 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"); - - /* 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, <t_traces.head, list) { - ltt_trace_stop(trace->trace_name); - } - - /* Delete all active connections, but leave them in the epoll set */ - cds_list_for_each_entry_safe(sock, sock_tmp, &ust_socks, list) { - ustcomm_del_sock(sock, 1); - } - - /* - * 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, <t_traces.head, list) { - ltt_trace_destroy(trace->trace_name, 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 */ - CMM_STORE_SHARED(buffers_to_export, 0); - have_listener = 0; - - /* Set up epoll */ - epoll_fd = epoll_create(MAX_EVENTS); - if (epoll_fd == -1) { - ERR("epoll_create failed, tracing shutting down"); - return; - } - - /* Create the socket */ - listen_sock = init_app_socket(epoll_fd); - if (!listen_sock) { - ERR("failed to create application socket," - " tracing shutting down"); - return; - } - create_listener(); - ltt_trace_setup("auto"); - result = ltt_trace_set_type("auto", "ustrelay"); - if (result < 0) { - ERR("ltt_trace_set_type failed"); - return; - } - - ltt_trace_alloc("auto"); - ltt_trace_start("auto"); - inform_consumer_daemon("auto"); -} - -void ust_before_fork(ust_fork_info_t *fork_info) -{ - /* Disable signals. This is to avoid that the child - * intervenes before it is properly setup for tracing. It is - * safer to disable all signals, because then we know we are not - * breaking anything by restoring the original mask. - */ - sigset_t all_sigs; - int result; - - /* FIXME: - - only do this if tracing is active - */ - - /* Disable signals */ - sigfillset(&all_sigs); - result = sigprocmask(SIG_BLOCK, &all_sigs, &fork_info->orig_sigs); - if (result == -1) { - 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 */ -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) { - PERROR("sigprocmask"); - return; - } -} - -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) -{ - /* Release urcu mutexes */ - rcu_bp_after_fork_child(); - - /* Sanitize the child */ - ust_fork(); - - /* Release mutexes and reenable signals */ - ust_after_fork_common(fork_info); -} - diff --git a/deprecated/libust/tracer.c b/deprecated/libust/tracer.c deleted file mode 100644 index 347ca48..0000000 --- a/deprecated/libust/tracer.c +++ /dev/null @@ -1,723 +0,0 @@ -/* - * tracer.c - * - * (C) Copyright 2005-2008 - - * Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Inspired from LTT : - * Karim Yaghmour (karim@opersys.com) - * Tom Zanussi (zanussi@us.ibm.com) - * Bob Wisniewski (bob@watson.ibm.com) - * And from K42 : - * Bob Wisniewski (bob@watson.ibm.com) - * - * Changelog: - * 22/09/06, Move to the marker/probes mechanism. - * 19/10/05, Complete lockless mechanism. - * 27/05/05, Modular redesign and rewrite. - */ - -#include -#include - -#include - -#include "tracercore.h" -#include "tracer.h" -#include "usterr_signal_safe.h" - -struct chan_info_struct chan_infos[] = { - [LTT_CHANNEL_METADATA] = { - LTT_METADATA_CHANNEL, - LTT_DEFAULT_SUBBUF_SIZE_LOW, - LTT_DEFAULT_N_SUBBUFS_LOW, - }, - [LTT_CHANNEL_UST] = { - LTT_UST_CHANNEL, - LTT_DEFAULT_SUBBUF_SIZE_HIGH, - LTT_DEFAULT_N_SUBBUFS_HIGH, - }, -}; - -static enum ltt_channels get_channel_type_from_name(const char *name) -{ - int i; - - if (!name) - return LTT_CHANNEL_UST; - - for (i = 0; i < ARRAY_SIZE(chan_infos); i++) - if (chan_infos[i].name && !strcmp(name, chan_infos[i].name)) - return (enum ltt_channels)i; - - return LTT_CHANNEL_UST; -} - -static CDS_LIST_HEAD(ltt_transport_list); -/* transport mutex, nests inside traces mutex (ltt_lock_traces) */ -static DEFINE_MUTEX(ltt_transport_mutex); -/** - * ltt_transport_register - LTT transport registration - * @transport: transport structure - * - * Registers a transport which can be used as output to extract the data out of - * LTTng. The module calling this registration function must ensure that no - * trap-inducing code will be executed by the transport functions. E.g. - * vmalloc_sync_all() must be called between a vmalloc and the moment the memory - * is made visible to the transport function. This registration acts as a - * vmalloc_sync_all. Therefore, only if the module allocates virtual memory - * after its registration must it synchronize the TLBs. - */ -void ltt_transport_register(struct ltt_transport *transport) -{ - pthread_mutex_lock(<t_transport_mutex); - cds_list_add_tail(&transport->node, <t_transport_list); - pthread_mutex_unlock(<t_transport_mutex); -} - -/** - * ltt_transport_unregister - LTT transport unregistration - * @transport: transport structure - */ -void ltt_transport_unregister(struct ltt_transport *transport) -{ - pthread_mutex_lock(<t_transport_mutex); - cds_list_del(&transport->node); - pthread_mutex_unlock(<t_transport_mutex); -} - -static inline int is_channel_overwrite(enum ltt_channels chan, - enum trace_mode mode) -{ - switch (mode) { - case LTT_TRACE_NORMAL: - return 0; - case LTT_TRACE_FLIGHT: - switch (chan) { - case LTT_CHANNEL_METADATA: - return 0; - default: - return 1; - } - case LTT_TRACE_HYBRID: - switch (chan) { - case LTT_CHANNEL_METADATA: - return 0; - default: - return 1; - } - default: - return 0; - } -} - -static void trace_async_wakeup(struct ust_trace *trace) -{ - int i; - struct ust_channel *chan; - - /* Must check each channel for pending read wakeup */ - for (i = 0; i < trace->nr_channels; i++) { - chan = &trace->channels[i]; - if (chan->active) - trace->ops->wakeup_channel(chan); - } -} - -/** - * _ltt_trace_find - find a trace by given name. - * trace_name: trace name - * - * Returns a pointer to the trace structure, NULL if not found. - */ -struct ust_trace *_ltt_trace_find(const char *trace_name) -{ - struct ust_trace *trace; - - cds_list_for_each_entry(trace, <t_traces.head, list) - if (!strncmp(trace->trace_name, trace_name, NAME_MAX)) - return trace; - - return NULL; -} - -/* _ltt_trace_find_setup : - * find a trace in setup list by given name. - * - * Returns a pointer to the trace structure, NULL if not found. - */ -struct ust_trace *_ltt_trace_find_setup(const char *trace_name) -{ - struct ust_trace *trace; - - cds_list_for_each_entry(trace, <t_traces.setup_head, list) - if (!strncmp(trace->trace_name, trace_name, NAME_MAX)) - return trace; - - return NULL; -} - -/** - * ltt_release_transport - Release an LTT transport - * @kref : reference count on the transport - */ -void ltt_release_transport(struct urcu_ref *urcu_ref) -{ - return; -} - -/** - * ltt_release_trace - Release a LTT trace - * @kref : reference count on the trace - */ -void ltt_release_trace(struct urcu_ref *urcu_ref) -{ - struct ust_trace *trace = _ust_container_of(urcu_ref, - struct ust_trace, urcu_ref); - ltt_channels_trace_free(trace->channels); - free(trace); -} - -static inline void prepare_chan_size_num(unsigned int *subbuf_size, - unsigned int *n_subbufs) -{ - /* Make sure the subbuffer size is larger than a page */ - *subbuf_size = max_t(unsigned int, *subbuf_size, PAGE_SIZE); - - /* round to next power of 2 */ - *subbuf_size = 1 << get_count_order(*subbuf_size); - *n_subbufs = 1 << get_count_order(*n_subbufs); - - /* Subbuf size and number must both be power of two */ - WARN_ON(hweight32(*subbuf_size) != 1); - WARN_ON(hweight32(*n_subbufs) != 1); -} - -int _ltt_trace_setup(const char *trace_name) -{ - int err = 0; - struct ust_trace *new_trace = NULL; - int metadata_index; - unsigned int chan; - enum ltt_channels chantype; - - if (_ltt_trace_find_setup(trace_name)) { - ERR("Trace name %s already used", trace_name); - err = -EEXIST; - goto traces_error; - } - - if (_ltt_trace_find(trace_name)) { - ERR("Trace name %s already used", trace_name); - err = -EEXIST; - goto traces_error; - } - - new_trace = zmalloc(sizeof(struct ust_trace)); - if (!new_trace) { - ERR("Unable to allocate memory for trace %s", trace_name); - err = -ENOMEM; - goto traces_error; - } - strncpy(new_trace->trace_name, trace_name, NAME_MAX); - new_trace->channels = ltt_channels_trace_alloc(&new_trace->nr_channels, - ust_channels_overwrite_by_default, - ust_channels_request_collection_by_default, 1); - if (!new_trace->channels) { - ERR("Unable to allocate memory for chaninfo %s\n", trace_name); - err = -ENOMEM; - goto trace_free; - } - - /* - * Force metadata channel to active, no overwrite. - */ - metadata_index = ltt_channels_get_index_from_name("metadata"); - WARN_ON(metadata_index < 0); - new_trace->channels[metadata_index].overwrite = 0; - new_trace->channels[metadata_index].active = 1; - - /* - * Set hardcoded tracer defaults for some channels - */ - for (chan = 0; chan < new_trace->nr_channels; chan++) { - if (!(new_trace->channels[chan].active)) - continue; - - chantype = get_channel_type_from_name( - ltt_channels_get_name_from_index(chan)); - new_trace->channels[chan].subbuf_size = - chan_infos[chantype].def_subbufsize; - new_trace->channels[chan].subbuf_cnt = - chan_infos[chantype].def_subbufcount; - } - - cds_list_add(&new_trace->list, <t_traces.setup_head); - return 0; - -trace_free: - free(new_trace); -traces_error: - return err; -} - - -int ltt_trace_setup(const char *trace_name) -{ - int ret; - ltt_lock_traces(); - ret = _ltt_trace_setup(trace_name); - ltt_unlock_traces(); - return ret; -} - -/* must be called from within a traces lock. */ -static void _ltt_trace_free(struct ust_trace *trace) -{ - cds_list_del(&trace->list); - free(trace); -} - -int ltt_trace_set_type(const char *trace_name, const char *trace_type) -{ - int err = 0; - struct ust_trace *trace; - struct ltt_transport *tran_iter, *transport = NULL; - - ltt_lock_traces(); - - trace = _ltt_trace_find_setup(trace_name); - if (!trace) { - ERR("Trace not found %s", trace_name); - err = -ENOENT; - goto traces_error; - } - - pthread_mutex_lock(<t_transport_mutex); - cds_list_for_each_entry(tran_iter, <t_transport_list, node) { - if (!strcmp(tran_iter->name, trace_type)) { - transport = tran_iter; - break; - } - } - pthread_mutex_unlock(<t_transport_mutex); - - if (!transport) { - ERR("Transport %s is not present", trace_type); - err = -EINVAL; - goto traces_error; - } - - trace->transport = transport; - -traces_error: - ltt_unlock_traces(); - return err; -} - -int ltt_trace_set_channel_subbufsize(const char *trace_name, - const char *channel_name, unsigned int size) -{ - int err = 0; - struct ust_trace *trace; - int index; - - ltt_lock_traces(); - - trace = _ltt_trace_find_setup(trace_name); - if (!trace) { - ERR("Trace not found %s", trace_name); - err = -ENOENT; - goto traces_error; - } - - index = ltt_channels_get_index_from_name(channel_name); - if (index < 0) { - ERR("Channel %s not found", channel_name); - err = -ENOENT; - goto traces_error; - } - trace->channels[index].subbuf_size = size; - -traces_error: - ltt_unlock_traces(); - return err; -} - -int ltt_trace_set_channel_subbufcount(const char *trace_name, - const char *channel_name, unsigned int cnt) -{ - int err = 0; - struct ust_trace *trace; - int index; - - ltt_lock_traces(); - - trace = _ltt_trace_find_setup(trace_name); - if (!trace) { - ERR("Trace not found %s", trace_name); - err = -ENOENT; - goto traces_error; - } - - index = ltt_channels_get_index_from_name(channel_name); - if (index < 0) { - ERR("Channel %s not found", channel_name); - err = -ENOENT; - goto traces_error; - } - trace->channels[index].subbuf_cnt = cnt; - -traces_error: - ltt_unlock_traces(); - return err; -} - -int ltt_trace_set_channel_enable(const char *trace_name, - const char *channel_name, unsigned int enable) -{ - int err = 0; - struct ust_trace *trace; - int index; - - ltt_lock_traces(); - - trace = _ltt_trace_find_setup(trace_name); - if (!trace) { - ERR("Trace not found %s", trace_name); - err = -ENOENT; - goto traces_error; - } - - /* - * Datas in metadata channel(marker info) is necessary to be able to - * read the trace, we always enable this channel. - */ - if (!enable && !strcmp(channel_name, "metadata")) { - ERR("Trying to disable metadata channel"); - err = -EINVAL; - goto traces_error; - } - - index = ltt_channels_get_index_from_name(channel_name); - if (index < 0) { - ERR("Channel %s not found", channel_name); - err = -ENOENT; - goto traces_error; - } - - trace->channels[index].active = enable; - -traces_error: - ltt_unlock_traces(); - return err; -} - -int ltt_trace_set_channel_overwrite(const char *trace_name, - const char *channel_name, unsigned int overwrite) -{ - int err = 0; - struct ust_trace *trace; - int index; - - ltt_lock_traces(); - - trace = _ltt_trace_find_setup(trace_name); - if (!trace) { - ERR("Trace not found %s", trace_name); - err = -ENOENT; - goto traces_error; - } - - /* - * Always put the metadata channel in non-overwrite mode : - * This is a very low traffic channel and it can't afford to have its - * data overwritten : this data (marker info) is necessary to be - * able to read the trace. - */ - if (overwrite && !strcmp(channel_name, "metadata")) { - ERR("Trying to set metadata channel to overwrite mode"); - err = -EINVAL; - goto traces_error; - } - - index = ltt_channels_get_index_from_name(channel_name); - if (index < 0) { - ERR("Channel %s not found", channel_name); - err = -ENOENT; - goto traces_error; - } - - trace->channels[index].overwrite = overwrite; - -traces_error: - ltt_unlock_traces(); - return err; -} - -int ltt_trace_alloc(const char *trace_name) -{ - int err = 0; - struct ust_trace *trace; - unsigned int subbuf_size, subbuf_cnt; - int chan; - const char *channel_name; - - ltt_lock_traces(); - - if (_ltt_trace_find(trace_name)) { /* Trace already allocated */ - err = 1; - goto traces_error; - } - - trace = _ltt_trace_find_setup(trace_name); - if (!trace) { - ERR("Trace not found %s", trace_name); - err = -ENOENT; - goto traces_error; - } - - urcu_ref_init(&trace->urcu_ref); - urcu_ref_init(&trace->ltt_transport_urcu_ref); - trace->active = 0; - trace->freq_scale = trace_clock_freq_scale(); - - if (!trace->transport) { - ERR("Transport is not set"); - err = -EINVAL; - goto transport_error; - } - trace->ops = &trace->transport->ops; - - trace->start_freq = trace_clock_frequency(); - trace->start_tsc = trace_clock_read64(); - gettimeofday(&trace->start_time, NULL); //ust// changed /* FIXME: is this ok? */ - - for (chan = 0; chan < trace->nr_channels; chan++) { - if (!(trace->channels[chan].active)) - continue; - - channel_name = ltt_channels_get_name_from_index(chan); - WARN_ON(!channel_name); - subbuf_size = trace->channels[chan].subbuf_size; - subbuf_cnt = trace->channels[chan].subbuf_cnt; - prepare_chan_size_num(&subbuf_size, &subbuf_cnt); - err = trace->ops->create_channel(trace_name, trace, - channel_name, - &trace->channels[chan], - subbuf_size, - subbuf_cnt, - trace->channels[chan].overwrite); - if (err != 0) { - ERR("Cannot create channel %s", channel_name); - goto create_channel_error; - } - } - - cds_list_del(&trace->list); - cds_list_add_rcu(&trace->list, <t_traces.head); - - ltt_unlock_traces(); - - return 0; - -create_channel_error: - for (chan--; chan >= 0; chan--) - if (trace->channels[chan].active) - trace->ops->remove_channel(&trace->channels[chan]); - -transport_error: -traces_error: - ltt_unlock_traces(); - return err; -} - -/* Must be called while sure that trace is in the list. */ -static int _ltt_trace_destroy(struct ust_trace *trace) -{ - int err = -EPERM; - - if (trace == NULL) { - err = -ENOENT; - goto traces_error; - } - if (trace->active) { - ERR("Can't destroy trace %s : tracer is active", trace->trace_name); - err = -EBUSY; - goto active_error; - } - - cds_list_del_rcu(&trace->list); - synchronize_rcu(); - - return 0; - -active_error: -traces_error: - return err; -} - -/* Sleepable part of the destroy */ -static void __ltt_trace_destroy(struct ust_trace *trace, int drop) -{ - int i; - struct ust_channel *chan; - - if(!drop) { - for (i = 0; i < trace->nr_channels; i++) { - chan = &trace->channels[i]; - if (chan->active) - trace->ops->finish_channel(chan); - } - } - - /* - * The currently destroyed trace is not in the trace list anymore, - * so it's safe to call the async wakeup ourself. It will deliver - * the last subbuffers. - */ - trace_async_wakeup(trace); - - for (i = 0; i < trace->nr_channels; i++) { - chan = &trace->channels[i]; - if (chan->active) - trace->ops->remove_channel(chan); - } - - urcu_ref_put(&trace->ltt_transport_urcu_ref, ltt_release_transport); - - urcu_ref_put(&trace->urcu_ref, ltt_release_trace); -} - -int ltt_trace_destroy(const char *trace_name, int drop) -{ - int err = 0; - struct ust_trace *trace; - - ltt_lock_traces(); - - trace = _ltt_trace_find(trace_name); - if (trace) { - err = _ltt_trace_destroy(trace); - if (err) - goto error; - - ltt_unlock_traces(); - - __ltt_trace_destroy(trace, drop); - - return 0; - } - - trace = _ltt_trace_find_setup(trace_name); - if (trace) { - _ltt_trace_free(trace); - ltt_unlock_traces(); - return 0; - } - - err = -ENOENT; - -error: - ltt_unlock_traces(); - return err; -} - -/* must be called from within a traces lock. */ -static int _ltt_trace_start(struct ust_trace *trace) -{ - int err = 0; - - if (trace == NULL) { - err = -ENOENT; - goto traces_error; - } - if (trace->active) - DBG("Tracing already active for trace %s", trace->trace_name); - trace->active = 1; - /* Read by trace points without protection : be careful */ - ltt_traces.num_active_traces++; - return err; - -traces_error: - return err; -} - -int ltt_trace_start(const char *trace_name) -{ - int err = 0; - struct ust_trace *trace; - - ltt_lock_traces(); - - trace = _ltt_trace_find(trace_name); - err = _ltt_trace_start(trace); - if (err) - goto no_trace; - - ltt_unlock_traces(); - - /* - * Call the process-wide state dump. - * Notice that there is no protection on the trace : that's exactly - * why we iterate on the list and check for trace equality instead of - * directly using this trace handle inside the logging function: we want - * to record events only in a single trace in the trace session list. - */ - - ltt_dump_ust_marker_state(trace); - - return err; - - /* Error handling */ -no_trace: - ltt_unlock_traces(); - return err; -} - -/* must be called from within traces lock */ -static int _ltt_trace_stop(struct ust_trace *trace) -{ - int err = -EPERM; - - if (trace == NULL) { - err = -ENOENT; - goto traces_error; - } - if (!trace->active) - DBG("LTT : Tracing not active for trace %s", trace->trace_name); - if (trace->active) { - trace->active = 0; - ltt_traces.num_active_traces--; - } - return 0; - -traces_error: - return err; -} - -int ltt_trace_stop(const char *trace_name) -{ - int err = 0; - struct ust_trace *trace; - - ltt_lock_traces(); - trace = _ltt_trace_find(trace_name); - err = _ltt_trace_stop(trace); - ltt_unlock_traces(); - return err; -} diff --git a/deprecated/libust/type-serializer.c b/deprecated/libust/type-serializer.c deleted file mode 100644 index 070542c..0000000 --- a/deprecated/libust/type-serializer.c +++ /dev/null @@ -1,126 +0,0 @@ -/** - * ltt-type-serializer.c - * - * LTTng specialized type serializer. - * - * Copyright Mathieu Desnoyers, 2008. - * - * Dual LGPL v2.1/GPL v2 license. - */ - -/* This file contains functions for tracepoint custom probes support. */ - -#define _GNU_SOURCE -#define _LGPL_SOURCE -#include -#include -#include -#include -#include "tracer.h" -#include "type-serializer.h" - -notrace -void _ltt_specialized_trace(const struct ust_marker *mdata, void *probe_data, - void *serialize_private, unsigned int data_size, - unsigned int largest_align) -{ - int ret; - uint16_t eID; - size_t slot_size; - unsigned int chan_index; - struct ust_buffer *buf; - struct ust_channel *chan; - struct ust_trace *trace; - u64 tsc; - long buf_offset; - int cpu; - unsigned int rflags; - - /* - * If we get here, it's probably because we have useful work to do. - */ - if (unlikely(ltt_traces.num_active_traces == 0)) - return; - - rcu_read_lock(); - cpu = ust_get_cpu(); - - /* Force volatile access. */ - CMM_STORE_SHARED(ltt_nesting, CMM_LOAD_SHARED(ltt_nesting) + 1); - - /* - * asm volatile and "memory" clobber prevent the compiler from moving - * instructions out of the ltt nesting count. This is required to ensure - * that probe side-effects which can cause recursion (e.g. unforeseen - * traps, divisions by 0, ...) are triggered within the incremented - * nesting count section. - */ - cmm_barrier(); - eID = mdata->event_id; - chan_index = mdata->channel_id; - - /* - * Iterate on each trace, typically small number of active traces, - * list iteration with prefetch is usually slower. - */ - cds_list_for_each_entry_rcu(trace, <t_traces.head, list) { - if (unlikely(!trace->active)) - continue; -//ust// if (unlikely(!ltt_run_filter(trace, eID))) -//ust// continue; -#ifdef CONFIG_LTT_DEBUG_EVENT_SIZE - rflags = LTT_RFLAG_ID_SIZE; -#else - if (unlikely(eID >= LTT_FREE_EVENTS)) - rflags = LTT_RFLAG_ID; - else - rflags = 0; -#endif - /* - * Skip channels added after trace creation. - */ - if (unlikely(chan_index >= trace->nr_channels)) - continue; - chan = &trace->channels[chan_index]; - if (!chan->active) - continue; - - /* If a new cpu was plugged since the trace was started, we did - * not add it to the trace, and therefore we write the event to - * cpu 0. - */ - if(cpu >= chan->n_cpus) { - cpu = 0; - } - - /* reserve space : header and data */ - ret = ltt_reserve_slot(chan, trace, data_size, largest_align, - cpu, &buf, &slot_size, &buf_offset, &tsc, - &rflags); - if (unlikely(ret < 0)) - continue; /* buffer full */ - - /* Out-of-order write : header and data */ - buf_offset = ltt_write_event_header(chan, buf, - buf_offset, eID, data_size, - tsc, rflags); - if (data_size) { - buf_offset += ltt_align(buf_offset, largest_align); - ust_buffers_write(buf, buf_offset, - serialize_private, data_size); - buf_offset += data_size; - } - /* Out-of-order commit */ - ltt_commit_slot(chan, buf, buf_offset, data_size, slot_size); - } - /* - * asm volatile and "memory" clobber prevent the compiler from moving - * instructions out of the ltt nesting count. This is required to ensure - * that probe side-effects which can cause recursion (e.g. unforeseen - * traps, divisions by 0, ...) are triggered within the incremented - * nesting count section. - */ - cmm_barrier(); - CMM_STORE_SHARED(ltt_nesting, CMM_LOAD_SHARED(ltt_nesting) - 1); - rcu_read_unlock(); -} diff --git a/deprecated/libust/type-serializer.h b/deprecated/libust/type-serializer.h deleted file mode 100644 index 3b1a23a..0000000 --- a/deprecated/libust/type-serializer.h +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef _LTT_TYPE_SERIALIZER_H -#define _LTT_TYPE_SERIALIZER_H - -#include -#include -#include -#include "buffers.h" - -/* - * largest_align must be non-zero, equal to the minimum between the largest type - * and sizeof(void *). - */ -extern void _ltt_specialized_trace(const struct ust_marker *mdata, void *probe_data, - void *serialize_private, unsigned int data_size, - unsigned int largest_align); - -/* - * Statically check that 0 < largest_align < sizeof(void *) to make sure it is - * dumb-proof. It will make sure 0 is changed into 1 and unsigned long long is - * changed into sizeof(void *) on 32-bit architectures. - */ -static inline void ltt_specialized_trace(const struct ust_marker *mdata, - void *probe_data, - void *serialize_private, unsigned int data_size, - unsigned int largest_align) -{ - largest_align = min_t(unsigned int, largest_align, sizeof(void *)); - largest_align = max_t(unsigned int, largest_align, 1); - _ltt_specialized_trace(mdata, probe_data, serialize_private, data_size, - largest_align); -} - -/* - * Type serializer definitions. - */ - -/* - * Return size of structure without end-of-structure padding. - */ -#define serialize_sizeof(type) offsetof(typeof(type), end_field) - -struct serialize_long_int { - unsigned long f1; - unsigned int f2; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_int_int_long { - unsigned int f1; - unsigned int f2; - unsigned long f3; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_int_int_short { - unsigned int f1; - unsigned int f2; - unsigned short f3; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_long_long_long { - unsigned long f1; - unsigned long f2; - unsigned long f3; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_long_long_int { - unsigned long f1; - unsigned long f2; - unsigned int f3; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_long_long_short_char { - unsigned long f1; - unsigned long f2; - unsigned short f3; - unsigned char f4; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_long_long_short { - unsigned long f1; - unsigned long f2; - unsigned short f3; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_long_short_char { - unsigned long f1; - unsigned short f2; - unsigned char f3; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_long_short { - unsigned long f1; - unsigned short f2; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_long_char { - unsigned long f1; - unsigned char f2; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_sizet_int { - size_t f1; - unsigned int f2; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_long_long_sizet_int { - unsigned long f1; - unsigned long f2; - size_t f3; - unsigned int f4; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_long_long_sizet_int_int { - unsigned long f1; - unsigned long f2; - size_t f3; - unsigned int f4; - unsigned int f5; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_l4421224411111 { - unsigned long f1; - uint32_t f2; - uint32_t f3; - uint16_t f4; - uint8_t f5; - uint16_t f6; - uint16_t f7; - uint32_t f8; - uint32_t f9; - uint8_t f10; - uint8_t f11; - uint8_t f12; - uint8_t f13; - uint8_t f14; - unsigned char end_field[0]; -} LTT_ALIGN; - -struct serialize_l214421224411111 { - unsigned long f1; - uint16_t f2; - uint8_t f3; - uint32_t f4; - uint32_t f5; - uint16_t f6; - uint8_t f7; - uint16_t f8; - uint16_t f9; - uint32_t f10; - uint32_t f11; - uint8_t f12; - uint8_t f13; - uint8_t f14; - uint8_t f15; - uint8_t f16; - uint8_t end_field[0]; -} LTT_ALIGN; - -struct serialize_l4412228 { - unsigned long f1; - uint32_t f2; - uint32_t f3; - uint8_t f4; - uint16_t f5; - uint16_t f6; - uint16_t f7; - uint64_t f8; - unsigned char end_field[0]; -} LTT_ALIGN; - -#endif /* _LTT_TYPE_SERIALIZER_H */ diff --git a/deprecated/libustcomm/Makefile.am b/deprecated/libustcomm/Makefile.am deleted file mode 100644 index 3ae96d5..0000000 --- a/deprecated/libustcomm/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include -AM_CFLAGS = -fno-strict-aliasing - -noinst_LTLIBRARIES = libustcomm.la -libustcomm_la_SOURCES = \ - ustcomm.h \ - ustcomm.c - -libustcomm_la_LDFLAGS = -no-undefined -static -libustcomm_la_CFLAGS = -DUST_COMPONENT="libustcomm" -fPIC -fno-strict-aliasing diff --git a/deprecated/libustcomm/ustcomm.c b/deprecated/libustcomm/ustcomm.c deleted file mode 100644 index 07f7f87..0000000 --- a/deprecated/libustcomm/ustcomm.c +++ /dev/null @@ -1,1028 +0,0 @@ -/* Copyright (C) 2009 Pierre-Marc Fournier - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* API used by UST components to communicate with each other via sockets. */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ustcomm.h" -#include "usterr.h" -#include "share.h" - -static int mkdir_p(const char *path, mode_t mode) -{ - const char *path_p; - char *tmp; - - int retval = 0; - int result; - mode_t old_umask; - - tmp = zmalloc(strlen(path) + 1); - if (tmp == NULL) - return -1; - - /* skip first / */ - path_p = path+1; - - old_umask = umask(0); - for(;;) { - while (*path_p != '/') { - if(*path_p == 0) - break; - ++path_p; - } - if (*path_p == '/') { - strncpy(tmp, path, path_p - path); - tmp[path_p-path] = '\0'; - if (tmp[path_p - path - 1] != '/') { - result = mkdir(tmp, mode); - if(result == -1) { - if (!(errno == EEXIST || errno == EACCES || errno == EROFS)) { - /* Then this is a real error */ - retval = -1; - break; - } - } - } - /* pass / */ - path_p++; - } else { - /* last component */ - result = mkdir(path, mode); - if (result == -1) - retval = -1; - break; - } - } - - free(tmp); - umask(old_umask); - return retval; -} - -static struct sockaddr_un * create_sock_addr(const char *name, - size_t *sock_addr_size) -{ - struct sockaddr_un * addr; - size_t alloc_size; - - alloc_size = (size_t) (((struct sockaddr_un *) 0)->sun_path) + - strlen(name) + 1; - - addr = malloc(alloc_size); - if (addr < 0) { - ERR("allocating addr failed"); - return NULL; - } - - addr->sun_family = AF_UNIX; - strcpy(addr->sun_path, name); - - *sock_addr_size = alloc_size; - - return addr; -} - -struct ustcomm_sock * ustcomm_init_sock(int fd, int epoll_fd, - struct cds_list_head *list) -{ - struct epoll_event ev; - struct ustcomm_sock *sock; - - sock = malloc(sizeof(struct ustcomm_sock)); - if (!sock) { - perror("malloc: couldn't allocate ustcomm_sock"); - return NULL; - } - - ev.events = EPOLLIN; - ev.data.ptr = sock; - sock->fd = fd; - - if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock->fd, &ev) == -1) { - perror("epoll_ctl: failed to add socket\n"); - free(sock); - return NULL; - } - - sock->epoll_fd = epoll_fd; - if (list) { - cds_list_add(&sock->list, list); - } else { - CDS_INIT_LIST_HEAD(&sock->list); - } - - return sock; -} - -void ustcomm_del_sock(struct ustcomm_sock *sock, int keep_in_epoll) -{ - cds_list_del(&sock->list); - if (!keep_in_epoll) { - if (epoll_ctl(sock->epoll_fd, EPOLL_CTL_DEL, sock->fd, NULL) == -1) { - PERROR("epoll_ctl: failed to delete socket"); - } - } - close(sock->fd); - free(sock); -} - -struct ustcomm_sock * ustcomm_init_named_socket(const char *name, - int epoll_fd) -{ - int result; - int fd; - size_t sock_addr_size; - struct sockaddr_un * addr; - struct ustcomm_sock *sock; - - fd = socket(PF_UNIX, SOCK_STREAM, 0); - if(fd == -1) { - PERROR("socket"); - return NULL; - } - - addr = create_sock_addr(name, &sock_addr_size); - if (addr == NULL) { - ERR("allocating addr, UST thread bailing"); - goto close_sock; - } - - result = access(name, F_OK); - if(result == 0) { - /* file exists */ - result = unlink(name); - if(result == -1) { - PERROR("unlink of socket file"); - goto free_addr; - } - DBG("socket already exists; overwriting"); - } - - result = bind(fd, (struct sockaddr *)addr, sock_addr_size); - if(result == -1) { - PERROR("bind"); - goto free_addr; - } - - result = listen(fd, 1); - if(result == -1) { - PERROR("listen"); - goto free_addr; - } - - sock = ustcomm_init_sock(fd, epoll_fd, - NULL); - if (!sock) { - ERR("failed to create ustcomm_sock"); - goto free_addr; - } - - free(addr); - - return sock; - -free_addr: - free(addr); -close_sock: - close(fd); - - return NULL; -} - -void ustcomm_del_named_sock(struct ustcomm_sock *sock, - int keep_socket_file) -{ - int result, fd; - struct stat st; - struct sockaddr dummy; - struct sockaddr_un *sockaddr = NULL; - int alloc_size; - - fd = sock->fd; - - if(!keep_socket_file) { - - /* Get the socket name */ - alloc_size = sizeof(dummy); - if (getsockname(fd, &dummy, (socklen_t *)&alloc_size) < 0) { - PERROR("getsockname failed"); - goto del_sock; - } - - sockaddr = zmalloc(alloc_size); - if (!sockaddr) { - ERR("failed to allocate sockaddr"); - goto del_sock; - } - - if (getsockname(fd, sockaddr, (socklen_t *)&alloc_size) < 0) { - PERROR("getsockname failed"); - goto free_sockaddr; - } - - /* Destroy socket */ - result = stat(sockaddr->sun_path, &st); - if(result < 0) { - PERROR("stat (%s)", sockaddr->sun_path); - goto free_sockaddr; - } - - /* Paranoid check before deleting. */ - result = S_ISSOCK(st.st_mode); - if(!result) { - ERR("The socket we are about to delete is not a socket."); - goto free_sockaddr; - } - - result = unlink(sockaddr->sun_path); - if(result < 0) { - PERROR("unlink"); - } - } - -free_sockaddr: - free(sockaddr); - -del_sock: - ustcomm_del_sock(sock, keep_socket_file); -} - -int ustcomm_recv_alloc(int sock, - struct ustcomm_header *header, - char **data) { - int result; - struct ustcomm_header peek_header; - struct iovec iov[2]; - struct msghdr msg; - - /* Just to make the caller fail hard */ - *data = NULL; - - result = recv(sock, &peek_header, sizeof(peek_header), - MSG_PEEK | MSG_WAITALL); - if (result <= 0) { - if(errno == ECONNRESET) { - return 0; - } else if (errno == EINTR) { - return -1; - } else if (result < 0) { - PERROR("recv"); - return -1; - } - return 0; - } - - memset(&msg, 0, sizeof(msg)); - - iov[0].iov_base = (char *)header; - iov[0].iov_len = sizeof(struct ustcomm_header); - - msg.msg_iov = iov; - msg.msg_iovlen = 1; - - if (peek_header.size) { - *data = zmalloc(peek_header.size); - if (!*data) { - return -ENOMEM; - } - - iov[1].iov_base = *data; - iov[1].iov_len = peek_header.size; - - msg.msg_iovlen++; - } - - result = recvmsg(sock, &msg, MSG_WAITALL); - if (result < 0) { - free(*data); - PERROR("recvmsg failed"); - } - - return result; -} - -/* returns 1 to indicate a message was received - * returns 0 to indicate no message was received (end of stream) - * returns -1 to indicate an error - */ -int ustcomm_recv_fd(int sock, - struct ustcomm_header *header, - char *data, int *fd) -{ - int result; - struct ustcomm_header peek_header; - struct iovec iov[2]; - struct msghdr msg; - struct cmsghdr *cmsg; - char buf[CMSG_SPACE(sizeof(int))]; - - result = recv(sock, &peek_header, sizeof(peek_header), - MSG_PEEK | MSG_WAITALL); - if (result <= 0) { - if(errno == ECONNRESET) { - return 0; - } else if (errno == EINTR) { - return -1; - } else if (result < 0) { - PERROR("recv"); - return -1; - } - return 0; - } - - memset(&msg, 0, sizeof(msg)); - - iov[0].iov_base = (char *)header; - iov[0].iov_len = sizeof(struct ustcomm_header); - - msg.msg_iov = iov; - msg.msg_iovlen = 1; - - if (peek_header.size && data) { - if (peek_header.size < 0 || - peek_header.size > USTCOMM_DATA_SIZE) { - ERR("big peek header! %ld", peek_header.size); - return 0; - } - - iov[1].iov_base = data; - iov[1].iov_len = peek_header.size; - - msg.msg_iovlen++; - } - - if (fd && peek_header.fd_included) { - msg.msg_control = buf; - msg.msg_controllen = sizeof(buf); - } - - result = recvmsg(sock, &msg, MSG_WAITALL); - if (result <= 0) { - if (result < 0) { - PERROR("recvmsg failed"); - } - return result; - } - - if (fd && peek_header.fd_included) { - cmsg = CMSG_FIRSTHDR(&msg); - result = 0; - while (cmsg != NULL) { - if (cmsg->cmsg_level == SOL_SOCKET - && cmsg->cmsg_type == SCM_RIGHTS) { - *fd = *(int *) CMSG_DATA(cmsg); - result = 1; - break; - } - cmsg = CMSG_NXTHDR(&msg, cmsg); - } - if (!result) { - ERR("Failed to receive file descriptor\n"); - } - } - - return 1; -} - -int ustcomm_recv(int sock, - struct ustcomm_header *header, - char *data) -{ - return ustcomm_recv_fd(sock, header, data, NULL); -} - - -int ustcomm_send_fd(int sock, - const struct ustcomm_header *header, - const char *data, - int *fd) -{ - struct iovec iov[2]; - struct msghdr msg; - int result; - struct cmsghdr *cmsg; - char buf[CMSG_SPACE(sizeof(int))]; - - memset(&msg, 0, sizeof(msg)); - - iov[0].iov_base = (char *)header; - iov[0].iov_len = sizeof(struct ustcomm_header); - - msg.msg_iov = iov; - msg.msg_iovlen = 1; - - if (header->size && data) { - iov[1].iov_base = (char *)data; - iov[1].iov_len = header->size; - - msg.msg_iovlen++; - - } - - if (fd && header->fd_included) { - msg.msg_control = buf; - msg.msg_controllen = sizeof(buf); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - *(int *) CMSG_DATA(cmsg) = *fd; - msg.msg_controllen = cmsg->cmsg_len; - } - - result = sendmsg(sock, &msg, MSG_NOSIGNAL); - if (result < 0 && errno != EPIPE) { - PERROR("sendmsg failed"); - } - return result; -} - -int ustcomm_send(int sock, - const struct ustcomm_header *header, - const char *data) -{ - return ustcomm_send_fd(sock, header, data, NULL); -} - -int ustcomm_req(int sock, - const struct ustcomm_header *req_header, - const char *req_data, - struct ustcomm_header *res_header, - char *res_data) -{ - int result; - - result = ustcomm_send(sock, req_header, req_data); - if ( result <= 0) { - return result; - } - - return ustcomm_recv(sock, res_header, res_data); -} - -/* Return value: - * 0: success - * -1: error - */ - -int ustcomm_connect_path(const char *name, int *connection_fd) -{ - int result, fd; - size_t sock_addr_size; - struct sockaddr_un *addr; - - fd = socket(PF_UNIX, SOCK_STREAM, 0); - if(fd == -1) { - PERROR("socket"); - return -1; - } - - addr = create_sock_addr(name, &sock_addr_size); - if (addr == NULL) { - ERR("allocating addr failed"); - goto close_sock; - } - - result = connect(fd, (struct sockaddr *)addr, sock_addr_size); - if(result == -1) { - PERROR("connect (path=%s)", name); - goto free_sock_addr; - } - - *connection_fd = fd; - - free(addr); - - return 0; - -free_sock_addr: - free(addr); -close_sock: - close(fd); - - return -1; -} - -/* Returns the current users socket directory, must be freed */ -char *ustcomm_user_sock_dir(void) -{ - int result; - char *sock_dir = NULL; - - result = asprintf(&sock_dir, "%s%s", USER_SOCK_DIR, - cuserid(NULL)); - if (result < 0) { - ERR("string overflow allocating directory name"); - return NULL; - } - - return sock_dir; -} - -static int time_and_pid_from_socket_name(char *sock_name, unsigned long *time, - pid_t *pid) -{ - char *saveptr, *pid_m_time_str; - char *sock_basename = strdup(basename(sock_name)); - - if (!sock_basename) { - return -1; - } - - /* This is the pid */ - pid_m_time_str = strtok_r(sock_basename, ".", &saveptr); - if (!pid_m_time_str) { - goto out_err; - } - - errno = 0; - *pid = (pid_t)strtoul(pid_m_time_str, NULL, 10); - if (errno) { - goto out_err; - } - - /* This should be the time-stamp */ - pid_m_time_str = strtok_r(NULL, ".", &saveptr); - if (!pid_m_time_str) { - goto out_err; - } - - errno = 0; - *time = strtoul(pid_m_time_str, NULL, 10); - if (errno) { - goto out_err; - } - - return 0; - -out_err: - free(sock_basename); - return -1; -} - -time_t ustcomm_pid_st_mtime(pid_t pid) -{ - struct stat proc_stat; - char proc_name[PATH_MAX]; - - if (snprintf(proc_name, PATH_MAX - 1, "/proc/%ld", (long) pid) < 0) { - return 0; - } - - if (stat(proc_name, &proc_stat)) { - return 0; - } - - return proc_stat.st_mtime; -} - -int ustcomm_is_socket_live(char *sock_name, pid_t *read_pid) -{ - time_t time_from_pid; - unsigned long time_from_sock; - pid_t pid; - - if (time_and_pid_from_socket_name(sock_name, &time_from_sock, &pid)) { - return 0; - } - - if (read_pid) { - *read_pid = pid; - } - - time_from_pid = ustcomm_pid_st_mtime(pid); - if (!time_from_pid) { - return 0; - } - - if ((unsigned long) time_from_pid == time_from_sock) { - return 1; - } - - return 0; -} - -#define MAX_SOCK_PATH_BASE_LEN 100 - -static int ustcomm_get_sock_name(char *dir_name, pid_t pid, char *sock_name) -{ - struct dirent *dirent; - char sock_path_base[MAX_SOCK_PATH_BASE_LEN]; - int len; - DIR *dir = opendir(dir_name); - - snprintf(sock_path_base, MAX_SOCK_PATH_BASE_LEN - 1, - "%ld.", (long) pid); - len = strlen(sock_path_base); - - while ((dirent = readdir(dir))) { - if (!strcmp(dirent->d_name, ".") || - !strcmp(dirent->d_name, "..") || - !strcmp(dirent->d_name, "ust-consumer") || - dirent->d_type == DT_DIR || - strncmp(dirent->d_name, sock_path_base, len)) { - continue; - } - - if (ustcomm_is_socket_live(dirent->d_name, NULL)) { - if (snprintf(sock_name, PATH_MAX - 1, "%s/%s", - dir_name, dirent->d_name) < 0) { - PERROR("path longer than PATH_MAX?"); - goto out_err; - } - closedir(dir); - return 0; - } - } - -out_err: - closedir(dir); - return -1; -} - -/* Open a connection to a traceable app. - * - * Return value: - * 0: success - * -1: error - */ - -static int connect_app_non_root(pid_t pid, int *app_fd) -{ - int result; - int retval = 0; - char *dir_name; - char sock_name[PATH_MAX]; - - dir_name = ustcomm_user_sock_dir(); - if (!dir_name) - return -ENOMEM; - - if (ustcomm_get_sock_name(dir_name, pid, sock_name)) { - retval = -ENOENT; - goto free_dir_name; - } - - result = ustcomm_connect_path(sock_name, app_fd); - if (result < 0) { - ERR("failed to connect to app"); - retval = -1; - goto free_dir_name; - } - -free_dir_name: - free(dir_name); - - return retval; -} - - - -static int connect_app_root(pid_t pid, int *app_fd) -{ - DIR *tmp_dir; - struct dirent *dirent; - char dir_name[PATH_MAX], sock_name[PATH_MAX]; - int result = -1; - - tmp_dir = opendir(USER_TMP_DIR); - if (!tmp_dir) { - return -1; - } - - while ((dirent = readdir(tmp_dir))) { - if (!strncmp(dirent->d_name, USER_SOCK_DIR_BASE, - strlen(USER_SOCK_DIR_BASE))) { - - if (snprintf(dir_name, PATH_MAX - 1, "%s/%s", USER_TMP_DIR, - dirent->d_name) < 0) { - continue; - } - - if (ustcomm_get_sock_name(dir_name, pid, sock_name)) { - continue; - } - - result = ustcomm_connect_path(sock_name, app_fd); - - if (result == 0) { - goto close_tmp_dir; - } - } - } - -close_tmp_dir: - closedir(tmp_dir); - - return result; -} - -int ustcomm_connect_app(pid_t pid, int *app_fd) -{ - *app_fd = 0; - - if (geteuid()) { - return connect_app_non_root(pid, app_fd); - } else { - return connect_app_root(pid, app_fd); - } - -} - -int ensure_dir_exists(const char *dir, mode_t mode) -{ - struct stat st; - int result; - - if (!strcmp(dir, "")) - return -1; - - result = stat(dir, &st); - if (result < 0 && errno != ENOENT) { - return -1; - } else if (result < 0) { - /* ENOENT */ - int result; - - result = mkdir_p(dir, mode); - if(result != 0) { - ERR("executing in recursive creation of directory %s", dir); - return -1; - } - } else { - if (st.st_mode != mode) { - result = chmod(dir, mode); - if (result < 0) { - ERR("couldn't set directory mode on %s", dir); - return -1; - } - } - } - - return 0; -} - -char * ustcomm_print_data(char *data_field, int field_size, - int *offset, const char *format, ...) -{ - va_list args; - int count, limit; - char *ptr = USTCOMM_POISON_PTR; - - limit = field_size - *offset; - va_start(args, format); - count = vsnprintf(&data_field[*offset], limit, format, args); - va_end(args); - - if (count < limit && count > -1) { - ptr = NULL + *offset; - *offset = *offset + count + 1; - } - - return ptr; -} - -char * ustcomm_restore_ptr(char *ptr, char *data_field, int data_field_size) -{ - if ((unsigned long)ptr > data_field_size || - ptr == USTCOMM_POISON_PTR) { - return NULL; - } - - return data_field + (long)ptr; -} - -int ustcomm_pack_single_field(struct ustcomm_header *header, - struct ustcomm_single_field *single_field, - const char *string) -{ - int offset = 0; - - single_field->field = ustcomm_print_data(single_field->data, - sizeof(single_field->data), - &offset, - string); - - if (single_field->field == USTCOMM_POISON_PTR) { - return -ENOMEM; - } - - header->size = COMPUTE_MSG_SIZE(single_field, offset); - - return 0; -} - -int ustcomm_unpack_single_field(struct ustcomm_single_field *single_field) -{ - single_field->field = ustcomm_restore_ptr(single_field->field, - single_field->data, - sizeof(single_field->data)); - if (!single_field->field) { - return -EINVAL; - } - - return 0; -} - -int ustcomm_pack_channel_info(struct ustcomm_header *header, - struct ustcomm_channel_info *ch_inf, - const char *trace, - const char *channel) -{ - int offset = 0; - - ch_inf->trace = ustcomm_print_data(ch_inf->data, - sizeof(ch_inf->data), - &offset, - trace); - - if (ch_inf->trace == USTCOMM_POISON_PTR) { - return -ENOMEM; - } - - ch_inf->channel = ustcomm_print_data(ch_inf->data, - sizeof(ch_inf->data), - &offset, - channel); - - if (ch_inf->channel == USTCOMM_POISON_PTR) { - return -ENOMEM; - } - - header->size = COMPUTE_MSG_SIZE(ch_inf, offset); - - return 0; -} - - -int ustcomm_unpack_channel_info(struct ustcomm_channel_info *ch_inf) -{ - ch_inf->trace = ustcomm_restore_ptr(ch_inf->trace, - ch_inf->data, - sizeof(ch_inf->data)); - if (!ch_inf->trace) { - return -EINVAL; - } - - ch_inf->channel = ustcomm_restore_ptr(ch_inf->channel, - ch_inf->data, - sizeof(ch_inf->data)); - if (!ch_inf->channel) { - return -EINVAL; - } - - return 0; -} - -int ustcomm_pack_buffer_info(struct ustcomm_header *header, - struct ustcomm_buffer_info *buf_inf, - const char *trace, - const char *channel, - int channel_cpu) -{ - int offset = 0; - - buf_inf->trace = ustcomm_print_data(buf_inf->data, - sizeof(buf_inf->data), - &offset, - trace); - - if (buf_inf->trace == USTCOMM_POISON_PTR) { - return -ENOMEM; - } - - buf_inf->channel = ustcomm_print_data(buf_inf->data, - sizeof(buf_inf->data), - &offset, - channel); - - if (buf_inf->channel == USTCOMM_POISON_PTR) { - return -ENOMEM; - } - - buf_inf->ch_cpu = channel_cpu; - - header->size = COMPUTE_MSG_SIZE(buf_inf, offset); - - return 0; -} - - -int ustcomm_unpack_buffer_info(struct ustcomm_buffer_info *buf_inf) -{ - buf_inf->trace = ustcomm_restore_ptr(buf_inf->trace, - buf_inf->data, - sizeof(buf_inf->data)); - if (!buf_inf->trace) { - return -EINVAL; - } - - buf_inf->channel = ustcomm_restore_ptr(buf_inf->channel, - buf_inf->data, - sizeof(buf_inf->data)); - if (!buf_inf->channel) { - return -EINVAL; - } - - return 0; -} - -int ustcomm_pack_ust_marker_info(struct ustcomm_header *header, - struct ustcomm_ust_marker_info *ust_marker_inf, - const char *trace, - const char *channel, - const char *ust_marker) -{ - int offset = 0; - - ust_marker_inf->trace = ustcomm_print_data(ust_marker_inf->data, - sizeof(ust_marker_inf->data), - &offset, - trace); - - if (ust_marker_inf->trace == USTCOMM_POISON_PTR) { - return -ENOMEM; - } - - - ust_marker_inf->channel = ustcomm_print_data(ust_marker_inf->data, - sizeof(ust_marker_inf->data), - &offset, - channel); - - if (ust_marker_inf->channel == USTCOMM_POISON_PTR) { - return -ENOMEM; - } - - - ust_marker_inf->ust_marker = ustcomm_print_data(ust_marker_inf->data, - sizeof(ust_marker_inf->data), - &offset, - ust_marker); - - if (ust_marker_inf->ust_marker == USTCOMM_POISON_PTR) { - return -ENOMEM; - } - - header->size = COMPUTE_MSG_SIZE(ust_marker_inf, offset); - - return 0; -} - -int ustcomm_unpack_ust_marker_info(struct ustcomm_ust_marker_info *ust_marker_inf) -{ - ust_marker_inf->trace = ustcomm_restore_ptr(ust_marker_inf->trace, - ust_marker_inf->data, - sizeof(ust_marker_inf->data)); - if (!ust_marker_inf->trace) { - return -EINVAL; - } - - ust_marker_inf->channel = ustcomm_restore_ptr(ust_marker_inf->channel, - ust_marker_inf->data, - sizeof(ust_marker_inf->data)); - if (!ust_marker_inf->channel) { - return -EINVAL; - } - - ust_marker_inf->ust_marker = ustcomm_restore_ptr(ust_marker_inf->ust_marker, - ust_marker_inf->data, - sizeof(ust_marker_inf->data)); - if (!ust_marker_inf->ust_marker) { - return -EINVAL; - } - - return 0; -} - diff --git a/deprecated/libustcomm/ustcomm.h b/deprecated/libustcomm/ustcomm.h deleted file mode 100644 index 4706b72..0000000 --- a/deprecated/libustcomm/ustcomm.h +++ /dev/null @@ -1,220 +0,0 @@ -/* Copyright (C) 2009 Pierre-Marc Fournier - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef USTCOMM_H -#define USTCOMM_H - -#include -#include -#include - -#include - -#define SOCK_DIR "/tmp/ust-app-socks" -#define USER_TMP_DIR "/tmp" -#define USER_SOCK_DIR_BASE "ust-socks-" -#define USER_SOCK_DIR USER_TMP_DIR "/" USER_SOCK_DIR_BASE - -struct ustcomm_sock { - struct cds_list_head list; - int fd; - int epoll_fd; -}; - -struct ustcomm_header { - int command; - long size; - int result; - int fd_included; -}; - -#define USTCOMM_BUFFER_SIZE ((1 << 12) - sizeof(struct ustcomm_header)) - -/* Specify a sata size that leaves margin at the end of a buffer - * in order to make sure that we never have more data than - * will fit in the buffer AND that the last chars (due to a - * pre-receive memset) will always be 0, terminating any string - */ -#define USTCOMM_DATA_SIZE (USTCOMM_BUFFER_SIZE - 20 * sizeof(void *)) - -enum tracectl_commands { - ALLOC_TRACE, - CONSUME_BUFFER, - CREATE_TRACE, - DESTROY_TRACE, - DISABLE_MARKER, - ENABLE_MARKER, - EXIT, - FORCE_SUBBUF_SWITCH, - GET_BUF_SHMID_PIPE_FD, - GET_PIDUNIQUE, - GET_SOCK_PATH, - GET_SUBBUFFER, - GET_SUBBUF_NUM_SIZE, - LIST_MARKERS, - LIST_TRACE_EVENTS, - LOAD_PROBE_LIB, - NOTIFY_BUF_MAPPED, - PRINT_MARKERS, - PRINT_TRACE_EVENTS, - PUT_SUBBUFFER, - SETUP_TRACE, - SET_SOCK_PATH, - SET_SUBBUF_NUM, - SET_SUBBUF_SIZE, - START, - START_TRACE, - STOP_TRACE, -}; - -struct ustcomm_single_field { - char *field; - char data[USTCOMM_DATA_SIZE]; -}; - -struct ustcomm_channel_info { - char *trace; - char *channel; - unsigned int subbuf_size; - unsigned int subbuf_num; - char data[USTCOMM_DATA_SIZE]; -}; - -struct ustcomm_buffer_info { - char *trace; - char *channel; - int ch_cpu; - pid_t pid; - int buf_shmid; - int buf_struct_shmid; - long consumed_old; - char data[USTCOMM_DATA_SIZE]; -}; - -struct ustcomm_ust_marker_info { - char *trace; - char *channel; - char *ust_marker; - char data[USTCOMM_DATA_SIZE]; -}; - -struct ustcomm_pidunique { - s64 pidunique; -}; - -struct ustcomm_notify_buf_mapped { - char data[USTCOMM_DATA_SIZE]; -}; - -/* Ensure directory existence, usefull for unix sockets */ -extern int ensure_dir_exists(const char *dir, mode_t mode); - -/* Create and delete sockets */ -extern struct ustcomm_sock * ustcomm_init_sock(int fd, int epoll_fd, - struct cds_list_head *list); -extern void ustcomm_del_sock(struct ustcomm_sock *sock, int keep_in_epoll); - -/* Create and delete named sockets */ -extern struct ustcomm_sock * ustcomm_init_named_socket(const char *name, - int epoll_fd); -extern void ustcomm_del_named_sock(struct ustcomm_sock *sock, - int keep_socket_file); - -/* Send and receive functions for file descriptors */ -extern int ustcomm_send_fd(int sock, const struct ustcomm_header *header, - const char *data, int *fd); -extern int ustcomm_recv_fd(int sock, struct ustcomm_header *header, - char *data, int *fd); - -/* Normal send and receive functions */ -extern int ustcomm_send(int sock, const struct ustcomm_header *header, - const char *data); -extern int ustcomm_recv(int sock, struct ustcomm_header *header, - char *data); - -/* Receive and allocate data, not to be used inside libust */ -extern int ustcomm_recv_alloc(int sock, - struct ustcomm_header *header, - char **data); - -/* Request function, send and receive */ -extern int ustcomm_req(int sock, - const struct ustcomm_header *req_header, - const char *req_data, - struct ustcomm_header *res_header, - char *res_data); - -extern int ustcomm_request_consumer(pid_t pid, const char *channel); - -/* Returns the current users socket directory, must be freed */ -extern char *ustcomm_user_sock_dir(void); - -/* Get the st_m_time from proc*/ -extern time_t ustcomm_pid_st_mtime(pid_t pid); - -/* Check that a socket is live */ -extern int ustcomm_is_socket_live(char *sock_name, pid_t *read_pid); - -extern int ustcomm_connect_app(pid_t pid, int *app_fd); -extern int ustcomm_connect_path(const char *path, int *connection_fd); - -extern int nth_token_is(const char *str, const char *token, int tok_no); - -extern char *nth_token(const char *str, int tok_no); - -/* String serialising functions, printf straight into a buffer */ -#define USTCOMM_POISON_PTR (void *)0x19831018 - -extern char * ustcomm_print_data(char *data_field, int field_size, - int *offset, const char *format, ...); -extern char * ustcomm_restore_ptr(char *ptr, char *data_field, - int data_field_size); - -#define COMPUTE_MSG_SIZE(struct_ptr, offset) \ - (size_t) (long)(struct_ptr)->data - (long)(struct_ptr) + (offset) - -/* Packing and unpacking functions, making life easier */ -extern int ustcomm_pack_single_field(struct ustcomm_header *header, - struct ustcomm_single_field *sf, - const char *trace); - -extern int ustcomm_unpack_single_field(struct ustcomm_single_field *sf); - -extern int ustcomm_pack_channel_info(struct ustcomm_header *header, - struct ustcomm_channel_info *ch_inf, - const char *trace, - const char *channel); - -extern int ustcomm_unpack_channel_info(struct ustcomm_channel_info *ch_inf); - -extern int ustcomm_pack_buffer_info(struct ustcomm_header *header, - struct ustcomm_buffer_info *buf_inf, - const char *trace, - const char *channel, - int channel_cpu); - -extern int ustcomm_unpack_buffer_info(struct ustcomm_buffer_info *buf_inf); - -extern int ustcomm_pack_ust_marker_info(struct ustcomm_header *header, - struct ustcomm_ust_marker_info *ust_marker_inf, - const char *trace, - const char *channel, - const char *ust_marker); - -extern int ustcomm_unpack_ust_marker_info(struct ustcomm_ust_marker_info *ust_marker_inf); - -#endif /* USTCOMM_H */ diff --git a/deprecated/libustconsumer/Makefile.am b/deprecated/libustconsumer/Makefile.am deleted file mode 100644 index 1f87479..0000000 --- a/deprecated/libustconsumer/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/libust -I$(top_srcdir)/libustcomm \ - -I$(top_srcdir)/include -AM_CFLAGS = -fno-strict-aliasing - -lib_LTLIBRARIES = libustconsumer.la - -libustconsumer_la_SOURCES = libustconsumer.c lowlevel.c lowlevel.h - -libustconsumer_la_LDFLAGS = -no-undefined -version-info 0:0:0 - -libustconsumer_la_LIBADD = \ - -lpthread \ - $(top_builddir)/snprintf/libustsnprintf.la \ - $(top_builddir)/libustcomm/libustcomm.la - -libustconsumer_la_CFLAGS = -fno-strict-aliasing diff --git a/deprecated/libustconsumer/libustconsumer.c b/deprecated/libustconsumer/libustconsumer.c deleted file mode 100644 index c6dd20c..0000000 --- a/deprecated/libustconsumer/libustconsumer.c +++ /dev/null @@ -1,923 +0,0 @@ -/* Copyright (C) 2009 Pierre-Marc Fournier - * 2010 Alexis Halle - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include "lowlevel.h" -#include "usterr_signal_safe.h" -#include "ustcomm.h" - -#define GET_SUBBUF_OK 1 -#define GET_SUBBUF_DONE 0 -#define GET_SUBBUF_DIED 2 - -#define PUT_SUBBUF_OK 1 -#define PUT_SUBBUF_DIED 0 -#define PUT_SUBBUF_PUSHED 2 -#define PUT_SUBBUF_DONE 3 - -#define UNIX_PATH_MAX 108 - -static int get_subbuffer(struct buffer_info *buf) -{ - struct ustcomm_header _send_hdr, *send_hdr; - struct ustcomm_header _recv_hdr, *recv_hdr; - struct ustcomm_buffer_info _send_msg, _recv_msg; - struct ustcomm_buffer_info *send_msg, *recv_msg; - int result; - - send_hdr = &_send_hdr; - recv_hdr = &_recv_hdr; - send_msg = &_send_msg; - recv_msg = &_recv_msg; - - result = ustcomm_pack_buffer_info(send_hdr, send_msg, buf->trace, - buf->channel, buf->channel_cpu); - if (result < 0) { - return result; - } - - send_hdr->command = GET_SUBBUFFER; - - result = ustcomm_req(buf->app_sock, send_hdr, (char *)send_msg, - recv_hdr, (char *)recv_msg); - if ((result < 0 && (errno == ECONNRESET || errno == EPIPE)) || - result == 0) { - DBG("app died while being traced"); - return GET_SUBBUF_DIED; - } else if (result < 0) { - ERR("get_subbuffer: ustcomm_req failed"); - return result; - } - - if (!recv_hdr->result) { - DBG("got subbuffer %s", buf->name); - buf->consumed_old = recv_msg->consumed_old; - return GET_SUBBUF_OK; - } else if (recv_hdr->result == -ENODATA) { - DBG("For buffer %s, the trace was not found. This likely means" - " it was destroyed by the user.", buf->name); - return GET_SUBBUF_DIED; - } - - DBG("error getting subbuffer %s", buf->name); - return recv_hdr->result; -} - -static int put_subbuffer(struct buffer_info *buf) -{ - struct ustcomm_header _send_hdr, *send_hdr; - struct ustcomm_header _recv_hdr, *recv_hdr; - struct ustcomm_buffer_info _send_msg, *send_msg; - int result; - - send_hdr = &_send_hdr; - recv_hdr = &_recv_hdr; - send_msg = &_send_msg; - - result = ustcomm_pack_buffer_info(send_hdr, send_msg, buf->trace, - buf->channel, buf->channel_cpu); - if (result < 0) { - return result; - } - - send_hdr->command = PUT_SUBBUFFER; - send_msg->consumed_old = buf->consumed_old; - - result = ustcomm_req(buf->app_sock, send_hdr, (char *)send_msg, - recv_hdr, NULL); - if ((result < 0 && (errno == ECONNRESET || errno == EPIPE)) || - result == 0) { - DBG("app died while being traced"); - return PUT_SUBBUF_DIED; - } else if (result < 0) { - ERR("put_subbuffer: ustcomm_req failed"); - return result; - } - - if (!recv_hdr->result) { - DBG("put subbuffer %s", buf->name); - return PUT_SUBBUF_OK; - } else if (recv_hdr->result == -ENODATA) { - DBG("For buffer %s, the trace was not found. This likely means" - " it was destroyed by the user.", buf->name); - return PUT_SUBBUF_DIED; - } - - DBG("error getting subbuffer %s", buf->name); - return recv_hdr->result; -} - -void decrement_active_buffers(void *arg) -{ - struct ustconsumer_instance *instance = arg; - pthread_mutex_lock(&instance->mutex); - instance->active_buffers--; - pthread_mutex_unlock(&instance->mutex); -} - -static int get_pidunique(int sock, int64_t *pidunique) -{ - struct ustcomm_header _send_hdr, *send_hdr; - struct ustcomm_header _recv_hdr, *recv_hdr; - struct ustcomm_pidunique _recv_msg, *recv_msg; - int result; - - send_hdr = &_send_hdr; - recv_hdr = &_recv_hdr; - recv_msg = &_recv_msg; - - memset(send_hdr, 0, sizeof(*send_hdr)); - - send_hdr->command = GET_PIDUNIQUE; - result = ustcomm_req(sock, send_hdr, NULL, recv_hdr, (char *)recv_msg); - if (result < 1) { - return -ENOTCONN; - } - if (recv_hdr->result < 0) { - ERR("App responded with error: %s", strerror(recv_hdr->result)); - return recv_hdr->result; - } - - *pidunique = recv_msg->pidunique; - - return 0; -} - -static int get_buf_shmid_pipe_fd(int sock, struct buffer_info *buf, - int *buf_shmid, int *buf_struct_shmid, - int *buf_pipe_fd) -{ - struct ustcomm_header _send_hdr, *send_hdr; - struct ustcomm_header _recv_hdr, *recv_hdr; - struct ustcomm_buffer_info _send_msg, *send_msg; - struct ustcomm_buffer_info _recv_msg, *recv_msg; - int result, recv_pipe_fd; - - send_hdr = &_send_hdr; - recv_hdr = &_recv_hdr; - send_msg = &_send_msg; - recv_msg = &_recv_msg; - - result = ustcomm_pack_buffer_info(send_hdr, send_msg, buf->trace, - buf->channel, buf->channel_cpu); - if (result < 0) { - ERR("Failed to pack buffer info"); - return result; - } - - send_hdr->command = GET_BUF_SHMID_PIPE_FD; - - result = ustcomm_send(sock, send_hdr, (char *)send_msg); - if (result < 1) { - ERR("Failed to send request"); - return -ENOTCONN; - } - result = ustcomm_recv_fd(sock, recv_hdr, (char *)recv_msg, &recv_pipe_fd); - if (result < 1) { - ERR("Failed to receive message and fd"); - return -ENOTCONN; - } - if (recv_hdr->result < 0) { - ERR("App responded with error %s", strerror(recv_hdr->result)); - return recv_hdr->result; - } - - *buf_shmid = recv_msg->buf_shmid; - *buf_struct_shmid = recv_msg->buf_struct_shmid; - *buf_pipe_fd = recv_pipe_fd; - - return 0; -} - -static int get_subbuf_num_size(int sock, struct buffer_info *buf, - int *subbuf_num, int *subbuf_size) -{ - struct ustcomm_header _send_hdr, *send_hdr; - struct ustcomm_header _recv_hdr, *recv_hdr; - struct ustcomm_channel_info _send_msg, *send_msg; - struct ustcomm_channel_info _recv_msg, *recv_msg; - int result; - - send_hdr = &_send_hdr; - recv_hdr = &_recv_hdr; - send_msg = &_send_msg; - recv_msg = &_recv_msg; - - result = ustcomm_pack_channel_info(send_hdr, send_msg, buf->trace, - buf->channel); - if (result < 0) { - return result; - } - - send_hdr->command = GET_SUBBUF_NUM_SIZE; - - result = ustcomm_req(sock, send_hdr, (char *)send_msg, - recv_hdr, (char *)recv_msg); - if (result < 1) { - return -ENOTCONN; - } - - *subbuf_num = recv_msg->subbuf_num; - *subbuf_size = recv_msg->subbuf_size; - - return recv_hdr->result; -} - - -static int notify_buffer_mapped(int sock, struct buffer_info *buf) -{ - struct ustcomm_header _send_hdr, *send_hdr; - struct ustcomm_header _recv_hdr, *recv_hdr; - struct ustcomm_buffer_info _send_msg, *send_msg; - int result; - - send_hdr = &_send_hdr; - recv_hdr = &_recv_hdr; - send_msg = &_send_msg; - - result = ustcomm_pack_buffer_info(send_hdr, send_msg, buf->trace, - buf->channel, buf->channel_cpu); - if (result < 0) { - return result; - } - - send_hdr->command = NOTIFY_BUF_MAPPED; - - result = ustcomm_req(sock, send_hdr, (char *)send_msg, - recv_hdr, NULL); - if (result < 1) { - return -ENOTCONN; - } - - return recv_hdr->result; -} - - -struct buffer_info *connect_buffer(struct ustconsumer_instance *instance, pid_t pid, - const char *trace, const char *channel, - int channel_cpu) -{ - struct buffer_info *buf; - int result; - struct shmid_ds shmds; - - buf = (struct buffer_info *) zmalloc(sizeof(struct buffer_info)); - if(buf == NULL) { - ERR("add_buffer: insufficient memory"); - return NULL; - } - - buf->trace = strdup(trace); - if (!buf->trace) { - goto free_buf; - } - - buf->channel = strdup(channel); - if (!buf->channel) { - goto free_buf_trace; - } - - result = asprintf(&buf->name, "%s_%d", channel, channel_cpu); - if (result < 0 || buf->name == NULL) { - goto free_buf_channel; - } - - buf->channel_cpu = channel_cpu; - buf->pid = pid; - - result = ustcomm_connect_app(buf->pid, &buf->app_sock); - if(result) { - WARN("unable to connect to process, it probably died before we were able to connect"); - goto free_buf_name; - } - - /* get pidunique */ - result = get_pidunique(buf->app_sock, &buf->pidunique); - if (result < 0) { - ERR("Failed to get pidunique"); - goto close_app_sock; - } - - /* get shmid and pipe fd */ - result = get_buf_shmid_pipe_fd(buf->app_sock, buf, &buf->shmid, - &buf->bufstruct_shmid, &buf->pipe_fd); - if (result < 0) { - ERR("Failed to get buf_shmid and pipe_fd"); - goto close_app_sock; - } else { - struct stat temp; - fstat(buf->pipe_fd, &temp); - if (!S_ISFIFO(temp.st_mode)) { - ERR("Didn't receive a fifo from the app"); - goto close_app_sock; - } - } - - - /* get number of subbufs and subbuf size */ - result = get_subbuf_num_size(buf->app_sock, buf, &buf->n_subbufs, - &buf->subbuf_size); - if (result < 0) { - ERR("Failed to get subbuf number and size"); - goto close_fifo; - } - - /* Set subbuffer's information */ - buf->subbuf_size_order = get_count_order(buf->subbuf_size); - buf->alloc_size = buf->subbuf_size * buf->n_subbufs; - - /* attach memory */ - buf->mem = shmat(buf->shmid, NULL, 0); - if(buf->mem == (void *) 0) { - PERROR("shmat"); - goto close_fifo; - } - DBG("successfully attached buffer memory"); - - buf->bufstruct_mem = shmat(buf->bufstruct_shmid, NULL, 0); - if(buf->bufstruct_mem == (void *) 0) { - PERROR("shmat"); - goto shmdt_mem; - } - DBG("successfully attached buffer bufstruct memory"); - - /* obtain info on the memory segment */ - result = shmctl(buf->shmid, IPC_STAT, &shmds); - if(result == -1) { - PERROR("shmctl"); - goto shmdt_bufstruct_mem; - } - buf->memlen = shmds.shm_segsz; - - /* Notify the application that we have mapped the buffer */ - result = notify_buffer_mapped(buf->app_sock, buf); - if (result < 0) { - goto shmdt_bufstruct_mem; - } - - if(instance->callbacks->on_open_buffer) - instance->callbacks->on_open_buffer(instance->callbacks, buf); - - pthread_mutex_lock(&instance->mutex); - instance->active_buffers++; - pthread_mutex_unlock(&instance->mutex); - - return buf; - -shmdt_bufstruct_mem: - shmdt(buf->bufstruct_mem); - -shmdt_mem: - shmdt(buf->mem); - -close_fifo: - close(buf->pipe_fd); - -close_app_sock: - close(buf->app_sock); - -free_buf_name: - free(buf->name); - -free_buf_channel: - free(buf->channel); - -free_buf_trace: - free(buf->trace); - -free_buf: - free(buf); - return NULL; -} - -static void destroy_buffer(struct ustconsumer_callbacks *callbacks, - struct buffer_info *buf) -{ - int result; - - result = close(buf->pipe_fd); - if(result == -1) { - WARN("problem closing the pipe fd"); - } - - result = close(buf->app_sock); - if(result == -1) { - WARN("problem calling ustcomm_close_app"); - } - - result = shmdt(buf->mem); - if(result == -1) { - PERROR("shmdt"); - } - - result = shmdt(buf->bufstruct_mem); - if(result == -1) { - PERROR("shmdt"); - } - - if(callbacks->on_close_buffer) - callbacks->on_close_buffer(callbacks, buf); - - free(buf); -} - -int consumer_loop(struct ustconsumer_instance *instance, struct buffer_info *buf) -{ - int result = 0; - int read_result; - char read_buf; - - pthread_cleanup_push(decrement_active_buffers, instance); - - for(;;) { - read_result = read(buf->pipe_fd, &read_buf, 1); - /* get the subbuffer */ - if (read_result == 1) { - result = get_subbuffer(buf); - if (result < 0) { - ERR("error getting subbuffer"); - continue; - } else if (result == GET_SUBBUF_DIED) { - finish_consuming_dead_subbuffer(instance->callbacks, buf); - break; - } - } else if ((read_result == -1 && (errno == ECONNRESET || errno == EPIPE)) || - result == 0) { - DBG("App died while being traced"); - finish_consuming_dead_subbuffer(instance->callbacks, buf); - break; - } else if (read_result == -1 && errno == EINTR) { - continue; - } - - if(instance->callbacks->on_read_subbuffer) - instance->callbacks->on_read_subbuffer(instance->callbacks, buf); - - /* put the subbuffer */ - result = put_subbuffer(buf); - if(result == -1) { - ERR("unknown error putting subbuffer (channel=%s)", buf->name); - break; - } - else if(result == PUT_SUBBUF_PUSHED) { - ERR("Buffer overflow (channel=%s), reader pushed. This channel will not be usable passed this point.", buf->name); - break; - } - else if(result == PUT_SUBBUF_DIED) { - DBG("application died while putting subbuffer"); - /* Skip the first subbuffer. We are not sure it is trustable - * because the put_subbuffer() did not complete. - */ - /* TODO: check on_put_error return value */ - if(instance->callbacks->on_put_error) - instance->callbacks->on_put_error(instance->callbacks, buf); - - finish_consuming_dead_subbuffer(instance->callbacks, buf); - break; - } - else if(result == PUT_SUBBUF_DONE) { - /* Done with this subbuffer */ - /* FIXME: add a case where this branch is used? Upon - * normal trace termination, at put_subbuf time, a - * special last-subbuffer code could be returned by - * the listener. - */ - break; - } - else if(result == PUT_SUBBUF_OK) { - } - } - - DBG("thread for buffer %s is stopping", buf->name); - - /* FIXME: destroy, unalloc... */ - - pthread_cleanup_pop(1); - - return 0; -} - -struct consumer_thread_args { - pid_t pid; - const char *trace; - const char *channel; - int channel_cpu; - struct ustconsumer_instance *instance; -}; - -void *consumer_thread(void *arg) -{ - struct buffer_info *buf; - struct consumer_thread_args *args = (struct consumer_thread_args *) arg; - int result; - sigset_t sigset; - - pthread_mutex_lock(&args->instance->mutex); - args->instance->active_threads++; - pthread_mutex_unlock(&args->instance->mutex); - - if(args->instance->callbacks->on_new_thread) - args->instance->callbacks->on_new_thread(args->instance->callbacks); - - /* Block signals that should be handled by the main thread. */ - result = sigemptyset(&sigset); - if(result == -1) { - PERROR("sigemptyset"); - goto end; - } - result = sigaddset(&sigset, SIGTERM); - if(result == -1) { - PERROR("sigaddset"); - goto end; - } - result = sigaddset(&sigset, SIGINT); - if(result == -1) { - PERROR("sigaddset"); - goto end; - } - result = sigprocmask(SIG_BLOCK, &sigset, NULL); - if(result == -1) { - PERROR("sigprocmask"); - goto end; - } - - buf = connect_buffer(args->instance, args->pid, args->trace, - args->channel, args->channel_cpu); - if(buf == NULL) { - ERR("failed to connect to buffer"); - goto end; - } - - consumer_loop(args->instance, buf); - - destroy_buffer(args->instance->callbacks, buf); - - end: - - if(args->instance->callbacks->on_close_thread) - args->instance->callbacks->on_close_thread(args->instance->callbacks); - - pthread_mutex_lock(&args->instance->mutex); - args->instance->active_threads--; - pthread_mutex_unlock(&args->instance->mutex); - - free((void *)args->channel); - free(args); - return NULL; -} - -int start_consuming_buffer(struct ustconsumer_instance *instance, pid_t pid, - const char *trace, const char *channel, - int channel_cpu) -{ - pthread_t thr; - struct consumer_thread_args *args; - int result; - - DBG("beginning of start_consuming_buffer: args: pid %d bufname %s_%d", pid, channel, - channel_cpu); - - args = (struct consumer_thread_args *) zmalloc(sizeof(struct consumer_thread_args)); - if (!args) { - return -ENOMEM; - } - - args->pid = pid; - args->trace = strdup(trace); - args->channel = strdup(channel); - args->channel_cpu = channel_cpu; - args->instance = instance; - DBG("beginning2 of start_consuming_buffer: args: pid %d trace %s" - " bufname %s_%d", args->pid, args->trace, args->channel, args->channel_cpu); - - result = pthread_create(&thr, NULL, consumer_thread, args); - if(result == -1) { - ERR("pthread_create failed"); - return -1; - } - result = pthread_detach(thr); - if(result == -1) { - ERR("pthread_detach failed"); - return -1; - } - DBG("end of start_consuming_buffer: args: pid %d trace %s " - "bufname %s_%d", args->pid, args->channel, args->trace, args->channel_cpu); - - return 0; -} -static void process_client_cmd(int sock, struct ustcomm_header *req_header, - char *recvbuf, struct ustconsumer_instance *instance) -{ - int result; - struct ustcomm_header _res_header = {0}; - struct ustcomm_header *res_header = &_res_header; - struct ustcomm_buffer_info *buf_inf; - - DBG("Processing client command"); - - switch (req_header->command) { - case CONSUME_BUFFER: - - buf_inf = (struct ustcomm_buffer_info *)recvbuf; - result = ustcomm_unpack_buffer_info(buf_inf); - if (result < 0) { - ERR("Couldn't unpack buffer info"); - return; - } - - DBG("Going to consume trace %s buffer %s_%d in process %d", - buf_inf->trace, buf_inf->channel, buf_inf->ch_cpu, - buf_inf->pid); - result = start_consuming_buffer(instance, buf_inf->pid, - buf_inf->trace, - buf_inf->channel, - buf_inf->ch_cpu); - if (result < 0) { - ERR("error in add_buffer"); - return; - } - - res_header->result = 0; - break; - case EXIT: - res_header->result = 0; - /* Only there to force poll to return */ - break; - default: - res_header->result = -EINVAL; - WARN("unknown command: %d", req_header->command); - } - - if (ustcomm_send(sock, res_header, NULL) <= 0) { - ERR("couldn't send command response"); - } -} - -#define MAX_EVENTS 10 - -int ustconsumer_start_instance(struct ustconsumer_instance *instance) -{ - struct ustcomm_header recv_hdr; - char recv_buf[USTCOMM_BUFFER_SIZE]; - struct ustcomm_sock *epoll_sock; - struct epoll_event events[MAX_EVENTS]; - struct sockaddr addr; - int result, epoll_fd, accept_fd, nfds, i, addr_size, timeout; - - if(!instance->is_init) { - ERR("libustconsumer instance not initialized"); - return 1; - } - epoll_fd = instance->epoll_fd; - - timeout = -1; - - /* app loop */ - for(;;) { - nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, timeout); - if (nfds == -1 && errno == EINTR) { - /* Caught signal */ - } else if (nfds == -1) { - PERROR("ustconsumer_start_instance: epoll_wait failed"); - continue; - } - - for (i = 0; i < nfds; ++i) { - epoll_sock = (struct ustcomm_sock *)events[i].data.ptr; - if (epoll_sock == instance->listen_sock) { - addr_size = sizeof(struct sockaddr); - accept_fd = accept(epoll_sock->fd, - &addr, - (socklen_t *)&addr_size); - if (accept_fd == -1) { - PERROR("ustconsumer_start_instance: " - "accept failed"); - continue; - } - ustcomm_init_sock(accept_fd, epoll_fd, - &instance->connections); - } else { - result = ustcomm_recv(epoll_sock->fd, &recv_hdr, - recv_buf); - if (result < 1) { - ustcomm_del_sock(epoll_sock, 0); - } else { - process_client_cmd(epoll_sock->fd, - &recv_hdr, recv_buf, - instance); - } - - } - } - - if (instance->quit_program) { - pthread_mutex_lock(&instance->mutex); - if (instance->active_buffers == 0 && instance->active_threads == 0) { - pthread_mutex_unlock(&instance->mutex); - break; - } - pthread_mutex_unlock(&instance->mutex); - timeout = 100; - } - } - - if(instance->callbacks->on_trace_end) - instance->callbacks->on_trace_end(instance); - - ustconsumer_delete_instance(instance); - - return 0; -} - -/* FIXME: threads and connections !? */ -void ustconsumer_delete_instance(struct ustconsumer_instance *instance) -{ - if (instance->is_init) { - ustcomm_del_named_sock(instance->listen_sock, 0); - close(instance->epoll_fd); - } - - pthread_mutex_destroy(&instance->mutex); - free(instance->sock_path); - free(instance); -} - -/* FIXME: Do something about the fixed path length, maybe get rid - * of the whole concept and use a pipe? - */ -int ustconsumer_stop_instance(struct ustconsumer_instance *instance, int send_msg) -{ - int result; - int fd; - int bytes = 0; - - char msg[] = "exit"; - - instance->quit_program = 1; - - if(!send_msg) - return 0; - - /* Send a message through the socket to force poll to return */ - - struct sockaddr_un addr; - -socket_again: - result = fd = socket(PF_UNIX, SOCK_STREAM, 0); - if(result == -1) { - if (errno == EINTR) - goto socket_again; - PERROR("socket"); - return 1; - } - - addr.sun_family = AF_UNIX; - - strncpy(addr.sun_path, instance->sock_path, UNIX_PATH_MAX); - addr.sun_path[UNIX_PATH_MAX-1] = '\0'; - -connect_again: - result = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); - if(result == -1) { - if (errno == EINTR) - goto connect_again; - PERROR("connect"); - } - - while(bytes != sizeof(msg)) { - int inc = send(fd, msg, sizeof(msg), 0); - if (inc < 0 && errno != EINTR) - break; - else - bytes += inc; - } - - close(fd); - - return 0; -} - -struct ustconsumer_instance -*ustconsumer_new_instance(struct ustconsumer_callbacks *callbacks, - char *sock_path) -{ - struct ustconsumer_instance *instance = - zmalloc(sizeof(struct ustconsumer_instance)); - if(!instance) { - return NULL; - } - - instance->callbacks = callbacks; - instance->quit_program = 0; - instance->is_init = 0; - instance->active_buffers = 0; - pthread_mutex_init(&instance->mutex, NULL); - - if (sock_path) { - instance->sock_path = strdup(sock_path); - } else { - instance->sock_path = NULL; - } - - return instance; -} - -static int init_ustconsumer_socket(struct ustconsumer_instance *instance) -{ - char *name; - - if (instance->sock_path) { - if (asprintf(&name, "%s", instance->sock_path) < 0) { - ERR("ustcomm_init_ustconsumer : asprintf failed (sock_path %s)", - instance->sock_path); - return -1; - } - } else { - int result; - - /* Only check if socket dir exists if we are using the default directory */ - result = ensure_dir_exists(SOCK_DIR, S_IRWXU | S_IRWXG | S_IRWXO); - if (result == -1) { - ERR("Unable to create socket directory %s", SOCK_DIR); - return -1; - } - - if (asprintf(&name, "%s/%s", SOCK_DIR, "ustconsumer") < 0) { - ERR("ustcomm_init_ustconsumer : asprintf failed (%s/ustconsumer)", - SOCK_DIR); - return -1; - } - } - - /* Set up epoll */ - instance->epoll_fd = epoll_create(MAX_EVENTS); - if (instance->epoll_fd == -1) { - ERR("epoll_create failed, start instance bailing"); - goto free_name; - } - - /* Create the named socket */ - instance->listen_sock = ustcomm_init_named_socket(name, - instance->epoll_fd); - if(!instance->listen_sock) { - ERR("error initializing named socket at %s", name); - goto close_epoll; - } - - CDS_INIT_LIST_HEAD(&instance->connections); - - free(name); - - return 0; - -close_epoll: - close(instance->epoll_fd); -free_name: - free(name); - - return -1; -} - -int ustconsumer_init_instance(struct ustconsumer_instance *instance) -{ - int result; - result = init_ustconsumer_socket(instance); - if(result == -1) { - ERR("failed to initialize socket"); - return 1; - } - instance->is_init = 1; - return 0; -} - diff --git a/deprecated/libustconsumer/lowlevel.c b/deprecated/libustconsumer/lowlevel.c deleted file mode 100644 index a54a8db..0000000 --- a/deprecated/libustconsumer/lowlevel.c +++ /dev/null @@ -1,207 +0,0 @@ -/* Copyright (C) 2009 Pierre-Marc Fournier - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include - -#include "ust/ustconsumer.h" -#include "buffers.h" -#include "tracer.h" -#include "usterr_signal_safe.h" - -/* This truncates to an offset in the buffer. */ -#define USTD_BUFFER_TRUNC(offset, bufinfo) \ - ((offset) & (~(((bufinfo)->subbuf_size*(bufinfo)->n_subbufs)-1))) - -#define LTT_MAGIC_NUMBER 0x00D6B7ED -#define LTT_REV_MAGIC_NUMBER 0xEDB7D600 - - -static void ltt_relay_print_subbuffer_errors( - struct buffer_info *buf, - long cons_off, int cpu) -{ - struct ust_buffer *ust_buf = buf->bufstruct_mem; - long cons_idx, commit_count, commit_count_mask, write_offset; - - cons_idx = SUBBUF_INDEX(cons_off, buf); - commit_count = uatomic_read(&ust_buf->commit_seq[cons_idx]); - commit_count_mask = (~0UL >> get_count_order(buf->n_subbufs)); - - /* - * No need to order commit_count and write_offset reads because we - * execute after trace is stopped when there are no readers left. - */ - write_offset = uatomic_read(&ust_buf->offset); - WARN( "LTT : unread channel %s offset is %ld " - "and cons_off : %ld (cpu %d)\n", - buf->channel, write_offset, cons_off, cpu); - /* Check each sub-buffer for non filled commit count */ - if (((commit_count - buf->subbuf_size) & commit_count_mask) - - (BUFFER_TRUNC(cons_off, buf) >> get_count_order(buf->n_subbufs)) != 0) { - ERR("LTT : %s : subbuffer %lu has non filled " - "commit count [seq] [%lu].\n", - buf->channel, cons_idx, commit_count); - } - ERR("LTT : %s : commit count : %lu, subbuf size %d\n", - buf->channel, commit_count, - buf->subbuf_size); -} - -static void ltt_relay_print_errors(struct buffer_info *buf, int cpu) -{ - struct ust_buffer *ust_buf = buf->bufstruct_mem; - long cons_off; - - for (cons_off = uatomic_read(&ust_buf->consumed); - (SUBBUF_TRUNC(uatomic_read(&ust_buf->offset), buf) - - cons_off) > 0; - cons_off = SUBBUF_ALIGN(cons_off, buf)) - ltt_relay_print_subbuffer_errors(buf, cons_off, cpu); -} - -static void ltt_relay_print_buffer_errors(struct buffer_info *buf, int cpu) -{ - struct ust_buffer *ust_buf = buf->bufstruct_mem; - - if (uatomic_read(&ust_buf->events_lost)) - ERR("channel %s: %ld events lost (cpu %d)", - buf->channel, - uatomic_read(&ust_buf->events_lost), cpu); - if (uatomic_read(&ust_buf->corrupted_subbuffers)) - ERR("channel %s : %ld corrupted subbuffers (cpu %d)", - buf->channel, - uatomic_read(&ust_buf->corrupted_subbuffers), cpu); - - ltt_relay_print_errors(buf, cpu); -} - -/* Returns the size of a subbuffer size. This is the size that - * will need to be written to disk. - * - * @subbuffer: pointer to the beginning of the subbuffer (the - * beginning of its header) - */ - -size_t subbuffer_data_size(void *subbuf) -{ - struct ltt_subbuffer_header *header = subbuf; - int reverse; - u32 data_size; - - if(header->magic_number == LTT_MAGIC_NUMBER) { - reverse = 0; - } - else if(header->magic_number == LTT_REV_MAGIC_NUMBER) { - reverse = 1; - } - else { - return -1; - } - - data_size = header->sb_size; - if(reverse) - data_size = bswap_32(data_size); - - return data_size; -} - - -void finish_consuming_dead_subbuffer(struct ustconsumer_callbacks *callbacks, struct buffer_info *buf) -{ - struct ust_buffer *ust_buf = buf->bufstruct_mem; - unsigned long n_subbufs_order = get_count_order(buf->n_subbufs); - unsigned long commit_seq_mask = (~0UL >> n_subbufs_order); - unsigned long cons_off; - int ret; - - DBG("processing dead buffer (%s)", buf->name); - DBG("consumed offset is %ld (%s)", uatomic_read(&ust_buf->consumed), - buf->name); - DBG("write offset is %ld (%s)", uatomic_read(&ust_buf->offset), - buf->name); - - /* - * Iterate on subbuffers to recover, including the one the writer - * just wrote data into. Using write position - 1 since the writer - * position points into the position that is going to be written. - */ - for (cons_off = uatomic_read(&ust_buf->consumed); - (long) (SUBBUF_TRUNC(uatomic_read(&ust_buf->offset) - 1, buf) - - cons_off) >= 0; - cons_off = SUBBUF_ALIGN(cons_off, buf)) { - /* - * commit_seq is the offset in the buffer of the end of the last sequential commit. - * Bytes beyond this limit cannot be recovered. This is a free-running counter. - */ - unsigned long commit_seq = - uatomic_read(&ust_buf->commit_seq[SUBBUF_INDEX(cons_off, buf)]); - struct ltt_subbuffer_header *header = - (struct ltt_subbuffer_header *)((char *) buf->mem - + SUBBUF_INDEX(cons_off, buf) * buf->subbuf_size); - unsigned long valid_length; - - /* Check if subbuf was fully written. This is from Mathieu's algorithm/paper. */ - if (((commit_seq - buf->subbuf_size) & commit_seq_mask) - - (USTD_BUFFER_TRUNC(uatomic_read(&ust_buf->consumed), buf) >> n_subbufs_order) == 0 - && header->data_size != 0xffffffff) { - assert(header->sb_size != 0xffffffff); - /* - * If it was fully written, we only check the data_size. - * This is the amount of valid data at the beginning of - * the subbuffer. - */ - valid_length = header->data_size; - DBG("writing full subbuffer (%ld) with valid_length = %ld", - SUBBUF_INDEX(cons_off, buf), valid_length); - } else { - /* - * If the subbuffer was not fully written, then we don't - * check data_size because it hasn't been written yet. - * Instead we check commit_seq and use it to choose a - * value for data_size. The viewer will need this value - * when parsing. Generally, this will happen only for - * the last subbuffer. However, if we have threads still - * holding reserved slots in the previous subbuffers, - * which could happen for other subbuffers prior to the - * last one. Note that when data_size is set, the - * commit_seq count is still at a value that shows the - * amount of valid data to read. It's only _after_ - * writing data_size that commit_seq is updated to - * include the end-of-buffer padding. - */ - valid_length = commit_seq & (buf->subbuf_size - 1); - DBG("writing unfull subbuffer (%ld) with valid_length = %ld", - SUBBUF_INDEX(cons_off, buf), valid_length); - header->data_size = valid_length; - header->sb_size = PAGE_ALIGN(valid_length); - } - - if (callbacks->on_read_partial_subbuffer) { - ret = callbacks->on_read_partial_subbuffer(callbacks, buf, - SUBBUF_INDEX(cons_off, buf), - valid_length); - if (ret < 0) - break; /* Error happened */ - } - } - /* Increment the consumed offset */ - uatomic_set(&ust_buf->consumed, cons_off); - ltt_relay_print_buffer_errors(buf, buf->channel_cpu); -} - diff --git a/deprecated/libustconsumer/lowlevel.h b/deprecated/libustconsumer/lowlevel.h deleted file mode 100644 index 6ae6476..0000000 --- a/deprecated/libustconsumer/lowlevel.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * lowlevel libustd header file - * - * Copyright 2005-2010 - - * Mathieu Desnoyers - * Copyright 2010- - * Oumarou Dicko - * Michael Sills-Lavoie - * Alexis Halle - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LOWLEVEL_H -#define LOWLEVEL_H - -#include "ust/ustconsumer.h" - -void finish_consuming_dead_subbuffer(struct ustconsumer_callbacks *callbacks, struct buffer_info *buf); -size_t subbuffer_data_size(void *subbuf); - -#endif /* LOWLEVEL_H */ - diff --git a/deprecated/libustctl/Makefile.am b/deprecated/libustctl/Makefile.am deleted file mode 100644 index bc7526b..0000000 --- a/deprecated/libustctl/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libustcomm -AM_CFLAGS = -fno-strict-aliasing - -lib_LTLIBRARIES = libustctl.la - -libustctl_la_SOURCES = \ - libustctl.c - -libustctl_la_LDFLAGS = -no-undefined -version-info 0:0:0 - -libustctl_la_LIBADD = \ - $(top_builddir)/libustcomm/libustcomm.la - -libustctl_la_CFLAGS = -DUST_COMPONENT="libustctl" -fno-strict-aliasing diff --git a/deprecated/libustctl/README b/deprecated/libustctl/README deleted file mode 100644 index fd4cc97..0000000 --- a/deprecated/libustctl/README +++ /dev/null @@ -1,2 +0,0 @@ -libustctl is a library that provides an API and its implementation to send -commands to traceable processes. diff --git a/deprecated/libustctl/libustctl.c b/deprecated/libustctl/libustctl.c deleted file mode 100644 index 4e6c495..0000000 --- a/deprecated/libustctl/libustctl.c +++ /dev/null @@ -1,770 +0,0 @@ -/* Copyright (C) 2009 Pierre-Marc Fournier, Philippe Proulx-Barrette - * Copyright (C) 2011 Ericsson AB - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include - -#include "ustcomm.h" -#include "ust/ustctl.h" -#include "usterr.h" - -static int do_cmd(int sock, - const struct ustcomm_header *req_header, - const char *req_data, - struct ustcomm_header *res_header, - char **res_data) -{ - int result, saved_errno = 0; - char *recv_buf; - - recv_buf = zmalloc(USTCOMM_BUFFER_SIZE); - if (!recv_buf) { - saved_errno = ENOMEM; - goto out; - } - - result = ustcomm_req(sock, req_header, req_data, res_header, recv_buf); - if (result > 0) { - saved_errno = -res_header->result; - if (res_header->size == 0 || saved_errno > 0) { - free(recv_buf); - } else { - if (res_data) { - *res_data = recv_buf; - } else { - free(recv_buf); - } - } - } else { - ERR("ustcomm req failed"); - if (result == 0) { - saved_errno = ENOTCONN; - } else { - saved_errno = -result; - } - free(recv_buf); - } - -out: - errno = saved_errno; - if (errno) { - return -1; - } - - return 0; -} - -int ustctl_connect_pid(pid_t pid) -{ - int sock; - - if (ustcomm_connect_app(pid, &sock)) { - ERR("could not connect to PID %u", (unsigned int) pid); - errno = ENOTCONN; - return -1; - } - - return sock; -} - -static int realloc_pid_list(pid_t **pid_list, unsigned int *pid_list_size) -{ - pid_t *new_pid_list; - unsigned int new_pid_list_size = 2 * *pid_list_size; - - new_pid_list = realloc(*pid_list, - new_pid_list_size * sizeof(pid_t)); - if (!*new_pid_list) { - return -1; - } - - *pid_list = new_pid_list; - *pid_list_size = new_pid_list_size; - - return 0; -} - -static int get_pids_in_dir(DIR *dir, pid_t **pid_list, - unsigned int *pid_list_index, - unsigned int *pid_list_size) -{ - struct dirent *dirent; - pid_t read_pid; - - while ((dirent = readdir(dir))) { - if (!strcmp(dirent->d_name, ".") || - !strcmp(dirent->d_name, "..") || - !strcmp(dirent->d_name, "ust-consumer") || - dirent->d_type == DT_DIR) { - - continue; - } - - if (ustcomm_is_socket_live(dirent->d_name, &read_pid)) { - - (*pid_list)[(*pid_list_index)++] = (long) read_pid; - - if (*pid_list_index == *pid_list_size) { - if (realloc_pid_list(pid_list, pid_list_size)) { - return -1; - } - } - } - } - - (*pid_list)[*pid_list_index] = 0; /* Array end */ - - return 0; -} - -static pid_t *get_pids_non_root(void) -{ - char *dir_name; - DIR *dir; - unsigned int pid_list_index = 0, pid_list_size = 1; - pid_t *pid_list = NULL; - - dir_name = ustcomm_user_sock_dir(); - if (!dir_name) { - return NULL; - } - - dir = opendir(dir_name); - if (!dir) { - goto free_dir_name; - } - - pid_list = malloc(pid_list_size * sizeof(pid_t)); - if (!pid_list) { - goto close_dir; - } - - if (get_pids_in_dir(dir, &pid_list, &pid_list_index, &pid_list_size)) { - /* if any errors are encountered, force freeing of the list */ - pid_list[0] = 0; - } - -close_dir: - closedir(dir); - -free_dir_name: - free(dir_name); - - return pid_list; -} - -static pid_t *get_pids_root(void) -{ - char *dir_name; - DIR *tmp_dir, *dir; - unsigned int pid_list_index = 0, pid_list_size = 1; - pid_t *pid_list = NULL; - struct dirent *dirent; - int result; - - tmp_dir = opendir(USER_TMP_DIR); - if (!tmp_dir) { - return NULL; - } - - pid_list = malloc(pid_list_size * sizeof(pid_t)); - if (!pid_list) { - goto close_tmp_dir; - } - - while ((dirent = readdir(tmp_dir))) { - /* Compare the dir to check for the USER_SOCK_DIR_BASE prefix */ - if (!strncmp(dirent->d_name, USER_SOCK_DIR_BASE, - strlen(USER_SOCK_DIR_BASE))) { - - if (asprintf(&dir_name, USER_TMP_DIR "/%s", - dirent->d_name) < 0) { - goto close_tmp_dir; - } - - dir = opendir(dir_name); - - free(dir_name); - - if (!dir) { - continue; - } - - result = get_pids_in_dir(dir, &pid_list, &pid_list_index, - &pid_list_size); - - closedir(dir); - - if (result) { - /* - * if any errors are encountered, - * force freeing of the list - */ - pid_list[0] = 0; - break; - } - } - } - -close_tmp_dir: - closedir(tmp_dir); - - return pid_list; -} - -pid_t *ustctl_get_online_pids(void) -{ - pid_t *pid_list; - - if (geteuid()) { - pid_list = get_pids_non_root(); - } else { - pid_list = get_pids_root(); - } - - if (pid_list && pid_list[0] == 0) { - /* No PID at all */ - free(pid_list); - pid_list = NULL; - } - - return pid_list; -} - -/** - * Sets ust_marker state (USTCTL_MS_ON or USTCTL_MS_OFF). - * - * @param mn Marker name - * @param state Marker's new state - * @param pid Traced process ID - * @return 0 if successful, or errors {USTCTL_ERR_GEN, USTCTL_ERR_ARG} - */ -int ustctl_set_ust_marker_state(int sock, const char *trace, const char *channel, - const char *ust_marker, int state) -{ - struct ustcomm_header req_header, res_header; - struct ustcomm_ust_marker_info ust_marker_inf; - int result; - - result = ustcomm_pack_ust_marker_info(&req_header, - &ust_marker_inf, - trace, - channel, - ust_marker); - if (result < 0) { - errno = -result; - return -1; - } - - req_header.command = state ? ENABLE_MARKER : DISABLE_MARKER; - - return do_cmd(sock, &req_header, (char *)&ust_marker_inf, - &res_header, NULL); -} - -/** - * Set subbuffer size. - * - * @param channel_size Channel name and size - * @param pid Traced process ID - * @return 0 if successful, or error - */ -int ustctl_set_subbuf_size(int sock, const char *trace, const char *channel, - unsigned int subbuf_size) -{ - struct ustcomm_header req_header, res_header; - struct ustcomm_channel_info ch_inf; - int result; - - result = ustcomm_pack_channel_info(&req_header, - &ch_inf, - trace, - channel); - if (result < 0) { - errno = -result; - return -1; - } - - req_header.command = SET_SUBBUF_SIZE; - ch_inf.subbuf_size = subbuf_size; - - return do_cmd(sock, &req_header, (char *)&ch_inf, - &res_header, NULL); -} - -/** - * Set subbuffer num. - * - * @param channel_num Channel name and num - * @param pid Traced process ID - * @return 0 if successful, or error - */ -int ustctl_set_subbuf_num(int sock, const char *trace, const char *channel, - unsigned int num) -{ - struct ustcomm_header req_header, res_header; - struct ustcomm_channel_info ch_inf; - int result; - - result = ustcomm_pack_channel_info(&req_header, - &ch_inf, - trace, - channel); - if (result < 0) { - errno = -result; - return -1; - } - - req_header.command = SET_SUBBUF_NUM; - ch_inf.subbuf_num = num; - - return do_cmd(sock, &req_header, (char *)&ch_inf, - &res_header, NULL); - -} - - -static int ustctl_get_subbuf_num_size(int sock, const char *trace, const char *channel, - int *num, int *size) -{ - struct ustcomm_header req_header, res_header; - struct ustcomm_channel_info ch_inf, *ch_inf_res; - int result; - - - result = ustcomm_pack_channel_info(&req_header, - &ch_inf, - trace, - channel); - if (result < 0) { - errno = -result; - return -1; - } - - req_header.command = GET_SUBBUF_NUM_SIZE; - - result = do_cmd(sock, &req_header, (char *)&ch_inf, - &res_header, (char **)&ch_inf_res); - if (result < 0) { - return -1; - } - - *num = ch_inf_res->subbuf_num; - *size = ch_inf_res->subbuf_size; - - free(ch_inf_res); - - return 0; -} - -/** - * Get subbuffer num. - * - * @param channel Channel name - * @param pid Traced process ID - * @return subbuf cnf if successful, or error - */ -int ustctl_get_subbuf_num(int sock, const char *trace, const char *channel) -{ - int num, size, result; - - result = ustctl_get_subbuf_num_size(sock, trace, channel, - &num, &size); - if (result < 0) { - errno = -result; - return -1; - } - - return num; -} - -/** - * Get subbuffer size. - * - * @param channel Channel name - * @param pid Traced process ID - * @return subbuf size if successful, or error - */ -int ustctl_get_subbuf_size(int sock, const char *trace, const char *channel) -{ - int num, size, result; - - result = ustctl_get_subbuf_num_size(sock, trace, channel, - &num, &size); - if (result < 0) { - errno = -result; - return -1; - } - - return size; -} - -static int do_trace_cmd(int sock, const char *trace, int command) -{ - struct ustcomm_header req_header, res_header; - struct ustcomm_single_field trace_inf; - int result; - - result = ustcomm_pack_single_field(&req_header, - &trace_inf, - trace); - if (result < 0) { - errno = -result; - return -1; - } - - req_header.command = command; - - return do_cmd(sock, &req_header, (char *)&trace_inf, &res_header, NULL); -} - -/** - * Destroys an UST trace according to a PID. - * - * @param pid Traced process ID - * @return 0 if successful, or error USTCTL_ERR_GEN - */ -int ustctl_destroy_trace(int sock, const char *trace) -{ - return do_trace_cmd(sock, trace, DESTROY_TRACE); -} - -/** - * Starts an UST trace (and setups it) according to a PID. - * - * @param pid Traced process ID - * @return 0 if successful, or error USTCTL_ERR_GEN - */ -int ustctl_setup_and_start(int sock, const char *trace) -{ - return do_trace_cmd(sock, trace, START); -} - -/** - * Creates an UST trace according to a PID. - * - * @param pid Traced process ID - * @return 0 if successful, or error USTCTL_ERR_GEN - */ -int ustctl_create_trace(int sock, const char *trace) -{ - return do_trace_cmd(sock, trace, CREATE_TRACE); -} - -/** - * Starts an UST trace according to a PID. - * - * @param pid Traced process ID - * @return 0 if successful, or error USTCTL_ERR_GEN - */ -int ustctl_start_trace(int sock, const char *trace) -{ - return do_trace_cmd(sock, trace, START_TRACE); -} - -/** - * Alloc an UST trace according to a PID. - * - * @param pid Traced process ID - * @return 0 if successful, or error USTCTL_ERR_GEN - */ -int ustctl_alloc_trace(int sock, const char *trace) -{ - return do_trace_cmd(sock, trace, ALLOC_TRACE); -} - - -int ustctl_force_switch(int sock, const char *trace) -{ - return do_trace_cmd(sock, trace, FORCE_SUBBUF_SWITCH); -} - -/** - * Stops an UST trace according to a PID. - * - * @param pid Traced process ID - * @return 0 if successful, or error USTCTL_ERR_GEN - */ -int ustctl_stop_trace(int sock, const char *trace) -{ - return do_trace_cmd(sock, trace, STOP_TRACE); -} - -/** - * Counts newlines ('\n') in a string. - * - * @param str String to search in - * @return Total newlines count - */ -unsigned int ustctl_count_nl(const char *str) -{ - unsigned int i = 0, tot = 0; - - while (str[i] != '\0') { - if (str[i] == '\n') { - ++tot; - } - ++i; - } - - return tot; -} - -/** - * Frees a CMSF array. - * - * @param cmsf CMSF array to free - * @return 0 if successful, or error USTCTL_ERR_ARG - */ -int ustctl_free_cmsf(struct ust_marker_status *cmsf) -{ - if (cmsf == NULL) { - return USTCTL_ERR_ARG; - } - - unsigned int i = 0; - while (cmsf[i].channel != NULL) { - free(cmsf[i].channel); - free(cmsf[i].ust_marker); - free(cmsf[i].fs); - ++i; - } - free(cmsf); - - return 0; -} - -/** - * Gets channel/ust_marker/state/format string for a given PID. - * - * @param cmsf Pointer to CMSF array to be filled (callee allocates, caller - * frees with `ustctl_free_cmsf') - * @param pid Targeted PID - * @return 0 if successful, or -1 on error - */ -int ustctl_get_cmsf(int sock, struct ust_marker_status **cmsf) -{ - struct ustcomm_header req_header, res_header; - char *big_str = NULL; - int result; - struct ust_marker_status *tmp_cmsf = NULL; - unsigned int i = 0, cmsf_ind = 0; - - if (cmsf == NULL) { - return -1; - } - - req_header.command = LIST_MARKERS; - req_header.size = 0; - - result = ustcomm_send(sock, &req_header, NULL); - if (result <= 0) { - PERROR("error while requesting ust_marker list"); - return -1; - } - - result = ustcomm_recv_alloc(sock, &res_header, &big_str); - if (result <= 0) { - ERR("error while receiving ust_marker list"); - return -1; - } - - tmp_cmsf = (struct ust_marker_status *) zmalloc(sizeof(struct ust_marker_status) * - (ustctl_count_nl(big_str) + 1)); - if (tmp_cmsf == NULL) { - ERR("Failed to allocate CMSF array"); - return -1; - } - - /* Parse received reply string (format: "[chan]/[mark] [st] [fs]"): */ - while (big_str[i] != '\0') { - char state; - - sscanf(big_str + i, "ust_marker: %a[^/]/%a[^ ] %c %a[^\n]", - &tmp_cmsf[cmsf_ind].channel, - &tmp_cmsf[cmsf_ind].ust_marker, - &state, - &tmp_cmsf[cmsf_ind].fs); - tmp_cmsf[cmsf_ind].state = (state == USTCTL_MS_CHR_ON ? - USTCTL_MS_ON : USTCTL_MS_OFF); /* Marker state */ - - while (big_str[i] != '\n') { - ++i; /* Go to next '\n' */ - } - ++i; /* Skip current pointed '\n' */ - ++cmsf_ind; - } - tmp_cmsf[cmsf_ind].channel = NULL; - tmp_cmsf[cmsf_ind].ust_marker = NULL; - tmp_cmsf[cmsf_ind].fs = NULL; - - *cmsf = tmp_cmsf; - - free(big_str); - return 0; -} - -/** - * Frees a TES array. - * - * @param tes TES array to free - * @return 0 if successful, or error USTCTL_ERR_ARG - */ -int ustctl_free_tes(struct trace_event_status *tes) -{ - if (tes == NULL) { - return USTCTL_ERR_ARG; - } - - unsigned int i = 0; - while (tes[i].name != NULL) { - free(tes[i].name); - ++i; - } - free(tes); - - return 0; -} - -/** - * Gets trace_events string for a given PID. - * - * @param tes Pointer to TES array to be filled (callee allocates, caller - * frees with `ustctl_free_tes') - * @param pid Targeted PID - * @return 0 if successful, or -1 on error - */ -int ustctl_get_tes(int sock, struct trace_event_status **tes) -{ - struct ustcomm_header req_header, res_header; - char *big_str = NULL; - int result; - struct trace_event_status *tmp_tes = NULL; - unsigned int i = 0, tes_ind = 0; - - if (tes == NULL) { - return -1; - } - - req_header.command = LIST_TRACE_EVENTS; - req_header.size = 0; - - result = ustcomm_send(sock, &req_header, NULL); - if (result != 1) { - ERR("error while requesting trace_event list"); - return -1; - } - - result = ustcomm_recv_alloc(sock, &res_header, &big_str); - if (result != 1) { - ERR("error while receiving ust_marker list"); - return -1; - } - - tmp_tes = (struct trace_event_status *) - zmalloc(sizeof(struct trace_event_status) * - (ustctl_count_nl(big_str) + 1)); - if (tmp_tes == NULL) { - ERR("Failed to allocate TES array"); - return -1; - } - - /* Parse received reply string (format: "[name]"): */ - while (big_str[i] != '\0') { - sscanf(big_str + i, "trace_event: %a[^\n]", - &tmp_tes[tes_ind].name); - while (big_str[i] != '\n') { - ++i; /* Go to next '\n' */ - } - ++i; /* Skip current pointed '\n' */ - ++tes_ind; - } - tmp_tes[tes_ind].name = NULL; - - *tes = tmp_tes; - - free(big_str); - return 0; -} - -/** - * Set sock path - * - * @param sock_path Sock path - * @param pid Traced process ID - * @return 0 if successful, or error - */ -int ustctl_set_sock_path(int sock, const char *sock_path) -{ - int result; - struct ustcomm_header req_header, res_header; - struct ustcomm_single_field sock_path_msg; - - result = ustcomm_pack_single_field(&req_header, - &sock_path_msg, - sock_path); - if (result < 0) { - errno = -result; - return -1; - } - - req_header.command = SET_SOCK_PATH; - - return do_cmd(sock, &req_header, (char *)&sock_path_msg, - &res_header, NULL); -} - -/** - * Get sock path - * - * @param sock_path Pointer to where the sock path will be returned - * @param pid Traced process ID - * @return 0 if successful, or error - */ -int ustctl_get_sock_path(int sock, char **sock_path) -{ - int result; - struct ustcomm_header req_header, res_header; - struct ustcomm_single_field *sock_path_msg; - - req_header.command = GET_SOCK_PATH; - req_header.size = 0; - - result = do_cmd(sock, &req_header, NULL, &res_header, - (char **)&sock_path_msg); - if (result < 0) { - return -1; - } - - result = ustcomm_unpack_single_field(sock_path_msg); - if (result < 0) { - return result; - } - - *sock_path = strdup(sock_path_msg->field); - - free(sock_path_msg); - - return 0; -} diff --git a/deprecated/ust-consumerd/Makefile.am b/deprecated/ust-consumerd/Makefile.am deleted file mode 100644 index 01e3b82..0000000 --- a/deprecated/ust-consumerd/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/libust -I$(top_srcdir)/libustcomm \ - -I$(top_srcdir)/include -I$(top_srcdir)/libustconsumer -AM_CFLAGS = -fno-strict-aliasing - -bin_PROGRAMS = ust-consumerd - -ust_consumerd_SOURCES = ust-consumerd.c - -ust_consumerd_LDADD = \ - $(top_builddir)/snprintf/libustsnprintf.la \ - $(top_builddir)/libustcomm/libustcomm.la \ - $(top_builddir)/libustconsumer/libustconsumer.la - -ust_consumerd_CFLAGS = -DUST_COMPONENT=ust-consumerd -fno-strict-aliasing diff --git a/deprecated/ust-consumerd/README b/deprecated/ust-consumerd/README deleted file mode 100644 index 6df4015..0000000 --- a/deprecated/ust-consumerd/README +++ /dev/null @@ -1,3 +0,0 @@ -This is ust-consumerd, the UST consumer daemon. - -This daemon is used to collect the traces for the traced programs and write them to disk. diff --git a/deprecated/ust-consumerd/ust-consumerd.c b/deprecated/ust-consumerd/ust-consumerd.c deleted file mode 100644 index 0761253..0000000 --- a/deprecated/ust-consumerd/ust-consumerd.c +++ /dev/null @@ -1,516 +0,0 @@ -/* Copyright (C) 2009 Pierre-Marc Fournier - * 2010 Alexis Halle - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "ust/ustconsumer.h" -#include "../libustconsumer/lowlevel.h" -#include "usterr.h" - -char *sock_path=NULL; -char *trace_path=NULL; -int daemon_mode = 0; -char *pidfile = NULL; - -struct ustconsumer_instance *instance; - -struct buffer_info_local { - /* output file */ - int file_fd; - /* the offset we must truncate to, to unput the last subbuffer */ - off_t previous_offset; -}; - -static int write_pidfile(const char *file_name, pid_t pid) -{ - FILE *pidfp; - - pidfp = fopen(file_name, "w"); - if(!pidfp) { - PERROR("fopen (%s)", file_name); - WARN("killing child process"); - return -1; - } - - fprintf(pidfp, "%d\n", pid); - - fclose(pidfp); - - return 0; -} - -int create_dir_if_needed(char *dir) -{ - int result; - result = mkdir(dir, 0777); - if(result == -1) { - if(errno != EEXIST) { - PERROR("mkdir"); - return -1; - } - } - - return 0; -} - -int unwrite_last_subbuffer(struct buffer_info *buf) -{ - int result; - struct buffer_info_local *buf_local = buf->user_data; - - result = ftruncate(buf_local->file_fd, buf_local->previous_offset); - if(result == -1) { - PERROR("ftruncate"); - return -1; - } - - result = lseek(buf_local->file_fd, buf_local->previous_offset, SEEK_SET); - if(result == (int)(off_t)-1) { - PERROR("lseek"); - return -1; - } - - return 0; -} - -int write_current_subbuffer(struct buffer_info *buf) -{ - int result; - struct buffer_info_local *buf_local = buf->user_data; - - void *subbuf_mem = buf->mem + (buf->consumed_old & (buf->n_subbufs * buf->subbuf_size-1)); - - size_t cur_sb_size = subbuffer_data_size(subbuf_mem); - - off_t cur_offset = lseek(buf_local->file_fd, 0, SEEK_CUR); - if(cur_offset == (off_t)-1) { - PERROR("lseek"); - return -1; - } - - buf_local->previous_offset = cur_offset; - DBG("previous_offset: %ld", cur_offset); - - result = patient_write(buf_local->file_fd, subbuf_mem, cur_sb_size); - if(result == -1) { - PERROR("write"); - return -1; - } - - return 0; -} - -int on_read_subbuffer(struct ustconsumer_callbacks *data, struct buffer_info *buf) -{ - return write_current_subbuffer(buf); -} - -int on_read_partial_subbuffer(struct ustconsumer_callbacks *data, struct buffer_info *buf, - long subbuf_index, unsigned long valid_length) -{ - struct buffer_info_local *buf_local = buf->user_data; - char *tmp; - int result; - unsigned long pad_size; - - result = patient_write(buf_local->file_fd, buf->mem + subbuf_index * buf->subbuf_size, valid_length); - if(result == -1) { - ERR("Error writing to buffer file"); - return result; - } - - /* pad with empty bytes */ - pad_size = PAGE_ALIGN(valid_length)-valid_length; - if(pad_size) { - tmp = zmalloc(pad_size); - result = patient_write(buf_local->file_fd, tmp, pad_size); - if(result == -1) { - ERR("Error writing to buffer file"); - return result; - } - free(tmp); - } - return result; -} - -int on_open_buffer(struct ustconsumer_callbacks *data, struct buffer_info *buf) -{ - char *tmp; - int result; - int fd; - struct buffer_info_local *buf_local = - zmalloc(sizeof(struct buffer_info_local)); - - if(!buf_local) { - ERR("could not allocate buffer_info_local struct"); - return 1; - } - - buf->user_data = buf_local; - - /* open file for output */ - if(!trace_path) { - /* Only create the directory if using the default path, because - * of the risk of typo when using trace path override. We don't - * want to risk creating plenty of useless directories in that case. - */ - result = create_dir_if_needed(USTCONSUMER_DEFAULT_TRACE_PATH); - if(result == -1) { - ERR("could not create directory %s", USTCONSUMER_DEFAULT_TRACE_PATH); - return 1; - } - - trace_path = USTCONSUMER_DEFAULT_TRACE_PATH; - } - - if (asprintf(&tmp, "%s/%u_%" PRId64 "", trace_path, buf->pid, buf->pidunique) < 0) { - ERR("on_open_buffer : asprintf failed (%s/%u_%" PRId64 ")", - trace_path, buf->pid, buf->pidunique); - return 1; - } - result = create_dir_if_needed(tmp); - if(result == -1) { - ERR("could not create directory %s", tmp); - free(tmp); - return 1; - } - free(tmp); - - if (asprintf(&tmp, "%s/%u_%" PRId64 "/%s", trace_path, buf->pid, buf->pidunique, buf->name) < 0) { - ERR("on_open_buffer : asprintf failed (%s/%u_%" PRId64 "/%s)", - trace_path, buf->pid, buf->pidunique, buf->name); - return 1; - } -again: - result = fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 00600); - if (result == -1 && errno == EINTR) - goto again; - - if(result == -1) { - PERROR("open"); - ERR("failed opening trace file %s", tmp); - return 1; - } - buf_local->file_fd = fd; - free(tmp); - - return 0; -} - -int on_close_buffer(struct ustconsumer_callbacks *data, struct buffer_info *buf) -{ - struct buffer_info_local *buf_local = buf->user_data; - int result; - -again: - result = close(buf_local->file_fd); - if (result == -1 && errno == EINTR) - goto again; - free(buf_local); - if(result == -1) { - PERROR("close"); - } - return 0; -} - -int on_put_error(struct ustconsumer_callbacks *data, struct buffer_info *buf) -{ - return unwrite_last_subbuffer(buf); -} - -struct ustconsumer_callbacks *new_callbacks() -{ - struct ustconsumer_callbacks *callbacks = - zmalloc(sizeof(struct ustconsumer_callbacks)); - - if(!callbacks) - return NULL; - - callbacks->on_open_buffer = on_open_buffer; - callbacks->on_close_buffer = on_close_buffer; - callbacks->on_read_subbuffer = on_read_subbuffer; - callbacks->on_read_partial_subbuffer = on_read_partial_subbuffer; - callbacks->on_put_error = on_put_error; - callbacks->on_new_thread = NULL; - callbacks->on_close_thread = NULL; - callbacks->on_trace_end = NULL; - - return callbacks; - -} - -int is_directory(const char *dir) -{ - int result; - struct stat st; - - result = stat(dir, &st); - if(result == -1) { - PERROR("stat"); - return 0; - } - - if(!S_ISDIR(st.st_mode)) { - return 0; - } - - return 1; -} - -void usage(void) -{ - fprintf(stderr, "Usage:\nust-consumerd OPTIONS\n\nOptions:\n" - "\t-h\t\tDisplay this usage.\n" - "\t-o DIR\t\tSpecify the directory where to output the traces.\n" - "\t-s PATH\t\tSpecify the path to use for the daemon socket.\n" - "\t-d\t\tStart as a daemon.\n" - "\t--pidfile FILE\tWrite the PID in this file (when using -d).\n"); -} - -int parse_args(int argc, char **argv) -{ - int c; - - while (1) { - int option_index = 0; - static struct option long_options[] = { - {"pidfile", 1, 0, 'p'}, - {"help", 0, 0, 'h'}, - {"version", 0, 0, 'V'}, - {0, 0, 0, 0} - }; - - c = getopt_long(argc, argv, "hs:o:d", long_options, &option_index); - if (c == -1) - break; - - switch (c) { - case 0: - printf("option %s", long_options[option_index].name); - if (optarg) - printf(" with arg %s", optarg); - printf("\n"); - break; - case 's': - sock_path = optarg; - break; - case 'o': - trace_path = optarg; - if(!is_directory(trace_path)) { - ERR("Not a valid directory. (%s)", trace_path); - return -1; - } - break; - case 'd': - daemon_mode = 1; - break; - case 'p': - pidfile = strdup(optarg); - break; - case 'h': - usage(); - exit(0); - case 'V': - printf("Version 0.0\n"); - break; - - default: - /* unknown option or other error; error is - printed by getopt, just return */ - return -1; - } - } - - return 0; -} - -void sigterm_handler(int sig) -{ - ustconsumer_stop_instance(instance, 0); -} - -int start_ustconsumer(int fd) -{ - int result; - sigset_t sigset; - struct sigaction sa; - - struct ustconsumer_callbacks *callbacks = new_callbacks(); - if(!callbacks) { - PERROR("new_callbacks"); - return 1; - } - - result = sigemptyset(&sigset); - if(result == -1) { - PERROR("sigemptyset"); - return 1; - } - sa.sa_handler = sigterm_handler; - sa.sa_mask = sigset; - sa.sa_flags = 0; - result = sigaction(SIGTERM, &sa, NULL); - if(result == -1) { - PERROR("sigaction"); - return 1; - } - result = sigaction(SIGINT, &sa, NULL); - if(result == -1) { - PERROR("sigaction"); - return 1; - } - - instance = ustconsumer_new_instance(callbacks, sock_path); - if(!instance) { - ERR("failed to create ustconsumer instance"); - return 1; - } - - result = ustconsumer_init_instance(instance); - if(result) { - ERR("failed to initialize ustconsumer instance"); - return 1; - } - - /* setup handler for SIGPIPE */ - result = sigemptyset(&sigset); - if(result == -1) { - PERROR("sigemptyset"); - return 1; - } - result = sigaddset(&sigset, SIGPIPE); - if(result == -1) { - PERROR("sigaddset"); - return 1; - } - result = sigprocmask(SIG_BLOCK, &sigset, NULL); - if(result == -1) { - PERROR("sigprocmask"); - return 1; - } - - /* Write pidfile */ - if(pidfile) { - result = write_pidfile(pidfile, getpid()); - if(result == -1) { - ERR("failed to write pidfile"); - return 1; - } - } - - /* Notify parent that we are successfully started. */ - if(fd != -1) { - /* write any one character */ - result = write(fd, "!", 1); - if(result == -1) { - PERROR("write"); - return -1; - } - if(result != 1) { - ERR("Problem sending confirmation of daemon start to parent"); - return -1; - } - result = close(fd); - if(result == -1) { - PERROR("close"); - } - } - - ustconsumer_start_instance(instance); - - free(callbacks); - - return 0; -} - -int start_ustconsumer_daemon() -{ - int result; - int fd[2]; - pid_t child_pid; - - result = pipe(fd); - - result = child_pid = fork(); - if(result == -1) { - PERROR("fork"); - return -1; - } - else if(result == 0) { - return start_ustconsumer(fd[1]); - } - else { - char buf; - - result = read(fd[0], &buf, 1); - if(result == -1) { - PERROR("read"); - return -1; - } - if(result != 1) { - ERR("did not receive valid confirmation that the daemon is started"); - return -1; - } - - result = close(fd[0]); - if(result == -1) { - PERROR("close"); - } - - DBG("The daemon is now successfully started"); - } - - /* Wait for confirmation that the server is ready. */ - - - return 0; -} - -int main(int argc, char **argv) -{ - int result; - - result = parse_args(argc, argv); - if(result == -1) { - exit(1); - } - - if(daemon_mode) { - result = start_ustconsumer_daemon(); - } - else { - result = start_ustconsumer(-1); - } - - return result; -} diff --git a/deprecated/ustconsumer.h b/deprecated/ustconsumer.h deleted file mode 100644 index 8c53488..0000000 --- a/deprecated/ustconsumer.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - * libustconsumer header file - * - * Copyright 2005-2010 - - * Mathieu Desnoyers - * Copyright 2010- - * Oumarou Dicko - * Michael Sills-Lavoie - * Alexis Halle - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _USTCONSUMER_H -#define _USTCONSUMER_H - -#include -#include -#include -#include - -#define USTCONSUMER_DEFAULT_TRACE_PATH "/tmp/usttrace" - -struct ustcomm_sock; - -struct buffer_info { - char *name; - char *trace; - char *channel; - int channel_cpu; - - pid_t pid; - int app_sock; - /* The pipe file descriptor */ - int pipe_fd; - - int shmid; - int bufstruct_shmid; - - /* the buffer memory */ - void *mem; - /* buffer size */ - int memlen; - /* number of subbuffers in buffer */ - int n_subbufs; - /* size of each subbuffer */ - int subbuf_size; - /* subbuf size count order */ - int subbuf_size_order; - /* alloc size of all subbuf */ - int alloc_size; - - /* the buffer information struct */ - void *bufstruct_mem; - - long consumed_old; - - int64_t pidunique; - - void *user_data; -}; - -struct ustconsumer_callbacks; - -/** - * struct ustconsumer_instance - Contains the data associated with a trace instance. - * The lib user can read but MUST NOT change any attributes but callbacks. - * @callbacks: Contains the necessary callbacks for a tracing session. - */ -struct ustconsumer_instance { - struct ustconsumer_callbacks *callbacks; - int quit_program; - int is_init; - struct cds_list_head connections; - int epoll_fd; - struct ustcomm_sock *listen_sock; - char *sock_path; - pthread_mutex_t mutex; - int active_buffers; - int active_threads; -}; - -/** -* struct ustconsumer_callbacks - Contains the necessary callbacks for a tracing -* session. The user can set the unnecessary functions to NULL if he does not -* need them. -*/ -struct ustconsumer_callbacks { - /** - * on_open_buffer - Is called after a buffer is attached to process memory - * - * @data: pointer to the callbacks structure that has been passed to the - * library. - * @buf: structure that contains the data associated with the buffer - * - * Returns 0 if the callback succeeds else not 0. - * - * It has to be thread safe, because it is called by many threads. - */ - int (*on_open_buffer)(struct ustconsumer_callbacks *data, - struct buffer_info *buf); - - /** - * on_close_buffer - Is called after a buffer is detached from process memory - * - * @data: pointer to the callbacks structure that has been passed to the - * library. - * @buf: structure that contains the data associated with the buffer - * - * Returns 0 if the callback succeeds else not 0. - * - * It has to be thread safe, because it is called by many threads. - */ - int (*on_close_buffer)(struct ustconsumer_callbacks *data, - struct buffer_info *buf); - - /** - * on_read_subbuffer - Is called after a subbuffer is a reserved. - * - * @data: pointer to the callbacks structure that has been passed to the - * library. - * @buf: structure that contains the data associated with the buffer - * - * Returns 0 if the callback succeeds else not 0. - * - * It has to be thread safe, because it is called by many threads. - */ - int (*on_read_subbuffer)(struct ustconsumer_callbacks *data, - struct buffer_info *buf); - - /** - * on_read_partial_subbuffer - Is called when an incomplete subbuffer - * is being salvaged from an app crash - * - * @data: pointer to the callbacks structure that has been passed to the - * library. - * @buf: structure that contains the data associated with the buffer - * @subbuf_index: index of the subbuffer to read in the buffer - * @valid_length: number of bytes considered safe to read - * - * Returns 0 if the callback succeeds else not 0. - * - * It has to be thread safe, because it is called by many threads. - */ - int (*on_read_partial_subbuffer)(struct ustconsumer_callbacks *data, - struct buffer_info *buf, - long subbuf_index, - unsigned long valid_length); - - /** - * on_put_error - Is called when a put error has occured and the last - * subbuffer read is no longer safe to keep - * - * @data: pointer to the callbacks structure that has been passed to the - * library. - * @buf: structure that contains the data associated with the buffer - * - * Returns 0 if the callback succeeds else not 0. - * - * It has to be thread safe, because it is called by many threads. - */ - int (*on_put_error)(struct ustconsumer_callbacks *data, - struct buffer_info *buf); - - /** - * on_new_thread - Is called when a new thread is created - * - * @data: pointer to the callbacks structure that has been passed to the - * library. - * - * Returns 0 if the callback succeeds else not 0. - * - * It has to be thread safe, because it is called by many threads. - */ - int (*on_new_thread)(struct ustconsumer_callbacks *data); - - /** - * on_close_thread - Is called just before a thread is destroyed - * - * @data: pointer to the callbacks structure that has been passed to the - * library. - * - * Returns 0 if the callback succeeds else not 0. - * - * It has to be thread safe, because it is called by many threads. - */ - int (*on_close_thread)(struct ustconsumer_callbacks *data); - - /** - * on_trace_end - Is called at the very end of the tracing session. At - * this time, everything has been closed and the threads have - * been destroyed. - * - * @instance: pointer to the instance structure that has been passed to - * the library. - * - * Returns 0 if the callback succeeds else not 0. - * - * After this callback is called, no other callback will be called - * again and the tracing instance will be deleted automatically by - * libustconsumer. After this call, the user must not use the libustconsumer instance. - */ - int (*on_trace_end)(struct ustconsumer_instance *instance); - - /** - * The library's data. - */ - void *user_data; -}; - -/** - * ustconsumer_new_instance - Is called to create a new tracing session. - * - * @callbacks: Pointer to a callbacks structure that contain the user - * callbacks and data. - * @sock_path: Path to the socket used for communication with the traced app - * - * Returns the instance if the function succeeds else NULL. - */ -struct ustconsumer_instance * -ustconsumer_new_instance( - struct ustconsumer_callbacks *callbacks, char *sock_path); - -/** - * ustconsumer_delete_instance - Is called to free a ustconsumer_instance struct - * - * @instance: The tracing session instance that needs to be freed. - * - * This function should only be called if the instance has not been started, - * as it will automatically be called at the end of ustconsumer_start_instance. - */ -void ustconsumer_delete_instance(struct ustconsumer_instance *instance); - -/** - * ustconsumer_init_instance - Is called to initiliaze a new tracing session - * - * @instance: The tracing session instance that needs to be started. - * - * Returns 0 if the function succeeds. - * - * This function must be called between ustconsumer_new_instance and - * ustconsumer_start_instance. It sets up the communication between the library - * and the tracing application. - */ -int ustconsumer_init_instance(struct ustconsumer_instance *instance); - -/** - * ustconsumer_start_instance - Is called to start a new tracing session. - * - * @instance: The tracing session instance that needs to be started. - * - * Returns 0 if the function succeeds. - * - * This is a blocking function. The caller will be blocked on it until the - * tracing session is stopped by the user using ustconsumer_stop_instance or until - * the traced application terminates - */ -int ustconsumer_start_instance(struct ustconsumer_instance *instance); - -/** - * ustconsumer_stop_instance - Is called to stop a tracing session. - * - * @instance: The tracing session instance that needs to be stoped. - * @send_msg: If true, a message will be sent to the listening thread through - * the daemon socket to force it to return from the poll syscall - * and realize that it must close. This is not necessary if the - * instance is being stopped as part of an interrupt handler, as - * the interrupt itself will cause poll to return. - * - * Returns 0 if the function succeeds. - * - * This function returns immediately, it only tells libustconsumer to stop the - * instance. The on_trace_end callback will be called when the tracing session - * will really be stopped. The instance is deleted automatically by libustconsumer - * after on_trace_end is called. - */ -int ustconsumer_stop_instance(struct ustconsumer_instance *instance, int send_msg); - -#endif /* _USTCONSUMER_H */ - diff --git a/deprecated/ustctl.h b/deprecated/ustctl.h deleted file mode 100644 index 33d7ade..0000000 --- a/deprecated/ustctl.h +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2009 Pierre-Marc Fournier - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _USTCTL_H -#define _USTCTL_H - -#include -#include -#include -#include -#include - -#define USTCTL_ERR_CONN 1 /* Process connection error */ -#define USTCTL_ERR_ARG 2 /* Invalid function argument */ -#define USTCTL_ERR_GEN 3 /* General ustctl error */ - -#define USTCTL_MS_CHR_OFF '0' /* Marker state 'on' character */ -#define USTCTL_MS_CHR_ON '1' /* Marker state 'on' character */ -#define USTCTL_MS_OFF 0 /* Marker state 'on' value */ -#define USTCTL_MS_ON 1 /* Marker state 'on' value */ - -#define USTCTL_SOCK_PATH "/tmp/socks/" - -/* Channel/marker/state/format string (cmsf) info. structure */ -struct ust_marker_status { - char *channel; /* Channel name (end of ust_marker_status array if NULL) */ - char *ust_marker; /* Marker name (end of ust_marker_status array if NULL) */ - int state; /* State (0 := marker disabled, 1 := marker enabled) */ - char *fs; /* Format string (end of ust_marker_status array if NULL) */ -}; - -struct trace_event_status { - char *name; -}; - -extern pid_t *ustctl_get_online_pids(void); - -extern int ustctl_connect_pid(pid_t pid); - -extern int ustctl_set_ust_marker_state(int sock, const char *trace, - const char *channel, const char *ust_marker, - int state); - -extern int ustctl_set_subbuf_size(int sock, const char *trace, - const char *channel, - unsigned int subbuf_size); - -extern int ustctl_set_subbuf_num(int sock, const char *trace, - const char *channel, - unsigned int num); - -extern int ustctl_get_subbuf_size(int sock, const char *trace, - const char *channel); - -extern int ustctl_get_subbuf_num(pid_t pid, const char *trace, - const char *channel); - -extern int ustctl_destroy_trace(int sock, const char *trace); - -extern int ustctl_setup_and_start(int sock, const char *trace); - -extern int ustctl_stop_trace(int sock, const char *trace); - -extern int ustctl_create_trace(int sock, const char *trace); - -extern int ustctl_start_trace(int sock, const char *trace); - -extern int ustctl_alloc_trace(int sock, const char *trace); - -extern int ustctl_free_cmsf(struct ust_marker_status *); -extern int ustctl_free_tes(struct trace_event_status *); -extern unsigned int ustctl_count_nl(const char *); - -extern int ustctl_get_cmsf(int sock, struct ust_marker_status **); - -extern int ustctl_get_tes(int sock, struct trace_event_status **); - -extern int ustctl_set_sock_path(int sock, const char *sock_path); - -extern int ustctl_get_sock_path(int sock, char **sock_path); - -extern int ustctl_force_switch(int sock, const char *trace); - -#endif /* _USTCTL_H */ diff --git a/deprecated/ustctl/Makefile.am b/deprecated/ustctl/Makefile.am deleted file mode 100644 index 1e442a3..0000000 --- a/deprecated/ustctl/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libustcomm \ - -I$(top_srcdir)/libustctl $(KCOMPAT_CFLAGS) -AM_CFLAGS = -fno-strict-aliasing - -bin_PROGRAMS = ustctl - -ustctl_SOURCES = \ - ustctl.c marker_cmds.c trace_cmds.c channel_cmds.c cli.c cli.h scanning_functions.c scanning_functions.h - -ustctl_CFLAGS = -DUST_COMPONENT=ustctl -fno-strict-aliasing - -ustctl_LDADD = \ - $(top_builddir)/snprintf/libustsnprintf.la \ - $(top_builddir)/libustcomm/libustcomm.la \ - $(top_builddir)/libustctl/libustctl.la diff --git a/deprecated/ustctl/README b/deprecated/ustctl/README deleted file mode 100644 index 3fdfbbd..0000000 --- a/deprecated/ustctl/README +++ /dev/null @@ -1,3 +0,0 @@ -ustctl is a helper application used to control tracing on programs that support tracing. - -It can list markers, enable/disable markers, start tracing and stop tracing. diff --git a/deprecated/ustctl/channel_cmds.c b/deprecated/ustctl/channel_cmds.c deleted file mode 100644 index 315fd56..0000000 --- a/deprecated/ustctl/channel_cmds.c +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright (C) 2011 Ericsson AB, Nils Carlson - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include -#include -#include -#include -#include "scanning_functions.h" -#include "usterr.h" -#include "cli.h" - -static int set_subbuf_size(int argc, char *argv[]) -{ - int sock, result = 0; - char *channel = NULL; - unsigned int size; - - sock = parse_and_connect_pid(argv[1]); - - if (scan_ch_and_num(argv[3], &channel, &size)) { - fprintf(stderr, "Failed to scan channel and size from" - " %s\n", argv[3]); - if (channel) - free(channel); - return -1; - } - if (ustctl_set_subbuf_size(sock, argv[2], channel, size)) { - ERR("error while trying to set the size of subbuffers " - "for PID %s\n", - argv[1]); - result = -1; - } - - free(channel); - - return result; -} - -static int set_subbuf_num(int argc, char *argv[]) -{ - int sock, result = 0; - char *channel = NULL; - unsigned int num; - - sock = parse_and_connect_pid(argv[1]); - - if (scan_ch_and_num(argv[3], &channel, &num)) { - fprintf(stderr, "Failed to scan channel and number from" - " %s\n", argv[3]); - if (channel) - free(channel); - return -1; - } - if (ustctl_set_subbuf_num(sock, argv[2], channel, num)) { - ERR("error while trying to set the number of subbuffers for PID %s\n", - argv[1]); - result = -1; - } - - free(channel); - - return result; -} - -static int get_subbuf_size(int argc, char *argv[]) -{ - int sock; - unsigned int size; - - sock = parse_and_connect_pid(argv[1]); - - if ((size = ustctl_get_subbuf_size(sock, argv[2], argv[3])) < 0) { - ERR("error while trying to get the subbuffer size from PID %s\n", - argv[1]); - return -1; - } - - printf("The subbufer size is %d bytes\n", size); - - return 0; -} - -static int get_subbuf_num(int argc, char *argv[]) -{ - int sock; - unsigned int num; - - sock = parse_and_connect_pid(argv[1]); - - if ((num = ustctl_get_subbuf_num(sock, argv[2], argv[3])) < 0) { - ERR("error while trying to get the subbuffer size from PID %s\n", - argv[1]); - return -1; - } - - printf("There are %u subbufers in each buffer\n", num); - - return 0; -} - -struct cli_cmd __cli_cmds channel_cmds[] = { - { - .name = "set-subbuf-size", - .description = "Set the subbuffer size for a channel", - .help_text = "set-subbuf-size / \n" - "Set the subbuffer size for a channel\n", - .function = set_subbuf_size, - .desired_args = 3, - .desired_args_op = CLI_EQ, - }, - { - .name = "set-subbuf-num", - .description = "Set the number of subbuffers for a channel", - .help_text = "set-subbuf-num / \n" - "Set the number of subbuffers for a channel\n", - .function = set_subbuf_num, - .desired_args = 3, - .desired_args_op = CLI_EQ, - }, - { - .name = "get-subbuf-size", - .description = "Get the subbuffer size for a channel", - .help_text = "get-subbuf-size \n" - "Get the subbuffer size for a channel\n", - .function = get_subbuf_size, - .desired_args = 3, - .desired_args_op = CLI_EQ, - }, - { - .name = "get-subbuf-num", - .description = "Get the number of subbuffers for a channel", - .help_text = "get-subbuf-num \n" - "Get the number of subbuffers for a channel\n", - .function = get_subbuf_num, - .desired_args = 3, - .desired_args_op = CLI_EQ, - }, -}; diff --git a/deprecated/ustctl/cli.c b/deprecated/ustctl/cli.c deleted file mode 100644 index 0ca9db5..0000000 --- a/deprecated/ustctl/cli.c +++ /dev/null @@ -1,207 +0,0 @@ -/* Copyright (C) 2011 Ericsson AB, Nils Carlson - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define _GNU_SOURCE -#include -#include -#include -#include "cli.h" - -/* This dummy command is needed to create the sections in cli.o before - * other .o files have these sections, usefull for development. - */ -static int _dummy(int argc, char *argv[]) { - return 0; -} - -/* Define a dummy cmd to guarantee existence of the builtin variables */ -struct cli_cmd __cli_cmds __dummy_cli_cmd[] = { - { - .name = "_dummy", - .description = NULL, - .help_text = NULL, - .function = _dummy, - .desired_args = 0, - .desired_args_op = 0, - }, -}; - -extern struct cli_cmd __start___cli_cmds[] __attribute__((visibility("hidden"))); -extern struct cli_cmd __stop___cli_cmds[] __attribute__((visibility("hidden"))); - -static struct cli_cmd **cli_cmd_list; -static int cli_cmd_list_size; - -static char *process_name; - -static int compute_cli_cmds_size(void) -{ - long cli_cmds_start, cli_cmds_end; - - cli_cmds_start = (long)__start___cli_cmds; - cli_cmds_end = (long)__stop___cli_cmds; - - return (cli_cmds_end - cli_cmds_start) / sizeof(struct cli_cmd); -} - -static void __attribute__((constructor)) generate_cli_cmd_list(int argc, char *argv[]) -{ - struct cli_cmd *cli_cmd; - int section_size, i; - - process_name = basename(argv[0]); - - section_size = compute_cli_cmds_size(); - - cli_cmd_list = malloc(section_size * sizeof(void *)); - if (!cli_cmd_list) { - fprintf(stderr, "Failed to allocate command list!"); - exit(EXIT_FAILURE); - } - - cli_cmd_list_size = 0; - - cli_cmd = __start___cli_cmds; - for (i = 0; i < section_size; i++) { - if (&cli_cmd[i] == &__dummy_cli_cmd[0]) { - continue; - } - - if (cli_cmd[i].name) { - cli_cmd_list[cli_cmd_list_size++] = &cli_cmd[i]; - } - } -} - -struct cli_cmd *find_cli_cmd(const char *command) -{ - int i; - - for (i = 0; i < cli_cmd_list_size; i++) { - if (!strcmp(cli_cmd_list[i]->name, command)) { - return cli_cmd_list[i]; - } - } - - return NULL; -} - -static int cmpcli_cmds(const void *p1, const void *p2) -{ - return strcmp(* (char * const *) ((struct cli_cmd *)p1)->name, - * (char * const *) ((struct cli_cmd *)p2)->name); -} - -#define HELP_BUFFER_SIZE 4096 - -static void print_cmd_help(const char *prefix, const char *infix, - struct cli_cmd *cli_cmd) -{ - if (cli_cmd->help_text) { - fprintf(stderr, "%s%s%s", - prefix, - infix, - cli_cmd->help_text); - } else if (cli_cmd->description) { - fprintf(stderr, "%s%s%s\n%s\n", - prefix, - infix, - cli_cmd->name, - cli_cmd->description); - } else { - fprintf(stderr, "No help available for %s\n", - cli_cmd->name); - } -} - -void list_cli_cmds(int option) -{ - int i; - - qsort(cli_cmd_list, cli_cmd_list_size, sizeof(void *), cmpcli_cmds); - - for (i = 0; i < cli_cmd_list_size; i++) { - switch (option) { - case CLI_SIMPLE_LIST: - fprintf(stderr, "%s ", cli_cmd_list[i]->name); - break; - case CLI_DESCRIPTIVE_LIST: - fprintf(stderr, " %-25s%s\n", cli_cmd_list[i]->name, - cli_cmd_list[i]->description); - break; - case CLI_EXTENDED_LIST: - print_cmd_help("", "", cli_cmd_list[i]); - fprintf(stderr, "\n"); - break; - } - } - - if (option == CLI_SIMPLE_LIST) { - fprintf(stderr, "\n"); - } -} - -int cli_print_help(const char *command) -{ - struct cli_cmd *cli_cmd; - - cli_cmd = find_cli_cmd(command); - if (!cli_cmd) { - return -1; - } - - print_cmd_help(process_name, " ", cli_cmd); - - return 0; -} - -static void cli_check_argc(const char *command, int args, - int operator, int desired_args) -{ - switch(operator) { - case CLI_EQ: - if (args != desired_args) - goto print_error; - break; - case CLI_GE: - if (args < desired_args) - goto print_error; - break; - } - - return; - -print_error: - fprintf(stderr, "%s %s requires %s%d argument%s, see usage.\n", - process_name, command, operator == CLI_EQ ? "" : "at least ", - desired_args, desired_args > 1 ? "s" : ""); - cli_print_help(command); - exit(EXIT_FAILURE); -} - - -void cli_dispatch_cmd(struct cli_cmd *cmd, int argc, char *argv[]) -{ - cli_check_argc(cmd->name, argc - 1, cmd->desired_args_op, - cmd->desired_args); - - if (cmd->function(argc, argv)) { - exit(EXIT_FAILURE); - } - - exit(EXIT_SUCCESS); -} diff --git a/deprecated/ustctl/cli.h b/deprecated/ustctl/cli.h deleted file mode 100644 index a1e4eed..0000000 --- a/deprecated/ustctl/cli.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (C) 2011 Ericsson AB, Nils Carlson - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#ifndef _CLI_H -#define _CLI_H - -struct cli_cmd { - const char *name; - const char *description; - const char *help_text; - int (*function)(int, char **); - int desired_args; - int desired_args_op; -} __attribute__((aligned(8))); - -#define __cli_cmds __attribute__((section("__cli_cmds"), aligned(8), used)) - -struct cli_cmd *find_cli_cmd(const char *command); - -enum cli_list_opts { - CLI_SIMPLE_LIST, - CLI_DESCRIPTIVE_LIST, - CLI_EXTENDED_LIST, -}; - -void list_cli_cmds(int option); - -int cli_print_help(const char *command); - -enum cli_arg_ops { - CLI_EQ, - CLI_GE, -}; - -void cli_dispatch_cmd(struct cli_cmd *cmd, int argc, char *argv[]); - -#endif /* _CLI_H */ diff --git a/deprecated/ustctl/marker_cmds.c b/deprecated/ustctl/marker_cmds.c deleted file mode 100644 index 8bcab83..0000000 --- a/deprecated/ustctl/marker_cmds.c +++ /dev/null @@ -1,141 +0,0 @@ -/* Copyright (C) 2011 Ericsson AB, Nils Carlson - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include -#include -#include -#include -#include "scanning_functions.h" -#include "usterr.h" -#include "cli.h" - -static int list_markers(int argc, char *argv[]) -{ - struct ust_marker_status *cmsf = NULL; - int i, sock; - - sock = parse_and_connect_pid(argv[1]); - - if (ustctl_get_cmsf(sock, &cmsf)) { - ERR("error while trying to list markers for PID %s\n", argv[1]); - return -1; - } - for (i = 0; cmsf[i].channel; i++) { - printf("{PID: %s, channel/marker: %s/%s, " - "state: %u, fmt: %s}\n", - argv[1], - cmsf[i].channel, - cmsf[i].ust_marker, - cmsf[i].state, - cmsf[i].fs); - } - ustctl_free_cmsf(cmsf); - return 0; -} - -static int enable_marker(int argc, char *argv[]) -{ - int i, sock, result = 0; - char *channel, *marker; - - sock = parse_and_connect_pid(argv[1]); - - for (i = 3; i < argc; i++) { - channel = NULL; - marker = NULL; - if (scan_ch_marker(argv[i], - &channel, &marker)) { - result = -1; - fprintf(stderr, "Failed to scan channel and marker from" - " %s\n", argv[i]); - if (channel) - free(channel); - if (marker) - free(marker); - } - if (ustctl_set_ust_marker_state(sock, argv[2], channel, marker, 1)) { - PERROR("error while trying to enable marker %s with PID %s", - argv[i], argv[1]); - result = -1; - } - free(channel); - free(marker); - } - - return result; -} - -static int disable_marker(int argc, char *argv[]) -{ - int i, sock, result = 0; - char *channel, *marker; - - sock = parse_and_connect_pid(argv[1]); - - for (i = 3; i < argc; i++) { - channel = NULL; - marker = NULL; - if (scan_ch_marker(argv[i], - &channel, &marker)) { - fprintf(stderr, "Failed to scan channel and marker from" - " %s\n", argv[i]); - if (channel) - free(channel); - if (marker) - free(marker); - return -1; - } - if (ustctl_set_ust_marker_state(sock, argv[2], channel, marker, 0)) { - PERROR("error while trying to disable marker %s with PID %s", - argv[i], argv[1]); - result = -1; - } - free(channel); - free(marker); - } - - return result; -} - -struct cli_cmd __cli_cmds ust_marker_cmds[] = { - { - .name = "list-markers", - .description = "List markers for a given pid", - .help_text = "list-markers \n" - "List the markers in a process\n", - .function = list_markers, - .desired_args = 1, - .desired_args_op = CLI_EQ, - }, - { - .name = "enable-marker", - .description = "Enable markers for a given pid", - .help_text = "enable-marker /... \n" - "Enable the listed markers for the trace in process pid\n", - .function = enable_marker, - .desired_args = 3, - .desired_args_op = CLI_GE, - }, - { - .name = "disable-marker", - .description = "Disable markers for a given pid", - .help_text = "disable-marker /... \n" - "Disable the listed markers for the trace in process pid\n", - .function = disable_marker, - .desired_args = 3, - .desired_args_op = CLI_GE, - } -}; diff --git a/deprecated/ustctl/scanning_functions.c b/deprecated/ustctl/scanning_functions.c deleted file mode 100644 index 4aa8c1c..0000000 --- a/deprecated/ustctl/scanning_functions.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2011 Ericsson AB, Nils Carlson - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define _GNU_SOURCE -#include -#include -#include "usterr.h" - - -int parse_and_connect_pid(const char *pid_string) -{ - pid_t pid; - int sock; - - errno = 0; - pid = strtoull(pid_string, NULL, 10); - if (errno) { - perror("Failed to parse pid"); - exit(EXIT_FAILURE); - } - - sock = ustctl_connect_pid(pid); - if (sock < 0) { - perror("Failed to connect to process"); - exit(EXIT_FAILURE); - } - - return sock; -} - -int scan_ch_marker(const char *channel_marker, char **channel, char **marker) -{ - int result; - - *channel = NULL; - *marker = NULL; - - result = sscanf(channel_marker, "%a[^/]/%as", channel, marker); - if (result != 2) { - if (errno) { - PERROR("Failed to read channel and marker names"); - } else { - ERR("Failed to parse marker and channel names"); - } - if (*channel) { - free(*channel); - } - if (*marker) { - free(*marker); - } - return -1; - } - - return 0; -} - -int scan_ch_and_num(const char *ch_num, char **channel, unsigned int *num) -{ - int result; - - *channel = NULL; - - result = sscanf(ch_num, "%a[^/]/%u", channel, num); - if (result != 2) { - if (errno) { - PERROR("Failed to parse channel and number"); - } else { - ERR("Failed to parse channel and number"); - } - if (*channel) { - free(*channel); - } - return -1; - } - - return 0; -} diff --git a/deprecated/ustctl/scanning_functions.h b/deprecated/ustctl/scanning_functions.h deleted file mode 100644 index 0f2d62e..0000000 --- a/deprecated/ustctl/scanning_functions.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (C) 2011 Ericsson AB, Nils Carlson - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#ifndef __SCANNING_FUNCTIONS_H -#define __SCANNING_FUNCTIONS_H - -int parse_and_connect_pid(const char *pid_string); - -int scan_ch_marker(const char *channel_marker, char **channel, char **marker); - -int scan_ch_and_num(const char *ch_num, char **channel, unsigned int *num); - -#endif /* __SCANNING_FUNCTIONS_H */ diff --git a/deprecated/ustctl/trace_cmds.c b/deprecated/ustctl/trace_cmds.c deleted file mode 100644 index a8f3a9c..0000000 --- a/deprecated/ustctl/trace_cmds.c +++ /dev/null @@ -1,162 +0,0 @@ -/* Copyright (C) 2011 Ericsson AB, Nils Carlson - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include -#include -#include -#include -#include "scanning_functions.h" -#include "usterr.h" -#include "cli.h" - - -static int create_trace(int argc, char *argv[]) -{ - int sock; - - sock = parse_and_connect_pid(argv[1]); - - if (ustctl_create_trace(sock, argv[2])) { - ERR("Failed to create trace %s for PID %s\n", argv[2], argv[1]); - return -1; - } - - return 0; -} - -static int alloc_trace(int argc, char *argv[]) -{ - int sock; - - sock = parse_and_connect_pid(argv[1]); - - if (ustctl_alloc_trace(sock, argv[2])) { - ERR("Failed to allocate trace %s for PID %s\n", argv[2], argv[1]); - return -1; - } - return 0; -} - -static int start_trace(int argc, char *argv[]) -{ - int sock; - - sock = parse_and_connect_pid(argv[1]); - - if (ustctl_start_trace(sock, argv[2])) { - ERR("Failed to start trace %s for PID %s\n", argv[2], argv[1]); - return -1; - } - return 0; -} - -static int stop_trace(int argc, char *argv[]) -{ - int sock; - - sock = parse_and_connect_pid(argv[1]); - - if (ustctl_stop_trace(sock, argv[2])) { - ERR("Failed to stop trace %s for PID %s\n", argv[2], argv[1]); - return -1; - } - return 0; -} - -static int destroy_trace(int argc, char *argv[]) -{ - int sock; - - sock = parse_and_connect_pid(argv[1]); - - if (ustctl_destroy_trace(sock, argv[2])) { - ERR("Failed to destroy trace %s for PID %s\n", argv[2], argv[1]); - return -1; - } - return 0; -} - -static int force_subbuf_switch(int argc, char *argv[]) -{ - int sock; - - sock = parse_and_connect_pid(argv[1]); - - if (ustctl_force_switch(sock, argv[2])) { - ERR("error while trying to force switch for PID %s\n", argv[1]); - return -1; - } - - return 0; -} - -struct cli_cmd __cli_cmds trace_cmds[] = { - { - .name = "create-trace", - .description = "Create a trace for a process", - .help_text = "create-trace \n" - "Create a trace for a process\n", - .function = create_trace, - .desired_args = 2, - .desired_args_op = CLI_EQ, - }, - { - .name = "alloc-trace", - .description = "Allocate a trace for a process", - .help_text = "alloc-trace \n" - "Allocate a trace for a process\n", - .function = alloc_trace, - .desired_args = 2, - .desired_args_op = CLI_EQ, - }, - { - .name = "start-trace", - .description = "Start a trace for a process", - .help_text = "start-trace \n" - "Start a trace for a process\n", - .function = start_trace, - .desired_args = 2, - .desired_args_op = CLI_EQ, - }, - { - .name = "stop-trace", - .description = "Stop a trace for a process", - .help_text = "stop-trace \n" - "Stop a trace for a process\n", - .function = stop_trace, - .desired_args = 2, - .desired_args_op = CLI_EQ, - }, - { - .name = "destroy-trace", - .description = "Destroy a trace for a process", - .help_text = "destroy-trace \n" - "Destroy a trace for a process\n", - .function = destroy_trace, - .desired_args = 2, - .desired_args_op = CLI_EQ, - }, - { - .name = "force-subbuf-switch", - .description = "Force a subbuffer switch", - .help_text = "force-subbuf-switch \n" - "Force a subbuffer switch for a trace, currently this forces\n" - "a subbuffer switch for all traces in a process\n", - .function = force_subbuf_switch, - .desired_args = 2, - .desired_args_op = CLI_EQ, - }, -}; diff --git a/deprecated/ustctl/ustctl.c b/deprecated/ustctl/ustctl.c deleted file mode 100644 index 18f7d30..0000000 --- a/deprecated/ustctl/ustctl.c +++ /dev/null @@ -1,272 +0,0 @@ -/* Copyright (C) 2009 Pierre-Marc Fournier - * Copyright (C) 2011 Ericsson AB, Nils Carlson - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include - -#include "ust/ustctl.h" -#include "usterr.h" -#include "cli.h" -#include "scanning_functions.h" - -void usage(const char *process_name) -{ - fprintf(stderr, "Usage: %s COMMAND [ARGS]...\n", process_name); - fprintf(stderr, - "Control tracing within a process that supports UST,\n" - " the Userspace Tracing libary\n" - "Options:\n" - " -h[], --help[=] " - "help, for a command if provided\n" - " -l, --list " - "short list of commands\n" - " -e, --extended-list " - "extented list of commands with help\n" - "Commands:\n"); - list_cli_cmds(CLI_DESCRIPTIVE_LIST); -} - -/* - * Provide backward compatibility for scripts that make use of the - * --commands in ustctl version <= 0.11 - */ -enum command { - CREATE_TRACE=1000, - ALLOC_TRACE, - START_TRACE, - STOP_TRACE, - DESTROY_TRACE, - LIST_MARKERS, - LIST_TRACE_EVENTS, - ENABLE_MARKER, - DISABLE_MARKER, -}; - -struct option options[] = -{ - { "create-trace", 0, 0, CREATE_TRACE }, - { "alloc-trace", 0, 0, ALLOC_TRACE }, - { "start-trace", 0, 0, START_TRACE }, - { "stop-trace", 0, 0, STOP_TRACE }, - { "destroy-trace", 0, 0, DESTROY_TRACE }, - { "list-markers", 0, 0, LIST_MARKERS }, - { "list-trace-events", 0, 0, LIST_TRACE_EVENTS}, - { "enable-marker", 0, 0, ENABLE_MARKER }, - { "disable-marker", 0, 0, DISABLE_MARKER }, - {"help", 2, NULL, 'h'}, - {"list", 0, NULL, 'l'}, - {"extended-list", 0, NULL, 'e'}, - {NULL, 0, NULL, 0}, -}; - -int main(int argc, char *argv[]) -{ - struct cli_cmd *cli_cmd; - char **args = argv; - int opt; - int i; - - if(argc <= 1) { - fprintf(stderr, "No operation specified.\n"); - usage(argv[0]); - exit(EXIT_FAILURE); - } - - while ((opt = getopt_long(argc, argv, "+h::le", - options, NULL)) != -1) { - switch (opt) { - case 'h': - if (!optarg) { - usage(argv[0]); - } else { - if (cli_print_help(optarg)) { - fprintf(stderr, "No such command %s\n", - optarg); - } - } - exit(EXIT_FAILURE); - break; - case 'l': - list_cli_cmds(CLI_SIMPLE_LIST); - exit(EXIT_FAILURE); - break; - case 'e': - list_cli_cmds(CLI_EXTENDED_LIST); - exit(EXIT_FAILURE); - case LIST_MARKERS: - case LIST_TRACE_EVENTS: - case CREATE_TRACE: - case ALLOC_TRACE: - case START_TRACE: - case STOP_TRACE: - case DESTROY_TRACE: - case ENABLE_MARKER: - case DISABLE_MARKER: - args = (char **)malloc(sizeof(char *) * (argc + 3)); - optind--; - args[optind] = strdup(&argv[optind][2]); - for (i = optind + 1; i < argc; i++) { - args[i] = argv[i]; - } - if (opt >= CREATE_TRACE && opt <= DESTROY_TRACE) { - args[argc] = strdup("auto"); - argc++; - } - if (opt >= ENABLE_MARKER && opt <= DISABLE_MARKER) { - args[argc] = args[argc - 2]; - args[argc - 2] = args[argc - 1]; - args[argc - 1] = strdup("auto"); - argc++; - } - args[argc] = NULL; - goto do_cli; - default: - fprintf(stderr, "Unknown option\n"); - break; - } - } - -do_cli: - cli_cmd = find_cli_cmd(args[optind]); - if (!cli_cmd) { - fprintf(stderr, "No such command %s\n", - args[optind]); - exit(EXIT_FAILURE); - } - - cli_dispatch_cmd(cli_cmd, argc - optind, &args[optind]); - - return 0; -} - -static int list_trace_events(int argc, char *argv[]) -{ - struct trace_event_status *tes = NULL; - int i, sock; - - sock = parse_and_connect_pid(argv[1]); - - if (ustctl_get_tes(sock, &tes)) { - ERR("error while trying to list " - "trace_events for PID %s\n", - argv[1]); - return -1; - } - i = 0; - for (i = 0; tes[i].name; i++) { - printf("{PID: %s, trace_event: %s}\n", - argv[1], - tes[i].name); - } - ustctl_free_tes(tes); - - return 0; -} - -static int set_sock_path(int argc, char *argv[]) -{ - int sock; - - sock = parse_and_connect_pid(argv[1]); - - if (ustctl_set_sock_path(sock, argv[2])) { - ERR("error while trying to set sock path for PID %s\n", argv[1]); - return -1; - } - - return 0; -} - -static int get_sock_path(int argc, char *argv[]) -{ - int sock; - char *sock_path; - - sock = parse_and_connect_pid(argv[1]); - - if (ustctl_get_sock_path(sock, &sock_path)) { - ERR("error while trying to get sock path for PID %s\n", argv[1]); - return -1; - } - printf("The socket path is %s\n", sock_path); - free(sock_path); - - return 0; -} - -static int list_pids(int argc, char *argv[]) -{ - pid_t *pid_list; - int i; - - pid_list = ustctl_get_online_pids(); - if (!pid_list) { - return -1; - } - - for (i = 0; pid_list[i]; i++) { - printf("%ld\n", (long)pid_list[i]); - } - - free(pid_list); - - return 0; -} - -struct cli_cmd __cli_cmds general_cmds[] = { - { - .name = "list-trace-events", - .description = "List trace-events for a given pid", - .help_text = "list-trace-events \n" - "List the trace-events in a process\n", - .function = list_trace_events, - .desired_args = 1, - .desired_args_op = CLI_EQ, - }, - { - .name = "set-sock-path", - .description = "Set the path to the consumer daemon socket", - .help_text = "set-sock-path \n" - "Set the path to the consumer daemon socket\n", - .function = set_sock_path, - .desired_args = 2, - .desired_args_op = CLI_EQ, - }, - { - .name = "get-sock-path", - .description = "Get the path to the consumer daemon socket", - .help_text = "get-sock-path \n" - "Get the path to the consumer daemon socket\n", - .function = get_sock_path, - .desired_args = 1, - .desired_args_op = CLI_EQ, - }, - { - .name = "list-pids", - .description = "List traceable pids", - .help_text = "list-pids\n" - "List the traceable pids for the current user\n", - .function = list_pids, - .desired_args = 0, - .desired_args_op = CLI_EQ, - }, -};