]> sourceware.org Git - systemtap.git/blob - tapset-been.cxx
Merge branch 'master' into dsmith/task_finder2
[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_privilege_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) << "struct stap_probe * const probe;";
126 s.op->newline() << "int state, type;";
127 s.op->newline(-1) << "} stap_be_probes[] = {";
128 s.op->indent(1);
129
130 for (unsigned i=0; i < probes.size(); i++)
131 {
132 s.op->newline () << "{";
133 s.op->line() << " .probe=" << common_probe_init (probes[i]) << ",";
134 s.op->line() << " .state=" << states[probes[i]->type] << ",";
135 s.op->line() << " .type=" << probes[i]->type;
136 s.op->line() << " },";
137 }
138 s.op->newline(-1) << "};";
139
140 s.op->newline() << "static void enter_be_probe (struct stap_be_probe *stp) {";
141 s.op->indent(1);
142 common_probe_entryfn_prologue (s.op, "stp->state", "stp->probe",
143 "_STP_PROBE_HANDLER_BEEN", false);
144 s.op->newline() << "(*stp->probe->ph) (c);";
145 common_probe_entryfn_epilogue (s.op, false);
146 s.op->newline(-1) << "}";
147 }
148
149 void
150 be_derived_probe_group::emit_module_init (systemtap_session& s)
151 {
152 if (probes.empty()) return;
153
154 s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
155 s.op->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
156 s.op->newline() << "if (stp->type == " << BEGIN << ")";
157 s.op->newline(1) << "enter_be_probe (stp); /* rc = 0 */";
158 // NB: begin probes that cause errors do not constitute registration
159 // failures. An error message will probably get printed and if
160 // MAXERRORS was left at 1, we'll get an stp_exit. The
161 // error-handling probes will be run during the ordinary
162 // unregistration phase.
163 s.op->newline(-2) << "}";
164 }
165
166 void
167 be_derived_probe_group::emit_module_exit (systemtap_session& s)
168 {
169 if (probes.empty()) return;
170
171 s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
172 s.op->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
173 s.op->newline() << "if (stp->type == " << END << ")";
174 s.op->newline(1) << "enter_be_probe (stp);";
175 s.op->newline(-2) << "}";
176
177 s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
178 s.op->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
179 s.op->newline() << "if (stp->type == " << ERROR << ")";
180 s.op->newline(1) << "enter_be_probe (stp);";
181 s.op->newline(-2) << "}";
182 }
183
184
185
186 // ------------------------------------------------------------------------
187 // never probes are never run
188 // ------------------------------------------------------------------------
189
190 struct never_derived_probe: public derived_probe
191 {
192 never_derived_probe (probe* p, probe_point* l): derived_probe (p, l) {}
193 void join_group (systemtap_session&) { /* thus no probe_group */ }
194 void emit_privilege_assertion (translator_output*) {}
195 void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged (o); }
196 };
197
198
199 struct never_builder: public derived_probe_builder
200 {
201 never_builder() {}
202 virtual void build(systemtap_session &,
203 probe * base,
204 probe_point * location,
205 literal_map_t const &,
206 vector<derived_probe *> & finished_results)
207 {
208 finished_results.push_back(new never_derived_probe(base, location));
209 }
210 };
211
212
213
214 // ------------------------------------------------------------------------
215 // unified registration for begin/end/error/never
216 // ------------------------------------------------------------------------
217
218 void
219 register_tapset_been(systemtap_session& s)
220 {
221 match_node* root = s.pattern_root;
222
223 root->bind(TOK_BEGIN)
224 ->bind_privilege(pr_stapusr)
225 ->bind(new be_builder(BEGIN));
226 root->bind_num(TOK_BEGIN)
227 ->bind_privilege(pr_stapusr)
228 ->bind(new be_builder(BEGIN));
229
230 root->bind(TOK_END)
231 ->bind_privilege(pr_stapusr)
232 ->bind(new be_builder(END));
233 root->bind_num(TOK_END)
234 ->bind_privilege(pr_stapusr)
235 ->bind(new be_builder(END));
236
237 root->bind(TOK_ERROR)
238 ->bind_privilege(pr_stapusr)
239 ->bind(new be_builder(ERROR));
240 root->bind_num(TOK_ERROR)
241 ->bind_privilege(pr_stapusr)
242 ->bind(new be_builder(ERROR));
243
244 root->bind(TOK_NEVER)
245 ->bind_privilege(pr_stapusr)
246 ->bind(new never_builder());
247 }
248
249 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.048862 seconds and 5 git commands to generate.