@@ -506,34 +506,47 @@ void account_idle_ticks(unsigned long ticks)
506
506
}
507
507
508
508
/*
509
- * Perform (stime * rtime) / total with reduced chances
510
- * of multiplication overflows by using smaller factors
511
- * like quotient and remainders of divisions between
512
- * rtime and total.
509
+ * Perform (stime * rtime) / total, but avoid multiplication overflow by
510
+ * loosing precision when the numbers are big.
513
511
*/
514
512
static cputime_t scale_stime (u64 stime , u64 rtime , u64 total )
515
513
{
516
- u64 rem , res , scaled ;
514
+ u64 scaled ;
517
515
518
- if (rtime >= total ) {
519
- /*
520
- * Scale up to rtime / total then add
521
- * the remainder scaled to stime / total.
522
- */
523
- res = div64_u64_rem (rtime , total , & rem );
524
- scaled = stime * res ;
525
- scaled += div64_u64 (stime * rem , total );
526
- } else {
527
- /*
528
- * Same in reverse: scale down to total / rtime
529
- * then substract that result scaled to
530
- * to the remaining part.
531
- */
532
- res = div64_u64_rem (total , rtime , & rem );
533
- scaled = div64_u64 (stime , res );
534
- scaled -= div64_u64 (scaled * rem , total );
516
+ for (;;) {
517
+ /* Make sure "rtime" is the bigger of stime/rtime */
518
+ if (stime > rtime ) {
519
+ u64 tmp = rtime ; rtime = stime ; stime = tmp ;
520
+ }
521
+
522
+ /* Make sure 'total' fits in 32 bits */
523
+ if (total >> 32 )
524
+ goto drop_precision ;
525
+
526
+ /* Does rtime (and thus stime) fit in 32 bits? */
527
+ if (!(rtime >> 32 ))
528
+ break ;
529
+
530
+ /* Can we just balance rtime/stime rather than dropping bits? */
531
+ if (stime >> 31 )
532
+ goto drop_precision ;
533
+
534
+ /* We can grow stime and shrink rtime and try to make them both fit */
535
+ stime <<= 1 ;
536
+ rtime >>= 1 ;
537
+ continue ;
538
+
539
+ drop_precision :
540
+ /* We drop from rtime, it has more bits than stime */
541
+ rtime >>= 1 ;
542
+ total >>= 1 ;
535
543
}
536
544
545
+ /*
546
+ * Make sure gcc understands that this is a 32x32->64 multiply,
547
+ * followed by a 64/32->64 divide.
548
+ */
549
+ scaled = div_u64 ((u64 ) (u32 ) stime * (u64 ) (u32 ) rtime , (u32 )total );
537
550
return (__force cputime_t ) scaled ;
538
551
}
539
552
@@ -545,7 +558,7 @@ static void cputime_adjust(struct task_cputime *curr,
545
558
struct cputime * prev ,
546
559
cputime_t * ut , cputime_t * st )
547
560
{
548
- cputime_t rtime , stime , total ;
561
+ cputime_t rtime , stime , utime , total ;
549
562
550
563
if (vtime_accounting_enabled ()) {
551
564
* ut = curr -> utime ;
@@ -568,13 +581,21 @@ static void cputime_adjust(struct task_cputime *curr,
568
581
*/
569
582
rtime = nsecs_to_cputime (curr -> sum_exec_runtime );
570
583
571
- if (!rtime ) {
572
- stime = 0 ;
573
- } else if (!total ) {
574
- stime = rtime ;
575
- } else {
584
+ /*
585
+ * Update userspace visible utime/stime values only if actual execution
586
+ * time is bigger than already exported. Note that can happen, that we
587
+ * provided bigger values due to scaling inaccuracy on big numbers.
588
+ */
589
+ if (prev -> stime + prev -> utime >= rtime )
590
+ goto out ;
591
+
592
+ if (total ) {
576
593
stime = scale_stime ((__force u64 )stime ,
577
594
(__force u64 )rtime , (__force u64 )total );
595
+ utime = rtime - stime ;
596
+ } else {
597
+ stime = rtime ;
598
+ utime = 0 ;
578
599
}
579
600
580
601
/*
@@ -583,8 +604,9 @@ static void cputime_adjust(struct task_cputime *curr,
583
604
* Let's enforce monotonicity.
584
605
*/
585
606
prev -> stime = max (prev -> stime , stime );
586
- prev -> utime = max (prev -> utime , rtime - prev -> stime );
607
+ prev -> utime = max (prev -> utime , utime );
587
608
609
+ out :
588
610
* ut = prev -> utime ;
589
611
* st = prev -> stime ;
590
612
}
0 commit comments