]>
sourceware.org Git - systemtap.git/blob - tapset-been.cxx
1 // tapset for begin/end/error/never
2 // Copyright (C) 2005-2010 Red Hat Inc.
3 // Copyright (C) 2005-2007 Intel Corporation.
4 // Copyright (C) 2008 James.Bottomley@HansenPartnership.com
6 // This file is part of systemtap, and is free software. You can
7 // redistribute it and/or modify it under the terms of the GNU General
8 // 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_BEGIN("begin");
25 static const string
TOK_END("end");
26 static const string
TOK_ERROR("error");
27 static const string
TOK_NEVER("never");
30 // ------------------------------------------------------------------------
31 // begin/end/error probes are run right during registration / deregistration
32 // ------------------------------------------------------------------------
34 enum be_t
{ BEGIN
, END
, ERROR
};
36 struct be_derived_probe
: public derived_probe
41 be_derived_probe (probe
* p
, probe_point
* l
, be_t t
, int64_t pr
):
42 derived_probe (p
, l
), type (t
), priority (pr
) {}
44 void join_group (systemtap_session
& s
);
46 static inline bool comp(be_derived_probe
const *a
,
47 be_derived_probe
const *b
)
49 // This allows the BEGIN/END/ERROR probes to intermingle.
50 // But that's OK - they're always treversed with a nested
51 // "if (type==FOO)" conditional.
52 return a
->priority
< b
->priority
;
55 // No assertion need be emitted, since these probes are allowed for
56 // unprivileged users.
57 void emit_unprivileged_assertion (translator_output
*) {}
59 void print_dupe_stamp(ostream
& o
) { print_dupe_stamp_unprivileged (o
); }
61 bool needs_global_locks () { return false; }
62 // begin/end probes don't need locks around global variables, since
63 // they aren't run concurrently with any other probes
67 struct be_derived_probe_group
: public generic_dpg
<be_derived_probe
>
70 void emit_module_decls (systemtap_session
& s
);
71 void emit_module_init (systemtap_session
& s
);
72 void emit_module_exit (systemtap_session
& s
);
75 struct be_builder
: public derived_probe_builder
79 be_builder(be_t t
) : type(t
) {}
81 virtual void build(systemtap_session
&,
83 probe_point
* location
,
84 literal_map_t
const & parameters
,
85 vector
<derived_probe
*> & finished_results
)
88 if ((type
== BEGIN
&& !get_param(parameters
, TOK_BEGIN
, priority
)) ||
89 (type
== END
&& !get_param(parameters
, TOK_END
, priority
)) ||
90 (type
== ERROR
&& !get_param(parameters
, TOK_ERROR
, priority
)))
92 finished_results
.push_back
93 (new be_derived_probe(base
, location
, type
, priority
));
99 be_derived_probe::join_group (systemtap_session
& s
)
101 if (! s
.be_derived_probes
)
102 s
.be_derived_probes
= new be_derived_probe_group ();
103 s
.be_derived_probes
->enroll (this);
108 be_derived_probe_group::emit_module_decls (systemtap_session
& s
)
110 if (probes
.empty()) return;
112 map
<be_t
, const char *> states
;
113 states
[BEGIN
] = "STAP_SESSION_STARTING";
114 states
[END
] = "STAP_SESSION_STOPPING";
115 states
[ERROR
] = "STAP_SESSION_ERROR";
117 s
.op
->newline() << "/* ---- begin/end/error probes ---- */";
119 // NB: We emit the table in sorted order here, so we don't have to
120 // store the priority numbers as integers and sort at run time.
122 sort(probes
.begin(), probes
.end(), be_derived_probe::comp
);
124 s
.op
->newline() << "static struct stap_be_probe {";
125 s
.op
->newline(1) << "void (*ph)(struct context*);";
126 s
.op
->newline() << "const char* pp;";
127 s
.op
->newline() << "int state, type;";
128 s
.op
->newline(-1) << "} stap_be_probes[] = {";
131 for (unsigned i
=0; i
< probes
.size(); i
++)
133 s
.op
->newline () << "{";
134 s
.op
->line() << " .pp="
135 << lex_cast_qstring (*probes
[i
]->sole_location()) << ",";
136 s
.op
->line() << " .ph=&" << probes
[i
]->name
<< ",";
137 s
.op
->line() << " .state=" << states
[probes
[i
]->type
] << ",";
138 s
.op
->line() << " .type=" << probes
[i
]->type
;
139 s
.op
->line() << " },";
141 s
.op
->newline(-1) << "};";
143 s
.op
->newline() << "static void enter_be_probe (struct stap_be_probe *stp) {";
145 common_probe_entryfn_prologue (s
.op
, "stp->state", "stp->pp", false);
146 s
.op
->newline() << "(*stp->ph) (c);";
147 common_probe_entryfn_epilogue (s
.op
, false);
148 s
.op
->newline(-1) << "}";
152 be_derived_probe_group::emit_module_init (systemtap_session
& s
)
154 if (probes
.empty()) return;
156 s
.op
->newline() << "for (i=0; i<" << probes
.size() << "; i++) {";
157 s
.op
->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
158 s
.op
->newline() << "if (stp->type == " << BEGIN
<< ")";
159 s
.op
->newline(1) << "enter_be_probe (stp); /* rc = 0 */";
160 // NB: begin probes that cause errors do not constitute registration
161 // failures. An error message will probably get printed and if
162 // MAXERRORS was left at 1, we'll get an stp_exit. The
163 // error-handling probes will be run during the ordinary
164 // unregistration phase.
165 s
.op
->newline(-2) << "}";
169 be_derived_probe_group::emit_module_exit (systemtap_session
& s
)
171 if (probes
.empty()) return;
173 s
.op
->newline() << "for (i=0; i<" << probes
.size() << "; i++) {";
174 s
.op
->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
175 s
.op
->newline() << "if (stp->type == " << END
<< ")";
176 s
.op
->newline(1) << "enter_be_probe (stp);";
177 s
.op
->newline(-2) << "}";
179 s
.op
->newline() << "for (i=0; i<" << probes
.size() << "; i++) {";
180 s
.op
->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
181 s
.op
->newline() << "if (stp->type == " << ERROR
<< ")";
182 s
.op
->newline(1) << "enter_be_probe (stp);";
183 s
.op
->newline(-2) << "}";
188 // ------------------------------------------------------------------------
189 // never probes are never run
190 // ------------------------------------------------------------------------
192 struct never_derived_probe
: public derived_probe
194 never_derived_probe (probe
* p
): derived_probe (p
) {}
195 never_derived_probe (probe
* p
, probe_point
* l
): derived_probe (p
, l
) {}
196 void join_group (systemtap_session
&) { /* thus no probe_group */ }
197 void emit_unprivileged_assertion (translator_output
*) {}
198 void print_dupe_stamp(ostream
& o
) { print_dupe_stamp_unprivileged (o
); }
202 struct never_builder
: public derived_probe_builder
205 virtual void build(systemtap_session
&,
207 probe_point
* location
,
208 literal_map_t
const &,
209 vector
<derived_probe
*> & finished_results
)
211 finished_results
.push_back(new never_derived_probe(base
, location
));
217 // ------------------------------------------------------------------------
218 // unified registration for begin/end/error/never
219 // ------------------------------------------------------------------------
222 register_tapset_been(systemtap_session
& s
)
224 match_node
* root
= s
.pattern_root
;
226 root
->bind(TOK_BEGIN
)
227 ->bind_unprivileged()
228 ->bind(new be_builder(BEGIN
));
229 root
->bind_num(TOK_BEGIN
)
230 ->bind_unprivileged()
231 ->bind(new be_builder(BEGIN
));
234 ->bind_unprivileged()
235 ->bind(new be_builder(END
));
236 root
->bind_num(TOK_END
)
237 ->bind_unprivileged()
238 ->bind(new be_builder(END
));
240 root
->bind(TOK_ERROR
)
241 ->bind_unprivileged()
242 ->bind(new be_builder(ERROR
));
243 root
->bind_num(TOK_ERROR
)
244 ->bind_unprivileged()
245 ->bind(new be_builder(ERROR
));
247 root
->bind(TOK_NEVER
)
248 ->bind_unprivileged()
249 ->bind(new never_builder());
252 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.054614 seconds and 6 git commands to generate.