diff options
author | fche <fche> | 2005-08-30 17:02:59 +0000 |
---|---|---|
committer | fche <fche> | 2005-08-30 17:02:59 +0000 |
commit | d7f37943633359c2e7e61ba8c84d15144aa3b87f (patch) | |
tree | ecce1c235cc563388042a3f12de138bb5b8b3c0d | |
parent | 4cd232e4b9d331288603843c8fc7bcbd76bedc21 (diff) | |
download | systemtap-steved-d7f37943633359c2e7e61ba8c84d15144aa3b87f.tar.gz systemtap-steved-d7f37943633359c2e7e61ba8c84d15144aa3b87f.tar.xz systemtap-steved-d7f37943633359c2e7e61ba8c84d15144aa3b87f.zip |
2005-08-30 Frank Ch. Eigler <fche@elastic.org>
PR systemtap/1268
* translator (varlock): Add deadlock detection code.
(emit_common_header): Add a new MAXTRYLOCK configuration macro.
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | translate.cxx | 31 |
2 files changed, 35 insertions, 2 deletions
@@ -1,3 +1,9 @@ +2005-08-30 Frank Ch. Eigler <fche@elastic.org> + + PR systemtap/1268 + * translator (varlock): Add deadlock detection code. + (emit_common_header): Add a new MAXTRYLOCK configuration macro. + 2005-08-29 Graydon Hoare <graydon@redhat.com> 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(); |