From 0da46fcdec144f944838350f08f59a36b8709e90 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 11 Mar 2010 17:14:59 -0800 Subject: Fix the edge-case of MAXTRYLOCK=0 We didn't really have good semantics for what is meant by MAXTRYLOCK=0, so when skipped.exp tried it, we ended up locking the variable and then reporting a skip without ever unlocking it. This is now cleaning up the semantics such that MAXTRYLOCK defines how many times we should loop if the lock is busy. Thus MAXTRYLOCK=0 means we try only once and fail immediately. The testcase was accidentally creating contention due to the broken unlock behavior. We now have to try a bit harder to create real contention, so some lengthy delays are inserted to hoard the lock. * runtime/probe_lock.h (stp_probe_lock): Fix the skip behavior. * testsuite/systemtap.base/skipped.exp: Add a big udelay. --- runtime/probe_lock.h | 30 +++++++++++++++++------------- testsuite/systemtap.base/skipped.exp | 8 +++++++- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/runtime/probe_lock.h b/runtime/probe_lock.h index 1915d4ff..1077f4c6 100644 --- a/runtime/probe_lock.h +++ b/runtime/probe_lock.h @@ -42,26 +42,30 @@ stp_unlock_probe(const struct stp_probe_lock *locks, unsigned num_locks) static unsigned stp_lock_probe(const struct stp_probe_lock *locks, unsigned num_locks) { - unsigned i, numtrylock = 0; + unsigned i, retries = 0; for (i = 0; i < num_locks; ++i) { if (locks[i].write_p) - while (!write_trylock(locks[i].lock) && - (++numtrylock < MAXTRYLOCK)) + while (!write_trylock(locks[i].lock)) { + if (++retries > MAXTRYLOCK) + goto skip; ndelay (TRYLOCKDELAY); + } else - while (!read_trylock(locks[i].lock) && - (++numtrylock < MAXTRYLOCK)) + while (!read_trylock(locks[i].lock)) { + if (++retries > MAXTRYLOCK) + goto skip; ndelay (TRYLOCKDELAY); - if (unlikely(numtrylock >= MAXTRYLOCK)) { - atomic_inc(&skipped_count); - #ifdef STP_TIMING - atomic_inc(locks[i].skipped); - #endif - stp_unlock_probe(locks, i); - return 0; - } + } } return 1; + +skip: + atomic_inc(&skipped_count); +#ifdef STP_TIMING + atomic_inc(locks[i].skipped); +#endif + stp_unlock_probe(locks, i); + return 0; } diff --git a/testsuite/systemtap.base/skipped.exp b/testsuite/systemtap.base/skipped.exp index 8815c737..f12bc6f1 100644 --- a/testsuite/systemtap.base/skipped.exp +++ b/testsuite/systemtap.base/skipped.exp @@ -5,10 +5,16 @@ if {! [installtest_p]} { untested $test; return } set nr_cpus [exec sh -c "grep ^processor /proc/cpuinfo | wc -l"] if {$nr_cpus < 2} { unsupported $test; return } +set script { +global f +probe timer.profile { f++; snooze() } +function snooze() %{ udelay(10000); %} +} + set errs 0 set warns 0 set oks 0 -spawn stap -e "probe timer.s(5) {exit()} probe timer.profile,syscall.* {f++} global f" -DMAXTRYLOCK=0 -tu +spawn stap -e $script -DMAXTRYLOCK=0 -DSTP_NO_OVERLOAD -tug expect { -timeout 60 -re {^ERROR: Skipped too many probes, check MAXSKIPPED or try again with stap -t for more details.\r\n} { incr errs; exp_continue } -- cgit