diff options
author | fche <fche> | 2006-01-03 22:33:53 +0000 |
---|---|---|
committer | fche <fche> | 2006-01-03 22:33:53 +0000 |
commit | 9a604face6354d63a3948a08e85613168a9dfb88 (patch) | |
tree | 3b4f269604baebeb2da9c84e973bed06202bd980 | |
parent | f256184bbdab4cf63c5ad8917e5b8a31de497fb9 (diff) | |
download | systemtap-steved-9a604face6354d63a3948a08e85613168a9dfb88.tar.gz systemtap-steved-9a604face6354d63a3948a08e85613168a9dfb88.tar.xz systemtap-steved-9a604face6354d63a3948a08e85613168a9dfb88.zip |
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.
2006-01-03 Frank Ch. Eigler <fche@redhat.com>
* io.c (_stp_softerror): New function.
2006-01-03 Frank Ch. Eigler <fche@redhat.com>
* systemtap.base/timers.exp: Extend the test run duration.
Accept skipped probe warnings at shutdown.
-rw-r--r-- | ChangeLog | 18 | ||||
-rw-r--r-- | elaborate.h | 9 | ||||
-rw-r--r-- | runtime/ChangeLog | 4 | ||||
-rw-r--r-- | runtime/io.c | 21 | ||||
-rw-r--r-- | stap.1.in | 13 | ||||
-rw-r--r-- | stapfuncs.5.in | 8 | ||||
-rw-r--r-- | tapset/logging.stp | 12 | ||||
-rw-r--r-- | tapsets.cxx | 200 | ||||
-rw-r--r-- | translate.cxx | 47 |
9 files changed, 193 insertions, 139 deletions
@@ -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; @@ -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\" "; |