On Wed, May 04, 2022 at 12:14:01AM +0200, Alexander Bluhm wrote: > Hi, > > We have one comment that locking for ratecheck(9) is missing. In > all other places locking status of the struct timeval *lasttime > is unclear. > > The easiest fix is a global mutex for all lasttime in ratecheck(). > This covers the usual usecase of the function. > > Same for ppsratecheck(9), lasttime and curpps are protected. > > Remove a useless #if 1 while there. > > ok?
For now this is the quickest way to move forward. OK claudio@ It would be nice to make ratecheck() and ppsratecheck() only require a lock in the unusual case of hitting the limit. At least in the common case these calls should be as cheap as possible. This is a nice little project for someone to explore how to implement this in a fast way that does not introduce bus locks or other slow operations. > Index: kern/kern_malloc.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/kern/kern_malloc.c,v > retrieving revision 1.146 > diff -u -p -r1.146 kern_malloc.c > --- kern/kern_malloc.c 16 May 2021 15:10:20 -0000 1.146 > +++ kern/kern_malloc.c 3 May 2022 21:51:21 -0000 > @@ -188,7 +188,6 @@ malloc(size_t size, int type, int flags) > if (size > 65535 * PAGE_SIZE) { > if (flags & M_CANFAIL) { > #ifndef SMALL_KERNEL > - /* XXX lock */ > if (ratecheck(&malloc_lasterr, &malloc_errintvl)) > printf("malloc(): allocation too large, " > "type = %d, size = %lu\n", type, size); > Index: kern/kern_time.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/kern/kern_time.c,v > retrieving revision 1.154 > diff -u -p -r1.154 kern_time.c > --- kern/kern_time.c 18 Jun 2021 15:59:14 -0000 1.154 > +++ kern/kern_time.c 3 May 2022 21:51:21 -0000 > @@ -782,11 +782,13 @@ itimerdecr(struct itimerspec *itp, long > int > ratecheck(struct timeval *lasttime, const struct timeval *mininterval) > { > + static struct mutex mtx = MUTEX_INITIALIZER(IPL_HIGH); > struct timeval tv, delta; > int rv = 0; > > getmicrouptime(&tv); > > + mtx_enter(&mtx); > timersub(&tv, lasttime, &delta); > > /* > @@ -798,6 +800,7 @@ ratecheck(struct timeval *lasttime, cons > *lasttime = tv; > rv = 1; > } > + mtx_leave(&mtx); > > return (rv); > } > @@ -808,11 +811,13 @@ ratecheck(struct timeval *lasttime, cons > int > ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) > { > + static struct mutex mtx = MUTEX_INITIALIZER(IPL_HIGH); > struct timeval tv, delta; > int rv; > > microuptime(&tv); > > + mtx_enter(&mtx); > timersub(&tv, lasttime, &delta); > > /* > @@ -837,20 +842,11 @@ ppsratecheck(struct timeval *lasttime, i > else > rv = 0; > > -#if 1 /*DIAGNOSTIC?*/ > /* be careful about wrap-around */ > if (*curpps + 1 > *curpps) > *curpps = *curpps + 1; > -#else > - /* > - * assume that there's not too many calls to this function. > - * not sure if the assumption holds, as it depends on *caller's* > - * behavior, not the behavior of this function. > - * IMHO it is wrong to make assumption on the caller's behavior, > - * so the above #if is #if 1, not #ifdef DIAGNOSTIC. > - */ > - *curpps = *curpps + 1; > -#endif > + > + mtx_leave(&mtx); > > return (rv); > } > -- :wq Claudio