From: Mathieu Desnoyers Date: Mon, 12 Nov 2012 21:40:06 +0000 (-0500) Subject: Cleanup: add lttng_/lttng-/LTTNG_ prefixes X-Git-Tag: v2.1.0-rc2~10 X-Git-Url: http://git.lttng.org/?a=commitdiff_plain;h=7dd08bec735b428479201f9f84d59c78deabdf57;p=lttng-ust.git Cleanup: add lttng_/lttng-/LTTNG_ prefixes ltt_event -> lttng_event mass rename Rename ltt_chan -> lttng_chan Rename ltt_session -> lttng_session Rename enum abstract_types to enum lttng_abstract_types Rename ltt_transport to lttng_transport Rename rest of ltt_ prefixes to lttng_ Complete file and symbol renames from LTT/ltt to LTTNG/lttng Finish ltt->lttng symbol conversion Reviewed-by: David Goulet Reviewed-by: Christian Babeux Signed-off-by: Mathieu Desnoyers --- diff --git a/include/lttng/ust-events.h b/include/lttng/ust-events.h index 1378a350..4a7d67f2 100644 --- a/include/lttng/ust-events.h +++ b/include/lttng/ust-events.h @@ -29,8 +29,8 @@ #define LTTNG_UST_UUID_LEN 16 -struct ltt_channel; -struct ltt_session; +struct lttng_channel; +struct lttng_session; struct lttng_ust_lib_ring_buffer_ctx; /* @@ -52,7 +52,7 @@ enum lttng_client_types { /* Type description */ /* Update the astract_types name table in lttng-types.c along with this enum */ -enum abstract_types { +enum lttng_abstract_types { atype_integer, atype_enum, atype_array, @@ -147,7 +147,7 @@ union _lttng_basic_type { }; struct lttng_basic_type { - enum abstract_types atype; + enum lttng_abstract_types atype; union { union _lttng_basic_type basic; } u; @@ -155,7 +155,7 @@ struct lttng_basic_type { #define LTTNG_UST_TYPE_PADDING 128 struct lttng_type { - enum abstract_types atype; + enum lttng_abstract_types atype; union { union _lttng_basic_type basic; struct { @@ -201,7 +201,7 @@ struct lttng_ctx_field { size_t (*get_size)(size_t offset); void (*record)(struct lttng_ctx_field *field, struct lttng_ust_lib_ring_buffer_ctx *ctx, - struct ltt_channel *chan); + struct lttng_channel *chan); union { char padding[LTTNG_UST_CTX_FIELD_PADDING]; } u; @@ -250,7 +250,7 @@ struct lttng_probe_desc { * be enabled. */ struct session_wildcard { - struct ltt_channel *chan; + struct lttng_channel *chan; struct lttng_ctx *ctx; /* TODO */ struct lttng_ust_event event_param; struct cds_list_head events; /* list of events enabled */ @@ -298,7 +298,7 @@ struct lttng_ust_field_list { }; struct ust_pending_probe; -struct ltt_event; +struct lttng_event; struct lttng_ust_filter_bytecode_node { struct cds_list_head node; @@ -313,17 +313,17 @@ struct lttng_bytecode_runtime { }; /* - * ltt_event structure is referred to by the tracing fast path. It must be - * kept small. + * lttng_event structure is referred to by the tracing fast path. It + * must be kept small. * * IMPORTANT: this structure is part of the ABI between the probe and * UST. Fields need to be only added at the end, never reordered, never * removed. */ -struct ltt_event { +struct lttng_event { /* LTTng-UST 2.0 starts here */ unsigned int id; - struct ltt_channel *chan; + struct lttng_channel *chan; int enabled; const struct lttng_event_desc *desc; void *filter_unused; @@ -350,16 +350,16 @@ struct lttng_ust_shm_handle; * UST. Fields need to be only added at the end, never reordered, never * removed. */ -struct ltt_channel_ops { - struct ltt_channel *(*channel_create)(const char *name, +struct lttng_channel_ops { + struct lttng_channel *(*channel_create)(const char *name, void *buf_addr, size_t subbuf_size, size_t num_subbuf, unsigned int switch_timer_interval, unsigned int read_timer_interval, int **shm_fd, int **wait_fd, uint64_t **memory_map_size, - struct ltt_channel *chan_priv_init); - void (*channel_destroy)(struct ltt_channel *ltt_chan); + struct lttng_channel *chan_priv_init); + void (*channel_destroy)(struct lttng_channel *lttng_chan); struct lttng_ust_lib_ring_buffer *(*buffer_read_open)(struct channel *chan, struct lttng_ust_shm_handle *handle, int **shm_fd, int **wait_fd, @@ -390,7 +390,7 @@ struct ltt_channel_ops { * UST. Fields need to be only added at the end, never reordered, never * removed. */ -struct ltt_channel { +struct lttng_channel { /* * The pointers located in this private data are NOT safe to be * dereferenced by the consumer. The only operations the @@ -401,12 +401,12 @@ struct ltt_channel { int enabled; struct lttng_ctx *ctx; /* Event ID management */ - struct ltt_session *session; + struct lttng_session *session; int objd; /* Object associated to channel */ unsigned int free_event_id; /* Next event ID to allocate */ unsigned int used_event_id; /* Max allocated event IDs */ struct cds_list_head list; /* Channel list */ - struct ltt_channel_ops *ops; + struct lttng_channel_ops *ops; int header_type; /* 0: unset, 1: compact, 2: large */ struct lttng_ust_shm_handle *handle; /* shared-memory handle */ unsigned int metadata_dumped:1; @@ -422,11 +422,11 @@ struct ltt_channel { * UST. Fields need to be only added at the end, never reordered, never * removed. */ -struct ltt_session { +struct lttng_session { int active; /* Is trace session active ? */ int been_active; /* Has trace session been active ? */ int objd; /* Object associated to session */ - struct ltt_channel *metadata; /* Metadata channel */ + struct lttng_channel *metadata; /* Metadata channel */ struct cds_list_head chan; /* Channel list head */ struct cds_list_head events; /* Event list head */ struct cds_list_head wildcards; /* Wildcard list head */ @@ -436,18 +436,18 @@ struct ltt_session { unsigned int metadata_dumped:1; }; -struct ltt_transport { +struct lttng_transport { char *name; struct cds_list_head node; - struct ltt_channel_ops ops; + struct lttng_channel_ops ops; }; -struct ltt_session *ltt_session_create(void); -int ltt_session_enable(struct ltt_session *session); -int ltt_session_disable(struct ltt_session *session); -void ltt_session_destroy(struct ltt_session *session); +struct lttng_session *lttng_session_create(void); +int lttng_session_enable(struct lttng_session *session); +int lttng_session_disable(struct lttng_session *session); +void lttng_session_destroy(struct lttng_session *session); -struct ltt_channel *ltt_channel_create(struct ltt_session *session, +struct lttng_channel *lttng_channel_create(struct lttng_session *session, const char *transport_name, void *buf_addr, size_t subbuf_size, size_t num_subbuf, @@ -455,8 +455,8 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session, unsigned int read_timer_interval, int **shm_fd, int **wait_fd, uint64_t **memory_map_size, - struct ltt_channel *chan_priv_init); -struct ltt_channel *ltt_global_channel_create(struct ltt_session *session, + struct lttng_channel *chan_priv_init); +struct lttng_channel *lttng_global_channel_create(struct lttng_session *session, int overwrite, void *buf_addr, size_t subbuf_size, size_t num_subbuf, unsigned int switch_timer_interval, @@ -464,27 +464,27 @@ struct ltt_channel *ltt_global_channel_create(struct ltt_session *session, int **shm_fd, int **wait_fd, uint64_t **memory_map_size); -int ltt_event_create(struct ltt_channel *chan, +int lttng_event_create(struct lttng_channel *chan, struct lttng_ust_event *event_param, - struct ltt_event **event); + struct lttng_event **event); -int ltt_channel_enable(struct ltt_channel *channel); -int ltt_channel_disable(struct ltt_channel *channel); -int ltt_event_enable(struct ltt_event *event); -int ltt_event_disable(struct ltt_event *event); +int lttng_channel_enable(struct lttng_channel *channel); +int lttng_channel_disable(struct lttng_channel *channel); +int lttng_event_enable(struct lttng_event *event); +int lttng_event_disable(struct lttng_event *event); -void ltt_transport_register(struct ltt_transport *transport); -void ltt_transport_unregister(struct ltt_transport *transport); +void lttng_transport_register(struct lttng_transport *transport); +void lttng_transport_unregister(struct lttng_transport *transport); void synchronize_trace(void); -int ltt_probe_register(struct lttng_probe_desc *desc); -void ltt_probe_unregister(struct lttng_probe_desc *desc); +int lttng_probe_register(struct lttng_probe_desc *desc); +void lttng_probe_unregister(struct lttng_probe_desc *desc); int pending_probe_fix_events(const struct lttng_event_desc *desc); -const struct lttng_event_desc *ltt_event_get(const char *name); -void ltt_event_put(const struct lttng_event_desc *desc); -int ltt_probes_init(void); -void ltt_probes_exit(void); +const struct lttng_event_desc *lttng_event_get(const char *name); +void lttng_event_put(const struct lttng_event_desc *desc); +int lttng_probes_init(void); +void lttng_probes_exit(void); int lttng_find_context(struct lttng_ctx *ctx, const char *name); struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p); void lttng_remove_context_field(struct lttng_ctx **ctx_p, @@ -501,37 +501,37 @@ extern const struct lttng_ust_lib_ring_buffer_client_cb *lttng_client_callbacks_ extern const struct lttng_ust_lib_ring_buffer_client_cb *lttng_client_callbacks_discard; extern const struct lttng_ust_lib_ring_buffer_client_cb *lttng_client_callbacks_overwrite; -struct ltt_transport *ltt_transport_find(const char *name); +struct lttng_transport *lttng_transport_find(const char *name); -int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list *list); -void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list *list); +int lttng_probes_get_event_list(struct lttng_ust_tracepoint_list *list); +void lttng_probes_prune_event_list(struct lttng_ust_tracepoint_list *list); struct lttng_ust_tracepoint_iter * lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list *list); -int ltt_probes_get_field_list(struct lttng_ust_field_list *list); -void ltt_probes_prune_field_list(struct lttng_ust_field_list *list); +int lttng_probes_get_field_list(struct lttng_ust_field_list *list); +void lttng_probes_prune_field_list(struct lttng_ust_field_list *list); struct lttng_ust_field_iter * lttng_ust_field_list_get_iter_next(struct lttng_ust_field_list *list); -int ltt_wildcard_enable(struct session_wildcard *wildcard); -int ltt_wildcard_disable(struct session_wildcard *wildcard); -int ltt_wildcard_create(struct ltt_channel *chan, +int lttng_wildcard_enable(struct session_wildcard *wildcard); +int lttng_wildcard_disable(struct session_wildcard *wildcard); +int lttng_wildcard_create(struct lttng_channel *chan, struct lttng_ust_event *event_param, struct session_wildcard **sl); -int ltt_loglevel_match(const struct lttng_event_desc *desc, +int lttng_loglevel_match(const struct lttng_event_desc *desc, enum lttng_ust_loglevel_type req_type, int req_loglevel); -void ltt_probes_create_wildcard_events(struct wildcard_entry *entry, +void lttng_probes_create_wildcard_events(struct wildcard_entry *entry, struct session_wildcard *wildcard); -int lttng_filter_event_attach_bytecode(struct ltt_event *event, +int lttng_filter_event_attach_bytecode(struct lttng_event *event, struct lttng_ust_filter_bytecode_node *filter); int lttng_filter_wildcard_attach_bytecode(struct session_wildcard *wildcard, struct lttng_ust_filter_bytecode_node *filter); -void lttng_filter_event_link_bytecode(struct ltt_event *event); -void lttng_filter_event_link_wildcard_bytecode(struct ltt_event *event, +void lttng_filter_event_link_bytecode(struct lttng_event *event); +void lttng_filter_event_link_wildcard_bytecode(struct lttng_event *event, struct session_wildcard *wildcard); void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard); -void lttng_free_event_filter_bytecode(struct ltt_event *event); +void lttng_free_event_filter_bytecode(struct lttng_event *event); void lttng_free_wildcard_filter_bytecode(struct session_wildcard *wildcard); -void lttng_free_event_filter_runtime(struct ltt_event *event); +void lttng_free_event_filter_runtime(struct lttng_event *event); #endif /* _LTTNG_UST_EVENTS_H */ diff --git a/include/lttng/ust-tracepoint-event.h b/include/lttng/ust-tracepoint-event.h index 3cecec9b..0be3395b 100644 --- a/include/lttng/ust-tracepoint-event.h +++ b/include/lttng/ust-tracepoint-event.h @@ -467,8 +467,8 @@ void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); \ static \ void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)) \ { \ - struct ltt_event *__event = __tp_data; \ - struct ltt_channel *__chan = __event->chan; \ + struct lttng_event *__event = __tp_data; \ + struct lttng_channel *__chan = __event->chan; \ struct lttng_ust_lib_ring_buffer_ctx __ctx; \ size_t __event_len, __event_align; \ size_t __dynamic_len_idx = 0; \ @@ -651,7 +651,7 @@ _TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void) { int ret; - ret = ltt_probe_register(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); + ret = lttng_probe_register(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); assert(!ret); } @@ -660,7 +660,7 @@ _TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void); static void _TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void) { - ltt_probe_unregister(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); + lttng_probe_unregister(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); } int _TP_COMBINE_TOKENS(__tracepoint_provider_, TRACEPOINT_PROVIDER); diff --git a/include/lttng/ust-tracer.h b/include/lttng/ust-tracer.h index 7b371953..a6672c9d 100644 --- a/include/lttng/ust-tracer.h +++ b/include/lttng/ust-tracer.h @@ -1,5 +1,5 @@ -#ifndef _LTTNG_TRACER_H -#define _LTTNG_TRACER_H +#ifndef _LTTNG_UST_TRACER_H +#define _LTTNG_UST_TRACER_H /* * Copyright (C) 2005-2011 Mathieu Desnoyers @@ -39,4 +39,4 @@ #define lttng_is_signed_type(type) (((type)(-1)) < 0) -#endif /* _LTTNG_TRACER_CORE_H */ +#endif /* _LTTNG_UST_TRACER_H */ diff --git a/liblttng-ust/Makefile.am b/liblttng-ust/Makefile.am index dff8b6e9..f8b334aa 100644 --- a/liblttng-ust/Makefile.am +++ b/liblttng-ust/Makefile.am @@ -8,7 +8,7 @@ lib_LTLIBRARIES = liblttng-ust-tracepoint.la liblttng-ust.la liblttng_ust_tracepoint_la_SOURCES = \ tracepoint.c \ tracepoint-internal.h \ - ltt-tracer-core.h \ + lttng-tracer-core.h \ jhash.h \ error.h liblttng_ust_tracepoint_la_LIBADD = \ @@ -19,15 +19,15 @@ liblttng_ust_tracepoint_la_CFLAGS = -DUST_COMPONENT="liblttng_ust_tracepoint" -f liblttng_ust_runtime_la_SOURCES = \ lttng-ust-comm.c \ lttng-ust-abi.c \ - ltt-probes.c \ + lttng-probes.c \ probes/lttng-probe-ust.c \ probes/lttng-probe-ust.h \ lttng-context-vtid.c \ lttng-context-vpid.c \ lttng-context-pthread-id.c \ lttng-context-procname.c \ - ltt-context.c \ - ltt-events.c \ + lttng-context.c \ + lttng-events.c \ lttng-filter.c \ lttng-filter.h \ lttng-filter-validator.c \ @@ -44,14 +44,14 @@ liblttng_ust_runtime_la_SOURCES = \ lttng-ust-uuid.h liblttng_ust_support_la_SOURCES = \ - ltt-tracer.h \ - ltt-tracer-core.h \ + lttng-tracer.h \ + lttng-tracer-core.h \ ust-core.c \ - ltt-ring-buffer-client.h \ - ltt-ring-buffer-client-discard.c \ - ltt-ring-buffer-client-overwrite.c \ - ltt-ring-buffer-metadata-client.h \ - ltt-ring-buffer-metadata-client.c + lttng-ring-buffer-client.h \ + lttng-ring-buffer-client-discard.c \ + lttng-ring-buffer-client-overwrite.c \ + lttng-ring-buffer-metadata-client.h \ + lttng-ring-buffer-metadata-client.c liblttng_ust_la_SOURCES = diff --git a/liblttng-ust/ltt-context.c b/liblttng-ust/ltt-context.c deleted file mode 100644 index 16894ec1..00000000 --- a/liblttng-ust/ltt-context.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * lttng-context.c - * - * LTTng UST trace/channel/event context management. - * - * Copyright (C) 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; only - * 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 - */ - - -#include -#include -#include -#include -#include - -int lttng_find_context(struct lttng_ctx *ctx, const char *name) -{ - unsigned int i; - - for (i = 0; i < ctx->nr_fields; i++) { - /* Skip allocated (but non-initialized) contexts */ - if (!ctx->fields[i].event_field.name) - continue; - if (!strcmp(ctx->fields[i].event_field.name, name)) - return 1; - } - return 0; -} - -/* - * Note: as we append context information, the pointer location may change. - */ -struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p) -{ - struct lttng_ctx_field *field; - struct lttng_ctx *ctx; - - if (!*ctx_p) { - *ctx_p = zmalloc(sizeof(struct lttng_ctx)); - if (!*ctx_p) - return NULL; - } - ctx = *ctx_p; - if (ctx->nr_fields + 1 > ctx->allocated_fields) { - struct lttng_ctx_field *new_fields; - - ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields); - new_fields = zmalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field)); - if (!new_fields) - return NULL; - if (ctx->fields) - memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields); - free(ctx->fields); - ctx->fields = new_fields; - } - field = &ctx->fields[ctx->nr_fields]; - ctx->nr_fields++; - return field; -} - -/* - * Remove last context field. - */ -void lttng_remove_context_field(struct lttng_ctx **ctx_p, - struct lttng_ctx_field *field) -{ - struct lttng_ctx *ctx; - - ctx = *ctx_p; - ctx->nr_fields--; - assert(&ctx->fields[ctx->nr_fields] == field); - memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field)); -} - -void lttng_destroy_context(struct lttng_ctx *ctx) -{ - int i; - - if (!ctx) - return; - for (i = 0; i < ctx->nr_fields; i++) { - if (ctx->fields[i].destroy) - ctx->fields[i].destroy(&ctx->fields[i]); - } - free(ctx->fields); - free(ctx); -} diff --git a/liblttng-ust/ltt-events.c b/liblttng-ust/ltt-events.c deleted file mode 100644 index ee82413d..00000000 --- a/liblttng-ust/ltt-events.c +++ /dev/null @@ -1,1526 +0,0 @@ -/* - * ltt-events.c - * - * Holds LTTng per-session event registry. - * - * Copyright (C) 2010-2012 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; only - * 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 _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "clock.h" - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include "error.h" -#include "compat.h" -#include "lttng-ust-uuid.h" - -#include "tracepoint-internal.h" -#include "ltt-tracer.h" -#include "ltt-tracer-core.h" -#include "wait.h" -#include "../libringbuffer/shm.h" -#include "jhash.h" - -/* - * The sessions mutex is the centralized mutex across UST tracing - * control and probe registration. All operations within this file are - * called by the communication thread, under ust_lock protection. - */ -static pthread_mutex_t sessions_mutex = PTHREAD_MUTEX_INITIALIZER; - -void ust_lock(void) -{ - pthread_mutex_lock(&sessions_mutex); -} - -void ust_unlock(void) -{ - pthread_mutex_unlock(&sessions_mutex); -} - -static CDS_LIST_HEAD(sessions); - -/* - * Wildcard list, containing the active wildcards. - * Protected by ust lock. - */ -static CDS_LIST_HEAD(wildcard_list); - -/* - * Pending probes hash table, containing the registered ltt events for - * which tracepoint probes are still missing. Protected by the sessions - * mutex. - */ -#define PENDING_PROBE_HASH_BITS 6 -#define PENDING_PROBE_HASH_SIZE (1 << PENDING_PROBE_HASH_BITS) -static struct cds_hlist_head pending_probe_table[PENDING_PROBE_HASH_SIZE]; - -struct ust_pending_probe { - struct ltt_event *event; - struct cds_hlist_node node; - enum lttng_ust_loglevel_type loglevel_type; - int loglevel; - char name[]; -}; - -static void _ltt_event_destroy(struct ltt_event *event); -static void _ltt_wildcard_destroy(struct session_wildcard *sw); -static void _ltt_channel_destroy(struct ltt_channel *chan); -static int _ltt_event_unregister(struct ltt_event *event); -static -int _ltt_event_metadata_statedump(struct ltt_session *session, - struct ltt_channel *chan, - struct ltt_event *event); -static -int _ltt_session_metadata_statedump(struct ltt_session *session); - -int ltt_loglevel_match(const struct lttng_event_desc *desc, - enum lttng_ust_loglevel_type req_type, - int req_loglevel) -{ - int ev_loglevel; - - if (req_type == LTTNG_UST_LOGLEVEL_ALL) - return 1; - if (!desc->loglevel) - ev_loglevel = TRACE_DEFAULT; - else - ev_loglevel = *(*desc->loglevel); - switch (req_type) { - case LTTNG_UST_LOGLEVEL_RANGE: - if (ev_loglevel <= req_loglevel || req_loglevel == -1) - return 1; - else - return 0; - case LTTNG_UST_LOGLEVEL_SINGLE: - if (ev_loglevel == req_loglevel || req_loglevel == -1) - return 1; - else - return 0; - case LTTNG_UST_LOGLEVEL_ALL: - default: - return 1; - } -} - -/* - * Return wildcard for a given event name if the event name match the - * one of the wildcards. - * Must be called with ust lock held. - * Returns NULL if not present. - */ -static -struct wildcard_entry *match_wildcard(const struct lttng_event_desc *desc) -{ - struct wildcard_entry *e; - - cds_list_for_each_entry(e, &wildcard_list, list) { - /* If only contain '*' */ - if (strlen(e->name) == 1) - goto possible_match; - /* Compare excluding final '*' */ - if (!strncmp(desc->name, e->name, strlen(e->name) - 1)) - goto possible_match; - continue; /* goto next, no match */ - possible_match: - if (ltt_loglevel_match(desc, - e->loglevel_type, - e->loglevel)) { - return e; - } - /* no match, loop to next */ - } - return NULL; -} - -/* - * called at event creation if probe is missing. - * called with session mutex held. - */ -static -int add_pending_probe(struct ltt_event *event, const char *name, - enum lttng_ust_loglevel_type loglevel_type, - int loglevel) -{ - struct cds_hlist_head *head; - struct ust_pending_probe *e; - size_t name_len = strlen(name) + 1; - uint32_t hash; - - if (name_len > LTTNG_UST_SYM_NAME_LEN) { - WARN("Truncating tracepoint name %s which exceeds size limits of %u chars", name, LTTNG_UST_SYM_NAME_LEN); - name_len = LTTNG_UST_SYM_NAME_LEN; - } - hash = jhash(name, name_len - 1, 0); - head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)]; - e = zmalloc(sizeof(struct ust_pending_probe) + name_len); - if (!e) - return -ENOMEM; - memcpy(&e->name[0], name, name_len); - e->name[name_len - 1] = '\0'; - e->loglevel_type = loglevel_type; - e->loglevel = loglevel; - cds_hlist_add_head(&e->node, head); - e->event = event; - event->pending_probe = e; - return 0; -} - -/* - * remove a pending probe. called when at event teardown and when an - * event is fixed (probe is loaded). - * called with session mutex held. - */ -static -void remove_pending_probe(struct ust_pending_probe *e) -{ - if (!e) - return; - cds_hlist_del(&e->node); - free(e); -} - -/* - * Called at library load: connect the probe on the events pending on - * probe load. - * called with session mutex held. - */ -int pending_probe_fix_events(const struct lttng_event_desc *desc) -{ - struct cds_hlist_head *head; - struct cds_hlist_node *node, *p; - struct ust_pending_probe *e; - const char *name = desc->name; - int ret = 0; - struct lttng_ust_event event_param; - size_t name_len = strlen(name) + 1; - uint32_t hash; - - /* Wildcard */ - { - struct wildcard_entry *wildcard; - - //FIXME: should iterate on all match for filter. - //FIXME: should re-use pending event if present rather - //than create duplicate. - wildcard = match_wildcard(desc); - if (strcmp(desc->name, "lttng_ust:metadata") && wildcard) { - struct session_wildcard *sw; - - cds_list_for_each_entry(sw, &wildcard->session_list, - session_list) { - struct ltt_event *ev; - int ret; - - memcpy(&event_param, &sw->event_param, - sizeof(event_param)); - strncpy(event_param.name, - desc->name, - sizeof(event_param.name)); - event_param.name[sizeof(event_param.name) - 1] = '\0'; - /* create event */ - ret = ltt_event_create(sw->chan, - &event_param, &ev); - if (ret) { - DBG("Error creating event"); - continue; - } - cds_list_add(&ev->wildcard_list, - &sw->events); - lttng_filter_event_link_wildcard_bytecode(ev, - sw); - } - } - } - - if (name_len > LTTNG_UST_SYM_NAME_LEN) { - WARN("Truncating tracepoint name %s which exceeds size limits of %u chars", name, LTTNG_UST_SYM_NAME_LEN); - name_len = LTTNG_UST_SYM_NAME_LEN; - } - hash = jhash(name, name_len - 1, 0); - head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)]; - cds_hlist_for_each_entry_safe(e, node, p, head, node) { - struct ltt_event *event; - struct ltt_channel *chan; - - if (!ltt_loglevel_match(desc, - e->loglevel_type, - e->loglevel)) { - continue; - } - if (strncmp(name, e->name, LTTNG_UST_SYM_NAME_LEN - 1)) { - continue; - } - /* TODO: wildcard same as pending event: duplicate */ - /* TODO: Should apply filter though */ - event = e->event; - chan = event->chan; - assert(!event->desc); - event->desc = desc; - event->pending_probe = NULL; - remove_pending_probe(e); - ret |= __tracepoint_probe_register(name, - event->desc->probe_callback, - event, event->desc->signature); - if (ret) - continue; - event->id = chan->free_event_id++; - ret |= _ltt_event_metadata_statedump(chan->session, chan, - event); - lttng_filter_event_link_bytecode(event); - } - return ret; -} - -void synchronize_trace(void) -{ - synchronize_rcu(); -} - -struct ltt_session *ltt_session_create(void) -{ - struct ltt_session *session; - int ret; - - session = zmalloc(sizeof(struct ltt_session)); - if (!session) - return NULL; - CDS_INIT_LIST_HEAD(&session->chan); - CDS_INIT_LIST_HEAD(&session->events); - CDS_INIT_LIST_HEAD(&session->wildcards); - ret = lttng_ust_uuid_generate(session->uuid); - if (ret != 0) { - session->uuid[0] = '\0'; - } - cds_list_add(&session->list, &sessions); - return session; -} - -void ltt_session_destroy(struct ltt_session *session) -{ - struct ltt_channel *chan, *tmpchan; - struct ltt_event *event, *tmpevent; - struct session_wildcard *wildcard, *tmpwildcard; - int ret; - - CMM_ACCESS_ONCE(session->active) = 0; - cds_list_for_each_entry(event, &session->events, list) { - ret = _ltt_event_unregister(event); - WARN_ON(ret); - } - synchronize_trace(); /* Wait for in-flight events to complete */ - cds_list_for_each_entry_safe(wildcard, tmpwildcard, &session->wildcards, list) - _ltt_wildcard_destroy(wildcard); - cds_list_for_each_entry_safe(event, tmpevent, &session->events, list) - _ltt_event_destroy(event); - cds_list_for_each_entry_safe(chan, tmpchan, &session->chan, list) - _ltt_channel_destroy(chan); - cds_list_del(&session->list); - free(session); -} - -int ltt_session_enable(struct ltt_session *session) -{ - int ret = 0; - struct ltt_channel *chan; - - if (session->active) { - ret = -EBUSY; - goto end; - } - - /* - * Snapshot the number of events per channel to know the type of header - * we need to use. - */ - cds_list_for_each_entry(chan, &session->chan, list) { - if (chan->header_type) - continue; /* don't change it if session stop/restart */ - if (chan->free_event_id < 31) - chan->header_type = 1; /* compact */ - else - chan->header_type = 2; /* large */ - } - - CMM_ACCESS_ONCE(session->active) = 1; - CMM_ACCESS_ONCE(session->been_active) = 1; - ret = _ltt_session_metadata_statedump(session); - if (ret) - CMM_ACCESS_ONCE(session->active) = 0; -end: - return ret; -} - -int ltt_session_disable(struct ltt_session *session) -{ - int ret = 0; - - if (!session->active) { - ret = -EBUSY; - goto end; - } - CMM_ACCESS_ONCE(session->active) = 0; -end: - return ret; -} - -int ltt_channel_enable(struct ltt_channel *channel) -{ - int old; - - if (channel == channel->session->metadata) - return -EPERM; - old = uatomic_xchg(&channel->enabled, 1); - if (old) - return -EEXIST; - return 0; -} - -int ltt_channel_disable(struct ltt_channel *channel) -{ - int old; - - if (channel == channel->session->metadata) - return -EPERM; - old = uatomic_xchg(&channel->enabled, 0); - if (!old) - return -EEXIST; - return 0; -} - -int ltt_event_enable(struct ltt_event *event) -{ - int old; - - if (event->chan == event->chan->session->metadata) - return -EPERM; - old = uatomic_xchg(&event->enabled, 1); - if (old) - return -EEXIST; - return 0; -} - -int ltt_event_disable(struct ltt_event *event) -{ - int old; - - if (event->chan == event->chan->session->metadata) - return -EPERM; - old = uatomic_xchg(&event->enabled, 0); - if (!old) - return -EEXIST; - return 0; -} - -struct ltt_channel *ltt_channel_create(struct ltt_session *session, - const char *transport_name, - void *buf_addr, - size_t subbuf_size, size_t num_subbuf, - unsigned int switch_timer_interval, - unsigned int read_timer_interval, - int **shm_fd, int **wait_fd, - uint64_t **memory_map_size, - struct ltt_channel *chan_priv_init) -{ - struct ltt_channel *chan = NULL; - struct ltt_transport *transport; - - if (session->been_active) - goto active; /* Refuse to add channel to active session */ - transport = ltt_transport_find(transport_name); - if (!transport) { - DBG("LTTng transport %s not found\n", - transport_name); - goto notransport; - } - chan_priv_init->id = session->free_chan_id++; - chan_priv_init->session = session; - /* - * Note: the channel creation op already writes into the packet - * headers. Therefore the "chan" information used as input - * should be already accessible. - */ - chan = transport->ops.channel_create(transport_name, buf_addr, - subbuf_size, num_subbuf, switch_timer_interval, - read_timer_interval, shm_fd, wait_fd, - memory_map_size, chan_priv_init); - if (!chan) - goto create_error; - chan->enabled = 1; - chan->ops = &transport->ops; - cds_list_add(&chan->list, &session->chan); - return chan; - -create_error: -notransport: -active: - return NULL; -} - -/* - * Only used internally at session destruction. - */ -static -void _ltt_channel_destroy(struct ltt_channel *chan) -{ - cds_list_del(&chan->list); - lttng_destroy_context(chan->ctx); - chan->ops->channel_destroy(chan); -} - -/* - * Supports event creation while tracing session is active. - */ -int ltt_event_create(struct ltt_channel *chan, - struct lttng_ust_event *event_param, - struct ltt_event **_event) -{ - const struct lttng_event_desc *desc = NULL; /* silence gcc */ - struct ltt_event *event; - int ret = 0; - - if (chan->used_event_id == -1U) { - ret = -ENOMEM; - goto full; - } - //FIXME: re-use event if already registered by wildcard or - //if we have a pending probe.... (CHECK) - /* - * This is O(n^2) (for each event, the loop is called at event - * creation). Might require a hash if we have lots of events. - */ - cds_list_for_each_entry(event, &chan->session->events, list) { - if (event->desc && !strncmp(event->desc->name, - event_param->name, - LTTNG_UST_SYM_NAME_LEN - 1)) { - ret = -EEXIST; - goto exist; - } - } - - /* - * Check if loglevel match. Refuse to connect event if not. - */ - if (event_param->instrumentation == LTTNG_UST_TRACEPOINT) { - desc = ltt_event_get(event_param->name); - if (desc) { - if (!ltt_loglevel_match(desc, - event_param->loglevel_type, - event_param->loglevel)) { - ret = -EPERM; - goto no_loglevel_match; - } - } - /* - * If descriptor is not there, it will be added to - * pending probes. - */ - } - event = zmalloc(sizeof(struct ltt_event)); - if (!event) { - ret = -ENOMEM; - goto cache_error; - } - event->chan = chan; - /* - * used_event_id counts the maximum number of event IDs that can - * register if all probes register. - */ - chan->used_event_id++; - event->enabled = 1; - CDS_INIT_LIST_HEAD(&event->filter_bytecode); - CDS_INIT_LIST_HEAD(&event->bytecode_runtime); - event->instrumentation = event_param->instrumentation; - /* Populate ltt_event structure before tracepoint registration. */ - cmm_smp_wmb(); - switch (event_param->instrumentation) { - case LTTNG_UST_TRACEPOINT: - event->desc = desc; - if (event->desc) { - ret = __tracepoint_probe_register(event_param->name, - event->desc->probe_callback, - event, event->desc->signature); - if (ret) - goto register_error; - event->id = chan->free_event_id++; - } else { - /* - * If the probe is not present, event->desc stays NULL, - * waiting for the probe to register, and the event->id - * stays unallocated. - */ - ret = add_pending_probe(event, event_param->name, - event_param->loglevel_type, - event_param->loglevel); - if (ret) - goto add_pending_error; - } - break; - default: - WARN_ON_ONCE(1); - } - if (event->desc) { - ret = _ltt_event_metadata_statedump(chan->session, chan, event); - if (ret) - goto statedump_error; - } - cds_list_add(&event->list, &chan->session->events); - *_event = event; - return 0; - -statedump_error: - if (event->desc) { - WARN_ON_ONCE(__tracepoint_probe_unregister(event_param->name, - event->desc->probe_callback, - event)); - ltt_event_put(event->desc); - } -add_pending_error: -register_error: - free(event); -cache_error: -no_loglevel_match: -exist: -full: - return ret; -} - -/* - * Only used internally at session destruction. - */ -int _ltt_event_unregister(struct ltt_event *event) -{ - int ret = -EINVAL; - - switch (event->instrumentation) { - case LTTNG_UST_TRACEPOINT: - if (event->desc) { - ret = __tracepoint_probe_unregister(event->desc->name, - event->desc->probe_callback, - event); - if (ret) - return ret; - } else { - remove_pending_probe(event->pending_probe); - ret = 0; - } - break; - default: - WARN_ON_ONCE(1); - } - return ret; -} - -/* - * Only used internally at session destruction. - */ -static -void _ltt_event_destroy(struct ltt_event *event) -{ - switch (event->instrumentation) { - case LTTNG_UST_TRACEPOINT: - if (event->desc) { - ltt_event_put(event->desc); - } - break; - default: - WARN_ON_ONCE(1); - } - cds_list_del(&event->list); - lttng_destroy_context(event->ctx); - lttng_free_event_filter_runtime(event); - lttng_free_event_filter_bytecode(event); - free(event); -} - -/* - * We have exclusive access to our metadata buffer (protected by the - * ust_lock), so we can do racy operations such as looking for - * remaining space left in packet and write, since mutual exclusion - * protects us from concurrent writes. - */ -int lttng_metadata_printf(struct ltt_session *session, - const char *fmt, ...) -{ - struct lttng_ust_lib_ring_buffer_ctx ctx; - struct ltt_channel *chan = session->metadata; - char *str = NULL; - int ret = 0, waitret; - size_t len, reserve_len, pos; - va_list ap; - - WARN_ON_ONCE(!CMM_ACCESS_ONCE(session->active)); - - va_start(ap, fmt); - ret = vasprintf(&str, fmt, ap); - va_end(ap); - if (ret < 0) - return -ENOMEM; - - len = strlen(str); - pos = 0; - - for (pos = 0; pos < len; pos += reserve_len) { - reserve_len = min_t(size_t, - chan->ops->packet_avail_size(chan->chan, chan->handle), - len - pos); - lib_ring_buffer_ctx_init(&ctx, chan->chan, NULL, reserve_len, - sizeof(char), -1, chan->handle); - /* - * We don't care about metadata buffer's records lost - * count, because we always retry here. Report error if - * we need to bail out after timeout or being - * interrupted. - */ - waitret = wait_cond_interruptible_timeout( - ({ - ret = chan->ops->event_reserve(&ctx, 0); - ret != -ENOBUFS || !ret; - }), - LTTNG_METADATA_TIMEOUT_MSEC); - if (waitret == -ETIMEDOUT || waitret == -EINTR || ret) { - DBG("LTTng: Failure to write metadata to buffers (%s)\n", - waitret == -EINTR ? "interrupted" : - (ret == -ENOBUFS ? "timeout" : "I/O error")); - if (waitret == -EINTR) - ret = waitret; - goto end; - } - chan->ops->event_write(&ctx, &str[pos], reserve_len); - chan->ops->event_commit(&ctx); - } -end: - free(str); - return ret; -} - -static -int _ltt_field_statedump(struct ltt_session *session, - const struct lttng_event_field *field) -{ - int ret = 0; - - if (field->nowrite) - return 0; - - switch (field->type.atype) { - case atype_integer: - ret = lttng_metadata_printf(session, - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n", - field->type.u.basic.integer.size, - field->type.u.basic.integer.alignment, - field->type.u.basic.integer.signedness, - (field->type.u.basic.integer.encoding == lttng_encode_none) - ? "none" - : (field->type.u.basic.integer.encoding == lttng_encode_UTF8) - ? "UTF8" - : "ASCII", - field->type.u.basic.integer.base, -#if (BYTE_ORDER == BIG_ENDIAN) - field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", -#else - field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", -#endif - field->name); - break; - case atype_float: - ret = lttng_metadata_printf(session, - " floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n", - field->type.u.basic._float.exp_dig, - field->type.u.basic._float.mant_dig, - field->type.u.basic._float.alignment, -#if (BYTE_ORDER == BIG_ENDIAN) - field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", -#else - field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", -#endif - field->name); - break; - case atype_enum: - ret = lttng_metadata_printf(session, - " %s %s;\n", - field->type.u.basic.enumeration.name, - field->name); - break; - case atype_array: - { - const struct lttng_basic_type *elem_type; - - elem_type = &field->type.u.array.elem_type; - ret = lttng_metadata_printf(session, - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n", - elem_type->u.basic.integer.size, - elem_type->u.basic.integer.alignment, - elem_type->u.basic.integer.signedness, - (elem_type->u.basic.integer.encoding == lttng_encode_none) - ? "none" - : (elem_type->u.basic.integer.encoding == lttng_encode_UTF8) - ? "UTF8" - : "ASCII", - elem_type->u.basic.integer.base, -#if (BYTE_ORDER == BIG_ENDIAN) - elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", -#else - elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", -#endif - field->name, field->type.u.array.length); - break; - } - case atype_sequence: - { - const struct lttng_basic_type *elem_type; - const struct lttng_basic_type *length_type; - - elem_type = &field->type.u.sequence.elem_type; - length_type = &field->type.u.sequence.length_type; - ret = lttng_metadata_printf(session, - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n", - length_type->u.basic.integer.size, - (unsigned int) length_type->u.basic.integer.alignment, - length_type->u.basic.integer.signedness, - (length_type->u.basic.integer.encoding == lttng_encode_none) - ? "none" - : ((length_type->u.basic.integer.encoding == lttng_encode_UTF8) - ? "UTF8" - : "ASCII"), - length_type->u.basic.integer.base, -#if (BYTE_ORDER == BIG_ENDIAN) - length_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", -#else - length_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", -#endif - field->name); - if (ret) - return ret; - - ret = lttng_metadata_printf(session, - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n", - elem_type->u.basic.integer.size, - (unsigned int) elem_type->u.basic.integer.alignment, - elem_type->u.basic.integer.signedness, - (elem_type->u.basic.integer.encoding == lttng_encode_none) - ? "none" - : ((elem_type->u.basic.integer.encoding == lttng_encode_UTF8) - ? "UTF8" - : "ASCII"), - elem_type->u.basic.integer.base, -#if (BYTE_ORDER == BIG_ENDIAN) - elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", -#else - elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", -#endif - field->name, - field->name); - break; - } - - case atype_string: - /* Default encoding is UTF8 */ - ret = lttng_metadata_printf(session, - " string%s _%s;\n", - field->type.u.basic.string.encoding == lttng_encode_ASCII ? - " { encoding = ASCII; }" : "", - field->name); - break; - default: - WARN_ON_ONCE(1); - return -EINVAL; - } - return ret; -} - -static -int _ltt_context_metadata_statedump(struct ltt_session *session, - struct lttng_ctx *ctx) -{ - int ret = 0; - int i; - - if (!ctx) - return 0; - for (i = 0; i < ctx->nr_fields; i++) { - const struct lttng_ctx_field *field = &ctx->fields[i]; - - ret = _ltt_field_statedump(session, &field->event_field); - if (ret) - return ret; - } - return ret; -} - -static -int _ltt_fields_metadata_statedump(struct ltt_session *session, - struct ltt_event *event) -{ - const struct lttng_event_desc *desc = event->desc; - int ret = 0; - int i; - - for (i = 0; i < desc->nr_fields; i++) { - const struct lttng_event_field *field = &desc->fields[i]; - - ret = _ltt_field_statedump(session, field); - if (ret) - return ret; - } - return ret; -} - -static -int _ltt_event_metadata_statedump(struct ltt_session *session, - struct ltt_channel *chan, - struct ltt_event *event) -{ - int ret = 0; - int loglevel = TRACE_DEFAULT; - - if (event->metadata_dumped || !CMM_ACCESS_ONCE(session->active)) - return 0; - if (chan == session->metadata) - return 0; - /* - * Don't print events for which probe load is pending. - */ - if (!event->desc) - return 0; - - ret = lttng_metadata_printf(session, - "event {\n" - " name = \"%s\";\n" - " id = %u;\n" - " stream_id = %u;\n", - event->desc->name, - event->id, - event->chan->id); - if (ret) - goto end; - - if (event->desc->loglevel) - loglevel = *(*event->desc->loglevel); - - ret = lttng_metadata_printf(session, - " loglevel = %d;\n", - loglevel); - if (ret) - goto end; - - if (event->desc->u.ext.model_emf_uri) { - ret = lttng_metadata_printf(session, - " model.emf.uri = \"%s\";\n", - *(event->desc->u.ext.model_emf_uri)); - if (ret) - goto end; - } - - if (event->ctx) { - ret = lttng_metadata_printf(session, - " context := struct {\n"); - if (ret) - goto end; - } - ret = _ltt_context_metadata_statedump(session, event->ctx); - if (ret) - goto end; - if (event->ctx) { - ret = lttng_metadata_printf(session, - " };\n"); - if (ret) - goto end; - } - - ret = lttng_metadata_printf(session, - " fields := struct {\n" - ); - if (ret) - goto end; - - ret = _ltt_fields_metadata_statedump(session, event); - if (ret) - goto end; - - /* - * LTTng space reservation can only reserve multiples of the - * byte size. - */ - ret = lttng_metadata_printf(session, - " };\n" - "};\n\n"); - if (ret) - goto end; - - event->metadata_dumped = 1; -end: - return ret; - -} - -static -int _ltt_channel_metadata_statedump(struct ltt_session *session, - struct ltt_channel *chan) -{ - int ret = 0; - - if (chan->metadata_dumped || !CMM_ACCESS_ONCE(session->active)) - return 0; - if (chan == session->metadata) - return 0; - - WARN_ON_ONCE(!chan->header_type); - ret = lttng_metadata_printf(session, - "stream {\n" - " id = %u;\n" - " event.header := %s;\n" - " packet.context := struct packet_context;\n", - chan->id, - chan->header_type == 1 ? "struct event_header_compact" : - "struct event_header_large"); - if (ret) - goto end; - - if (chan->ctx) { - ret = lttng_metadata_printf(session, - " event.context := struct {\n"); - if (ret) - goto end; - } - ret = _ltt_context_metadata_statedump(session, chan->ctx); - if (ret) - goto end; - if (chan->ctx) { - ret = lttng_metadata_printf(session, - " };\n"); - if (ret) - goto end; - } - - ret = lttng_metadata_printf(session, - "};\n\n"); - - chan->metadata_dumped = 1; -end: - return ret; -} - -static -int _ltt_stream_packet_context_declare(struct ltt_session *session) -{ - return lttng_metadata_printf(session, - "struct packet_context {\n" - " uint64_clock_monotonic_t timestamp_begin;\n" - " uint64_clock_monotonic_t timestamp_end;\n" - " uint64_t content_size;\n" - " uint64_t packet_size;\n" - " unsigned long events_discarded;\n" - " uint32_t cpu_id;\n" - "};\n\n" - ); -} - -/* - * Compact header: - * id: range: 0 - 30. - * id 31 is reserved to indicate an extended header. - * - * Large header: - * id: range: 0 - 65534. - * id 65535 is reserved to indicate an extended header. - */ -static -int _ltt_event_header_declare(struct ltt_session *session) -{ - return lttng_metadata_printf(session, - "struct event_header_compact {\n" - " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n" - " variant {\n" - " struct {\n" - " uint27_clock_monotonic_t timestamp;\n" - " } compact;\n" - " struct {\n" - " uint32_t id;\n" - " uint64_clock_monotonic_t timestamp;\n" - " } extended;\n" - " } v;\n" - "} align(%u);\n" - "\n" - "struct event_header_large {\n" - " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n" - " variant {\n" - " struct {\n" - " uint32_clock_monotonic_t timestamp;\n" - " } compact;\n" - " struct {\n" - " uint32_t id;\n" - " uint64_clock_monotonic_t timestamp;\n" - " } extended;\n" - " } v;\n" - "} align(%u);\n\n", - lttng_alignof(uint32_t) * CHAR_BIT, - lttng_alignof(uint16_t) * CHAR_BIT - ); -} - -/* - * Approximation of NTP time of day to clock monotonic correlation, - * taken at start of trace. - * Yes, this is only an approximation. Yes, we can (and will) do better - * in future versions. - */ -static -uint64_t measure_clock_offset(void) -{ - uint64_t offset, monotonic[2], realtime; - struct timespec rts = { 0, 0 }; - int ret; - - monotonic[0] = trace_clock_read64(); - ret = clock_gettime(CLOCK_REALTIME, &rts); - if (ret < 0) - return 0; - monotonic[1] = trace_clock_read64(); - offset = (monotonic[0] + monotonic[1]) >> 1; - realtime = (uint64_t) rts.tv_sec * 1000000000ULL; - realtime += rts.tv_nsec; - offset = realtime - offset; - return offset; -} - -/* - * Output metadata into this session's metadata buffers. - */ -static -int _ltt_session_metadata_statedump(struct ltt_session *session) -{ - unsigned char *uuid_c = session->uuid; - char uuid_s[LTTNG_UST_UUID_STR_LEN], - clock_uuid_s[LTTNG_UST_UUID_STR_LEN]; - struct ltt_channel *chan; - struct ltt_event *event; - int ret = 0; - char procname[LTTNG_UST_PROCNAME_LEN] = ""; - char hostname[HOST_NAME_MAX]; - - if (!CMM_ACCESS_ONCE(session->active)) - return 0; - if (session->metadata_dumped) - goto skip_session; - if (!session->metadata) { - DBG("LTTng: attempt to start tracing, but metadata channel is not found. Operation abort.\n"); - return -EPERM; - } - - snprintf(uuid_s, sizeof(uuid_s), - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - uuid_c[0], uuid_c[1], uuid_c[2], uuid_c[3], - uuid_c[4], uuid_c[5], uuid_c[6], uuid_c[7], - uuid_c[8], uuid_c[9], uuid_c[10], uuid_c[11], - uuid_c[12], uuid_c[13], uuid_c[14], uuid_c[15]); - - ret = lttng_metadata_printf(session, - "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n" - "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n" - "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n" - "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n" - "typealias integer { size = %u; align = %u; signed = false; } := unsigned long;\n" - "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n" - "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n" - "\n" - "trace {\n" - " major = %u;\n" - " minor = %u;\n" - " uuid = \"%s\";\n" - " byte_order = %s;\n" - " packet.header := struct {\n" - " uint32_t magic;\n" - " uint8_t uuid[16];\n" - " uint32_t stream_id;\n" - " };\n" - "};\n\n", - lttng_alignof(uint8_t) * CHAR_BIT, - lttng_alignof(uint16_t) * CHAR_BIT, - lttng_alignof(uint32_t) * CHAR_BIT, - lttng_alignof(uint64_t) * CHAR_BIT, - sizeof(unsigned long) * CHAR_BIT, - lttng_alignof(unsigned long) * CHAR_BIT, - CTF_SPEC_MAJOR, - CTF_SPEC_MINOR, - uuid_s, -#if (BYTE_ORDER == BIG_ENDIAN) - "be" -#else - "le" -#endif - ); - if (ret) - goto end; - - /* ignore error, just use empty string if error. */ - hostname[0] = '\0'; - ret = gethostname(hostname, sizeof(hostname)); - if (ret && errno == ENAMETOOLONG) - hostname[HOST_NAME_MAX - 1] = '\0'; - lttng_ust_getprocname(procname); - procname[LTTNG_UST_PROCNAME_LEN - 1] = '\0'; - ret = lttng_metadata_printf(session, - "env {\n" - " hostname = \"%s\";\n" - " vpid = %d;\n" - " procname = \"%s\";\n" - " domain = \"ust\";\n" - " tracer_name = \"lttng-ust\";\n" - " tracer_major = %u;\n" - " tracer_minor = %u;\n" - " tracer_patchlevel = %u;\n" - "};\n\n", - hostname, - (int) getpid(), - procname, - LTTNG_UST_MAJOR_VERSION, - LTTNG_UST_MINOR_VERSION, - LTTNG_UST_PATCHLEVEL_VERSION - ); - if (ret) - goto end; - - ret = lttng_metadata_printf(session, - "clock {\n" - " name = %s;\n", - "monotonic" - ); - if (ret) - goto end; - - if (!trace_clock_uuid(clock_uuid_s)) { - ret = lttng_metadata_printf(session, - " uuid = \"%s\";\n", - clock_uuid_s - ); - if (ret) - goto end; - } - - ret = lttng_metadata_printf(session, - " description = \"Monotonic Clock\";\n" - " freq = %" PRIu64 "; /* Frequency, in Hz */\n" - " /* clock value offset from Epoch is: offset * (1/freq) */\n" - " offset = %" PRIu64 ";\n" - "};\n\n", - trace_clock_freq(), - measure_clock_offset() - ); - if (ret) - goto end; - - ret = lttng_metadata_printf(session, - "typealias integer {\n" - " size = 27; align = 1; signed = false;\n" - " map = clock.monotonic.value;\n" - "} := uint27_clock_monotonic_t;\n" - "\n" - "typealias integer {\n" - " size = 32; align = %u; signed = false;\n" - " map = clock.monotonic.value;\n" - "} := uint32_clock_monotonic_t;\n" - "\n" - "typealias integer {\n" - " size = 64; align = %u; signed = false;\n" - " map = clock.monotonic.value;\n" - "} := uint64_clock_monotonic_t;\n\n", - lttng_alignof(uint32_t) * CHAR_BIT, - lttng_alignof(uint64_t) * CHAR_BIT - ); - if (ret) - goto end; - - ret = _ltt_stream_packet_context_declare(session); - if (ret) - goto end; - - ret = _ltt_event_header_declare(session); - if (ret) - goto end; - -skip_session: - cds_list_for_each_entry(chan, &session->chan, list) { - ret = _ltt_channel_metadata_statedump(session, chan); - if (ret) - goto end; - } - - cds_list_for_each_entry(event, &session->events, list) { - ret = _ltt_event_metadata_statedump(session, event->chan, event); - if (ret) - goto end; - } - session->metadata_dumped = 1; -end: - return ret; -} - -void lttng_ust_events_exit(void) -{ - struct ltt_session *session, *tmpsession; - - cds_list_for_each_entry_safe(session, tmpsession, &sessions, list) - ltt_session_destroy(session); -} - -/* WILDCARDS */ - -static -int wildcard_same_loglevel(struct wildcard_entry *e, - enum lttng_ust_loglevel_type loglevel_type, - int loglevel) -{ - if (e->loglevel_type == loglevel_type && e->loglevel == loglevel) - return 1; - else - return 0; -} - -#if 0 -static -int wildcard_is_within(struct wildcard_entry *e, - enum lttng_ust_loglevel_type loglevel_type, - int loglevel) -{ - if (e->loglevel_type == LTTNG_UST_LOGLEVEL_ALL - || e->loglevel == -1) - return 1; - switch (e->loglevel_type) { - case LTTNG_UST_LOGLEVEL_RANGE: - switch (loglevel_type) { - case LTTNG_UST_LOGLEVEL_RANGE: - if (e->loglevel >= loglevel) - return 1; - else - return 0; - case LTTNG_UST_LOGLEVEL_SINGLE: - if (e->loglevel <= 0 && loglevel == 0) - return 1; - else - return 0; - } - case LTTNG_UST_LOGLEVEL_SINGLE: - switch (loglevel_type) { - case LTTNG_UST_LOGLEVEL_RANGE: - if (loglevel <= 0) - return 1; - else - return 0; - case LTTNG_UST_LOGLEVEL_SINGLE: - if (e->loglevel == loglevel) - return 1; - else - return 0; - } - } -} -#endif - -/* - * Add the wildcard to the wildcard list. Must be called with - * ust lock held. - */ -static -struct session_wildcard *add_wildcard(struct ltt_channel *chan, - struct lttng_ust_event *event_param) -{ - struct wildcard_entry *e; - struct session_wildcard *sw; - size_t name_len = strlen(event_param->name) + 1; - int found = 0; - - //FIXME: ensure that wildcard re-use pending events, or - //re-use actual events, applying its filter on top. - - /* - * Try to find global wildcard entry. Given that this is shared - * across all sessions, we need to check for exact loglevel - * match, not just whether contained within the existing ones. - */ - cds_list_for_each_entry(e, &wildcard_list, list) { - if (!strncmp(event_param->name, e->name, - LTTNG_UST_SYM_NAME_LEN - 1)) { - if (wildcard_same_loglevel(e, - event_param->loglevel_type, - event_param->loglevel)) { - found = 1; - break; - } - } - } - - if (!found) { - /* - * Create global wildcard entry if not found. Using - * zmalloc here to allocate a variable length element. - * Could cause some memory fragmentation if overused. - */ - e = zmalloc(sizeof(struct wildcard_entry) + name_len); - if (!e) - return ERR_PTR(-ENOMEM); - memcpy(&e->name[0], event_param->name, name_len); - e->loglevel_type = event_param->loglevel_type; - e->loglevel = event_param->loglevel; - CDS_INIT_LIST_HEAD(&e->filter_bytecode); - cds_list_add(&e->list, &wildcard_list); - CDS_INIT_LIST_HEAD(&e->session_list); - } - - /* session wildcard */ - cds_list_for_each_entry(sw, &e->session_list, session_list) { - if (chan == sw->chan) { - DBG("wildcard %s busy for this channel", - event_param->name); - return ERR_PTR(-EEXIST); /* Already there */ - } - } - sw = zmalloc(sizeof(struct session_wildcard)); - if (!sw) - return ERR_PTR(-ENOMEM); - sw->chan = chan; - sw->enabled = 1; - memcpy(&sw->event_param, event_param, sizeof(sw->event_param)); - sw->event_param.instrumentation = LTTNG_UST_TRACEPOINT; - sw->event_param.loglevel_type = event_param->loglevel_type; - sw->event_param.loglevel = event_param->loglevel; - CDS_INIT_LIST_HEAD(&sw->filter_bytecode); - CDS_INIT_LIST_HEAD(&sw->events); - cds_list_add(&sw->list, &chan->session->wildcards); - cds_list_add(&sw->session_list, &e->session_list); - sw->entry = e; - ltt_probes_create_wildcard_events(e, sw); - return sw; -} - -/* - * Remove the wildcard from the wildcard list. Must be called with - * ust_lock held. Only called at session teardown. - */ -static -void _remove_wildcard(struct session_wildcard *wildcard) -{ - struct ltt_event *ev, *tmp; - - /* - * Just remove the events owned (for enable/disable) by this - * wildcard from the list. The session teardown will take care - * of freeing the event memory. - */ - cds_list_for_each_entry_safe(ev, tmp, &wildcard->events, - wildcard_list) { - cds_list_del(&ev->wildcard_list); - } - cds_list_del(&wildcard->session_list); - cds_list_del(&wildcard->list); - if (cds_list_empty(&wildcard->entry->session_list)) { - cds_list_del(&wildcard->entry->list); - free(wildcard->entry); - } - lttng_free_wildcard_filter_bytecode(wildcard); - free(wildcard); -} - -int ltt_wildcard_create(struct ltt_channel *chan, - struct lttng_ust_event *event_param, - struct session_wildcard **_sw) -{ - struct session_wildcard *sw; - - sw = add_wildcard(chan, event_param); - if (!sw || IS_ERR(sw)) { - return PTR_ERR(sw); - } - *_sw = sw; - return 0; -} - -static -void _ltt_wildcard_destroy(struct session_wildcard *sw) -{ - _remove_wildcard(sw); -} - -int ltt_wildcard_enable(struct session_wildcard *wildcard) -{ - struct ltt_event *ev; - int ret; - - if (wildcard->enabled) - return -EEXIST; - cds_list_for_each_entry(ev, &wildcard->events, wildcard_list) { - ret = ltt_event_enable(ev); - if (ret) { - DBG("Error: enable error.\n"); - return ret; - } - } - wildcard->enabled = 1; - return 0; -} - -int ltt_wildcard_disable(struct session_wildcard *wildcard) -{ - struct ltt_event *ev; - int ret; - - if (!wildcard->enabled) - return -EEXIST; - cds_list_for_each_entry(ev, &wildcard->events, wildcard_list) { - ret = ltt_event_disable(ev); - if (ret) { - DBG("Error: disable error.\n"); - return ret; - } - } - wildcard->enabled = 0; - return 0; -} - -/* - * Take the TLS "fault" in libuuid if dlopen'd, which can take the - * dynamic linker mutex, outside of the UST lock, since the UST lock is - * taken in constructors, which are called with dynamic linker mutex - * held. - */ -void lttng_fixup_event_tls(void) -{ - unsigned char uuid[LTTNG_UST_UUID_STR_LEN]; - - (void) lttng_ust_uuid_generate(uuid); -} diff --git a/liblttng-ust/ltt-probes.c b/liblttng-ust/ltt-probes.c deleted file mode 100644 index aeb6db65..00000000 --- a/liblttng-ust/ltt-probes.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * ltt-probes.c - * - * Holds LTTng probes registry. - * - * Copyright 2010-2012 (c) - 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; only - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include "tracepoint-internal.h" -#include -#include -#include - -#include "ltt-tracer-core.h" -#include "jhash.h" -#include "error.h" - -/* - * probe list is protected by ust_lock()/ust_unlock(). - */ -static CDS_LIST_HEAD(probe_list); - -static -const struct lttng_probe_desc *find_provider(const char *provider) -{ - struct lttng_probe_desc *iter; - - cds_list_for_each_entry(iter, &probe_list, head) { - if (!strcmp(iter->provider, provider)) - return iter; - } - return NULL; -} - -static -const struct lttng_event_desc *find_event(const char *name) -{ - struct lttng_probe_desc *probe_desc; - int i; - - cds_list_for_each_entry(probe_desc, &probe_list, head) { - for (i = 0; i < probe_desc->nr_events; i++) { - if (!strncmp(probe_desc->event_desc[i]->name, name, - LTTNG_UST_SYM_NAME_LEN - 1)) - return probe_desc->event_desc[i]; - } - } - return NULL; -} - -int ltt_probe_register(struct lttng_probe_desc *desc) -{ - struct lttng_probe_desc *iter; - int ret = 0; - int i; - - ust_lock(); - if (find_provider(desc->provider)) { - ret = -EEXIST; - goto end; - } - /* - * TODO: This is O(N^2). Turn into a hash table when probe registration - * overhead becomes an issue. - */ - for (i = 0; i < desc->nr_events; i++) { - if (find_event(desc->event_desc[i]->name)) { - ret = -EEXIST; - goto end; - } - } - - /* - * We sort the providers by struct lttng_probe_desc pointer - * address. - */ - cds_list_for_each_entry_reverse(iter, &probe_list, head) { - BUG_ON(iter == desc); /* Should never be in the list twice */ - if (iter < desc) { - /* We belong to the location right after iter. */ - cds_list_add(&desc->head, &iter->head); - goto desc_added; - } - } - /* We should be added at the head of the list */ - cds_list_add(&desc->head, &probe_list); -desc_added: - DBG("just registered probe %s containing %u events", - desc->provider, desc->nr_events); - /* - * fix the events awaiting probe load. - */ - for (i = 0; i < desc->nr_events; i++) { - const struct lttng_event_desc *ed; - - ed = desc->event_desc[i]; - DBG("Registered event probe \"%s\" with signature \"%s\"", - ed->name, ed->signature); - ret = pending_probe_fix_events(ed); - assert(!ret); - } -end: - ust_unlock(); - return ret; -} - -void ltt_probe_unregister(struct lttng_probe_desc *desc) -{ - ust_lock(); - cds_list_del(&desc->head); - DBG("just unregistered probe %s", desc->provider); - ust_unlock(); -} - -/* - * called with UST lock held. - */ -const struct lttng_event_desc *ltt_event_get(const char *name) -{ - const struct lttng_event_desc *event; - - event = find_event(name); - if (!event) - return NULL; - return event; -} - -void ltt_event_put(const struct lttng_event_desc *event) -{ -} - -void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list *list) -{ - struct tp_list_entry *list_entry, *tmp; - - cds_list_for_each_entry_safe(list_entry, tmp, &list->head, head) { - cds_list_del(&list_entry->head); - free(list_entry); - } -} - -/* - * called with UST lock held. - */ -int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list *list) -{ - struct lttng_probe_desc *probe_desc; - int i; - - CDS_INIT_LIST_HEAD(&list->head); - cds_list_for_each_entry(probe_desc, &probe_list, head) { - for (i = 0; i < probe_desc->nr_events; i++) { - struct tp_list_entry *list_entry; - - list_entry = zmalloc(sizeof(*list_entry)); - if (!list_entry) - goto err_nomem; - cds_list_add(&list_entry->head, &list->head); - strncpy(list_entry->tp.name, - probe_desc->event_desc[i]->name, - LTTNG_UST_SYM_NAME_LEN); - list_entry->tp.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; - if (!probe_desc->event_desc[i]->loglevel) { - list_entry->tp.loglevel = TRACE_DEFAULT; - } else { - list_entry->tp.loglevel = *(*probe_desc->event_desc[i]->loglevel); - } - } - } - if (cds_list_empty(&list->head)) - list->iter = NULL; - else - list->iter = - cds_list_first_entry(&list->head, struct tp_list_entry, head); - return 0; - -err_nomem: - ltt_probes_prune_event_list(list); - return -ENOMEM; -} - -/* - * Return current iteration position, advance internal iterator to next. - * Return NULL if end of list. - */ -struct lttng_ust_tracepoint_iter * - lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list *list) -{ - struct tp_list_entry *entry; - - if (!list->iter) - return NULL; - entry = list->iter; - if (entry->head.next == &list->head) - list->iter = NULL; - else - list->iter = cds_list_entry(entry->head.next, - struct tp_list_entry, head); - return &entry->tp; -} - -void ltt_probes_prune_field_list(struct lttng_ust_field_list *list) -{ - struct tp_field_list_entry *list_entry, *tmp; - - cds_list_for_each_entry_safe(list_entry, tmp, &list->head, head) { - cds_list_del(&list_entry->head); - free(list_entry); - } -} - -/* - * called with UST lock held. - */ -int ltt_probes_get_field_list(struct lttng_ust_field_list *list) -{ - struct lttng_probe_desc *probe_desc; - int i; - - CDS_INIT_LIST_HEAD(&list->head); - cds_list_for_each_entry(probe_desc, &probe_list, head) { - for (i = 0; i < probe_desc->nr_events; i++) { - const struct lttng_event_desc *event_desc = - probe_desc->event_desc[i]; - int j; - - if (event_desc->nr_fields == 0) { - /* Events without fields. */ - struct tp_field_list_entry *list_entry; - - list_entry = zmalloc(sizeof(*list_entry)); - if (!list_entry) - goto err_nomem; - cds_list_add(&list_entry->head, &list->head); - strncpy(list_entry->field.event_name, - event_desc->name, - LTTNG_UST_SYM_NAME_LEN); - list_entry->field.event_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; - list_entry->field.field_name[0] = '\0'; - list_entry->field.type = LTTNG_UST_FIELD_OTHER; - if (!event_desc->loglevel) { - list_entry->field.loglevel = TRACE_DEFAULT; - } else { - list_entry->field.loglevel = *(*event_desc->loglevel); - } - list_entry->field.nowrite = 1; - } - - for (j = 0; j < event_desc->nr_fields; j++) { - const struct lttng_event_field *event_field = - &event_desc->fields[j]; - struct tp_field_list_entry *list_entry; - - list_entry = zmalloc(sizeof(*list_entry)); - if (!list_entry) - goto err_nomem; - cds_list_add(&list_entry->head, &list->head); - strncpy(list_entry->field.event_name, - event_desc->name, - LTTNG_UST_SYM_NAME_LEN); - list_entry->field.event_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; - strncpy(list_entry->field.field_name, - event_field->name, - LTTNG_UST_SYM_NAME_LEN); - list_entry->field.field_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; - switch (event_field->type.atype) { - case atype_integer: - list_entry->field.type = LTTNG_UST_FIELD_INTEGER; - break; - case atype_string: - list_entry->field.type = LTTNG_UST_FIELD_STRING; - break; - case atype_array: - if (event_field->type.u.array.elem_type.atype != atype_integer - || event_field->type.u.array.elem_type.u.basic.integer.encoding == lttng_encode_none) - list_entry->field.type = LTTNG_UST_FIELD_OTHER; - else - list_entry->field.type = LTTNG_UST_FIELD_STRING; - break; - case atype_sequence: - if (event_field->type.u.sequence.elem_type.atype != atype_integer - || event_field->type.u.sequence.elem_type.u.basic.integer.encoding == lttng_encode_none) - list_entry->field.type = LTTNG_UST_FIELD_OTHER; - else - list_entry->field.type = LTTNG_UST_FIELD_STRING; - break; - case atype_float: - list_entry->field.type = LTTNG_UST_FIELD_FLOAT; - break; - case atype_enum: - list_entry->field.type = LTTNG_UST_FIELD_ENUM; - break; - default: - list_entry->field.type = LTTNG_UST_FIELD_OTHER; - } - if (!event_desc->loglevel) { - list_entry->field.loglevel = TRACE_DEFAULT; - } else { - list_entry->field.loglevel = *(*event_desc->loglevel); - } - list_entry->field.nowrite = event_field->nowrite; - } - } - } - if (cds_list_empty(&list->head)) - list->iter = NULL; - else - list->iter = - cds_list_first_entry(&list->head, - struct tp_field_list_entry, head); - return 0; - -err_nomem: - ltt_probes_prune_field_list(list); - return -ENOMEM; -} - -/* - * Return current iteration position, advance internal iterator to next. - * Return NULL if end of list. - */ -struct lttng_ust_field_iter * - lttng_ust_field_list_get_iter_next(struct lttng_ust_field_list *list) -{ - struct tp_field_list_entry *entry; - - if (!list->iter) - return NULL; - entry = list->iter; - if (entry->head.next == &list->head) - list->iter = NULL; - else - list->iter = cds_list_entry(entry->head.next, - struct tp_field_list_entry, head); - return &entry->field; -} - -/* - * marshall all probes/all events and create those that fit the - * wildcard. Add them to the events list as created. - */ -void ltt_probes_create_wildcard_events(struct wildcard_entry *entry, - struct session_wildcard *wildcard) -{ - struct lttng_probe_desc *probe_desc; - struct lttng_ust_event event_param; - int i; - - cds_list_for_each_entry(probe_desc, &probe_list, head) { - for (i = 0; i < probe_desc->nr_events; i++) { - const struct lttng_event_desc *event_desc; - int match = 0; - - event_desc = probe_desc->event_desc[i]; - /* compare excluding final '*' */ - assert(strlen(entry->name) > 0); - if (strcmp(event_desc->name, "lttng_ust:metadata") - && (strlen(entry->name) == 1 - || !strncmp(event_desc->name, entry->name, - strlen(entry->name) - 1))) { - if (ltt_loglevel_match(event_desc, - entry->loglevel_type, - entry->loglevel)) { - match = 1; - } - } - if (match) { - struct ltt_event *ev; - int ret; - - memcpy(&event_param, &wildcard->event_param, - sizeof(event_param)); - strncpy(event_param.name, - event_desc->name, - sizeof(event_param.name)); - event_param.name[sizeof(event_param.name) - 1] = '\0'; - /* create event */ - ret = ltt_event_create(wildcard->chan, - &event_param, &ev); - if (ret) { - DBG("Error creating event"); - continue; - } - cds_list_add(&ev->wildcard_list, - &wildcard->events); - } - } - } - lttng_filter_wildcard_link_bytecode(wildcard); -} - diff --git a/liblttng-ust/ltt-ring-buffer-client-discard.c b/liblttng-ust/ltt-ring-buffer-client-discard.c deleted file mode 100644 index 416984d4..00000000 --- a/liblttng-ust/ltt-ring-buffer-client-discard.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * ltt-ring-buffer-client-discard.c - * - * LTTng lib ring buffer client (discard mode). - * - * Copyright (C) 2010-2012 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; only - * 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 _GNU_SOURCE -#include "ltt-tracer.h" - -#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD -#define RING_BUFFER_MODE_TEMPLATE_STRING "discard" -#define RING_BUFFER_MODE_TEMPLATE_INIT \ - ltt_ring_buffer_client_discard_init -#define RING_BUFFER_MODE_TEMPLATE_EXIT \ - ltt_ring_buffer_client_discard_exit -#define LTTNG_CLIENT_TYPE LTTNG_CLIENT_DISCARD -#define LTTNG_CLIENT_CALLBACKS lttng_client_callbacks_discard -#include "ltt-ring-buffer-client.h" diff --git a/liblttng-ust/ltt-ring-buffer-client-overwrite.c b/liblttng-ust/ltt-ring-buffer-client-overwrite.c deleted file mode 100644 index de9d613a..00000000 --- a/liblttng-ust/ltt-ring-buffer-client-overwrite.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * ltt-ring-buffer-client-overwrite.c - * - * LTTng lib ring buffer client (overwrite mode). - * - * Copyright (C) 2010-2012 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; only - * 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 _GNU_SOURCE -#include "ltt-tracer.h" - -#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_OVERWRITE -#define RING_BUFFER_MODE_TEMPLATE_STRING "overwrite" -#define RING_BUFFER_MODE_TEMPLATE_INIT \ - ltt_ring_buffer_client_overwrite_init -#define RING_BUFFER_MODE_TEMPLATE_EXIT \ - ltt_ring_buffer_client_overwrite_exit -#define LTTNG_CLIENT_TYPE LTTNG_CLIENT_OVERWRITE -#define LTTNG_CLIENT_CALLBACKS lttng_client_callbacks_overwrite -#include "ltt-ring-buffer-client.h" diff --git a/liblttng-ust/ltt-ring-buffer-client.h b/liblttng-ust/ltt-ring-buffer-client.h deleted file mode 100644 index 0e329bad..00000000 --- a/liblttng-ust/ltt-ring-buffer-client.h +++ /dev/null @@ -1,595 +0,0 @@ -/* - * ltt-ring-buffer-client.h - * - * LTTng lib ring buffer client template. - * - * Copyright (C) 2010-2012 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; only - * 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 - */ - -#include -#include -#include "lttng/bitfield.h" -#include "clock.h" -#include "lttng-ust-uuid.h" -#include "ltt-tracer.h" -#include "../libringbuffer/frontend_types.h" - -#define LTTNG_COMPACT_EVENT_BITS 5 -#define LTTNG_COMPACT_TSC_BITS 27 - -/* - * Keep the natural field alignment for _each field_ within this structure if - * you ever add/remove a field from this header. Packed attribute is not used - * because gcc generates poor code on at least powerpc and mips. Don't ever - * let gcc add padding between the structure elements. - */ - -struct packet_header { - /* Trace packet header */ - uint32_t magic; /* - * Trace magic number. - * contains endianness information. - */ - uint8_t uuid[LTTNG_UST_UUID_LEN]; - uint32_t stream_id; - - struct { - /* Stream packet context */ - uint64_t timestamp_begin; /* Cycle count at subbuffer start */ - uint64_t timestamp_end; /* Cycle count at subbuffer end */ - uint64_t content_size; /* Size of data in subbuffer */ - uint64_t packet_size; /* Subbuffer size (include padding) */ - unsigned long events_discarded; /* - * Events lost in this subbuffer since - * the beginning of the trace. - * (may overflow) - */ - uint32_t cpu_id; /* CPU id associated with stream */ - uint8_t header_end; /* End of header */ - } ctx; -}; - - -static inline uint64_t lib_ring_buffer_clock_read(struct channel *chan) -{ - return trace_clock_read64(); -} - -static inline -size_t ctx_get_size(size_t offset, struct lttng_ctx *ctx) -{ - int i; - size_t orig_offset = offset; - - if (caa_likely(!ctx)) - return 0; - for (i = 0; i < ctx->nr_fields; i++) - offset += ctx->fields[i].get_size(offset); - return offset - orig_offset; -} - -static inline -void ctx_record(struct lttng_ust_lib_ring_buffer_ctx *bufctx, - struct ltt_channel *chan, - struct lttng_ctx *ctx) -{ - int i; - - if (caa_likely(!ctx)) - return; - for (i = 0; i < ctx->nr_fields; i++) - ctx->fields[i].record(&ctx->fields[i], bufctx, chan); -} - -/* - * record_header_size - Calculate the header size and padding necessary. - * @config: ring buffer instance configuration - * @chan: channel - * @offset: offset in the write buffer - * @pre_header_padding: padding to add before the header (output) - * @ctx: reservation context - * - * Returns the event header size (including padding). - * - * The payload must itself determine its own alignment from the biggest type it - * contains. - */ -static __inline__ -unsigned char record_header_size(const struct lttng_ust_lib_ring_buffer_config *config, - struct channel *chan, size_t offset, - size_t *pre_header_padding, - struct lttng_ust_lib_ring_buffer_ctx *ctx) -{ - struct ltt_channel *ltt_chan = channel_get_private(chan); - struct ltt_event *event = ctx->priv; - size_t orig_offset = offset; - size_t padding; - - switch (ltt_chan->header_type) { - case 1: /* compact */ - padding = lib_ring_buffer_align(offset, lttng_alignof(uint32_t)); - offset += padding; - if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) { - offset += sizeof(uint32_t); /* id and timestamp */ - } else { - /* Minimum space taken by LTTNG_COMPACT_EVENT_BITS id */ - offset += (LTTNG_COMPACT_EVENT_BITS + CHAR_BIT - 1) / CHAR_BIT; - /* Align extended struct on largest member */ - offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); - offset += sizeof(uint32_t); /* id */ - offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); - offset += sizeof(uint64_t); /* timestamp */ - } - break; - case 2: /* large */ - padding = lib_ring_buffer_align(offset, lttng_alignof(uint16_t)); - offset += padding; - offset += sizeof(uint16_t); - if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) { - offset += lib_ring_buffer_align(offset, lttng_alignof(uint32_t)); - offset += sizeof(uint32_t); /* timestamp */ - } else { - /* Align extended struct on largest member */ - offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); - offset += sizeof(uint32_t); /* id */ - offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); - offset += sizeof(uint64_t); /* timestamp */ - } - break; - default: - padding = 0; - WARN_ON_ONCE(1); - } - offset += ctx_get_size(offset, event->ctx); - offset += ctx_get_size(offset, ltt_chan->ctx); - - *pre_header_padding = padding; - return offset - orig_offset; -} - -#include "../libringbuffer/api.h" - -static -void ltt_write_event_header_slow(const struct lttng_ust_lib_ring_buffer_config *config, - struct lttng_ust_lib_ring_buffer_ctx *ctx, - uint32_t event_id); - -/* - * ltt_write_event_header - * - * Writes the event header to the offset (already aligned on 32-bits). - * - * @config: ring buffer instance configuration - * @ctx: reservation context - * @event_id: event ID - */ -static __inline__ -void ltt_write_event_header(const struct lttng_ust_lib_ring_buffer_config *config, - struct lttng_ust_lib_ring_buffer_ctx *ctx, - uint32_t event_id) -{ - struct ltt_channel *ltt_chan = channel_get_private(ctx->chan); - struct ltt_event *event = ctx->priv; - - if (caa_unlikely(ctx->rflags)) - goto slow_path; - - switch (ltt_chan->header_type) { - case 1: /* compact */ - { - uint32_t id_time = 0; - - bt_bitfield_write(&id_time, uint32_t, - 0, - LTTNG_COMPACT_EVENT_BITS, - event_id); - bt_bitfield_write(&id_time, uint32_t, - LTTNG_COMPACT_EVENT_BITS, - LTTNG_COMPACT_TSC_BITS, - ctx->tsc); - lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time)); - break; - } - case 2: /* large */ - { - uint32_t timestamp = (uint32_t) ctx->tsc; - uint16_t id = event_id; - - lib_ring_buffer_write(config, ctx, &id, sizeof(id)); - lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint32_t)); - lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); - break; - } - default: - WARN_ON_ONCE(1); - } - - ctx_record(ctx, ltt_chan, ltt_chan->ctx); - ctx_record(ctx, ltt_chan, event->ctx); - lib_ring_buffer_align_ctx(ctx, ctx->largest_align); - - return; - -slow_path: - ltt_write_event_header_slow(config, ctx, event_id); -} - -static -void ltt_write_event_header_slow(const struct lttng_ust_lib_ring_buffer_config *config, - struct lttng_ust_lib_ring_buffer_ctx *ctx, - uint32_t event_id) -{ - struct ltt_channel *ltt_chan = channel_get_private(ctx->chan); - struct ltt_event *event = ctx->priv; - - switch (ltt_chan->header_type) { - case 1: /* compact */ - if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) { - uint32_t id_time = 0; - - bt_bitfield_write(&id_time, uint32_t, - 0, - LTTNG_COMPACT_EVENT_BITS, - event_id); - bt_bitfield_write(&id_time, uint32_t, - LTTNG_COMPACT_EVENT_BITS, - LTTNG_COMPACT_TSC_BITS, - ctx->tsc); - lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time)); - } else { - uint8_t id = 0; - uint64_t timestamp = ctx->tsc; - - bt_bitfield_write(&id, uint8_t, - 0, - LTTNG_COMPACT_EVENT_BITS, - 31); - lib_ring_buffer_write(config, ctx, &id, sizeof(id)); - /* Align extended struct on largest member */ - lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t)); - lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id)); - lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t)); - lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); - } - break; - case 2: /* large */ - { - if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) { - uint32_t timestamp = (uint32_t) ctx->tsc; - uint16_t id = event_id; - - lib_ring_buffer_write(config, ctx, &id, sizeof(id)); - lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint32_t)); - lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); - } else { - uint16_t id = 65535; - uint64_t timestamp = ctx->tsc; - - lib_ring_buffer_write(config, ctx, &id, sizeof(id)); - /* Align extended struct on largest member */ - lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t)); - lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id)); - lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t)); - lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); - } - break; - } - default: - WARN_ON_ONCE(1); - } - ctx_record(ctx, ltt_chan, ltt_chan->ctx); - ctx_record(ctx, ltt_chan, event->ctx); - lib_ring_buffer_align_ctx(ctx, ctx->largest_align); -} - -static const struct lttng_ust_lib_ring_buffer_config client_config; - -static uint64_t client_ring_buffer_clock_read(struct channel *chan) -{ - return lib_ring_buffer_clock_read(chan); -} - -static -size_t client_record_header_size(const struct lttng_ust_lib_ring_buffer_config *config, - struct channel *chan, size_t offset, - size_t *pre_header_padding, - struct lttng_ust_lib_ring_buffer_ctx *ctx) -{ - return record_header_size(config, chan, offset, - pre_header_padding, ctx); -} - -/** - * client_packet_header_size - called on buffer-switch to a new sub-buffer - * - * Return header size without padding after the structure. Don't use packed - * structure because gcc generates inefficient code on some architectures - * (powerpc, mips..) - */ -static size_t client_packet_header_size(void) -{ - return offsetof(struct packet_header, ctx.header_end); -} - -static void client_buffer_begin(struct lttng_ust_lib_ring_buffer *buf, uint64_t tsc, - unsigned int subbuf_idx, - struct lttng_ust_shm_handle *handle) -{ - struct channel *chan = shmp(handle, buf->backend.chan); - struct packet_header *header = - (struct packet_header *) - lib_ring_buffer_offset_address(&buf->backend, - subbuf_idx * chan->backend.subbuf_size, - handle); - struct ltt_channel *ltt_chan = channel_get_private(chan); - - header->magic = CTF_MAGIC_NUMBER; - memcpy(header->uuid, ltt_chan->uuid, sizeof(ltt_chan->uuid)); - header->stream_id = ltt_chan->id; - header->ctx.timestamp_begin = tsc; - header->ctx.timestamp_end = 0; - header->ctx.content_size = ~0ULL; /* for debugging */ - header->ctx.packet_size = ~0ULL; - header->ctx.events_discarded = 0; - header->ctx.cpu_id = buf->backend.cpu; -} - -/* - * offset is assumed to never be 0 here : never deliver a completely empty - * subbuffer. data_size is between 1 and subbuf_size. - */ -static void client_buffer_end(struct lttng_ust_lib_ring_buffer *buf, uint64_t tsc, - unsigned int subbuf_idx, unsigned long data_size, - struct lttng_ust_shm_handle *handle) -{ - struct channel *chan = shmp(handle, buf->backend.chan); - struct packet_header *header = - (struct packet_header *) - lib_ring_buffer_offset_address(&buf->backend, - subbuf_idx * chan->backend.subbuf_size, - handle); - unsigned long records_lost = 0; - - header->ctx.timestamp_end = tsc; - header->ctx.content_size = - (uint64_t) data_size * CHAR_BIT; /* in bits */ - header->ctx.packet_size = - (uint64_t) PAGE_ALIGN(data_size) * CHAR_BIT; /* in bits */ - - records_lost += lib_ring_buffer_get_records_lost_full(&client_config, buf); - records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf); - records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf); - header->ctx.events_discarded = records_lost; -} - -static int client_buffer_create(struct lttng_ust_lib_ring_buffer *buf, void *priv, - int cpu, const char *name, struct lttng_ust_shm_handle *handle) -{ - return 0; -} - -static void client_buffer_finalize(struct lttng_ust_lib_ring_buffer *buf, void *priv, int cpu, struct lttng_ust_shm_handle *handle) -{ -} - -static const struct lttng_ust_lib_ring_buffer_config client_config = { - .cb.ring_buffer_clock_read = client_ring_buffer_clock_read, - .cb.record_header_size = client_record_header_size, - .cb.subbuffer_header_size = client_packet_header_size, - .cb.buffer_begin = client_buffer_begin, - .cb.buffer_end = client_buffer_end, - .cb.buffer_create = client_buffer_create, - .cb.buffer_finalize = client_buffer_finalize, - - .tsc_bits = LTTNG_COMPACT_TSC_BITS, - .alloc = RING_BUFFER_ALLOC_PER_CPU, - .sync = RING_BUFFER_SYNC_GLOBAL, - .mode = RING_BUFFER_MODE_TEMPLATE, - .backend = RING_BUFFER_PAGE, - .output = RING_BUFFER_MMAP, - .oops = RING_BUFFER_OOPS_CONSISTENCY, - .ipi = RING_BUFFER_NO_IPI_BARRIER, - .wakeup = RING_BUFFER_WAKEUP_BY_WRITER, - .client_type = LTTNG_CLIENT_TYPE, -}; - -const struct lttng_ust_lib_ring_buffer_client_cb *LTTNG_CLIENT_CALLBACKS = &client_config.cb; - -static -struct ltt_channel *_channel_create(const char *name, - void *buf_addr, - size_t subbuf_size, size_t num_subbuf, - unsigned int switch_timer_interval, - unsigned int read_timer_interval, - int **shm_fd, int **wait_fd, - uint64_t **memory_map_size, - struct ltt_channel *chan_priv_init) -{ - void *priv; - struct ltt_channel *ltt_chan = NULL; - struct lttng_ust_shm_handle *handle; - - handle = channel_create(&client_config, name, - &priv, __alignof__(*ltt_chan), sizeof(*ltt_chan), - chan_priv_init, - buf_addr, subbuf_size, num_subbuf, - switch_timer_interval, read_timer_interval, - shm_fd, wait_fd, memory_map_size); - if (!handle) - return NULL; - ltt_chan = priv; - ltt_chan->handle = handle; - ltt_chan->chan = shmp(ltt_chan->handle, ltt_chan->handle->chan); - return ltt_chan; -} - -static -void ltt_channel_destroy(struct ltt_channel *ltt_chan) -{ - channel_destroy(ltt_chan->chan, ltt_chan->handle, 0); -} - -static -struct lttng_ust_lib_ring_buffer *ltt_buffer_read_open(struct channel *chan, - struct lttng_ust_shm_handle *handle, - int **shm_fd, int **wait_fd, - uint64_t **memory_map_size) -{ - struct lttng_ust_lib_ring_buffer *buf; - int cpu; - - for_each_channel_cpu(cpu, chan) { - buf = channel_get_ring_buffer(&client_config, chan, - cpu, handle, shm_fd, wait_fd, - memory_map_size); - if (!lib_ring_buffer_open_read(buf, handle, 0)) - return buf; - } - return NULL; -} - -static -void ltt_buffer_read_close(struct lttng_ust_lib_ring_buffer *buf, - struct lttng_ust_shm_handle *handle) -{ - lib_ring_buffer_release_read(buf, handle, 0); -} - -static -int ltt_event_reserve(struct lttng_ust_lib_ring_buffer_ctx *ctx, - uint32_t event_id) -{ - struct ltt_channel *ltt_chan = channel_get_private(ctx->chan); - int ret, cpu; - - cpu = lib_ring_buffer_get_cpu(&client_config); - if (cpu < 0) - return -EPERM; - ctx->cpu = cpu; - - switch (ltt_chan->header_type) { - case 1: /* compact */ - if (event_id > 30) - ctx->rflags |= LTT_RFLAG_EXTENDED; - break; - case 2: /* large */ - if (event_id > 65534) - ctx->rflags |= LTT_RFLAG_EXTENDED; - break; - default: - WARN_ON_ONCE(1); - } - - ret = lib_ring_buffer_reserve(&client_config, ctx); - if (ret) - goto put; - ltt_write_event_header(&client_config, ctx, event_id); - return 0; -put: - lib_ring_buffer_put_cpu(&client_config); - return ret; -} - -static -void ltt_event_commit(struct lttng_ust_lib_ring_buffer_ctx *ctx) -{ - lib_ring_buffer_commit(&client_config, ctx); - lib_ring_buffer_put_cpu(&client_config); -} - -static -void ltt_event_write(struct lttng_ust_lib_ring_buffer_ctx *ctx, const void *src, - size_t len) -{ - lib_ring_buffer_write(&client_config, ctx, src, len); -} - -#if 0 -static -wait_queue_head_t *ltt_get_reader_wait_queue(struct channel *chan) -{ - return &chan->read_wait; -} - -static -wait_queue_head_t *ltt_get_hp_wait_queue(struct channel *chan) -{ - return &chan->hp_wait; -} -#endif //0 - -static -int ltt_is_finalized(struct channel *chan) -{ - return lib_ring_buffer_channel_is_finalized(chan); -} - -static -int ltt_is_disabled(struct channel *chan) -{ - return lib_ring_buffer_channel_is_disabled(chan); -} - -static -int ltt_flush_buffer(struct channel *chan, struct lttng_ust_shm_handle *handle) -{ - struct lttng_ust_lib_ring_buffer *buf; - int cpu; - - for_each_channel_cpu(cpu, chan) { - int *shm_fd, *wait_fd; - uint64_t *memory_map_size; - - buf = channel_get_ring_buffer(&client_config, chan, - cpu, handle, &shm_fd, &wait_fd, - &memory_map_size); - lib_ring_buffer_switch(&client_config, buf, - SWITCH_ACTIVE, handle); - } - return 0; -} - -static struct ltt_transport ltt_relay_transport = { - .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap", - .ops = { - .channel_create = _channel_create, - .channel_destroy = ltt_channel_destroy, - .buffer_read_open = ltt_buffer_read_open, - .buffer_read_close = ltt_buffer_read_close, - .event_reserve = ltt_event_reserve, - .event_commit = ltt_event_commit, - .event_write = ltt_event_write, - .packet_avail_size = NULL, /* Would be racy anyway */ - //.get_reader_wait_queue = ltt_get_reader_wait_queue, - //.get_hp_wait_queue = ltt_get_hp_wait_queue, - .is_finalized = ltt_is_finalized, - .is_disabled = ltt_is_disabled, - .flush_buffer = ltt_flush_buffer, - }, -}; - -void RING_BUFFER_MODE_TEMPLATE_INIT(void) -{ - DBG("LTT : ltt ring buffer client init\n"); - ltt_transport_register(<t_relay_transport); -} - -void RING_BUFFER_MODE_TEMPLATE_EXIT(void) -{ - DBG("LTT : ltt ring buffer client exit\n"); - ltt_transport_unregister(<t_relay_transport); -} diff --git a/liblttng-ust/ltt-ring-buffer-metadata-client.c b/liblttng-ust/ltt-ring-buffer-metadata-client.c deleted file mode 100644 index cc72a7fe..00000000 --- a/liblttng-ust/ltt-ring-buffer-metadata-client.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * ltt-ring-buffer-metadata-client.c - * - * LTTng lib ring buffer metadta client. - * - * Copyright (C) 2010-2012 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; only - * 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 _GNU_SOURCE -#include "ltt-tracer.h" - -#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD -#define RING_BUFFER_MODE_TEMPLATE_STRING "metadata" -#define RING_BUFFER_MODE_TEMPLATE_INIT \ - ltt_ring_buffer_metadata_client_init -#define RING_BUFFER_MODE_TEMPLATE_EXIT \ - ltt_ring_buffer_metadata_client_exit -#define LTTNG_CLIENT_TYPE LTTNG_CLIENT_METADATA -#define LTTNG_CLIENT_CALLBACKS lttng_client_callbacks_metadata -#include "ltt-ring-buffer-metadata-client.h" diff --git a/liblttng-ust/ltt-ring-buffer-metadata-client.h b/liblttng-ust/ltt-ring-buffer-metadata-client.h deleted file mode 100644 index acc56fdd..00000000 --- a/liblttng-ust/ltt-ring-buffer-metadata-client.h +++ /dev/null @@ -1,342 +0,0 @@ -/* - * ltt-ring-buffer-client.h - * - * LTTng lib ring buffer client template. - * - * Copyright (C) 2010-2012 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; only - * 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 - */ - -#include -#include -#include "lttng/bitfield.h" -#include "ltt-tracer.h" -#include "../libringbuffer/frontend_types.h" - -struct metadata_packet_header { - uint32_t magic; /* 0x75D11D57 */ - uint8_t uuid[LTTNG_UST_UUID_LEN]; /* Unique Universal Identifier */ - uint32_t checksum; /* 0 if unused */ - uint32_t content_size; /* in bits */ - uint32_t packet_size; /* in bits */ - uint8_t compression_scheme; /* 0 if unused */ - uint8_t encryption_scheme; /* 0 if unused */ - uint8_t checksum_scheme; /* 0 if unused */ - uint8_t major; /* CTF spec major version number */ - uint8_t minor; /* CTF spec minor version number */ - uint8_t header_end[0]; -}; - -struct metadata_record_header { - uint8_t header_end[0]; /* End of header */ -}; - -static const struct lttng_ust_lib_ring_buffer_config client_config; - -static inline uint64_t lib_ring_buffer_clock_read(struct channel *chan) -{ - return 0; -} - -static inline -unsigned char record_header_size(const struct lttng_ust_lib_ring_buffer_config *config, - struct channel *chan, size_t offset, - size_t *pre_header_padding, - struct lttng_ust_lib_ring_buffer_ctx *ctx) -{ - return 0; -} - -#include "../libringbuffer/api.h" - -static uint64_t client_ring_buffer_clock_read(struct channel *chan) -{ - return 0; -} - -static -size_t client_record_header_size(const struct lttng_ust_lib_ring_buffer_config *config, - struct channel *chan, size_t offset, - size_t *pre_header_padding, - struct lttng_ust_lib_ring_buffer_ctx *ctx) -{ - return 0; -} - -/** - * client_packet_header_size - called on buffer-switch to a new sub-buffer - * - * Return header size without padding after the structure. Don't use packed - * structure because gcc generates inefficient code on some architectures - * (powerpc, mips..) - */ -static size_t client_packet_header_size(void) -{ - return offsetof(struct metadata_packet_header, header_end); -} - -static void client_buffer_begin(struct lttng_ust_lib_ring_buffer *buf, uint64_t tsc, - unsigned int subbuf_idx, - struct lttng_ust_shm_handle *handle) -{ - struct channel *chan = shmp(handle, buf->backend.chan); - struct metadata_packet_header *header = - (struct metadata_packet_header *) - lib_ring_buffer_offset_address(&buf->backend, - subbuf_idx * chan->backend.subbuf_size, - handle); - struct ltt_channel *ltt_chan = channel_get_private(chan); - - header->magic = TSDL_MAGIC_NUMBER; - memcpy(header->uuid, ltt_chan->uuid, sizeof(ltt_chan->uuid)); - header->checksum = 0; /* 0 if unused */ - header->content_size = 0xFFFFFFFF; /* in bits, for debugging */ - header->packet_size = 0xFFFFFFFF; /* in bits, for debugging */ - header->compression_scheme = 0; /* 0 if unused */ - header->encryption_scheme = 0; /* 0 if unused */ - header->checksum_scheme = 0; /* 0 if unused */ - header->major = CTF_SPEC_MAJOR; - header->minor = CTF_SPEC_MINOR; - -} - -/* - * offset is assumed to never be 0 here : never deliver a completely empty - * subbuffer. data_size is between 1 and subbuf_size. - */ -static void client_buffer_end(struct lttng_ust_lib_ring_buffer *buf, uint64_t tsc, - unsigned int subbuf_idx, unsigned long data_size, - struct lttng_ust_shm_handle *handle) -{ - struct channel *chan = shmp(handle, buf->backend.chan); - struct metadata_packet_header *header = - (struct metadata_packet_header *) - lib_ring_buffer_offset_address(&buf->backend, - subbuf_idx * chan->backend.subbuf_size, - handle); - unsigned long records_lost = 0; - - header->content_size = data_size * CHAR_BIT; /* in bits */ - header->packet_size = PAGE_ALIGN(data_size) * CHAR_BIT; /* in bits */ - /* - * We do not care about the records lost count, because the metadata - * channel waits and retry. - */ - (void) lib_ring_buffer_get_records_lost_full(&client_config, buf); - records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf); - records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf); - WARN_ON_ONCE(records_lost != 0); -} - -static int client_buffer_create(struct lttng_ust_lib_ring_buffer *buf, void *priv, - int cpu, const char *name, - struct lttng_ust_shm_handle *handle) -{ - return 0; -} - -static void client_buffer_finalize(struct lttng_ust_lib_ring_buffer *buf, - void *priv, int cpu, - struct lttng_ust_shm_handle *handle) -{ -} - -static const struct lttng_ust_lib_ring_buffer_config client_config = { - .cb.ring_buffer_clock_read = client_ring_buffer_clock_read, - .cb.record_header_size = client_record_header_size, - .cb.subbuffer_header_size = client_packet_header_size, - .cb.buffer_begin = client_buffer_begin, - .cb.buffer_end = client_buffer_end, - .cb.buffer_create = client_buffer_create, - .cb.buffer_finalize = client_buffer_finalize, - - .tsc_bits = 0, - .alloc = RING_BUFFER_ALLOC_GLOBAL, - .sync = RING_BUFFER_SYNC_GLOBAL, - .mode = RING_BUFFER_MODE_TEMPLATE, - .backend = RING_BUFFER_PAGE, - .output = RING_BUFFER_MMAP, - .oops = RING_BUFFER_OOPS_CONSISTENCY, - .ipi = RING_BUFFER_NO_IPI_BARRIER, - .wakeup = RING_BUFFER_WAKEUP_BY_WRITER, - .client_type = LTTNG_CLIENT_TYPE, -}; - -const struct lttng_ust_lib_ring_buffer_client_cb *LTTNG_CLIENT_CALLBACKS = &client_config.cb; - -static -struct ltt_channel *_channel_create(const char *name, - void *buf_addr, - size_t subbuf_size, size_t num_subbuf, - unsigned int switch_timer_interval, - unsigned int read_timer_interval, - int **shm_fd, int **wait_fd, - uint64_t **memory_map_size, - struct ltt_channel *chan_priv_init) -{ - void *priv; - struct ltt_channel *ltt_chan = NULL; - struct lttng_ust_shm_handle *handle; - - handle = channel_create(&client_config, name, - &priv, __alignof__(*ltt_chan), sizeof(*ltt_chan), - chan_priv_init, - buf_addr, subbuf_size, num_subbuf, - switch_timer_interval, read_timer_interval, - shm_fd, wait_fd, memory_map_size); - if (!handle) - return NULL; - ltt_chan = priv; - ltt_chan->handle = handle; - ltt_chan->chan = shmp(ltt_chan->handle, ltt_chan->handle->chan); - return ltt_chan; -} - -static -void ltt_channel_destroy(struct ltt_channel *ltt_chan) -{ - channel_destroy(ltt_chan->chan, ltt_chan->handle, 0); -} - -static -struct lttng_ust_lib_ring_buffer *ltt_buffer_read_open(struct channel *chan, - struct lttng_ust_shm_handle *handle, - int **shm_fd, int **wait_fd, - uint64_t **memory_map_size) -{ - struct lttng_ust_lib_ring_buffer *buf; - - buf = channel_get_ring_buffer(&client_config, chan, - 0, handle, shm_fd, wait_fd, memory_map_size); - if (!lib_ring_buffer_open_read(buf, handle, 0)) - return buf; - return NULL; -} - -static -void ltt_buffer_read_close(struct lttng_ust_lib_ring_buffer *buf, - struct lttng_ust_shm_handle *handle) -{ - lib_ring_buffer_release_read(buf, handle, 0); -} - -static -int ltt_event_reserve(struct lttng_ust_lib_ring_buffer_ctx *ctx, uint32_t event_id) -{ - return lib_ring_buffer_reserve(&client_config, ctx); -} - -static -void ltt_event_commit(struct lttng_ust_lib_ring_buffer_ctx *ctx) -{ - lib_ring_buffer_commit(&client_config, ctx); -} - -static -void ltt_event_write(struct lttng_ust_lib_ring_buffer_ctx *ctx, const void *src, - size_t len) -{ - lib_ring_buffer_write(&client_config, ctx, src, len); -} - -static -size_t ltt_packet_avail_size(struct channel *chan, struct lttng_ust_shm_handle *handle) - -{ - unsigned long o_begin; - struct lttng_ust_lib_ring_buffer *buf; - - buf = shmp(handle, chan->backend.buf[0].shmp); /* Only for global buffer ! */ - o_begin = v_read(&client_config, &buf->offset); - if (subbuf_offset(o_begin, chan) != 0) { - return chan->backend.subbuf_size - subbuf_offset(o_begin, chan); - } else { - return chan->backend.subbuf_size - subbuf_offset(o_begin, chan) - - sizeof(struct metadata_packet_header); - } -} - -#if 0 -static -wait_queue_head_t *ltt_get_reader_wait_queue(struct channel *chan) -{ - return &chan->read_wait; -} - -static -wait_queue_head_t *ltt_get_hp_wait_queue(struct channel *chan) -{ - return &chan->hp_wait; -} -#endif //0 - -static -int ltt_is_finalized(struct channel *chan) -{ - return lib_ring_buffer_channel_is_finalized(chan); -} - -static -int ltt_is_disabled(struct channel *chan) -{ - return lib_ring_buffer_channel_is_disabled(chan); -} - -static -int ltt_flush_buffer(struct channel *chan, struct lttng_ust_shm_handle *handle) -{ - struct lttng_ust_lib_ring_buffer *buf; - int *shm_fd, *wait_fd; - uint64_t *memory_map_size; - - buf = channel_get_ring_buffer(&client_config, chan, - 0, handle, &shm_fd, &wait_fd, - &memory_map_size); - lib_ring_buffer_switch(&client_config, buf, - SWITCH_ACTIVE, handle); - return 0; -} - -static struct ltt_transport ltt_relay_transport = { - .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap", - .ops = { - .channel_create = _channel_create, - .channel_destroy = ltt_channel_destroy, - .buffer_read_open = ltt_buffer_read_open, - .buffer_read_close = ltt_buffer_read_close, - .event_reserve = ltt_event_reserve, - .event_commit = ltt_event_commit, - .event_write = ltt_event_write, - .packet_avail_size = ltt_packet_avail_size, - //.get_reader_wait_queue = ltt_get_reader_wait_queue, - //.get_hp_wait_queue = ltt_get_hp_wait_queue, - .is_finalized = ltt_is_finalized, - .is_disabled = ltt_is_disabled, - .flush_buffer = ltt_flush_buffer, - }, -}; - -void RING_BUFFER_MODE_TEMPLATE_INIT(void) -{ - DBG("LTT : ltt ring buffer client init\n"); - ltt_transport_register(<t_relay_transport); -} - -void RING_BUFFER_MODE_TEMPLATE_EXIT(void) -{ - DBG("LTT : ltt ring buffer client exit\n"); - ltt_transport_unregister(<t_relay_transport); -} diff --git a/liblttng-ust/ltt-tracer-core.h b/liblttng-ust/ltt-tracer-core.h deleted file mode 100644 index 34c5557a..00000000 --- a/liblttng-ust/ltt-tracer-core.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _LTT_TRACER_CORE_H -#define _LTT_TRACER_CORE_H - -/* - * Copyright (C) 2005-2011 Mathieu Desnoyers - * - * This contains the core definitions for the Linux Trace Toolkit. - * - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct ltt_session; -struct ltt_channel; -struct ltt_event; - -void ust_lock(void); -void ust_unlock(void); - -void lttng_fixup_event_tls(void); -void lttng_fixup_vtid_tls(void); -void lttng_fixup_procname_tls(void); - -#endif /* _LTT_TRACER_CORE_H */ diff --git a/liblttng-ust/ltt-tracer.h b/liblttng-ust/ltt-tracer.h deleted file mode 100644 index e3593b18..00000000 --- a/liblttng-ust/ltt-tracer.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _LTT_TRACER_H -#define _LTT_TRACER_H - -/* - * Copyright (C) 2005-2011 Mathieu Desnoyers - * - * This contains the definitions for the Linux Trace Toolkit tracer. - * - * Ported to userspace by 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; 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 - */ - -#include -#include -#include -#include "ltt-tracer-core.h" -#include "compat.h" - -/* Number of bytes to log with a read/write event */ -#define LTT_LOG_RW_SIZE 32L -#define LTT_MAX_SMALL_SIZE 0xFFFFU - -/* Tracer properties */ -#define CTF_MAGIC_NUMBER 0xC1FC1FC1 -#define TSDL_MAGIC_NUMBER 0x75D11D57 - -/* CTF specification version followed */ -#define CTF_SPEC_MAJOR 1 -#define CTF_SPEC_MINOR 8 - -/* - * Number of milliseconds to retry before failing metadata writes on buffer full - * condition. (10 seconds) - */ -#define LTTNG_METADATA_TIMEOUT_MSEC 10000 - -#define LTT_RFLAG_EXTENDED RING_BUFFER_RFLAG_END -#define LTT_RFLAG_END (LTT_RFLAG_EXTENDED << 1) - -#endif /* _LTT_TRACER_H */ diff --git a/liblttng-ust/lttng-context-procname.c b/liblttng-ust/lttng-context-procname.c index 96cd1ee2..0d42be91 100644 --- a/liblttng-ust/lttng-context-procname.c +++ b/liblttng-ust/lttng-context-procname.c @@ -64,7 +64,7 @@ size_t procname_get_size(size_t offset) static void procname_record(struct lttng_ctx_field *field, struct lttng_ust_lib_ring_buffer_ctx *ctx, - struct ltt_channel *chan) + struct lttng_channel *chan) { char *procname; diff --git a/liblttng-ust/lttng-context-pthread-id.c b/liblttng-ust/lttng-context-pthread-id.c index 44c60c3a..e0f662f2 100644 --- a/liblttng-ust/lttng-context-pthread-id.c +++ b/liblttng-ust/lttng-context-pthread-id.c @@ -38,7 +38,7 @@ size_t pthread_id_get_size(size_t offset) static void pthread_id_record(struct lttng_ctx_field *field, struct lttng_ust_lib_ring_buffer_ctx *ctx, - struct ltt_channel *chan) + struct lttng_channel *chan) { unsigned long pthread_id; diff --git a/liblttng-ust/lttng-context-vpid.c b/liblttng-ust/lttng-context-vpid.c index fdf68fb1..3ab786f4 100644 --- a/liblttng-ust/lttng-context-vpid.c +++ b/liblttng-ust/lttng-context-vpid.c @@ -74,7 +74,7 @@ size_t vpid_get_size(size_t offset) static void vpid_record(struct lttng_ctx_field *field, struct lttng_ust_lib_ring_buffer_ctx *ctx, - struct ltt_channel *chan) + struct lttng_channel *chan) { pid_t pid; diff --git a/liblttng-ust/lttng-context-vtid.c b/liblttng-ust/lttng-context-vtid.c index 81508515..dd443774 100644 --- a/liblttng-ust/lttng-context-vtid.c +++ b/liblttng-ust/lttng-context-vtid.c @@ -26,7 +26,7 @@ #include #include #include -#include "ltt-tracer-core.h" +#include "lttng-tracer-core.h" /* * We cache the result to ensure we don't trigger a system call for @@ -57,7 +57,7 @@ size_t vtid_get_size(size_t offset) static void vtid_record(struct lttng_ctx_field *field, struct lttng_ust_lib_ring_buffer_ctx *ctx, - struct ltt_channel *chan) + struct lttng_channel *chan) { if (caa_unlikely(!cached_vtid)) cached_vtid = gettid(); diff --git a/liblttng-ust/lttng-context.c b/liblttng-ust/lttng-context.c new file mode 100644 index 00000000..16894ec1 --- /dev/null +++ b/liblttng-ust/lttng-context.c @@ -0,0 +1,101 @@ +/* + * lttng-context.c + * + * LTTng UST trace/channel/event context management. + * + * Copyright (C) 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; only + * 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 + */ + + +#include +#include +#include +#include +#include + +int lttng_find_context(struct lttng_ctx *ctx, const char *name) +{ + unsigned int i; + + for (i = 0; i < ctx->nr_fields; i++) { + /* Skip allocated (but non-initialized) contexts */ + if (!ctx->fields[i].event_field.name) + continue; + if (!strcmp(ctx->fields[i].event_field.name, name)) + return 1; + } + return 0; +} + +/* + * Note: as we append context information, the pointer location may change. + */ +struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p) +{ + struct lttng_ctx_field *field; + struct lttng_ctx *ctx; + + if (!*ctx_p) { + *ctx_p = zmalloc(sizeof(struct lttng_ctx)); + if (!*ctx_p) + return NULL; + } + ctx = *ctx_p; + if (ctx->nr_fields + 1 > ctx->allocated_fields) { + struct lttng_ctx_field *new_fields; + + ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields); + new_fields = zmalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field)); + if (!new_fields) + return NULL; + if (ctx->fields) + memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields); + free(ctx->fields); + ctx->fields = new_fields; + } + field = &ctx->fields[ctx->nr_fields]; + ctx->nr_fields++; + return field; +} + +/* + * Remove last context field. + */ +void lttng_remove_context_field(struct lttng_ctx **ctx_p, + struct lttng_ctx_field *field) +{ + struct lttng_ctx *ctx; + + ctx = *ctx_p; + ctx->nr_fields--; + assert(&ctx->fields[ctx->nr_fields] == field); + memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field)); +} + +void lttng_destroy_context(struct lttng_ctx *ctx) +{ + int i; + + if (!ctx) + return; + for (i = 0; i < ctx->nr_fields; i++) { + if (ctx->fields[i].destroy) + ctx->fields[i].destroy(&ctx->fields[i]); + } + free(ctx->fields); + free(ctx); +} diff --git a/liblttng-ust/lttng-events.c b/liblttng-ust/lttng-events.c new file mode 100644 index 00000000..24b5c666 --- /dev/null +++ b/liblttng-ust/lttng-events.c @@ -0,0 +1,1526 @@ +/* + * lttng-events.c + * + * Holds LTTng per-session event registry. + * + * Copyright (C) 2010-2012 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; only + * 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 _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "clock.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include "error.h" +#include "compat.h" +#include "lttng-ust-uuid.h" + +#include "tracepoint-internal.h" +#include "lttng-tracer.h" +#include "lttng-tracer-core.h" +#include "wait.h" +#include "../libringbuffer/shm.h" +#include "jhash.h" + +/* + * The sessions mutex is the centralized mutex across UST tracing + * control and probe registration. All operations within this file are + * called by the communication thread, under ust_lock protection. + */ +static pthread_mutex_t sessions_mutex = PTHREAD_MUTEX_INITIALIZER; + +void ust_lock(void) +{ + pthread_mutex_lock(&sessions_mutex); +} + +void ust_unlock(void) +{ + pthread_mutex_unlock(&sessions_mutex); +} + +static CDS_LIST_HEAD(sessions); + +/* + * Wildcard list, containing the active wildcards. + * Protected by ust lock. + */ +static CDS_LIST_HEAD(wildcard_list); + +/* + * Pending probes hash table, containing the registered ltt events for + * which tracepoint probes are still missing. Protected by the sessions + * mutex. + */ +#define PENDING_PROBE_HASH_BITS 6 +#define PENDING_PROBE_HASH_SIZE (1 << PENDING_PROBE_HASH_BITS) +static struct cds_hlist_head pending_probe_table[PENDING_PROBE_HASH_SIZE]; + +struct ust_pending_probe { + struct lttng_event *event; + struct cds_hlist_node node; + enum lttng_ust_loglevel_type loglevel_type; + int loglevel; + char name[]; +}; + +static void _lttng_event_destroy(struct lttng_event *event); +static void _lttng_wildcard_destroy(struct session_wildcard *sw); +static void _lttng_channel_destroy(struct lttng_channel *chan); +static int _lttng_event_unregister(struct lttng_event *event); +static +int _lttng_event_metadata_statedump(struct lttng_session *session, + struct lttng_channel *chan, + struct lttng_event *event); +static +int _lttng_session_metadata_statedump(struct lttng_session *session); + +int lttng_loglevel_match(const struct lttng_event_desc *desc, + enum lttng_ust_loglevel_type req_type, + int req_loglevel) +{ + int ev_loglevel; + + if (req_type == LTTNG_UST_LOGLEVEL_ALL) + return 1; + if (!desc->loglevel) + ev_loglevel = TRACE_DEFAULT; + else + ev_loglevel = *(*desc->loglevel); + switch (req_type) { + case LTTNG_UST_LOGLEVEL_RANGE: + if (ev_loglevel <= req_loglevel || req_loglevel == -1) + return 1; + else + return 0; + case LTTNG_UST_LOGLEVEL_SINGLE: + if (ev_loglevel == req_loglevel || req_loglevel == -1) + return 1; + else + return 0; + case LTTNG_UST_LOGLEVEL_ALL: + default: + return 1; + } +} + +/* + * Return wildcard for a given event name if the event name match the + * one of the wildcards. + * Must be called with ust lock held. + * Returns NULL if not present. + */ +static +struct wildcard_entry *match_wildcard(const struct lttng_event_desc *desc) +{ + struct wildcard_entry *e; + + cds_list_for_each_entry(e, &wildcard_list, list) { + /* If only contain '*' */ + if (strlen(e->name) == 1) + goto possible_match; + /* Compare excluding final '*' */ + if (!strncmp(desc->name, e->name, strlen(e->name) - 1)) + goto possible_match; + continue; /* goto next, no match */ + possible_match: + if (lttng_loglevel_match(desc, + e->loglevel_type, + e->loglevel)) { + return e; + } + /* no match, loop to next */ + } + return NULL; +} + +/* + * called at event creation if probe is missing. + * called with session mutex held. + */ +static +int add_pending_probe(struct lttng_event *event, const char *name, + enum lttng_ust_loglevel_type loglevel_type, + int loglevel) +{ + struct cds_hlist_head *head; + struct ust_pending_probe *e; + size_t name_len = strlen(name) + 1; + uint32_t hash; + + if (name_len > LTTNG_UST_SYM_NAME_LEN) { + WARN("Truncating tracepoint name %s which exceeds size limits of %u chars", name, LTTNG_UST_SYM_NAME_LEN); + name_len = LTTNG_UST_SYM_NAME_LEN; + } + hash = jhash(name, name_len - 1, 0); + head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)]; + e = zmalloc(sizeof(struct ust_pending_probe) + name_len); + if (!e) + return -ENOMEM; + memcpy(&e->name[0], name, name_len); + e->name[name_len - 1] = '\0'; + e->loglevel_type = loglevel_type; + e->loglevel = loglevel; + cds_hlist_add_head(&e->node, head); + e->event = event; + event->pending_probe = e; + return 0; +} + +/* + * remove a pending probe. called when at event teardown and when an + * event is fixed (probe is loaded). + * called with session mutex held. + */ +static +void remove_pending_probe(struct ust_pending_probe *e) +{ + if (!e) + return; + cds_hlist_del(&e->node); + free(e); +} + +/* + * Called at library load: connect the probe on the events pending on + * probe load. + * called with session mutex held. + */ +int pending_probe_fix_events(const struct lttng_event_desc *desc) +{ + struct cds_hlist_head *head; + struct cds_hlist_node *node, *p; + struct ust_pending_probe *e; + const char *name = desc->name; + int ret = 0; + struct lttng_ust_event event_param; + size_t name_len = strlen(name) + 1; + uint32_t hash; + + /* Wildcard */ + { + struct wildcard_entry *wildcard; + + //FIXME: should iterate on all match for filter. + //FIXME: should re-use pending event if present rather + //than create duplicate. + wildcard = match_wildcard(desc); + if (strcmp(desc->name, "lttng_ust:metadata") && wildcard) { + struct session_wildcard *sw; + + cds_list_for_each_entry(sw, &wildcard->session_list, + session_list) { + struct lttng_event *ev; + int ret; + + memcpy(&event_param, &sw->event_param, + sizeof(event_param)); + strncpy(event_param.name, + desc->name, + sizeof(event_param.name)); + event_param.name[sizeof(event_param.name) - 1] = '\0'; + /* create event */ + ret = lttng_event_create(sw->chan, + &event_param, &ev); + if (ret) { + DBG("Error creating event"); + continue; + } + cds_list_add(&ev->wildcard_list, + &sw->events); + lttng_filter_event_link_wildcard_bytecode(ev, + sw); + } + } + } + + if (name_len > LTTNG_UST_SYM_NAME_LEN) { + WARN("Truncating tracepoint name %s which exceeds size limits of %u chars", name, LTTNG_UST_SYM_NAME_LEN); + name_len = LTTNG_UST_SYM_NAME_LEN; + } + hash = jhash(name, name_len - 1, 0); + head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)]; + cds_hlist_for_each_entry_safe(e, node, p, head, node) { + struct lttng_event *event; + struct lttng_channel *chan; + + if (!lttng_loglevel_match(desc, + e->loglevel_type, + e->loglevel)) { + continue; + } + if (strncmp(name, e->name, LTTNG_UST_SYM_NAME_LEN - 1)) { + continue; + } + /* TODO: wildcard same as pending event: duplicate */ + /* TODO: Should apply filter though */ + event = e->event; + chan = event->chan; + assert(!event->desc); + event->desc = desc; + event->pending_probe = NULL; + remove_pending_probe(e); + ret |= __tracepoint_probe_register(name, + event->desc->probe_callback, + event, event->desc->signature); + if (ret) + continue; + event->id = chan->free_event_id++; + ret |= _lttng_event_metadata_statedump(chan->session, chan, + event); + lttng_filter_event_link_bytecode(event); + } + return ret; +} + +void synchronize_trace(void) +{ + synchronize_rcu(); +} + +struct lttng_session *lttng_session_create(void) +{ + struct lttng_session *session; + int ret; + + session = zmalloc(sizeof(struct lttng_session)); + if (!session) + return NULL; + CDS_INIT_LIST_HEAD(&session->chan); + CDS_INIT_LIST_HEAD(&session->events); + CDS_INIT_LIST_HEAD(&session->wildcards); + ret = lttng_ust_uuid_generate(session->uuid); + if (ret != 0) { + session->uuid[0] = '\0'; + } + cds_list_add(&session->list, &sessions); + return session; +} + +void lttng_session_destroy(struct lttng_session *session) +{ + struct lttng_channel *chan, *tmpchan; + struct lttng_event *event, *tmpevent; + struct session_wildcard *wildcard, *tmpwildcard; + int ret; + + CMM_ACCESS_ONCE(session->active) = 0; + cds_list_for_each_entry(event, &session->events, list) { + ret = _lttng_event_unregister(event); + WARN_ON(ret); + } + synchronize_trace(); /* Wait for in-flight events to complete */ + cds_list_for_each_entry_safe(wildcard, tmpwildcard, &session->wildcards, list) + _lttng_wildcard_destroy(wildcard); + cds_list_for_each_entry_safe(event, tmpevent, &session->events, list) + _lttng_event_destroy(event); + cds_list_for_each_entry_safe(chan, tmpchan, &session->chan, list) + _lttng_channel_destroy(chan); + cds_list_del(&session->list); + free(session); +} + +int lttng_session_enable(struct lttng_session *session) +{ + int ret = 0; + struct lttng_channel *chan; + + if (session->active) { + ret = -EBUSY; + goto end; + } + + /* + * Snapshot the number of events per channel to know the type of header + * we need to use. + */ + cds_list_for_each_entry(chan, &session->chan, list) { + if (chan->header_type) + continue; /* don't change it if session stop/restart */ + if (chan->free_event_id < 31) + chan->header_type = 1; /* compact */ + else + chan->header_type = 2; /* large */ + } + + CMM_ACCESS_ONCE(session->active) = 1; + CMM_ACCESS_ONCE(session->been_active) = 1; + ret = _lttng_session_metadata_statedump(session); + if (ret) + CMM_ACCESS_ONCE(session->active) = 0; +end: + return ret; +} + +int lttng_session_disable(struct lttng_session *session) +{ + int ret = 0; + + if (!session->active) { + ret = -EBUSY; + goto end; + } + CMM_ACCESS_ONCE(session->active) = 0; +end: + return ret; +} + +int lttng_channel_enable(struct lttng_channel *channel) +{ + int old; + + if (channel == channel->session->metadata) + return -EPERM; + old = uatomic_xchg(&channel->enabled, 1); + if (old) + return -EEXIST; + return 0; +} + +int lttng_channel_disable(struct lttng_channel *channel) +{ + int old; + + if (channel == channel->session->metadata) + return -EPERM; + old = uatomic_xchg(&channel->enabled, 0); + if (!old) + return -EEXIST; + return 0; +} + +int lttng_event_enable(struct lttng_event *event) +{ + int old; + + if (event->chan == event->chan->session->metadata) + return -EPERM; + old = uatomic_xchg(&event->enabled, 1); + if (old) + return -EEXIST; + return 0; +} + +int lttng_event_disable(struct lttng_event *event) +{ + int old; + + if (event->chan == event->chan->session->metadata) + return -EPERM; + old = uatomic_xchg(&event->enabled, 0); + if (!old) + return -EEXIST; + return 0; +} + +struct lttng_channel *lttng_channel_create(struct lttng_session *session, + const char *transport_name, + void *buf_addr, + size_t subbuf_size, size_t num_subbuf, + unsigned int switch_timer_interval, + unsigned int read_timer_interval, + int **shm_fd, int **wait_fd, + uint64_t **memory_map_size, + struct lttng_channel *chan_priv_init) +{ + struct lttng_channel *chan = NULL; + struct lttng_transport *transport; + + if (session->been_active) + goto active; /* Refuse to add channel to active session */ + transport = lttng_transport_find(transport_name); + if (!transport) { + DBG("LTTng transport %s not found\n", + transport_name); + goto notransport; + } + chan_priv_init->id = session->free_chan_id++; + chan_priv_init->session = session; + /* + * Note: the channel creation op already writes into the packet + * headers. Therefore the "chan" information used as input + * should be already accessible. + */ + chan = transport->ops.channel_create(transport_name, buf_addr, + subbuf_size, num_subbuf, switch_timer_interval, + read_timer_interval, shm_fd, wait_fd, + memory_map_size, chan_priv_init); + if (!chan) + goto create_error; + chan->enabled = 1; + chan->ops = &transport->ops; + cds_list_add(&chan->list, &session->chan); + return chan; + +create_error: +notransport: +active: + return NULL; +} + +/* + * Only used internally at session destruction. + */ +static +void _lttng_channel_destroy(struct lttng_channel *chan) +{ + cds_list_del(&chan->list); + lttng_destroy_context(chan->ctx); + chan->ops->channel_destroy(chan); +} + +/* + * Supports event creation while tracing session is active. + */ +int lttng_event_create(struct lttng_channel *chan, + struct lttng_ust_event *event_param, + struct lttng_event **_event) +{ + const struct lttng_event_desc *desc = NULL; /* silence gcc */ + struct lttng_event *event; + int ret = 0; + + if (chan->used_event_id == -1U) { + ret = -ENOMEM; + goto full; + } + //FIXME: re-use event if already registered by wildcard or + //if we have a pending probe.... (CHECK) + /* + * This is O(n^2) (for each event, the loop is called at event + * creation). Might require a hash if we have lots of events. + */ + cds_list_for_each_entry(event, &chan->session->events, list) { + if (event->desc && !strncmp(event->desc->name, + event_param->name, + LTTNG_UST_SYM_NAME_LEN - 1)) { + ret = -EEXIST; + goto exist; + } + } + + /* + * Check if loglevel match. Refuse to connect event if not. + */ + if (event_param->instrumentation == LTTNG_UST_TRACEPOINT) { + desc = lttng_event_get(event_param->name); + if (desc) { + if (!lttng_loglevel_match(desc, + event_param->loglevel_type, + event_param->loglevel)) { + ret = -EPERM; + goto no_loglevel_match; + } + } + /* + * If descriptor is not there, it will be added to + * pending probes. + */ + } + event = zmalloc(sizeof(struct lttng_event)); + if (!event) { + ret = -ENOMEM; + goto cache_error; + } + event->chan = chan; + /* + * used_event_id counts the maximum number of event IDs that can + * register if all probes register. + */ + chan->used_event_id++; + event->enabled = 1; + CDS_INIT_LIST_HEAD(&event->filter_bytecode); + CDS_INIT_LIST_HEAD(&event->bytecode_runtime); + event->instrumentation = event_param->instrumentation; + /* Populate lttng_event structure before tracepoint registration. */ + cmm_smp_wmb(); + switch (event_param->instrumentation) { + case LTTNG_UST_TRACEPOINT: + event->desc = desc; + if (event->desc) { + ret = __tracepoint_probe_register(event_param->name, + event->desc->probe_callback, + event, event->desc->signature); + if (ret) + goto register_error; + event->id = chan->free_event_id++; + } else { + /* + * If the probe is not present, event->desc stays NULL, + * waiting for the probe to register, and the event->id + * stays unallocated. + */ + ret = add_pending_probe(event, event_param->name, + event_param->loglevel_type, + event_param->loglevel); + if (ret) + goto add_pending_error; + } + break; + default: + WARN_ON_ONCE(1); + } + if (event->desc) { + ret = _lttng_event_metadata_statedump(chan->session, chan, event); + if (ret) + goto statedump_error; + } + cds_list_add(&event->list, &chan->session->events); + *_event = event; + return 0; + +statedump_error: + if (event->desc) { + WARN_ON_ONCE(__tracepoint_probe_unregister(event_param->name, + event->desc->probe_callback, + event)); + lttng_event_put(event->desc); + } +add_pending_error: +register_error: + free(event); +cache_error: +no_loglevel_match: +exist: +full: + return ret; +} + +/* + * Only used internally at session destruction. + */ +int _lttng_event_unregister(struct lttng_event *event) +{ + int ret = -EINVAL; + + switch (event->instrumentation) { + case LTTNG_UST_TRACEPOINT: + if (event->desc) { + ret = __tracepoint_probe_unregister(event->desc->name, + event->desc->probe_callback, + event); + if (ret) + return ret; + } else { + remove_pending_probe(event->pending_probe); + ret = 0; + } + break; + default: + WARN_ON_ONCE(1); + } + return ret; +} + +/* + * Only used internally at session destruction. + */ +static +void _lttng_event_destroy(struct lttng_event *event) +{ + switch (event->instrumentation) { + case LTTNG_UST_TRACEPOINT: + if (event->desc) { + lttng_event_put(event->desc); + } + break; + default: + WARN_ON_ONCE(1); + } + cds_list_del(&event->list); + lttng_destroy_context(event->ctx); + lttng_free_event_filter_runtime(event); + lttng_free_event_filter_bytecode(event); + free(event); +} + +/* + * We have exclusive access to our metadata buffer (protected by the + * ust_lock), so we can do racy operations such as looking for + * remaining space left in packet and write, since mutual exclusion + * protects us from concurrent writes. + */ +int lttng_metadata_printf(struct lttng_session *session, + const char *fmt, ...) +{ + struct lttng_ust_lib_ring_buffer_ctx ctx; + struct lttng_channel *chan = session->metadata; + char *str = NULL; + int ret = 0, waitret; + size_t len, reserve_len, pos; + va_list ap; + + WARN_ON_ONCE(!CMM_ACCESS_ONCE(session->active)); + + va_start(ap, fmt); + ret = vasprintf(&str, fmt, ap); + va_end(ap); + if (ret < 0) + return -ENOMEM; + + len = strlen(str); + pos = 0; + + for (pos = 0; pos < len; pos += reserve_len) { + reserve_len = min_t(size_t, + chan->ops->packet_avail_size(chan->chan, chan->handle), + len - pos); + lib_ring_buffer_ctx_init(&ctx, chan->chan, NULL, reserve_len, + sizeof(char), -1, chan->handle); + /* + * We don't care about metadata buffer's records lost + * count, because we always retry here. Report error if + * we need to bail out after timeout or being + * interrupted. + */ + waitret = wait_cond_interruptible_timeout( + ({ + ret = chan->ops->event_reserve(&ctx, 0); + ret != -ENOBUFS || !ret; + }), + LTTNG_METADATA_TIMEOUT_MSEC); + if (waitret == -ETIMEDOUT || waitret == -EINTR || ret) { + DBG("LTTng: Failure to write metadata to buffers (%s)\n", + waitret == -EINTR ? "interrupted" : + (ret == -ENOBUFS ? "timeout" : "I/O error")); + if (waitret == -EINTR) + ret = waitret; + goto end; + } + chan->ops->event_write(&ctx, &str[pos], reserve_len); + chan->ops->event_commit(&ctx); + } +end: + free(str); + return ret; +} + +static +int _lttng_field_statedump(struct lttng_session *session, + const struct lttng_event_field *field) +{ + int ret = 0; + + if (field->nowrite) + return 0; + + switch (field->type.atype) { + case atype_integer: + ret = lttng_metadata_printf(session, + " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n", + field->type.u.basic.integer.size, + field->type.u.basic.integer.alignment, + field->type.u.basic.integer.signedness, + (field->type.u.basic.integer.encoding == lttng_encode_none) + ? "none" + : (field->type.u.basic.integer.encoding == lttng_encode_UTF8) + ? "UTF8" + : "ASCII", + field->type.u.basic.integer.base, +#if (BYTE_ORDER == BIG_ENDIAN) + field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", +#else + field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", +#endif + field->name); + break; + case atype_float: + ret = lttng_metadata_printf(session, + " floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n", + field->type.u.basic._float.exp_dig, + field->type.u.basic._float.mant_dig, + field->type.u.basic._float.alignment, +#if (BYTE_ORDER == BIG_ENDIAN) + field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", +#else + field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", +#endif + field->name); + break; + case atype_enum: + ret = lttng_metadata_printf(session, + " %s %s;\n", + field->type.u.basic.enumeration.name, + field->name); + break; + case atype_array: + { + const struct lttng_basic_type *elem_type; + + elem_type = &field->type.u.array.elem_type; + ret = lttng_metadata_printf(session, + " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n", + elem_type->u.basic.integer.size, + elem_type->u.basic.integer.alignment, + elem_type->u.basic.integer.signedness, + (elem_type->u.basic.integer.encoding == lttng_encode_none) + ? "none" + : (elem_type->u.basic.integer.encoding == lttng_encode_UTF8) + ? "UTF8" + : "ASCII", + elem_type->u.basic.integer.base, +#if (BYTE_ORDER == BIG_ENDIAN) + elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", +#else + elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", +#endif + field->name, field->type.u.array.length); + break; + } + case atype_sequence: + { + const struct lttng_basic_type *elem_type; + const struct lttng_basic_type *length_type; + + elem_type = &field->type.u.sequence.elem_type; + length_type = &field->type.u.sequence.length_type; + ret = lttng_metadata_printf(session, + " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n", + length_type->u.basic.integer.size, + (unsigned int) length_type->u.basic.integer.alignment, + length_type->u.basic.integer.signedness, + (length_type->u.basic.integer.encoding == lttng_encode_none) + ? "none" + : ((length_type->u.basic.integer.encoding == lttng_encode_UTF8) + ? "UTF8" + : "ASCII"), + length_type->u.basic.integer.base, +#if (BYTE_ORDER == BIG_ENDIAN) + length_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", +#else + length_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", +#endif + field->name); + if (ret) + return ret; + + ret = lttng_metadata_printf(session, + " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n", + elem_type->u.basic.integer.size, + (unsigned int) elem_type->u.basic.integer.alignment, + elem_type->u.basic.integer.signedness, + (elem_type->u.basic.integer.encoding == lttng_encode_none) + ? "none" + : ((elem_type->u.basic.integer.encoding == lttng_encode_UTF8) + ? "UTF8" + : "ASCII"), + elem_type->u.basic.integer.base, +#if (BYTE_ORDER == BIG_ENDIAN) + elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", +#else + elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", +#endif + field->name, + field->name); + break; + } + + case atype_string: + /* Default encoding is UTF8 */ + ret = lttng_metadata_printf(session, + " string%s _%s;\n", + field->type.u.basic.string.encoding == lttng_encode_ASCII ? + " { encoding = ASCII; }" : "", + field->name); + break; + default: + WARN_ON_ONCE(1); + return -EINVAL; + } + return ret; +} + +static +int _lttng_context_metadata_statedump(struct lttng_session *session, + struct lttng_ctx *ctx) +{ + int ret = 0; + int i; + + if (!ctx) + return 0; + for (i = 0; i < ctx->nr_fields; i++) { + const struct lttng_ctx_field *field = &ctx->fields[i]; + + ret = _lttng_field_statedump(session, &field->event_field); + if (ret) + return ret; + } + return ret; +} + +static +int _lttng_fields_metadata_statedump(struct lttng_session *session, + struct lttng_event *event) +{ + const struct lttng_event_desc *desc = event->desc; + int ret = 0; + int i; + + for (i = 0; i < desc->nr_fields; i++) { + const struct lttng_event_field *field = &desc->fields[i]; + + ret = _lttng_field_statedump(session, field); + if (ret) + return ret; + } + return ret; +} + +static +int _lttng_event_metadata_statedump(struct lttng_session *session, + struct lttng_channel *chan, + struct lttng_event *event) +{ + int ret = 0; + int loglevel = TRACE_DEFAULT; + + if (event->metadata_dumped || !CMM_ACCESS_ONCE(session->active)) + return 0; + if (chan == session->metadata) + return 0; + /* + * Don't print events for which probe load is pending. + */ + if (!event->desc) + return 0; + + ret = lttng_metadata_printf(session, + "event {\n" + " name = \"%s\";\n" + " id = %u;\n" + " stream_id = %u;\n", + event->desc->name, + event->id, + event->chan->id); + if (ret) + goto end; + + if (event->desc->loglevel) + loglevel = *(*event->desc->loglevel); + + ret = lttng_metadata_printf(session, + " loglevel = %d;\n", + loglevel); + if (ret) + goto end; + + if (event->desc->u.ext.model_emf_uri) { + ret = lttng_metadata_printf(session, + " model.emf.uri = \"%s\";\n", + *(event->desc->u.ext.model_emf_uri)); + if (ret) + goto end; + } + + if (event->ctx) { + ret = lttng_metadata_printf(session, + " context := struct {\n"); + if (ret) + goto end; + } + ret = _lttng_context_metadata_statedump(session, event->ctx); + if (ret) + goto end; + if (event->ctx) { + ret = lttng_metadata_printf(session, + " };\n"); + if (ret) + goto end; + } + + ret = lttng_metadata_printf(session, + " fields := struct {\n" + ); + if (ret) + goto end; + + ret = _lttng_fields_metadata_statedump(session, event); + if (ret) + goto end; + + /* + * LTTng space reservation can only reserve multiples of the + * byte size. + */ + ret = lttng_metadata_printf(session, + " };\n" + "};\n\n"); + if (ret) + goto end; + + event->metadata_dumped = 1; +end: + return ret; + +} + +static +int _lttng_channel_metadata_statedump(struct lttng_session *session, + struct lttng_channel *chan) +{ + int ret = 0; + + if (chan->metadata_dumped || !CMM_ACCESS_ONCE(session->active)) + return 0; + if (chan == session->metadata) + return 0; + + WARN_ON_ONCE(!chan->header_type); + ret = lttng_metadata_printf(session, + "stream {\n" + " id = %u;\n" + " event.header := %s;\n" + " packet.context := struct packet_context;\n", + chan->id, + chan->header_type == 1 ? "struct event_header_compact" : + "struct event_header_large"); + if (ret) + goto end; + + if (chan->ctx) { + ret = lttng_metadata_printf(session, + " event.context := struct {\n"); + if (ret) + goto end; + } + ret = _lttng_context_metadata_statedump(session, chan->ctx); + if (ret) + goto end; + if (chan->ctx) { + ret = lttng_metadata_printf(session, + " };\n"); + if (ret) + goto end; + } + + ret = lttng_metadata_printf(session, + "};\n\n"); + + chan->metadata_dumped = 1; +end: + return ret; +} + +static +int _lttng_stream_packet_context_declare(struct lttng_session *session) +{ + return lttng_metadata_printf(session, + "struct packet_context {\n" + " uint64_clock_monotonic_t timestamp_begin;\n" + " uint64_clock_monotonic_t timestamp_end;\n" + " uint64_t content_size;\n" + " uint64_t packet_size;\n" + " unsigned long events_discarded;\n" + " uint32_t cpu_id;\n" + "};\n\n" + ); +} + +/* + * Compact header: + * id: range: 0 - 30. + * id 31 is reserved to indicate an extended header. + * + * Large header: + * id: range: 0 - 65534. + * id 65535 is reserved to indicate an extended header. + */ +static +int _lttng_event_header_declare(struct lttng_session *session) +{ + return lttng_metadata_printf(session, + "struct event_header_compact {\n" + " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n" + " variant {\n" + " struct {\n" + " uint27_clock_monotonic_t timestamp;\n" + " } compact;\n" + " struct {\n" + " uint32_t id;\n" + " uint64_clock_monotonic_t timestamp;\n" + " } extended;\n" + " } v;\n" + "} align(%u);\n" + "\n" + "struct event_header_large {\n" + " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n" + " variant {\n" + " struct {\n" + " uint32_clock_monotonic_t timestamp;\n" + " } compact;\n" + " struct {\n" + " uint32_t id;\n" + " uint64_clock_monotonic_t timestamp;\n" + " } extended;\n" + " } v;\n" + "} align(%u);\n\n", + lttng_alignof(uint32_t) * CHAR_BIT, + lttng_alignof(uint16_t) * CHAR_BIT + ); +} + +/* + * Approximation of NTP time of day to clock monotonic correlation, + * taken at start of trace. + * Yes, this is only an approximation. Yes, we can (and will) do better + * in future versions. + */ +static +uint64_t measure_clock_offset(void) +{ + uint64_t offset, monotonic[2], realtime; + struct timespec rts = { 0, 0 }; + int ret; + + monotonic[0] = trace_clock_read64(); + ret = clock_gettime(CLOCK_REALTIME, &rts); + if (ret < 0) + return 0; + monotonic[1] = trace_clock_read64(); + offset = (monotonic[0] + monotonic[1]) >> 1; + realtime = (uint64_t) rts.tv_sec * 1000000000ULL; + realtime += rts.tv_nsec; + offset = realtime - offset; + return offset; +} + +/* + * Output metadata into this session's metadata buffers. + */ +static +int _lttng_session_metadata_statedump(struct lttng_session *session) +{ + unsigned char *uuid_c = session->uuid; + char uuid_s[LTTNG_UST_UUID_STR_LEN], + clock_uuid_s[LTTNG_UST_UUID_STR_LEN]; + struct lttng_channel *chan; + struct lttng_event *event; + int ret = 0; + char procname[LTTNG_UST_PROCNAME_LEN] = ""; + char hostname[HOST_NAME_MAX]; + + if (!CMM_ACCESS_ONCE(session->active)) + return 0; + if (session->metadata_dumped) + goto skip_session; + if (!session->metadata) { + DBG("LTTng: attempt to start tracing, but metadata channel is not found. Operation abort.\n"); + return -EPERM; + } + + snprintf(uuid_s, sizeof(uuid_s), + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid_c[0], uuid_c[1], uuid_c[2], uuid_c[3], + uuid_c[4], uuid_c[5], uuid_c[6], uuid_c[7], + uuid_c[8], uuid_c[9], uuid_c[10], uuid_c[11], + uuid_c[12], uuid_c[13], uuid_c[14], uuid_c[15]); + + ret = lttng_metadata_printf(session, + "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n" + "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n" + "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n" + "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n" + "typealias integer { size = %u; align = %u; signed = false; } := unsigned long;\n" + "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n" + "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n" + "\n" + "trace {\n" + " major = %u;\n" + " minor = %u;\n" + " uuid = \"%s\";\n" + " byte_order = %s;\n" + " packet.header := struct {\n" + " uint32_t magic;\n" + " uint8_t uuid[16];\n" + " uint32_t stream_id;\n" + " };\n" + "};\n\n", + lttng_alignof(uint8_t) * CHAR_BIT, + lttng_alignof(uint16_t) * CHAR_BIT, + lttng_alignof(uint32_t) * CHAR_BIT, + lttng_alignof(uint64_t) * CHAR_BIT, + sizeof(unsigned long) * CHAR_BIT, + lttng_alignof(unsigned long) * CHAR_BIT, + CTF_SPEC_MAJOR, + CTF_SPEC_MINOR, + uuid_s, +#if (BYTE_ORDER == BIG_ENDIAN) + "be" +#else + "le" +#endif + ); + if (ret) + goto end; + + /* ignore error, just use empty string if error. */ + hostname[0] = '\0'; + ret = gethostname(hostname, sizeof(hostname)); + if (ret && errno == ENAMETOOLONG) + hostname[HOST_NAME_MAX - 1] = '\0'; + lttng_ust_getprocname(procname); + procname[LTTNG_UST_PROCNAME_LEN - 1] = '\0'; + ret = lttng_metadata_printf(session, + "env {\n" + " hostname = \"%s\";\n" + " vpid = %d;\n" + " procname = \"%s\";\n" + " domain = \"ust\";\n" + " tracer_name = \"lttng-ust\";\n" + " tracer_major = %u;\n" + " tracer_minor = %u;\n" + " tracer_patchlevel = %u;\n" + "};\n\n", + hostname, + (int) getpid(), + procname, + LTTNG_UST_MAJOR_VERSION, + LTTNG_UST_MINOR_VERSION, + LTTNG_UST_PATCHLEVEL_VERSION + ); + if (ret) + goto end; + + ret = lttng_metadata_printf(session, + "clock {\n" + " name = %s;\n", + "monotonic" + ); + if (ret) + goto end; + + if (!trace_clock_uuid(clock_uuid_s)) { + ret = lttng_metadata_printf(session, + " uuid = \"%s\";\n", + clock_uuid_s + ); + if (ret) + goto end; + } + + ret = lttng_metadata_printf(session, + " description = \"Monotonic Clock\";\n" + " freq = %" PRIu64 "; /* Frequency, in Hz */\n" + " /* clock value offset from Epoch is: offset * (1/freq) */\n" + " offset = %" PRIu64 ";\n" + "};\n\n", + trace_clock_freq(), + measure_clock_offset() + ); + if (ret) + goto end; + + ret = lttng_metadata_printf(session, + "typealias integer {\n" + " size = 27; align = 1; signed = false;\n" + " map = clock.monotonic.value;\n" + "} := uint27_clock_monotonic_t;\n" + "\n" + "typealias integer {\n" + " size = 32; align = %u; signed = false;\n" + " map = clock.monotonic.value;\n" + "} := uint32_clock_monotonic_t;\n" + "\n" + "typealias integer {\n" + " size = 64; align = %u; signed = false;\n" + " map = clock.monotonic.value;\n" + "} := uint64_clock_monotonic_t;\n\n", + lttng_alignof(uint32_t) * CHAR_BIT, + lttng_alignof(uint64_t) * CHAR_BIT + ); + if (ret) + goto end; + + ret = _lttng_stream_packet_context_declare(session); + if (ret) + goto end; + + ret = _lttng_event_header_declare(session); + if (ret) + goto end; + +skip_session: + cds_list_for_each_entry(chan, &session->chan, list) { + ret = _lttng_channel_metadata_statedump(session, chan); + if (ret) + goto end; + } + + cds_list_for_each_entry(event, &session->events, list) { + ret = _lttng_event_metadata_statedump(session, event->chan, event); + if (ret) + goto end; + } + session->metadata_dumped = 1; +end: + return ret; +} + +void lttng_ust_events_exit(void) +{ + struct lttng_session *session, *tmpsession; + + cds_list_for_each_entry_safe(session, tmpsession, &sessions, list) + lttng_session_destroy(session); +} + +/* WILDCARDS */ + +static +int wildcard_same_loglevel(struct wildcard_entry *e, + enum lttng_ust_loglevel_type loglevel_type, + int loglevel) +{ + if (e->loglevel_type == loglevel_type && e->loglevel == loglevel) + return 1; + else + return 0; +} + +#if 0 +static +int wildcard_is_within(struct wildcard_entry *e, + enum lttng_ust_loglevel_type loglevel_type, + int loglevel) +{ + if (e->loglevel_type == LTTNG_UST_LOGLEVEL_ALL + || e->loglevel == -1) + return 1; + switch (e->loglevel_type) { + case LTTNG_UST_LOGLEVEL_RANGE: + switch (loglevel_type) { + case LTTNG_UST_LOGLEVEL_RANGE: + if (e->loglevel >= loglevel) + return 1; + else + return 0; + case LTTNG_UST_LOGLEVEL_SINGLE: + if (e->loglevel <= 0 && loglevel == 0) + return 1; + else + return 0; + } + case LTTNG_UST_LOGLEVEL_SINGLE: + switch (loglevel_type) { + case LTTNG_UST_LOGLEVEL_RANGE: + if (loglevel <= 0) + return 1; + else + return 0; + case LTTNG_UST_LOGLEVEL_SINGLE: + if (e->loglevel == loglevel) + return 1; + else + return 0; + } + } +} +#endif + +/* + * Add the wildcard to the wildcard list. Must be called with + * ust lock held. + */ +static +struct session_wildcard *add_wildcard(struct lttng_channel *chan, + struct lttng_ust_event *event_param) +{ + struct wildcard_entry *e; + struct session_wildcard *sw; + size_t name_len = strlen(event_param->name) + 1; + int found = 0; + + //FIXME: ensure that wildcard re-use pending events, or + //re-use actual events, applying its filter on top. + + /* + * Try to find global wildcard entry. Given that this is shared + * across all sessions, we need to check for exact loglevel + * match, not just whether contained within the existing ones. + */ + cds_list_for_each_entry(e, &wildcard_list, list) { + if (!strncmp(event_param->name, e->name, + LTTNG_UST_SYM_NAME_LEN - 1)) { + if (wildcard_same_loglevel(e, + event_param->loglevel_type, + event_param->loglevel)) { + found = 1; + break; + } + } + } + + if (!found) { + /* + * Create global wildcard entry if not found. Using + * zmalloc here to allocate a variable length element. + * Could cause some memory fragmentation if overused. + */ + e = zmalloc(sizeof(struct wildcard_entry) + name_len); + if (!e) + return ERR_PTR(-ENOMEM); + memcpy(&e->name[0], event_param->name, name_len); + e->loglevel_type = event_param->loglevel_type; + e->loglevel = event_param->loglevel; + CDS_INIT_LIST_HEAD(&e->filter_bytecode); + cds_list_add(&e->list, &wildcard_list); + CDS_INIT_LIST_HEAD(&e->session_list); + } + + /* session wildcard */ + cds_list_for_each_entry(sw, &e->session_list, session_list) { + if (chan == sw->chan) { + DBG("wildcard %s busy for this channel", + event_param->name); + return ERR_PTR(-EEXIST); /* Already there */ + } + } + sw = zmalloc(sizeof(struct session_wildcard)); + if (!sw) + return ERR_PTR(-ENOMEM); + sw->chan = chan; + sw->enabled = 1; + memcpy(&sw->event_param, event_param, sizeof(sw->event_param)); + sw->event_param.instrumentation = LTTNG_UST_TRACEPOINT; + sw->event_param.loglevel_type = event_param->loglevel_type; + sw->event_param.loglevel = event_param->loglevel; + CDS_INIT_LIST_HEAD(&sw->filter_bytecode); + CDS_INIT_LIST_HEAD(&sw->events); + cds_list_add(&sw->list, &chan->session->wildcards); + cds_list_add(&sw->session_list, &e->session_list); + sw->entry = e; + lttng_probes_create_wildcard_events(e, sw); + return sw; +} + +/* + * Remove the wildcard from the wildcard list. Must be called with + * ust_lock held. Only called at session teardown. + */ +static +void _remove_wildcard(struct session_wildcard *wildcard) +{ + struct lttng_event *ev, *tmp; + + /* + * Just remove the events owned (for enable/disable) by this + * wildcard from the list. The session teardown will take care + * of freeing the event memory. + */ + cds_list_for_each_entry_safe(ev, tmp, &wildcard->events, + wildcard_list) { + cds_list_del(&ev->wildcard_list); + } + cds_list_del(&wildcard->session_list); + cds_list_del(&wildcard->list); + if (cds_list_empty(&wildcard->entry->session_list)) { + cds_list_del(&wildcard->entry->list); + free(wildcard->entry); + } + lttng_free_wildcard_filter_bytecode(wildcard); + free(wildcard); +} + +int lttng_wildcard_create(struct lttng_channel *chan, + struct lttng_ust_event *event_param, + struct session_wildcard **_sw) +{ + struct session_wildcard *sw; + + sw = add_wildcard(chan, event_param); + if (!sw || IS_ERR(sw)) { + return PTR_ERR(sw); + } + *_sw = sw; + return 0; +} + +static +void _lttng_wildcard_destroy(struct session_wildcard *sw) +{ + _remove_wildcard(sw); +} + +int lttng_wildcard_enable(struct session_wildcard *wildcard) +{ + struct lttng_event *ev; + int ret; + + if (wildcard->enabled) + return -EEXIST; + cds_list_for_each_entry(ev, &wildcard->events, wildcard_list) { + ret = lttng_event_enable(ev); + if (ret) { + DBG("Error: enable error.\n"); + return ret; + } + } + wildcard->enabled = 1; + return 0; +} + +int lttng_wildcard_disable(struct session_wildcard *wildcard) +{ + struct lttng_event *ev; + int ret; + + if (!wildcard->enabled) + return -EEXIST; + cds_list_for_each_entry(ev, &wildcard->events, wildcard_list) { + ret = lttng_event_disable(ev); + if (ret) { + DBG("Error: disable error.\n"); + return ret; + } + } + wildcard->enabled = 0; + return 0; +} + +/* + * Take the TLS "fault" in libuuid if dlopen'd, which can take the + * dynamic linker mutex, outside of the UST lock, since the UST lock is + * taken in constructors, which are called with dynamic linker mutex + * held. + */ +void lttng_fixup_event_tls(void) +{ + unsigned char uuid[LTTNG_UST_UUID_STR_LEN]; + + (void) lttng_ust_uuid_generate(uuid); +} diff --git a/liblttng-ust/lttng-filter.c b/liblttng-ust/lttng-filter.c index 6c3eda4b..c298addf 100644 --- a/liblttng-ust/lttng-filter.c +++ b/liblttng-ust/lttng-filter.c @@ -128,7 +128,7 @@ const char *print_op(enum filter_op op) } static -int apply_field_reloc(struct ltt_event *event, +int apply_field_reloc(struct lttng_event *event, struct bytecode_runtime *runtime, uint32_t runtime_len, uint32_t reloc_offset, @@ -216,7 +216,7 @@ int apply_field_reloc(struct ltt_event *event, static int bytecode_is_linked(struct lttng_ust_filter_bytecode_node *filter_bytecode, - struct ltt_event *event) + struct lttng_event *event) { struct lttng_bytecode_runtime *bc_runtime; @@ -232,7 +232,7 @@ int bytecode_is_linked(struct lttng_ust_filter_bytecode_node *filter_bytecode, * bytecode runtime. */ static -int _lttng_filter_event_link_bytecode(struct ltt_event *event, +int _lttng_filter_event_link_bytecode(struct lttng_event *event, struct lttng_ust_filter_bytecode_node *filter_bytecode) { int ret, offset, next_offset; @@ -303,7 +303,7 @@ link_error: return ret; } -void lttng_filter_event_link_bytecode(struct ltt_event *event) +void lttng_filter_event_link_bytecode(struct lttng_event *event) { struct lttng_ust_filter_bytecode_node *filter_bytecode; int ret; @@ -317,7 +317,7 @@ void lttng_filter_event_link_bytecode(struct ltt_event *event) } } -void lttng_filter_event_link_wildcard_bytecode(struct ltt_event *event, +void lttng_filter_event_link_wildcard_bytecode(struct lttng_event *event, struct session_wildcard *wildcard) { struct lttng_ust_filter_bytecode_node *filter_bytecode; @@ -339,7 +339,7 @@ void lttng_filter_event_link_wildcard_bytecode(struct ltt_event *event, */ void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard) { - struct ltt_event *event; + struct lttng_event *event; if (cds_list_empty(&wildcard->filter_bytecode)) return; @@ -354,7 +354,7 @@ void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard) * Need to attach filter to an event before starting tracing for the * session. We own the filter_bytecode if we return success. */ -int lttng_filter_event_attach_bytecode(struct ltt_event *event, +int lttng_filter_event_attach_bytecode(struct lttng_event *event, struct lttng_ust_filter_bytecode_node *filter_bytecode) { cds_list_add(&filter_bytecode->node, &event->filter_bytecode); @@ -372,7 +372,7 @@ int lttng_filter_wildcard_attach_bytecode(struct session_wildcard *wildcard, return 0; } -void lttng_free_event_filter_bytecode(struct ltt_event *event) +void lttng_free_event_filter_bytecode(struct lttng_event *event) { struct lttng_ust_filter_bytecode_node *filter_bytecode, *tmp; @@ -392,7 +392,7 @@ void lttng_free_wildcard_filter_bytecode(struct session_wildcard *wildcard) } } -void lttng_free_event_filter_runtime(struct ltt_event *event) +void lttng_free_event_filter_runtime(struct lttng_event *event) { struct bytecode_runtime *runtime, *tmp; diff --git a/liblttng-ust/lttng-probes.c b/liblttng-ust/lttng-probes.c new file mode 100644 index 00000000..e473b989 --- /dev/null +++ b/liblttng-ust/lttng-probes.c @@ -0,0 +1,423 @@ +/* + * lttng-probes.c + * + * Holds LTTng probes registry. + * + * Copyright 2010-2012 (c) - 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; only + * 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 + */ + +#include +#include +#include +#include +#include +#include +#include "tracepoint-internal.h" +#include +#include +#include + +#include "lttng-tracer-core.h" +#include "jhash.h" +#include "error.h" + +/* + * probe list is protected by ust_lock()/ust_unlock(). + */ +static CDS_LIST_HEAD(probe_list); + +static +const struct lttng_probe_desc *find_provider(const char *provider) +{ + struct lttng_probe_desc *iter; + + cds_list_for_each_entry(iter, &probe_list, head) { + if (!strcmp(iter->provider, provider)) + return iter; + } + return NULL; +} + +static +const struct lttng_event_desc *find_event(const char *name) +{ + struct lttng_probe_desc *probe_desc; + int i; + + cds_list_for_each_entry(probe_desc, &probe_list, head) { + for (i = 0; i < probe_desc->nr_events; i++) { + if (!strncmp(probe_desc->event_desc[i]->name, name, + LTTNG_UST_SYM_NAME_LEN - 1)) + return probe_desc->event_desc[i]; + } + } + return NULL; +} + +int lttng_probe_register(struct lttng_probe_desc *desc) +{ + struct lttng_probe_desc *iter; + int ret = 0; + int i; + + ust_lock(); + if (find_provider(desc->provider)) { + ret = -EEXIST; + goto end; + } + /* + * TODO: This is O(N^2). Turn into a hash table when probe registration + * overhead becomes an issue. + */ + for (i = 0; i < desc->nr_events; i++) { + if (find_event(desc->event_desc[i]->name)) { + ret = -EEXIST; + goto end; + } + } + + /* + * We sort the providers by struct lttng_probe_desc pointer + * address. + */ + cds_list_for_each_entry_reverse(iter, &probe_list, head) { + BUG_ON(iter == desc); /* Should never be in the list twice */ + if (iter < desc) { + /* We belong to the location right after iter. */ + cds_list_add(&desc->head, &iter->head); + goto desc_added; + } + } + /* We should be added at the head of the list */ + cds_list_add(&desc->head, &probe_list); +desc_added: + DBG("just registered probe %s containing %u events", + desc->provider, desc->nr_events); + /* + * fix the events awaiting probe load. + */ + for (i = 0; i < desc->nr_events; i++) { + const struct lttng_event_desc *ed; + + ed = desc->event_desc[i]; + DBG("Registered event probe \"%s\" with signature \"%s\"", + ed->name, ed->signature); + ret = pending_probe_fix_events(ed); + assert(!ret); + } +end: + ust_unlock(); + return ret; +} + +/* Backward compatibility with UST 2.0 */ +int ltt_probe_register(struct lttng_probe_desc *desc) +{ + return lttng_probe_register(desc); +} + +void lttng_probe_unregister(struct lttng_probe_desc *desc) +{ + ust_lock(); + cds_list_del(&desc->head); + DBG("just unregistered probe %s", desc->provider); + ust_unlock(); +} + +/* Backward compatibility with UST 2.0 */ +void ltt_probe_unregister(struct lttng_probe_desc *desc) +{ + lttng_probe_unregister(desc); +} + +/* + * called with UST lock held. + */ +const struct lttng_event_desc *lttng_event_get(const char *name) +{ + const struct lttng_event_desc *event; + + event = find_event(name); + if (!event) + return NULL; + return event; +} + +void lttng_event_put(const struct lttng_event_desc *event) +{ +} + +void lttng_probes_prune_event_list(struct lttng_ust_tracepoint_list *list) +{ + struct tp_list_entry *list_entry, *tmp; + + cds_list_for_each_entry_safe(list_entry, tmp, &list->head, head) { + cds_list_del(&list_entry->head); + free(list_entry); + } +} + +/* + * called with UST lock held. + */ +int lttng_probes_get_event_list(struct lttng_ust_tracepoint_list *list) +{ + struct lttng_probe_desc *probe_desc; + int i; + + CDS_INIT_LIST_HEAD(&list->head); + cds_list_for_each_entry(probe_desc, &probe_list, head) { + for (i = 0; i < probe_desc->nr_events; i++) { + struct tp_list_entry *list_entry; + + list_entry = zmalloc(sizeof(*list_entry)); + if (!list_entry) + goto err_nomem; + cds_list_add(&list_entry->head, &list->head); + strncpy(list_entry->tp.name, + probe_desc->event_desc[i]->name, + LTTNG_UST_SYM_NAME_LEN); + list_entry->tp.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; + if (!probe_desc->event_desc[i]->loglevel) { + list_entry->tp.loglevel = TRACE_DEFAULT; + } else { + list_entry->tp.loglevel = *(*probe_desc->event_desc[i]->loglevel); + } + } + } + if (cds_list_empty(&list->head)) + list->iter = NULL; + else + list->iter = + cds_list_first_entry(&list->head, struct tp_list_entry, head); + return 0; + +err_nomem: + lttng_probes_prune_event_list(list); + return -ENOMEM; +} + +/* + * Return current iteration position, advance internal iterator to next. + * Return NULL if end of list. + */ +struct lttng_ust_tracepoint_iter * + lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list *list) +{ + struct tp_list_entry *entry; + + if (!list->iter) + return NULL; + entry = list->iter; + if (entry->head.next == &list->head) + list->iter = NULL; + else + list->iter = cds_list_entry(entry->head.next, + struct tp_list_entry, head); + return &entry->tp; +} + +void lttng_probes_prune_field_list(struct lttng_ust_field_list *list) +{ + struct tp_field_list_entry *list_entry, *tmp; + + cds_list_for_each_entry_safe(list_entry, tmp, &list->head, head) { + cds_list_del(&list_entry->head); + free(list_entry); + } +} + +/* + * called with UST lock held. + */ +int lttng_probes_get_field_list(struct lttng_ust_field_list *list) +{ + struct lttng_probe_desc *probe_desc; + int i; + + CDS_INIT_LIST_HEAD(&list->head); + cds_list_for_each_entry(probe_desc, &probe_list, head) { + for (i = 0; i < probe_desc->nr_events; i++) { + const struct lttng_event_desc *event_desc = + probe_desc->event_desc[i]; + int j; + + if (event_desc->nr_fields == 0) { + /* Events without fields. */ + struct tp_field_list_entry *list_entry; + + list_entry = zmalloc(sizeof(*list_entry)); + if (!list_entry) + goto err_nomem; + cds_list_add(&list_entry->head, &list->head); + strncpy(list_entry->field.event_name, + event_desc->name, + LTTNG_UST_SYM_NAME_LEN); + list_entry->field.event_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; + list_entry->field.field_name[0] = '\0'; + list_entry->field.type = LTTNG_UST_FIELD_OTHER; + if (!event_desc->loglevel) { + list_entry->field.loglevel = TRACE_DEFAULT; + } else { + list_entry->field.loglevel = *(*event_desc->loglevel); + } + list_entry->field.nowrite = 1; + } + + for (j = 0; j < event_desc->nr_fields; j++) { + const struct lttng_event_field *event_field = + &event_desc->fields[j]; + struct tp_field_list_entry *list_entry; + + list_entry = zmalloc(sizeof(*list_entry)); + if (!list_entry) + goto err_nomem; + cds_list_add(&list_entry->head, &list->head); + strncpy(list_entry->field.event_name, + event_desc->name, + LTTNG_UST_SYM_NAME_LEN); + list_entry->field.event_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; + strncpy(list_entry->field.field_name, + event_field->name, + LTTNG_UST_SYM_NAME_LEN); + list_entry->field.field_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; + switch (event_field->type.atype) { + case atype_integer: + list_entry->field.type = LTTNG_UST_FIELD_INTEGER; + break; + case atype_string: + list_entry->field.type = LTTNG_UST_FIELD_STRING; + break; + case atype_array: + if (event_field->type.u.array.elem_type.atype != atype_integer + || event_field->type.u.array.elem_type.u.basic.integer.encoding == lttng_encode_none) + list_entry->field.type = LTTNG_UST_FIELD_OTHER; + else + list_entry->field.type = LTTNG_UST_FIELD_STRING; + break; + case atype_sequence: + if (event_field->type.u.sequence.elem_type.atype != atype_integer + || event_field->type.u.sequence.elem_type.u.basic.integer.encoding == lttng_encode_none) + list_entry->field.type = LTTNG_UST_FIELD_OTHER; + else + list_entry->field.type = LTTNG_UST_FIELD_STRING; + break; + case atype_float: + list_entry->field.type = LTTNG_UST_FIELD_FLOAT; + break; + case atype_enum: + list_entry->field.type = LTTNG_UST_FIELD_ENUM; + break; + default: + list_entry->field.type = LTTNG_UST_FIELD_OTHER; + } + if (!event_desc->loglevel) { + list_entry->field.loglevel = TRACE_DEFAULT; + } else { + list_entry->field.loglevel = *(*event_desc->loglevel); + } + list_entry->field.nowrite = event_field->nowrite; + } + } + } + if (cds_list_empty(&list->head)) + list->iter = NULL; + else + list->iter = + cds_list_first_entry(&list->head, + struct tp_field_list_entry, head); + return 0; + +err_nomem: + lttng_probes_prune_field_list(list); + return -ENOMEM; +} + +/* + * Return current iteration position, advance internal iterator to next. + * Return NULL if end of list. + */ +struct lttng_ust_field_iter * + lttng_ust_field_list_get_iter_next(struct lttng_ust_field_list *list) +{ + struct tp_field_list_entry *entry; + + if (!list->iter) + return NULL; + entry = list->iter; + if (entry->head.next == &list->head) + list->iter = NULL; + else + list->iter = cds_list_entry(entry->head.next, + struct tp_field_list_entry, head); + return &entry->field; +} + +/* + * marshall all probes/all events and create those that fit the + * wildcard. Add them to the events list as created. + */ +void lttng_probes_create_wildcard_events(struct wildcard_entry *entry, + struct session_wildcard *wildcard) +{ + struct lttng_probe_desc *probe_desc; + struct lttng_ust_event event_param; + int i; + + cds_list_for_each_entry(probe_desc, &probe_list, head) { + for (i = 0; i < probe_desc->nr_events; i++) { + const struct lttng_event_desc *event_desc; + int match = 0; + + event_desc = probe_desc->event_desc[i]; + /* compare excluding final '*' */ + assert(strlen(entry->name) > 0); + if (strcmp(event_desc->name, "lttng_ust:metadata") + && (strlen(entry->name) == 1 + || !strncmp(event_desc->name, entry->name, + strlen(entry->name) - 1))) { + if (lttng_loglevel_match(event_desc, + entry->loglevel_type, + entry->loglevel)) { + match = 1; + } + } + if (match) { + struct lttng_event *ev; + int ret; + + memcpy(&event_param, &wildcard->event_param, + sizeof(event_param)); + strncpy(event_param.name, + event_desc->name, + sizeof(event_param.name)); + event_param.name[sizeof(event_param.name) - 1] = '\0'; + /* create event */ + ret = lttng_event_create(wildcard->chan, + &event_param, &ev); + if (ret) { + DBG("Error creating event"); + continue; + } + cds_list_add(&ev->wildcard_list, + &wildcard->events); + } + } + } + lttng_filter_wildcard_link_bytecode(wildcard); +} + diff --git a/liblttng-ust/lttng-ring-buffer-client-discard.c b/liblttng-ust/lttng-ring-buffer-client-discard.c new file mode 100644 index 00000000..0463864b --- /dev/null +++ b/liblttng-ust/lttng-ring-buffer-client-discard.c @@ -0,0 +1,34 @@ +/* + * lttng-ring-buffer-client-discard.c + * + * LTTng lib ring buffer client (discard mode). + * + * Copyright (C) 2010-2012 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; only + * 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 _GNU_SOURCE +#include "lttng-tracer.h" + +#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD +#define RING_BUFFER_MODE_TEMPLATE_STRING "discard" +#define RING_BUFFER_MODE_TEMPLATE_INIT \ + lttng_ring_buffer_client_discard_init +#define RING_BUFFER_MODE_TEMPLATE_EXIT \ + lttng_ring_buffer_client_discard_exit +#define LTTNG_CLIENT_TYPE LTTNG_CLIENT_DISCARD +#define LTTNG_CLIENT_CALLBACKS lttng_client_callbacks_discard +#include "lttng-ring-buffer-client.h" diff --git a/liblttng-ust/lttng-ring-buffer-client-overwrite.c b/liblttng-ust/lttng-ring-buffer-client-overwrite.c new file mode 100644 index 00000000..3d6fdabf --- /dev/null +++ b/liblttng-ust/lttng-ring-buffer-client-overwrite.c @@ -0,0 +1,34 @@ +/* + * lttng-ring-buffer-client-overwrite.c + * + * LTTng lib ring buffer client (overwrite mode). + * + * Copyright (C) 2010-2012 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; only + * 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 _GNU_SOURCE +#include "lttng-tracer.h" + +#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_OVERWRITE +#define RING_BUFFER_MODE_TEMPLATE_STRING "overwrite" +#define RING_BUFFER_MODE_TEMPLATE_INIT \ + lttng_ring_buffer_client_overwrite_init +#define RING_BUFFER_MODE_TEMPLATE_EXIT \ + lttng_ring_buffer_client_overwrite_exit +#define LTTNG_CLIENT_TYPE LTTNG_CLIENT_OVERWRITE +#define LTTNG_CLIENT_CALLBACKS lttng_client_callbacks_overwrite +#include "lttng-ring-buffer-client.h" diff --git a/liblttng-ust/lttng-ring-buffer-client.h b/liblttng-ust/lttng-ring-buffer-client.h new file mode 100644 index 00000000..ad77802f --- /dev/null +++ b/liblttng-ust/lttng-ring-buffer-client.h @@ -0,0 +1,595 @@ +/* + * lttng-ring-buffer-client.h + * + * LTTng lib ring buffer client template. + * + * Copyright (C) 2010-2012 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; only + * 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 + */ + +#include +#include +#include "lttng/bitfield.h" +#include "clock.h" +#include "lttng-ust-uuid.h" +#include "lttng-tracer.h" +#include "../libringbuffer/frontend_types.h" + +#define LTTNG_COMPACT_EVENT_BITS 5 +#define LTTNG_COMPACT_TSC_BITS 27 + +/* + * Keep the natural field alignment for _each field_ within this structure if + * you ever add/remove a field from this header. Packed attribute is not used + * because gcc generates poor code on at least powerpc and mips. Don't ever + * let gcc add padding between the structure elements. + */ + +struct packet_header { + /* Trace packet header */ + uint32_t magic; /* + * Trace magic number. + * contains endianness information. + */ + uint8_t uuid[LTTNG_UST_UUID_LEN]; + uint32_t stream_id; + + struct { + /* Stream packet context */ + uint64_t timestamp_begin; /* Cycle count at subbuffer start */ + uint64_t timestamp_end; /* Cycle count at subbuffer end */ + uint64_t content_size; /* Size of data in subbuffer */ + uint64_t packet_size; /* Subbuffer size (include padding) */ + unsigned long events_discarded; /* + * Events lost in this subbuffer since + * the beginning of the trace. + * (may overflow) + */ + uint32_t cpu_id; /* CPU id associated with stream */ + uint8_t header_end; /* End of header */ + } ctx; +}; + + +static inline uint64_t lib_ring_buffer_clock_read(struct channel *chan) +{ + return trace_clock_read64(); +} + +static inline +size_t ctx_get_size(size_t offset, struct lttng_ctx *ctx) +{ + int i; + size_t orig_offset = offset; + + if (caa_likely(!ctx)) + return 0; + for (i = 0; i < ctx->nr_fields; i++) + offset += ctx->fields[i].get_size(offset); + return offset - orig_offset; +} + +static inline +void ctx_record(struct lttng_ust_lib_ring_buffer_ctx *bufctx, + struct lttng_channel *chan, + struct lttng_ctx *ctx) +{ + int i; + + if (caa_likely(!ctx)) + return; + for (i = 0; i < ctx->nr_fields; i++) + ctx->fields[i].record(&ctx->fields[i], bufctx, chan); +} + +/* + * record_header_size - Calculate the header size and padding necessary. + * @config: ring buffer instance configuration + * @chan: channel + * @offset: offset in the write buffer + * @pre_header_padding: padding to add before the header (output) + * @ctx: reservation context + * + * Returns the event header size (including padding). + * + * The payload must itself determine its own alignment from the biggest type it + * contains. + */ +static __inline__ +unsigned char record_header_size(const struct lttng_ust_lib_ring_buffer_config *config, + struct channel *chan, size_t offset, + size_t *pre_header_padding, + struct lttng_ust_lib_ring_buffer_ctx *ctx) +{ + struct lttng_channel *lttng_chan = channel_get_private(chan); + struct lttng_event *event = ctx->priv; + size_t orig_offset = offset; + size_t padding; + + switch (lttng_chan->header_type) { + case 1: /* compact */ + padding = lib_ring_buffer_align(offset, lttng_alignof(uint32_t)); + offset += padding; + if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTTNG_RFLAG_EXTENDED))) { + offset += sizeof(uint32_t); /* id and timestamp */ + } else { + /* Minimum space taken by LTTNG_COMPACT_EVENT_BITS id */ + offset += (LTTNG_COMPACT_EVENT_BITS + CHAR_BIT - 1) / CHAR_BIT; + /* Align extended struct on largest member */ + offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); + offset += sizeof(uint32_t); /* id */ + offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); + offset += sizeof(uint64_t); /* timestamp */ + } + break; + case 2: /* large */ + padding = lib_ring_buffer_align(offset, lttng_alignof(uint16_t)); + offset += padding; + offset += sizeof(uint16_t); + if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTTNG_RFLAG_EXTENDED))) { + offset += lib_ring_buffer_align(offset, lttng_alignof(uint32_t)); + offset += sizeof(uint32_t); /* timestamp */ + } else { + /* Align extended struct on largest member */ + offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); + offset += sizeof(uint32_t); /* id */ + offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); + offset += sizeof(uint64_t); /* timestamp */ + } + break; + default: + padding = 0; + WARN_ON_ONCE(1); + } + offset += ctx_get_size(offset, event->ctx); + offset += ctx_get_size(offset, lttng_chan->ctx); + + *pre_header_padding = padding; + return offset - orig_offset; +} + +#include "../libringbuffer/api.h" + +static +void lttng_write_event_header_slow(const struct lttng_ust_lib_ring_buffer_config *config, + struct lttng_ust_lib_ring_buffer_ctx *ctx, + uint32_t event_id); + +/* + * lttng_write_event_header + * + * Writes the event header to the offset (already aligned on 32-bits). + * + * @config: ring buffer instance configuration + * @ctx: reservation context + * @event_id: event ID + */ +static __inline__ +void lttng_write_event_header(const struct lttng_ust_lib_ring_buffer_config *config, + struct lttng_ust_lib_ring_buffer_ctx *ctx, + uint32_t event_id) +{ + struct lttng_channel *lttng_chan = channel_get_private(ctx->chan); + struct lttng_event *event = ctx->priv; + + if (caa_unlikely(ctx->rflags)) + goto slow_path; + + switch (lttng_chan->header_type) { + case 1: /* compact */ + { + uint32_t id_time = 0; + + bt_bitfield_write(&id_time, uint32_t, + 0, + LTTNG_COMPACT_EVENT_BITS, + event_id); + bt_bitfield_write(&id_time, uint32_t, + LTTNG_COMPACT_EVENT_BITS, + LTTNG_COMPACT_TSC_BITS, + ctx->tsc); + lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time)); + break; + } + case 2: /* large */ + { + uint32_t timestamp = (uint32_t) ctx->tsc; + uint16_t id = event_id; + + lib_ring_buffer_write(config, ctx, &id, sizeof(id)); + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint32_t)); + lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); + break; + } + default: + WARN_ON_ONCE(1); + } + + ctx_record(ctx, lttng_chan, lttng_chan->ctx); + ctx_record(ctx, lttng_chan, event->ctx); + lib_ring_buffer_align_ctx(ctx, ctx->largest_align); + + return; + +slow_path: + lttng_write_event_header_slow(config, ctx, event_id); +} + +static +void lttng_write_event_header_slow(const struct lttng_ust_lib_ring_buffer_config *config, + struct lttng_ust_lib_ring_buffer_ctx *ctx, + uint32_t event_id) +{ + struct lttng_channel *lttng_chan = channel_get_private(ctx->chan); + struct lttng_event *event = ctx->priv; + + switch (lttng_chan->header_type) { + case 1: /* compact */ + if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTTNG_RFLAG_EXTENDED))) { + uint32_t id_time = 0; + + bt_bitfield_write(&id_time, uint32_t, + 0, + LTTNG_COMPACT_EVENT_BITS, + event_id); + bt_bitfield_write(&id_time, uint32_t, + LTTNG_COMPACT_EVENT_BITS, + LTTNG_COMPACT_TSC_BITS, + ctx->tsc); + lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time)); + } else { + uint8_t id = 0; + uint64_t timestamp = ctx->tsc; + + bt_bitfield_write(&id, uint8_t, + 0, + LTTNG_COMPACT_EVENT_BITS, + 31); + lib_ring_buffer_write(config, ctx, &id, sizeof(id)); + /* Align extended struct on largest member */ + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t)); + lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id)); + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t)); + lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); + } + break; + case 2: /* large */ + { + if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTTNG_RFLAG_EXTENDED))) { + uint32_t timestamp = (uint32_t) ctx->tsc; + uint16_t id = event_id; + + lib_ring_buffer_write(config, ctx, &id, sizeof(id)); + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint32_t)); + lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); + } else { + uint16_t id = 65535; + uint64_t timestamp = ctx->tsc; + + lib_ring_buffer_write(config, ctx, &id, sizeof(id)); + /* Align extended struct on largest member */ + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t)); + lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id)); + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t)); + lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); + } + break; + } + default: + WARN_ON_ONCE(1); + } + ctx_record(ctx, lttng_chan, lttng_chan->ctx); + ctx_record(ctx, lttng_chan, event->ctx); + lib_ring_buffer_align_ctx(ctx, ctx->largest_align); +} + +static const struct lttng_ust_lib_ring_buffer_config client_config; + +static uint64_t client_ring_buffer_clock_read(struct channel *chan) +{ + return lib_ring_buffer_clock_read(chan); +} + +static +size_t client_record_header_size(const struct lttng_ust_lib_ring_buffer_config *config, + struct channel *chan, size_t offset, + size_t *pre_header_padding, + struct lttng_ust_lib_ring_buffer_ctx *ctx) +{ + return record_header_size(config, chan, offset, + pre_header_padding, ctx); +} + +/** + * client_packet_header_size - called on buffer-switch to a new sub-buffer + * + * Return header size without padding after the structure. Don't use packed + * structure because gcc generates inefficient code on some architectures + * (powerpc, mips..) + */ +static size_t client_packet_header_size(void) +{ + return offsetof(struct packet_header, ctx.header_end); +} + +static void client_buffer_begin(struct lttng_ust_lib_ring_buffer *buf, uint64_t tsc, + unsigned int subbuf_idx, + struct lttng_ust_shm_handle *handle) +{ + struct channel *chan = shmp(handle, buf->backend.chan); + struct packet_header *header = + (struct packet_header *) + lib_ring_buffer_offset_address(&buf->backend, + subbuf_idx * chan->backend.subbuf_size, + handle); + struct lttng_channel *lttng_chan = channel_get_private(chan); + + header->magic = CTF_MAGIC_NUMBER; + memcpy(header->uuid, lttng_chan->uuid, sizeof(lttng_chan->uuid)); + header->stream_id = lttng_chan->id; + header->ctx.timestamp_begin = tsc; + header->ctx.timestamp_end = 0; + header->ctx.content_size = ~0ULL; /* for debugging */ + header->ctx.packet_size = ~0ULL; + header->ctx.events_discarded = 0; + header->ctx.cpu_id = buf->backend.cpu; +} + +/* + * offset is assumed to never be 0 here : never deliver a completely empty + * subbuffer. data_size is between 1 and subbuf_size. + */ +static void client_buffer_end(struct lttng_ust_lib_ring_buffer *buf, uint64_t tsc, + unsigned int subbuf_idx, unsigned long data_size, + struct lttng_ust_shm_handle *handle) +{ + struct channel *chan = shmp(handle, buf->backend.chan); + struct packet_header *header = + (struct packet_header *) + lib_ring_buffer_offset_address(&buf->backend, + subbuf_idx * chan->backend.subbuf_size, + handle); + unsigned long records_lost = 0; + + header->ctx.timestamp_end = tsc; + header->ctx.content_size = + (uint64_t) data_size * CHAR_BIT; /* in bits */ + header->ctx.packet_size = + (uint64_t) PAGE_ALIGN(data_size) * CHAR_BIT; /* in bits */ + + records_lost += lib_ring_buffer_get_records_lost_full(&client_config, buf); + records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf); + records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf); + header->ctx.events_discarded = records_lost; +} + +static int client_buffer_create(struct lttng_ust_lib_ring_buffer *buf, void *priv, + int cpu, const char *name, struct lttng_ust_shm_handle *handle) +{ + return 0; +} + +static void client_buffer_finalize(struct lttng_ust_lib_ring_buffer *buf, void *priv, int cpu, struct lttng_ust_shm_handle *handle) +{ +} + +static const struct lttng_ust_lib_ring_buffer_config client_config = { + .cb.ring_buffer_clock_read = client_ring_buffer_clock_read, + .cb.record_header_size = client_record_header_size, + .cb.subbuffer_header_size = client_packet_header_size, + .cb.buffer_begin = client_buffer_begin, + .cb.buffer_end = client_buffer_end, + .cb.buffer_create = client_buffer_create, + .cb.buffer_finalize = client_buffer_finalize, + + .tsc_bits = LTTNG_COMPACT_TSC_BITS, + .alloc = RING_BUFFER_ALLOC_PER_CPU, + .sync = RING_BUFFER_SYNC_GLOBAL, + .mode = RING_BUFFER_MODE_TEMPLATE, + .backend = RING_BUFFER_PAGE, + .output = RING_BUFFER_MMAP, + .oops = RING_BUFFER_OOPS_CONSISTENCY, + .ipi = RING_BUFFER_NO_IPI_BARRIER, + .wakeup = RING_BUFFER_WAKEUP_BY_WRITER, + .client_type = LTTNG_CLIENT_TYPE, +}; + +const struct lttng_ust_lib_ring_buffer_client_cb *LTTNG_CLIENT_CALLBACKS = &client_config.cb; + +static +struct lttng_channel *_channel_create(const char *name, + void *buf_addr, + size_t subbuf_size, size_t num_subbuf, + unsigned int switch_timer_interval, + unsigned int read_timer_interval, + int **shm_fd, int **wait_fd, + uint64_t **memory_map_size, + struct lttng_channel *chan_priv_init) +{ + void *priv; + struct lttng_channel *lttng_chan = NULL; + struct lttng_ust_shm_handle *handle; + + handle = channel_create(&client_config, name, + &priv, __alignof__(*lttng_chan), sizeof(*lttng_chan), + chan_priv_init, + buf_addr, subbuf_size, num_subbuf, + switch_timer_interval, read_timer_interval, + shm_fd, wait_fd, memory_map_size); + if (!handle) + return NULL; + lttng_chan = priv; + lttng_chan->handle = handle; + lttng_chan->chan = shmp(lttng_chan->handle, lttng_chan->handle->chan); + return lttng_chan; +} + +static +void lttng_channel_destroy(struct lttng_channel *lttng_chan) +{ + channel_destroy(lttng_chan->chan, lttng_chan->handle, 0); +} + +static +struct lttng_ust_lib_ring_buffer *lttng_buffer_read_open(struct channel *chan, + struct lttng_ust_shm_handle *handle, + int **shm_fd, int **wait_fd, + uint64_t **memory_map_size) +{ + struct lttng_ust_lib_ring_buffer *buf; + int cpu; + + for_each_channel_cpu(cpu, chan) { + buf = channel_get_ring_buffer(&client_config, chan, + cpu, handle, shm_fd, wait_fd, + memory_map_size); + if (!lib_ring_buffer_open_read(buf, handle, 0)) + return buf; + } + return NULL; +} + +static +void lttng_buffer_read_close(struct lttng_ust_lib_ring_buffer *buf, + struct lttng_ust_shm_handle *handle) +{ + lib_ring_buffer_release_read(buf, handle, 0); +} + +static +int lttng_event_reserve(struct lttng_ust_lib_ring_buffer_ctx *ctx, + uint32_t event_id) +{ + struct lttng_channel *lttng_chan = channel_get_private(ctx->chan); + int ret, cpu; + + cpu = lib_ring_buffer_get_cpu(&client_config); + if (cpu < 0) + return -EPERM; + ctx->cpu = cpu; + + switch (lttng_chan->header_type) { + case 1: /* compact */ + if (event_id > 30) + ctx->rflags |= LTTNG_RFLAG_EXTENDED; + break; + case 2: /* large */ + if (event_id > 65534) + ctx->rflags |= LTTNG_RFLAG_EXTENDED; + break; + default: + WARN_ON_ONCE(1); + } + + ret = lib_ring_buffer_reserve(&client_config, ctx); + if (ret) + goto put; + lttng_write_event_header(&client_config, ctx, event_id); + return 0; +put: + lib_ring_buffer_put_cpu(&client_config); + return ret; +} + +static +void lttng_event_commit(struct lttng_ust_lib_ring_buffer_ctx *ctx) +{ + lib_ring_buffer_commit(&client_config, ctx); + lib_ring_buffer_put_cpu(&client_config); +} + +static +void lttng_event_write(struct lttng_ust_lib_ring_buffer_ctx *ctx, const void *src, + size_t len) +{ + lib_ring_buffer_write(&client_config, ctx, src, len); +} + +#if 0 +static +wait_queue_head_t *lttng_get_reader_wait_queue(struct channel *chan) +{ + return &chan->read_wait; +} + +static +wait_queue_head_t *lttng_get_hp_wait_queue(struct channel *chan) +{ + return &chan->hp_wait; +} +#endif //0 + +static +int lttng_is_finalized(struct channel *chan) +{ + return lib_ring_buffer_channel_is_finalized(chan); +} + +static +int lttng_is_disabled(struct channel *chan) +{ + return lib_ring_buffer_channel_is_disabled(chan); +} + +static +int lttng_flush_buffer(struct channel *chan, struct lttng_ust_shm_handle *handle) +{ + struct lttng_ust_lib_ring_buffer *buf; + int cpu; + + for_each_channel_cpu(cpu, chan) { + int *shm_fd, *wait_fd; + uint64_t *memory_map_size; + + buf = channel_get_ring_buffer(&client_config, chan, + cpu, handle, &shm_fd, &wait_fd, + &memory_map_size); + lib_ring_buffer_switch(&client_config, buf, + SWITCH_ACTIVE, handle); + } + return 0; +} + +static struct lttng_transport lttng_relay_transport = { + .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap", + .ops = { + .channel_create = _channel_create, + .channel_destroy = lttng_channel_destroy, + .buffer_read_open = lttng_buffer_read_open, + .buffer_read_close = lttng_buffer_read_close, + .event_reserve = lttng_event_reserve, + .event_commit = lttng_event_commit, + .event_write = lttng_event_write, + .packet_avail_size = NULL, /* Would be racy anyway */ + //.get_reader_wait_queue = lttng_get_reader_wait_queue, + //.get_hp_wait_queue = lttng_get_hp_wait_queue, + .is_finalized = lttng_is_finalized, + .is_disabled = lttng_is_disabled, + .flush_buffer = lttng_flush_buffer, + }, +}; + +void RING_BUFFER_MODE_TEMPLATE_INIT(void) +{ + DBG("LTT : ltt ring buffer client init\n"); + lttng_transport_register(<tng_relay_transport); +} + +void RING_BUFFER_MODE_TEMPLATE_EXIT(void) +{ + DBG("LTT : ltt ring buffer client exit\n"); + lttng_transport_unregister(<tng_relay_transport); +} diff --git a/liblttng-ust/lttng-ring-buffer-metadata-client.c b/liblttng-ust/lttng-ring-buffer-metadata-client.c new file mode 100644 index 00000000..126c0488 --- /dev/null +++ b/liblttng-ust/lttng-ring-buffer-metadata-client.c @@ -0,0 +1,34 @@ +/* + * lttng-ring-buffer-metadata-client.c + * + * LTTng lib ring buffer metadta client. + * + * Copyright (C) 2010-2012 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; only + * 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 _GNU_SOURCE +#include "lttng-tracer.h" + +#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD +#define RING_BUFFER_MODE_TEMPLATE_STRING "metadata" +#define RING_BUFFER_MODE_TEMPLATE_INIT \ + lttng_ring_buffer_metadata_client_init +#define RING_BUFFER_MODE_TEMPLATE_EXIT \ + lttng_ring_buffer_metadata_client_exit +#define LTTNG_CLIENT_TYPE LTTNG_CLIENT_METADATA +#define LTTNG_CLIENT_CALLBACKS lttng_client_callbacks_metadata +#include "lttng-ring-buffer-metadata-client.h" diff --git a/liblttng-ust/lttng-ring-buffer-metadata-client.h b/liblttng-ust/lttng-ring-buffer-metadata-client.h new file mode 100644 index 00000000..8bffe547 --- /dev/null +++ b/liblttng-ust/lttng-ring-buffer-metadata-client.h @@ -0,0 +1,342 @@ +/* + * lttng-ring-buffer-client.h + * + * LTTng lib ring buffer client template. + * + * Copyright (C) 2010-2012 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; only + * 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 + */ + +#include +#include +#include "lttng/bitfield.h" +#include "lttng-tracer.h" +#include "../libringbuffer/frontend_types.h" + +struct metadata_packet_header { + uint32_t magic; /* 0x75D11D57 */ + uint8_t uuid[LTTNG_UST_UUID_LEN]; /* Unique Universal Identifier */ + uint32_t checksum; /* 0 if unused */ + uint32_t content_size; /* in bits */ + uint32_t packet_size; /* in bits */ + uint8_t compression_scheme; /* 0 if unused */ + uint8_t encryption_scheme; /* 0 if unused */ + uint8_t checksum_scheme; /* 0 if unused */ + uint8_t major; /* CTF spec major version number */ + uint8_t minor; /* CTF spec minor version number */ + uint8_t header_end[0]; +}; + +struct metadata_record_header { + uint8_t header_end[0]; /* End of header */ +}; + +static const struct lttng_ust_lib_ring_buffer_config client_config; + +static inline uint64_t lib_ring_buffer_clock_read(struct channel *chan) +{ + return 0; +} + +static inline +unsigned char record_header_size(const struct lttng_ust_lib_ring_buffer_config *config, + struct channel *chan, size_t offset, + size_t *pre_header_padding, + struct lttng_ust_lib_ring_buffer_ctx *ctx) +{ + return 0; +} + +#include "../libringbuffer/api.h" + +static uint64_t client_ring_buffer_clock_read(struct channel *chan) +{ + return 0; +} + +static +size_t client_record_header_size(const struct lttng_ust_lib_ring_buffer_config *config, + struct channel *chan, size_t offset, + size_t *pre_header_padding, + struct lttng_ust_lib_ring_buffer_ctx *ctx) +{ + return 0; +} + +/** + * client_packet_header_size - called on buffer-switch to a new sub-buffer + * + * Return header size without padding after the structure. Don't use packed + * structure because gcc generates inefficient code on some architectures + * (powerpc, mips..) + */ +static size_t client_packet_header_size(void) +{ + return offsetof(struct metadata_packet_header, header_end); +} + +static void client_buffer_begin(struct lttng_ust_lib_ring_buffer *buf, uint64_t tsc, + unsigned int subbuf_idx, + struct lttng_ust_shm_handle *handle) +{ + struct channel *chan = shmp(handle, buf->backend.chan); + struct metadata_packet_header *header = + (struct metadata_packet_header *) + lib_ring_buffer_offset_address(&buf->backend, + subbuf_idx * chan->backend.subbuf_size, + handle); + struct lttng_channel *lttng_chan = channel_get_private(chan); + + header->magic = TSDL_MAGIC_NUMBER; + memcpy(header->uuid, lttng_chan->uuid, sizeof(lttng_chan->uuid)); + header->checksum = 0; /* 0 if unused */ + header->content_size = 0xFFFFFFFF; /* in bits, for debugging */ + header->packet_size = 0xFFFFFFFF; /* in bits, for debugging */ + header->compression_scheme = 0; /* 0 if unused */ + header->encryption_scheme = 0; /* 0 if unused */ + header->checksum_scheme = 0; /* 0 if unused */ + header->major = CTF_SPEC_MAJOR; + header->minor = CTF_SPEC_MINOR; + +} + +/* + * offset is assumed to never be 0 here : never deliver a completely empty + * subbuffer. data_size is between 1 and subbuf_size. + */ +static void client_buffer_end(struct lttng_ust_lib_ring_buffer *buf, uint64_t tsc, + unsigned int subbuf_idx, unsigned long data_size, + struct lttng_ust_shm_handle *handle) +{ + struct channel *chan = shmp(handle, buf->backend.chan); + struct metadata_packet_header *header = + (struct metadata_packet_header *) + lib_ring_buffer_offset_address(&buf->backend, + subbuf_idx * chan->backend.subbuf_size, + handle); + unsigned long records_lost = 0; + + header->content_size = data_size * CHAR_BIT; /* in bits */ + header->packet_size = PAGE_ALIGN(data_size) * CHAR_BIT; /* in bits */ + /* + * We do not care about the records lost count, because the metadata + * channel waits and retry. + */ + (void) lib_ring_buffer_get_records_lost_full(&client_config, buf); + records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf); + records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf); + WARN_ON_ONCE(records_lost != 0); +} + +static int client_buffer_create(struct lttng_ust_lib_ring_buffer *buf, void *priv, + int cpu, const char *name, + struct lttng_ust_shm_handle *handle) +{ + return 0; +} + +static void client_buffer_finalize(struct lttng_ust_lib_ring_buffer *buf, + void *priv, int cpu, + struct lttng_ust_shm_handle *handle) +{ +} + +static const struct lttng_ust_lib_ring_buffer_config client_config = { + .cb.ring_buffer_clock_read = client_ring_buffer_clock_read, + .cb.record_header_size = client_record_header_size, + .cb.subbuffer_header_size = client_packet_header_size, + .cb.buffer_begin = client_buffer_begin, + .cb.buffer_end = client_buffer_end, + .cb.buffer_create = client_buffer_create, + .cb.buffer_finalize = client_buffer_finalize, + + .tsc_bits = 0, + .alloc = RING_BUFFER_ALLOC_GLOBAL, + .sync = RING_BUFFER_SYNC_GLOBAL, + .mode = RING_BUFFER_MODE_TEMPLATE, + .backend = RING_BUFFER_PAGE, + .output = RING_BUFFER_MMAP, + .oops = RING_BUFFER_OOPS_CONSISTENCY, + .ipi = RING_BUFFER_NO_IPI_BARRIER, + .wakeup = RING_BUFFER_WAKEUP_BY_WRITER, + .client_type = LTTNG_CLIENT_TYPE, +}; + +const struct lttng_ust_lib_ring_buffer_client_cb *LTTNG_CLIENT_CALLBACKS = &client_config.cb; + +static +struct lttng_channel *_channel_create(const char *name, + void *buf_addr, + size_t subbuf_size, size_t num_subbuf, + unsigned int switch_timer_interval, + unsigned int read_timer_interval, + int **shm_fd, int **wait_fd, + uint64_t **memory_map_size, + struct lttng_channel *chan_priv_init) +{ + void *priv; + struct lttng_channel *lttng_chan = NULL; + struct lttng_ust_shm_handle *handle; + + handle = channel_create(&client_config, name, + &priv, __alignof__(*lttng_chan), sizeof(*lttng_chan), + chan_priv_init, + buf_addr, subbuf_size, num_subbuf, + switch_timer_interval, read_timer_interval, + shm_fd, wait_fd, memory_map_size); + if (!handle) + return NULL; + lttng_chan = priv; + lttng_chan->handle = handle; + lttng_chan->chan = shmp(lttng_chan->handle, lttng_chan->handle->chan); + return lttng_chan; +} + +static +void lttng_channel_destroy(struct lttng_channel *lttng_chan) +{ + channel_destroy(lttng_chan->chan, lttng_chan->handle, 0); +} + +static +struct lttng_ust_lib_ring_buffer *lttng_buffer_read_open(struct channel *chan, + struct lttng_ust_shm_handle *handle, + int **shm_fd, int **wait_fd, + uint64_t **memory_map_size) +{ + struct lttng_ust_lib_ring_buffer *buf; + + buf = channel_get_ring_buffer(&client_config, chan, + 0, handle, shm_fd, wait_fd, memory_map_size); + if (!lib_ring_buffer_open_read(buf, handle, 0)) + return buf; + return NULL; +} + +static +void lttng_buffer_read_close(struct lttng_ust_lib_ring_buffer *buf, + struct lttng_ust_shm_handle *handle) +{ + lib_ring_buffer_release_read(buf, handle, 0); +} + +static +int lttng_event_reserve(struct lttng_ust_lib_ring_buffer_ctx *ctx, uint32_t event_id) +{ + return lib_ring_buffer_reserve(&client_config, ctx); +} + +static +void lttng_event_commit(struct lttng_ust_lib_ring_buffer_ctx *ctx) +{ + lib_ring_buffer_commit(&client_config, ctx); +} + +static +void lttng_event_write(struct lttng_ust_lib_ring_buffer_ctx *ctx, const void *src, + size_t len) +{ + lib_ring_buffer_write(&client_config, ctx, src, len); +} + +static +size_t lttng_packet_avail_size(struct channel *chan, struct lttng_ust_shm_handle *handle) + +{ + unsigned long o_begin; + struct lttng_ust_lib_ring_buffer *buf; + + buf = shmp(handle, chan->backend.buf[0].shmp); /* Only for global buffer ! */ + o_begin = v_read(&client_config, &buf->offset); + if (subbuf_offset(o_begin, chan) != 0) { + return chan->backend.subbuf_size - subbuf_offset(o_begin, chan); + } else { + return chan->backend.subbuf_size - subbuf_offset(o_begin, chan) + - sizeof(struct metadata_packet_header); + } +} + +#if 0 +static +wait_queue_head_t *lttng_get_reader_wait_queue(struct channel *chan) +{ + return &chan->read_wait; +} + +static +wait_queue_head_t *lttng_get_hp_wait_queue(struct channel *chan) +{ + return &chan->hp_wait; +} +#endif //0 + +static +int lttng_is_finalized(struct channel *chan) +{ + return lib_ring_buffer_channel_is_finalized(chan); +} + +static +int lttng_is_disabled(struct channel *chan) +{ + return lib_ring_buffer_channel_is_disabled(chan); +} + +static +int lttng_flush_buffer(struct channel *chan, struct lttng_ust_shm_handle *handle) +{ + struct lttng_ust_lib_ring_buffer *buf; + int *shm_fd, *wait_fd; + uint64_t *memory_map_size; + + buf = channel_get_ring_buffer(&client_config, chan, + 0, handle, &shm_fd, &wait_fd, + &memory_map_size); + lib_ring_buffer_switch(&client_config, buf, + SWITCH_ACTIVE, handle); + return 0; +} + +static struct lttng_transport lttng_relay_transport = { + .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap", + .ops = { + .channel_create = _channel_create, + .channel_destroy = lttng_channel_destroy, + .buffer_read_open = lttng_buffer_read_open, + .buffer_read_close = lttng_buffer_read_close, + .event_reserve = lttng_event_reserve, + .event_commit = lttng_event_commit, + .event_write = lttng_event_write, + .packet_avail_size = lttng_packet_avail_size, + //.get_reader_wait_queue = lttng_get_reader_wait_queue, + //.get_hp_wait_queue = lttng_get_hp_wait_queue, + .is_finalized = lttng_is_finalized, + .is_disabled = lttng_is_disabled, + .flush_buffer = lttng_flush_buffer, + }, +}; + +void RING_BUFFER_MODE_TEMPLATE_INIT(void) +{ + DBG("LTT : ltt ring buffer client init\n"); + lttng_transport_register(<tng_relay_transport); +} + +void RING_BUFFER_MODE_TEMPLATE_EXIT(void) +{ + DBG("LTT : ltt ring buffer client exit\n"); + lttng_transport_unregister(<tng_relay_transport); +} diff --git a/liblttng-ust/lttng-tracer-core.h b/liblttng-ust/lttng-tracer-core.h new file mode 100644 index 00000000..09289c33 --- /dev/null +++ b/liblttng-ust/lttng-tracer-core.h @@ -0,0 +1,44 @@ +#ifndef _LTTNG_TRACER_CORE_H +#define _LTTNG_TRACER_CORE_H + +/* + * Copyright (C) 2005-2011 Mathieu Desnoyers + * + * This contains the core definitions for the Linux Trace Toolkit. + * + * 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct lttng_session; +struct lttng_channel; +struct lttng_event; + +void ust_lock(void); +void ust_unlock(void); + +void lttng_fixup_event_tls(void); +void lttng_fixup_vtid_tls(void); +void lttng_fixup_procname_tls(void); + +#endif /* _LTTNG_TRACER_CORE_H */ diff --git a/liblttng-ust/lttng-tracer.h b/liblttng-ust/lttng-tracer.h new file mode 100644 index 00000000..1bc97bc3 --- /dev/null +++ b/liblttng-ust/lttng-tracer.h @@ -0,0 +1,49 @@ +#ifndef _LTTNG_TRACER_H +#define _LTTNG_TRACER_H + +/* + * Copyright (C) 2005-2011 Mathieu Desnoyers + * + * This contains the definitions for the Linux Trace Toolkit tracer. + * + * Ported to userspace by 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; 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 + */ + +#include +#include +#include +#include "lttng-tracer-core.h" +#include "compat.h" + +/* Tracer properties */ +#define CTF_MAGIC_NUMBER 0xC1FC1FC1 +#define TSDL_MAGIC_NUMBER 0x75D11D57 + +/* CTF specification version followed */ +#define CTF_SPEC_MAJOR 1 +#define CTF_SPEC_MINOR 8 + +/* + * Number of milliseconds to retry before failing metadata writes on buffer full + * condition. (10 seconds) + */ +#define LTTNG_METADATA_TIMEOUT_MSEC 10000 + +#define LTTNG_RFLAG_EXTENDED RING_BUFFER_RFLAG_END +#define LTTNG_RFLAG_END (LTTNG_RFLAG_EXTENDED << 1) + +#endif /* _LTTNG_TRACER_H */ diff --git a/liblttng-ust/lttng-ust-abi.c b/liblttng-ust/lttng-ust-abi.c index 56d588a8..9b0143cd 100644 --- a/liblttng-ust/lttng-ust-abi.c +++ b/liblttng-ust/lttng-ust-abi.c @@ -47,7 +47,7 @@ #include "tracepoint-internal.h" #include #include -#include "ltt-tracer.h" +#include "lttng-tracer.h" static int lttng_ust_abi_close_in_progress; @@ -262,10 +262,10 @@ int lttng_abi_create_root_handle(void) static int lttng_abi_create_session(void *owner) { - struct ltt_session *session; + struct lttng_session *session; int session_objd, ret; - session = ltt_session_create(); + session = lttng_session_create(); if (!session) return -ENOMEM; session_objd = objd_alloc(session, <tng_session_ops, owner); @@ -277,7 +277,7 @@ int lttng_abi_create_session(void *owner) return session_objd; objd_error: - ltt_session_destroy(session); + lttng_session_destroy(session); return ret; } @@ -294,7 +294,7 @@ long lttng_abi_tracer_version(int objd, static long lttng_abi_add_context(int objd, struct lttng_ust_context *context_param, - struct lttng_ctx **ctx, struct ltt_session *session) + struct lttng_ctx **ctx, struct lttng_session *session) { if (session->been_active) return -EPERM; @@ -370,21 +370,21 @@ static const struct lttng_ust_objd_ops lttng_ops = { static void lttng_metadata_create_events(int channel_objd) { - struct ltt_channel *channel = objd_private(channel_objd); + struct lttng_channel *channel = objd_private(channel_objd); static struct lttng_ust_event metadata_params = { .instrumentation = LTTNG_UST_TRACEPOINT, .name = "lttng_ust:metadata", .loglevel_type = LTTNG_UST_LOGLEVEL_ALL, .loglevel = TRACE_DEFAULT, }; - struct ltt_event *event; + struct lttng_event *event; int ret; /* * We tolerate no failure path after event creation. It will stay * invariant for the rest of the session. */ - ret = ltt_event_create(channel, &metadata_params, &event); + ret = lttng_event_create(channel, &metadata_params, &event); if (ret < 0) { goto create_error; } @@ -401,13 +401,13 @@ int lttng_abi_create_channel(int session_objd, union ust_args *uargs, void *owner) { - struct ltt_session *session = objd_private(session_objd); + struct lttng_session *session = objd_private(session_objd); const struct lttng_ust_objd_ops *ops; const char *transport_name; - struct ltt_channel *chan; + struct lttng_channel *chan; int chan_objd; int ret = 0; - struct ltt_channel chan_priv_init; + struct lttng_channel chan_priv_init; switch (channel_type) { case PER_CPU_CHANNEL: @@ -443,7 +443,7 @@ int lttng_abi_create_channel(int session_objd, * We tolerate no failure path after channel creation. It will stay * invariant for the rest of the session. */ - chan = ltt_channel_create(session, transport_name, NULL, + chan = lttng_channel_create(session, transport_name, NULL, chan_param->subbuf_size, chan_param->num_subbuf, chan_param->switch_timer_interval, @@ -503,7 +503,7 @@ static long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg, union ust_args *uargs, void *owner) { - struct ltt_session *session = objd_private(objd); + struct lttng_session *session = objd_private(objd); switch (cmd) { case LTTNG_UST_CHANNEL: @@ -512,10 +512,10 @@ long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg, PER_CPU_CHANNEL, uargs, owner); case LTTNG_UST_SESSION_START: case LTTNG_UST_ENABLE: - return ltt_session_enable(session); + return lttng_session_enable(session); case LTTNG_UST_SESSION_STOP: case LTTNG_UST_DISABLE: - return ltt_session_disable(session); + return lttng_session_disable(session); case LTTNG_UST_METADATA: return lttng_abi_create_channel(objd, (struct lttng_ust_channel *) arg, @@ -536,10 +536,10 @@ long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg, static int lttng_release_session(int objd) { - struct ltt_session *session = objd_private(objd); + struct lttng_session *session = objd_private(objd); if (session) { - ltt_session_destroy(session); + lttng_session_destroy(session); return 0; } else { return -EINVAL; @@ -596,7 +596,7 @@ int lttng_abi_tracepoint_list(void *owner) objd_set_private(list_objd, list); /* populate list by walking on all registered probes. */ - ret = ltt_probes_get_event_list(list); + ret = lttng_probes_get_event_list(list); if (ret) { goto list_error; } @@ -621,7 +621,7 @@ int lttng_release_tracepoint_list(int objd) struct lttng_ust_tracepoint_list *list = objd_private(objd); if (list) { - ltt_probes_prune_event_list(list); + lttng_probes_prune_event_list(list); free(list); return 0; } else { @@ -678,7 +678,7 @@ int lttng_abi_tracepoint_field_list(void *owner) objd_set_private(list_objd, list); /* populate list by walking on all registered probes. */ - ret = ltt_probes_get_field_list(list); + ret = lttng_probes_get_field_list(list); if (ret) { goto list_error; } @@ -703,7 +703,7 @@ int lttng_release_tracepoint_field_list(int objd) struct lttng_ust_field_list *list = objd_private(objd); if (list) { - ltt_probes_prune_field_list(list); + lttng_probes_prune_field_list(list); free(list); return 0; } else { @@ -718,14 +718,14 @@ static const struct lttng_ust_objd_ops lttng_tracepoint_field_list_ops = { struct stream_priv_data { struct lttng_ust_lib_ring_buffer *buf; - struct ltt_channel *ltt_chan; + struct lttng_channel *lttng_chan; }; static int lttng_abi_open_stream(int channel_objd, struct lttng_ust_stream *info, union ust_args *uargs, void *owner) { - struct ltt_channel *channel = objd_private(channel_objd); + struct lttng_channel *channel = objd_private(channel_objd); struct lttng_ust_lib_ring_buffer *buf; struct stream_priv_data *priv; int stream_objd, ret; @@ -743,7 +743,7 @@ int lttng_abi_open_stream(int channel_objd, struct lttng_ust_stream *info, goto alloc_error; } priv->buf = buf; - priv->ltt_chan = channel; + priv->lttng_chan = channel; stream_objd = objd_alloc(priv, &lib_ring_buffer_objd_ops, owner); if (stream_objd < 0) { ret = stream_objd; @@ -765,8 +765,8 @@ int lttng_abi_create_event(int channel_objd, struct lttng_ust_event *event_param, void *owner) { - struct ltt_channel *channel = objd_private(channel_objd); - struct ltt_event *event; + struct lttng_channel *channel = objd_private(channel_objd); + struct lttng_event *event; int event_objd, ret; event_param->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; @@ -779,7 +779,7 @@ int lttng_abi_create_event(int channel_objd, * We tolerate no failure path after event creation. It will stay * invariant for the rest of the session. */ - ret = ltt_event_create(channel, event_param, &event); + ret = lttng_event_create(channel, event_param, &event); if (ret < 0) { goto event_error; } @@ -804,7 +804,7 @@ int lttng_abi_create_wildcard(int channel_objd, struct lttng_ust_event *event_param, void *owner) { - struct ltt_channel *channel = objd_private(channel_objd); + struct lttng_channel *channel = objd_private(channel_objd); struct session_wildcard *wildcard; int wildcard_objd, ret; @@ -818,7 +818,7 @@ int lttng_abi_create_wildcard(int channel_objd, * We tolerate no failure path after wildcard creation. It will * stay invariant for the rest of the session. */ - ret = ltt_wildcard_create(channel, event_param, &wildcard); + ret = lttng_wildcard_create(channel, event_param, &wildcard); if (ret < 0) { goto wildcard_error; } @@ -866,7 +866,7 @@ static long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg, union ust_args *uargs, void *owner) { - struct ltt_channel *channel = objd_private(objd); + struct lttng_channel *channel = objd_private(objd); switch (cmd) { case LTTNG_UST_STREAM: @@ -895,9 +895,9 @@ long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg, (struct lttng_ust_context *) arg, &channel->ctx, channel->session); case LTTNG_UST_ENABLE: - return ltt_channel_enable(channel); + return lttng_channel_enable(channel); case LTTNG_UST_DISABLE: - return ltt_channel_disable(channel); + return lttng_channel_disable(channel); case LTTNG_UST_FLUSH_BUFFER: return channel->ops->flush_buffer(channel->chan, channel->handle); default: @@ -924,7 +924,7 @@ static long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg, union ust_args *uargs, void *owner) { - struct ltt_channel *channel = objd_private(objd); + struct lttng_channel *channel = objd_private(objd); switch (cmd) { case LTTNG_UST_STREAM: @@ -951,7 +951,7 @@ long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg, */ unsigned int lttng_channel_poll(struct file *file, poll_table *wait) { - struct ltt_channel *channel = file->private_data; + struct lttng_channel *channel = file->private_data; unsigned int mask = 0; if (file->f_mode & FMODE_READ) { @@ -975,7 +975,7 @@ unsigned int lttng_channel_poll(struct file *file, poll_table *wait) static int lttng_channel_release(int objd) { - struct ltt_channel *channel = objd_private(objd); + struct lttng_channel *channel = objd_private(objd); if (channel) return lttng_ust_objd_unref(channel->session->objd); @@ -1020,11 +1020,11 @@ int lttng_rb_release(int objd) { struct stream_priv_data *priv = objd_private(objd); struct lttng_ust_lib_ring_buffer *buf; - struct ltt_channel *channel; + struct lttng_channel *channel; if (priv) { buf = priv->buf; - channel = priv->ltt_chan; + channel = priv->lttng_chan; free(priv); /* * If we are at ABI exit, we don't want to close the @@ -1075,7 +1075,7 @@ static long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg, union ust_args *uargs, void *owner) { - struct ltt_event *event = objd_private(objd); + struct lttng_event *event = objd_private(objd); switch (cmd) { case LTTNG_UST_CONTEXT: @@ -1083,9 +1083,9 @@ long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg, (struct lttng_ust_context *) arg, &event->ctx, event->chan->session); case LTTNG_UST_ENABLE: - return ltt_event_enable(event); + return lttng_event_enable(event); case LTTNG_UST_DISABLE: - return ltt_event_disable(event); + return lttng_event_disable(event); case LTTNG_UST_FILTER: { int ret; @@ -1104,7 +1104,7 @@ long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg, static int lttng_event_release(int objd) { - struct ltt_event *event = objd_private(objd); + struct lttng_event *event = objd_private(objd); if (event) return lttng_ust_objd_unref(event->chan->objd); @@ -1152,9 +1152,9 @@ long lttng_wildcard_cmd(int objd, unsigned int cmd, unsigned long arg, &wildcard->ctx, wildcard->chan->session); #endif case LTTNG_UST_ENABLE: - return ltt_wildcard_enable(wildcard); + return lttng_wildcard_enable(wildcard); case LTTNG_UST_DISABLE: - return ltt_wildcard_disable(wildcard); + return lttng_wildcard_disable(wildcard); case LTTNG_UST_FILTER: { int ret; diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index 58461462..98483cb8 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -46,7 +46,7 @@ #include #include #include "tracepoint-internal.h" -#include "ltt-tracer-core.h" +#include "lttng-tracer-core.h" #include "compat.h" #include "../libringbuffer/tlsfixup.h" @@ -131,12 +131,12 @@ struct sock_info local_apps = { static int wait_poll_fallback; -extern void ltt_ring_buffer_client_overwrite_init(void); -extern void ltt_ring_buffer_client_discard_init(void); -extern void ltt_ring_buffer_metadata_client_init(void); -extern void ltt_ring_buffer_client_overwrite_exit(void); -extern void ltt_ring_buffer_client_discard_exit(void); -extern void ltt_ring_buffer_metadata_client_exit(void); +extern void lttng_ring_buffer_client_overwrite_init(void); +extern void lttng_ring_buffer_client_discard_init(void); +extern void lttng_ring_buffer_metadata_client_init(void); +extern void lttng_ring_buffer_client_overwrite_exit(void); +extern void lttng_ring_buffer_client_discard_exit(void); +extern void lttng_ring_buffer_metadata_client_exit(void); /* * Force a read (imply TLS fixup for dlopen) of TLS variables. @@ -882,7 +882,7 @@ restart: len = ustcomm_recv_unix_sock(sock, &lum, sizeof(lum)); switch (len) { case 0: /* orderly shutdown */ - DBG("%s ltt-sessiond has performed an orderly shutdown", sock_info->name); + DBG("%s lttng-sessiond has performed an orderly shutdown", sock_info->name); ust_lock(); /* * Either sessiond has shutdown or refused us by closing the socket. @@ -1003,9 +1003,9 @@ void __attribute__((constructor)) lttng_ust_init(void) */ init_usterr(); init_tracepoint(); - ltt_ring_buffer_metadata_client_init(); - ltt_ring_buffer_client_overwrite_init(); - ltt_ring_buffer_client_discard_init(); + lttng_ring_buffer_metadata_client_init(); + lttng_ring_buffer_client_overwrite_init(); + lttng_ring_buffer_client_discard_init(); timeout_mode = get_timeout(&constructor_timeout); @@ -1069,7 +1069,7 @@ void __attribute__((constructor)) lttng_ust_init(void) &constructor_timeout); } while (ret < 0 && errno == EINTR); if (ret < 0 && errno == ETIMEDOUT) { - ERR("Timed out waiting for ltt-sessiond"); + ERR("Timed out waiting for lttng-sessiond"); } else { assert(!ret); } @@ -1101,9 +1101,9 @@ void lttng_ust_cleanup(int exiting) */ lttng_ust_abi_exit(); lttng_ust_events_exit(); - ltt_ring_buffer_client_discard_exit(); - ltt_ring_buffer_client_overwrite_exit(); - ltt_ring_buffer_metadata_client_exit(); + lttng_ring_buffer_client_discard_exit(); + lttng_ring_buffer_client_overwrite_exit(); + lttng_ring_buffer_metadata_client_exit(); exit_tracepoint(); if (!exiting) { /* Reinitialize values for fork */ diff --git a/liblttng-ust/tracepoint.c b/liblttng-ust/tracepoint.c index 85b14d2c..c803f8af 100644 --- a/liblttng-ust/tracepoint.c +++ b/liblttng-ust/tracepoint.c @@ -38,7 +38,7 @@ #include #include "tracepoint-internal.h" -#include "ltt-tracer-core.h" +#include "lttng-tracer-core.h" #include "jhash.h" #include "error.h" diff --git a/liblttng-ust/ust-core.c b/liblttng-ust/ust-core.c index 7c17a766..f9c00ff0 100644 --- a/liblttng-ust/ust-core.c +++ b/liblttng-ust/ust-core.c @@ -22,7 +22,7 @@ #include #include -static CDS_LIST_HEAD(ltt_transport_list); +static CDS_LIST_HEAD(lttng_transport_list); void init_usterr(void) { @@ -37,11 +37,11 @@ void init_usterr(void) } } -struct ltt_transport *ltt_transport_find(const char *name) +struct lttng_transport *lttng_transport_find(const char *name) { - struct ltt_transport *transport; + struct lttng_transport *transport; - cds_list_for_each_entry(transport, <t_transport_list, node) { + cds_list_for_each_entry(transport, <tng_transport_list, node) { if (!strcmp(transport->name, name)) return transport; } @@ -49,23 +49,23 @@ struct ltt_transport *ltt_transport_find(const char *name) } /** - * ltt_transport_register - LTT transport registration + * lttng_transport_register - LTT transport registration * @transport: transport structure * * Registers a transport which can be used as output to extract the data out of * LTTng. Called with ust_lock held. */ -void ltt_transport_register(struct ltt_transport *transport) +void lttng_transport_register(struct lttng_transport *transport) { - cds_list_add_tail(&transport->node, <t_transport_list); + cds_list_add_tail(&transport->node, <tng_transport_list); } /** - * ltt_transport_unregister - LTT transport unregistration + * lttng_transport_unregister - LTT transport unregistration * @transport: transport structure * Called with ust_lock held. */ -void ltt_transport_unregister(struct ltt_transport *transport) +void lttng_transport_unregister(struct lttng_transport *transport) { cds_list_del(&transport->node); }