]> sourceware.org Git - systemtap.git/blob - tapset-been.cxx
buildrun.cxx: adapt to kernel 5.4+
[systemtap.git] / 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.
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 #include "session.h"
11 #include "tapsets.h"
12 #include "translate.h"
13 #include "util.h"
14
15 #include <algorithm>
16 #include <string>
17
18
19 using namespace std;
20 using namespace __gnu_cxx;
21
22
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");
27
28
29 // ------------------------------------------------------------------------
30 // begin/end/error probes are run right during registration / deregistration
31 // ------------------------------------------------------------------------
32
33 enum be_t { BEGIN, END, ERROR };
34
35 struct be_derived_probe: public derived_probe
36 {
37 be_t type;
38 int64_t priority;
39
40 be_derived_probe (probe* p, probe_point* l, be_t t, int64_t pr):
41 derived_probe (p, l), type (t), priority (pr) {}
42
43 void join_group (systemtap_session& s);
44
45 static inline bool comp(be_derived_probe const *a,
46 be_derived_probe const *b)
47 {
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;
52 }
53
54 // No assertion need be emitted, since these probes are allowed for
55 // unprivileged users.
56 void emit_privilege_assertion (translator_output*) {}
57
58 void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged (o); }
59
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
63 };
64
65
66 struct be_derived_probe_group: public generic_dpg<be_derived_probe>
67 {
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);
72
73 public:
74 void emit_module_decls (systemtap_session& s);
75 void emit_module_init (systemtap_session& s);
76 void emit_module_exit (systemtap_session& s);
77 };
78
79 struct be_builder: public derived_probe_builder
80 {
81 be_t type;
82
83 be_builder(be_t t) : type(t) {}
84
85 virtual void build(systemtap_session &,
86 probe * base,
87 probe_point * location,
88 literal_map_t const & parameters,
89 vector<derived_probe *> & finished_results)
90 {
91 int64_t priority = 0;
92 if (type == BEGIN)
93 get_param(parameters, TOK_BEGIN, priority);
94 else if (type == END)
95 get_param(parameters, TOK_END, priority);
96 else if (type == ERROR)
97 get_param(parameters, TOK_ERROR, priority);
98
99 finished_results.push_back
100 (new be_derived_probe(base, location, type, priority));
101 }
102
103 virtual string name() { return "begin/end builder"; }
104 };
105
106
107 void
108 be_derived_probe::join_group (systemtap_session& s)
109 {
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;
114 }
115
116
117 void
118 be_derived_probe_group::emit_module_decls (systemtap_session& s)
119 {
120 if (probes.empty()) return;
121
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";
126
127 s.op->newline() << "/* ---- begin/end/error probes ---- */";
128
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.
131
132 sort(probes.begin(), probes.end(), be_derived_probe::comp);
133
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[] = {";
138 s.op->indent(1);
139
140 for (unsigned i=0; i < probes.size(); i++)
141 {
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() << " },";
147 }
148 s.op->newline(-1) << "};";
149
150 s.op->newline() << "static void enter_be_probe (struct stap_be_probe *stp) {";
151 s.op->indent(1);
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) << "}";
157 }
158
159 void
160 be_derived_probe_group::emit_module_init (systemtap_session& s)
161 {
162 if (probes.empty()) return;
163
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) << "}";
174 }
175
176 void
177 be_derived_probe_group::emit_module_exit (systemtap_session& s)
178 {
179 if (probes.empty()) return;
180
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) << "}";
186
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) << "}";
192 }
193
194 bool
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)
199 {
200 if (!be || be->probes.empty())
201 return false;
202
203 sort(be->probes.begin(), be->probes.end(), be_derived_probe::comp);
204
205 for (auto i = be->probes.begin(); i != be->probes.end(); ++i)
206 {
207 be_derived_probe *p = *i;
208 if (p->type == BEGIN)
209 begin_v.push_back(p);
210 }
211
212 for (auto i = be->probes.begin(); i != be->probes.end(); ++i)
213 {
214 be_derived_probe *p = *i;
215 if (p->type != BEGIN)
216 end_v.push_back(p);
217 }
218
219 return true;
220 }
221
222 // ------------------------------------------------------------------------
223 // never probes are never run
224 // ------------------------------------------------------------------------
225
226 struct never_derived_probe: public derived_probe
227 {
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); }
232 };
233
234
235 struct never_builder: public derived_probe_builder
236 {
237 never_builder() {}
238 virtual void build(systemtap_session &,
239 probe * base,
240 probe_point * location,
241 literal_map_t const &,
242 vector<derived_probe *> & finished_results)
243 {
244 finished_results.push_back(new never_derived_probe(base, location));
245 }
246
247 virtual string name() { return "never builder"; }
248 };
249
250
251
252 // ------------------------------------------------------------------------
253 // unified registration for begin/end/error/never
254 // ------------------------------------------------------------------------
255
256 void
257 register_tapset_been(systemtap_session& s)
258 {
259 match_node* root = s.pattern_root;
260
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));
267
268 root->bind(TOK_END)
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));
274
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));
281
282 root->bind(TOK_NEVER)
283 ->bind_privilege(pr_all)
284 ->bind(new never_builder());
285 }
286
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.