X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=libust%2Ftracer.c;h=ffcc2e74926996257ef7531fa622c1ee9179c0c9;hb=8d6300d3b3cb0219e1109e931a2219dbd812b24d;hp=5e4e1c0919e207f8eed2d54fcdcf861d6ba8c4e8;hpb=204141ee9da22a244c9095287f4f1c513784b171;p=ust.git diff --git a/libust/tracer.c b/libust/tracer.c index 5e4e1c0..ffcc2e7 100644 --- a/libust/tracer.c +++ b/libust/tracer.c @@ -34,7 +34,8 @@ #include #include -#include +#include + #include "tracercore.h" #include "tracer.h" #include "usterr.h" @@ -45,12 +46,12 @@ /* Default callbacks for modules */ notrace int ltt_filter_control_default(enum ltt_filter_control_msg msg, - struct ltt_trace_struct *trace) + struct ust_trace *trace) { return 0; } -int ltt_statedump_default(struct ltt_trace_struct *trace) +int ltt_statedump_default(struct ust_trace *trace) { return 0; } @@ -58,21 +59,17 @@ int ltt_statedump_default(struct ltt_trace_struct *trace) /* Callbacks for registered modules */ int (*ltt_filter_control_functor) - (enum ltt_filter_control_msg msg, struct ltt_trace_struct *trace) = + (enum ltt_filter_control_msg msg, struct ust_trace *trace) = ltt_filter_control_default; struct module *ltt_filter_control_owner; /* These function pointers are protected by a trace activation check */ struct module *ltt_run_filter_owner; -int (*ltt_statedump_functor)(struct ltt_trace_struct *trace) = +int (*ltt_statedump_functor)(struct ust_trace *trace) = ltt_statedump_default; struct module *ltt_statedump_owner; -struct chan_info_struct { - const char *name; - unsigned int def_subbufsize; - unsigned int def_subbufcount; -} chan_infos[] = { +struct chan_info_struct chan_infos[] = { [LTT_CHANNEL_METADATA] = { LTT_METADATA_CHANNEL, LTT_DEFAULT_SUBBUF_SIZE_LOW, @@ -140,7 +137,7 @@ static enum ltt_channels get_channel_type_from_name(const char *name) //ust// } //ust// ltt_filter_control_functor = //ust// (int (*)(enum ltt_filter_control_msg, -//ust// struct ltt_trace_struct *))function; +//ust// struct ust_trace *))function; //ust// ltt_filter_control_owner = owner; //ust// break; //ust// case LTT_FUNCTION_STATEDUMP: @@ -149,7 +146,7 @@ static enum ltt_channels get_channel_type_from_name(const char *name) //ust// goto end; //ust// } //ust// ltt_statedump_functor = -//ust// (int (*)(struct ltt_trace_struct *))function; +//ust// (int (*)(struct ust_trace *))function; //ust// ltt_statedump_owner = owner; //ust// break; //ust// } @@ -184,8 +181,9 @@ static enum ltt_channels get_channel_type_from_name(const char *name) //ust// //ust// } -static LIST_HEAD(ltt_transport_list); - +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 @@ -207,9 +205,9 @@ void ltt_transport_register(struct ltt_transport *transport) */ //ust// vmalloc_sync_all(); - ltt_lock_traces(); - list_add_tail(&transport->node, <t_transport_list); - ltt_unlock_traces(); + pthread_mutex_lock(<t_transport_mutex); + cds_list_add_tail(&transport->node, <t_transport_list); + pthread_mutex_unlock(<t_transport_mutex); } /** @@ -218,9 +216,9 @@ void ltt_transport_register(struct ltt_transport *transport) */ void ltt_transport_unregister(struct ltt_transport *transport) { - ltt_lock_traces(); - list_del(&transport->node); - ltt_unlock_traces(); + 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, @@ -248,26 +246,7 @@ static inline int is_channel_overwrite(enum ltt_channels chan, } } -/** - * ltt_write_trace_header - Write trace header - * @trace: Trace information - * @header: Memory address where the information must be written to - */ -void notrace ltt_write_trace_header(struct ltt_trace_struct *trace, - struct ltt_subbuffer_header *header) -{ - header->magic_number = LTT_TRACER_MAGIC_NUMBER; - header->major_version = LTT_TRACER_VERSION_MAJOR; - header->minor_version = LTT_TRACER_VERSION_MINOR; - header->arch_size = sizeof(void *); - header->alignment = ltt_get_alignment(); - header->start_time_sec = trace->start_time.tv_sec; - header->start_time_usec = trace->start_time.tv_usec; - header->start_freq = trace->start_freq; - header->freq_scale = trace->freq_scale; -} - -static void trace_async_wakeup(struct ltt_trace_struct *trace) +static void trace_async_wakeup(struct ust_trace *trace) { int i; struct ust_channel *chan; @@ -283,7 +262,7 @@ static void trace_async_wakeup(struct ltt_trace_struct *trace) //ust// /* Timer to send async wakeups to the readers */ //ust// static void async_wakeup(unsigned long data) //ust// { -//ust// struct ltt_trace_struct *trace; +//ust// struct ust_trace *trace; //ust// //ust// /* //ust// * PREEMPT_RT does not allow spinlocks to be taken within preempt @@ -297,7 +276,7 @@ static void trace_async_wakeup(struct ltt_trace_struct *trace) //ust// #else //ust// ltt_lock_traces(); //ust// #endif -//ust// list_for_each_entry_rcu(trace, <t_traces.head, list) { +//ust// cds_list_for_each_entry_rcu(trace, <t_traces.head, list) { //ust// trace_async_wakeup(trace); //ust// } //ust// #ifndef CONFIG_PREEMPT_RT @@ -315,11 +294,11 @@ static void trace_async_wakeup(struct ltt_trace_struct *trace) * * Returns a pointer to the trace structure, NULL if not found. */ -struct ltt_trace_struct *_ltt_trace_find(const char *trace_name) +struct ust_trace *_ltt_trace_find(const char *trace_name) { - struct ltt_trace_struct *trace; + struct ust_trace *trace; - list_for_each_entry(trace, <t_traces.head, list) + cds_list_for_each_entry(trace, <t_traces.head, list) if (!strncmp(trace->trace_name, trace_name, NAME_MAX)) return trace; @@ -331,11 +310,11 @@ struct ltt_trace_struct *_ltt_trace_find(const char *trace_name) * * Returns a pointer to the trace structure, NULL if not found. */ -struct ltt_trace_struct *_ltt_trace_find_setup(const char *trace_name) +struct ust_trace *_ltt_trace_find_setup(const char *trace_name) { - struct ltt_trace_struct *trace; + struct ust_trace *trace; - list_for_each_entry(trace, <t_traces.setup_head, list) + cds_list_for_each_entry(trace, <t_traces.setup_head, list) if (!strncmp(trace->trace_name, trace_name, NAME_MAX)) return trace; @@ -346,10 +325,10 @@ struct ltt_trace_struct *_ltt_trace_find_setup(const char *trace_name) * ltt_release_transport - Release an LTT transport * @kref : reference count on the transport */ -void ltt_release_transport(struct kref *kref) +void ltt_release_transport(struct urcu_ref *urcu_ref) { -//ust// struct ltt_trace_struct *trace = container_of(kref, -//ust// struct ltt_trace_struct, ltt_transport_kref); +//ust// struct ust_trace *trace = container_of(kref, +//ust// struct ust_trace, ltt_transport_kref); //ust// trace->ops->remove_dirs(trace); } @@ -357,17 +336,21 @@ void ltt_release_transport(struct kref *kref) * ltt_release_trace - Release a LTT trace * @kref : reference count on the trace */ -void ltt_release_trace(struct kref *kref) +void ltt_release_trace(struct urcu_ref *urcu_ref) { - struct ltt_trace_struct *trace = container_of(kref, - struct ltt_trace_struct, kref); + struct ust_trace *trace = _ust_container_of(urcu_ref, + struct ust_trace, urcu_ref); ltt_channels_trace_free(trace->channels); - kfree(trace); + 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); @@ -379,7 +362,7 @@ static inline void prepare_chan_size_num(unsigned int *subbuf_size, int _ltt_trace_setup(const char *trace_name) { int err = 0; - struct ltt_trace_struct *new_trace = NULL; + struct ust_trace *new_trace = NULL; int metadata_index; unsigned int chan; enum ltt_channels chantype; @@ -396,7 +379,7 @@ int _ltt_trace_setup(const char *trace_name) goto traces_error; } - new_trace = kzalloc(sizeof(struct ltt_trace_struct), GFP_KERNEL); + new_trace = zmalloc(sizeof(struct ust_trace)); if (!new_trace) { ERR("Unable to allocate memory for trace %s", trace_name); err = -ENOMEM; @@ -404,7 +387,8 @@ int _ltt_trace_setup(const char *trace_name) } strncpy(new_trace->trace_name, trace_name, NAME_MAX); new_trace->channels = ltt_channels_trace_alloc(&new_trace->nr_channels, - 0, 1); + 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; @@ -434,11 +418,11 @@ int _ltt_trace_setup(const char *trace_name) chan_infos[chantype].def_subbufcount; } - list_add(&new_trace->list, <t_traces.setup_head); + cds_list_add(&new_trace->list, <t_traces.setup_head); return 0; trace_free: - kfree(new_trace); + free(new_trace); traces_error: return err; } @@ -454,16 +438,16 @@ int ltt_trace_setup(const char *trace_name) } /* must be called from within a traces lock. */ -static void _ltt_trace_free(struct ltt_trace_struct *trace) +static void _ltt_trace_free(struct ust_trace *trace) { - list_del(&trace->list); - kfree(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 ltt_trace_struct *trace; + struct ust_trace *trace; struct ltt_transport *tran_iter, *transport = NULL; ltt_lock_traces(); @@ -475,12 +459,15 @@ int ltt_trace_set_type(const char *trace_name, const char *trace_type) goto traces_error; } - list_for_each_entry(tran_iter, <t_transport_list, node) { + 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; @@ -498,7 +485,7 @@ int ltt_trace_set_channel_subbufsize(const char *trace_name, const char *channel_name, unsigned int size) { int err = 0; - struct ltt_trace_struct *trace; + struct ust_trace *trace; int index; ltt_lock_traces(); @@ -527,7 +514,7 @@ int ltt_trace_set_channel_subbufcount(const char *trace_name, const char *channel_name, unsigned int cnt) { int err = 0; - struct ltt_trace_struct *trace; + struct ust_trace *trace; int index; ltt_lock_traces(); @@ -556,7 +543,7 @@ int ltt_trace_set_channel_enable(const char *trace_name, const char *channel_name, unsigned int enable) { int err = 0; - struct ltt_trace_struct *trace; + struct ust_trace *trace; int index; ltt_lock_traces(); @@ -596,7 +583,7 @@ int ltt_trace_set_channel_overwrite(const char *trace_name, const char *channel_name, unsigned int overwrite) { int err = 0; - struct ltt_trace_struct *trace; + struct ust_trace *trace; int index; ltt_lock_traces(); @@ -637,7 +624,7 @@ traces_error: int ltt_trace_alloc(const char *trace_name) { int err = 0; - struct ltt_trace_struct *trace; + struct ust_trace *trace; unsigned int subbuf_size, subbuf_cnt; //ust// unsigned long flags; int chan; @@ -645,6 +632,11 @@ int ltt_trace_alloc(const char *trace_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); @@ -652,9 +644,9 @@ int ltt_trace_alloc(const char *trace_name) goto traces_error; } - kref_init(&trace->kref); - kref_init(&trace->ltt_transport_kref); -//ust// init_waitqueue_head(&trace->kref_wq); + urcu_ref_init(&trace->urcu_ref); + urcu_ref_init(&trace->ltt_transport_urcu_ref); +//ust// init_waitqueue_head(&trace->urcu_ref_wq); trace->active = 0; //ust// get_trace_clock(); trace->freq_scale = trace_clock_freq_scale(); @@ -704,13 +696,13 @@ int ltt_trace_alloc(const char *trace_name) } } - list_del(&trace->list); -//ust// if (list_empty(<t_traces.head)) { + cds_list_del(&trace->list); +//ust// if (cds_list_empty(<t_traces.head)) { //ust// mod_timer(<t_async_wakeup_timer, //ust// jiffies + LTT_PERCPU_TIMER_INTERVAL); //ust// set_kernel_trace_flag_all_tasks(); //ust// } - list_add_rcu(&trace->list, <t_traces.head); + cds_list_add_rcu(&trace->list, <t_traces.head); //ust// synchronize_sched(); ltt_unlock_traces(); @@ -760,7 +752,7 @@ traces_error: //ust// } /* Must be called while sure that trace is in the list. */ -static int _ltt_trace_destroy(struct ltt_trace_struct *trace) +static int _ltt_trace_destroy(struct ust_trace *trace) { int err = -EPERM; @@ -774,9 +766,9 @@ static int _ltt_trace_destroy(struct ltt_trace_struct *trace) goto active_error; } /* Everything went fine */ - list_del_rcu(&trace->list); + cds_list_del_rcu(&trace->list); synchronize_rcu(); - if (list_empty(<t_traces.head)) { + if (cds_list_empty(<t_traces.head)) { //ust// clear_kernel_trace_flag_all_tasks(); /* * We stop the asynchronous delivery of reader wakeup, but @@ -794,20 +786,19 @@ traces_error: } /* Sleepable part of the destroy */ -static void __ltt_trace_destroy(struct ltt_trace_struct *trace) +static void __ltt_trace_destroy(struct ust_trace *trace, int drop) { int i; struct ust_channel *chan; - for (i = 0; i < trace->nr_channels; i++) { - chan = &trace->channels[i]; - if (chan->active) - trace->ops->finish_channel(chan); + if(!drop) { + for (i = 0; i < trace->nr_channels; i++) { + chan = &trace->channels[i]; + if (chan->active) + trace->ops->finish_channel(chan); + } } - return; /* FIXME: temporary for ust */ -//ust// flush_scheduled_work(); - /* * The currently destroyed trace is not in the trace list anymore, * so it's safe to call the async wakeup ourself. It will deliver @@ -821,7 +812,7 @@ static void __ltt_trace_destroy(struct ltt_trace_struct *trace) trace->ops->remove_channel(chan); } - kref_put(&trace->ltt_transport_kref, ltt_release_transport); + urcu_ref_put(&trace->ltt_transport_urcu_ref, ltt_release_transport); //ust// module_put(trace->transport->owner); @@ -834,13 +825,13 @@ static void __ltt_trace_destroy(struct ltt_trace_struct *trace) //ust// __wait_event_interruptible(trace->kref_wq, //ust// (atomic_read(&trace->kref.refcount) == 1), ret); //ust// } - kref_put(&trace->kref, ltt_release_trace); + urcu_ref_put(&trace->urcu_ref, ltt_release_trace); } -int ltt_trace_destroy(const char *trace_name) +int ltt_trace_destroy(const char *trace_name, int drop) { int err = 0; - struct ltt_trace_struct *trace; + struct ust_trace *trace; ltt_lock_traces(); @@ -852,7 +843,7 @@ int ltt_trace_destroy(const char *trace_name) ltt_unlock_traces(); - __ltt_trace_destroy(trace); + __ltt_trace_destroy(trace, drop); //ust// put_trace_clock(); return 0; @@ -874,7 +865,7 @@ error: } /* must be called from within a traces lock. */ -static int _ltt_trace_start(struct ltt_trace_struct *trace) +static int _ltt_trace_start(struct ust_trace *trace) { int err = 0; @@ -903,7 +894,7 @@ traces_error: int ltt_trace_start(const char *trace_name) { int err = 0; - struct ltt_trace_struct *trace; + struct ust_trace *trace; ltt_lock_traces(); @@ -915,11 +906,11 @@ int ltt_trace_start(const char *trace_name) ltt_unlock_traces(); /* - * Call the kernel state dump. - * Events will be mixed with real kernel events, it's ok. + * 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. + * 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_marker_state(trace); @@ -941,7 +932,7 @@ no_trace: } /* must be called from within traces lock */ -static int _ltt_trace_stop(struct ltt_trace_struct *trace) +static int _ltt_trace_stop(struct ust_trace *trace) { int err = -EPERM; @@ -968,7 +959,7 @@ traces_error: int ltt_trace_stop(const char *trace_name) { int err = 0; - struct ltt_trace_struct *trace; + struct ust_trace *trace; ltt_lock_traces(); trace = _ltt_trace_find(trace_name); @@ -985,7 +976,7 @@ int ltt_trace_stop(const char *trace_name) int ltt_filter_control(enum ltt_filter_control_msg msg, const char *trace_name) { int err; - struct ltt_trace_struct *trace; + struct ust_trace *trace; DBG("ltt_filter_control : trace %s", trace_name); ltt_lock_traces();