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