Received: by 10.223.185.116 with SMTP id b49csp1595804wrg; Wed, 21 Feb 2018 23:10:33 -0800 (PST) X-Google-Smtp-Source: AH8x226QAGbIeidtbEvRha/NEFeGZjx9top39Z1j2qwQXpFCDe84Xu3dbKuQAjxW10qplDXim9Lo X-Received: by 2002:a17:902:a03:: with SMTP id 3-v6mr5655352plo.282.1519283433695; Wed, 21 Feb 2018 23:10:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519283433; cv=none; d=google.com; s=arc-20160816; b=dFEbgBbYOVZC/UGLDVUXR5d8/2ZdL2IivXa3h8dp5TP/vhhe7d0i7VUb4Hh1Y2jKwO FINCb7Msds6M8fGA8BvWkpcGiMOvQd9FF6Y2+NGQndFFjB9bwtw5d7j//6iREG6c1hLC QugRwAwDs66McJz0YFM6pJEcRye6GCmwnoSYKhCrrTzY60v7+tMSJOD959H+9pjZLZ/S y6FEuGf+Ar1oNHtBTs9i00l91ZxzdkxlUKn1w50snXSa8acjlytL3cb125/QP4/IzMMC K6wRHBAM2YlbWtEI/IbbCVarKWzppmeA8xWDfWlH+8xU8POxa+JAo6UhhA6J/yBGTsll H9tA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=0dF/FQ+sUdJ8UibxTlroJK7Tn1pEg6R2YGA9/pb6R5I=; b=0509FeiJaBo/mFpUiYEnHN+nTWJGEwI2Z0Jwsp67v+c7PFboh6TegaeN4AeZ/S0mMo ts6HpPRUgdkTSmNNEjUNfq9aVgJT9jzPHb6MTMCoJORtEGnAHSiAjVb0JB6Hre0Sat7M OQYUjyF5VJ2nNStIOyNrTqbUvMsE7bihTlKVwPl4FaJoAPQe5wfOleQMM+qzsSycVVkO H8iK8zopXm1bzQzDA8W5Lj0NylyM6IdcQbY+BOU8O6HSLD8IxcUW6naOXL0oqSBkOkjP SNlHhtUXC8ZSRCrUK6KRGRY3CqRtdNKX2Vblb3E1t6bE3ooBRSX7/h/cNC03qz52k8NA eYTg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=GlLopH+4; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f7si4299789pfj.360.2018.02.21.23.10.19; Wed, 21 Feb 2018 23:10:33 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=GlLopH+4; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752740AbeBVHGk (ORCPT + 99 others); Thu, 22 Feb 2018 02:06:40 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:51323 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752728AbeBVHGg (ORCPT ); Thu, 22 Feb 2018 02:06:36 -0500 Received: by mail-wm0-f68.google.com with SMTP id h21so1820162wmd.1 for ; Wed, 21 Feb 2018 23:06:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=0dF/FQ+sUdJ8UibxTlroJK7Tn1pEg6R2YGA9/pb6R5I=; b=GlLopH+4T8PKIj5RilBd9Ibj+lvMjLNY64qHh5q3XgltTsC4JcyP2eZCoiWh2Useum vO7DzZ9iE5TiJOYtbtWKVBCcOlZaZbXJTMFwp+0bnEJf5AGgFIPDg0iw6z8Lr44+pD++ R28xOumw6r6slAySo7b9R1y78/CAQbqtQULadP5mas2Z243ISG0DeKwVOBZzEknvhxWW CryXtn+IynrdkV3W3dhwihoVleFnITjxgMigg6MaCg5Mi+Ys6cuBx6n4+1lCy3+t37zf XXwV5Ody+3CB1/kqwYGFhAan1Vc3GkUWgTNu243j/2YlHP2eJTN2IxvzfbruXbfC5m8j 9RdA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=0dF/FQ+sUdJ8UibxTlroJK7Tn1pEg6R2YGA9/pb6R5I=; b=NLeRkBSbYgSDZOkwYdkQ9IBIq8vJY50wiErUM/YMHMFhK3AQ5U1pSXHxkHlUD3sJ58 smUUNx+8/W4dDmQrizr+GSXHVr/jTS2An3lALtKF3yERlejJYDpihnzPlDll2wHt2DdC k0jSpCpRS4iF2grDXwuCDPIf5KxFewHbidn4xu20n4VQ2joyWJwpymBKQcySxFKzkq0M FWWHCUX12B+MIINBoijfzVWwP8XBsD2oLWnsONJYRM+moJvcOm4D2ayuQrFtj4A5SQju 1AW8Z6b0Pmv8+j5gsCewdOdbbeJNNHJBS+7w0W+TK+mEiBpu+gf84sp2F2DvtzQAp9qp V1qQ== X-Gm-Message-State: APf1xPBG3SyeKRM2YsyAdsoQsUoW5thRL2XLIFjmoCG4NGrD9tOgc4As 8xplq3BGiFRO0qzML9qKM/U= X-Received: by 10.80.137.187 with SMTP id g56mr7980724edg.225.1519283195234; Wed, 21 Feb 2018 23:06:35 -0800 (PST) Received: from auth1-smtp.messagingengine.com (auth1-smtp.messagingengine.com. [66.111.4.227]) by smtp.gmail.com with ESMTPSA id t23sm6185265edb.54.2018.02.21.23.06.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Feb 2018 23:06:34 -0800 (PST) Received: from compute7.internal (compute7.nyi.internal [10.202.2.47]) by mailauth.nyi.internal (Postfix) with ESMTP id DF85520C4A; Thu, 22 Feb 2018 02:06:32 -0500 (EST) Received: from frontend1 ([10.202.2.160]) by compute7.internal (MEProxy); Thu, 22 Feb 2018 02:06:32 -0500 X-ME-Sender: Received: from localhost (unknown [45.32.128.109]) by mail.messagingengine.com (Postfix) with ESMTPA id 1AF357E371; Thu, 22 Feb 2018 02:06:32 -0500 (EST) From: Boqun Feng To: linux-kernel@vger.kernel.org Cc: Peter Zijlstra , Ingo Molnar , Andrea Parri , Boqun Feng Subject: [RFC tip/locking/lockdep v5 11/17] lockdep: Take read/write status in consideration when generate chainkey Date: Thu, 22 Feb 2018 15:08:58 +0800 Message-Id: <20180222070904.548-12-boqun.feng@gmail.com> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180222070904.548-1-boqun.feng@gmail.com> References: <20180222070904.548-1-boqun.feng@gmail.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently, the chainkey of a lock chain is a hash sum of the class_idx of all the held locks, the read/write status are not taken in to consideration while generating the chainkey. This could result into a problem, if we have: P1() { read_lock(B); lock(A); } P2() { lock(A); read_lock(B); } P3() { lock(A); write_lock(B); } , and P1(), P2(), P3() run one by one. And when running P2(), lockdep detects such a lock chain A -> B is not a deadlock, then it's added in the chain cache, and then when running P3(), even if it's a deadlock, we could miss it because of the hit of chain cache. This could be confirmed by self testcase "chain cached mixed R-L/L-W ". To resolve this, we use concept"hlock_id" to generate the chainkey, the hlock_id is a tuple (hlock->class_idx, hlock->read), which fits in a u16 type. With this, the chainkeys are different is the lock sequences have the same locks but different read/write status. Besides, since we use "hlock_id" to generate chainkeys, the chain_hlocks array now store the "hlock_id"s rather than lock_class indexes. Signed-off-by: Boqun Feng --- kernel/locking/lockdep.c | 56 +++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 254f90bade54..1b981dc4c061 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -307,6 +307,21 @@ static struct hlist_head classhash_table[CLASSHASH_SIZE]; static struct hlist_head chainhash_table[CHAINHASH_SIZE]; +/* + * the id chain_hlocks + */ +static inline u16 hlock_id(struct held_lock *hlock) +{ + BUILD_BUG_ON(MAX_LOCKDEP_KEYS_BITS + 2 > 16); + + return (hlock->class_idx | (hlock->read << MAX_LOCKDEP_KEYS_BITS)); +} + +static inline unsigned int chain_hlock_class_idx(u16 hlock_id) +{ + return hlock_id & MAX_LOCKDEP_KEYS; +} + /* * The hash key of the lock dependency chains is a hash itself too: * it's a hash of all locks taken up to that lock, including that lock. @@ -2191,7 +2206,10 @@ static u16 chain_hlocks[MAX_LOCKDEP_CHAIN_HLOCKS]; struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i) { - return lock_classes + chain_hlocks[chain->base + i]; + u16 chain_hlock = chain_hlocks[chain->base + i]; + unsigned int class_idx = chain_hlock_class_idx(chain_hlock); + + return lock_classes + class_idx - 1; } /* @@ -2217,12 +2235,12 @@ static inline int get_first_held_lock(struct task_struct *curr, /* * Returns the next chain_key iteration */ -static u64 print_chain_key_iteration(int class_idx, u64 chain_key) +static u64 print_chain_key_iteration(u16 hlock_id, u64 chain_key) { - u64 new_chain_key = iterate_chain_key(chain_key, class_idx); + u64 new_chain_key = iterate_chain_key(chain_key, hlock_id); - printk(" class_idx:%d -> chain_key:%016Lx", - class_idx, + printk(" hlock_id:%d -> chain_key:%016Lx", + (unsigned int)hlock_id, (unsigned long long)new_chain_key); return new_chain_key; } @@ -2238,12 +2256,12 @@ print_chain_keys_held_locks(struct task_struct *curr, struct held_lock *hlock_ne printk("depth: %u\n", depth + 1); for (i = get_first_held_lock(curr, hlock_next); i < depth; i++) { hlock = curr->held_locks + i; - chain_key = print_chain_key_iteration(hlock->class_idx, chain_key); + chain_key = print_chain_key_iteration(hlock_id(hlock), chain_key); print_lock(hlock); } - print_chain_key_iteration(hlock_next->class_idx, chain_key); + print_chain_key_iteration(hlock_id(hlock_next), chain_key); print_lock(hlock_next); } @@ -2251,14 +2269,14 @@ static void print_chain_keys_chain(struct lock_chain *chain) { int i; u64 chain_key = 0; - int class_id; + u16 hlock_id; printk("depth: %u\n", chain->depth); for (i = 0; i < chain->depth; i++) { - class_id = chain_hlocks[chain->base + i]; - chain_key = print_chain_key_iteration(class_id + 1, chain_key); + hlock_id = chain_hlocks[chain->base + i]; + chain_key = print_chain_key_iteration(hlock_id, chain_key); - print_lock_name(lock_classes + class_id); + print_lock_name(lock_classes + chain_hlock_class_idx(hlock_id) - 1); printk("\n"); } } @@ -2307,7 +2325,7 @@ static int check_no_collision(struct task_struct *curr, } for (j = 0; j < chain->depth - 1; j++, i++) { - id = curr->held_locks[i].class_idx - 1; + id = hlock_id(&curr->held_locks[i]); if (DEBUG_LOCKS_WARN_ON(chain_hlocks[chain->base + j] != id)) { print_collision(curr, hlock, chain); @@ -2364,8 +2382,8 @@ static inline int add_chain_cache_classes(unsigned int prev, if (likely(nr_chain_hlocks + chain->depth <= MAX_LOCKDEP_CHAIN_HLOCKS)) { chain->base = nr_chain_hlocks; nr_chain_hlocks += chain->depth; - chain_hlocks[chain->base] = prev - 1; - chain_hlocks[chain->base + 1] = next -1; + chain_hlocks[chain->base] = prev; + chain_hlocks[chain->base + 1] = next; } #ifdef CONFIG_DEBUG_LOCKDEP /* @@ -2399,7 +2417,6 @@ static inline int add_chain_cache(struct task_struct *curr, struct held_lock *hlock, u64 chain_key) { - struct lock_class *class = hlock_class(hlock); struct hlist_head *hash_head = chainhashentry(chain_key); struct lock_chain *chain; int i, j; @@ -2438,10 +2455,9 @@ static inline int add_chain_cache(struct task_struct *curr, if (likely(nr_chain_hlocks + chain->depth <= MAX_LOCKDEP_CHAIN_HLOCKS)) { chain->base = nr_chain_hlocks; for (j = 0; j < chain->depth - 1; j++, i++) { - int lock_id = curr->held_locks[i].class_idx - 1; - chain_hlocks[chain->base + j] = lock_id; + chain_hlocks[chain->base + j] = hlock_id(&curr->held_locks[i]); } - chain_hlocks[chain->base + j] = class - lock_classes; + chain_hlocks[chain->base + j] = hlock_id(hlock); } if (nr_chain_hlocks < MAX_LOCKDEP_CHAIN_HLOCKS) @@ -2639,7 +2655,7 @@ static void check_chain_key(struct task_struct *curr) if (prev_hlock && (prev_hlock->irq_context != hlock->irq_context)) chain_key = 0; - chain_key = iterate_chain_key(chain_key, hlock->class_idx); + chain_key = iterate_chain_key(chain_key, hlock_id(hlock)); prev_hlock = hlock; } if (chain_key != curr->curr_chain_key) { @@ -3590,7 +3606,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, chain_key = 0; chain_head = 1; } - chain_key = iterate_chain_key(chain_key, class_idx); + chain_key = iterate_chain_key(chain_key, hlock_id(hlock)); if (nest_lock && !__lock_is_held(nest_lock, -1)) return print_lock_nested_lock_not_held(curr, hlock, ip); -- 2.16.1