From 4e3c1b9b19e384d42f060576673d4c3f5453e8cb Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 23 Nov 2010 17:25:15 -0500 Subject: [PATCH] ltt-events: initial addition Signed-off-by: Mathieu Desnoyers --- ltt-events.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++ ltt-events.h | 54 +++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 ltt-events.c create mode 100644 ltt-events.h diff --git a/ltt-events.c b/ltt-events.c new file mode 100644 index 00000000..a85b7932 --- /dev/null +++ b/ltt-events.c @@ -0,0 +1,148 @@ +/* + * ltt-events.c + * + * Copyright 2010 (c) - Mathieu Desnoyers + * + * Holds LTTng per-session event registry. + */ + +#include +#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); +} diff --git a/ltt-events.h b/ltt-events.h new file mode 100644 index 00000000..d205cdb0 --- /dev/null +++ b/ltt-events.h @@ -0,0 +1,54 @@ +/* + * ltt-events.h + * + * Copyright 2010 (c) - Mathieu Desnoyers + * + * Holds LTTng per-session event registry. + */ + +#include + +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); -- 2.34.1