From owner-svn-src-head@freebsd.org Thu Feb 6 20:51:46 2020 Return-Path: <owner-svn-src-head@freebsd.org> Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id C6CC523AA35; Thu, 6 Feb 2020 20:51:46 +0000 (UTC) (envelope-from jeff@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 48D9b64tGXz3C4V; Thu, 6 Feb 2020 20:51:46 +0000 (UTC) (envelope-from jeff@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id A2B53218A0; Thu, 6 Feb 2020 20:51:46 +0000 (UTC) (envelope-from jeff@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 016KpksH000138; Thu, 6 Feb 2020 20:51:46 GMT (envelope-from jeff@FreeBSD.org) Received: (from jeff@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 016KpkjY000137; Thu, 6 Feb 2020 20:51:46 GMT (envelope-from jeff@FreeBSD.org) Message-Id: <202002062051.016KpkjY000137@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jeff set sender to jeff@FreeBSD.org using -f From: Jeff Roberson <jeff@FreeBSD.org> Date: Thu, 6 Feb 2020 20:51:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r357641 - head/sys/kern X-SVN-Group: head X-SVN-Commit-Author: jeff X-SVN-Commit-Paths: head/sys/kern X-SVN-Commit-Revision: 357641 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for the src tree for head/-current <svn-src-head.freebsd.org> List-Unsubscribe: <https://lists.freebsd.org/mailman/options/svn-src-head>, <mailto:svn-src-head-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-head/> List-Post: <mailto:svn-src-head@freebsd.org> List-Help: <mailto:svn-src-head-request@freebsd.org?subject=help> List-Subscribe: <https://lists.freebsd.org/mailman/listinfo/svn-src-head>, <mailto:svn-src-head-request@freebsd.org?subject=subscribe> X-List-Received-Date: Thu, 06 Feb 2020 20:51:46 -0000 Author: jeff Date: Thu Feb 6 20:51:46 2020 New Revision: 357641 URL: https://svnweb.freebsd.org/changeset/base/357641 Log: Fix a race in smr_advance() that could result in unnecessary poll calls. This was relatively harmless but surprising to see in counters. The race occurred when rd_seq was read after the goal was updated and we incorrectly calculated the delta between them. Reviewed by: rlibby Differential Revision: https://reviews.freebsd.org/D23464 Modified: head/sys/kern/subr_smr.c Modified: head/sys/kern/subr_smr.c ============================================================================== --- head/sys/kern/subr_smr.c Thu Feb 6 20:47:50 2020 (r357640) +++ head/sys/kern/subr_smr.c Thu Feb 6 20:51:46 2020 (r357641) @@ -160,7 +160,7 @@ static uma_zone_t smr_zone; #define SMR_SEQ_INCR (UINT_MAX / 10000) #define SMR_SEQ_INIT (UINT_MAX - 100000) /* Force extra polls to test the integer overflow detection. */ -#define SMR_SEQ_MAX_DELTA (1000) +#define SMR_SEQ_MAX_DELTA (SMR_SEQ_INCR * 32) #define SMR_SEQ_MAX_ADVANCE SMR_SEQ_MAX_DELTA / 2 #endif @@ -188,7 +188,7 @@ smr_seq_t smr_advance(smr_t smr) { smr_shared_t s; - smr_seq_t goal; + smr_seq_t goal, s_rd_seq; /* * It is illegal to enter while in an smr section. @@ -203,12 +203,18 @@ smr_advance(smr_t smr) atomic_thread_fence_rel(); /* + * Load the current read seq before incrementing the goal so + * we are guaranteed it is always < goal. + */ + s = zpcpu_get(smr)->c_shared; + s_rd_seq = atomic_load_acq_int(&s->s_rd_seq); + + /* * Increment the shared write sequence by 2. Since it is * initialized to 1 this means the only valid values are * odd and an observed value of 0 in a particular CPU means * it is not currently in a read section. */ - s = zpcpu_get(smr)->c_shared; goal = atomic_fetchadd_int(&s->s_wr_seq, SMR_SEQ_INCR) + SMR_SEQ_INCR; counter_u64_add(advance, 1); @@ -217,7 +223,7 @@ smr_advance(smr_t smr) * far ahead of the read sequence number. This keeps the * wrap detecting arithmetic working in pathological cases. */ - if (goal - atomic_load_int(&s->s_rd_seq) >= SMR_SEQ_MAX_DELTA) { + if (SMR_SEQ_DELTA(goal, s_rd_seq) >= SMR_SEQ_MAX_DELTA) { counter_u64_add(advance_wait, 1); smr_wait(smr, goal - SMR_SEQ_MAX_ADVANCE); }