]>
sourceware.org Git - systemtap.git/blob - tapset-been.cxx
1 // tapset for begin/end/error/never
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
12 #include "translate.h"
20 using namespace __gnu_cxx
;
23 static const string
TOK_BEGIN("begin");
24 static const string
TOK_END("end");
25 static const string
TOK_ERROR("error");
26 static const string
TOK_NEVER("never");
29 // ------------------------------------------------------------------------
30 // begin/end/error probes are run right during registration / deregistration
31 // ------------------------------------------------------------------------
33 enum be_t
{ BEGIN
, END
, ERROR
};
35 struct be_derived_probe
: public derived_probe
40 be_derived_probe (probe
* p
, probe_point
* l
, be_t t
, int64_t pr
):
41 derived_probe (p
, l
), type (t
), priority (pr
) {}
43 void join_group (systemtap_session
& s
);
45 static inline bool comp(be_derived_probe
const *a
,
46 be_derived_probe
const *b
)
48 // This allows the BEGIN/END/ERROR probes to intermingle.
49 // But that's OK - they're always treversed with a nested
50 // "if (type==FOO)" conditional.
51 return a
->priority
< b
->priority
;
54 // No assertion need be emitted, since these probes are allowed for
55 // unprivileged users.
56 void emit_privilege_assertion (translator_output
*) {}
58 void print_dupe_stamp(ostream
& o
) { print_dupe_stamp_unprivileged (o
); }
60 bool needs_global_locks () { return false; }
61 // begin/end probes don't need locks around global variables, since
62 // they aren't run concurrently with any other probes
66 struct be_derived_probe_group
: public generic_dpg
<be_derived_probe
>
68 friend bool sort_for_bpf(systemtap_session
& s
,
69 be_derived_probe_group
*be
,
70 std::vector
<derived_probe
*> &begin_v
,
71 std::vector
<derived_probe
*> &end_v
);
74 void emit_module_decls (systemtap_session
& s
);
75 void emit_module_init (systemtap_session
& s
);
76 void emit_module_exit (systemtap_session
& s
);
79 struct be_builder
: public derived_probe_builder
83 be_builder(be_t t
) : type(t
) {}
85 virtual void build(systemtap_session
&,
87 probe_point
* location
,
88 literal_map_t
const & parameters
,
89 vector
<derived_probe
*> & finished_results
)
93 get_param(parameters
, TOK_BEGIN
, priority
);
95 get_param(parameters
, TOK_END
, priority
);
96 else if (type
== ERROR
)
97 get_param(parameters
, TOK_ERROR
, priority
);
99 finished_results
.push_back
100 (new be_derived_probe(base
, location
, type
, priority
));
103 virtual string
name() { return "begin/end builder"; }
108 be_derived_probe::join_group (systemtap_session
& s
)
110 if (! s
.be_derived_probes
)
111 s
.be_derived_probes
= new be_derived_probe_group ();
112 s
.be_derived_probes
->enroll (this);
113 this->group
= s
.be_derived_probes
;
118 be_derived_probe_group::emit_module_decls (systemtap_session
& s
)
120 if (probes
.empty()) return;
122 map
<be_t
, const char *> states
;
123 states
[BEGIN
] = "STAP_SESSION_STARTING";
124 states
[END
] = "STAP_SESSION_STOPPING";
125 states
[ERROR
] = "STAP_SESSION_ERROR";
127 s
.op
->newline() << "/* ---- begin/end/error probes ---- */";
129 // NB: We emit the table in sorted order here, so we don't have to
130 // store the priority numbers as integers and sort at run time.
132 sort(probes
.begin(), probes
.end(), be_derived_probe::comp
);
134 s
.op
->newline() << "static struct stap_be_probe {";
135 s
.op
->newline(1) << "const struct stap_probe * const probe;";
136 s
.op
->newline() << "int state, type;";
137 s
.op
->newline(-1) << "} stap_be_probes[] = {";
140 for (unsigned i
=0; i
< probes
.size(); i
++)
142 s
.op
->newline () << "{";
143 s
.op
->line() << " .probe=" << common_probe_init (probes
[i
]) << ",";
144 s
.op
->line() << " .state=" << states
[probes
[i
]->type
] << ",";
145 s
.op
->line() << " .type=" << probes
[i
]->type
;
146 s
.op
->line() << " },";
148 s
.op
->newline(-1) << "};";
150 s
.op
->newline() << "static void enter_be_probe (struct stap_be_probe *stp) {";
152 common_probe_entryfn_prologue (s
, "stp->state", "stp->probe",
153 "stp_probe_type_been", false);
154 s
.op
->newline() << "(*stp->probe->ph) (c);";
155 common_probe_entryfn_epilogue (s
, false, otf_safe_context(s
));
156 s
.op
->newline(-1) << "}";
160 be_derived_probe_group::emit_module_init (systemtap_session
& s
)
162 if (probes
.empty()) return;
164 s
.op
->newline() << "for (i=0; i<" << probes
.size() << "; i++) {";
165 s
.op
->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
166 s
.op
->newline() << "if (stp->type == " << BEGIN
<< ")";
167 s
.op
->newline(1) << "enter_be_probe (stp); /* rc = 0 */";
168 // NB: begin probes that cause errors do not constitute registration
169 // failures. An error message will probably get printed and if
170 // MAXERRORS was left at 1, we'll get an stp_exit. The
171 // error-handling probes will be run during the ordinary
172 // unregistration phase.
173 s
.op
->newline(-2) << "}";
177 be_derived_probe_group::emit_module_exit (systemtap_session
& s
)
179 if (probes
.empty()) return;
181 s
.op
->newline() << "for (i=0; i<" << probes
.size() << "; i++) {";
182 s
.op
->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
183 s
.op
->newline() << "if (stp->type == " << END
<< ")";
184 s
.op
->newline(1) << "enter_be_probe (stp);";
185 s
.op
->newline(-2) << "}";
187 s
.op
->newline() << "for (i=0; i<" << probes
.size() << "; i++) {";
188 s
.op
->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
189 s
.op
->newline() << "if (stp->type == " << ERROR
<< ")";
190 s
.op
->newline(1) << "enter_be_probe (stp);";
191 s
.op
->newline(-2) << "}";
195 sort_for_bpf(systemtap_session
& s
__attribute__ ((unused
)),
196 be_derived_probe_group
*be
,
197 std::vector
<derived_probe
*> &begin_v
,
198 std::vector
<derived_probe
*> &end_v
)
200 if (!be
|| be
->probes
.empty())
203 sort(be
->probes
.begin(), be
->probes
.end(), be_derived_probe::comp
);
205 for (auto i
= be
->probes
.begin(); i
!= be
->probes
.end(); ++i
)
207 be_derived_probe
*p
= *i
;
208 if (p
->type
== BEGIN
)
209 begin_v
.push_back(p
);
212 for (auto i
= be
->probes
.begin(); i
!= be
->probes
.end(); ++i
)
214 be_derived_probe
*p
= *i
;
215 if (p
->type
!= BEGIN
)
222 // ------------------------------------------------------------------------
223 // never probes are never run
224 // ------------------------------------------------------------------------
226 struct never_derived_probe
: public derived_probe
228 never_derived_probe (probe
* p
, probe_point
* l
): derived_probe (p
, l
) {}
229 void join_group (systemtap_session
&) { /* thus no probe_group */ }
230 void emit_privilege_assertion (translator_output
*) {}
231 void print_dupe_stamp(ostream
& o
) { print_dupe_stamp_unprivileged (o
); }
235 struct never_builder
: public derived_probe_builder
238 virtual void build(systemtap_session
&,
240 probe_point
* location
,
241 literal_map_t
const &,
242 vector
<derived_probe
*> & finished_results
)
244 finished_results
.push_back(new never_derived_probe(base
, location
));
247 virtual string
name() { return "never builder"; }
252 // ------------------------------------------------------------------------
253 // unified registration for begin/end/error/never
254 // ------------------------------------------------------------------------
257 register_tapset_been(systemtap_session
& s
)
259 match_node
* root
= s
.pattern_root
;
261 root
->bind(TOK_BEGIN
)
262 ->bind_privilege(pr_all
)
263 ->bind(new be_builder(BEGIN
));
264 root
->bind_num(TOK_BEGIN
)
265 ->bind_privilege(pr_all
)
266 ->bind(new be_builder(BEGIN
));
269 ->bind_privilege(pr_all
)
270 ->bind(new be_builder(END
));
271 root
->bind_num(TOK_END
)
272 ->bind_privilege(pr_all
)
273 ->bind(new be_builder(END
));
275 root
->bind(TOK_ERROR
)
276 ->bind_privilege(pr_all
)
277 ->bind(new be_builder(ERROR
));
278 root
->bind_num(TOK_ERROR
)
279 ->bind_privilege(pr_all
)
280 ->bind(new be_builder(ERROR
));
282 root
->bind(TOK_NEVER
)
283 ->bind_privilege(pr_all
)
284 ->bind(new never_builder());
287 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.057495 seconds and 5 git commands to generate.