Received: by 2002:a25:8b12:0:0:0:0:0 with SMTP id i18csp1228228ybl; Fri, 23 Aug 2019 15:45:02 -0700 (PDT) X-Google-Smtp-Source: APXvYqx7P+JfhtdX8byppqy3VqKMes0pHVVipq8Iur86rqSZ3VRG+jKXD2zQ7gWvnTrYjobbXFxc X-Received: by 2002:a17:902:5c3:: with SMTP id f61mr6837163plf.98.1566600302897; Fri, 23 Aug 2019 15:45:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1566600302; cv=none; d=google.com; s=arc-20160816; b=Hva5Z8UraZb5jMRajCLpHTOkGAsjDAH6WBncZTM0uQjcMPj9/xEp+G2yAd3Wx5G214 zPWgUwLfPWnsP5ptMSABbMuDb6RRW6nnwouFgd4nIOtSxVxXnMIlLT9jvT0CM+6mbMtP hTQ8jkJSlQmA/nXRtCCUBXAK/txRtaRHI4CEOQjXHlTAo/CYWmevyNIQexnK8LKlu/mo evq0HyvrC/IeqDLg61oah62JLqM+aaqpc8PxyuxZu3Yz29O5Ps1CAP4MmzkdoMR1Q/se Un3h2FiBo1qSr1nT2Fg5qNkXd0CsbSUtWgCHFHwivWdNhFsXS9B77FNh12K62JswaNGN 8u3w== 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; bh=P/dzOJ+2t+008ErHNtbW7Or2GOSSkyjf4ju4w3fOaDg=; b=Px19qhs6rwujpPc/SGgl0t4J5h4Jq6JUoOqR2KffZ6IgaWlcg95lPmMdCMCxwYlVrg TbkdBBPFtALNLjnCY5sot2Hrn07CY9AYvAsTELvkr4X2wbJWx8+Y0V/Zmm4dKb29KDG+ vrqqYRANIQWgjeJ7nPL4GR7fktz68tk0i1OnBnsZjpE8qYhNYrTYr+FHPRnuFE8A8ee0 ThMViLc082sD09uaZiT175bvjvn3AS7mTpjHKPWb6LhpyYghks1W9IoYSQQZKW1NRi9d FxL6ISULIQoK7rp9Q9q+oZB8KfftZ7CppkBAm276CMlJ533/89Fau6tixxOjXphZ98L2 Zdog== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 123si4001558pfy.61.2019.08.23.15.44.47; Fri, 23 Aug 2019 15:45:02 -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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728122AbfHWJVM (ORCPT + 99 others); Fri, 23 Aug 2019 05:21:12 -0400 Received: from mx2.suse.de ([195.135.220.15]:35380 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725857AbfHWJVM (ORCPT ); Fri, 23 Aug 2019 05:21:12 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 61DD8B0E6; Fri, 23 Aug 2019 09:21:10 +0000 (UTC) Date: Fri, 23 Aug 2019 11:21:09 +0200 From: Petr Mladek To: John Ogness Cc: linux-kernel@vger.kernel.org, Andrea Parri , Sergey Senozhatsky , Sergey Senozhatsky , Steven Rostedt , Brendan Higgins , Peter Zijlstra , Thomas Gleixner , Linus Torvalds , Greg Kroah-Hartman Subject: numlist_push() barriers Re: [RFC PATCH v4 1/9] printk-rb: add a new printk ringbuffer implementation Message-ID: <20190823092109.doduc36avylm5cds@pathway.suse.cz> References: <20190807222634.1723-1-john.ogness@linutronix.de> <20190807222634.1723-2-john.ogness@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20190807222634.1723-2-john.ogness@linutronix.de> User-Agent: NeoMutt/20170912 (1.9.0) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu 2019-08-08 00:32:26, John Ogness wrote: > --- /dev/null > +++ b/kernel/printk/numlist.c > +/** > + * numlist_push() - Add a node to the list and assign it a sequence number. > + * > + * @nl: The numbered list to push to. > + * > + * @n: A node to push to the numbered list. > + * The node must not already be part of a list. > + * > + * @id: The ID of the node. > + * > + * A node is added in two steps: The first step is to make this node the > + * head, which causes a following push to add to this node. The second step is > + * to update @next_id of the former head node to point to this one, which > + * makes this node visible to any task that sees the former head node. > + */ > +void numlist_push(struct numlist *nl, struct nl_node *n, unsigned long id) > +{ > + unsigned long head_id; > + unsigned long seq; > + unsigned long r; > + > + /* > + * bA: > + * > + * Setup the node to be a list terminator: next_id == id. > + */ > + WRITE_ONCE(n->next_id, id); Do we need WRITE_ONCE() here? Both "n" and "id" are given as parameters and do not change. The assigment must be done before "id" is set as nl->head_id. The ordering is enforced by cmpxchg_release(). > + > + /* bB: #1 */ > + head_id = atomic_long_read(&nl->head_id); > + > + for (;;) { > + /* bC: */ > + while (!numlist_read(nl, head_id, &seq, NULL)) { > + /* > + * @head_id is invalid. Try again with an > + * updated value. > + */ > + > + cpu_relax(); I have got very confused by this. cpu_relax() suggests that this cycle is busy waiting until a particular node becomes valid. My first though was that it must cause deadlock in NMI when the interrupted code is supposed to make the node valid. But it is the other way. The head is always valid when it is added to the list. It might become invalid when another CPU moves the head and the old one gets reused. Anyway, I do not see any reason for cpu_relax() here. Also the entire cycle would deserve a comment to avoid this mistake. For example: /* * bC: Read seq from current head. Repeat with new * head when it has changed and the old one got reused. */ > + > + /* bB: #2 */ > + head_id = atomic_long_read(&nl->head_id); > + } > + > + /* > + * bD: > + * > + * Set @seq to +1 of @seq from the previous head. > + * > + * Memory barrier involvement: > + * > + * If bB reads from bE, then bC->aA reads from bD. > + * > + * Relies on: > + * > + * RELEASE from bD to bE > + * matching > + * ADDRESS DEP. from bB to bC->aA > + */ > + WRITE_ONCE(n->seq, seq + 1); Do we really need WRITE_ONCE() here? It is the same problem as with setting n->next_id above. > + > + /* > + * bE: > + * > + * This store_release() guarantees that @seq and @next are > + * stored before the node with @id is visible to any popping > + * writers. It pairs with the address dependency between @id > + * and @seq/@next provided by numlist_read(). See bD and bF > + * for details. > + */ > + r = atomic_long_cmpxchg_release(&nl->head_id, head_id, id); > + if (r == head_id) > + break; > + > + /* bB: #3 */ > + head_id = r; > + } > + > + n = nl->node(head_id, nl->node_arg); > + > + /* > + * The old head (which is still the list terminator), cannot be > + * removed because the list will always have at least one node. > + * Therefore @n must be non-NULL. > + */ Please, move this comment above the nl->node() call. Both locations makes sense. I just see it as an important note for the call and thus is should be above. Also it will be better separated from the below comments for the _release() barrier. > + /* > + * bF: the STORE part for @next_id > + * > + * Set @next_id of the previous head to @id. > + * > + * Memory barrier involvement: > + * > + * If bB reads from bE, then bF overwrites bA. > + * > + * Relies on: > + * > + * RELEASE from bA to bE > + * matching > + * ADDRESS DEP. from bB to bF > + */ > + /* > + * bG: the RELEASE part for @next_id > + * > + * This _release() guarantees that a reader will see the updates to > + * this node's @seq/@next_id if the reader saw the @next_id of the > + * previous node in the list. It pairs with the address dependency > + * between @id and @seq/@next provided by numlist_read(). > + * > + * Memory barrier involvement: > + * > + * If aB reads from bG, then aA' reads from bD, where aA' is in > + * numlist_read() to read the node ID from bG. > + * If aB reads from bG, then aB' reads from bA, where aB' is in > + * numlist_read() to read the node ID from bG. > + * > + * Relies on: > + * > + * RELEASE from bG to bD > + * matching > + * ADDRESS DEP. from aB to aA' > + * > + * RELEASE from bG to bA > + * matching > + * ADDRESS DEP. from aB to aB' > + */ > + smp_store_release(&n->next_id, id); Sigh, I see this line one screen below the previous command thanks to the extensive comments. Well, bF comment looks redundant. > +} Best Regards, Petr