]> sourceware.org Git - systemtap.git/blob - tapset-been.cxx
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
[systemtap.git] / 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
5 //
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
9 // later version.
10
11 #include "session.h"
12 #include "tapsets.h"
13 #include "translate.h"
14 #include "util.h"
15
16 #include <algorithm>
17 #include <string>
18
19
20 using namespace std;
21 using namespace __gnu_cxx;
22
23
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");
28
29
30 // ------------------------------------------------------------------------
31 // begin/end/error probes are run right during registration / deregistration
32 // ------------------------------------------------------------------------
33
34 enum be_t { BEGIN, END, ERROR };
35
36 struct be_derived_probe: public derived_probe
37 {
38 be_t type;
39 int64_t priority;
40
41 be_derived_probe (probe* p, probe_point* l, be_t t, int64_t pr):
42 derived_probe (p, l), type (t), priority (pr) {}
43
44 void join_group (systemtap_session& s);
45
46 static inline bool comp(be_derived_probe const *a,
47 be_derived_probe const *b)
48 {
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;
53 }
54
55 // No assertion need be emitted, since these probes are allowed for
56 // unprivileged users.
57 void emit_unprivileged_assertion (translator_output*) {}
58
59 void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged (o); }
60
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
64 };
65
66
67 struct be_derived_probe_group: public generic_dpg<be_derived_probe>
68 {
69 public:
70 void emit_module_decls (systemtap_session& s);
71 void emit_module_init (systemtap_session& s);
72 void emit_module_exit (systemtap_session& s);
73 };
74
75 struct be_builder: public derived_probe_builder
76 {
77 be_t type;
78
79 be_builder(be_t t) : type(t) {}
80
81 virtual void build(systemtap_session &,
82 probe * base,
83 probe_point * location,
84 literal_map_t const & parameters,
85 vector<derived_probe *> & finished_results)
86 {
87 int64_t priority;
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)))
91 priority = 0;
92 finished_results.push_back
93 (new be_derived_probe(base, location, type, priority));
94 }
95 };
96
97
98 void
99 be_derived_probe::join_group (systemtap_session& s)
100 {
101 if (! s.be_derived_probes)
102 s.be_derived_probes = new be_derived_probe_group ();
103 s.be_derived_probes->enroll (this);
104 }
105
106
107 void
108 be_derived_probe_group::emit_module_decls (systemtap_session& s)
109 {
110 if (probes.empty()) return;
111
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";
116
117 s.op->newline() << "/* ---- begin/end/error probes ---- */";
118
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.
121
122 sort(probes.begin(), probes.end(), be_derived_probe::comp);
123
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[] = {";
129 s.op->indent(1);
130
131 for (unsigned i=0; i < probes.size(); i++)
132 {
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() << " },";
140 }
141 s.op->newline(-1) << "};";
142
143 s.op->newline() << "static void enter_be_probe (struct stap_be_probe *stp) {";
144 s.op->indent(1);
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) << "}";
149 }
150
151 void
152 be_derived_probe_group::emit_module_init (systemtap_session& s)
153 {
154 if (probes.empty()) return;
155
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) << "}";
166 }
167
168 void
169 be_derived_probe_group::emit_module_exit (systemtap_session& s)
170 {
171 if (probes.empty()) return;
172
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) << "}";
178
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) << "}";
184 }
185
186
187
188 // ------------------------------------------------------------------------
189 // never probes are never run
190 // ------------------------------------------------------------------------
191
192 struct never_derived_probe: public derived_probe
193 {
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); }
199 };
200
201
202 struct never_builder: public derived_probe_builder
203 {
204 never_builder() {}
205 virtual void build(systemtap_session &,
206 probe * base,
207 probe_point * location,
208 literal_map_t const &,
209 vector<derived_probe *> & finished_results)
210 {
211 finished_results.push_back(new never_derived_probe(base, location));
212 }
213 };
214
215
216
217 // ------------------------------------------------------------------------
218 // unified registration for begin/end/error/never
219 // ------------------------------------------------------------------------
220
221 void
222 register_tapset_been(systemtap_session& s)
223 {
224 match_node* root = s.pattern_root;
225
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));
232
233 root->bind(TOK_END)
234 ->bind_unprivileged()
235 ->bind(new be_builder(END));
236 root->bind_num(TOK_END)
237 ->bind_unprivileged()
238 ->bind(new be_builder(END));
239
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));
246
247 root->bind(TOK_NEVER)
248 ->bind_unprivileged()
249 ->bind(new never_builder());
250 }
251
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.