Version 2.3.2
[lttng-modules.git] / lttng-probes.c
CommitLineData
02119ee5 1/*
a90917c3 2 * lttng-probes.c
02119ee5 3 *
02119ee5 4 * Holds LTTng probes registry.
17baffe2 5 *
886d51a3
MD
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
02119ee5
MD
21 */
22
23#include <linux/module.h>
24#include <linux/list.h>
25#include <linux/mutex.h>
271b6681 26#include <linux/seq_file.h>
02119ee5 27
a90917c3 28#include "lttng-events.h"
02119ee5
MD
29
30static LIST_HEAD(probe_list);
31static DEFINE_MUTEX(probe_mutex);
02119ee5 32
85a9ca7f
MD
33static
34const struct lttng_event_desc *find_event(const char *name)
02119ee5 35{
85a9ca7f
MD
36 struct lttng_probe_desc *probe_desc;
37 int i;
02119ee5 38
85a9ca7f
MD
39 list_for_each_entry(probe_desc, &probe_list, head) {
40 for (i = 0; i < probe_desc->nr_events; i++) {
f7bdf4db
MD
41 if (!strcmp(probe_desc->event_desc[i]->name, name))
42 return probe_desc->event_desc[i];
85a9ca7f 43 }
02119ee5
MD
44 }
45 return NULL;
46}
47
a90917c3 48int lttng_probe_register(struct lttng_probe_desc *desc)
02119ee5 49{
02119ee5 50 int ret = 0;
85a9ca7f 51 int i;
02119ee5
MD
52
53 mutex_lock(&probe_mutex);
85a9ca7f
MD
54 /*
55 * TODO: This is O(N^2). Turn into a hash table when probe registration
56 * overhead becomes an issue.
57 */
58 for (i = 0; i < desc->nr_events; i++) {
f7bdf4db 59 if (find_event(desc->event_desc[i]->name)) {
85a9ca7f
MD
60 ret = -EEXIST;
61 goto end;
62 }
02119ee5 63 }
85a9ca7f 64 list_add(&desc->head, &probe_list);
02119ee5
MD
65end:
66 mutex_unlock(&probe_mutex);
67 return ret;
68}
a90917c3 69EXPORT_SYMBOL_GPL(lttng_probe_register);
02119ee5 70
a90917c3 71void lttng_probe_unregister(struct lttng_probe_desc *desc)
02119ee5 72{
02119ee5 73 mutex_lock(&probe_mutex);
85a9ca7f 74 list_del(&desc->head);
02119ee5 75 mutex_unlock(&probe_mutex);
02119ee5 76}
a90917c3 77EXPORT_SYMBOL_GPL(lttng_probe_unregister);
02119ee5 78
a90917c3 79const struct lttng_event_desc *lttng_event_get(const char *name)
02119ee5 80{
85a9ca7f 81 const struct lttng_event_desc *event;
02119ee5
MD
82 int ret;
83
84 mutex_lock(&probe_mutex);
85a9ca7f 85 event = find_event(name);
c099397a 86 mutex_unlock(&probe_mutex);
85a9ca7f 87 if (!event)
c099397a 88 return NULL;
dc7f600a 89 ret = try_module_get(event->owner);
02119ee5 90 WARN_ON_ONCE(!ret);
85a9ca7f 91 return event;
02119ee5 92}
a90917c3 93EXPORT_SYMBOL_GPL(lttng_event_get);
02119ee5 94
a90917c3 95void lttng_event_put(const struct lttng_event_desc *event)
02119ee5 96{
dc7f600a 97 module_put(event->owner);
02119ee5 98}
a90917c3 99EXPORT_SYMBOL_GPL(lttng_event_put);
271b6681
MD
100
101static
102void *tp_list_start(struct seq_file *m, loff_t *pos)
103{
104 struct lttng_probe_desc *probe_desc;
105 int iter = 0, i;
106
cbd4ecb2 107 mutex_lock(&probe_mutex);
271b6681
MD
108 list_for_each_entry(probe_desc, &probe_list, head) {
109 for (i = 0; i < probe_desc->nr_events; i++) {
110 if (iter++ >= *pos)
f7bdf4db 111 return (void *) probe_desc->event_desc[i];
271b6681
MD
112 }
113 }
114 /* End of list */
115 return NULL;
116}
117
118static
119void *tp_list_next(struct seq_file *m, void *p, loff_t *ppos)
120{
121 struct lttng_probe_desc *probe_desc;
122 int iter = 0, i;
123
124 (*ppos)++;
125 list_for_each_entry(probe_desc, &probe_list, head) {
126 for (i = 0; i < probe_desc->nr_events; i++) {
127 if (iter++ >= *ppos)
f7bdf4db 128 return (void *) probe_desc->event_desc[i];
271b6681
MD
129 }
130 }
131 /* End of list */
132 return NULL;
133}
134
135static
136void tp_list_stop(struct seq_file *m, void *p)
137{
cbd4ecb2 138 mutex_unlock(&probe_mutex);
271b6681
MD
139}
140
141static
142int tp_list_show(struct seq_file *m, void *p)
143{
144 const struct lttng_event_desc *probe_desc = p;
145
146 seq_printf(m, "event { name = %s; };\n",
147 probe_desc->name);
148 return 0;
149}
150
151static
152const struct seq_operations lttng_tracepoint_list_seq_ops = {
153 .start = tp_list_start,
154 .next = tp_list_next,
155 .stop = tp_list_stop,
156 .show = tp_list_show,
157};
158
159static
160int lttng_tracepoint_list_open(struct inode *inode, struct file *file)
161{
162 return seq_open(file, &lttng_tracepoint_list_seq_ops);
163}
164
165const struct file_operations lttng_tracepoint_list_fops = {
2e54c205 166 .owner = THIS_MODULE,
271b6681
MD
167 .open = lttng_tracepoint_list_open,
168 .read = seq_read,
169 .llseek = seq_lseek,
a51729c7 170 .release = seq_release,
271b6681 171};
This page took 0.035936 seconds and 4 git commands to generate.