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