Commit | Line | Data |
---|---|---|
4e3c1b9b MD |
1 | /* |
2 | * ltt-events.c | |
3 | * | |
4 | * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
5 | * | |
6 | * Holds LTTng per-session event registry. | |
7 | */ | |
8 | ||
9 | #include <linux/module.h> | |
10 | #include "ltt-events.h" | |
11 | ||
12 | static LIST_HEAD(sessions); | |
13 | static DEFINE_MUTEX(sessions_mutex); | |
14 | static struct kmem_cache *event_cache; | |
15 | ||
16 | struct ltt_session *ltt_session_create(char *name) | |
17 | { | |
18 | struct ltt_session *session; | |
19 | ||
20 | mutex_lock(&sessions_mutex); | |
21 | list_for_each_entry(session, &sessions, list) | |
22 | if (!strcmp(session->name, name)) | |
23 | goto exist; | |
24 | session = kmalloc(sizeof(struct ltt_session) + strlen(name) + 1); | |
25 | if (!session) | |
26 | return NULL; | |
27 | strcpy(session->name, name); | |
28 | INIT_LIST_HEAD(&session->chan); | |
29 | list_add(&session->list, &sessions); | |
30 | mutex_unlock(&sessions_mutex); | |
31 | return session; | |
32 | ||
33 | exist: | |
34 | mutex_unlock(&sessions_mutex); | |
35 | return NULL; | |
36 | } | |
37 | ||
38 | int ltt_session_destroy(struct ltt_session *session) | |
39 | { | |
40 | struct ltt_channel *chan, *tmpchan; | |
41 | struct ltt_event *event, *tmpevent; | |
42 | ||
43 | mutex_lock(&sessions_mutex); | |
44 | list_for_each_entry_safe(event, tmpevent, &session->events, list) | |
45 | _ltt_event_destroy(event); | |
46 | list_for_each_entry_safe(chan, tmpchan, &session->chan, list) | |
47 | _ltt_channel_destroy(chan); | |
48 | list_del(&session->list); | |
49 | mutex_unlock(&sessions_mutex); | |
50 | kfree(session); | |
51 | } | |
52 | ||
53 | struct ltt_channel *ltt_channel_create(struct ltt_session *session, char *name, | |
54 | int overwrite, void *buf_addr, | |
55 | size_t subbuf_size, size_t num_subbuf, | |
56 | unsigned int switch_timer_interval, | |
57 | unsigned int read_timer_interval) | |
58 | { | |
59 | struct ltt_channel *chan; | |
60 | ||
61 | mutex_lock(&sessions_mutex); | |
62 | list_for_each_entry(chan, &session->chan, list) | |
63 | if (!strcmp(chan->name, name)) | |
64 | goto exist; | |
65 | chan = kmalloc(sizeof(struct ltt_channel) + strlen(name) + 1, GFP_KERNEL); | |
66 | if (!chan) | |
67 | return NULL; | |
68 | strcpy(chan->name, name); | |
69 | chan->session = session; | |
70 | ||
71 | /* TODO: create rb channel */ | |
72 | list_add(&chan->list, &session->chan); | |
73 | mutex_unlock(&sessions_mutex); | |
74 | return chan; | |
75 | ||
76 | exist: | |
77 | mutex_unlock(&sessions_mutex); | |
78 | return NULL; | |
79 | } | |
80 | ||
81 | /* | |
82 | * Only used internally at session destruction. | |
83 | */ | |
84 | int _ltt_channel_destroy(struct ltt_channel *chan) | |
85 | { | |
86 | list_del(&chan->list); | |
87 | kfree(chan); | |
88 | } | |
89 | ||
90 | struct ltt_event *ltt_event_create(struct ltt_channel *chan, char *name, | |
91 | void *filter) | |
92 | { | |
93 | struct ltt_event *event; | |
94 | ||
95 | mutex_lock(&sessions_mutex); | |
96 | /* | |
97 | * This is O(n^2) (for each event loop called at event creation). | |
98 | * Might require a hash if we have lots of events. | |
99 | */ | |
100 | list_for_each_entry(event, &chan->session->events, list) | |
101 | if (!strcmp(event->name, name)) | |
102 | goto exist; | |
103 | event = kmem_cache_zalloc(events_cache, GFP_KERNEL); | |
104 | if (!event) | |
105 | goto cache_error; | |
106 | event->name = kmalloc(strlen(name) + 1, GFP_KERNEL); | |
107 | if (!event->name) | |
108 | goto error; | |
109 | strcpy(event->name, name); | |
110 | event->chan = chan; | |
111 | event->filter = filter; | |
112 | event->id = atomic_inc_return(&chan->free_event_id) - 1; | |
113 | /* TODO register to tracepoint */ | |
114 | mutex_unlock(&sessions_mutex); | |
115 | return event; | |
116 | ||
117 | error: | |
118 | kmem_cache_free(event); | |
119 | cache_error: | |
120 | exist: | |
121 | mutex_unlock(&sessions_mutex); | |
122 | return NULL; | |
123 | } | |
124 | ||
125 | /* | |
126 | * Only used internally at session destruction. | |
127 | */ | |
128 | int _ltt_event_destroy(struct ltt_event *event) | |
129 | { | |
130 | /* TODO unregister from tracepoint */ | |
131 | kfree(event->name); | |
132 | kmem_cache_free(event); | |
133 | } | |
134 | ||
135 | static int __init ltt_events_init(void) | |
136 | { | |
137 | int ret; | |
138 | ||
139 | events_cache = KMEM_CACHE(ltt_event, 0); | |
140 | if (!events_cache) | |
141 | return -ENOMEM; | |
142 | return 0; | |
143 | } | |
144 | ||
145 | static void __exit ltt_events_exit(void) | |
146 | { | |
147 | kmem_cache_destroy(events_cache); | |
148 | } |