#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;
/*
/* 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,
};
struct lttng_basic_type {
- enum abstract_types atype;
+ enum lttng_abstract_types atype;
union {
union _lttng_basic_type basic;
} u;
#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 {
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;
* 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 */
};
struct ust_pending_probe;
-struct ltt_event;
+struct lttng_event;
struct lttng_ust_filter_bytecode_node {
struct cds_list_head node;
};
/*
- * 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;
* 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,
* 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
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;
* 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 */
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,
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,
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,
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 */
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; \
{
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);
}
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);
-#ifndef _LTTNG_TRACER_H
-#define _LTTNG_TRACER_H
+#ifndef _LTTNG_UST_TRACER_H
+#define _LTTNG_UST_TRACER_H
/*
* Copyright (C) 2005-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
#define lttng_is_signed_type(type) (((type)(-1)) < 0)
-#endif /* _LTTNG_TRACER_CORE_H */
+#endif /* _LTTNG_UST_TRACER_H */
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 = \
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 \
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 =
+++ /dev/null
-/*
- * lttng-context.c
- *
- * LTTng UST trace/channel/event context management.
- *
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * 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 <lttng/ust-events.h>
-#include <lttng/ust-tracer.h>
-#include <helper.h>
-#include <string.h>
-#include <assert.h>
-
-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);
-}
+++ /dev/null
-/*
- * ltt-events.c
- *
- * Holds LTTng per-session event registry.
- *
- * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * 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 <stdio.h>
-#include <urcu/list.h>
-#include <urcu/hlist.h>
-#include <pthread.h>
-#include <errno.h>
-#include <sys/shm.h>
-#include <sys/ipc.h>
-#include <stdint.h>
-#include <stddef.h>
-#include <inttypes.h>
-#include <time.h>
-#include <lttng/ust-endian.h>
-#include "clock.h"
-
-#include <urcu-bp.h>
-#include <urcu/compiler.h>
-#include <urcu/uatomic.h>
-#include <urcu/arch.h>
-
-#include <lttng/tracepoint.h>
-#include <lttng/ust-events.h>
-
-#include <usterr-signal-safe.h>
-#include <helper.h>
-#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 <id> {\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 <id> {\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);
-}
+++ /dev/null
-/*
- * ltt-probes.c
- *
- * Holds LTTng probes registry.
- *
- * Copyright 2010-2012 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * 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 <string.h>
-#include <errno.h>
-#include <urcu/list.h>
-#include <urcu/hlist.h>
-#include <lttng/ust-events.h>
-#include <lttng/tracepoint.h>
-#include "tracepoint-internal.h"
-#include <assert.h>
-#include <helper.h>
-#include <ctype.h>
-
-#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);
-}
-
+++ /dev/null
-/*
- * ltt-ring-buffer-client-discard.c
- *
- * LTTng lib ring buffer client (discard mode).
- *
- * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * 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"
+++ /dev/null
-/*
- * ltt-ring-buffer-client-overwrite.c
- *
- * LTTng lib ring buffer client (overwrite mode).
- *
- * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * 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"
+++ /dev/null
-/*
- * ltt-ring-buffer-client.h
- *
- * LTTng lib ring buffer client template.
- *
- * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * 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 <stdint.h>
-#include <lttng/ust-events.h>
-#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);
-}
+++ /dev/null
-/*
- * ltt-ring-buffer-metadata-client.c
- *
- * LTTng lib ring buffer metadta client.
- *
- * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * 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"
+++ /dev/null
-/*
- * ltt-ring-buffer-client.h
- *
- * LTTng lib ring buffer client template.
- *
- * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * 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 <stdint.h>
-#include <lttng/ust-events.h>
-#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);
-}
+++ /dev/null
-#ifndef _LTT_TRACER_CORE_H
-#define _LTT_TRACER_CORE_H
-
-/*
- * Copyright (C) 2005-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * 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 <stdint.h>
-#include <stddef.h>
-#include <urcu/arch.h>
-#include <urcu/list.h>
-#include <lttng/ust-tracer.h>
-#include <lttng/bug.h>
-#include <lttng/ringbuffer-config.h>
-#include <usterr-signal-safe.h>
-
-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 */
+++ /dev/null
-#ifndef _LTT_TRACER_H
-#define _LTT_TRACER_H
-
-/*
- * Copyright (C) 2005-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * 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 <stdarg.h>
-#include <stdint.h>
-#include <lttng/ust-events.h>
-#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 */
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;
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;
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;
#include <lttng/ust-tracer.h>
#include <lttng/ringbuffer-config.h>
#include <lttng/ust-tid.h>
-#include "ltt-tracer-core.h"
+#include "lttng-tracer-core.h"
/*
* We cache the result to ensure we don't trigger a system call for
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();
--- /dev/null
+/*
+ * lttng-context.c
+ *
+ * LTTng UST trace/channel/event context management.
+ *
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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 <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <helper.h>
+#include <string.h>
+#include <assert.h>
+
+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);
+}
--- /dev/null
+/*
+ * lttng-events.c
+ *
+ * Holds LTTng per-session event registry.
+ *
+ * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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 <stdio.h>
+#include <urcu/list.h>
+#include <urcu/hlist.h>
+#include <pthread.h>
+#include <errno.h>
+#include <sys/shm.h>
+#include <sys/ipc.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <time.h>
+#include <lttng/ust-endian.h>
+#include "clock.h"
+
+#include <urcu-bp.h>
+#include <urcu/compiler.h>
+#include <urcu/uatomic.h>
+#include <urcu/arch.h>
+
+#include <lttng/tracepoint.h>
+#include <lttng/ust-events.h>
+
+#include <usterr-signal-safe.h>
+#include <helper.h>
+#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 <id> {\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 <id> {\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);
+}
}
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,
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;
* 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;
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;
}
}
-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;
*/
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;
* 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);
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;
}
}
-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;
--- /dev/null
+/*
+ * lttng-probes.c
+ *
+ * Holds LTTng probes registry.
+ *
+ * Copyright 2010-2012 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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 <string.h>
+#include <errno.h>
+#include <urcu/list.h>
+#include <urcu/hlist.h>
+#include <lttng/ust-events.h>
+#include <lttng/tracepoint.h>
+#include "tracepoint-internal.h"
+#include <assert.h>
+#include <helper.h>
+#include <ctype.h>
+
+#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);
+}
+
--- /dev/null
+/*
+ * lttng-ring-buffer-client-discard.c
+ *
+ * LTTng lib ring buffer client (discard mode).
+ *
+ * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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"
--- /dev/null
+/*
+ * lttng-ring-buffer-client-overwrite.c
+ *
+ * LTTng lib ring buffer client (overwrite mode).
+ *
+ * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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"
--- /dev/null
+/*
+ * lttng-ring-buffer-client.h
+ *
+ * LTTng lib ring buffer client template.
+ *
+ * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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 <stdint.h>
+#include <lttng/ust-events.h>
+#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);
+}
--- /dev/null
+/*
+ * lttng-ring-buffer-metadata-client.c
+ *
+ * LTTng lib ring buffer metadta client.
+ *
+ * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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"
--- /dev/null
+/*
+ * lttng-ring-buffer-client.h
+ *
+ * LTTng lib ring buffer client template.
+ *
+ * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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 <stdint.h>
+#include <lttng/ust-events.h>
+#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);
+}
--- /dev/null
+#ifndef _LTTNG_TRACER_CORE_H
+#define _LTTNG_TRACER_CORE_H
+
+/*
+ * Copyright (C) 2005-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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 <stdint.h>
+#include <stddef.h>
+#include <urcu/arch.h>
+#include <urcu/list.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/bug.h>
+#include <lttng/ringbuffer-config.h>
+#include <usterr-signal-safe.h>
+
+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 */
--- /dev/null
+#ifndef _LTTNG_TRACER_H
+#define _LTTNG_TRACER_H
+
+/*
+ * Copyright (C) 2005-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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 <stdarg.h>
+#include <stdint.h>
+#include <lttng/ust-events.h>
+#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 */
#include "tracepoint-internal.h"
#include <usterr-signal-safe.h>
#include <helper.h>
-#include "ltt-tracer.h"
+#include "lttng-tracer.h"
static int lttng_ust_abi_close_in_progress;
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);
return session_objd;
objd_error:
- ltt_session_destroy(session);
+ lttng_session_destroy(session);
return ret;
}
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;
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;
}
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:
* 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,
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:
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,
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;
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;
}
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 {
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;
}
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 {
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;
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;
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';
* 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;
}
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;
* 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;
}
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:
(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:
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:
*/
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) {
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);
{
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
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:
(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;
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);
&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;
#include <usterr-signal-safe.h>
#include <helper.h>
#include "tracepoint-internal.h"
-#include "ltt-tracer-core.h"
+#include "lttng-tracer-core.h"
#include "compat.h"
#include "../libringbuffer/tlsfixup.h"
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.
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.
*/
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);
&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);
}
*/
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 */
#include <helper.h>
#include "tracepoint-internal.h"
-#include "ltt-tracer-core.h"
+#include "lttng-tracer-core.h"
#include "jhash.h"
#include "error.h"
#include <lttng/ust-events.h>
#include <usterr-signal-safe.h>
-static CDS_LIST_HEAD(ltt_transport_list);
+static CDS_LIST_HEAD(lttng_transport_list);
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;
}
}
/**
- * 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);
}