2 // Copyright (C) 2005-2011 Red Hat Inc.
3 // Copyright (C) 2005-2007 Intel Corporation.
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
13 #include "translate.h"
21 using namespace __gnu_cxx
;
24 static const string
TOK_TIMER("timer");
27 // ------------------------------------------------------------------------
28 // timer derived probes
29 // ------------------------------------------------------------------------
32 struct timer_derived_probe
: public derived_probe
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
);
40 // No assertion need be emitted, since this probe is allowed for unprivileged
42 void emit_privilege_assertion (translator_output
*) {}
43 void print_dupe_stamp(ostream
& o
) { print_dupe_stamp_unprivileged (o
); }
47 struct timer_derived_probe_group
: public generic_dpg
<timer_derived_probe
>
49 void emit_interval (translator_output
* o
);
51 void emit_module_decls (systemtap_session
& s
);
52 void emit_module_init (systemtap_session
& s
);
53 void emit_module_exit (systemtap_session
& s
);
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
)
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"));
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
76 timer_derived_probe::join_group (systemtap_session
& s
)
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
;
86 timer_derived_probe_group::emit_interval (translator_output
* o
)
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) << "})";
98 timer_derived_probe_group::emit_module_decls (systemtap_session
& s
)
100 if (probes
.empty()) return;
102 s
.op
->newline() << "/* ---- timer probes ---- */";
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() << "] = {";
110 for (unsigned i
=0; i
< probes
.size(); i
++)
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() << " },";
119 s
.op
->newline(-1) << "};";
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) << "{";
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);
135 s
.op
->newline(-1) << "}";
136 s
.op
->newline(-1) << "}";
141 timer_derived_probe_group::emit_module_init (systemtap_session
& s
)
143 if (probes
.empty()) return;
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
);
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
162 timer_derived_probe_group::emit_module_exit (systemtap_session
& s
)
164 if (probes
.empty()) return;
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);";
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
182 // * hrtimer_derived_probe: creates a probe point based on the hrtimer APIs.
185 struct hrtimer_derived_probe
: public derived_probe
187 // set a (generous) maximum of one day in ns
188 static const int64_t max_ns_interval
= 1000000000LL * 60LL * 60LL * 24LL;
190 // 100us seems like a reasonable minimum
191 static const int64_t min_ns_interval
= 100000LL;
193 int64_t interval
, randomize
;
195 hrtimer_derived_probe (probe
* p
, probe_point
* l
, int64_t i
, int64_t r
,
197 derived_probe (p
, l
), interval (i
), randomize (r
)
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()));
204 // randomize = 0 means no randomization
205 if ((r
< 0) || (r
> i
))
206 throw SEMANTIC_ERROR(_("randomization value out of range"));
209 void join_group (systemtap_session
& s
);
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
); }
218 struct hrtimer_derived_probe_group
: public generic_dpg
<hrtimer_derived_probe
>
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
);
226 bool otf_supported (systemtap_session
& s
)
227 { return !s
.runtime_usermode_p(); }
229 // workqueue manipulation is safe in hrtimers
230 bool otf_safe_context (systemtap_session
& s
)
231 { return otf_supported(s
); }
236 hrtimer_derived_probe::join_group (systemtap_session
& s
)
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
;
246 hrtimer_derived_probe_group::emit_module_decls (systemtap_session
& s
)
248 if (probes
.empty()) return;
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() << "] = {";
255 for (unsigned i
=0; i
< probes
.size(); i
++)
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() << " },";
263 s
.op
->newline(-1) << "};";
266 if (!s
.runtime_usermode_p())
268 s
.op
->newline() << "static hrtimer_return_t _stp_hrtimer_notify_function (struct hrtimer *timer) {";
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);";
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) << "}";
280 s
.op
->newline() << "{";
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);
286 s
.op
->newline(-1) << "}";
287 s
.op
->newline() << "return rc;";
288 s
.op
->newline(-1) << "}";
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;";
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) << "}";
302 s
.op
->newline() << "{";
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);
308 s
.op
->newline(-1) << "}";
309 s
.op
->newline(-1) << "}";
315 hrtimer_derived_probe_group::emit_module_init (systemtap_session
& s
)
317 if (probes
.empty()) return;
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;";
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) << "}";
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())
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) << "}";
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) << "}";
361 // Mark as enabled since we successfully started the timer
362 if (!s
.runtime_usermode_p())
363 s
.op
->newline( 0) << "stp->enabled = 1;";
365 s
.op
->newline(-1) << "}"; // for loop
370 hrtimer_derived_probe_group::emit_module_refresh (systemtap_session
& s
)
372 if (probes
.empty() || s
.runtime_usermode_p()) return;
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) << "}";
392 hrtimer_derived_probe_group::emit_module_exit (systemtap_session
& s
)
394 if (probes
.empty()) return;
396 s
.op
->newline() << "for (i=0; i<" << probes
.size() << "; i++)";
398 s
.op
->newline() << "_stp_hrtimer_delete(& stap_hrtimer_probes[i]);";
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.)
414 struct profile_derived_probe
: public derived_probe
416 profile_derived_probe (systemtap_session
&s
, probe
* p
, probe_point
* l
);
417 void join_group (systemtap_session
& s
);
421 struct profile_derived_probe_group
: public generic_dpg
<profile_derived_probe
>
424 void emit_module_decls (systemtap_session
& s
);
425 void emit_module_init (systemtap_session
& s
);
426 void emit_module_exit (systemtap_session
& s
);
430 profile_derived_probe::profile_derived_probe (systemtap_session
&, probe
* p
, probe_point
* l
):
437 profile_derived_probe::join_group (systemtap_session
& s
)
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
;
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.
454 profile_derived_probe_group::emit_module_decls (systemtap_session
& s
)
456 if (probes
.empty()) return;
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 ---- */";
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.
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) << "}";
483 for (unsigned i
=0; i
<probes
.size(); i
++)
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
)
496 s
.op
->newline() << "c->actionremaining = MAXACTION;";
499 s
.op
->newline() << "if (c->last_error == NULL) probe->ph (c);";
501 common_probe_entryfn_epilogue (s
, true);
502 s
.op
->newline(-1) << "}";
504 s
.op
->newline() << "#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)"; // == using_rpn of yore
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 };";
515 s
.op
->newline() << "#else";
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) << "}";
522 s
.op
->newline() << "#endif";
527 profile_derived_probe_group::emit_module_init (systemtap_session
& s
)
529 if (probes
.empty()) return;
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";
541 profile_derived_probe_group::emit_module_exit (systemtap_session
& s
)
543 if (probes
.empty()) return;
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";
554 // ------------------------------------------------------------------------
555 // unified probe builder for timer probes
556 // ------------------------------------------------------------------------
559 struct timer_builder
: public derived_probe_builder
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
);
566 static void register_patterns(systemtap_session
& s
);
570 timer_builder::build(systemtap_session
& sess
,
572 probe_point
* location
,
573 literal_map_t
const & parameters
,
574 vector
<derived_probe
*> & finished_results
)
576 int64_t scale
=1, period
, rand
=0;
578 if (has_null_param(parameters
, "profile"))
580 if (sess
.runtime_usermode_p())
581 throw SEMANTIC_ERROR (_("profile timer probes not available with the dyninst runtime"));
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!"));
592 sess
.unwindsym_modules
.insert ("kernel");
593 finished_results
.push_back
594 (new profile_derived_probe(sess
, base
, location
));
598 if (!get_param(parameters
, "randomize", rand
))
601 if (get_param(parameters
, "jiffies", period
))
603 if (sess
.runtime_usermode_p())
604 throw SEMANTIC_ERROR (_("jiffies timer probes not available with the dyninst runtime"));
606 // always use basic timers for jiffies
607 finished_results
.push_back
608 (new timer_derived_probe(base
, location
, period
, rand
, false));
611 else if (get_param(parameters
, "hz", period
))
614 throw SEMANTIC_ERROR (_("frequency must be greater than 0"));
615 period
= (1000000000 + period
- 1)/period
;
617 else if (get_param(parameters
, "s", period
) ||
618 get_param(parameters
, "sec", period
))
624 else if (get_param(parameters
, "ms", period
) ||
625 get_param(parameters
, "msec", period
))
631 else if (get_param(parameters
, "us", period
) ||
632 get_param(parameters
, "usec", period
))
638 else if (get_param(parameters
, "ns", period
) ||
639 get_param(parameters
, "nsec", period
))
644 throw SEMANTIC_ERROR (_("unrecognized timer variant"));
646 // Redirect wallclock-time based probes to hrtimer code on recent
648 if (strverscmp(sess
.kernel_base_release
.c_str(), "2.6.17") < 0)
650 // hrtimers didn't exist, so use the old-school timers
651 period
= (period
+ 1000000 - 1)/1000000;
652 rand
= (rand
+ 1000000 - 1)/1000000;
654 finished_results
.push_back
655 (new timer_derived_probe(base
, location
, period
, rand
, true));
658 finished_results
.push_back
659 (new hrtimer_derived_probe(base
, location
, period
, rand
, scale
));
663 register_tapset_timers(systemtap_session
& s
)
665 match_node
* root
= s
.pattern_root
;
666 derived_probe_builder
*builder
= new timer_builder();
668 root
= root
->bind(TOK_TIMER
);
671 ->bind_privilege(pr_all
)
673 root
->bind_num("s")->bind_num("randomize")
674 ->bind_privilege(pr_all
)
676 root
->bind_num("sec")
677 ->bind_privilege(pr_all
)
679 root
->bind_num("sec")->bind_num("randomize")
680 ->bind_privilege(pr_all
)
684 ->bind_privilege(pr_all
)
686 root
->bind_num("ms")->bind_num("randomize")
687 ->bind_privilege(pr_all
)
689 root
->bind_num("msec")
690 ->bind_privilege(pr_all
)
692 root
->bind_num("msec")->bind_num("randomize")
693 ->bind_privilege(pr_all
)
697 ->bind_privilege(pr_all
)
699 root
->bind_num("us")->bind_num("randomize")
700 ->bind_privilege(pr_all
)
702 root
->bind_num("usec")
703 ->bind_privilege(pr_all
)
705 root
->bind_num("usec")->bind_num("randomize")
706 ->bind_privilege(pr_all
)
710 ->bind_privilege(pr_all
)
712 root
->bind_num("ns")->bind_num("randomize")
713 ->bind_privilege(pr_all
)
715 root
->bind_num("nsec")
716 ->bind_privilege(pr_all
)
718 root
->bind_num("nsec")->bind_num("randomize")
719 ->bind_privilege(pr_all
)
722 root
->bind_num("jiffies")
723 ->bind_privilege(pr_all
)
725 root
->bind_num("jiffies")->bind_num("randomize")
726 ->bind_privilege(pr_all
)
730 ->bind_privilege(pr_all
)
733 // Not ok for unprivileged users, because register_timer_hook only
734 // allows a single attached callback. No resource-sharing -> no
735 // unprivileged access.
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")
747 root
->bind("profile")
749 ->bind_privilege(pr_all
)
756 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */