Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp3392910imu; Mon, 28 Jan 2019 04:11:11 -0800 (PST) X-Google-Smtp-Source: ALg8bN5LBRem7PS3B6Lm6J6v9p6GVy2zribqaU+4cR8yyAUO3KaStjsgf7plkWpu/Y/k+4Ay5igP X-Received: by 2002:a17:902:680f:: with SMTP id h15mr21257487plk.40.1548677471176; Mon, 28 Jan 2019 04:11:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1548677471; cv=none; d=google.com; s=arc-20160816; b=05moDPc1NGjqwS/wbAK92/ME/r6DNXI1mNjnSTNMxD7DoV8BdQKBem7oGPLVXXt2us Pvmv8MjPoc2AuuiilpfHTCnQ0v+lfT3XDfYv+U+/nNzAzCgNuQGsbuJ8N9THKhNfNIg4 qYo7QVJrIEGVASaW5ouiXWbfHMO8aFLzNeKmdd6UzuUnzd18ThGIfVQnGMDzbERMCMQq giwGnErMXxJuqDxZkiO4oYzh5zeXHzTusBcOVSP5fq+hpXrOVrAi1XWj0YH97h1wsFqo g3BdRB2/0e8dIIgM1WsBPGW6uJ1CYphxgXuXQxd4/s6u7J273h4lHgAyxrY0eAgW1YKI WF3A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from; bh=ftJG7G4AJcpjzzgG+BY0tMKhCDCP6mvHzTPlhtrS8lA=; b=EyV1RYr8IjV+2YvJmS5dpWgKogKGvgGZWyZb1qq5YrXxdjx0Oc3RAxSlF8+CZZqKRn 66CVjfef2d/cWXnUf91k4d4oomDstP+llPZKzy+8HIP2OYAFDvHjoxyYmHBi0VBKCNxW uMNKpdY2Pvsh2/Levbg6j1T7ZIV/JAVAjyERqJBB1HB7XhjMm0ljUdHWZxTjWegNM+i1 FJXrJCZhVxe6P5EBdO2G4wZHYKrgiWKcgS0jz7fyLKPJtngAiZbcN4EAyXJ/Gz3ypGmn SmB+c/v4cJ/2hrWKknUqxCzPZJ76GYjK3jjnUkZ87r+m5k0QgxAGwBsM3tZsaYkpV96T 57cQ== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s17si3038845pgi.513.2019.01.28.04.10.55; Mon, 28 Jan 2019 04:11:11 -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; 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=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726832AbfA1MJv (ORCPT + 99 others); Mon, 28 Jan 2019 07:09:51 -0500 Received: from mga11.intel.com ([192.55.52.93]:39669 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726786AbfA1MJv (ORCPT ); Mon, 28 Jan 2019 07:09:51 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 28 Jan 2019 04:09:49 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,534,1539673200"; d="scan'208";a="129489662" Received: from elena-thinkpad-x230.fi.intel.com ([10.237.68.34]) by orsmga002.jf.intel.com with ESMTP; 28 Jan 2019 04:09:47 -0800 From: Elena Reshetova To: peterz@infradead.org Cc: linux-kernel@vger.kernel.org, keescook@chromium.org, andrea.parri@amarulasolutions.com, Elena Reshetova Subject: [PATCH] refcount_t: add ACQUIRE ordering on success for dec(sub)_and_test variants Date: Mon, 28 Jan 2019 14:09:37 +0200 Message-Id: <1548677377-22177-1-git-send-email-elena.reshetova@intel.com> X-Mailer: git-send-email 2.7.4 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This adds an smp_acquire__after_ctrl_dep() barrier on successful decrease of refcounter value from 1 to 0 for refcount_dec(sub)_and_test variants and therefore gives stronger memory ordering guarantees than prior versions of these functions. Co-Developed-by: Peter Zijlstra (Intel) Signed-off-by: Elena Reshetova --- Documentation/core-api/refcount-vs-atomic.rst | 28 +++++++++++++++++++++++---- arch/x86/include/asm/refcount.h | 21 ++++++++++++++++---- lib/refcount.c | 16 ++++++++++----- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/Documentation/core-api/refcount-vs-atomic.rst b/Documentation/core-api/refcount-vs-atomic.rst index 322851b..95d4b4e 100644 --- a/Documentation/core-api/refcount-vs-atomic.rst +++ b/Documentation/core-api/refcount-vs-atomic.rst @@ -54,6 +54,14 @@ must propagate to all other CPUs before the release operation (A-cumulative property). This is implemented using :c:func:`smp_store_release`. +An ACQUIRE memory ordering guarantees that all post loads and +stores (all po-later instructions) on the same CPU are +completed after the acquire operation. It also guarantees that all +po-later stores on the same CPU and all propagated stores from other CPUs +must propagate to all other CPUs after the acquire operation +(A-cumulative property). This is implemented using +:c:func:`smp_acquire__after_ctrl_dep`. + A control dependency (on success) for refcounters guarantees that if a reference for an object was successfully obtained (reference counter increment or addition happened, function returned true), @@ -119,24 +127,36 @@ Memory ordering guarantees changes: result of obtaining pointer to the object! -case 5) - decrement-based RMW ops that return a value ------------------------------------------------------ +case 5) - generic dec/sub decrement-based RMW ops that return a value +--------------------------------------------------------------------- Function changes: * :c:func:`atomic_dec_and_test` --> :c:func:`refcount_dec_and_test` * :c:func:`atomic_sub_and_test` --> :c:func:`refcount_sub_and_test` + +Memory ordering guarantees changes: + + * fully ordered --> RELEASE ordering + ACQUIRE ordering and control dependency + on success. + + +case 6) other decrement-based RMW ops that return a value +--------------------------------------------------------- + +Function changes: + * no atomic counterpart --> :c:func:`refcount_dec_if_one` * ``atomic_add_unless(&var, -1, 1)`` --> ``refcount_dec_not_one(&var)`` Memory ordering guarantees changes: - * fully ordered --> RELEASE ordering + control dependency + * fully ordered --> RELEASE ordering + control dependency .. note:: :c:func:`atomic_add_unless` only provides full order on success. -case 6) - lock-based RMW +case 7) - lock-based RMW ------------------------ Function changes: diff --git a/arch/x86/include/asm/refcount.h b/arch/x86/include/asm/refcount.h index dbaed55..ab8f584 100644 --- a/arch/x86/include/asm/refcount.h +++ b/arch/x86/include/asm/refcount.h @@ -67,16 +67,29 @@ static __always_inline void refcount_dec(refcount_t *r) static __always_inline __must_check bool refcount_sub_and_test(unsigned int i, refcount_t *r) { - return GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl", + bool ret = GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl", REFCOUNT_CHECK_LT_ZERO, r->refs.counter, e, "er", i, "cx"); + + if (ret) { + smp_acquire__after_ctrl_dep(); + return true; + } + + return false; } static __always_inline __must_check bool refcount_dec_and_test(refcount_t *r) { - return GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl", - REFCOUNT_CHECK_LT_ZERO, - r->refs.counter, e, "cx"); + bool ret = GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl", + REFCOUNT_CHECK_LT_ZERO, + r->refs.counter, e, "cx"); + if (ret) { + smp_acquire__after_ctrl_dep(); + return true; + } + + return false; } static __always_inline __must_check diff --git a/lib/refcount.c b/lib/refcount.c index ebcf8cd..732feac 100644 --- a/lib/refcount.c +++ b/lib/refcount.c @@ -33,6 +33,9 @@ * Note that the allocator is responsible for ordering things between free() * and alloc(). * + * The decrements dec_and_test() and sub_and_test() also provide acquire + * ordering on success. + * */ #include @@ -164,8 +167,7 @@ EXPORT_SYMBOL(refcount_inc_checked); * at UINT_MAX. * * Provides release memory ordering, such that prior loads and stores are done - * before, and provides a control dependency such that free() must come after. - * See the comment on top. + * before, and provides an acquire ordering on success such that free() must come after. * * Use of this function is not recommended for the normal reference counting * use case in which references are taken and released one at a time. In these @@ -190,7 +192,12 @@ bool refcount_sub_and_test_checked(unsigned int i, refcount_t *r) } while (!atomic_try_cmpxchg_release(&r->refs, &val, new)); - return !new; + if (!new) { + smp_acquire__after_ctrl_dep(); + return true; + } + return false; + } EXPORT_SYMBOL(refcount_sub_and_test_checked); @@ -202,8 +209,7 @@ EXPORT_SYMBOL(refcount_sub_and_test_checked); * decrement when saturated at UINT_MAX. * * Provides release memory ordering, such that prior loads and stores are done - * before, and provides a control dependency such that free() must come after. - * See the comment on top. + * before, and provides an acquire ordering on success such that free() must come after. * * Return: true if the resulting refcount is 0, false otherwise */ -- 2.7.4