Version 2.8.7
[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>
241ae9a8
MD
27#include <wrapper/vmalloc.h> /* for wrapper_vmalloc_sync_all() */
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;
0451bcec 59 const char *subname;
07dfc1d0
MD
60
61 if (!ctx)
62 return -1;
0451bcec
MD
63 if (strncmp(name, "$ctx.", strlen("$ctx.")) == 0) {
64 subname = name + strlen("$ctx.");
65 } else {
66 subname = name;
67 }
07dfc1d0
MD
68 for (i = 0; i < ctx->nr_fields; i++) {
69 /* Skip allocated (but non-initialized) contexts */
70 if (!ctx->fields[i].event_field.name)
71 continue;
0451bcec 72 if (!strcmp(ctx->fields[i].event_field.name, subname))
07dfc1d0
MD
73 return i;
74 }
75 return -1;
76}
77EXPORT_SYMBOL_GPL(lttng_get_context_index);
78
2001023e
MD
79/*
80 * Note: as we append context information, the pointer location may change.
81 */
2dccf128
MD
82struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p)
83{
84 struct lttng_ctx_field *field;
85 struct lttng_ctx *ctx;
86
87 if (!*ctx_p) {
88 *ctx_p = kzalloc(sizeof(struct lttng_ctx), GFP_KERNEL);
89 if (!*ctx_p)
90 return NULL;
a9dd15da 91 (*ctx_p)->largest_align = 1;
2dccf128
MD
92 }
93 ctx = *ctx_p;
94 if (ctx->nr_fields + 1 > ctx->allocated_fields) {
95 struct lttng_ctx_field *new_fields;
96
0f034e0f 97 ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
2dccf128
MD
98 new_fields = kzalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field), GFP_KERNEL);
99 if (!new_fields)
100 return NULL;
101 if (ctx->fields)
77aefe99 102 memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
2dccf128
MD
103 kfree(ctx->fields);
104 ctx->fields = new_fields;
105 }
106 field = &ctx->fields[ctx->nr_fields];
107 ctx->nr_fields++;
108 return field;
109}
110EXPORT_SYMBOL_GPL(lttng_append_context);
111
a9dd15da
MD
112/*
113 * lttng_context_update() should be called at least once between context
114 * modification and trace start.
115 */
116void lttng_context_update(struct lttng_ctx *ctx)
117{
118 int i;
119 size_t largest_align = 8; /* in bits */
120
121 for (i = 0; i < ctx->nr_fields; i++) {
122 struct lttng_type *type;
123 size_t field_align = 8;
124
125 type = &ctx->fields[i].event_field.type;
126 switch (type->atype) {
127 case atype_integer:
128 field_align = type->u.basic.integer.alignment;
129 break;
130 case atype_array:
131 {
132 struct lttng_basic_type *btype;
133
134 btype = &type->u.array.elem_type;
135 switch (btype->atype) {
136 case atype_integer:
137 field_align = btype->u.basic.integer.alignment;
138 break;
139 case atype_string:
140 break;
141
142 case atype_array:
143 case atype_sequence:
144 default:
145 WARN_ON_ONCE(1);
146 break;
147 }
148 break;
149 }
150 case atype_sequence:
151 {
152 struct lttng_basic_type *btype;
153
154 btype = &type->u.sequence.length_type;
155 switch (btype->atype) {
156 case atype_integer:
157 field_align = btype->u.basic.integer.alignment;
158 break;
159
160 case atype_string:
161 case atype_array:
162 case atype_sequence:
163 default:
164 WARN_ON_ONCE(1);
165 break;
166 }
167
168 btype = &type->u.sequence.elem_type;
169 switch (btype->atype) {
170 case atype_integer:
171 field_align = max_t(size_t,
172 field_align,
173 btype->u.basic.integer.alignment);
174 break;
175
176 case atype_string:
177 break;
178
179 case atype_array:
180 case atype_sequence:
181 default:
182 WARN_ON_ONCE(1);
183 break;
184 }
185 break;
186 }
187 case atype_string:
188 break;
189
190 case atype_enum:
191 default:
192 WARN_ON_ONCE(1);
193 break;
194 }
195 largest_align = max_t(size_t, largest_align, field_align);
196 }
197 ctx->largest_align = largest_align >> 3; /* bits to bytes */
198}
199
4cae220c
MD
200/*
201 * Remove last context field.
202 */
8289661d
MD
203void lttng_remove_context_field(struct lttng_ctx **ctx_p,
204 struct lttng_ctx_field *field)
205{
206 struct lttng_ctx *ctx;
207
208 ctx = *ctx_p;
209 ctx->nr_fields--;
4cae220c 210 WARN_ON_ONCE(&ctx->fields[ctx->nr_fields] != field);
8289661d
MD
211 memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field));
212}
213EXPORT_SYMBOL_GPL(lttng_remove_context_field);
214
2dccf128
MD
215void lttng_destroy_context(struct lttng_ctx *ctx)
216{
217 int i;
218
8070f5c0
MD
219 if (!ctx)
220 return;
9e7e4892
MD
221 for (i = 0; i < ctx->nr_fields; i++) {
222 if (ctx->fields[i].destroy)
223 ctx->fields[i].destroy(&ctx->fields[i]);
224 }
2dccf128
MD
225 kfree(ctx->fields);
226 kfree(ctx);
227}
07dfc1d0
MD
228
229int lttng_context_init(void)
230{
231 int ret;
232
f127e61e
MD
233 ret = lttng_add_hostname_to_ctx(&lttng_static_ctx);
234 if (ret) {
38c4a82c 235 printk(KERN_WARNING "Cannot add context lttng_add_hostname_to_ctx");
f127e61e
MD
236 }
237 ret = lttng_add_nice_to_ctx(&lttng_static_ctx);
07dfc1d0 238 if (ret) {
38c4a82c 239 printk(KERN_WARNING "Cannot add context lttng_add_nice_to_ctx");
07dfc1d0 240 }
07dfc1d0
MD
241 ret = lttng_add_pid_to_ctx(&lttng_static_ctx);
242 if (ret) {
38c4a82c 243 printk(KERN_WARNING "Cannot add context lttng_add_pid_to_ctx");
07dfc1d0 244 }
f127e61e 245 ret = lttng_add_ppid_to_ctx(&lttng_static_ctx);
07dfc1d0 246 if (ret) {
38c4a82c 247 printk(KERN_WARNING "Cannot add context lttng_add_ppid_to_ctx");
07dfc1d0
MD
248 }
249 ret = lttng_add_prio_to_ctx(&lttng_static_ctx);
250 if (ret) {
38c4a82c 251 printk(KERN_WARNING "Cannot add context lttng_add_prio_to_ctx");
07dfc1d0 252 }
f127e61e 253 ret = lttng_add_procname_to_ctx(&lttng_static_ctx);
07dfc1d0 254 if (ret) {
38c4a82c 255 printk(KERN_WARNING "Cannot add context lttng_add_procname_to_ctx");
07dfc1d0
MD
256 }
257 ret = lttng_add_tid_to_ctx(&lttng_static_ctx);
258 if (ret) {
38c4a82c 259 printk(KERN_WARNING "Cannot add context lttng_add_tid_to_ctx");
07dfc1d0 260 }
f127e61e 261 ret = lttng_add_vppid_to_ctx(&lttng_static_ctx);
07dfc1d0 262 if (ret) {
38c4a82c 263 printk(KERN_WARNING "Cannot add context lttng_add_vppid_to_ctx");
07dfc1d0 264 }
f127e61e 265 ret = lttng_add_vtid_to_ctx(&lttng_static_ctx);
07dfc1d0 266 if (ret) {
38c4a82c 267 printk(KERN_WARNING "Cannot add context lttng_add_vtid_to_ctx");
07dfc1d0 268 }
f127e61e 269 ret = lttng_add_vpid_to_ctx(&lttng_static_ctx);
07dfc1d0 270 if (ret) {
38c4a82c 271 printk(KERN_WARNING "Cannot add context lttng_add_vpid_to_ctx");
07dfc1d0 272 }
b3699d90
MD
273 ret = lttng_add_cpu_id_to_ctx(&lttng_static_ctx);
274 if (ret) {
275 printk(KERN_WARNING "Cannot add context lttng_add_cpu_id_to_ctx");
276 }
79150a49
JD
277 ret = lttng_add_interruptible_to_ctx(&lttng_static_ctx);
278 if (ret) {
279 printk(KERN_WARNING "Cannot add context lttng_add_interruptible_to_ctx");
280 }
281 ret = lttng_add_need_reschedule_to_ctx(&lttng_static_ctx);
282 if (ret) {
283 printk(KERN_WARNING "Cannot add context lttng_add_need_reschedule_to_ctx");
284 }
79150a49 285 ret = lttng_add_preemptible_to_ctx(&lttng_static_ctx);
26e3ab8f 286 if (ret && ret != -ENOSYS) {
79150a49
JD
287 printk(KERN_WARNING "Cannot add context lttng_add_preemptible_to_ctx");
288 }
79150a49 289 ret = lttng_add_migratable_to_ctx(&lttng_static_ctx);
26e3ab8f 290 if (ret && ret != -ENOSYS) {
79150a49
JD
291 printk(KERN_WARNING "Cannot add context lttng_add_migratable_to_ctx");
292 }
f127e61e 293 /* TODO: perf counters for filtering */
07dfc1d0
MD
294 return 0;
295}
296
297void lttng_context_exit(void)
298{
299 lttng_destroy_context(lttng_static_ctx);
300 lttng_static_ctx = NULL;
301}
This page took 0.042766 seconds and 4 git commands to generate.