Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756036AbcK3Agn (ORCPT ); Tue, 29 Nov 2016 19:36:43 -0500 Received: from mail-wj0-f196.google.com ([209.85.210.196]:35214 "EHLO mail-wj0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755302AbcK3AgE (ORCPT ); Tue, 29 Nov 2016 19:36:04 -0500 From: Chris Wilson To: linux-kernel@vger.kernel.org Cc: Chris Wilson , Peter Zijlstra , Maarten Lankhorst , =?UTF-8?q?Nicolai=20H=C3=A4hnle?= Subject: [PATCH 3/4] locking: Add kselftests for ww_mutex ABBA deadlock detection Date: Wed, 30 Nov 2016 00:35:47 +0000 Message-Id: <20161130003548.22266-3-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20161130003548.22266-1-chris@chris-wilson.co.uk> References: <1480335612-12069-1-git-send-email-nhaehnle@gmail.com> <20161130003548.22266-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2458 Lines: 103 Signed-off-by: Chris Wilson Cc: Peter Zijlstra Cc: Maarten Lankhorst Cc: Nicolai Hähnle --- kernel/locking/test-ww_mutex.c | 75 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/kernel/locking/test-ww_mutex.c b/kernel/locking/test-ww_mutex.c index 02a4bacf8aac..63a5031de138 100644 --- a/kernel/locking/test-ww_mutex.c +++ b/kernel/locking/test-ww_mutex.c @@ -153,6 +153,77 @@ static int test_aa(void) return ret; } +struct test_abba { + struct work_struct work; + struct ww_mutex a_mutex; + struct ww_mutex b_mutex; + struct completion a_ready; + struct completion b_ready; + struct completion done; + int ret; +}; + +static void test_abba_work(struct work_struct *work) +{ + struct test_abba *abba = container_of(work, typeof(*abba), work); + struct ww_acquire_ctx ctx; + + ww_acquire_init(&ctx, &ww_class); + ww_mutex_lock(&abba->b_mutex, &ctx); + + complete(&abba->b_ready); + wait_for_completion(&abba->a_ready); + abba->ret = ww_mutex_lock(&abba->a_mutex, &ctx); + if (!abba->ret) + ww_mutex_unlock(&abba->a_mutex); + + ww_mutex_unlock(&abba->b_mutex); + ww_acquire_fini(&ctx); + + complete(&abba->done); +} + +static int test_abba(void) +{ + struct test_abba abba; + struct ww_acquire_ctx ctx; + int ret; + + ww_mutex_init(&abba.a_mutex, &ww_class); + ww_mutex_init(&abba.b_mutex, &ww_class); + INIT_WORK_ONSTACK(&abba.work, test_abba_work); + init_completion(&abba.a_ready); + init_completion(&abba.b_ready); + init_completion(&abba.done); + + schedule_work(&abba.work); + + ww_acquire_init(&ctx, &ww_class); + ww_mutex_lock(&abba.a_mutex, &ctx); + complete(&abba.a_ready); + wait_for_completion(&abba.b_ready); + ret = ww_mutex_lock(&abba.b_mutex, &ctx); + if (!ret) + ww_mutex_unlock(&abba.b_mutex); + ww_mutex_unlock(&abba.a_mutex); + + wait_for_completion(&abba.done); + + if (ret != -EDEADLK && abba.ret != -EDEADLK) { + pr_err("%s: missed ABBA deadlock, A ret=%d, B ret=%d\n", + __func__, ret, abba.ret); + ret = -EINVAL; + goto out; + } + + ret = 0; +out: + ww_acquire_fini(&ctx); + flush_work(&abba.work); + destroy_work_on_stack(&abba.work); + return ret; +} + static int __init test_ww_mutex_init(void) { int ret; @@ -165,6 +236,10 @@ static int __init test_ww_mutex_init(void) if (ret) return ret; + ret = test_abba(); + if (ret) + return ret; + return 0; } -- 2.10.2