Received: by 2002:a25:8b12:0:0:0:0:0 with SMTP id i18csp1976862ybl; Thu, 29 Aug 2019 01:36:05 -0700 (PDT) X-Google-Smtp-Source: APXvYqw0fdupiEIOCXFmjZ2jISi1lwNJTMpUM+ajOl4O2VV1JBqHDKoHgpV/Bd/7RP9oOSx595o9 X-Received: by 2002:a17:90a:da04:: with SMTP id e4mr2852411pjv.116.1567067765869; Thu, 29 Aug 2019 01:36:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1567067765; cv=none; d=google.com; s=arc-20160816; b=D7g/jf5r1NhZUd89DLz2iuc0WAX2HcwyTZsZMti73EZbfkUlBeDWNxnKQQO1xSbaM5 Nhz+/fObSHHDaIGu7jj481u1d6l/H4wej9WTL4UDmQRXTIeLFBDLeSBamzeJ9NppZVRZ VJ79aiqwhGRvozbg75+SOWQ1c9ugAx5gMUTDn6fqB2A0f0tGUMmpU7UJ4ZysZKW7jlBY GcGfaJTJp310i6hrqNjZwacCiZ/wGQr0gewGlWG28wn++2YjWSfPhaeqw8YBq8bbQj2x CYHgK4b+QsGuLDl70JNGPfJRVZ/o8+xT0l2E4hUl8PHDofgn6Idt9fNWIG8lyz2Gio2P 1vWw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=LkyFJrLqM/1skkJ2JlKIrqfmHWAJ7sxdhCa7MxHNzNk=; b=iJGAQqmqL7sAikgBeM3bZVku2gixBUoszwlJ6Cr+HGUJbw69YQDceG3AaT1l/yuawn 22kOsPjk0mLaDsLOi6sLNJJ8N0kotojUZi0DUEwpAxCXax8z5S1umZEbPSKAn75EsHOR IRPZD5irqj88VVPhNA0M5f3cxZypoNGmTfOG6s+gvgsX/pfR3z4Jq4CBy/1BotADENd4 JuezHCirYbP9xC/sZv37451z9iXZEIJ+RJlIkd3HDK3o6QhTltkB+nTHHD2VbFBglBE1 kgET/s1npbjWEcdRfbemg/r4ipsbYCyE3mWFTP2nDvif+Q0OL7+hkRfBqJ1OMaQu7ifK 4Xgw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=GI63RI2O; 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 p33si1470483pgb.0.2019.08.29.01.35.50; Thu, 29 Aug 2019 01:36:05 -0700 (PDT) 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=GI63RI2O; 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 S1727963AbfH2IdN (ORCPT + 99 others); Thu, 29 Aug 2019 04:33:13 -0400 Received: from mail-pf1-f195.google.com ([209.85.210.195]:34853 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726330AbfH2IdL (ORCPT ); Thu, 29 Aug 2019 04:33:11 -0400 Received: by mail-pf1-f195.google.com with SMTP id d85so1588008pfd.2 for ; Thu, 29 Aug 2019 01:33:11 -0700 (PDT) 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 :mime-version:content-transfer-encoding; bh=LkyFJrLqM/1skkJ2JlKIrqfmHWAJ7sxdhCa7MxHNzNk=; b=GI63RI2O2Agt0MZqP9S6OT3XQNshcxT8YKQsqJUFAcNIWwB2xCGVLxjAd3Lq3xroZj aIEGTUtowqk8TyP2HtO6IZhe+leyPuE7hIeFefJu+7BmLQVBO9ALwuy9ioRqzEWFICwL 1atPMXxvSMcgsHu25eHyUrI+QrTrWWBzjoNRg8WVAgd7QEw0DIqcs9Xzr67zYw6eAtWL FURAiaVgj1QRYwwcKuhC5lt7sE53zpKCkik02gaFLC66tWlMnLKSOl9KhFL6vIWT5BfC MEH13BoAknzN8taWWvmkQd530AxLTJacHDayluiYWPWNMe2hIMhBwIs3F7+w0gcZsE87 Fohg== 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:mime-version:content-transfer-encoding; bh=LkyFJrLqM/1skkJ2JlKIrqfmHWAJ7sxdhCa7MxHNzNk=; b=VFRoR0gPHTZ0IMvrqmyH3TOGszK+blyEBMK8g4oiAfHC9xsToflNgJjqfC+QCeEbxl gPyrG3onhEcYR9lUufMqmGovQyOzeOygczn4hPLAkjICJsJZ8AUCgPw8ddZo4uxIbZKt fO74ReLqaZ96nbvTxVryfc5rdG1y+iyO/409GoDWaNS3yr0rc0tnxQWwn9gcdwfPXXqO CfyGmA/chs4bmjrH+Pamm7NpYiDYY150a1pgkFD06EHrcbIwDr6Jr24gOrhBuY1LJbMM s3WbdVZWMzpF3JOH3ZY0U/A/7qQvDvvMzDRCWuL17mrlYWdSvM8Np3jGaPR2nz/mkz0I IKTQ== X-Gm-Message-State: APjAAAVUGGMPrijkFUVhBNp0fi5U98t+8+/i6qOltx/5HthZMrZMSY4Y ZIkCsq6hikIkLaNeEhVuN3o= X-Received: by 2002:a62:35c6:: with SMTP id c189mr9873050pfa.96.1567067590794; Thu, 29 Aug 2019 01:33:10 -0700 (PDT) Received: from localhost.localdomain ([203.100.54.194]) by smtp.gmail.com with ESMTPSA id v22sm1260155pgk.69.2019.08.29.01.33.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 29 Aug 2019 01:33:10 -0700 (PDT) From: Yuyang Du To: peterz@infradead.org, will.deacon@arm.com, mingo@kernel.org Cc: bvanassche@acm.org, ming.lei@redhat.com, frederic@kernel.org, tglx@linutronix.de, linux-kernel@vger.kernel.org, longman@redhat.com, paulmck@linux.vnet.ibm.com, boqun.feng@gmail.com, Yuyang Du Subject: [PATCH v4 22/30] locking/lockdep: Hash held lock's read-write type into chain key Date: Thu, 29 Aug 2019 16:31:24 +0800 Message-Id: <20190829083132.22394-23-duyuyang@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: <20190829083132.22394-1-duyuyang@gmail.com> References: <20190829083132.22394-1-duyuyang@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When computing a chain's hash key, we need to consider a held lock's read-write type. To do so, we hash the held lock's read-write type into the chain key. So the additional data to use Jenkins hash algorithm is a composite of the new held lock's lock class index (lower 16 bits) and its read-write type (higher 16 bits) as opposed to just class index before: held lock type (16 bits) : lock class index (16 bits) Signed-off-by: Yuyang Du --- include/linux/lockdep.h | 1 + kernel/locking/lockdep.c | 55 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index eab8a90..3de4b37 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -183,6 +183,7 @@ static inline void lockdep_copy_map(struct lockdep_map *to, } #define LOCK_TYPE_BITS 2 +#define LOCK_TYPE_SHIFT 16 /* * Every lock has a list of other locks that were taken after or before diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 1166262..d13b6b7 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -370,11 +370,22 @@ struct pending_free { * it's a hash of all locks taken up to that lock, including that lock. * It's a 64-bit hash, because it's important for the keys to be * unique. + * + * The additional u32 data to hash is a composite of the new held lock's + * lock class index (lower 16 bits) and its read-write type (higher 16 + * bits): + * + * hlock type (16 bits) : lock class index (16 bits) + * + * N.B. The bits taken for lock type and index are specified by + * LOCK_TYPE_SHIFT. */ -static inline u64 iterate_chain_key(u64 key, u32 idx) +static inline u64 iterate_chain_key(u64 key, u32 idx, int hlock_type) { u32 k0 = key, k1 = key >> 32; + idx += hlock_type << LOCK_TYPE_SHIFT; + __jhash_mix(idx, k0, k1); /* Macro that modifies arguments! */ return k0 | (u64)k1 << 32; @@ -960,7 +971,8 @@ static bool check_lock_chain_key(struct lock_chain *chain) int i; for (i = chain->base; i < chain->base + chain->depth; i++) - chain_key = iterate_chain_key(chain_key, chain_hlocks[i]); + chain_key = iterate_chain_key(chain_key, chain_hlocks[i], + chain_hlocks_type[i]); /* * The 'unsigned long long' casts avoid that a compiler warning * is reported when building tools/lib/lockdep. @@ -2700,12 +2712,13 @@ 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(int class_idx, u64 chain_key, int lock_type) { - u64 new_chain_key = iterate_chain_key(chain_key, class_idx); + u64 new_chain_key = iterate_chain_key(chain_key, class_idx, lock_type); - printk(" class_idx:%d -> chain_key:%016Lx", + printk(" class_idx:%d (lock_type %d) -> chain_key:%016Lx", class_idx, + lock_type, (unsigned long long)new_chain_key); return new_chain_key; } @@ -2722,12 +2735,15 @@ static u64 print_chain_key_iteration(int class_idx, u64 chain_key) hlock_next->irq_context); for (; 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->class_idx, + chain_key, + hlock->read); print_lock(hlock); } - print_chain_key_iteration(hlock_next->class_idx, chain_key); + print_chain_key_iteration(hlock_next->class_idx, chain_key, + hlock_next->read); print_lock(hlock_next); } @@ -2735,12 +2751,14 @@ static void print_chain_keys_chain(struct lock_chain *chain) { int i; u64 chain_key = INITIAL_CHAIN_KEY; - int class_id; + int class_id, lock_type; 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, chain_key); + lock_type = chain_hlocks_type[chain->base + i]; + chain_key = print_chain_key_iteration(class_id, chain_key, + lock_type); print_lock_name(lock_classes + class_id); printk("\n"); @@ -2780,7 +2798,7 @@ static int check_no_collision(struct task_struct *curr, struct held_lock *hlock, struct lock_chain *chain, int depth) { #ifdef CONFIG_DEBUG_LOCKDEP - int i, j, id; + int i, j, id, type; i = get_first_held_lock(curr, hlock, depth); @@ -2789,10 +2807,12 @@ static int check_no_collision(struct task_struct *curr, struct held_lock *hlock, return 0; } - for (j = 0; j < chain->depth - 1; j++, i++) { + for (j = chain->base; j < chain->base + chain->depth - 1; j++, i++) { id = curr->held_locks[i].class_idx; + type = curr->held_locks[i].read; - if (DEBUG_LOCKS_WARN_ON(chain_hlocks[chain->base + j] != id)) { + if (DEBUG_LOCKS_WARN_ON((chain_hlocks[j] != id) || + (chain_hlocks_type[j] != type))) { print_collision(curr, hlock, chain, depth); return 0; } @@ -3081,7 +3101,8 @@ static int validate_chain(struct task_struct *curr, struct held_lock *next, * lock_chains. If it exists the check is actually not needed. */ chain_key = iterate_chain_key(hlock->prev_chain_key, - hlock_class(next) - lock_classes); + hlock_class(next) - lock_classes, + next->read); goto chain_again; @@ -3139,7 +3160,8 @@ static void check_chain_key(struct task_struct *curr) if (prev_hlock && (prev_hlock->irq_context != hlock->irq_context)) chain_key = INITIAL_CHAIN_KEY; - chain_key = iterate_chain_key(chain_key, hlock->class_idx); + chain_key = iterate_chain_key(chain_key, hlock->class_idx, + hlock->read); prev_hlock = hlock; } if (chain_key != curr->curr_chain_key) { @@ -4048,7 +4070,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, if (separate_irq_context(curr, hlock)) chain_key = INITIAL_CHAIN_KEY; - chain_key = iterate_chain_key(chain_key, class_idx); + chain_key = iterate_chain_key(chain_key, class_idx, read); if (nest_lock && !__lock_is_held(nest_lock, -1)) { print_lock_nested_lock_not_held(curr, hlock, ip); @@ -4908,7 +4930,8 @@ static void remove_class_from_lock_chain(struct pending_free *pf, recalc: chain_key = INITIAL_CHAIN_KEY; for (i = chain->base; i < chain->base + chain->depth; i++) - chain_key = iterate_chain_key(chain_key, chain_hlocks[i]); + chain_key = iterate_chain_key(chain_key, chain_hlocks[i], + chain_hlocks_type[i]); if (chain->depth && chain->chain_key == chain_key) return; /* Overwrite the chain key for concurrent RCU readers. */ -- 1.8.3.1