]> sourceware.org Git - systemtap.git/blob - tapset-been.cxx
Merge branch 'master' of git://sources.redhat.com/git/systemtap
[systemtap.git] / tapset-been.cxx
1 // tapset for begin/end/error/never
2 // Copyright (C) 2005-2009 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 bool needs_global_locks () { return false; }
56 // begin/end probes don't need locks around global variables, since
57 // they aren't run concurrently with any other probes
58 };
59
60
61 struct be_derived_probe_group: public generic_dpg<be_derived_probe>
62 {
63 public:
64 void emit_module_decls (systemtap_session& s);
65 void emit_module_init (systemtap_session& s);
66 void emit_module_exit (systemtap_session& s);
67 };
68
69 struct be_builder: public derived_probe_builder
70 {
71 be_t type;
72
73 be_builder(be_t t) : type(t) {}
74
75 virtual void build(systemtap_session &,
76 probe * base,
77 probe_point * location,
78 literal_map_t const & parameters,
79 vector<derived_probe *> & finished_results)
80 {
81 int64_t priority;
82 if ((type == BEGIN && !get_param(parameters, TOK_BEGIN, priority)) ||
83 (type == END && !get_param(parameters, TOK_END, priority)) ||
84 (type == ERROR && !get_param(parameters, TOK_ERROR, priority)))
85 priority = 0;
86 finished_results.push_back
87 (new be_derived_probe(base, location, type, priority));
88 }
89 };
90
91
92 void
93 be_derived_probe::join_group (systemtap_session& s)
94 {
95 if (! s.be_derived_probes)
96 s.be_derived_probes = new be_derived_probe_group ();
97 s.be_derived_probes->enroll (this);
98 }
99
100
101 void
102 be_derived_probe_group::emit_module_decls (systemtap_session& s)
103 {
104 if (probes.empty()) return;
105
106 map<be_t, const char *> states;
107 states[BEGIN] = "STAP_SESSION_STARTING";
108 states[END] = "STAP_SESSION_STOPPING";
109 states[ERROR] = "STAP_SESSION_ERROR";
110
111 s.op->newline() << "/* ---- begin/end/error probes ---- */";
112
113 // NB: We emit the table in sorted order here, so we don't have to
114 // store the priority numbers as integers and sort at run time.
115
116 sort(probes.begin(), probes.end(), be_derived_probe::comp);
117
118 s.op->newline() << "static struct stap_be_probe {";
119 s.op->newline(1) << "void (*ph)(struct context*);";
120 s.op->newline() << "const char* pp;";
121 s.op->newline() << "int state, type;";
122 s.op->newline(-1) << "} stap_be_probes[] = {";
123 s.op->indent(1);
124
125 for (unsigned i=0; i < probes.size(); i++)
126 {
127 s.op->newline () << "{";
128 s.op->line() << " .pp="
129 << lex_cast_qstring (*probes[i]->sole_location()) << ",";
130 s.op->line() << " .ph=&" << probes[i]->name << ",";
131 s.op->line() << " .state=" << states[probes[i]->type] << ",";
132 s.op->line() << " .type=" << probes[i]->type;
133 s.op->line() << " },";
134 }
135 s.op->newline(-1) << "};";
136
137 s.op->newline() << "static void enter_be_probe (struct stap_be_probe *stp) {";
138 s.op->indent(1);
139 common_probe_entryfn_prologue (s.op, "stp->state", "stp->pp", false);
140 s.op->newline() << "(*stp->ph) (c);";
141 common_probe_entryfn_epilogue (s.op, false);
142 s.op->newline(-1) << "}";
143 }
144
145 void
146 be_derived_probe_group::emit_module_init (systemtap_session& s)
147 {
148 if (probes.empty()) return;
149
150 s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
151 s.op->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
152 s.op->newline() << "if (stp->type == " << BEGIN << ")";
153 s.op->newline(1) << "enter_be_probe (stp); /* rc = 0 */";
154 // NB: begin probes that cause errors do not constitute registration
155 // failures. An error message will probably get printed and if
156 // MAXERRORS was left at 1, we'll get an stp_exit. The
157 // error-handling probes will be run during the ordinary
158 // unregistration phase.
159 s.op->newline(-2) << "}";
160 }
161
162 void
163 be_derived_probe_group::emit_module_exit (systemtap_session& s)
164 {
165 if (probes.empty()) return;
166
167 s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
168 s.op->newline(1) << "struct stap_be_probe* stp = & stap_be_probes [i];";
169 s.op->newline() << "if (stp->type == " << END << ")";
170 s.op->newline(1) << "enter_be_probe (stp);";
171 s.op->newline(-2) << "}";
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 == " << ERROR << ")";
176 s.op->newline(1) << "enter_be_probe (stp);";
177 s.op->newline(-2) << "}";
178 }
179
180
181
182 // ------------------------------------------------------------------------
183 // never probes are never run
184 // ------------------------------------------------------------------------
185
186 struct never_derived_probe: public derived_probe
187 {
188 never_derived_probe (probe* p): derived_probe (p) {}
189 never_derived_probe (probe* p, probe_point* l): derived_probe (p, l) {}
190 void join_group (systemtap_session&) { /* thus no probe_group */ }
191 };
192
193
194 struct never_builder: public derived_probe_builder
195 {
196 never_builder() {}
197 virtual void build(systemtap_session &,
198 probe * base,
199 probe_point * location,
200 literal_map_t const &,
201 vector<derived_probe *> & finished_results)
202 {
203 finished_results.push_back(new never_derived_probe(base, location));
204 }
205 };
206
207
208
209 // ------------------------------------------------------------------------
210 // unified registration for begin/end/error/never
211 // ------------------------------------------------------------------------
212
213 void
214 register_tapset_been(systemtap_session& s)
215 {
216 match_node* root = s.pattern_root;
217
218 root->bind(TOK_BEGIN)->allow_unprivileged()->bind(new be_builder(BEGIN));
219 root->bind_num(TOK_BEGIN)->allow_unprivileged()->bind(new be_builder(BEGIN));
220 root->bind(TOK_END)->allow_unprivileged()->bind(new be_builder(END));
221 root->bind_num(TOK_END)->allow_unprivileged()->bind(new be_builder(END));
222 root->bind(TOK_ERROR)->allow_unprivileged()->bind(new be_builder(ERROR));
223 root->bind_num(TOK_ERROR)->allow_unprivileged()->bind(new be_builder(ERROR));
224
225 root->bind(TOK_NEVER)->allow_unprivileged()->bind(new never_builder());
226 }
227
228 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.052507 seconds and 6 git commands to generate.