public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Stanislaw Gruszka <sgruszka@redhat.com>
To: Ingo Molnar <mingo@kernel.org>, Peter Zijlstra <peterz@infradead.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>,
	hpa@zytor.com, rostedt@goodmis.org, akpm@linux-foundation.org,
	tglx@linutronix.de,
	Linus Torvalds <torvalds@linux-foundation.org>,
	linux-kernel@vger.kernel.org, Dave Hansen <dave@sr71.net>
Subject: [PATCH -tip 1/4 v2] sched: Avoid cputime scaling overflow
Date: Tue, 30 Apr 2013 17:14:42 +0200	[thread overview]
Message-ID: <20130430151441.GC10465@redhat.com> (raw)
In-Reply-To: <1367314507-9728-1-git-send-email-sgruszka@redhat.com>

Here is patch, which add Linus cputime scaling algorithm to the kernel.

This is follow up of commit d9a3c9823a2e6a543eb7807fb3d15d8233817ec5
"sched: Lower chances of cputime scaling overflow" which try to avoid
multiplication overflow, but not guarantee that the overflow will not
happen.

Linus crated different algorithm, which avoid completely multiplication
overflow by dropping precision when numbers are big. It was tested
by me and it gives good relative error of scaled numbers. Testing
method is described here:
http://marc.info/?l=linux-kernel&m=136733059505406&w=2

Originally-From: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
v1 -> v2: add Originally-From and testing information. 

 kernel/sched/cputime.c | 57 +++++++++++++++++++++++++++++++-------------------
 1 file changed, 35 insertions(+), 22 deletions(-)

diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index ea32f02..b3dd984 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -506,34 +506,47 @@ void account_idle_ticks(unsigned long ticks)
 }
 
 /*
- * Perform (stime * rtime) / total with reduced chances
- * of multiplication overflows by using smaller factors
- * like quotient and remainders of divisions between
- * rtime and total.
+ * Perform (stime * rtime) / total, but avoid multiplication overflow by
+ * loosing precision when the numbers are big.
  */
 static cputime_t scale_stime(u64 stime, u64 rtime, u64 total)
 {
-	u64 rem, res, scaled;
+	u64 scaled;
 
-	if (rtime >= total) {
-		/*
-		 * Scale up to rtime / total then add
-		 * the remainder scaled to stime / total.
-		 */
-		res = div64_u64_rem(rtime, total, &rem);
-		scaled = stime * res;
-		scaled += div64_u64(stime * rem, total);
-	} else {
-		/*
-		 * Same in reverse: scale down to total / rtime
-		 * then substract that result scaled to
-		 * to the remaining part.
-		 */
-		res = div64_u64_rem(total, rtime, &rem);
-		scaled = div64_u64(stime, res);
-		scaled -= div64_u64(scaled * rem, total);
+	for (;;) {
+		/* Make sure "rtime" is the bigger of stime/rtime */
+		if (stime > rtime) {
+			u64 tmp = rtime; rtime = stime; stime = tmp;
+		}
+
+		/* Make sure 'total' fits in 32 bits */
+		if (total >> 32)
+			goto drop_precision;
+
+		/* Does rtime (and thus stime) fit in 32 bits? */
+		if (!(rtime >> 32))
+			break;
+
+		/* Can we just balance rtime/stime rather than dropping bits? */
+		if (stime >> 31)
+			goto drop_precision;
+
+		/* We can grow stime and shrink rtime and try to make them both fit */
+		stime <<= 1;
+		rtime >>= 1;
+		continue;
+
+drop_precision:
+		/* We drop from rtime, it has more bits than stime */
+		rtime >>= 1;
+		total >>= 1;
 	}
 
+	/*
+	 * Make sure gcc understands that this is a 32x32->64 multiply,
+	 * followed by a 64/32->64 divide.
+	 */
+	scaled = div_u64((u64) (u32) stime * (u64) (u32) rtime, (u32)total);
 	return (__force cputime_t) scaled;
 }
 
-- 
1.7.11.7


  parent reply	other threads:[~2013-04-30 15:14 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-30  9:35 [PATCH -tip 1/4] sched: Avoid cputime scaling overflow Stanislaw Gruszka
2013-04-30  9:35 ` [PATCH -tip 2/4] sched: Do not account bogus utime Stanislaw Gruszka
2013-05-01 10:04   ` [tip:sched/urgent] " tip-bot for Stanislaw Gruszka
2013-04-30  9:35 ` [PATCH -tip 3/4] sched: Avoid prev->stime underflow Stanislaw Gruszka
2013-05-01 10:06   ` [tip:sched/urgent] " tip-bot for Stanislaw Gruszka
2013-04-30  9:35 ` [PATCH -tip 4/4] Revert "math64: New div64_u64_rem helper" Stanislaw Gruszka
2013-05-01 10:07   ` [tip:sched/urgent] " tip-bot for Stanislaw Gruszka
2013-04-30 11:11 ` [PATCH -tip 1/4] sched: Avoid cputime scaling overflow Ingo Molnar
2013-04-30 15:14 ` Stanislaw Gruszka [this message]
2013-05-01 10:03   ` [tip:sched/urgent] " tip-bot for Stanislaw Gruszka
2013-05-02 13:10     ` Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130430151441.GC10465@redhat.com \
    --to=sgruszka@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=dave@sr71.net \
    --cc=fweisbec@gmail.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox