Received: by 10.223.185.116 with SMTP id b49csp2244813wrg; Sat, 24 Feb 2018 14:54:25 -0800 (PST) X-Google-Smtp-Source: AH8x225o/l0vA1V+J6dSiip9pJnqfC2tWixftlZcaX4Ka9WlfG9Sab3bZK6D/04vmXRxZVBA2C1O X-Received: by 10.99.152.10 with SMTP id q10mr4960881pgd.212.1519512865784; Sat, 24 Feb 2018 14:54:25 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519512865; cv=none; d=google.com; s=arc-20160816; b=gnOql6BmXZim+i7ZtmkdyIdaR5n4VAjRD2lTmEvnBZD+HY0VGHrIyvWo5S5NUddRvI KyRCcMqUAuxRKDuNLUyHhte40k7GPMu74L2njxY7xygW5lBHjIMgHn/AvBNMCg0uJoyi LQAdtDaXnn/6roJ8Zxlcm6wIJIuZ+aRmPdBnQW2c/5DqyHgg703G1VNbrCC86V3JnXzJ PgsRZjbs7dgolR8znpwaYo4/lahPH0QfM9NNQHMNz5jdn4EwNJnI5sgjgpdZBfni56+K JgDI0XUPjH9jLGcdG6E6MVmuDLv2IBBd+LaBuTvwbSSzcwoq7zpJlDf7+kQvziUJsrlr WD5Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature:arc-authentication-results; bh=7Smx0iOCSSX9eHeK55h8g9w1ZJ7StZgbNaauQwbIgbw=; b=T4d5aMKVoOGSV4TihVOd+qMzRz3xQywa4wbwnGTToLjhmSrN4N7vKxjpmn1HJw9mXm RQJdRyhG7BKAGlFgsXoriQTbqSxJbvjcgJdHblDsdLNwzEMvgziJ5Wq5kvW3j7rXk+kH MwWsw6rLBDtCVIRRhLcaMt50Xku5t/obbeB36usEWLnLRuxDZz89Lf2417JPwudRQWKa CICvRZTPGfC7vJV0dF4TYjQcwezAvRpOcrfAGZomGMsyhjV/jD+UGL+1WBczp0s6wblE rxUi9tm/+yyT+0/TaBHH3sf5BrLvlAj4ojGm37Pbh417+/OcvPW+FrWcD+o84btYOL0D 8jmA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=VdRmZ1gm; 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 z100-v6si4206533plh.415.2018.02.24.14.54.10; Sat, 24 Feb 2018 14:54:25 -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=VdRmZ1gm; 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 S1751553AbeBXWxb (ORCPT + 99 others); Sat, 24 Feb 2018 17:53:31 -0500 Received: from mail-wr0-f179.google.com ([209.85.128.179]:43409 "EHLO mail-wr0-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751449AbeBXWx3 (ORCPT ); Sat, 24 Feb 2018 17:53:29 -0500 Received: by mail-wr0-f179.google.com with SMTP id u49so17513310wrc.10; Sat, 24 Feb 2018 14:53:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=7Smx0iOCSSX9eHeK55h8g9w1ZJ7StZgbNaauQwbIgbw=; b=VdRmZ1gm1ySoVxTpFISfdaZda0ZzTRDOTVnR/rGZItnJ+aMcgcpk0aO+Z6kYEyJf80 Vqqxtsjxh8V5btux3a7SHAIBixheNdnmBU3VNOAvlnQ7lA4V4Eu4t6pneypcgQev2U8C wJEpkgIVBOWyrnMu/aOPQLHIMYqOiDGUr1yZRfeMwmvlwPY3M8v03ftpJZ9yLu3cZM/G D9xYp1JQrEXvtv2vOmnKaiPlqeopgVILv0CbEw90Kh6xaNeHkRp2Mn48Vac5j/Tn8oHE 6DL7t4BmhXGtsU/m1MSN6MRtUy3aXIAUjku0b2vp3/RPK3/kGkrz5cSua1iT9kK3xecE L9+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=7Smx0iOCSSX9eHeK55h8g9w1ZJ7StZgbNaauQwbIgbw=; b=Jz7pArbKY+Vz46v5G/f+R8UZOic7Z0fvuwNtNAiqgOqcI4/p3+s2CD1ZZuEPL2JDFX PHiIOeYQcZZZJdEtXWWu54tu+FeOkU5INmvri41G9W6mg7A5hBYB33qE3mv76uk5AIEK GmtjcqvzqromsARG/ZBCi3moCHwCl8s5gJ3kdF7XRNLT3Z3NbG3uN25wWAH3XY8vvYTl /QyYRPnuNgSQ8/f1yC4IA9+GQjEilSRQI804YSlKlhcxOaB7rjWG6+oSoE8proNXbLUA 08UIcuHPToOiAzKKmbblOJL1CmUJVdqPUzM0Zg9rwO6E64IQg+J+1NN+vMVhLR3BzuPu OcYg== X-Gm-Message-State: APf1xPBUrUCt4AZ4km0tm7/nhZ9N5mbLJLjPs6QieHaTt8GX8exwq3S/ rdRFJbJzRzE9UgKpPhpMKJ0= X-Received: by 10.223.155.158 with SMTP id d30mr5735831wrc.96.1519512807381; Sat, 24 Feb 2018 14:53:27 -0800 (PST) Received: from andrea (dynamic-2a00-1028-8386-da8a-64c6-3415-9f26-73a3.ipv6.broadband.iol.cz. [2a00:1028:8386:da8a:64c6:3415:9f26:73a3]) by smtp.gmail.com with ESMTPSA id 47sm5212011wrb.48.2018.02.24.14.53.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 24 Feb 2018 14:53:26 -0800 (PST) Date: Sat, 24 Feb 2018 23:53:20 +0100 From: Andrea Parri To: Boqun Feng Cc: linux-kernel@vger.kernel.org, Peter Zijlstra , Ingo Molnar , Randy Dunlap , Jonathan Corbet , "open list:DOCUMENTATION" Subject: Re: [RFC tip/locking/lockdep v5 16/17] lockdep: Documention for recursive read lock detection reasoning Message-ID: <20180224225320.GA3027@andrea> References: <20180222070904.548-1-boqun.feng@gmail.com> <20180222070904.548-17-boqun.feng@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20180222070904.548-17-boqun.feng@gmail.com> User-Agent: Mutt/1.5.24 (2015-08-30) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Feb 22, 2018 at 03:09:03PM +0800, Boqun Feng wrote: > As now we support recursive read lock deadlock detection, add related > explanation in the Documentation/lockdep/lockdep-desgin.txt: > > * Definition of recursive read locks, non-recursive locks, strong > dependency path and notions of -(**)->. > > * Lockdep's assumption. > > * Informal proof of recursive read lock deadlock detection. Once again... much appreciated!!, thanks for sharing. > > Signed-off-by: Boqun Feng > Cc: Randy Dunlap > --- > Documentation/locking/lockdep-design.txt | 170 +++++++++++++++++++++++++++++++ > 1 file changed, 170 insertions(+) > > diff --git a/Documentation/locking/lockdep-design.txt b/Documentation/locking/lockdep-design.txt > index 382bc25589c2..fd8a8d97ce58 100644 > --- a/Documentation/locking/lockdep-design.txt > +++ b/Documentation/locking/lockdep-design.txt > @@ -284,3 +284,173 @@ Run the command and save the output, then compare against the output from > a later run of this command to identify the leakers. This same output > can also help you find situations where runtime lock initialization has > been omitted. > + > +Recursive Read Deadlock Detection: > +---------------------------------- > +Lockdep now is equipped with deadlock detection for recursive read locks. > + > +Recursive read locks, as their name indicates, are the locks able to be > +acquired recursively. Unlike non-recursive read locks, recursive read locks > +only get blocked by current write lock *holders* other than write lock > +*waiters*, for example: > + > + TASK A: TASK B: > + > + read_lock(X); > + > + write_lock(X); > + > + read_lock(X); > + > +is not a deadlock for recursive read locks, as while the task B is waiting for > +the lock X, the second read_lock() doesn't need to wait because it's a recursive > +read lock. > + > +Note that a lock can be a write lock(exclusive lock), a non-recursive read lock > +(non-recursive shared lock) or a recursive read lock(recursive shared lock), > +depending on the API used to acquire it(more specifically, the value of the > +'read' parameter for lock_acquire(...)). In other words, a single lock instance > +has three types of acquisition depending on the acquisition functions: > +exclusive, non-recursive read, and recursive read. > + > +That said, recursive read locks could introduce deadlocks too, considering the > +following: > + > + TASK A: TASK B: > + > + read_lock(X); > + read_lock(Y); > + write_lock(Y); > + write_lock(X); > + > +, neither task could get the write locks because the corresponding read locks > +are held by each other. > + > +Lockdep could detect recursive read lock related deadlocks. The dependencies(edges) > +in the lockdep graph are classified into four categories: > + > +1) -(NN)->: non-recursive to non-recursive dependency, non-recursive locks include > + non-recursive read locks, write locks and exclusive locks(e.g. spinlock_t). > + They are treated equally in deadlock detection. "X -(NN)-> Y" means > + X -> Y and both X and Y are non-recursive locks. > + > +2) -(RN)->: recursive to non-recursive dependency, recursive locks means recursive read > + locks. "X -(RN)-> Y" means X -> Y and X is recursive read lock and > + Y is non-recursive lock. > + > +3) -(NR)->: non-recursive to recursive dependency, "X -(NR)-> Y" means X -> Y and X is > + non-recursive lock and Y is recursive lock. > + > +4) -(RR)->: recursive to recursive dependency, "X -(RR)-> Y" means X -> Y and both X > + and Y are recursive locks. > + > +Note that given two locks, they may have multiple dependencies between them, for example: > + > + TASK A: > + > + read_lock(X); > + write_lock(Y); > + ... > + > + TASK B: > + > + write_lock(X); > + write_lock(Y); > + > +, we have both X -(RN)-> Y and X -(NN)-> Y in the dependency graph. > + > +And obviously a non-recursive lock can block the corresponding recursive lock, > +and vice versa. Besides a non-recursive lock may block the other non-recursive > +lock of the same instance(e.g. a write lock may block a corresponding > +non-recursive read lock and vice versa). > + > +We use -(*N)-> for edges that is either -(RN)-> or -(NN)->, the similar for -(N*)->, > +-(*R)-> and -(R*)-> > + > +A "path" is a series of conjunct dependency edges in the graph. And we define a > +"strong" path, which indicates the strong dependency throughout each dependency > +in the path, as the path that doesn't have two conjunct edges(dependencies) as > +-(*R)-> and -(R*)->. IOW, a "strong" path is a path from a lock walking to another > +through the lock dependencies, and if X -> Y -> Z in the path(where X, Y, Z are > +locks), if the walk from X to Y is through a -(NR)-> or -(RR)-> dependency, the > +walk from Y to Z must not be through a -(RN)-> or -(RR)-> dependency, otherwise > +it's not a strong path. > + > +We now prove that if a strong path forms a circle, then we have a potential deadlock. > +By "forms a circle", it means for a set of locks A0,A1...An, there is a path from > +A0 to An: > + > + A0 -> A1 -> ... -> An > + > +and there is also a dependency An->A0. And as the circle is formed by a strong path, > +so there are no two conjunct dependency edges as -(*R)-> and -(R*)->. > + > + > +To understand the actual proof, let's look into lockdep's assumption: > + > +For each lockdep dependency A -> B, there may exist a case where someone is > +trying to acquire B with A held, and the existence of such a case is > +independent to the existences of cases for other lockdep dependencies. > + > +For example if we have two functions func1 and func2: > + > + void func1(...) { > + lock(A); > + lock(B); > + unlock(A); > + unlock(B); > + > + lock(C); > + lock(A); > + unlock(A); > + unlock(C); > + } > + > + void func2(...) { > + lock(B); > + lock(C); > + unlock(C); > + unlock(B); > + } > + > +lockdep will generate dependencies: A->B, B->C and C->A, and assume that: > + > + there may exist a case where someone is trying to acquire B with A held, > + there may exist a case where someone is trying to acquire C with B held, > + and there may exist a case where someone is trying to acquire A with C held, > + > +and those three cases exist *independently*, meaning they can happen at the > +same time(which requires func1() being called simultaneously by two CPUs or > +tasks, which may be impossible due to other constraints in the real life) > + > + > +With this assumption, we can prove that if a strong dependency path forms a circle, > +then it indicates a deadlock as far as lockdep is concerned. As mentioned in a private communication, I would recommend the adoption of a "more impersonal" style. Here, for instance, the expression: "indicates a deadlock as far as lockdep is concerned" would be replaced with: "indicates a deadlock as (informally) defined in Sect. ?.?"; similarly (from the proof): "For a strong dependency [...], lockdep assumes that [...]" would be replaced with: "For a strong dependency [...], from assumption/notation ?.?, we have/we can conclude [...]". This could mean that additional text/content would need to be added to the present doc./.txt; OTOH, this could help to make this doc. self-contained/ more accessible to "non-lockdep-experts". Andrea > + > +For a strong dependency circle like: > + > + A0 -> A1 -> ... -> An > + ^ | > + | | > + +------------------+ > +, lockdep assumes that > + > + there may exist a case where someone is trying to acquire A1 with A0 held > + there may exist a case where someone is trying to acquire A2 with A1 held > + ... > + there may exist a case where someone is trying to acquire An with An-1 held > + there may exist a case where someone is trying to acquire A0 with An held > + > +, and because it's a *strong* dependency circle for every Ai (0<=i<=n), Ai is either > +held as a non-recursive lock or someone is trying to acquire Ai as a non-recursive lock, > +which gives: > + > +* If Ai is held as a non-recursive lock, then trying to acquire it, > + whether as a recursive lock or not, will get blocked. > + > +* If Ai is held as a recursive lock, then there must be someone is trying to acquire > + it as a non-recursive lock, and because recursive locks blocks non-recursive locks, > + then it(the "someone") will get blocked. > + > +So all the holders of A0, A1...An are blocked with A0, A1...An held by each other, > +no one can progress, therefore deadlock. > -- > 2.16.1 >