[v2,4/4] locktorture: With nested locks, occasionally skip main lock
Commit Message
If we're using nested locking to stress things, occasionally
skip taking the main lock, so that we can get some different
contention patterns between the writers (to hopefully get two
disjoint blocked trees)
This patch was inspired by earlier work by Connor O'Brien.
Comments or feedback would be greatly appreciated!
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: "Paul E. McKenney" <paulmck@kernel.org>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Joel Fernandes <joel@joelfernandes.org>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Valentin Schneider <vschneid@redhat.com>
Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: John Stultz <jstultz@google.com>
---
kernel/locking/locktorture.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
Comments
On Fri, 03 Feb 2023, John Stultz wrote:
>@@ -754,21 +755,28 @@ static int lock_torture_writer(void *arg)
> schedule_timeout_uninterruptible(1);
>
> lockset_mask = torture_random(&rand);
>+ skip_main_lock = nlocks && !(torture_random(&rand) % 100);
For the sake of future readers of locktorture.c, this deserves a comment
as to why we wanna skip the main lock (copy/paste from the changelog).
Thanks,
Davidlohr
On Sun, Feb 5, 2023 at 11:33 AM Davidlohr Bueso <dave@stgolabs.net> wrote:
> On Fri, 03 Feb 2023, John Stultz wrote:
>
> >@@ -754,21 +755,28 @@ static int lock_torture_writer(void *arg)
> > schedule_timeout_uninterruptible(1);
> >
> > lockset_mask = torture_random(&rand);
> >+ skip_main_lock = nlocks && !(torture_random(&rand) % 100);
>
> For the sake of future readers of locktorture.c, this deserves a comment
> as to why we wanna skip the main lock (copy/paste from the changelog).
Good point! I'll send this update out soon.
Thanks again for the review and feedback!
-john
@@ -745,6 +745,7 @@ static int lock_torture_writer(void *arg)
int tid = lwsp - cxt.lwsa;
DEFINE_TORTURE_RANDOM(rand);
u32 lockset_mask;
+ bool skip_main_lock;
VERBOSE_TOROUT_STRING("lock_torture_writer task started");
set_user_nice(current, MAX_NICE);
@@ -754,21 +755,28 @@ static int lock_torture_writer(void *arg)
schedule_timeout_uninterruptible(1);
lockset_mask = torture_random(&rand);
+ skip_main_lock = nlocks && !(torture_random(&rand) % 100);
+
cxt.cur_ops->task_boost(&rand);
if (cxt.cur_ops->nested_lock)
cxt.cur_ops->nested_lock(tid, lockset_mask);
- cxt.cur_ops->writelock(tid);
- if (WARN_ON_ONCE(lock_is_write_held))
- lwsp->n_lock_fail++;
- lock_is_write_held = true;
- if (WARN_ON_ONCE(atomic_read(&lock_is_read_held)))
- lwsp->n_lock_fail++; /* rare, but... */
- lwsp->n_lock_acquired++;
+ if (!skip_main_lock) {
+ cxt.cur_ops->writelock(tid);
+ if (WARN_ON_ONCE(lock_is_write_held))
+ lwsp->n_lock_fail++;
+ lock_is_write_held = true;
+ if (WARN_ON_ONCE(atomic_read(&lock_is_read_held)))
+ lwsp->n_lock_fail++; /* rare, but... */
+
+ lwsp->n_lock_acquired++;
+ }
cxt.cur_ops->write_delay(&rand);
- lock_is_write_held = false;
- WRITE_ONCE(last_lock_release, jiffies);
- cxt.cur_ops->writeunlock(tid);
+ if (!skip_main_lock) {
+ lock_is_write_held = false;
+ WRITE_ONCE(last_lock_release, jiffies);
+ cxt.cur_ops->writeunlock(tid);
+ }
if (cxt.cur_ops->nested_unlock)
cxt.cur_ops->nested_unlock(tid, lockset_mask);