static int test_aa(void) { struct ww_mutex mutex; struct ww_acquire_ctx ctx; int ret; ww_mutex_init(&mutex, &ww_class); ww_acquire_init(&ctx, &ww_class); ww_mutex_lock(&mutex, &ctx); if (ww_mutex_trylock(&mutex)) { pr_err("%s: trylocked itself!\n", __func__); ww_mutex_unlock(&mutex); ret = -EINVAL; goto out; } ret = ww_mutex_lock(&mutex, &ctx); if (ret != -EALREADY) { pr_err("%s: missed deadlock for recursing, ret=%d\n", __func__, ret); if (!ret) ww_mutex_unlock(&mutex); ret = -EINVAL; goto out; } ret = 0; out: ww_mutex_unlock(&mutex); ww_acquire_fini(&ctx); return ret; }
static void test_mutex_work(struct work_struct *work) { struct test_mutex *mtx = container_of(work, typeof(*mtx), work); complete(&mtx->ready); wait_for_completion(&mtx->go); if (mtx->flags & TEST_MTX_TRY) { while (!ww_mutex_trylock(&mtx->mutex)) cond_resched(); } else { ww_mutex_lock(&mtx->mutex, NULL); } complete(&mtx->done); ww_mutex_unlock(&mtx->mutex); }
static inline int modeset_lock(struct drm_modeset_lock *lock, struct drm_modeset_acquire_ctx *ctx, bool interruptible, bool slow) { int ret; WARN_ON(ctx->contended); if (ctx->trylock_only) { lockdep_assert_held(&ctx->ww_ctx); if (!ww_mutex_trylock(&lock->mutex)) return -EBUSY; else return 0; } else if (interruptible && slow) { ret = ww_mutex_lock_slow_interruptible(&lock->mutex, &ctx->ww_ctx); } else if (interruptible) { ret = ww_mutex_lock_interruptible(&lock->mutex, &ctx->ww_ctx); } else if (slow) { ww_mutex_lock_slow(&lock->mutex, &ctx->ww_ctx); ret = 0; } else { ret = ww_mutex_lock(&lock->mutex, &ctx->ww_ctx); } if (!ret) { WARN_ON(!list_empty(&lock->head)); list_add(&lock->head, &ctx->locked); } else if (ret == -EALREADY) { /* we already hold the lock.. this is fine. For atomic * we will need to be able to drm_modeset_lock() things * without having to keep track of what is already locked * or not. */ ret = 0; } else if (ret == -EDEADLK) { ctx->contended = lock; } return ret; }