]> sourceware.org Git - systemtap.git/blob - tapset-timers.cxx
Fixed PR18577 by making 'stap -l **' faster.
[systemtap.git] / tapset-timers.cxx
1 // tapset for timers
2 // Copyright (C) 2005-2011 Red Hat Inc.
3 // Copyright (C) 2005-2007 Intel Corporation.
4 //
5 // This file is part of systemtap, and is free software. You can
6 // redistribute it and/or modify it under the terms of the GNU General
7 // Public License (GPL); either version 2, or (at your option) any
8 // later version.
9
10
11 #include "session.h"
12 #include "tapsets.h"
13 #include "translate.h"
14 #include "util.h"
15
16 #include <cstring>
17 #include <string>
18
19
20 using namespace std;
21 using namespace __gnu_cxx;
22
23
24 static const string TOK_TIMER("timer");
25
26
27 // ------------------------------------------------------------------------
28 // timer derived probes
29 // ------------------------------------------------------------------------
30
31
32 struct timer_derived_probe: public derived_probe
33 {
34 int64_t interval, randomize;
35 bool time_is_msecs; // NB: hrtimers get ms-based probes on modern kernels instead
36 timer_derived_probe (probe* p, probe_point* l,
37 int64_t i, int64_t r, bool ms=false);
38 virtual void join_group (systemtap_session& s);
39
40 // No assertion need be emitted, since this probe is allowed for unprivileged
41 // users.
42 void emit_privilege_assertion (translator_output*) {}
43 void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged (o); }
44 };
45
46
47 struct timer_derived_probe_group: public generic_dpg<timer_derived_probe>
48 {
49 void emit_interval (translator_output* o);
50 public:
51 void emit_module_decls (systemtap_session& s);
52 void emit_module_init (systemtap_session& s);
53 void emit_module_exit (systemtap_session& s);
54 };
55
56
57 timer_derived_probe::timer_derived_probe (probe* p, probe_point* l,
58 int64_t i, int64_t r, bool ms):
59 derived_probe (p, l), interval (i), randomize (r), time_is_msecs(ms)
60 {
61 if (interval <= 0 || interval > 1000000) // make i and r fit into plain ints
62 //TRANSLATORS: 'timer' is the name of a probe point
63 throw SEMANTIC_ERROR (_("invalid interval for jiffies timer"));
64 // randomize = 0 means no randomization
65 if (randomize < 0 || randomize > interval)
66 //TRANSLATORS: 'randomize' is a key word
67 throw SEMANTIC_ERROR (_("invalid randomize for jiffies timer"));
68
69 if (locations.size() != 1)
70 throw SEMANTIC_ERROR (_("only expect one probe point"));
71 // so we don't have to loop over them in the other functions
72 }
73
74
75 void
76 timer_derived_probe::join_group (systemtap_session& s)
77 {
78 if (! s.timer_derived_probes)
79 s.timer_derived_probes = new timer_derived_probe_group ();
80 s.timer_derived_probes->enroll (this);
81 this->group = s.timer_derived_probes;
82 }
83
84
85 void
86 timer_derived_probe_group::emit_interval (translator_output* o)
87 {
88 o->line() << "({";
89 o->newline(1) << "unsigned i = stp->intrv;";
90 o->newline() << "if (stp->rnd != 0)";
91 o->newline(1) << "i += _stp_random_pm(stp->rnd);";
92 o->newline(-1) << "stp->ms ? msecs_to_jiffies(i) : i;";
93 o->newline(-1) << "})";
94 }
95
96
97 void
98 timer_derived_probe_group::emit_module_decls (systemtap_session& s)
99 {
100 if (probes.empty()) return;
101
102 s.op->newline() << "/* ---- timer probes ---- */";
103
104 s.op->newline() << "static struct stap_timer_probe {";
105 s.op->newline(1) << "struct timer_list timer_list;";
106 s.op->newline() << "const struct stap_probe * const probe;";
107 s.op->newline() << "unsigned intrv, ms, rnd;";
108 s.op->newline(-1) << "} stap_timer_probes [" << probes.size() << "] = {";
109 s.op->indent(1);
110 for (unsigned i=0; i < probes.size(); i++)
111 {
112 s.op->newline () << "{";
113 s.op->line() << " .probe=" << common_probe_init (probes[i]) << ",";
114 s.op->line() << " .intrv=" << probes[i]->interval << ",";
115 s.op->line() << " .ms=" << probes[i]->time_is_msecs << ",";
116 s.op->line() << " .rnd=" << probes[i]->randomize;
117 s.op->line() << " },";
118 }
119 s.op->newline(-1) << "};";
120 s.op->newline();
121
122 s.op->newline() << "static void enter_timer_probe (unsigned long val) {";
123 s.op->newline(1) << "struct stap_timer_probe* stp = & stap_timer_probes [val];";
124 s.op->newline() << "if ((atomic_read (session_state()) == STAP_SESSION_STARTING) ||";
125 s.op->newline() << " (atomic_read (session_state()) == STAP_SESSION_RUNNING))";
126 s.op->newline(1) << "mod_timer (& stp->timer_list, jiffies + ";
127 emit_interval (s.op);
128 s.op->line() << ");";
129 s.op->newline(-1) << "{";
130 s.op->indent(1);
131 common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "stp->probe",
132 "stp_probe_type_timer");
133 s.op->newline() << "(*stp->probe->ph) (c);";
134 common_probe_entryfn_epilogue (s, true, otf_safe_context(s));
135 s.op->newline(-1) << "}";
136 s.op->newline(-1) << "}";
137 }
138
139
140 void
141 timer_derived_probe_group::emit_module_init (systemtap_session& s)
142 {
143 if (probes.empty()) return;
144
145 s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
146 s.op->newline(1) << "struct stap_timer_probe* stp = & stap_timer_probes [i];";
147 s.op->newline() << "probe_point = stp->probe->pp;";
148 s.op->newline() << "init_timer (& stp->timer_list);";
149 s.op->newline() << "stp->timer_list.function = & enter_timer_probe;";
150 s.op->newline() << "stp->timer_list.data = i;"; // NB: important!
151 // copy timer renew calculations from above :-(
152 s.op->newline() << "stp->timer_list.expires = jiffies + ";
153 emit_interval (s.op);
154 s.op->line() << ";";
155 s.op->newline() << "add_timer (& stp->timer_list);";
156 // note: no partial failure rollback is needed: add_timer cannot fail.
157 s.op->newline(-1) << "}"; // for loop
158 }
159
160
161 void
162 timer_derived_probe_group::emit_module_exit (systemtap_session& s)
163 {
164 if (probes.empty()) return;
165
166 s.op->newline() << "for (i=0; i<" << probes.size() << "; i++)";
167 s.op->newline(1) << "del_timer_sync (& stap_timer_probes[i].timer_list);";
168 s.op->indent(-1);
169 }
170
171
172
173 // ------------------------------------------------------------------------
174 // hrtimer derived probes
175 // ------------------------------------------------------------------------
176 // This is a new timer interface that provides more flexibility in specifying
177 // intervals, and uses the hrtimer APIs when available for greater precision.
178 // While hrtimers were added in 2.6.16, the API's weren't exported until
179 // 2.6.17, so we must check this kernel version before attempting to use
180 // hrtimers.
181 //
182 // * hrtimer_derived_probe: creates a probe point based on the hrtimer APIs.
183
184
185 struct hrtimer_derived_probe: public derived_probe
186 {
187 // set a (generous) maximum of one day in ns
188 static const int64_t max_ns_interval = 1000000000LL * 60LL * 60LL * 24LL;
189
190 // 100us seems like a reasonable minimum
191 static const int64_t min_ns_interval = 100000LL;
192
193 int64_t interval, randomize;
194
195 hrtimer_derived_probe (probe* p, probe_point* l, int64_t i, int64_t r,
196 int64_t scale):
197 derived_probe (p, l), interval (i), randomize (r)
198 {
199 if ((i < min_ns_interval) || (i > max_ns_interval))
200 throw SEMANTIC_ERROR(_F("interval value out of range (%s, %s)",
201 (lex_cast(scale < min_ns_interval ? min_ns_interval/scale : 1).c_str()),
202 lex_cast(max_ns_interval/scale).c_str()));
203
204 // randomize = 0 means no randomization
205 if ((r < 0) || (r > i))
206 throw SEMANTIC_ERROR(_("randomization value out of range"));
207 }
208
209 void join_group (systemtap_session& s);
210
211 // No assertion need be emitted, since these probes are allowed for
212 // unprivileged users.
213 void emit_privilege_assertion (translator_output*) {}
214 void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged (o); }
215 };
216
217
218 struct hrtimer_derived_probe_group: public generic_dpg<hrtimer_derived_probe>
219 {
220 public:
221 void emit_module_decls (systemtap_session& s);
222 void emit_module_init (systemtap_session& s);
223 void emit_module_refresh (systemtap_session& s);
224 void emit_module_exit (systemtap_session& s);
225
226 bool otf_supported (systemtap_session& s)
227 { return !s.runtime_usermode_p(); }
228
229 // workqueue manipulation is safe in hrtimers
230 bool otf_safe_context (systemtap_session& s)
231 { return otf_supported(s); }
232 };
233
234
235 void
236 hrtimer_derived_probe::join_group (systemtap_session& s)
237 {
238 if (! s.hrtimer_derived_probes)
239 s.hrtimer_derived_probes = new hrtimer_derived_probe_group ();
240 s.hrtimer_derived_probes->enroll (this);
241 this->group = s.hrtimer_derived_probes;
242 }
243
244
245 void
246 hrtimer_derived_probe_group::emit_module_decls (systemtap_session& s)
247 {
248 if (probes.empty()) return;
249
250 s.op->newline() << "/* ---- hrtimer probes ---- */";
251 s.op->newline() << "#include \"timer.c\"";
252 s.op->newline() << "static struct stap_hrtimer_probe stap_hrtimer_probes [" << probes.size() << "] = {";
253
254 s.op->indent(1);
255 for (unsigned i=0; i < probes.size(); i++)
256 {
257 s.op->newline () << "{";
258 s.op->line() << " .probe=" << common_probe_init (probes[i]) << ",";
259 s.op->line() << " .intrv=" << probes[i]->interval << "LL,";
260 s.op->line() << " .rnd=" << probes[i]->randomize << "LL";
261 s.op->line() << " },";
262 }
263 s.op->newline(-1) << "};";
264 s.op->newline();
265
266 if (!s.runtime_usermode_p())
267 {
268 s.op->newline() << "static hrtimer_return_t _stp_hrtimer_notify_function (struct hrtimer *timer) {";
269
270 s.op->newline(1) << "int rc = HRTIMER_NORESTART;";
271 s.op->newline() << "struct stap_hrtimer_probe *stp = container_of(timer, struct stap_hrtimer_probe, hrtimer);";
272
273 // Update the timer with the next trigger time
274 s.op->newline() << "if ((atomic_read (session_state()) == STAP_SESSION_STARTING) ||";
275 s.op->newline() << " (atomic_read (session_state()) == STAP_SESSION_RUNNING)) {";
276 s.op->newline(1) << "_stp_hrtimer_update(stp);";
277 s.op->newline() << "rc = HRTIMER_RESTART;";
278 s.op->newline(-1) << "}";
279
280 s.op->newline() << "{";
281 s.op->indent(1);
282 common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "stp->probe",
283 "stp_probe_type_hrtimer");
284 s.op->newline() << "(*stp->probe->ph) (c);";
285 common_probe_entryfn_epilogue (s, true, otf_safe_context(s));
286 s.op->newline(-1) << "}";
287 s.op->newline() << "return rc;";
288 s.op->newline(-1) << "}";
289 }
290 else
291 {
292 s.op->newline() << "static void _stp_hrtimer_notify_function (sigval_t value)";
293 s.op->newline(1) << "{";
294 s.op->newline() << "struct stap_hrtimer_probe *stp = value.sival_ptr;";
295
296 // Update the timer with the next trigger time
297 s.op->newline() << "if ((atomic_read (session_state()) == STAP_SESSION_STARTING) ||";
298 s.op->newline() << " (atomic_read (session_state()) == STAP_SESSION_RUNNING)) {";
299 s.op->newline(1) << "_stp_hrtimer_update(stp);";
300 s.op->newline(-1) << "}";
301
302 s.op->newline() << "{";
303 s.op->indent(1);
304 common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "stp->probe",
305 "stp_probe_type_hrtimer");
306 s.op->newline() << "(*stp->probe->ph) (c);";
307 common_probe_entryfn_epilogue (s, true, otf_safe_context(s));
308 s.op->newline(-1) << "}";
309 s.op->newline(-1) << "}";
310 }
311 }
312
313
314 void
315 hrtimer_derived_probe_group::emit_module_init (systemtap_session& s)
316 {
317 if (probes.empty()) return;
318
319 s.op->newline( 0) << "_stp_hrtimer_init();";
320 s.op->newline( 0) << "for (i=0; i<" << probes.size() << "; i++) {";
321 s.op->newline(+1) << "struct stap_hrtimer_probe* stp = & stap_hrtimer_probes [i];";
322 s.op->newline( 0) << "probe_point = stp->probe->pp;";
323
324 // Note: no partial failure rollback is needed for kernel hrtimer
325 // probes (hrtimer_start only "fails" if the timer was already
326 // active, which cannot be). But, stapdyn timer probes need a
327 // rollback, and it won't hurt the kernel hrtimers.
328 s.op->newline( 0) << "rc = _stp_hrtimer_create(stp, _stp_hrtimer_notify_function);";
329 s.op->newline( 0) << "if (rc) {";
330 s.op->newline(+1) << "for (j=i-1; j>=0; j--) {"; // partial rollback
331 s.op->newline(+1) << "_stp_hrtimer_cancel(& stap_hrtimer_probes[j]);";
332 if (!s.runtime_usermode_p())
333 s.op->newline( 0) << "stap_hrtimer_probes[j].enabled = 0;";
334 s.op->newline(-1) << "}";
335 s.op->newline( 0) << "break;"; // don't attempt to register any more
336 s.op->newline(-1) << "}";
337
338 // If not in kernel mode, then we always want to start the timer because
339 // on-the-fly starting/stopping is not supported.
340 if (!s.runtime_usermode_p())
341 {
342 // If the probe condition is off, then don't bother starting the timer
343 s.op->newline( 0) << "if (!stp->probe->cond_enabled) {";
344 s.op->newline(+1) << "dbug_otf(\"not starting (hrtimer) pidx %zu\\n\",";
345 s.op->newline( 0) << "stp->probe->index);";
346 s.op->newline( 0) << "continue;";
347 s.op->newline(-1) << "}";
348 }
349
350 // Start the timer (with rollback on failure)
351 s.op->newline( 0) << "rc = _stp_hrtimer_start(stp);";
352 s.op->newline( 0) << "if (rc) {";
353 s.op->newline(+1) << "for (j=i-1; j>=0; j--) {"; // partial rollback
354 s.op->newline(+1) << "_stp_hrtimer_cancel(& stap_hrtimer_probes[j]);";
355 if (!s.runtime_usermode_p())
356 s.op->newline( 0) << "stap_hrtimer_probes[j].enabled = 0;";
357 s.op->newline(-1) << "}";
358 s.op->newline( 0) << "break;"; // don't attempt to register any more
359 s.op->newline(-1) << "}";
360
361 // Mark as enabled since we successfully started the timer
362 if (!s.runtime_usermode_p())
363 s.op->newline( 0) << "stp->enabled = 1;";
364
365 s.op->newline(-1) << "}"; // for loop
366 }
367
368
369 void
370 hrtimer_derived_probe_group::emit_module_refresh (systemtap_session& s)
371 {
372 if (probes.empty() || s.runtime_usermode_p()) return;
373
374 // Check if we need to enable/disable any timers
375 s.op->newline( 0) << "for (i=0; i <" << probes.size() << "; i++) {";
376 s.op->newline(+1) << "struct stap_hrtimer_probe* stp = &stap_hrtimer_probes[i];";
377 // timer disabled, but condition says enabled?
378 s.op->newline( 0) << "if (!stp->enabled && stp->probe->cond_enabled) {";
379 s.op->newline(+1) << "dbug_otf(\"enabling (hrtimer) pidx %zu\\n\", stp->probe->index);";
380 s.op->newline( 0) << "_stp_hrtimer_start(stp);";
381 // timer enabled, but condition says disabled?
382 s.op->newline(-1) << "} else if (stp->enabled && !stp->probe->cond_enabled) {";
383 s.op->newline(+1) << "dbug_otf(\"disabling (hrtimer) pidx %zu\\n\", stp->probe->index);";
384 s.op->newline( 0) << "_stp_hrtimer_cancel(stp);";
385 s.op->newline(-1) << "}";
386 s.op->newline( 0) << "stp->enabled = stp->probe->cond_enabled;";
387 s.op->newline(-1) << "}";
388 }
389
390
391 void
392 hrtimer_derived_probe_group::emit_module_exit (systemtap_session& s)
393 {
394 if (probes.empty()) return;
395
396 s.op->newline() << "for (i=0; i<" << probes.size() << "; i++)";
397 s.op->indent(1);
398 s.op->newline() << "_stp_hrtimer_delete(& stap_hrtimer_probes[i]);";
399 s.op->indent(-1);
400 }
401
402
403
404 // ------------------------------------------------------------------------
405 // profile derived probes
406 // ------------------------------------------------------------------------
407 // On kernels < 2.6.10, this uses the register_profile_notifier API to
408 // generate the timed events for profiling; on kernels >= 2.6.10 this
409 // uses the register_timer_hook API. The latter doesn't currently allow
410 // simultaneous users, so insertion will fail if the profiler is busy.
411 // (Conflicting users may include OProfile, other SystemTap probes, etc.)
412
413
414 struct profile_derived_probe: public derived_probe
415 {
416 profile_derived_probe (systemtap_session &s, probe* p, probe_point* l);
417 void join_group (systemtap_session& s);
418 };
419
420
421 struct profile_derived_probe_group: public generic_dpg<profile_derived_probe>
422 {
423 public:
424 void emit_module_decls (systemtap_session& s);
425 void emit_module_init (systemtap_session& s);
426 void emit_module_exit (systemtap_session& s);
427 };
428
429
430 profile_derived_probe::profile_derived_probe (systemtap_session &, probe* p, probe_point* l):
431 derived_probe(p, l)
432 {
433 }
434
435
436 void
437 profile_derived_probe::join_group (systemtap_session& s)
438 {
439 if (! s.profile_derived_probes)
440 s.profile_derived_probes = new profile_derived_probe_group ();
441 s.profile_derived_probes->enroll (this);
442 this->group = s.profile_derived_probes;
443 }
444
445
446 // timer.profile probe handlers are hooked up in an entertaining way
447 // to the underlying kernel facility. The fact that 2.6.11+ era
448 // "register_timer_hook" API allows only one consumer *system-wide*
449 // will give a hint. We will have a single entry function (and thus
450 // trivial registration / unregistration), and it will call all probe
451 // handler functions in sequence.
452
453 void
454 profile_derived_probe_group::emit_module_decls (systemtap_session& s)
455 {
456 if (probes.empty()) return;
457
458 // kernels < 2.6.10: use register_profile_notifier API
459 // kernels >= 2.6.10: use register_timer_hook API
460 s.op->newline() << "/* ---- profile probes ---- */";
461
462 // This function calls all the profiling probe handlers in sequence.
463 // The only tricky thing is that the context will be reused amongst
464 // them. While a simple sequence of calls to the individual probe
465 // handlers is unlikely to go terribly wrong (with c->last_error
466 // being set causing an early return), but for extra assurance, we
467 // open-code the same logic here.
468
469 s.op->newline() << "static void enter_all_profile_probes (struct pt_regs *regs) {";
470 s.op->newline(1) << "const struct stap_probe * probe = "
471 << common_probe_init (probes[0]) << ";";
472 common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "probe",
473 "stp_probe_type_profile_timer");
474 // Timer interrupts save all registers, so if the interrupt happened
475 // in user space we can rely on it being the full user pt_regs.
476 s.op->newline() << "if (user_mode(regs)) {";
477 s.op->newline(1) << "c->user_mode_p = 1;";
478 s.op->newline() << "c->uregs = regs;";
479 s.op->newline(-1) << "} else {";
480 s.op->newline(1) << "c->kregs = regs;";
481 s.op->newline(-1) << "}";
482
483 for (unsigned i=0; i<probes.size(); i++)
484 {
485 if (i > 0)
486 {
487 // Some lightweight inter-probe context resetting
488 // XXX: not quite right: MAXERRORS not respected
489 // XXX: STP_TIMING stats are also not correct
490 s.op->newline() << "probe = " << common_probe_init (probes[i]) << ";";
491 s.op->newline() << "#ifdef STP_NEED_PROBE_NAME";
492 s.op->newline() << "c->probe_name = probe->pn;";
493 s.op->newline() << "#endif";
494 if(!s.suppress_time_limits)
495 {
496 s.op->newline() << "c->actionremaining = MAXACTION;";
497 }
498 }
499 s.op->newline() << "if (c->last_error == NULL) probe->ph (c);";
500 }
501 common_probe_entryfn_epilogue (s, true, otf_safe_context(s));
502 s.op->newline(-1) << "}";
503
504 s.op->newline() << "#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)"; // == using_rpn of yore
505
506 s.op->newline() << "static int enter_profile_probes (struct notifier_block *self,"
507 << " unsigned long val, void *data) {";
508 s.op->newline(1) << "(void) self; (void) val;";
509 s.op->newline() << "enter_all_profile_probes ((struct pt_regs *) data);";
510 s.op->newline() << "return 0;";
511 s.op->newline(-1) << "}";
512 s.op->newline() << "struct notifier_block stap_profile_notifier = {"
513 << " .notifier_call = & enter_profile_probes };";
514
515 s.op->newline() << "#else";
516
517 s.op->newline() << "static int enter_profile_probes (struct pt_regs *regs) {";
518 s.op->newline(1) << "enter_all_profile_probes (regs);";
519 s.op->newline() << "return 0;";
520 s.op->newline(-1) << "}";
521
522 s.op->newline() << "#endif";
523 }
524
525
526 void
527 profile_derived_probe_group::emit_module_init (systemtap_session& s)
528 {
529 if (probes.empty()) return;
530
531 s.op->newline() << "probe_point = \"timer.profile\";"; // NB: hard-coded for convenience
532 s.op->newline() << "#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)"; // == using_rpn of yore
533 s.op->newline() << "rc = register_profile_notifier (& stap_profile_notifier);";
534 s.op->newline() << "#else";
535 s.op->newline() << "rc = register_timer_hook (& enter_profile_probes);";
536 s.op->newline() << "#endif";
537 }
538
539
540 void
541 profile_derived_probe_group::emit_module_exit (systemtap_session& s)
542 {
543 if (probes.empty()) return;
544
545 s.op->newline() << "#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)"; // == using_rpn of yore
546 s.op->newline() << "unregister_profile_notifier (& stap_profile_notifier);";
547 s.op->newline() << "#else";
548 s.op->newline() << "unregister_timer_hook (& enter_profile_probes);";
549 s.op->newline() << "#endif";
550 }
551
552
553
554 // ------------------------------------------------------------------------
555 // unified probe builder for timer probes
556 // ------------------------------------------------------------------------
557
558
559 struct timer_builder: public derived_probe_builder
560 {
561 virtual void build(systemtap_session & sess,
562 probe * base, probe_point * location,
563 literal_map_t const & parameters,
564 vector<derived_probe *> & finished_results);
565
566 static void register_patterns(systemtap_session& s);
567 };
568
569 void
570 timer_builder::build(systemtap_session & sess,
571 probe * base,
572 probe_point * location,
573 literal_map_t const & parameters,
574 vector<derived_probe *> & finished_results)
575 {
576 int64_t scale=1, period, rand=0;
577
578 if (has_null_param(parameters, "profile"))
579 {
580 if (sess.runtime_usermode_p())
581 throw SEMANTIC_ERROR (_("profile timer probes not available with the dyninst runtime"));
582
583 /* As the latest mechanism for timer hook support has been
584 removed, we need to bail explicitly if the corresponding
585 symbols are missing: */
586 if ((sess.kernel_exports.find("register_timer_hook") == sess.kernel_exports.end()
587 || sess.kernel_exports.find("unregister_timer_hook") == sess.kernel_exports.end())
588 && (sess.kernel_exports.find("register_profile_notifier") == sess.kernel_exports.end()
589 || sess.kernel_exports.find("unregister_profile_notifier") == sess.kernel_exports.end()))
590 throw SEMANTIC_ERROR (_("profiling timer support (register_timer_hook) not found in kernel!"));
591
592 sess.unwindsym_modules.insert ("kernel");
593 finished_results.push_back
594 (new profile_derived_probe(sess, base, location));
595 return;
596 }
597
598 if (!get_param(parameters, "randomize", rand))
599 rand = 0;
600
601 if (get_param(parameters, "jiffies", period))
602 {
603 if (sess.runtime_usermode_p())
604 throw SEMANTIC_ERROR (_("jiffies timer probes not available with the dyninst runtime"));
605
606 // always use basic timers for jiffies
607 finished_results.push_back
608 (new timer_derived_probe(base, location, period, rand, false));
609 return;
610 }
611 else if (get_param(parameters, "hz", period))
612 {
613 if (period <= 0)
614 throw SEMANTIC_ERROR (_("frequency must be greater than 0"));
615 period = (1000000000 + period - 1)/period;
616 }
617 else if (get_param(parameters, "s", period) ||
618 get_param(parameters, "sec", period))
619 {
620 scale = 1000000000;
621 period *= scale;
622 rand *= scale;
623 }
624 else if (get_param(parameters, "ms", period) ||
625 get_param(parameters, "msec", period))
626 {
627 scale = 1000000;
628 period *= scale;
629 rand *= scale;
630 }
631 else if (get_param(parameters, "us", period) ||
632 get_param(parameters, "usec", period))
633 {
634 scale = 1000;
635 period *= scale;
636 rand *= scale;
637 }
638 else if (get_param(parameters, "ns", period) ||
639 get_param(parameters, "nsec", period))
640 {
641 // ok
642 }
643 else
644 throw SEMANTIC_ERROR (_("unrecognized timer variant"));
645
646 // Redirect wallclock-time based probes to hrtimer code on recent
647 // enough kernels.
648 if (strverscmp(sess.kernel_base_release.c_str(), "2.6.17") < 0)
649 {
650 // hrtimers didn't exist, so use the old-school timers
651 period = (period + 1000000 - 1)/1000000;
652 rand = (rand + 1000000 - 1)/1000000;
653
654 finished_results.push_back
655 (new timer_derived_probe(base, location, period, rand, true));
656 }
657 else
658 finished_results.push_back
659 (new hrtimer_derived_probe(base, location, period, rand, scale));
660 }
661
662 void
663 register_tapset_timers(systemtap_session& s)
664 {
665 match_node* root = s.pattern_root;
666 derived_probe_builder *builder = new timer_builder();
667
668 root = root->bind(TOK_TIMER);
669
670 root->bind_num("s")
671 ->bind_privilege(pr_all)
672 ->bind(builder);
673 root->bind_num("s")->bind_num("randomize")
674 ->bind_privilege(pr_all)
675 ->bind(builder);
676 root->bind_num("sec")
677 ->bind_privilege(pr_all)
678 ->bind(builder);
679 root->bind_num("sec")->bind_num("randomize")
680 ->bind_privilege(pr_all)
681 ->bind(builder);
682
683 root->bind_num("ms")
684 ->bind_privilege(pr_all)
685 ->bind(builder);
686 root->bind_num("ms")->bind_num("randomize")
687 ->bind_privilege(pr_all)
688 ->bind(builder);
689 root->bind_num("msec")
690 ->bind_privilege(pr_all)
691 ->bind(builder);
692 root->bind_num("msec")->bind_num("randomize")
693 ->bind_privilege(pr_all)
694 ->bind(builder);
695
696 root->bind_num("us")
697 ->bind_privilege(pr_all)
698 ->bind(builder);
699 root->bind_num("us")->bind_num("randomize")
700 ->bind_privilege(pr_all)
701 ->bind(builder);
702 root->bind_num("usec")
703 ->bind_privilege(pr_all)
704 ->bind(builder);
705 root->bind_num("usec")->bind_num("randomize")
706 ->bind_privilege(pr_all)
707 ->bind(builder);
708
709 root->bind_num("ns")
710 ->bind_privilege(pr_all)
711 ->bind(builder);
712 root->bind_num("ns")->bind_num("randomize")
713 ->bind_privilege(pr_all)
714 ->bind(builder);
715 root->bind_num("nsec")
716 ->bind_privilege(pr_all)
717 ->bind(builder);
718 root->bind_num("nsec")->bind_num("randomize")
719 ->bind_privilege(pr_all)
720 ->bind(builder);
721
722 root->bind_num("jiffies")
723 ->bind_privilege(pr_all)
724 ->bind(builder);
725 root->bind_num("jiffies")->bind_num("randomize")
726 ->bind_privilege(pr_all)
727 ->bind(builder);
728
729 root->bind_num("hz")
730 ->bind_privilege(pr_all)
731 ->bind(builder);
732
733 // Not ok for unprivileged users, because register_timer_hook only
734 // allows a single attached callback. No resource-sharing -> no
735 // unprivileged access.
736 //
737 // Sigh, but for dyninst users, we want a semantic error that
738 // profile probes aren't supported (which will come from
739 // timer_builder::build()), not a privilege error. So, we'll fake
740 // it so that profile probes are allowed for all.
741 if (!s.runtime_usermode_p()) {
742 root->bind("profile")
743 ->bind("tick")
744 ->bind(builder);
745 }
746 else {
747 root->bind("profile")
748 ->bind("tick")
749 ->bind_privilege(pr_all)
750 ->bind(builder);
751 }
752 }
753
754
755
756 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.080616 seconds and 5 git commands to generate.