Branch data Line data Source code
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 [ + - ]: 2414 : static const string TOK_BEGIN("begin");
24 [ + - ]: 2414 : static const string TOK_END("end");
25 [ + - ]: 2414 : static const string TOK_ERROR("error");
26 [ + - ]: 2414 : 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 [ # # ]: 0 : struct be_derived_probe: public derived_probe
36 : : {
37 : : be_t type;
38 : : int64_t priority;
39 : :
40 : 1966 : be_derived_probe (probe* p, probe_point* l, be_t t, int64_t pr):
41 : 1966 : derived_probe (p, l), type (t), priority (pr) {}
42 : :
43 : : void join_group (systemtap_session& s);
44 : :
45 : 5167 : 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 : 5167 : return a->priority < b->priority;
52 : : }
53 : :
54 : : // No assertion need be emitted, since these probes are allowed for
55 : : // unprivileged users.
56 : 897 : void emit_privilege_assertion (translator_output*) {}
57 : :
58 : 2930 : void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged (o); }
59 : :
60 : 7085 : 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 [ # # ]: 779 : struct be_derived_probe_group: public generic_dpg<be_derived_probe>
67 : : {
68 : : public:
69 : : void emit_module_decls (systemtap_session& s);
70 : : void emit_module_init (systemtap_session& s);
71 : : void emit_module_exit (systemtap_session& s);
72 : : };
73 : :
74 [ # # ]: 0 : struct be_builder: public derived_probe_builder
75 : : {
76 : : be_t type;
77 : :
78 : 7308 : be_builder(be_t t) : type(t) {}
79 : :
80 : 1966 : virtual void build(systemtap_session &,
81 : : probe * base,
82 : : probe_point * location,
83 : : literal_map_t const & parameters,
84 : : vector<derived_probe *> & finished_results)
85 : : {
86 : : int64_t priority;
87 [ + + ][ + - ]: 2417 : if ((type == BEGIN && !get_param(parameters, TOK_BEGIN, priority)) ||
[ + + ][ + + ]
[ + + ][ + + ]
[ + + ][ + + ]
88 [ + - ]: 436 : (type == END && !get_param(parameters, TOK_END, priority)) ||
89 [ + - ]: 15 : (type == ERROR && !get_param(parameters, TOK_ERROR, priority)))
90 : 1873 : priority = 0;
91 : : finished_results.push_back
92 [ + - ][ + - ]: 1966 : (new be_derived_probe(base, location, type, priority));
[ + - ]
93 : 1966 : }
94 : : };
95 : :
96 : :
97 : : void
98 : 1966 : be_derived_probe::join_group (systemtap_session& s)
99 : : {
100 [ + + ]: 1966 : if (! s.be_derived_probes)
101 [ + - ]: 779 : s.be_derived_probes = new be_derived_probe_group ();
102 : 1966 : s.be_derived_probes->enroll (this);
103 : 1966 : }
104 : :
105 : :
106 : : void
107 : 480 : be_derived_probe_group::emit_module_decls (systemtap_session& s)
108 : : {
109 [ + - ][ + - ]: 960 : if (probes.empty()) return;
110 : :
111 [ + - ]: 480 : map<be_t, const char *> states;
112 [ + - ]: 480 : states[BEGIN] = "STAP_SESSION_STARTING";
113 [ + - ]: 480 : states[END] = "STAP_SESSION_STOPPING";
114 [ + - ]: 480 : states[ERROR] = "STAP_SESSION_ERROR";
115 : :
116 [ + - ][ + - ]: 480 : s.op->newline() << "/* ---- begin/end/error probes ---- */";
117 : :
118 : : // NB: We emit the table in sorted order here, so we don't have to
119 : : // store the priority numbers as integers and sort at run time.
120 : :
121 [ + - ][ + - ]: 480 : sort(probes.begin(), probes.end(), be_derived_probe::comp);
[ + - ]
122 : :
123 [ + - ][ + - ]: 480 : s.op->newline() << "static struct stap_be_probe {";
124 [ + - ][ + - ]: 480 : s.op->newline(1) << "const struct stap_probe * const probe;";
125 [ + - ][ + - ]: 480 : s.op->newline() << "int state, type;";
126 [ + - ][ + - ]: 480 : s.op->newline(-1) << "} stap_be_probes[] = {";
127 [ + - ]: 480 : s.op->indent(1);
128 : :
129 [ + + ]: 1944 : for (unsigned i=0; i < probes.size(); i++)
130 : : {
131 [ + - ][ + - ]: 1464 : s.op->newline () << "{";
132 [ + - ][ + - ]: 1464 : s.op->line() << " .probe=" << common_probe_init (probes[i]) << ",";
[ + - ][ + - ]
[ + - ][ + - ]
133 [ + - ][ + - ]: 1464 : s.op->line() << " .state=" << states[probes[i]->type] << ",";
[ + - ][ + - ]
[ + - ]
134 [ + - ][ + - ]: 1464 : s.op->line() << " .type=" << probes[i]->type;
[ + - ]
135 [ + - ][ + - ]: 1464 : s.op->line() << " },";
136 : : }
137 [ + - ][ + - ]: 480 : s.op->newline(-1) << "};";
138 : :
139 [ + - ][ + - ]: 480 : s.op->newline() << "static void enter_be_probe (struct stap_be_probe *stp) {";
140 [ + - ]: 480 : s.op->indent(1);
141 : : common_probe_entryfn_prologue (s, "stp->state", "stp->probe",
142 [ + - ][ + - ]: 480 : "stp_probe_type_been", false);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
143 [ + - ][ + - ]: 480 : s.op->newline() << "(*stp->probe->ph) (c);";
144 [ + - ]: 480 : common_probe_entryfn_epilogue (s, false);
145 [ + - ][ + - ]: 480 : s.op->newline(-1) << "}";
[ + - ]
146 : : }
147 : :
148 : : void
149 : 480 : be_derived_probe_group::emit_module_init (systemtap_session& s)
150 : : {
151 [ - + ]: 960 : if (probes.empty()) return;
152 : :
153 : 480 : s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
154 : 480 : s.op->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
155 : 480 : s.op->newline() << "if (stp->type == " << BEGIN << ")";
156 : 480 : s.op->newline(1) << "enter_be_probe (stp); /* rc = 0 */";
157 : : // NB: begin probes that cause errors do not constitute registration
158 : : // failures. An error message will probably get printed and if
159 : : // MAXERRORS was left at 1, we'll get an stp_exit. The
160 : : // error-handling probes will be run during the ordinary
161 : : // unregistration phase.
162 : 480 : s.op->newline(-2) << "}";
163 : : }
164 : :
165 : : void
166 : 686 : be_derived_probe_group::emit_module_exit (systemtap_session& s)
167 : : {
168 [ - + ]: 1372 : if (probes.empty()) return;
169 : :
170 : 686 : s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
171 : 686 : s.op->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
172 : 686 : s.op->newline() << "if (stp->type == " << END << ")";
173 : 686 : s.op->newline(1) << "enter_be_probe (stp);";
174 : 686 : s.op->newline(-2) << "}";
175 : :
176 : 686 : s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
177 : 686 : s.op->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
178 : 686 : s.op->newline() << "if (stp->type == " << ERROR << ")";
179 : 686 : s.op->newline(1) << "enter_be_probe (stp);";
180 : 686 : s.op->newline(-2) << "}";
181 : : }
182 : :
183 : :
184 : :
185 : : // ------------------------------------------------------------------------
186 : : // never probes are never run
187 : : // ------------------------------------------------------------------------
188 : :
189 [ # # ]: 0 : struct never_derived_probe: public derived_probe
190 : : {
191 : 93 : never_derived_probe (probe* p, probe_point* l): derived_probe (p, l) {}
192 : 93 : void join_group (systemtap_session&) { /* thus no probe_group */ }
193 : 22 : void emit_privilege_assertion (translator_output*) {}
194 : 170 : void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged (o); }
195 : : };
196 : :
197 : :
198 [ # # ]: 0 : struct never_builder: public derived_probe_builder
199 : : {
200 : 1218 : never_builder() {}
201 : 93 : virtual void build(systemtap_session &,
202 : : probe * base,
203 : : probe_point * location,
204 : : literal_map_t const &,
205 : : vector<derived_probe *> & finished_results)
206 : : {
207 [ + - ][ + - ]: 93 : finished_results.push_back(new never_derived_probe(base, location));
208 : 93 : }
209 : : };
210 : :
211 : :
212 : :
213 : : // ------------------------------------------------------------------------
214 : : // unified registration for begin/end/error/never
215 : : // ------------------------------------------------------------------------
216 : :
217 : : void
218 : 1218 : register_tapset_been(systemtap_session& s)
219 : : {
220 : 1218 : match_node* root = s.pattern_root;
221 : :
222 : : root->bind(TOK_BEGIN)
223 : : ->bind_privilege(pr_all)
224 : 1218 : ->bind(new be_builder(BEGIN));
225 : : root->bind_num(TOK_BEGIN)
226 : : ->bind_privilege(pr_all)
227 : 1218 : ->bind(new be_builder(BEGIN));
228 : :
229 : : root->bind(TOK_END)
230 : : ->bind_privilege(pr_all)
231 : 1218 : ->bind(new be_builder(END));
232 : : root->bind_num(TOK_END)
233 : : ->bind_privilege(pr_all)
234 : 1218 : ->bind(new be_builder(END));
235 : :
236 : : root->bind(TOK_ERROR)
237 : : ->bind_privilege(pr_all)
238 : 1218 : ->bind(new be_builder(ERROR));
239 : : root->bind_num(TOK_ERROR)
240 : : ->bind_privilege(pr_all)
241 : 1218 : ->bind(new be_builder(ERROR));
242 : :
243 : : root->bind(TOK_NEVER)
244 : : ->bind_privilege(pr_all)
245 : 1218 : ->bind(new never_builder());
246 [ + - ][ + - ]: 8460 : }
247 : :
248 : : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
|