Contexts for RT debugging
[lttng-modules.git] / lttng-context.c
CommitLineData
2dccf128 1/*
a90917c3 2 * lttng-context.c
2dccf128 3 *
2dccf128 4 * LTTng trace/channel/event context management.
17baffe2 5 *
886d51a3
MD
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
2dccf128
MD
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() */
a90917c3
MD
28#include "lttng-events.h"
29#include "lttng-tracer.h"
2dccf128 30
07dfc1d0
MD
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 */
39struct lttng_ctx *lttng_static_ctx;
40
44252f0f
MD
41int 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++) {
4b58a8e4
MD
46 /* Skip allocated (but non-initialized) contexts */
47 if (!ctx->fields[i].event_field.name)
48 continue;
44252f0f
MD
49 if (!strcmp(ctx->fields[i].event_field.name, name))
50 return 1;
51 }
52 return 0;
53}
54EXPORT_SYMBOL_GPL(lttng_find_context);
55
07dfc1d0
MD
56int 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}
71EXPORT_SYMBOL_GPL(lttng_get_context_index);
72
2001023e
MD
73/*
74 * Note: as we append context information, the pointer location may change.
75 */
2dccf128
MD
76struct 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;
a9dd15da 85 (*ctx_p)->largest_align = 1;
2dccf128
MD
86 }
87 ctx = *ctx_p;
88 if (ctx->nr_fields + 1 > ctx->allocated_fields) {
89 struct lttng_ctx_field *new_fields;
90
0f034e0f 91 ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
2dccf128
MD
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)
77aefe99 96 memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
2dccf128
MD
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}
104EXPORT_SYMBOL_GPL(lttng_append_context);
105
a9dd15da
MD
106/*
107 * lttng_context_update() should be called at least once between context
108 * modification and trace start.
109 */
110void 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
4cae220c
MD
194/*
195 * Remove last context field.
196 */
8289661d
MD
197void 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--;
4cae220c 204 WARN_ON_ONCE(&ctx->fields[ctx->nr_fields] != field);
8289661d
MD
205 memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field));
206}
207EXPORT_SYMBOL_GPL(lttng_remove_context_field);
208
2dccf128
MD
209void lttng_destroy_context(struct lttng_ctx *ctx)
210{
211 int i;
212
8070f5c0
MD
213 if (!ctx)
214 return;
9e7e4892
MD
215 for (i = 0; i < ctx->nr_fields; i++) {
216 if (ctx->fields[i].destroy)
217 ctx->fields[i].destroy(&ctx->fields[i]);
218 }
2dccf128
MD
219 kfree(ctx->fields);
220 kfree(ctx);
221}
07dfc1d0
MD
222
223int lttng_context_init(void)
224{
225 int ret;
226
f127e61e
MD
227 ret = lttng_add_hostname_to_ctx(&lttng_static_ctx);
228 if (ret) {
38c4a82c 229 printk(KERN_WARNING "Cannot add context lttng_add_hostname_to_ctx");
f127e61e
MD
230 }
231 ret = lttng_add_nice_to_ctx(&lttng_static_ctx);
07dfc1d0 232 if (ret) {
38c4a82c 233 printk(KERN_WARNING "Cannot add context lttng_add_nice_to_ctx");
07dfc1d0 234 }
07dfc1d0
MD
235 ret = lttng_add_pid_to_ctx(&lttng_static_ctx);
236 if (ret) {
38c4a82c 237 printk(KERN_WARNING "Cannot add context lttng_add_pid_to_ctx");
07dfc1d0 238 }
f127e61e 239 ret = lttng_add_ppid_to_ctx(&lttng_static_ctx);
07dfc1d0 240 if (ret) {
38c4a82c 241 printk(KERN_WARNING "Cannot add context lttng_add_ppid_to_ctx");
07dfc1d0
MD
242 }
243 ret = lttng_add_prio_to_ctx(&lttng_static_ctx);
244 if (ret) {
38c4a82c 245 printk(KERN_WARNING "Cannot add context lttng_add_prio_to_ctx");
07dfc1d0 246 }
f127e61e 247 ret = lttng_add_procname_to_ctx(&lttng_static_ctx);
07dfc1d0 248 if (ret) {
38c4a82c 249 printk(KERN_WARNING "Cannot add context lttng_add_procname_to_ctx");
07dfc1d0
MD
250 }
251 ret = lttng_add_tid_to_ctx(&lttng_static_ctx);
252 if (ret) {
38c4a82c 253 printk(KERN_WARNING "Cannot add context lttng_add_tid_to_ctx");
07dfc1d0 254 }
f127e61e 255 ret = lttng_add_vppid_to_ctx(&lttng_static_ctx);
07dfc1d0 256 if (ret) {
38c4a82c 257 printk(KERN_WARNING "Cannot add context lttng_add_vppid_to_ctx");
07dfc1d0 258 }
f127e61e 259 ret = lttng_add_vtid_to_ctx(&lttng_static_ctx);
07dfc1d0 260 if (ret) {
38c4a82c 261 printk(KERN_WARNING "Cannot add context lttng_add_vtid_to_ctx");
07dfc1d0 262 }
f127e61e 263 ret = lttng_add_vpid_to_ctx(&lttng_static_ctx);
07dfc1d0 264 if (ret) {
38c4a82c 265 printk(KERN_WARNING "Cannot add context lttng_add_vpid_to_ctx");
07dfc1d0 266 }
b3699d90
MD
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 }
79150a49
JD
271 ret = lttng_add_interruptible_to_ctx(&lttng_static_ctx);
272 if (ret) {
273 printk(KERN_WARNING "Cannot add context lttng_add_interruptible_to_ctx");
274 }
275 ret = lttng_add_need_reschedule_to_ctx(&lttng_static_ctx);
276 if (ret) {
277 printk(KERN_WARNING "Cannot add context lttng_add_need_reschedule_to_ctx");
278 }
279#if defined(CONFIG_PREEMPT_RT_FULL) || defined(CONFIG_PREEMPT)
280 ret = lttng_add_preemptible_to_ctx(&lttng_static_ctx);
281 if (ret != -ENOSYS) {
282 printk(KERN_WARNING "Cannot add context lttng_add_preemptible_to_ctx");
283 }
284#endif
285#ifdef CONFIG_PREEMPT_RT_FULL
286 ret = lttng_add_migratable_to_ctx(&lttng_static_ctx);
287 if (ret != -ENOSYS) {
288 printk(KERN_WARNING "Cannot add context lttng_add_migratable_to_ctx");
289 }
290#endif
f127e61e 291 /* TODO: perf counters for filtering */
07dfc1d0
MD
292 return 0;
293}
294
295void lttng_context_exit(void)
296{
297 lttng_destroy_context(lttng_static_ctx);
298 lttng_static_ctx = NULL;
299}
This page took 0.042296 seconds and 4 git commands to generate.