Cleanup: apply `include-what-you-use` guideline for `size_t`
[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:
183 field_align = type->u.basic.integer.alignment;
184 break;
185 case atype_array:
186 {
187 struct lttng_basic_type *btype;
188
189 btype = &type->u.array.elem_type;
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:
198 case atype_sequence:
199 default:
200 WARN_ON_ONCE(1);
201 break;
202 }
203 break;
204 }
205 case atype_sequence:
206 {
207 struct lttng_basic_type *btype;
208
209 btype = &type->u.sequence.length_type;
210 switch (btype->atype) {
211 case atype_integer:
212 field_align = btype->u.basic.integer.alignment;
213 break;
214
215 case atype_string:
216 case atype_array:
217 case atype_sequence:
218 default:
219 WARN_ON_ONCE(1);
220 break;
221 }
222
223 btype = &type->u.sequence.elem_type;
224 switch (btype->atype) {
225 case atype_integer:
226 field_align = max_t(size_t,
227 field_align,
228 btype->u.basic.integer.alignment);
229 break;
230
231 case atype_string:
232 break;
233
234 case atype_array:
235 case atype_sequence:
236 default:
237 WARN_ON_ONCE(1);
238 break;
239 }
240 break;
241 }
242 case atype_string:
243 break;
53569322
MD
244 case atype_dynamic:
245 break;
b2cc986a
MD
246 case atype_enum:
247 default:
248 WARN_ON_ONCE(1);
249 break;
250 }
251 largest_align = max_t(size_t, largest_align, field_align);
252 }
253 ctx->largest_align = largest_align >> 3; /* bits to bytes */
254}
255
b13d13b1
MD
256/*
257 * Remove last context field.
258 */
8020ceb5
MD
259void lttng_remove_context_field(struct lttng_ctx **ctx_p,
260 struct lttng_ctx_field *field)
261{
262 struct lttng_ctx *ctx;
263
264 ctx = *ctx_p;
265 ctx->nr_fields--;
8173ec7c 266 assert(&ctx->fields[ctx->nr_fields] == field);
53569322 267 assert(field->field_name == NULL);
8020ceb5
MD
268 memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field));
269}
8020ceb5
MD
270
271void lttng_destroy_context(struct lttng_ctx *ctx)
272{
273 int i;
274
275 if (!ctx)
276 return;
277 for (i = 0; i < ctx->nr_fields; i++) {
278 if (ctx->fields[i].destroy)
279 ctx->fields[i].destroy(&ctx->fields[i]);
53569322 280 free(ctx->fields[i].field_name);
8020ceb5 281 }
8d8a24c8
MD
282 free(ctx->fields);
283 free(ctx);
8020ceb5 284}
a0a3bef9 285
53569322
MD
286/*
287 * Can be safely performed concurrently with tracing using the struct
288 * lttng_ctx. Using RCU update. Needs to match RCU read-side handling of
289 * contexts.
290 *
291 * This does not allow adding, removing, or changing typing of the
292 * contexts, since this needs to stay invariant for metadata. However,
293 * it allows updating the handlers associated with all contexts matching
294 * a provider (by name) while tracing is using it, in a way that ensures
295 * a single RCU read-side critical section see either all old, or all
296 * new handlers.
297 */
298int lttng_ust_context_set_provider_rcu(struct lttng_ctx **_ctx,
299 const char *name,
300 size_t (*get_size)(struct lttng_ctx_field *field, size_t offset),
301 void (*record)(struct lttng_ctx_field *field,
302 struct lttng_ust_lib_ring_buffer_ctx *ctx,
303 struct lttng_channel *chan),
304 void (*get_value)(struct lttng_ctx_field *field,
305 struct lttng_ctx_value *value))
306{
307 int i, ret;
308 struct lttng_ctx *ctx = *_ctx, *new_ctx;
309 struct lttng_ctx_field *new_fields;
310
311 if (!ctx || !lttng_find_context_provider(ctx, name))
312 return 0;
313 /*
314 * We have at least one instance of context for the provider.
315 */
316 new_ctx = zmalloc(sizeof(*new_ctx));
317 if (!new_ctx)
318 return -ENOMEM;
319 *new_ctx = *ctx;
320 new_fields = zmalloc(sizeof(*new_fields) * ctx->allocated_fields);
321 if (!new_fields) {
322 ret = -ENOMEM;
323 goto field_error;
324 }
325 memcpy(new_fields, ctx->fields,
326 sizeof(*new_fields) * ctx->allocated_fields);
327 for (i = 0; i < ctx->nr_fields; i++) {
328 if (strncmp(new_fields[i].event_field.name,
329 name, strlen(name)) != 0)
330 continue;
331 new_fields[i].get_size = get_size;
332 new_fields[i].record = record;
333 new_fields[i].get_value = get_value;
334 }
335 new_ctx->fields = new_fields;
336 rcu_assign_pointer(*_ctx, new_ctx);
337 synchronize_trace();
338 free(ctx->fields);
339 free(ctx);
340 return 0;
341
342field_error:
343 free(new_ctx);
344 return ret;
345}
346
347int lttng_session_context_init(struct lttng_ctx **ctx)
a0a3bef9
MD
348{
349 int ret;
350
53569322 351 ret = lttng_add_pthread_id_to_ctx(ctx);
a0a3bef9
MD
352 if (ret) {
353 WARN("Cannot add context lttng_add_pthread_id_to_ctx");
53569322 354 goto error;
a0a3bef9 355 }
53569322 356 ret = lttng_add_vtid_to_ctx(ctx);
a0a3bef9
MD
357 if (ret) {
358 WARN("Cannot add context lttng_add_vtid_to_ctx");
53569322 359 goto error;
a0a3bef9 360 }
53569322 361 ret = lttng_add_vpid_to_ctx(ctx);
a0a3bef9
MD
362 if (ret) {
363 WARN("Cannot add context lttng_add_vpid_to_ctx");
53569322 364 goto error;
a0a3bef9 365 }
53569322 366 ret = lttng_add_procname_to_ctx(ctx);
a0a3bef9
MD
367 if (ret) {
368 WARN("Cannot add context lttng_add_procname_to_ctx");
53569322 369 goto error;
a0a3bef9 370 }
53569322 371 ret = lttng_add_cpu_id_to_ctx(ctx);
c7ea8487
MD
372 if (ret) {
373 WARN("Cannot add context lttng_add_cpu_id_to_ctx");
53569322 374 goto error;
c7ea8487 375 }
735bef47
MJ
376 ret = lttng_add_cgroup_ns_to_ctx(ctx);
377 if (ret) {
378 WARN("Cannot add context lttng_add_cgroup_ns_to_ctx");
379 goto error;
380 }
381 ret = lttng_add_ipc_ns_to_ctx(ctx);
382 if (ret) {
383 WARN("Cannot add context lttng_add_ipc_ns_to_ctx");
384 goto error;
385 }
386 ret = lttng_add_mnt_ns_to_ctx(ctx);
387 if (ret) {
388 WARN("Cannot add context lttng_add_mnt_ns_to_ctx");
389 goto error;
390 }
391 ret = lttng_add_net_ns_to_ctx(ctx);
392 if (ret) {
393 WARN("Cannot add context lttng_add_net_ns_to_ctx");
394 goto error;
395 }
396 ret = lttng_add_pid_ns_to_ctx(ctx);
397 if (ret) {
398 WARN("Cannot add context lttng_add_pid_ns_to_ctx");
399 goto error;
400 }
401 ret = lttng_add_user_ns_to_ctx(ctx);
402 if (ret) {
403 WARN("Cannot add context lttng_add_user_ns_to_ctx");
404 goto error;
405 }
406 ret = lttng_add_uts_ns_to_ctx(ctx);
407 if (ret) {
408 WARN("Cannot add context lttng_add_uts_ns_to_ctx");
409 goto error;
410 }
fca2f191
MJ
411 ret = lttng_add_vuid_to_ctx(ctx);
412 if (ret) {
413 WARN("Cannot add context lttng_add_vuid_to_ctx");
414 goto error;
415 }
416 ret = lttng_add_veuid_to_ctx(ctx);
417 if (ret) {
418 WARN("Cannot add context lttng_add_veuid_to_ctx");
419 goto error;
420 }
421 ret = lttng_add_vsuid_to_ctx(ctx);
422 if (ret) {
423 WARN("Cannot add context lttng_add_vsuid_to_ctx");
424 goto error;
425 }
426 ret = lttng_add_vgid_to_ctx(ctx);
427 if (ret) {
428 WARN("Cannot add context lttng_add_vgid_to_ctx");
429 goto error;
430 }
431 ret = lttng_add_vegid_to_ctx(ctx);
432 if (ret) {
433 WARN("Cannot add context lttng_add_vegid_to_ctx");
434 goto error;
435 }
436 ret = lttng_add_vsgid_to_ctx(ctx);
437 if (ret) {
438 WARN("Cannot add context lttng_add_vsgid_to_ctx");
439 goto error;
440 }
53569322
MD
441 lttng_context_update(*ctx);
442 return 0;
a0a3bef9 443
53569322
MD
444error:
445 lttng_destroy_context(*ctx);
446 return ret;
a0a3bef9 447}
4a1f7569
MD
448
449/* For backward compatibility. Leave those exported symbols in place. */
450struct lttng_ctx *lttng_static_ctx;
451
452void lttng_context_init(void)
453{
454}
455
456void lttng_context_exit(void)
457{
458}
This page took 0.048997 seconds and 4 git commands to generate.