> On 6. Feb 2020, at 21:51, Jeff Roberson <j...@freebsd.org> wrote:
>
> 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) {
SMR_SEQ_DELTA is not defined, therefore compilation fails.
Best regards
Michael
> counter_u64_add(advance_wait, 1);
> smr_wait(smr, goal - SMR_SEQ_MAX_ADVANCE);
> }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"