Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1739297
| Path | csiph.com!fu-berlin.de!bofh.it!news.nic.it!robomod |
|---|---|
| From | Boqun Feng <boqun.feng@gmail.com> |
| Newsgroups | linux.kernel |
| Subject | [RFC tip/locking/lockdep v3 11/14] lockdep: Take read/write status in consideration when generate chainkey |
| Date | Tue, 26 Sep 2017 00:20:01 +0200 |
| Message-ID | <utJTj-47L-1@gated-at.bofh.it> (permalink) |
| References | <utJTj-47L-3@gated-at.bofh.it> |
| X-Original-To | linux-kernel@vger.kernel.org |
| 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=KOB2oLjJ0ir30kVRu5qDBqn7eJm+81FwYTXUQH97XDw=; b=uwAXWE5mk+YLc1SlooZVoVcH+wO7VMDHA6o2Ih+UNXGH7ZzVxAgjXaManxHFDqgrDj ya12WxWBW3vgH7zyBig2Skr9DNIvBSIzfv3KAPqq9bkBd9Ub0xyRxAhB+BOP4E+OlRpy 3fdRLdAggETqXRiyxNzWVfI3ZJtsJPhmYkH61AtGv/eJveCSOmgnN4KMDjrG2Gbmn7Sx jq9olyGjgKmheJmCRSygewbEIdzvUk1pdWpaoT8lwt/GMyY5c918cYWKYWsBMqIguxB3 Nb0O1hd/b+2VSQlPAqB/KV24uDdjtmtm8B/DoO/iMUMjQ8nj72N1ypWq/5fXSyBstFlM CDxg== |
| 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=KOB2oLjJ0ir30kVRu5qDBqn7eJm+81FwYTXUQH97XDw=; b=c4kD6dCeyCnHpY/KWIkta3Ha61jMMBP6JJhQ/7L0D3GLXRzg5s06KImw+WT/fvw4uC dRYCf5FlAn2Z5T/3QzjurmRakI04P3D+mdFTvzUAzETc+bkHIb8bpLSLit1OYngkXTnN enz1sAl2my0zGLFosjEJ4E+lvmhKqVbzpuLpPnHRGew9zj/rjTboR5p61yOrbr4GAm6u 7Aapsz92fkOlc3hhJkDllL7aJ2cU4RMNGb/V00Xi5pK4LVuJhhYCGlm4VowR9+MRTnMq fie4JoJFqCS7lCQNXqidz48TPkNoIDiJhsvG3kUtOQllsZh8OMAeL382ulyOad0HyVJT UtaA== |
| X-Gm-Message-State | AHPjjUgylCdW4W373nyPvTjK4SKiBhOi85yPsD8cIniXvbXBAeo7ZGtT 3gFBDPXH2cKrDpbySNrvXDfZjc/B |
| X-Google-SMTP-Source | AOwi7QA1OZ19CPitGz60c8OQ7BwkEvJROk3fvLIa9sSRkj6E4CugqZ+gjI4M9BQNacVUOA6aTCqZoQ== |
| X-Received | by 10.98.149.68 with SMTP id p65mr8707836pfd.301.1506377968507; Mon, 25 Sep 2017 15:19:28 -0700 (PDT) |
| X-Mailer | git-send-email 2.14.1 |
| Sender | robomod@news.nic.it |
| List-ID | <linux-kernel.vger.kernel.org> |
| X-Mailing-List | linux-kernel@vger.kernel.org |
| Approved | robomod@news.nic.it |
| Lines | 204 |
| Organization | linux.* mail to news gateway |
| X-Original-Cc | Ingo Molnar <mingo@kernel.org>, Peter Zijlstra <peterz@infradead.org>, Gautham R Shenoy <ego@linux.vnet.ibm.com>, Byungchul Park <byungchul.park@lge.com>, Boqun Feng <boqun.feng@gmail.com> |
| X-Original-Date | Tue, 26 Sep 2017 06:18:45 +0800 |
| X-Original-Message-ID | <20170925221848.6646-12-boqun.feng@gmail.com> |
| X-Original-References | <20170925221848.6646-1-boqun.feng@gmail.com> |
| X-Original-Sender | linux-kernel-owner@vger.kernel.org |
| Xref | csiph.com linux.kernel:1739297 |
Show key headers only | View raw
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 <boqun.feng@gmail.com>
---
kernel/locking/lockdep.c | 60 ++++++++++++++++++++++++++++++------------------
1 file changed, 38 insertions(+), 22 deletions(-)
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index cae595168970..33a7ff4ab60d 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -311,6 +311,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.
@@ -2212,7 +2227,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;
}
/*
@@ -2238,12 +2256,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;
}
@@ -2259,12 +2277,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);
}
@@ -2272,14 +2290,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");
}
}
@@ -2328,7 +2346,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);
@@ -2385,8 +2403,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
/*
@@ -2420,7 +2438,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;
@@ -2459,10 +2476,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)
@@ -2660,7 +2676,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) {
@@ -3626,7 +3642,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);
@@ -5136,9 +5152,9 @@ static int commit_xhlock(struct cross_lock *xlock, struct hist_lock *xhlock)
unsigned int xid, pid;
u64 chain_key;
- xid = xlock_class(xlock) - lock_classes;
+ xid = xlock_class(xlock) - lock_classes + 1;
chain_key = iterate_chain_key((u64)0, xid);
- pid = xhlock_class(xhlock) - lock_classes;
+ pid = xhlock_class(xhlock) - lock_classes + 1;
chain_key = iterate_chain_key(chain_key, pid);
if (lookup_chain_cache(chain_key))
--
2.14.1
Back to linux.kernel | Previous | Next | Find similar | Unroll thread
[RFC tip/locking/lockdep v3 11/14] lockdep: Take read/write status in consideration when generate chainkey Boqun Feng <boqun.feng@gmail.com> - 2017-09-26 00:20 +0200
csiph-web