| @@ -370,6 +370,28 @@ static struct lock_torture_ops rw_lock_irq_ops = { · 369 unmodified lines |
| 370 | 370 | }; |
| 371 | 371 | |
| 372 | 372 | static DEFINE_MUTEX(torture_mutex); |
| 373 | +static struct mutex torture_nested_mutexes[MAX_NESTED_LOCKS]; |
| 374 | +static struct lock_class_key nested_mutex_keys[MAX_NESTED_LOCKS]; |
| 375 | + |
| 376 | +static void torture_mutex_init(void) |
| 377 | +{ |
| 378 | + int i; |
| 379 | + |
| 380 | + for (i = 0; i < MAX_NESTED_LOCKS; i++) |
| 381 | + __mutex_init(&torture_nested_mutexes[i], __func__, |
| 382 | + &nested_mutex_keys[i]); |
| 383 | +} |
| 384 | + |
| 385 | +static int torture_mutex_nested_lock(int tid __maybe_unused, |
| 386 | + u32 lockset) |
| 387 | +{ |
| 388 | + int i; |
| 389 | + |
| 390 | + for (i = 0; i < nested_locks; i++) |
| 391 | + if (lockset & (1 << i)) |
| 392 | + mutex_lock(&torture_nested_mutexes[i]); |
| 393 | + return 0; |
| 394 | +} |
| 373 | 395 | |
| 374 | 396 | static int torture_mutex_lock(int tid __maybe_unused) |
| 375 | 397 | __acquires(torture_mutex) |
| @@ -398,11 +420,24 @@ __releases(torture_mutex) · 22 unmodified lines |
| 398 | 420 | mutex_unlock(&torture_mutex); |
| 399 | 421 | } |
| 400 | 422 | |
| 423 | +static void torture_mutex_nested_unlock(int tid __maybe_unused, |
| 424 | + u32 lockset) |
| 425 | +{ |
| 426 | + int i; |
| 427 | + |
| 428 | + for (i = nested_locks - 1; i >= 0; i--) |
| 429 | + if (lockset & (1 << i)) |
| 430 | + mutex_unlock(&torture_nested_mutexes[i]); |
| 431 | +} |
| 432 | + |
| 401 | 433 | static struct lock_torture_ops mutex_lock_ops = { |
| 434 | + .init = torture_mutex_init, |
| 435 | + .nested_lock = torture_mutex_nested_lock, |
| 402 | 436 | .writelock = torture_mutex_lock, |
| 403 | 437 | .write_delay = torture_mutex_delay, |
| 404 | 438 | .task_boost = torture_rt_boost, |
| 405 | 439 | .writeunlock = torture_mutex_unlock, |
| 440 | + .nested_unlock = torture_mutex_nested_unlock, |
| 406 | 441 | .readlock = NULL, |
| 407 | 442 | .read_delay = NULL, |
| 408 | 443 | .readunlock = NULL, |