summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog18
-rw-r--r--elaborate.h9
-rw-r--r--runtime/ChangeLog4
-rw-r--r--runtime/io.c21
-rw-r--r--stap.1.in13
-rw-r--r--stapfuncs.5.in8
-rw-r--r--tapset/logging.stp12
-rw-r--r--tapsets.cxx200
-rw-r--r--translate.cxx47
9 files changed, 193 insertions, 139 deletions
diff --git a/ChangeLog b/ChangeLog
index 9489c0d8..e1f6ed91 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2006-01-03 Frank Ch. Eigler <fche@redhat.com>
+
+ PR 1144, 1379
+ * tapsets.cxx (emit_probe_prologue, _epilogue): New routines.
+ Call from existing derived_probe spots. Implement soft errors in
+ epilogue code. Implement reentrancy detection in prologue code.
+ (dwarf_derived_probe::emit_deregistration): Add kprobes layer
+ "nmissed" to skipped_count.
+ * translate.cxx (varlock): Use nsleep(TRYLOCKDELAY) in lock
+ contention loop.
+ (emit_module_exit): Report number of soft errors and skipped probes.
+ (emit_function, _probe): Add __restrict__ marker to context pointer.
+ (translate_pass): Define new MAXTRYLOCK, TRYLOCKDELAY, MAXERRORS,
+ MAXSKIPPED parameters.
+ * tapset/logging.stp (error): Don't stp_error, just set context state.
+ * stap.1.in, stapfuncs.5.in: Document soft errors.
+ * elaborate.h: Corresponding changes.
+
2005-12-23 Kevin Stafford <krstaffo@us.ibm.com>
* tapset/2.6.9-20.ELsmp/syscalls.stp: added kernel
diff --git a/elaborate.h b/elaborate.h
index f2a4bd56..afaf8b18 100644
--- a/elaborate.h
+++ b/elaborate.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-// Copyright (C) 2005 Red Hat Inc.
+// Copyright (C) 2005, 2006 Red Hat Inc.
//
// This file is part of systemtap, and is free software. You can
// redistribute it and/or modify it under the terms of the GNU General
@@ -128,11 +128,14 @@ struct derived_probe: public probe
unsigned probeidx) = 0;
// ... for all probe-points:
// ELABORATE_SPECIFIC_SIGNATURE ENTRYFN {
- // /* allocate context */
+ // /* allocate context - probe_prologue */
// /* copy parameters, initial state into context */
// probe_NUMBER (context);
- // /* deallocate context */
+ // /* deallocate context - probe_epilogue */
// }
+
+ void emit_probe_prologue (translator_output* o, const std::string&);
+ void emit_probe_epilogue (translator_output* o);
};
// ------------------------------------------------------------------------
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index 7155d74c..07973c93 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,7 @@
+2006-01-03 Frank Ch. Eigler <fche@redhat.com>
+
+ * io.c (_stp_softerror): New function.
+
2005-12-14 Martin Hunt <hunt@redhat.com>
* pmap-gen.c (_stp_pmap_new_*): Initialize lock.
diff --git a/runtime/io.c b/runtime/io.c
index cf178951..b72590f3 100644
--- a/runtime/io.c
+++ b/runtime/io.c
@@ -1,6 +1,6 @@
/* -*- linux-c -*-
* I/O for printing warnings, errors and debug messages
- * Copyright (C) 2005 Red Hat Inc.
+ * Copyright (C) 2005, 2006 Red Hat Inc.
*
* This file is part of systemtap, and is free software. You can
* redistribute it and/or modify it under the terms of the GNU General
@@ -138,6 +138,25 @@ void _stp_error (const char *fmt, ...)
_stp_exit();
}
+
+/** Prints error message.
+ * This function sends an error message immediately to stpd. It
+ * will also be sent over the bulk transport (relayfs) if it is
+ * being used. If the last character is not a newline, then one
+ * is added.
+ *
+ * @param fmt A variable number of args.
+ * @sa _stp_error
+ */
+void _stp_softerror (const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ _stp_vlog (ERROR, NULL, 0, fmt, args);
+ va_end(args);
+}
+
+
static void _stp_dbug (char *func, int line, const char *fmt, ...)
{
va_list args;
diff --git a/stap.1.in b/stap.1.in
index e90bb09e..69c1e6d2 100644
--- a/stap.1.in
+++ b/stap.1.in
@@ -50,7 +50,7 @@ a named file, from standard input, or from the command line. The
program runs until it is interrupted by the user, or if the script
voluntarily invokes the
.I exit()
-function, or by any fatal error.
+function, or by sufficient number of soft errors.
.PP
The language, which is described in a later section, is strictly typed,
declaration free, procedural, and inspired by
@@ -639,8 +639,9 @@ the module then communicates with it, copying trace data from the
kernel into temporary files, until the user sends an interrupt signal.
Any run-time error encountered by the probe handlers, such as running
out of memory, division by zero, exceeding nesting or runtime limits,
-results in an error condition that prevents further probes from
-running. Finally, stpd unloads the module, and cleans up.
+results in a soft error indication. Soft errors in excess of
+MAXERRORS block of all subsequent probes, and terminate the session.
+Finally, stpd unloads the module, and cleans up.
.SH EXAMPLES
See the
@@ -692,6 +693,12 @@ Maximum number of statements to execute during any single probe hit.
.TP
MAXMAPENTRIES
Maximum number of rows in any single global array.
+.TP
+MAXERRORS
+Maximum number of soft errors before an exit is triggered.
+.TP
+MAXSKIPPED
+Maximum number of skipped reentrant probes before an exit is triggered.
.PP
In case something goes wrong with
diff --git a/stapfuncs.5.in b/stapfuncs.5.in
index 806a0906..56d6aed5 100644
--- a/stapfuncs.5.in
+++ b/stapfuncs.5.in
@@ -48,13 +48,13 @@ prepends the string "WARNING:".
.TP
error:unknown (msg:string)
-A fatal error has occurred. Log the given string to the error stream.
+An error has occurred. Log the given string to the error stream.
Append an implicit end-of-line.
.I stpd
prepends the string "ERROR:".
-Block any further execution of statements in this probe, block
-any new probe handlers, and end the systemtap session as soon
-as possible.
+Block any further execution of statements in this probe. If the number
+of errors so far exceeds the MAXERRORS parameter, also trigger an
+.IR exit() .
.TP
exit:unknown ()
diff --git a/tapset/logging.stp b/tapset/logging.stp
index 54f4c272..c9c60c8d 100644
--- a/tapset/logging.stp
+++ b/tapset/logging.stp
@@ -1,5 +1,5 @@
// logging tapset
-// Copyright (C) 2005 Red Hat Inc.
+// Copyright (C) 2005, 2006 Red Hat Inc.
//
// This file is part of systemtap, and is free software. You can
// redistribute it and/or modify it under the terms of the GNU General
@@ -26,6 +26,12 @@ function exit () %{
%}
function error (msg:string) %{
- CONTEXT->last_error = "called error()"; /* kill current probe */
- _stp_error ("%s", THIS->msg); /* implies _stp_exit */
+ /* This is an assignment of a local char[] to a global char*.
+ It would normally be just as unsafe as returning a pointer to
+ a local variable from a function. However, the translated
+ code ensures that upon an error (last_error != NULL), the
+ context stack is only ever unwound, and not reused, before
+ the probe-level stp-error call. */
+ CONTEXT->last_error = THIS->msg;
+ CONTEXT->last_stmt = NULL;
%}
diff --git a/tapsets.cxx b/tapsets.cxx
index fcf84820..a6c57b80 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1,5 +1,5 @@
// tapset resolution
-// Copyright (C) 2005 Red Hat Inc.
+// Copyright (C) 2005, 2006 Red Hat Inc.
// Copyright (C) 2005 Intel Corporation.
//
// This file is part of systemtap, and is free software. You can
@@ -86,6 +86,63 @@ lex_cast_qstring(IN const & in)
// ------------------------------------------------------------------------
+
+void
+derived_probe::emit_probe_prologue (translator_output* o,
+ const std::string& statereq)
+{
+ o->newline() << "struct context* c = per_cpu_ptr "
+ << "(contexts, smp_processor_id());";
+ o->newline() << "if (atomic_read (&session_state) != " << statereq << ")";
+ o->newline(1) << "goto probe_epilogue;";
+
+ o->newline(-1) << "if (unlikely (atomic_inc_return (&c->busy) != 1)) {";
+
+ o->newline(1) << "if (atomic_inc_return (& skipped_count) > MAXSKIPPED) {";
+ o->newline(1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
+ // NB: We don't assume that we can safely call stp_error etc. in such
+ // a reentrant context. But this is OK:
+ o->newline() << "_stp_exit ();";
+ o->newline(-1) << "}";
+
+ o->newline() << "atomic_dec (& c->busy);";
+ o->newline() << "goto probe_epilogue;";
+ o->newline(-1) << "}";
+ o->newline();
+ o->newline() << "c->last_error = 0;";
+ o->newline() << "c->probe_point = probe_point;";
+ o->newline() << "c->nesting = 0;";
+ o->newline() << "c->regs = 0;";
+ o->newline() << "c->actioncount = 0;";
+}
+
+void
+derived_probe::emit_probe_epilogue (translator_output* o)
+{
+ o->newline() << "if (unlikely (c->last_error && c->last_error[0])) {";
+ o->newline(1) << "if (c->last_stmt != NULL)";
+ o->newline(1) << "_stp_softerror (\"%s near %s\", c->last_error, c->last_stmt);";
+ o->newline(-1) << "else";
+ o->newline(1) << "_stp_softerror (\"%s\", c->last_error);";
+ o->indent(-1);
+ o->newline() << "atomic_inc (& error_count);";
+
+ o->newline() << "if (atomic_read (& error_count) > MAXERRORS) {";
+ o->newline(1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
+ o->newline() << "_stp_exit ();";
+ o->newline(-1) << "}";
+
+ o->newline(-1) << "}";
+
+ o->newline() << "atomic_dec (&c->busy);";
+ o->newline(-1) << "probe_epilogue: ;";
+ o->indent(1);
+}
+
+
+
+
+// ------------------------------------------------------------------------
// begin/end probes are run right during registration / deregistration
// ------------------------------------------------------------------------
@@ -147,40 +204,19 @@ be_derived_probe::emit_probe_entries (translator_output* o, unsigned j)
// While begin/end probes are executed single-threaded, we
// still code defensively and use a per-cpu context.
- o->newline(1) << "struct context* c = per_cpu_ptr (contexts, smp_processor_id());";
+ o->indent(1);
o->newline() << "const char* probe_point = "
- << lex_cast_qstring(*l) << ";";
-
- // A precondition for running a probe handler is that we're in STARTING
- // or STOPPING state (not ERROR), and that no one else is already using
- // this context.
- o->newline() << "if (atomic_read (&session_state) != ";
- if (begin) o->line() << "STAP_SESSION_STARTING)";
- else o->line() << "STAP_SESSION_STOPPING)";
- o->newline(1) << "return;";
- o->newline(-1) << "if (atomic_inc_return (&c->busy) != 1) {";
- o->newline(1) << "_stp_warn (\"probe reentrancy (%s vs %s)\\n\", "
- << "c->probe_point, probe_point);";
- o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
- o->newline() << "atomic_dec (&c->busy);";
- o->newline() << "return;";
- o->newline(-1) << "}";
- o->newline();
- o->newline() << "c->last_error = 0;";
- o->newline() << "c->probe_point = probe_point;";
- o->newline() << "c->nesting = 0;";
- o->newline() << "c->regs = 0;";
- o->newline() << "c->actioncount = 0;";
+ << lex_cast_qstring(*l) << ";";
+ emit_probe_prologue (o,
+ (begin ?
+ "STAP_SESSION_STARTING" :
+ "STAP_SESSION_STOPPING"));
// NB: locals are initialized by probe function itself
o->newline() << "probe_" << j << " (c);";
- o->newline() << "if (c->last_error && c->last_error[0]) {";
- o->newline(1) << "_stp_error (\"%s near %s\", c->last_error, c->last_stmt);";
- o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
- o->newline(-1) << "}";
+ emit_probe_epilogue (o);
- o->newline() << "atomic_dec (&c->busy);";
o->newline(-1) << "}" << endl;
}
}
@@ -2936,12 +2972,24 @@ dwarf_derived_probe::emit_deregistrations (translator_output* o, unsigned proben
{
o->newline() << "#ifdef ARCH_SUPPORTS_KRETPROBES";
o->newline() << "unregister_kretprobe (&(" << probe_name << "));";
+ o->newline() << "atomic_add ("
+ << probe_name << ".kp.nmissed,"
+ << "& skipped_count);";
+ o->newline() << "atomic_add ("
+ << probe_name << ".nmissed,"
+ << "& skipped_count);";
o->newline() << "#else";
o->newline() << ";";
o->newline() << "#endif";
}
else
- o->newline() << "unregister_kprobe (&(" << probe_name << "));";
+ {
+ o->newline() << "unregister_kprobe (&(" << probe_name << "));";
+ o->newline() << "atomic_add ("
+ << probe_name << ".nmissed,"
+ << "& skipped_count);";
+ }
+
o->indent(-1);
o->newline(-1) << "}";
}
@@ -3053,7 +3101,7 @@ dwarf_derived_probe::emit_probe_entries (translator_output* o,
else
o->line() << "struct kprobe *probe_instance";
o->line() << ", struct pt_regs *regs) {";
- o->newline(1) << "struct context* c = per_cpu_ptr (contexts, smp_processor_id());";
+ o->indent(1);
// Calculate the name of the current probe by finding its index in the probe array.
if (has_return)
@@ -3064,35 +3112,14 @@ dwarf_derived_probe::emit_probe_entries (translator_output* o,
o->newline() << "const char* probe_point = "
<< string_array
<< "[ (probe_instance - &(" << probe_array << "[0]))];";
-
- // A precondition for running a probe handler is that we're in RUNNING
- // state (not ERROR), and that no one else is already using this context.
- o->newline() << "if (atomic_read (&session_state) != STAP_SESSION_RUNNING)";
- o->newline(1) << "return 0;";
- o->newline(-1) << "if (atomic_inc_return (&c->busy) != 1) {";
- o->newline(1) << "_stp_warn (\"probe reentrancy (%s vs %s)\\n\", "
- << "c->probe_point, probe_point);";
- o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
- o->newline() << "atomic_dec (&c->busy);";
- o->newline() << "return 0;";
- o->newline(-1) << "}";
- o->newline();
-
- o->newline() << "c->last_error = 0;";
- o->newline() << "c->probe_point = probe_point;";
- o->newline() << "c->nesting = 0;";
+ emit_probe_prologue (o, "STAP_SESSION_RUNNING");
o->newline() << "c->regs = regs;";
- o->newline() << "c->actioncount = 0;";
// NB: locals are initialized by probe function itself
o->newline() << "probe_" << probenum << " (c);";
- o->newline() << "if (c->last_error && c->last_error[0]) {";
- o->newline(1) << "_stp_error (\"%s near %s\", c->last_error, c->last_stmt);";
- o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
- o->newline(-1) << "}";
+ emit_probe_epilogue (o);
- o->newline() << "atomic_dec (& c->busy);";
o->newline() << "return 0;";
o->newline(-1) << "}" << endl;
if (has_return)
@@ -3244,26 +3271,12 @@ timer_derived_probe::emit_probe_entries (translator_output* o, unsigned j)
o->newline() << "static struct timer_list timer_" << j << ";";
o->newline() << "void enter_" << j << " (unsigned long val) {";
- o->newline(1) << "struct context* c = per_cpu_ptr (contexts, smp_processor_id());";
+ o->indent(1);
o->newline() << "const char* probe_point = "
<< lex_cast_qstring(*locations[0]) << ";";
- o->newline() << "(void) val;";
-
- // A precondition for running a probe handler is that we're in
- // RUNNING state (not ERROR), and that no one else is already using
- // this context.
- o->newline() << "if (atomic_read (&session_state) != STAP_SESSION_RUNNING)";
- o->newline(1) << "return;";
-
- o->newline(-1) << "if (atomic_inc_return (&c->busy) != 1) {";
- o->newline(1) << "_stp_warn (\"probe reentrancy (%s vs %s)\\n\", "
- << "c->probe_point, probe_point);";
- o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
- o->newline() << "atomic_dec (&c->busy);";
- o->newline() << "return;";
- o->newline(-1) << "}";
- o->newline();
+ emit_probe_prologue (o, "STAP_SESSION_RUNNING");
+ o->newline() << "(void) val;";
o->newline() << "mod_timer (& timer_" << j << ", jiffies + ";
if (time_is_msecs)
o->line() << "msecs_to_jiffies(";
@@ -3274,21 +3287,10 @@ timer_derived_probe::emit_probe_entries (translator_output* o, unsigned j)
o->line() << ")";
o->line() << ");";
- o->newline() << "c->probe_point = probe_point;";
- o->newline() << "c->last_error = 0;";
- o->newline() << "c->nesting = 0;";
- o->newline() << "c->regs = 0;";
- o->newline() << "c->actioncount = 0;";
-
// NB: locals are initialized by probe function itself
o->newline() << "probe_" << j << " (c);";
- o->newline() << "if (c->last_error && c->last_error[0]) {";
- o->newline(1) << "_stp_error (\"%s near %s\", c->last_error, c->last_stmt);";
- o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
- o->newline(-1) << "}";
-
- o->newline() << "atomic_dec (&c->busy);";
+ emit_probe_epilogue (o);
o->newline(-1) << "}" << endl;
}
@@ -3394,45 +3396,19 @@ profile_derived_probe::emit_probe_entries (translator_output* o, unsigned j)
o->newline() << "int enter_" << j << " (struct pt_regs *regs) {";
}
- o->newline(1) << "struct context* c = per_cpu_ptr (contexts, smp_processor_id());";
+ o->indent(1);
o->newline() << "const char* probe_point = "
<< lex_cast_qstring(*locations[0]) << ";";
+ emit_probe_prologue (o, "STAP_SESSION_RUNNING");
if (using_rpn) {
o->newline() << "(void) self;";
o->newline() << "(void) val;";
}
- // A precondition for running a probe handler is that we're in
- // RUNNING state (not ERROR), and that no one else is already using
- // this context.
- o->newline() << "if (atomic_read (&session_state) != STAP_SESSION_RUNNING)";
- o->newline(1) << "return 0;";
-
- o->newline(-1) << "if (atomic_inc_return (&c->busy) != 1) {";
- o->newline(1) << "_stp_warn (\"probe reentrancy (%s vs %s)\\n\", "
- << "c->probe_point, probe_point);";
- o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
- o->newline() << "atomic_dec (&c->busy);";
- o->newline() << "return 0;";
- o->newline(-1) << "}";
- o->newline();
-
- o->newline() << "c->probe_point = probe_point;";
- o->newline() << "c->last_error = 0;";
- o->newline() << "c->nesting = 0;";
- o->newline() << "c->regs = regs;";
- o->newline() << "c->actioncount = 0;";
-
- // NB: locals are initialized by probe function itself
o->newline() << "probe_" << j << " (c);";
- o->newline() << "if (c->last_error && c->last_error[0]) {";
- o->newline(1) << "_stp_error (\"%s near %s\", c->last_error, c->last_stmt);";
- o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
- o->newline(-1) << "}";
-
- o->newline() << "atomic_dec (&c->busy);";
+ emit_probe_epilogue (o);
o->newline() << "return 0;";
o->newline(-1) << "}" << endl;
}
diff --git a/translate.cxx b/translate.cxx
index bda28e8b..78788de9 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -1,5 +1,5 @@
// translation pass
-// Copyright (C) 2005 Red Hat Inc.
+// Copyright (C) 2005, 2006 Red Hat Inc.
// Copyright (C) 2005 Intel Corporation
//
// This file is part of systemtap, and is free software. You can
@@ -444,11 +444,10 @@ struct varlock
c.o->newline() << "{";
c.o->newline(1) << "unsigned trylock_count = 0;";
c.o->newline() << "while ("
- << "!(write_trylock (& " << v << "_lock))"
- << " && "
- << "(trylock_count++ < MAXTRYLOCK)"
- << ") ; /* spin */";
- c.o->newline() << "if (unlikely (trylock_count >= MAXTRYLOCK)) {";
+ << "!(write_trylock (& " << v << "_lock)) &&";
+ c.o->newline(1) << "(trylock_count++ < MAXTRYLOCK)"
+ << ") ndelay (TRYLOCKDELAY); /* spin */";
+ c.o->newline(-1) << "if (unlikely (trylock_count >= MAXTRYLOCK)) {";
c.o->newline(1) << "c->last_error = \"locking timeout over variable "
<< v << "\";";
c.o->newline() << "goto " << post_unlock_label << ";";
@@ -820,6 +819,8 @@ c_unparser::emit_common_header ()
o->newline() << "#define STAP_SESSION_STOPPING 3";
o->newline() << "#define STAP_SESSION_STOPPED 4";
o->newline() << "atomic_t session_state = ATOMIC_INIT (STAP_SESSION_STARTING);";
+ o->newline() << "atomic_t error_count = ATOMIC_INIT (0);";
+ o->newline() << "atomic_t skipped_count = ATOMIC_INIT (0);";
o->newline();
o->newline() << "struct context {";
o->newline(1) << "atomic_t busy;";
@@ -942,7 +943,7 @@ void
c_unparser::emit_functionsig (functiondecl* v)
{
o->newline() << "static void function_" << v->name
- << " (struct context *c);";
+ << " (struct context * __restrict__ c);";
}
@@ -1101,6 +1102,15 @@ c_unparser::emit_module_exit ()
o->newline() << "free_percpu (contexts);";
+ // print final error/reentrancy counts if non-zero
+ o->newline() << "if (atomic_read (& skipped_count) || "
+ << "atomic_read (& error_count))";
+ o->newline(1) << "_stp_warn (\"Number of errors: %d, "
+ << "skipped probes: %d\\n\", "
+ << "(int) atomic_read (& error_count), "
+ << "(int) atomic_read (& skipped_count));";
+ o->indent(-1);
+
o->newline(-1) << "}" << endl;
}
@@ -1109,7 +1119,7 @@ void
c_unparser::emit_function (functiondecl* v)
{
o->newline() << "void function_" << c_varname (v->name)
- << " (struct context* c) {";
+ << " (struct context* __restrict__ c) {";
o->indent(1);
this->current_probe = 0;
this->current_probenum = 0;
@@ -1160,8 +1170,8 @@ c_unparser::emit_function (functiondecl* v)
void
c_unparser::emit_probe (derived_probe* v, unsigned i)
{
- o->newline() << "static void probe_" << i << " (struct context *c);";
- o->newline() << "void probe_" << i << " (struct context *c) {";
+ // o->newline() << "static void probe_" << i << " (struct context *c);";
+ o->newline() << "static void probe_" << i << " (struct context * __restrict__ c) {";
o->indent(1);
// initialize frame pointer
@@ -1667,6 +1677,7 @@ c_unparser::visit_statement (statement *s, unsigned actions)
if (actions > 0)
{
o->newline() << "c->actioncount += " << actions << ";";
+ // XXX: This check is inserted too frequently.
o->newline() << "if (unlikely (c->actioncount > MAXACTION)) {";
o->newline(1) << "c->last_error = \"MAXACTION exceeded\";";
o->newline() << "goto " << outlabel << ";";
@@ -3437,15 +3448,24 @@ translate_pass (systemtap_session& s)
s.op->newline() << "#ifndef MAXSTRINGLEN";
s.op->newline() << "#define MAXSTRINGLEN 128";
s.op->newline() << "#endif";
- s.op->newline() << "#ifndef MAXTRYLOCK";
- s.op->newline() << "#define MAXTRYLOCK 20";
- s.op->newline() << "#endif";
s.op->newline() << "#ifndef MAXACTION";
s.op->newline() << "#define MAXACTION 1000";
s.op->newline() << "#endif";
+ s.op->newline() << "#ifndef MAXTRYLOCK";
+ s.op->newline() << "#define MAXTRYLOCK MAXACTION";
+ s.op->newline() << "#endif";
+ s.op->newline() << "#ifndef TRYLOCKDELAY";
+ s.op->newline() << "#define TRYLOCKDELAY 100";
+ s.op->newline() << "#endif";
s.op->newline() << "#ifndef MAXMAPENTRIES";
s.op->newline() << "#define MAXMAPENTRIES 2048";
s.op->newline() << "#endif";
+ s.op->newline() << "#ifndef MAXERRORS";
+ s.op->newline() << "#define MAXERRORS 10";
+ s.op->newline() << "#endif";
+ s.op->newline() << "#ifndef MAXSKIPPED";
+ s.op->newline() << "#define MAXSKIPPED 100";
+ s.op->newline() << "#endif";
// impedance mismatch
s.op->newline() << "#define STP_STRING_SIZE MAXSTRINGLEN";
@@ -3463,6 +3483,7 @@ translate_pass (systemtap_session& s)
s.op->newline() << "#include \"regs.c\"";
s.op->newline() << "#include <linux/string.h>";
s.op->newline() << "#include <linux/timer.h>";
+ s.op->newline() << "#include <linux/delay.h>";
s.op->newline() << "#include <linux/profile.h>";
s.op->newline() << "#endif";
s.op->newline() << "#include \"loc2c-runtime.h\" ";