Blame view
kernel/tracepoint.c
13.3 KB
97e1c18e8 tracing: Kernel T... |
1 |
/* |
de7b29739 tracepoint: Use s... |
2 |
* Copyright (C) 2008-2014 Mathieu Desnoyers |
97e1c18e8 tracing: Kernel T... |
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <linux/module.h> #include <linux/mutex.h> #include <linux/types.h> #include <linux/jhash.h> #include <linux/list.h> #include <linux/rcupdate.h> #include <linux/tracepoint.h> #include <linux/err.h> #include <linux/slab.h> |
a871bd33a tracing: Add sysc... |
27 |
#include <linux/sched.h> |
c5905afb0 static keys: Intr... |
28 |
#include <linux/static_key.h> |
97e1c18e8 tracing: Kernel T... |
29 |
|
654986462 tracepoints: Fix ... |
30 31 |
extern struct tracepoint * const __start___tracepoints_ptrs[]; extern struct tracepoint * const __stop___tracepoints_ptrs[]; |
97e1c18e8 tracing: Kernel T... |
32 33 34 |
/* Set to 1 to enable tracepoint debug output */ static const int tracepoint_debug; |
de7b29739 tracepoint: Use s... |
35 |
#ifdef CONFIG_MODULES |
97e1c18e8 tracing: Kernel T... |
36 |
/* |
de7b29739 tracepoint: Use s... |
37 |
* Tracepoint module list mutex protects the local module list. |
97e1c18e8 tracing: Kernel T... |
38 |
*/ |
de7b29739 tracepoint: Use s... |
39 |
static DEFINE_MUTEX(tracepoint_module_list_mutex); |
97e1c18e8 tracing: Kernel T... |
40 |
|
de7b29739 tracepoint: Use s... |
41 |
/* Local list of struct tp_module */ |
b75ef8b44 Tracepoint: Disso... |
42 43 |
static LIST_HEAD(tracepoint_module_list); #endif /* CONFIG_MODULES */ |
97e1c18e8 tracing: Kernel T... |
44 |
/* |
de7b29739 tracepoint: Use s... |
45 46 |
* tracepoints_mutex protects the builtin and module tracepoints. * tracepoints_mutex nests inside tracepoint_module_list_mutex. |
97e1c18e8 tracing: Kernel T... |
47 |
*/ |
de7b29739 tracepoint: Use s... |
48 |
static DEFINE_MUTEX(tracepoints_mutex); |
97e1c18e8 tracing: Kernel T... |
49 50 51 |
/* * Note about RCU : |
fd589a8f0 trivial: fix typo... |
52 |
* It is used to delay the free of multiple probes array until a quiescent |
97e1c18e8 tracing: Kernel T... |
53 |
* state is reached. |
97e1c18e8 tracing: Kernel T... |
54 |
*/ |
19dba33c4 tracepoint: simpl... |
55 |
struct tp_probes { |
0dea6d526 tracepoint: Remov... |
56 |
struct rcu_head rcu; |
38516ab59 tracing: Let trac... |
57 |
struct tracepoint_func probes[0]; |
19dba33c4 tracepoint: simpl... |
58 |
}; |
97e1c18e8 tracing: Kernel T... |
59 |
|
19dba33c4 tracepoint: simpl... |
60 |
static inline void *allocate_probes(int count) |
97e1c18e8 tracing: Kernel T... |
61 |
{ |
38516ab59 tracing: Let trac... |
62 |
struct tp_probes *p = kmalloc(count * sizeof(struct tracepoint_func) |
19dba33c4 tracepoint: simpl... |
63 64 |
+ sizeof(struct tp_probes), GFP_KERNEL); return p == NULL ? NULL : p->probes; |
97e1c18e8 tracing: Kernel T... |
65 |
} |
19dba33c4 tracepoint: simpl... |
66 |
static void rcu_free_old_probes(struct rcu_head *head) |
97e1c18e8 tracing: Kernel T... |
67 |
{ |
0dea6d526 tracepoint: Remov... |
68 |
kfree(container_of(head, struct tp_probes, rcu)); |
19dba33c4 tracepoint: simpl... |
69 |
} |
38516ab59 tracing: Let trac... |
70 |
static inline void release_probes(struct tracepoint_func *old) |
19dba33c4 tracepoint: simpl... |
71 72 73 74 |
{ if (old) { struct tp_probes *tp_probes = container_of(old, struct tp_probes, probes[0]); |
0dea6d526 tracepoint: Remov... |
75 |
call_rcu_sched(&tp_probes->rcu, rcu_free_old_probes); |
19dba33c4 tracepoint: simpl... |
76 |
} |
97e1c18e8 tracing: Kernel T... |
77 |
} |
de7b29739 tracepoint: Use s... |
78 |
static void debug_print_probes(struct tracepoint_func *funcs) |
97e1c18e8 tracing: Kernel T... |
79 80 |
{ int i; |
de7b29739 tracepoint: Use s... |
81 |
if (!tracepoint_debug || !funcs) |
97e1c18e8 tracing: Kernel T... |
82 |
return; |
de7b29739 tracepoint: Use s... |
83 84 85 |
for (i = 0; funcs[i].func; i++) printk(KERN_DEBUG "Probe %d : %p ", i, funcs[i].func); |
97e1c18e8 tracing: Kernel T... |
86 |
} |
de7b29739 tracepoint: Use s... |
87 88 |
static struct tracepoint_func *func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func) |
97e1c18e8 tracing: Kernel T... |
89 90 |
{ int nr_probes = 0; |
38516ab59 tracing: Let trac... |
91 |
struct tracepoint_func *old, *new; |
97e1c18e8 tracing: Kernel T... |
92 |
|
de7b29739 tracepoint: Use s... |
93 |
if (WARN_ON(!tp_func->func)) |
4c69e6ea4 tracepoints: Prev... |
94 |
return ERR_PTR(-EINVAL); |
97e1c18e8 tracing: Kernel T... |
95 |
|
de7b29739 tracepoint: Use s... |
96 97 |
debug_print_probes(*funcs); old = *funcs; |
97e1c18e8 tracing: Kernel T... |
98 99 |
if (old) { /* (N -> N+1), (N != 0, 1) probes */ |
38516ab59 tracing: Let trac... |
100 |
for (nr_probes = 0; old[nr_probes].func; nr_probes++) |
de7b29739 tracepoint: Use s... |
101 102 |
if (old[nr_probes].func == tp_func->func && old[nr_probes].data == tp_func->data) |
97e1c18e8 tracing: Kernel T... |
103 104 105 |
return ERR_PTR(-EEXIST); } /* + 2 : one for new probe, one for NULL func */ |
19dba33c4 tracepoint: simpl... |
106 |
new = allocate_probes(nr_probes + 2); |
97e1c18e8 tracing: Kernel T... |
107 108 109 |
if (new == NULL) return ERR_PTR(-ENOMEM); if (old) |
38516ab59 tracing: Let trac... |
110 |
memcpy(new, old, nr_probes * sizeof(struct tracepoint_func)); |
de7b29739 tracepoint: Use s... |
111 |
new[nr_probes] = *tp_func; |
38516ab59 tracing: Let trac... |
112 |
new[nr_probes + 1].func = NULL; |
de7b29739 tracepoint: Use s... |
113 114 |
*funcs = new; debug_print_probes(*funcs); |
97e1c18e8 tracing: Kernel T... |
115 116 |
return old; } |
de7b29739 tracepoint: Use s... |
117 118 |
static void *func_remove(struct tracepoint_func **funcs, struct tracepoint_func *tp_func) |
97e1c18e8 tracing: Kernel T... |
119 120 |
{ int nr_probes = 0, nr_del = 0, i; |
38516ab59 tracing: Let trac... |
121 |
struct tracepoint_func *old, *new; |
97e1c18e8 tracing: Kernel T... |
122 |
|
de7b29739 tracepoint: Use s... |
123 |
old = *funcs; |
97e1c18e8 tracing: Kernel T... |
124 |
|
f66af459a tracepoint: check... |
125 |
if (!old) |
19dba33c4 tracepoint: simpl... |
126 |
return ERR_PTR(-ENOENT); |
f66af459a tracepoint: check... |
127 |
|
de7b29739 tracepoint: Use s... |
128 |
debug_print_probes(*funcs); |
97e1c18e8 tracing: Kernel T... |
129 |
/* (N -> M), (N > 1, M >= 0) probes */ |
de7b29739 tracepoint: Use s... |
130 |
if (tp_func->func) { |
4c69e6ea4 tracepoints: Prev... |
131 |
for (nr_probes = 0; old[nr_probes].func; nr_probes++) { |
de7b29739 tracepoint: Use s... |
132 133 |
if (old[nr_probes].func == tp_func->func && old[nr_probes].data == tp_func->data) |
4c69e6ea4 tracepoints: Prev... |
134 135 |
nr_del++; } |
97e1c18e8 tracing: Kernel T... |
136 |
} |
4c69e6ea4 tracepoints: Prev... |
137 138 139 140 |
/* * If probe is NULL, then nr_probes = nr_del = 0, and then the * entire entry will be removed. */ |
97e1c18e8 tracing: Kernel T... |
141 142 |
if (nr_probes - nr_del == 0) { /* N -> 0, (N > 1) */ |
de7b29739 tracepoint: Use s... |
143 144 |
*funcs = NULL; debug_print_probes(*funcs); |
97e1c18e8 tracing: Kernel T... |
145 146 147 148 149 |
return old; } else { int j = 0; /* N -> M, (N > 1, M > 0) */ /* + 1 for NULL */ |
19dba33c4 tracepoint: simpl... |
150 |
new = allocate_probes(nr_probes - nr_del + 1); |
97e1c18e8 tracing: Kernel T... |
151 152 |
if (new == NULL) return ERR_PTR(-ENOMEM); |
38516ab59 tracing: Let trac... |
153 |
for (i = 0; old[i].func; i++) |
de7b29739 tracepoint: Use s... |
154 155 |
if (old[i].func != tp_func->func || old[i].data != tp_func->data) |
97e1c18e8 tracing: Kernel T... |
156 |
new[j++] = old[i]; |
38516ab59 tracing: Let trac... |
157 |
new[nr_probes - nr_del].func = NULL; |
de7b29739 tracepoint: Use s... |
158 |
*funcs = new; |
97e1c18e8 tracing: Kernel T... |
159 |
} |
de7b29739 tracepoint: Use s... |
160 |
debug_print_probes(*funcs); |
97e1c18e8 tracing: Kernel T... |
161 162 163 164 |
return old; } /* |
de7b29739 tracepoint: Use s... |
165 |
* Add the probe function to a tracepoint. |
97e1c18e8 tracing: Kernel T... |
166 |
*/ |
de7b29739 tracepoint: Use s... |
167 168 |
static int tracepoint_add_func(struct tracepoint *tp, struct tracepoint_func *func) |
97e1c18e8 tracing: Kernel T... |
169 |
{ |
de7b29739 tracepoint: Use s... |
170 |
struct tracepoint_func *old, *tp_funcs; |
97e1c18e8 tracing: Kernel T... |
171 |
|
de7b29739 tracepoint: Use s... |
172 173 |
if (tp->regfunc && !static_key_enabled(&tp->key)) tp->regfunc(); |
97e1c18e8 tracing: Kernel T... |
174 |
|
b725dfea2 tracepoint: Fix s... |
175 176 |
tp_funcs = rcu_dereference_protected(tp->funcs, lockdep_is_held(&tracepoints_mutex)); |
de7b29739 tracepoint: Use s... |
177 178 179 180 181 |
old = func_add(&tp_funcs, func); if (IS_ERR(old)) { WARN_ON_ONCE(1); return PTR_ERR(old); } |
974198758 tracing: Move tra... |
182 |
|
97e1c18e8 tracing: Kernel T... |
183 184 185 186 187 188 189 |
/* * rcu_assign_pointer has a smp_wmb() which makes sure that the new * probe callbacks array is consistent before setting a pointer to it. * This array is referenced by __DO_TRACE from * include/linux/tracepoints.h. A matching smp_read_barrier_depends() * is used. */ |
de7b29739 tracepoint: Use s... |
190 191 192 |
rcu_assign_pointer(tp->funcs, tp_funcs); if (!static_key_enabled(&tp->key)) static_key_slow_inc(&tp->key); |
8058bd0fa tracepoint: Fix u... |
193 |
release_probes(old); |
de7b29739 tracepoint: Use s... |
194 |
return 0; |
97e1c18e8 tracing: Kernel T... |
195 196 197 |
} /* |
de7b29739 tracepoint: Use s... |
198 |
* Remove a probe function from a tracepoint. |
97e1c18e8 tracing: Kernel T... |
199 200 201 202 |
* Note: only waiting an RCU period after setting elem->call to the empty * function insures that the original callback is not used anymore. This insured * by preempt_disable around the call site. */ |
de7b29739 tracepoint: Use s... |
203 204 |
static int tracepoint_remove_func(struct tracepoint *tp, struct tracepoint_func *func) |
97e1c18e8 tracing: Kernel T... |
205 |
{ |
de7b29739 tracepoint: Use s... |
206 |
struct tracepoint_func *old, *tp_funcs; |
97e1c18e8 tracing: Kernel T... |
207 |
|
b725dfea2 tracepoint: Fix s... |
208 209 |
tp_funcs = rcu_dereference_protected(tp->funcs, lockdep_is_held(&tracepoints_mutex)); |
de7b29739 tracepoint: Use s... |
210 211 212 213 |
old = func_remove(&tp_funcs, func); if (IS_ERR(old)) { WARN_ON_ONCE(1); return PTR_ERR(old); |
97e1c18e8 tracing: Kernel T... |
214 |
} |
b75ef8b44 Tracepoint: Disso... |
215 |
|
de7b29739 tracepoint: Use s... |
216 217 218 219 |
if (!tp_funcs) { /* Removed last function */ if (tp->unregfunc && static_key_enabled(&tp->key)) tp->unregfunc(); |
b75ef8b44 Tracepoint: Disso... |
220 |
|
de7b29739 tracepoint: Use s... |
221 222 |
if (static_key_enabled(&tp->key)) static_key_slow_dec(&tp->key); |
127cafbb2 tracepoint: intro... |
223 |
} |
de7b29739 tracepoint: Use s... |
224 |
rcu_assign_pointer(tp->funcs, tp_funcs); |
8058bd0fa tracepoint: Fix u... |
225 |
release_probes(old); |
de7b29739 tracepoint: Use s... |
226 |
return 0; |
127cafbb2 tracepoint: intro... |
227 |
} |
97e1c18e8 tracing: Kernel T... |
228 229 |
/** * tracepoint_probe_register - Connect a probe to a tracepoint |
de7b29739 tracepoint: Use s... |
230 |
* @tp: tracepoint |
97e1c18e8 tracing: Kernel T... |
231 |
* @probe: probe handler |
cac92ba74 kernel/tracepoint... |
232 |
* @data: tracepoint data |
97e1c18e8 tracing: Kernel T... |
233 |
* |
de7b29739 tracepoint: Use s... |
234 235 236 237 238 |
* Returns 0 if ok, error value on error. * Note: if @tp is within a module, the caller is responsible for * unregistering the probe before the module is gone. This can be * performed either with a tracepoint module going notifier, or from * within module exit functions. |
97e1c18e8 tracing: Kernel T... |
239 |
*/ |
de7b29739 tracepoint: Use s... |
240 |
int tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data) |
97e1c18e8 tracing: Kernel T... |
241 |
{ |
de7b29739 tracepoint: Use s... |
242 243 |
struct tracepoint_func tp_func; int ret; |
97e1c18e8 tracing: Kernel T... |
244 245 |
mutex_lock(&tracepoints_mutex); |
de7b29739 tracepoint: Use s... |
246 247 248 |
tp_func.func = probe; tp_func.data = data; ret = tracepoint_add_func(tp, &tp_func); |
b75ef8b44 Tracepoint: Disso... |
249 |
mutex_unlock(&tracepoints_mutex); |
b196e2b9e tracing: Warn if ... |
250 |
return ret; |
97e1c18e8 tracing: Kernel T... |
251 252 253 254 255 |
} EXPORT_SYMBOL_GPL(tracepoint_probe_register); /** * tracepoint_probe_unregister - Disconnect a probe from a tracepoint |
de7b29739 tracepoint: Use s... |
256 |
* @tp: tracepoint |
97e1c18e8 tracing: Kernel T... |
257 |
* @probe: probe function pointer |
cac92ba74 kernel/tracepoint... |
258 |
* @data: tracepoint data |
97e1c18e8 tracing: Kernel T... |
259 |
* |
de7b29739 tracepoint: Use s... |
260 |
* Returns 0 if ok, error value on error. |
97e1c18e8 tracing: Kernel T... |
261 |
*/ |
de7b29739 tracepoint: Use s... |
262 |
int tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data) |
97e1c18e8 tracing: Kernel T... |
263 |
{ |
de7b29739 tracepoint: Use s... |
264 265 |
struct tracepoint_func tp_func; int ret; |
97e1c18e8 tracing: Kernel T... |
266 267 |
mutex_lock(&tracepoints_mutex); |
de7b29739 tracepoint: Use s... |
268 269 270 |
tp_func.func = probe; tp_func.data = data; ret = tracepoint_remove_func(tp, &tp_func); |
b75ef8b44 Tracepoint: Disso... |
271 |
mutex_unlock(&tracepoints_mutex); |
de7b29739 tracepoint: Use s... |
272 |
return ret; |
97e1c18e8 tracing: Kernel T... |
273 274 |
} EXPORT_SYMBOL_GPL(tracepoint_probe_unregister); |
227a83756 markers/tracpoint... |
275 |
#ifdef CONFIG_MODULES |
45ab2813d tracing: Do not a... |
276 277 |
bool trace_module_has_bad_taint(struct module *mod) { |
66cc69e34 Fix: module signa... |
278 279 |
return mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP) | (1 << TAINT_UNSIGNED_MODULE)); |
45ab2813d tracing: Do not a... |
280 |
} |
de7b29739 tracepoint: Use s... |
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
static BLOCKING_NOTIFIER_HEAD(tracepoint_notify_list); /** * register_tracepoint_notifier - register tracepoint coming/going notifier * @nb: notifier block * * Notifiers registered with this function are called on module * coming/going with the tracepoint_module_list_mutex held. * The notifier block callback should expect a "struct tp_module" data * pointer. */ int register_tracepoint_module_notifier(struct notifier_block *nb) { struct tp_module *tp_mod; int ret; mutex_lock(&tracepoint_module_list_mutex); ret = blocking_notifier_chain_register(&tracepoint_notify_list, nb); if (ret) goto end; list_for_each_entry(tp_mod, &tracepoint_module_list, list) (void) nb->notifier_call(nb, MODULE_STATE_COMING, tp_mod); end: mutex_unlock(&tracepoint_module_list_mutex); return ret; } EXPORT_SYMBOL_GPL(register_tracepoint_module_notifier); /** * unregister_tracepoint_notifier - unregister tracepoint coming/going notifier * @nb: notifier block * * The notifier block callback should expect a "struct tp_module" data * pointer. */ int unregister_tracepoint_module_notifier(struct notifier_block *nb) { struct tp_module *tp_mod; int ret; mutex_lock(&tracepoint_module_list_mutex); ret = blocking_notifier_chain_unregister(&tracepoint_notify_list, nb); if (ret) goto end; list_for_each_entry(tp_mod, &tracepoint_module_list, list) (void) nb->notifier_call(nb, MODULE_STATE_GOING, tp_mod); end: mutex_unlock(&tracepoint_module_list_mutex); return ret; } EXPORT_SYMBOL_GPL(unregister_tracepoint_module_notifier); /* * Ensure the tracer unregistered the module's probes before the module * teardown is performed. Prevents leaks of probe and data pointers. */ static void tp_module_going_check_quiescent(struct tracepoint * const *begin, struct tracepoint * const *end) { struct tracepoint * const *iter; if (!begin) return; for (iter = begin; iter < end; iter++) WARN_ON_ONCE((*iter)->funcs); } |
b75ef8b44 Tracepoint: Disso... |
348 349 |
static int tracepoint_module_coming(struct module *mod) { |
0dea6d526 tracepoint: Remov... |
350 |
struct tp_module *tp_mod; |
b75ef8b44 Tracepoint: Disso... |
351 |
int ret = 0; |
7dec935a3 tracepoint: Do no... |
352 353 |
if (!mod->num_tracepoints) return 0; |
b75ef8b44 Tracepoint: Disso... |
354 |
/* |
c10076c43 tracepoints/modul... |
355 356 |
* We skip modules that taint the kernel, especially those with different * module headers (for forced load), to make sure we don't cause a crash. |
66cc69e34 Fix: module signa... |
357 |
* Staging, out-of-tree, and unsigned GPL modules are fine. |
b75ef8b44 Tracepoint: Disso... |
358 |
*/ |
45ab2813d tracing: Do not a... |
359 |
if (trace_module_has_bad_taint(mod)) |
b75ef8b44 Tracepoint: Disso... |
360 |
return 0; |
de7b29739 tracepoint: Use s... |
361 |
mutex_lock(&tracepoint_module_list_mutex); |
b75ef8b44 Tracepoint: Disso... |
362 363 364 365 366 |
tp_mod = kmalloc(sizeof(struct tp_module), GFP_KERNEL); if (!tp_mod) { ret = -ENOMEM; goto end; } |
eb7d035c5 tracepoint: Simpl... |
367 |
tp_mod->mod = mod; |
0dea6d526 tracepoint: Remov... |
368 |
list_add_tail(&tp_mod->list, &tracepoint_module_list); |
de7b29739 tracepoint: Use s... |
369 370 |
blocking_notifier_call_chain(&tracepoint_notify_list, MODULE_STATE_COMING, tp_mod); |
b75ef8b44 Tracepoint: Disso... |
371 |
end: |
de7b29739 tracepoint: Use s... |
372 |
mutex_unlock(&tracepoint_module_list_mutex); |
b75ef8b44 Tracepoint: Disso... |
373 374 |
return ret; } |
de7b29739 tracepoint: Use s... |
375 |
static void tracepoint_module_going(struct module *mod) |
b75ef8b44 Tracepoint: Disso... |
376 |
{ |
de7b29739 tracepoint: Use s... |
377 |
struct tp_module *tp_mod; |
b75ef8b44 Tracepoint: Disso... |
378 |
|
7dec935a3 tracepoint: Do no... |
379 |
if (!mod->num_tracepoints) |
de7b29739 tracepoint: Use s... |
380 |
return; |
7dec935a3 tracepoint: Do no... |
381 |
|
de7b29739 tracepoint: Use s... |
382 383 |
mutex_lock(&tracepoint_module_list_mutex); list_for_each_entry(tp_mod, &tracepoint_module_list, list) { |
eb7d035c5 tracepoint: Simpl... |
384 |
if (tp_mod->mod == mod) { |
de7b29739 tracepoint: Use s... |
385 386 387 388 389 390 391 392 393 394 |
blocking_notifier_call_chain(&tracepoint_notify_list, MODULE_STATE_GOING, tp_mod); list_del(&tp_mod->list); kfree(tp_mod); /* * Called the going notifier before checking for * quiescence. */ tp_module_going_check_quiescent(mod->tracepoints_ptrs, mod->tracepoints_ptrs + mod->num_tracepoints); |
b75ef8b44 Tracepoint: Disso... |
395 396 397 398 399 400 401 402 403 |
break; } } /* * In the case of modules that were tainted at "coming", we'll simply * walk through the list without finding it. We cannot use the "tainted" * flag on "going", in case a module taints the kernel only after being * loaded. */ |
de7b29739 tracepoint: Use s... |
404 |
mutex_unlock(&tracepoint_module_list_mutex); |
b75ef8b44 Tracepoint: Disso... |
405 |
} |
227a83756 markers/tracpoint... |
406 |
|
de7b29739 tracepoint: Use s... |
407 408 |
static int tracepoint_module_notify(struct notifier_block *self, unsigned long val, void *data) |
32f857427 tracepoints: use ... |
409 410 |
{ struct module *mod = data; |
b75ef8b44 Tracepoint: Disso... |
411 |
int ret = 0; |
32f857427 tracepoints: use ... |
412 413 414 |
switch (val) { case MODULE_STATE_COMING: |
b75ef8b44 Tracepoint: Disso... |
415 416 417 418 |
ret = tracepoint_module_coming(mod); break; case MODULE_STATE_LIVE: break; |
32f857427 tracepoints: use ... |
419 |
case MODULE_STATE_GOING: |
de7b29739 tracepoint: Use s... |
420 421 422 |
tracepoint_module_going(mod); break; case MODULE_STATE_UNFORMED: |
32f857427 tracepoints: use ... |
423 424 |
break; } |
b75ef8b44 Tracepoint: Disso... |
425 |
return ret; |
32f857427 tracepoints: use ... |
426 |
} |
de7b29739 tracepoint: Use s... |
427 |
static struct notifier_block tracepoint_module_nb = { |
32f857427 tracepoints: use ... |
428 429 430 |
.notifier_call = tracepoint_module_notify, .priority = 0, }; |
de7b29739 tracepoint: Use s... |
431 |
static __init int init_tracepoints(void) |
32f857427 tracepoints: use ... |
432 |
{ |
de7b29739 tracepoint: Use s... |
433 434 435 |
int ret; ret = register_module_notifier(&tracepoint_module_nb); |
eb7d035c5 tracepoint: Simpl... |
436 |
if (ret) |
de7b29739 tracepoint: Use s... |
437 438 |
pr_warning("Failed to register tracepoint module enter notifier "); |
eb7d035c5 tracepoint: Simpl... |
439 |
|
de7b29739 tracepoint: Use s... |
440 |
return ret; |
32f857427 tracepoints: use ... |
441 442 |
} __initcall(init_tracepoints); |
227a83756 markers/tracpoint... |
443 |
#endif /* CONFIG_MODULES */ |
a871bd33a tracing: Add sysc... |
444 |
|
de7b29739 tracepoint: Use s... |
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 |
static void for_each_tracepoint_range(struct tracepoint * const *begin, struct tracepoint * const *end, void (*fct)(struct tracepoint *tp, void *priv), void *priv) { struct tracepoint * const *iter; if (!begin) return; for (iter = begin; iter < end; iter++) fct(*iter, priv); } /** * for_each_kernel_tracepoint - iteration on all kernel tracepoints * @fct: callback * @priv: private data */ void for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv), void *priv) { for_each_tracepoint_range(__start___tracepoints_ptrs, __stop___tracepoints_ptrs, fct, priv); } EXPORT_SYMBOL_GPL(for_each_kernel_tracepoint); |
3d27d8cb3 tracing: Make sys... |
470 |
#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS |
60d970c25 tracing: Fix sysc... |
471 |
|
974198758 tracing: Move tra... |
472 |
/* NB: reg/unreg are called while guarded with the tracepoints_mutex */ |
a871bd33a tracing: Add sysc... |
473 474 475 476 |
static int sys_tracepoint_refcount; void syscall_regfunc(void) { |
8063e41d2 tracing: Change s... |
477 |
struct task_struct *p, *t; |
a871bd33a tracing: Add sysc... |
478 |
|
a871bd33a tracing: Add sysc... |
479 |
if (!sys_tracepoint_refcount) { |
8063e41d2 tracing: Change s... |
480 481 |
read_lock(&tasklist_lock); for_each_process_thread(p, t) { |
ea73c79e3 tracing: syscall_... |
482 |
set_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT); |
8063e41d2 tracing: Change s... |
483 484 |
} read_unlock(&tasklist_lock); |
a871bd33a tracing: Add sysc... |
485 486 |
} sys_tracepoint_refcount++; |
a871bd33a tracing: Add sysc... |
487 488 489 490 |
} void syscall_unregfunc(void) { |
8063e41d2 tracing: Change s... |
491 |
struct task_struct *p, *t; |
a871bd33a tracing: Add sysc... |
492 |
|
a871bd33a tracing: Add sysc... |
493 494 |
sys_tracepoint_refcount--; if (!sys_tracepoint_refcount) { |
8063e41d2 tracing: Change s... |
495 496 |
read_lock(&tasklist_lock); for_each_process_thread(p, t) { |
667000011 tracing: Rename F... |
497 |
clear_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT); |
8063e41d2 tracing: Change s... |
498 499 |
} read_unlock(&tasklist_lock); |
a871bd33a tracing: Add sysc... |
500 |
} |
a871bd33a tracing: Add sysc... |
501 |
} |
60d970c25 tracing: Fix sysc... |
502 |
#endif |