From d7f37943633359c2e7e61ba8c84d15144aa3b87f Mon Sep 17 00:00:00 2001 From: fche Date: Tue, 30 Aug 2005 17:02:59 +0000 Subject: 2005-08-30 Frank Ch. Eigler PR systemtap/1268 * translator (varlock): Add deadlock detection code. (emit_common_header): Add a new MAXTRYLOCK configuration macro. --- ChangeLog | 6 ++++++ translate.cxx | 31 +++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 52d3a8fb..2a6a2b32 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-08-30 Frank Ch. Eigler + + PR systemtap/1268 + * translator (varlock): Add deadlock detection code. + (emit_common_header): Add a new MAXTRYLOCK configuration macro. + 2005-08-29 Graydon Hoare PR translator/1265 diff --git a/translate.cxx b/translate.cxx index a8d768ae..6e68e7e3 100644 --- a/translate.cxx +++ b/translate.cxx @@ -281,12 +281,36 @@ struct varlock c_unparser & c; var const & v; bool w; + string post_unlock_label; varlock(c_unparser & c, var const & v, bool w): c(c), v(v), w(w) { if (v.is_local()) return; - c.o->newline() << (w ? "write_lock" : "read_lock") - << " (& " << v << "_lock);"; + + // There may be a few opportunities for deadlock beyond bug #1268 + // (foreach). In general, we use a loop with FOO_trylock with a + // manual "timeout". If it takes too many iterations to acquire + // the lock, we signal a deadlock error in the context and jump + // over all the code, right past the corresponding unlock. + + static unsigned unlock_label_counter = 0; + post_unlock_label = string ("post_unlock_") + + stringify (unlock_label_counter ++); + + c.o->newline() << "{"; + c.o->newline(1) << "unsigned trylock_count = 0;"; + c.o->newline() << "while (" + << "!(" << (w ? "write_trylock" : "read_trylock") + << " (& " << v << "_lock))" + << " && " + << "(trylock_count++ < MAXTRYLOCK)" + << ") ; /* spin */"; + c.o->newline() << "if (unlikely (trylock_count >= MAXTRYLOCK)) {"; + c.o->newline(1) << "c->last_error = \"deadlock over variable " + << v << "\";"; + c.o->newline() << "goto " << post_unlock_label << ";"; + c.o->newline(-1) << "}"; + c.o->newline(-1) << "}"; } ~varlock() @@ -294,6 +318,8 @@ struct varlock if (v.is_local()) return; c.o->newline() << (w ? "write_unlock" : "read_unlock") << " (& " << v << "_lock);"; + c.o->newline(-1) << post_unlock_label << ": ;"; + c.o->indent(1); } }; @@ -527,6 +553,7 @@ c_unparser::emit_common_header () o->newline() << "#define MAXNESTING 30"; o->newline() << "#define MAXCONCURRENCY NR_CPUS"; o->newline() << "#define MAXSTRINGLEN 128"; + o->newline() << "#define MAXTRYLOCK 20"; o->newline() << "#define MAXACTION 1000"; o->newline() << "#define MAXMAPENTRIES 2048"; o->newline(); -- cgit