Commit | Line | Data |
---|---|---|
ce5aef0b MD |
1 | /* |
2 | * ltt-probes.c | |
3 | * | |
4 | * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
5 | * | |
6 | * Holds LTTng probes registry. | |
7 | * | |
8 | * Dual LGPL v2.1/GPL v2 license. | |
9 | */ | |
10 | ||
8d8a24c8 MD |
11 | #include <string.h> |
12 | #include <errno.h> | |
13 | #include <urcu/list.h> | |
4318ae1b MD |
14 | #include <lttng/core.h> |
15 | #include <lttng/ust-events.h> | |
a3bb4b27 | 16 | #include <assert.h> |
ce5aef0b | 17 | |
8165c8da MD |
18 | #include "ltt-tracer-core.h" |
19 | ||
20 | /* | |
17dfb34b | 21 | * probe list is protected by ust_lock()/ust_unlock(). |
8165c8da | 22 | */ |
8d8a24c8 | 23 | static CDS_LIST_HEAD(probe_list); |
ce5aef0b MD |
24 | |
25 | static | |
26 | const struct lttng_event_desc *find_event(const char *name) | |
27 | { | |
28 | struct lttng_probe_desc *probe_desc; | |
29 | int i; | |
30 | ||
8d8a24c8 | 31 | cds_list_for_each_entry(probe_desc, &probe_list, head) { |
ce5aef0b MD |
32 | for (i = 0; i < probe_desc->nr_events; i++) { |
33 | if (!strcmp(probe_desc->event_desc[i].name, name)) | |
34 | return &probe_desc->event_desc[i]; | |
35 | } | |
36 | } | |
37 | return NULL; | |
38 | } | |
39 | ||
40 | int ltt_probe_register(struct lttng_probe_desc *desc) | |
41 | { | |
42 | int ret = 0; | |
43 | int i; | |
44 | ||
17dfb34b | 45 | ust_lock(); |
ce5aef0b MD |
46 | /* |
47 | * TODO: This is O(N^2). Turn into a hash table when probe registration | |
48 | * overhead becomes an issue. | |
49 | */ | |
50 | for (i = 0; i < desc->nr_events; i++) { | |
51 | if (find_event(desc->event_desc[i].name)) { | |
52 | ret = -EEXIST; | |
53 | goto end; | |
54 | } | |
55 | } | |
8d8a24c8 | 56 | cds_list_add(&desc->head, &probe_list); |
8165c8da MD |
57 | |
58 | /* | |
59 | * fix the events awaiting probe load. | |
60 | */ | |
61 | for (i = 0; i < desc->nr_events; i++) { | |
62 | ret = pending_probe_fix_events(&desc->event_desc[i]); | |
63 | assert(!ret); | |
64 | } | |
ce5aef0b | 65 | end: |
17dfb34b | 66 | ust_unlock(); |
ce5aef0b MD |
67 | return ret; |
68 | } | |
ce5aef0b MD |
69 | |
70 | void ltt_probe_unregister(struct lttng_probe_desc *desc) | |
71 | { | |
17dfb34b | 72 | ust_lock(); |
8d8a24c8 | 73 | cds_list_del(&desc->head); |
17dfb34b | 74 | ust_unlock(); |
ce5aef0b | 75 | } |
ce5aef0b | 76 | |
8165c8da MD |
77 | /* |
78 | * called with UST lock held. | |
79 | */ | |
ce5aef0b MD |
80 | const struct lttng_event_desc *ltt_event_get(const char *name) |
81 | { | |
82 | const struct lttng_event_desc *event; | |
ce5aef0b | 83 | |
ce5aef0b | 84 | event = find_event(name); |
ce5aef0b MD |
85 | if (!event) |
86 | return NULL; | |
ce5aef0b MD |
87 | return event; |
88 | } | |
ce5aef0b MD |
89 | |
90 | void ltt_event_put(const struct lttng_event_desc *event) | |
91 | { | |
ce5aef0b | 92 | } |
ce5aef0b | 93 | |
8d8a24c8 | 94 | #if 0 |
ce5aef0b MD |
95 | static |
96 | void *tp_list_start(struct seq_file *m, loff_t *pos) | |
97 | { | |
98 | struct lttng_probe_desc *probe_desc; | |
99 | int iter = 0, i; | |
100 | ||
8d8a24c8 MD |
101 | pthread_mutex_lock(&probe_mutex); |
102 | cds_list_for_each_entry(probe_desc, &probe_list, head) { | |
ce5aef0b MD |
103 | for (i = 0; i < probe_desc->nr_events; i++) { |
104 | if (iter++ >= *pos) | |
105 | return (void *) &probe_desc->event_desc[i]; | |
106 | } | |
107 | } | |
108 | /* End of list */ | |
109 | return NULL; | |
110 | } | |
111 | ||
112 | static | |
113 | void *tp_list_next(struct seq_file *m, void *p, loff_t *ppos) | |
114 | { | |
115 | struct lttng_probe_desc *probe_desc; | |
116 | int iter = 0, i; | |
117 | ||
118 | (*ppos)++; | |
8d8a24c8 | 119 | cds_list_for_each_entry(probe_desc, &probe_list, head) { |
ce5aef0b MD |
120 | for (i = 0; i < probe_desc->nr_events; i++) { |
121 | if (iter++ >= *ppos) | |
122 | return (void *) &probe_desc->event_desc[i]; | |
123 | } | |
124 | } | |
125 | /* End of list */ | |
126 | return NULL; | |
127 | } | |
128 | ||
129 | static | |
130 | void tp_list_stop(struct seq_file *m, void *p) | |
131 | { | |
8d8a24c8 | 132 | pthread_mutex_unlock(&probe_mutex); |
ce5aef0b MD |
133 | } |
134 | ||
135 | static | |
136 | int tp_list_show(struct seq_file *m, void *p) | |
137 | { | |
138 | const struct lttng_event_desc *probe_desc = p; | |
139 | ||
140 | /* | |
141 | * Don't export lttng internal events (metadata). | |
142 | */ | |
143 | if (!strncmp(probe_desc->name, "lttng_", sizeof("lttng_") - 1)) | |
144 | return 0; | |
145 | seq_printf(m, "event { name = %s; };\n", | |
146 | probe_desc->name); | |
147 | return 0; | |
148 | } | |
149 | ||
150 | static | |
151 | const struct seq_operations lttng_tracepoint_list_seq_ops = { | |
152 | .start = tp_list_start, | |
153 | .next = tp_list_next, | |
154 | .stop = tp_list_stop, | |
155 | .show = tp_list_show, | |
156 | }; | |
157 | ||
158 | static | |
159 | int lttng_tracepoint_list_open(struct inode *inode, struct file *file) | |
160 | { | |
161 | return seq_open(file, <tng_tracepoint_list_seq_ops); | |
162 | } | |
163 | ||
164 | const struct file_operations lttng_tracepoint_list_fops = { | |
165 | .open = lttng_tracepoint_list_open, | |
166 | .read = seq_read, | |
167 | .llseek = seq_lseek, | |
168 | .release = seq_release, | |
169 | }; | |
8d8a24c8 | 170 | #endif //0 |