Version 2.7.7
[lttng-modules.git] / lttng-context.c
1 /*
2 * lttng-context.c
3 *
4 * LTTng trace/channel/event context management.
5 *
6 * Copyright (C) 2011-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
21 */
22
23 #include <linux/module.h>
24 #include <linux/list.h>
25 #include <linux/mutex.h>
26 #include <linux/slab.h>
27 #include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */
28 #include "lttng-events.h"
29 #include "lttng-tracer.h"
30
31 /*
32 * The filter implementation requires that two consecutive "get" for the
33 * same context performed by the same thread return the same result.
34 */
35
36 /*
37 * Static array of contexts, for $ctx filters.
38 */
39 struct lttng_ctx *lttng_static_ctx;
40
41 int lttng_find_context(struct lttng_ctx *ctx, const char *name)
42 {
43 unsigned int i;
44
45 for (i = 0; i < ctx->nr_fields; i++) {
46 /* Skip allocated (but non-initialized) contexts */
47 if (!ctx->fields[i].event_field.name)
48 continue;
49 if (!strcmp(ctx->fields[i].event_field.name, name))
50 return 1;
51 }
52 return 0;
53 }
54 EXPORT_SYMBOL_GPL(lttng_find_context);
55
56 int lttng_get_context_index(struct lttng_ctx *ctx, const char *name)
57 {
58 unsigned int i;
59
60 if (!ctx)
61 return -1;
62 for (i = 0; i < ctx->nr_fields; i++) {
63 /* Skip allocated (but non-initialized) contexts */
64 if (!ctx->fields[i].event_field.name)
65 continue;
66 if (!strcmp(ctx->fields[i].event_field.name, name))
67 return i;
68 }
69 return -1;
70 }
71 EXPORT_SYMBOL_GPL(lttng_get_context_index);
72
73 /*
74 * Note: as we append context information, the pointer location may change.
75 */
76 struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p)
77 {
78 struct lttng_ctx_field *field;
79 struct lttng_ctx *ctx;
80
81 if (!*ctx_p) {
82 *ctx_p = kzalloc(sizeof(struct lttng_ctx), GFP_KERNEL);
83 if (!*ctx_p)
84 return NULL;
85 (*ctx_p)->largest_align = 1;
86 }
87 ctx = *ctx_p;
88 if (ctx->nr_fields + 1 > ctx->allocated_fields) {
89 struct lttng_ctx_field *new_fields;
90
91 ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
92 new_fields = kzalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field), GFP_KERNEL);
93 if (!new_fields)
94 return NULL;
95 if (ctx->fields)
96 memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
97 kfree(ctx->fields);
98 ctx->fields = new_fields;
99 }
100 field = &ctx->fields[ctx->nr_fields];
101 ctx->nr_fields++;
102 return field;
103 }
104 EXPORT_SYMBOL_GPL(lttng_append_context);
105
106 /*
107 * lttng_context_update() should be called at least once between context
108 * modification and trace start.
109 */
110 void lttng_context_update(struct lttng_ctx *ctx)
111 {
112 int i;
113 size_t largest_align = 8; /* in bits */
114
115 for (i = 0; i < ctx->nr_fields; i++) {
116 struct lttng_type *type;
117 size_t field_align = 8;
118
119 type = &ctx->fields[i].event_field.type;
120 switch (type->atype) {
121 case atype_integer:
122 field_align = type->u.basic.integer.alignment;
123 break;
124 case atype_array:
125 {
126 struct lttng_basic_type *btype;
127
128 btype = &type->u.array.elem_type;
129 switch (btype->atype) {
130 case atype_integer:
131 field_align = btype->u.basic.integer.alignment;
132 break;
133 case atype_string:
134 break;
135
136 case atype_array:
137 case atype_sequence:
138 default:
139 WARN_ON_ONCE(1);
140 break;
141 }
142 break;
143 }
144 case atype_sequence:
145 {
146 struct lttng_basic_type *btype;
147
148 btype = &type->u.sequence.length_type;
149 switch (btype->atype) {
150 case atype_integer:
151 field_align = btype->u.basic.integer.alignment;
152 break;
153
154 case atype_string:
155 case atype_array:
156 case atype_sequence:
157 default:
158 WARN_ON_ONCE(1);
159 break;
160 }
161
162 btype = &type->u.sequence.elem_type;
163 switch (btype->atype) {
164 case atype_integer:
165 field_align = max_t(size_t,
166 field_align,
167 btype->u.basic.integer.alignment);
168 break;
169
170 case atype_string:
171 break;
172
173 case atype_array:
174 case atype_sequence:
175 default:
176 WARN_ON_ONCE(1);
177 break;
178 }
179 break;
180 }
181 case atype_string:
182 break;
183
184 case atype_enum:
185 default:
186 WARN_ON_ONCE(1);
187 break;
188 }
189 largest_align = max_t(size_t, largest_align, field_align);
190 }
191 ctx->largest_align = largest_align >> 3; /* bits to bytes */
192 }
193
194 /*
195 * Remove last context field.
196 */
197 void lttng_remove_context_field(struct lttng_ctx **ctx_p,
198 struct lttng_ctx_field *field)
199 {
200 struct lttng_ctx *ctx;
201
202 ctx = *ctx_p;
203 ctx->nr_fields--;
204 WARN_ON_ONCE(&ctx->fields[ctx->nr_fields] != field);
205 memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field));
206 }
207 EXPORT_SYMBOL_GPL(lttng_remove_context_field);
208
209 void lttng_destroy_context(struct lttng_ctx *ctx)
210 {
211 int i;
212
213 if (!ctx)
214 return;
215 for (i = 0; i < ctx->nr_fields; i++) {
216 if (ctx->fields[i].destroy)
217 ctx->fields[i].destroy(&ctx->fields[i]);
218 }
219 kfree(ctx->fields);
220 kfree(ctx);
221 }
222
223 int lttng_context_init(void)
224 {
225 int ret;
226
227 ret = lttng_add_hostname_to_ctx(&lttng_static_ctx);
228 if (ret) {
229 printk(KERN_WARNING "Cannot add context lttng_add_hostname_to_ctx");
230 }
231 ret = lttng_add_nice_to_ctx(&lttng_static_ctx);
232 if (ret) {
233 printk(KERN_WARNING "Cannot add context lttng_add_nice_to_ctx");
234 }
235 ret = lttng_add_pid_to_ctx(&lttng_static_ctx);
236 if (ret) {
237 printk(KERN_WARNING "Cannot add context lttng_add_pid_to_ctx");
238 }
239 ret = lttng_add_ppid_to_ctx(&lttng_static_ctx);
240 if (ret) {
241 printk(KERN_WARNING "Cannot add context lttng_add_ppid_to_ctx");
242 }
243 ret = lttng_add_prio_to_ctx(&lttng_static_ctx);
244 if (ret) {
245 printk(KERN_WARNING "Cannot add context lttng_add_prio_to_ctx");
246 }
247 ret = lttng_add_procname_to_ctx(&lttng_static_ctx);
248 if (ret) {
249 printk(KERN_WARNING "Cannot add context lttng_add_procname_to_ctx");
250 }
251 ret = lttng_add_tid_to_ctx(&lttng_static_ctx);
252 if (ret) {
253 printk(KERN_WARNING "Cannot add context lttng_add_tid_to_ctx");
254 }
255 ret = lttng_add_vppid_to_ctx(&lttng_static_ctx);
256 if (ret) {
257 printk(KERN_WARNING "Cannot add context lttng_add_vppid_to_ctx");
258 }
259 ret = lttng_add_vtid_to_ctx(&lttng_static_ctx);
260 if (ret) {
261 printk(KERN_WARNING "Cannot add context lttng_add_vtid_to_ctx");
262 }
263 ret = lttng_add_vpid_to_ctx(&lttng_static_ctx);
264 if (ret) {
265 printk(KERN_WARNING "Cannot add context lttng_add_vpid_to_ctx");
266 }
267 ret = lttng_add_cpu_id_to_ctx(&lttng_static_ctx);
268 if (ret) {
269 printk(KERN_WARNING "Cannot add context lttng_add_cpu_id_to_ctx");
270 }
271 /* TODO: perf counters for filtering */
272 return 0;
273 }
274
275 void lttng_context_exit(void)
276 {
277 lttng_destroy_context(lttng_static_ctx);
278 lttng_static_ctx = NULL;
279 }
This page took 0.034122 seconds and 4 git commands to generate.