]>
sourceware.org Git - systemtap.git/blob - tapset-been.cxx
99b59574bf90b828e7623ee474640bf35f9c9eca
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
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
13 #include "translate.h"
21 using namespace __gnu_cxx
;
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");
30 // ------------------------------------------------------------------------
31 // begin/end/error probes are run right during registration / deregistration
32 // ------------------------------------------------------------------------
34 enum be_t
{ BEGIN
, END
, ERROR
};
36 struct be_derived_probe
: public derived_probe
41 be_derived_probe (probe
* p
, probe_point
* l
, be_t t
, int64_t pr
):
42 derived_probe (p
, l
), type (t
), priority (pr
) {}
44 void join_group (systemtap_session
& s
);
46 static inline bool comp(be_derived_probe
const *a
,
47 be_derived_probe
const *b
)
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
;
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
61 struct be_derived_probe_group
: public generic_dpg
<be_derived_probe
>
64 void emit_module_decls (systemtap_session
& s
);
65 void emit_module_init (systemtap_session
& s
);
66 void emit_module_exit (systemtap_session
& s
);
69 struct be_builder
: public derived_probe_builder
73 be_builder(be_t t
) : type(t
) {}
75 virtual void build(systemtap_session
&,
77 probe_point
* location
,
78 literal_map_t
const & parameters
,
79 vector
<derived_probe
*> & finished_results
)
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
)))
86 finished_results
.push_back
87 (new be_derived_probe(base
, location
, type
, priority
));
93 be_derived_probe::join_group (systemtap_session
& s
)
95 if (! s
.be_derived_probes
)
96 s
.be_derived_probes
= new be_derived_probe_group ();
97 s
.be_derived_probes
->enroll (this);
102 be_derived_probe_group::emit_module_decls (systemtap_session
& s
)
104 if (probes
.empty()) return;
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";
111 s
.op
->newline() << "/* ---- begin/end/error probes ---- */";
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.
116 sort(probes
.begin(), probes
.end(), be_derived_probe::comp
);
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[] = {";
125 for (unsigned i
=0; i
< probes
.size(); i
++)
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() << " },";
135 s
.op
->newline(-1) << "};";
137 s
.op
->newline() << "static void enter_be_probe (struct stap_be_probe *stp) {";
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) << "}";
146 be_derived_probe_group::emit_module_init (systemtap_session
& s
)
148 if (probes
.empty()) return;
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) << "}";
163 be_derived_probe_group::emit_module_exit (systemtap_session
& s
)
165 if (probes
.empty()) return;
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) << "}";
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) << "}";
182 // ------------------------------------------------------------------------
183 // never probes are never run
184 // ------------------------------------------------------------------------
186 struct never_derived_probe
: public derived_probe
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 */ }
194 struct never_builder
: public derived_probe_builder
197 virtual void build(systemtap_session
&,
199 probe_point
* location
,
200 literal_map_t
const &,
201 vector
<derived_probe
*> & finished_results
)
203 finished_results
.push_back(new never_derived_probe(base
, location
));
209 // ------------------------------------------------------------------------
210 // unified registration for begin/end/error/never
211 // ------------------------------------------------------------------------
214 register_tapset_been(systemtap_session
& s
)
216 match_node
* root
= s
.pattern_root
;
218 root
->bind(TOK_BEGIN
)
219 ->allow_unprivileged()
220 ->bind(new be_builder(BEGIN
));
221 root
->bind_num(TOK_BEGIN
)
222 ->allow_unprivileged()
223 ->bind(new be_builder(BEGIN
));
226 ->allow_unprivileged()
227 ->bind(new be_builder(END
));
228 root
->bind_num(TOK_END
)
229 ->allow_unprivileged()
230 ->bind(new be_builder(END
));
232 root
->bind(TOK_ERROR
)
233 ->allow_unprivileged()
234 ->bind(new be_builder(ERROR
));
235 root
->bind_num(TOK_ERROR
)
236 ->allow_unprivileged()
237 ->bind(new be_builder(ERROR
));
239 root
->bind(TOK_NEVER
)
240 ->allow_unprivileged()
241 ->bind(new never_builder());
244 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.048195 seconds and 5 git commands to generate.