--- /dev/null
+/*
+ * ltt-events.c
+ *
+ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Holds LTTng per-session event registry.
+ */
+
+#include <linux/module.h>
+#include "ltt-events.h"
+
+static LIST_HEAD(sessions);
+static DEFINE_MUTEX(sessions_mutex);
+static struct kmem_cache *event_cache;
+
+struct ltt_session *ltt_session_create(char *name)
+{
+ struct ltt_session *session;
+
+ mutex_lock(&sessions_mutex);
+ list_for_each_entry(session, &sessions, list)
+ if (!strcmp(session->name, name))
+ goto exist;
+ session = kmalloc(sizeof(struct ltt_session) + strlen(name) + 1);
+ if (!session)
+ return NULL;
+ strcpy(session->name, name);
+ INIT_LIST_HEAD(&session->chan);
+ list_add(&session->list, &sessions);
+ mutex_unlock(&sessions_mutex);
+ return session;
+
+exist:
+ mutex_unlock(&sessions_mutex);
+ return NULL;
+}
+
+int ltt_session_destroy(struct ltt_session *session)
+{
+ struct ltt_channel *chan, *tmpchan;
+ struct ltt_event *event, *tmpevent;
+
+ mutex_lock(&sessions_mutex);
+ list_for_each_entry_safe(event, tmpevent, &session->events, list)
+ _ltt_event_destroy(event);
+ list_for_each_entry_safe(chan, tmpchan, &session->chan, list)
+ _ltt_channel_destroy(chan);
+ list_del(&session->list);
+ mutex_unlock(&sessions_mutex);
+ kfree(session);
+}
+
+struct ltt_channel *ltt_channel_create(struct ltt_session *session, char *name,
+ int overwrite, void *buf_addr,
+ size_t subbuf_size, size_t num_subbuf,
+ unsigned int switch_timer_interval,
+ unsigned int read_timer_interval)
+{
+ struct ltt_channel *chan;
+
+ mutex_lock(&sessions_mutex);
+ list_for_each_entry(chan, &session->chan, list)
+ if (!strcmp(chan->name, name))
+ goto exist;
+ chan = kmalloc(sizeof(struct ltt_channel) + strlen(name) + 1, GFP_KERNEL);
+ if (!chan)
+ return NULL;
+ strcpy(chan->name, name);
+ chan->session = session;
+
+ /* TODO: create rb channel */
+ list_add(&chan->list, &session->chan);
+ mutex_unlock(&sessions_mutex);
+ return chan;
+
+exist:
+ mutex_unlock(&sessions_mutex);
+ return NULL;
+}
+
+/*
+ * Only used internally at session destruction.
+ */
+int _ltt_channel_destroy(struct ltt_channel *chan)
+{
+ list_del(&chan->list);
+ kfree(chan);
+}
+
+struct ltt_event *ltt_event_create(struct ltt_channel *chan, char *name,
+ void *filter)
+{
+ struct ltt_event *event;
+
+ mutex_lock(&sessions_mutex);
+ /*
+ * This is O(n^2) (for each event loop called at event creation).
+ * Might require a hash if we have lots of events.
+ */
+ list_for_each_entry(event, &chan->session->events, list)
+ if (!strcmp(event->name, name))
+ goto exist;
+ event = kmem_cache_zalloc(events_cache, GFP_KERNEL);
+ if (!event)
+ goto cache_error;
+ event->name = kmalloc(strlen(name) + 1, GFP_KERNEL);
+ if (!event->name)
+ goto error;
+ strcpy(event->name, name);
+ event->chan = chan;
+ event->filter = filter;
+ event->id = atomic_inc_return(&chan->free_event_id) - 1;
+ /* TODO register to tracepoint */
+ mutex_unlock(&sessions_mutex);
+ return event;
+
+error:
+ kmem_cache_free(event);
+cache_error:
+exist:
+ mutex_unlock(&sessions_mutex);
+ return NULL;
+}
+
+/*
+ * Only used internally at session destruction.
+ */
+int _ltt_event_destroy(struct ltt_event *event)
+{
+ /* TODO unregister from tracepoint */
+ kfree(event->name);
+ kmem_cache_free(event);
+}
+
+static int __init ltt_events_init(void)
+{
+ int ret;
+
+ events_cache = KMEM_CACHE(ltt_event, 0);
+ if (!events_cache)
+ return -ENOMEM;
+ return 0;
+}
+
+static void __exit ltt_events_exit(void)
+{
+ kmem_cache_destroy(events_cache);
+}
--- /dev/null
+/*
+ * ltt-events.h
+ *
+ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Holds LTTng per-session event registry.
+ */
+
+#include <linux/list.h>
+
+struct ltt_channel;
+struct ltt_session;
+
+/*
+ * ltt_event structure is referred to by the tracing fast path. It must be
+ * kept small.
+ */
+struct ltt_event {
+ unsigned int id;
+ struct ltt_channel *chan;
+ void *filter;
+ char *name;
+ struct list_head list; /* Event list */
+};
+
+struct ltt_channel {
+ struct channel *chan; /* Channel buffers */
+ /* Event ID management */
+ struct ltt_session *session;
+ atomic_t free_event_id; /* Next event ID to allocate */
+ struct list_head list; /* Channel list */
+ char name[PATH_MAX];
+};
+
+struct ltt_session {
+ struct list_head chan; /* Channel list head */
+ struct list_head events; /* Event list head */
+ struct list_head list; /* Session list */
+ char name[PATH_MAX];
+};
+
+struct ltt_session *ltt_session_create(char *name);
+int ltt_session_destroy(struct ltt_session *session);
+
+struct ltt_channel *ltt_channel_create(struct ltt_session *session, char *name,
+ int overwrite, void *buf_addr,
+ size_t subbuf_size, size_t num_subbuf,
+ unsigned int switch_timer_interval,
+ unsigned int read_timer_interval);
+int _ltt_channel_destroy(struct ltt_channel *chan);
+
+struct ltt_event *ltt_event_create(struct ltt_channel *chan, char *name,
+ void *filter);
+int _ltt_event_destroy(struct ltt_event *event);