Skip to content

Commit 12235da

Browse files
mlankhorstPeter Zijlstra
authored andcommitted
kernel/locking: Add context to ww_mutex_trylock()
i915 will soon gain an eviction path that trylock a whole lot of locks for eviction, getting dmesg failures like below: BUG: MAX_LOCK_DEPTH too low! turning off the locking correctness validator. depth: 48 max: 48! 48 locks held by i915_selftest/5776: #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160 #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915] #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915] #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915] #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915] #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915] ... #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915] #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915] INFO: lockdep is turned off. Fixing eviction to nest into ww_class_acquire is a high priority, but it requires a rework of the entire driver, which can only be done one step at a time. As an intermediate solution, add an acquire context to ww_mutex_trylock, which allows us to do proper nesting annotations on the trylocks, making the above lockdep splat disappear. This is also useful in regulator_lock_nested, which may avoid dropping regulator_nesting_mutex in the uncontended path, so use it there. TTM may be another user for this, where we could lock a buffer in a fastpath with list locks held, without dropping all locks we hold. [peterz: rework actual ww_mutex_trylock() implementations] Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r/YUBGPdDDjKlxAuXJ@hirez.programming.kicks-ass.net
1 parent 6880fa6 commit 12235da

File tree

8 files changed

+137
-38
lines changed

8 files changed

+137
-38
lines changed

drivers/gpu/drm/drm_modeset_lock.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
248248
if (ctx->trylock_only) {
249249
lockdep_assert_held(&ctx->ww_ctx);
250250

251-
if (!ww_mutex_trylock(&lock->mutex))
251+
if (!ww_mutex_trylock(&lock->mutex, NULL))
252252
return -EBUSY;
253253
else
254254
return 0;

drivers/regulator/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ static inline int regulator_lock_nested(struct regulator_dev *rdev,
145145

146146
mutex_lock(&regulator_nesting_mutex);
147147

148-
if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
148+
if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
149149
if (rdev->mutex_owner == current)
150150
rdev->ref_cnt++;
151151
else

include/linux/dma-resv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ static inline int dma_resv_lock_slow_interruptible(struct dma_resv *obj,
173173
*/
174174
static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
175175
{
176-
return ww_mutex_trylock(&obj->lock);
176+
return ww_mutex_trylock(&obj->lock, NULL);
177177
}
178178

179179
/**

include/linux/ww_mutex.h

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,10 @@
2828
#ifndef CONFIG_PREEMPT_RT
2929
#define WW_MUTEX_BASE mutex
3030
#define ww_mutex_base_init(l,n,k) __mutex_init(l,n,k)
31-
#define ww_mutex_base_trylock(l) mutex_trylock(l)
3231
#define ww_mutex_base_is_locked(b) mutex_is_locked((b))
3332
#else
3433
#define WW_MUTEX_BASE rt_mutex
3534
#define ww_mutex_base_init(l,n,k) __rt_mutex_init(l,n,k)
36-
#define ww_mutex_base_trylock(l) rt_mutex_trylock(l)
3735
#define ww_mutex_base_is_locked(b) rt_mutex_base_is_locked(&(b)->rtmutex)
3836
#endif
3937

@@ -339,17 +337,8 @@ ww_mutex_lock_slow_interruptible(struct ww_mutex *lock,
339337

340338
extern void ww_mutex_unlock(struct ww_mutex *lock);
341339

342-
/**
343-
* ww_mutex_trylock - tries to acquire the w/w mutex without acquire context
344-
* @lock: mutex to lock
345-
*
346-
* Trylocks a mutex without acquire context, so no deadlock detection is
347-
* possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
348-
*/
349-
static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock)
350-
{
351-
return ww_mutex_base_trylock(&lock->base);
352-
}
340+
extern int __must_check ww_mutex_trylock(struct ww_mutex *lock,
341+
struct ww_acquire_ctx *ctx);
353342

354343
/***
355344
* ww_mutex_destroy - mark a w/w mutex unusable

kernel/locking/mutex.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ static inline unsigned long __owner_flags(unsigned long owner)
9494
return owner & MUTEX_FLAGS;
9595
}
9696

97+
/*
98+
* Returns: __mutex_owner(lock) on failure or NULL on success.
99+
*/
97100
static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
98101
{
99102
unsigned long owner, curr = (unsigned long)current;
@@ -736,6 +739,44 @@ __ww_mutex_lock(struct mutex *lock, unsigned int state, unsigned int subclass,
736739
return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
737740
}
738741

742+
/**
743+
* ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
744+
* @ww: mutex to lock
745+
* @ww_ctx: optional w/w acquire context
746+
*
747+
* Trylocks a mutex with the optional acquire context; no deadlock detection is
748+
* possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
749+
*
750+
* Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
751+
* specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
752+
*
753+
* A mutex acquired with this function must be released with ww_mutex_unlock.
754+
*/
755+
int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
756+
{
757+
if (!ww_ctx)
758+
return mutex_trylock(&ww->base);
759+
760+
MUTEX_WARN_ON(ww->base.magic != &ww->base);
761+
762+
/*
763+
* Reset the wounded flag after a kill. No other process can
764+
* race and wound us here, since they can't have a valid owner
765+
* pointer if we don't have any locks held.
766+
*/
767+
if (ww_ctx->acquired == 0)
768+
ww_ctx->wounded = 0;
769+
770+
if (__mutex_trylock(&ww->base)) {
771+
ww_mutex_set_context_fastpath(ww, ww_ctx);
772+
mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
773+
return 1;
774+
}
775+
776+
return 0;
777+
}
778+
EXPORT_SYMBOL(ww_mutex_trylock);
779+
739780
#ifdef CONFIG_DEBUG_LOCK_ALLOC
740781
void __sched
741782
mutex_lock_nested(struct mutex *lock, unsigned int subclass)

kernel/locking/test-ww_mutex.c

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@
1616
static DEFINE_WD_CLASS(ww_class);
1717
struct workqueue_struct *wq;
1818

19+
#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
20+
#define ww_acquire_init_noinject(a, b) do { \
21+
ww_acquire_init((a), (b)); \
22+
(a)->deadlock_inject_countdown = ~0U; \
23+
} while (0)
24+
#else
25+
#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
26+
#endif
27+
1928
struct test_mutex {
2029
struct work_struct work;
2130
struct ww_mutex mutex;
@@ -36,7 +45,7 @@ static void test_mutex_work(struct work_struct *work)
3645
wait_for_completion(&mtx->go);
3746

3847
if (mtx->flags & TEST_MTX_TRY) {
39-
while (!ww_mutex_trylock(&mtx->mutex))
48+
while (!ww_mutex_trylock(&mtx->mutex, NULL))
4049
cond_resched();
4150
} else {
4251
ww_mutex_lock(&mtx->mutex, NULL);
@@ -109,37 +118,56 @@ static int test_mutex(void)
109118
return 0;
110119
}
111120

112-
static int test_aa(void)
121+
static int test_aa(bool trylock)
113122
{
114123
struct ww_mutex mutex;
115124
struct ww_acquire_ctx ctx;
116125
int ret;
126+
const char *from = trylock ? "trylock" : "lock";
117127

118128
ww_mutex_init(&mutex, &ww_class);
119129
ww_acquire_init(&ctx, &ww_class);
120130

121-
ww_mutex_lock(&mutex, &ctx);
131+
if (!trylock) {
132+
ret = ww_mutex_lock(&mutex, &ctx);
133+
if (ret) {
134+
pr_err("%s: initial lock failed!\n", __func__);
135+
goto out;
136+
}
137+
} else {
138+
if (!ww_mutex_trylock(&mutex, &ctx)) {
139+
pr_err("%s: initial trylock failed!\n", __func__);
140+
goto out;
141+
}
142+
}
122143

123-
if (ww_mutex_trylock(&mutex)) {
124-
pr_err("%s: trylocked itself!\n", __func__);
144+
if (ww_mutex_trylock(&mutex, NULL)) {
145+
pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
146+
ww_mutex_unlock(&mutex);
147+
ret = -EINVAL;
148+
goto out;
149+
}
150+
151+
if (ww_mutex_trylock(&mutex, &ctx)) {
152+
pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
125153
ww_mutex_unlock(&mutex);
126154
ret = -EINVAL;
127155
goto out;
128156
}
129157

130158
ret = ww_mutex_lock(&mutex, &ctx);
131159
if (ret != -EALREADY) {
132-
pr_err("%s: missed deadlock for recursing, ret=%d\n",
133-
__func__, ret);
160+
pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
161+
__func__, ret, from);
134162
if (!ret)
135163
ww_mutex_unlock(&mutex);
136164
ret = -EINVAL;
137165
goto out;
138166
}
139167

168+
ww_mutex_unlock(&mutex);
140169
ret = 0;
141170
out:
142-
ww_mutex_unlock(&mutex);
143171
ww_acquire_fini(&ctx);
144172
return ret;
145173
}
@@ -150,7 +178,7 @@ struct test_abba {
150178
struct ww_mutex b_mutex;
151179
struct completion a_ready;
152180
struct completion b_ready;
153-
bool resolve;
181+
bool resolve, trylock;
154182
int result;
155183
};
156184

@@ -160,8 +188,13 @@ static void test_abba_work(struct work_struct *work)
160188
struct ww_acquire_ctx ctx;
161189
int err;
162190

163-
ww_acquire_init(&ctx, &ww_class);
164-
ww_mutex_lock(&abba->b_mutex, &ctx);
191+
ww_acquire_init_noinject(&ctx, &ww_class);
192+
if (!abba->trylock)
193+
ww_mutex_lock(&abba->b_mutex, &ctx);
194+
else
195+
WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
196+
197+
WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
165198

166199
complete(&abba->b_ready);
167200
wait_for_completion(&abba->a_ready);
@@ -181,7 +214,7 @@ static void test_abba_work(struct work_struct *work)
181214
abba->result = err;
182215
}
183216

184-
static int test_abba(bool resolve)
217+
static int test_abba(bool trylock, bool resolve)
185218
{
186219
struct test_abba abba;
187220
struct ww_acquire_ctx ctx;
@@ -192,12 +225,18 @@ static int test_abba(bool resolve)
192225
INIT_WORK_ONSTACK(&abba.work, test_abba_work);
193226
init_completion(&abba.a_ready);
194227
init_completion(&abba.b_ready);
228+
abba.trylock = trylock;
195229
abba.resolve = resolve;
196230

197231
schedule_work(&abba.work);
198232

199-
ww_acquire_init(&ctx, &ww_class);
200-
ww_mutex_lock(&abba.a_mutex, &ctx);
233+
ww_acquire_init_noinject(&ctx, &ww_class);
234+
if (!trylock)
235+
ww_mutex_lock(&abba.a_mutex, &ctx);
236+
else
237+
WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
238+
239+
WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
201240

202241
complete(&abba.a_ready);
203242
wait_for_completion(&abba.b_ready);
@@ -249,7 +288,7 @@ static void test_cycle_work(struct work_struct *work)
249288
struct ww_acquire_ctx ctx;
250289
int err, erra = 0;
251290

252-
ww_acquire_init(&ctx, &ww_class);
291+
ww_acquire_init_noinject(&ctx, &ww_class);
253292
ww_mutex_lock(&cycle->a_mutex, &ctx);
254293

255294
complete(cycle->a_signal);
@@ -581,7 +620,9 @@ static int stress(int nlocks, int nthreads, unsigned int flags)
581620
static int __init test_ww_mutex_init(void)
582621
{
583622
int ncpus = num_online_cpus();
584-
int ret;
623+
int ret, i;
624+
625+
printk(KERN_INFO "Beginning ww mutex selftests\n");
585626

586627
wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
587628
if (!wq)
@@ -591,17 +632,19 @@ static int __init test_ww_mutex_init(void)
591632
if (ret)
592633
return ret;
593634

594-
ret = test_aa();
635+
ret = test_aa(false);
595636
if (ret)
596637
return ret;
597638

598-
ret = test_abba(false);
639+
ret = test_aa(true);
599640
if (ret)
600641
return ret;
601642

602-
ret = test_abba(true);
603-
if (ret)
604-
return ret;
643+
for (i = 0; i < 4; i++) {
644+
ret = test_abba(i & 1, i & 2);
645+
if (ret)
646+
return ret;
647+
}
605648

606649
ret = test_cycle(ncpus);
607650
if (ret)
@@ -619,6 +662,7 @@ static int __init test_ww_mutex_init(void)
619662
if (ret)
620663
return ret;
621664

665+
printk(KERN_INFO "All ww mutex selftests passed\n");
622666
return 0;
623667
}
624668

kernel/locking/ww_rt_mutex.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,31 @@
99
#define WW_RT
1010
#include "rtmutex.c"
1111

12+
int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
13+
{
14+
struct rt_mutex *rtm = &lock->base;
15+
16+
if (!ww_ctx)
17+
return rt_mutex_trylock(rtm);
18+
19+
/*
20+
* Reset the wounded flag after a kill. No other process can
21+
* race and wound us here, since they can't have a valid owner
22+
* pointer if we don't have any locks held.
23+
*/
24+
if (ww_ctx->acquired == 0)
25+
ww_ctx->wounded = 0;
26+
27+
if (__rt_mutex_trylock(&rtm->rtmutex)) {
28+
ww_mutex_set_context_fastpath(lock, ww_ctx);
29+
mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
30+
return 1;
31+
}
32+
33+
return 0;
34+
}
35+
EXPORT_SYMBOL(ww_mutex_trylock);
36+
1237
static int __sched
1338
__ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
1439
unsigned int state, unsigned long ip)

lib/locking-selftest.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ static void init_shared_classes(void)
258258
#define WWAF(x) ww_acquire_fini(x)
259259

260260
#define WWL(x, c) ww_mutex_lock(x, c)
261-
#define WWT(x) ww_mutex_trylock(x)
261+
#define WWT(x) ww_mutex_trylock(x, NULL)
262262
#define WWL1(x) ww_mutex_lock(x, NULL)
263263
#define WWU(x) ww_mutex_unlock(x)
264264

0 commit comments

Comments
 (0)