summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfche <fche>2005-08-30 17:02:59 +0000
committerfche <fche>2005-08-30 17:02:59 +0000
commitd7f37943633359c2e7e61ba8c84d15144aa3b87f (patch)
treeecce1c235cc563388042a3f12de138bb5b8b3c0d
parent4cd232e4b9d331288603843c8fc7bcbd76bedc21 (diff)
downloadsystemtap-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--ChangeLog6
-rw-r--r--translate.cxx31
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 <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();