Re: svn commit: r357641 - head/sys/kern
On 2/6/20, Michael Tuexen wrote: > > >> On 6. Feb 2020, at 21:51, Jeff Roberson 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 / 1) >> #define SMR_SEQ_INIT(UINT_MAX - 10) >> /* 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. https://reviews.freebsd.org/D23464#516866 https://reviews.freebsd.org/D23464#516881 Jung-uk Kim > Best regards > Michael >> counter_u64_add(advance_wait, 1); >> smr_wait(smr, goal - SMR_SEQ_MAX_ADVANCE); >> } signature.asc Description: OpenPGP digital signature
Re: svn commit: r357641 - head/sys/kern
> On 6. Feb 2020, at 21:51, Jeff Roberson 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 / 1) > #define SMR_SEQ_INIT(UINT_MAX - 10) > /* 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"
svn commit: r357641 - head/sys/kern
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.cThu Feb 6 20:47:50 2020(r357640) +++ head/sys/kern/subr_smr.cThu Feb 6 20:51:46 2020(r357641) @@ -160,7 +160,7 @@ static uma_zone_t smr_zone; #defineSMR_SEQ_INCR(UINT_MAX / 1) #defineSMR_SEQ_INIT(UINT_MAX - 10) /* Force extra polls to test the integer overflow detection. */ -#defineSMR_SEQ_MAX_DELTA (1000) +#defineSMR_SEQ_MAX_DELTA (SMR_SEQ_INCR * 32) #defineSMR_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); } ___ 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"