Received: by 2002:a25:ca44:0:0:0:0:0 with SMTP id a65csp1116323ybg; Mon, 27 Jul 2020 08:18:32 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxPmQSZ6RZum+EzQUq8s3YtDiOrIIZcZn4xD0bViYIi/HFvWzRXG5R3ZKl6LxCl+JeGirvE X-Received: by 2002:a17:906:4356:: with SMTP id z22mr22257270ejm.414.1595863111974; Mon, 27 Jul 2020 08:18:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1595863111; cv=none; d=google.com; s=arc-20160816; b=ykk6cYpcxk2VqFdUVkw20PxIaUnj7MxCXeXjvTX4BvFCYPEfVwBvbfPwbM7ylS159l AkGyPukRNSDQLgC0q+Ld5kYnqbhj4FObWBdV39mRLgrs+lEqmDUOG0bAPuTT6U0F0k1T 9fxdFlc0cv1J6kdB08ZBXr/hou5JVVct7EuLldjXoSgI3On8ewi/xm5fssgxV7AooR1n lMao/n0kjvlPTB2pxIq+dhjLFaGKyAeYLNA1yjpsWktEa2+L0W46R4Mt7DUpciILDiM4 WtjGbg1cHbT3Suv4n/+bswJY52UbT0nGOWc5+xIZcJlUmHcPxEk1TGGH9aT5jgyMwKNl ujww== 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=TJsF2nMrNlNErC8JmZ9iRyCUXFlwrDwcqSNT6vw4J+o=; b=u++aZ0AsEZAJ2lf1MVptdUI9XNsvTYJtEaDIWAthjzIN1w+UnVQbZ7O+2n/Sx9QQ2c C6GtaWseNiyX8wPM+HfUnmTIj/BU7S9LbdhJyizsW7DFYJPPbqdPPx4GkSWsw8fTOfsD zApG/TSJ8qXlKuXWLZnZBtrnEzmPK4mhgj4DwgfK0r65UX16qR2oREo0/XXCBy5jMBeJ GiMiq9UHAK/zzmsVUEMZUAnVIeihZyJ1s438LtrLMwLp+sfK2ao1tIaB3m0J0ltvNBnM RGwQMut+HopxayCq9Go4m3tkB8KdLbyvfXeaJenHoB6ykTbntKC8l6D6AgZHfryv+h5w MgFA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ha25si5716541ejb.628.2020.07.27.08.18.09; Mon, 27 Jul 2020 08:18:31 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729116AbgG0PRs (ORCPT + 99 others); Mon, 27 Jul 2020 11:17:48 -0400 Received: from netrider.rowland.org ([192.131.102.5]:46657 "HELO netrider.rowland.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1729039AbgG0PRr (ORCPT ); Mon, 27 Jul 2020 11:17:47 -0400 Received: (qmail 1470770 invoked by uid 1000); 27 Jul 2020 11:17:46 -0400 Date: Mon, 27 Jul 2020 11:17:46 -0400 From: Alan Stern To: Eric Biggers Cc: Matthew Wilcox , linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org, "Paul E . McKenney" , linux-fsdevel@vger.kernel.org, Akira Yokosawa , Andrea Parri , Boqun Feng , Daniel Lustig , "Darrick J . Wong" , Dave Chinner , David Howells , Jade Alglave , Luc Maranget , Nicholas Piggin , Peter Zijlstra , Will Deacon Subject: Re: [PATCH] tools/memory-model: document the "one-time init" pattern Message-ID: <20200727151746.GC1468275@rowland.harvard.edu> References: <20200717044427.68747-1-ebiggers@kernel.org> <20200717174750.GQ12769@casper.infradead.org> <20200718013839.GD2183@sol.localdomain> <20200718021304.GS12769@casper.infradead.org> <20200718052818.GF2183@sol.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20200718052818.GF2183@sol.localdomain> User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Jul 17, 2020 at 10:28:18PM -0700, Eric Biggers wrote: > I'm still not sure this is the best API. I cast my vote for something along the following lines. It's simple, easily understood and easily used. The approach has two variants: One that returns an integer and one that returns a pointer. I'll use the pointer variant to illustrate. Given a type "T", an object x of type pointer-to-T, and a function "func" that takes various arguments and returns a pointer-to-T, the accepted API for calling func once would be to create once_func() as follows: T *once_func(T **ppt, args...) { static DEFINE_MUTEX(mut); T *p; p = smp_load_acquire(ppt); /* Mild optimization */ if (p) return p; mutex_lock(mut); p = smp_load_acquire(ppt); if (!p) { p = func(args...); if (!IS_ERR_OR_NULL(p)) smp_store_release(ppt, p); } mutex_unlock(mut); return p; } Users then would have to call once_func(&x, args...) and check the result. Different x objects would constitute different "once" domains. (In the integer variant, x, p and the return type of func are all int, and ppt is an int *. Everything else is the same. This variant would be used in cases where you're not allocating anything, you're doing some other sort of initialization only once.) While this would be a perfectly good recipe in itself, the whole thing can be made much simpler for users by creating a MAKE_ONCE_FUNC macro which would generate once_func given the type T, the name "func", and the args. The result is type-safe. IMO the fact that once_func() is not inline is an advantage, not a drawback. Yes, it doesn't actually do any allocation or anything like that -- the idea is that once_func's purpose is merely to ensure that func is successfully called only once. Any memory allocation or other stuff of that sort should be handled by func. In fact, the only drawback I can think of is that because this relies on a single mutex for all the different possible x's, it might lead to locking conflicts (if func had to call once_func() recursively, for example). In most reasonable situations such conflicts would not arise. Alan Stern