Re: [PATCH] sched/cputime: make scale_stime() more precise

From: Oleg Nesterov
Date: Thu Jul 18 2019 - 09:21:12 EST


To simplify the review, see the code with this patch applied:

/*
* Perform (stime * rtime) / total, but avoid multiplication overflow
* by losing precision when the numbers are big.
*
* NOTE! currently the only user is cputime_adjust() and thus
*
* stime < total && rtime > total
*
* this means that the end result is always precise and the additional
* div64_u64_rem() inside the main loop is called at most once.
*/
static u64 scale_stime(u64 stime, u64 rtime, u64 total)
{
u64 res = 0, div, rem;

/* can stime * rtime overflow ? */
while (ilog2(stime) + ilog2(rtime) > 62) {
if (stime > rtime)
swap(rtime, stime);

if (rtime >= total) {
/*
* (rtime * stime) / total is equal to
*
* (rtime / total) * stime +
* (rtime % total) * stime / total
*
* if nothing overflows. Can the 1st multiplication
* overflow? Yes, but we do not care: this can only
* happen if the end result can't fit in u64 anyway.
*
* So the code below does
*
* res += (rtime / total) * stime;
* rtime = rtime % total;
*/
div = div64_u64_rem(rtime, total, &rem);
res += div * stime;
rtime = rem;
continue;
}

/* drop precision */
rtime >>= 1;
total >>= 1;
if (!total)
return res;
}

return res + div64_u64(stime * rtime, total);
}