e441d4ae2060561a44b9d980ef3e6d73800b1a26
[lttng-ust.git] / liblttng-ust / lttng-context.c
1 /*
2 * lttng-context.c
3 *
4 * LTTng UST trace/channel/event context management.
5 *
6 * Copyright (C) 2011 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 #define _LGPL_SOURCE
24 #include <lttng/ust-events.h>
25 #include <lttng/ust-tracer.h>
26 #include <lttng/ust-context-provider.h>
27 #include <lttng/urcu/pointer.h>
28 #include <usterr-signal-safe.h>
29 #include <helper.h>
30 #include <stddef.h>
31 #include <string.h>
32 #include <assert.h>
33 #include "tracepoint-internal.h"
34
35 #include "context-internal.h"
36
37 /*
38 * The filter implementation requires that two consecutive "get" for the
39 * same context performed by the same thread return the same result.
40 */
41
42 int lttng_find_context(struct lttng_ctx *ctx, const char *name)
43 {
44 unsigned int i;
45 const char *subname;
46
47 if (strncmp(name, "$ctx.", strlen("$ctx.")) == 0) {
48 subname = name + strlen("$ctx.");
49 } else {
50 subname = name;
51 }
52 for (i = 0; i < ctx->nr_fields; i++) {
53 /* Skip allocated (but non-initialized) contexts */
54 if (!ctx->fields[i].event_field.name)
55 continue;
56 if (!strcmp(ctx->fields[i].event_field.name, subname))
57 return 1;
58 }
59 return 0;
60 }
61
62 int lttng_get_context_index(struct lttng_ctx *ctx, const char *name)
63 {
64 unsigned int i;
65 const char *subname;
66
67 if (!ctx)
68 return -1;
69 if (strncmp(name, "$ctx.", strlen("$ctx.")) == 0) {
70 subname = name + strlen("$ctx.");
71 } else {
72 subname = name;
73 }
74 for (i = 0; i < ctx->nr_fields; i++) {
75 /* Skip allocated (but non-initialized) contexts */
76 if (!ctx->fields[i].event_field.name)
77 continue;
78 if (!strcmp(ctx->fields[i].event_field.name, subname))
79 return i;
80 }
81 return -1;
82 }
83
84 static int lttng_find_context_provider(struct lttng_ctx *ctx, const char *name)
85 {
86 unsigned int i;
87
88 for (i = 0; i < ctx->nr_fields; i++) {
89 /* Skip allocated (but non-initialized) contexts */
90 if (!ctx->fields[i].event_field.name)
91 continue;
92 if (!strncmp(ctx->fields[i].event_field.name, name,
93 strlen(name)))
94 return 1;
95 }
96 return 0;
97 }
98
99 /*
100 * Note: as we append context information, the pointer location may change.
101 */
102 struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p)
103 {
104 struct lttng_ctx_field *field;
105 struct lttng_ctx *ctx;
106
107 if (!*ctx_p) {
108 *ctx_p = zmalloc(sizeof(struct lttng_ctx));
109 if (!*ctx_p)
110 return NULL;
111 (*ctx_p)->largest_align = 1;
112 }
113 ctx = *ctx_p;
114 if (ctx->nr_fields + 1 > ctx->allocated_fields) {
115 struct lttng_ctx_field *new_fields;
116
117 ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
118 new_fields = zmalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field));
119 if (!new_fields)
120 return NULL;
121 if (ctx->fields)
122 memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
123 free(ctx->fields);
124 ctx->fields = new_fields;
125 }
126 field = &ctx->fields[ctx->nr_fields];
127 ctx->nr_fields++;
128 return field;
129 }
130
131 int lttng_context_add_rcu(struct lttng_ctx **ctx_p,
132 const struct lttng_ctx_field *f)
133 {
134 struct lttng_ctx *old_ctx = *ctx_p, *new_ctx = NULL;
135 struct lttng_ctx_field *new_fields = NULL;
136 struct lttng_ctx_field *nf;
137
138 if (old_ctx) {
139 new_ctx = zmalloc(sizeof(struct lttng_ctx));
140 if (!new_ctx)
141 return -ENOMEM;
142 *new_ctx = *old_ctx;
143 new_fields = zmalloc(new_ctx->allocated_fields
144 * sizeof(struct lttng_ctx_field));
145 if (!new_fields) {
146 free(new_ctx);
147 return -ENOMEM;
148 }
149 memcpy(new_fields, old_ctx->fields,
150 sizeof(*old_ctx->fields) * old_ctx->nr_fields);
151 new_ctx->fields = new_fields;
152 }
153 nf = lttng_append_context(&new_ctx);
154 if (!nf) {
155 free(new_fields);
156 free(new_ctx);
157 return -ENOMEM;
158 }
159 *nf = *f;
160 lttng_context_update(new_ctx);
161 lttng_ust_rcu_assign_pointer(*ctx_p, new_ctx);
162 lttng_ust_synchronize_trace();
163 if (old_ctx) {
164 free(old_ctx->fields);
165 free(old_ctx);
166 }
167 return 0;
168 }
169
170 /*
171 * lttng_context_update() should be called at least once between context
172 * modification and trace start.
173 */
174 void lttng_context_update(struct lttng_ctx *ctx)
175 {
176 int i;
177 size_t largest_align = 8; /* in bits */
178
179 for (i = 0; i < ctx->nr_fields; i++) {
180 struct lttng_type *type;
181 size_t field_align = 8;
182
183 type = &ctx->fields[i].event_field.type;
184 switch (type->atype) {
185 case atype_integer:
186 field_align = type->u.integer.alignment;
187 break;
188 case atype_array:
189 {
190 struct lttng_basic_type *btype;
191
192 btype = &type->u.legacy.array.elem_type;
193 switch (btype->atype) {
194 case atype_integer:
195 field_align = btype->u.basic.integer.alignment;
196 break;
197 case atype_string:
198 break;
199
200 case atype_array:
201 case atype_array_nestable:
202 case atype_sequence:
203 case atype_sequence_nestable:
204 default:
205 WARN_ON_ONCE(1);
206 break;
207 }
208 break;
209 }
210 case atype_array_nestable:
211 {
212 const struct lttng_type *nested_type;
213
214 nested_type = type->u.array_nestable.elem_type;
215 switch (nested_type->atype) {
216 case atype_integer:
217 field_align = nested_type->u.integer.alignment;
218 break;
219 case atype_string:
220 break;
221
222 case atype_array:
223 case atype_array_nestable:
224 case atype_sequence:
225 case atype_sequence_nestable:
226 default:
227 WARN_ON_ONCE(1);
228 break;
229 }
230 field_align = max_t(size_t, field_align,
231 type->u.array_nestable.alignment);
232 break;
233 }
234 case atype_sequence:
235 {
236 struct lttng_basic_type *btype;
237
238 btype = &type->u.legacy.sequence.length_type;
239 switch (btype->atype) {
240 case atype_integer:
241 field_align = btype->u.basic.integer.alignment;
242 break;
243
244 case atype_string:
245 case atype_array:
246 case atype_array_nestable:
247 case atype_sequence:
248 case atype_sequence_nestable:
249 default:
250 WARN_ON_ONCE(1);
251 break;
252 }
253
254 btype = &type->u.legacy.sequence.elem_type;
255 switch (btype->atype) {
256 case atype_integer:
257 field_align = max_t(size_t,
258 field_align,
259 btype->u.basic.integer.alignment);
260 break;
261
262 case atype_string:
263 break;
264
265 case atype_array:
266 case atype_array_nestable:
267 case atype_sequence:
268 case atype_sequence_nestable:
269 default:
270 WARN_ON_ONCE(1);
271 break;
272 }
273 break;
274 }
275 case atype_sequence_nestable:
276 {
277 const struct lttng_type *nested_type;
278
279 nested_type = type->u.sequence_nestable.elem_type;
280 switch (nested_type->atype) {
281 case atype_integer:
282 field_align = nested_type->u.integer.alignment;
283 break;
284
285 case atype_string:
286 break;
287
288 case atype_array:
289 case atype_array_nestable:
290 case atype_sequence:
291 case atype_sequence_nestable:
292 default:
293 WARN_ON_ONCE(1);
294 break;
295 }
296 field_align = max_t(size_t, field_align,
297 type->u.sequence_nestable.alignment);
298 break;
299 }
300 case atype_string:
301 break;
302 case atype_dynamic:
303 break;
304 case atype_enum:
305 case atype_enum_nestable:
306 default:
307 WARN_ON_ONCE(1);
308 break;
309 }
310 largest_align = max_t(size_t, largest_align, field_align);
311 }
312 ctx->largest_align = largest_align >> 3; /* bits to bytes */
313 }
314
315 /*
316 * Remove last context field.
317 */
318 void lttng_remove_context_field(struct lttng_ctx **ctx_p,
319 struct lttng_ctx_field *field)
320 {
321 struct lttng_ctx *ctx;
322
323 ctx = *ctx_p;
324 ctx->nr_fields--;
325 assert(&ctx->fields[ctx->nr_fields] == field);
326 assert(field->field_name == NULL);
327 memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field));
328 }
329
330 void lttng_destroy_context(struct lttng_ctx *ctx)
331 {
332 int i;
333
334 if (!ctx)
335 return;
336 for (i = 0; i < ctx->nr_fields; i++) {
337 if (ctx->fields[i].destroy)
338 ctx->fields[i].destroy(&ctx->fields[i]);
339 free(ctx->fields[i].field_name);
340 }
341 free(ctx->fields);
342 free(ctx);
343 }
344
345 /*
346 * Can be safely performed concurrently with tracing using the struct
347 * lttng_ctx. Using RCU update. Needs to match RCU read-side handling of
348 * contexts.
349 *
350 * This does not allow adding, removing, or changing typing of the
351 * contexts, since this needs to stay invariant for metadata. However,
352 * it allows updating the handlers associated with all contexts matching
353 * a provider (by name) while tracing is using it, in a way that ensures
354 * a single RCU read-side critical section see either all old, or all
355 * new handlers.
356 */
357 int lttng_ust_context_set_provider_rcu(struct lttng_ctx **_ctx,
358 const char *name,
359 size_t (*get_size)(struct lttng_ctx_field *field, size_t offset),
360 void (*record)(struct lttng_ctx_field *field,
361 struct lttng_ust_lib_ring_buffer_ctx *ctx,
362 struct lttng_channel *chan),
363 void (*get_value)(struct lttng_ctx_field *field,
364 struct lttng_ctx_value *value))
365 {
366 int i, ret;
367 struct lttng_ctx *ctx = *_ctx, *new_ctx;
368 struct lttng_ctx_field *new_fields;
369
370 if (!ctx || !lttng_find_context_provider(ctx, name))
371 return 0;
372 /*
373 * We have at least one instance of context for the provider.
374 */
375 new_ctx = zmalloc(sizeof(*new_ctx));
376 if (!new_ctx)
377 return -ENOMEM;
378 *new_ctx = *ctx;
379 new_fields = zmalloc(sizeof(*new_fields) * ctx->allocated_fields);
380 if (!new_fields) {
381 ret = -ENOMEM;
382 goto field_error;
383 }
384 memcpy(new_fields, ctx->fields,
385 sizeof(*new_fields) * ctx->allocated_fields);
386 for (i = 0; i < ctx->nr_fields; i++) {
387 if (strncmp(new_fields[i].event_field.name,
388 name, strlen(name)) != 0)
389 continue;
390 new_fields[i].get_size = get_size;
391 new_fields[i].record = record;
392 new_fields[i].get_value = get_value;
393 }
394 new_ctx->fields = new_fields;
395 lttng_ust_rcu_assign_pointer(*_ctx, new_ctx);
396 lttng_ust_synchronize_trace();
397 free(ctx->fields);
398 free(ctx);
399 return 0;
400
401 field_error:
402 free(new_ctx);
403 return ret;
404 }
405
406 int lttng_context_init_all(struct lttng_ctx **ctx)
407 {
408 int ret;
409
410 ret = lttng_add_pthread_id_to_ctx(ctx);
411 if (ret) {
412 WARN("Cannot add context lttng_add_pthread_id_to_ctx");
413 goto error;
414 }
415 ret = lttng_add_vtid_to_ctx(ctx);
416 if (ret) {
417 WARN("Cannot add context lttng_add_vtid_to_ctx");
418 goto error;
419 }
420 ret = lttng_add_vpid_to_ctx(ctx);
421 if (ret) {
422 WARN("Cannot add context lttng_add_vpid_to_ctx");
423 goto error;
424 }
425 ret = lttng_add_procname_to_ctx(ctx);
426 if (ret) {
427 WARN("Cannot add context lttng_add_procname_to_ctx");
428 goto error;
429 }
430 ret = lttng_add_cpu_id_to_ctx(ctx);
431 if (ret) {
432 WARN("Cannot add context lttng_add_cpu_id_to_ctx");
433 goto error;
434 }
435 ret = lttng_add_cgroup_ns_to_ctx(ctx);
436 if (ret) {
437 WARN("Cannot add context lttng_add_cgroup_ns_to_ctx");
438 goto error;
439 }
440 ret = lttng_add_ipc_ns_to_ctx(ctx);
441 if (ret) {
442 WARN("Cannot add context lttng_add_ipc_ns_to_ctx");
443 goto error;
444 }
445 ret = lttng_add_mnt_ns_to_ctx(ctx);
446 if (ret) {
447 WARN("Cannot add context lttng_add_mnt_ns_to_ctx");
448 goto error;
449 }
450 ret = lttng_add_net_ns_to_ctx(ctx);
451 if (ret) {
452 WARN("Cannot add context lttng_add_net_ns_to_ctx");
453 goto error;
454 }
455 ret = lttng_add_pid_ns_to_ctx(ctx);
456 if (ret) {
457 WARN("Cannot add context lttng_add_pid_ns_to_ctx");
458 goto error;
459 }
460 ret = lttng_add_time_ns_to_ctx(ctx);
461 if (ret) {
462 WARN("Cannot add context lttng_add_time_ns_to_ctx");
463 goto error;
464 }
465 ret = lttng_add_user_ns_to_ctx(ctx);
466 if (ret) {
467 WARN("Cannot add context lttng_add_user_ns_to_ctx");
468 goto error;
469 }
470 ret = lttng_add_uts_ns_to_ctx(ctx);
471 if (ret) {
472 WARN("Cannot add context lttng_add_uts_ns_to_ctx");
473 goto error;
474 }
475 ret = lttng_add_vuid_to_ctx(ctx);
476 if (ret) {
477 WARN("Cannot add context lttng_add_vuid_to_ctx");
478 goto error;
479 }
480 ret = lttng_add_veuid_to_ctx(ctx);
481 if (ret) {
482 WARN("Cannot add context lttng_add_veuid_to_ctx");
483 goto error;
484 }
485 ret = lttng_add_vsuid_to_ctx(ctx);
486 if (ret) {
487 WARN("Cannot add context lttng_add_vsuid_to_ctx");
488 goto error;
489 }
490 ret = lttng_add_vgid_to_ctx(ctx);
491 if (ret) {
492 WARN("Cannot add context lttng_add_vgid_to_ctx");
493 goto error;
494 }
495 ret = lttng_add_vegid_to_ctx(ctx);
496 if (ret) {
497 WARN("Cannot add context lttng_add_vegid_to_ctx");
498 goto error;
499 }
500 ret = lttng_add_vsgid_to_ctx(ctx);
501 if (ret) {
502 WARN("Cannot add context lttng_add_vsgid_to_ctx");
503 goto error;
504 }
505 lttng_context_update(*ctx);
506 return 0;
507
508 error:
509 lttng_destroy_context(*ctx);
510 return ret;
511 }
This page took 0.039809 seconds and 3 git commands to generate.