Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/time: Only set CONFIG_ARCH_HAS_SCALED_CPUTIME on PPC64

scaled cputime is only meaningfull when the processor has
SPURR and/or PURR, which means only on PPC64.

Removing it on PPC32 significantly reduces the size of
vtime_account_system() and vtime_account_idle() on an 8xx:

Before:
00000000 l F .text 000000a8 vtime_delta
00000280 g F .text 0000010c vtime_account_system
0000038c g F .text 00000048 vtime_account_idle

After:
(vtime_delta gets inlined inside the two functions)
000001d8 g F .text 000000a0 vtime_account_system
00000278 g F .text 00000038 vtime_account_idle

In terms of performance, we also get approximatly 7% improvement on
task switch. The following small benchmark app is run with perf stat:

void *thread(void *arg)
{
int i;

for (i = 0; i < atoi((char*)arg); i++)
pthread_yield();
}

int main(int argc, char **argv)
{
pthread_t th1, th2;

pthread_create(&th1, NULL, thread, argv[1]);
pthread_create(&th2, NULL, thread, argv[1]);
pthread_join(th1, NULL);
pthread_join(th2, NULL);

return 0;
}

Before the patch:

Performance counter stats for 'chrt -f 98 ./sched 100000' (50 runs):

8228.476465 task-clock (msec) # 0.954 CPUs utilized ( +- 0.23% )
200004 context-switches # 0.024 M/sec ( +- 0.00% )

After the patch:

Performance counter stats for 'chrt -f 98 ./sched 100000' (50 runs):

7649.070444 task-clock (msec) # 0.955 CPUs utilized ( +- 0.27% )
200004 context-switches # 0.026 M/sec ( +- 0.00% )

Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Christophe Leroy and committed by
Michael Ellerman
abcff86d b38a181c

+19 -4
+1 -1
arch/powerpc/Kconfig
··· 137 137 select ARCH_HAS_PMEM_API if PPC64 138 138 select ARCH_HAS_PTE_SPECIAL 139 139 select ARCH_HAS_MEMBARRIER_CALLBACKS 140 - select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE 140 + select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC64 141 141 select ARCH_HAS_SG_CHAIN 142 142 select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !RELOCATABLE && !HIBERNATION) 143 143 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
+4
arch/powerpc/include/asm/accounting.h
··· 15 15 /* Accumulated cputime values to flush on ticks*/ 16 16 unsigned long utime; 17 17 unsigned long stime; 18 + #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 18 19 unsigned long utime_scaled; 19 20 unsigned long stime_scaled; 21 + #endif 20 22 unsigned long gtime; 21 23 unsigned long hardirq_time; 22 24 unsigned long softirq_time; ··· 27 25 /* Internal counters */ 28 26 unsigned long starttime; /* TB value snapshot */ 29 27 unsigned long starttime_user; /* TB value on exit to usermode */ 28 + #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 30 29 unsigned long startspurr; /* SPURR value snapshot */ 31 30 unsigned long utime_sspurr; /* ->user_time when ->startspurr set */ 31 + #endif 32 32 }; 33 33 34 34 #endif
-1
arch/powerpc/include/asm/cputime.h
··· 61 61 struct cpu_accounting_data *acct0 = get_accounting(prev); 62 62 63 63 acct->starttime = acct0->starttime; 64 - acct->startspurr = acct0->startspurr; 65 64 } 66 65 #endif 67 66
+10 -2
arch/powerpc/kernel/time.c
··· 176 176 * Read the SPURR on systems that have it, otherwise the PURR, 177 177 * or if that doesn't exist return the timebase value passed in. 178 178 */ 179 - static unsigned long read_spurr(unsigned long tb) 179 + static inline unsigned long read_spurr(unsigned long tb) 180 180 { 181 181 if (cpu_has_feature(CPU_FTR_SPURR)) 182 182 return mfspr(SPRN_SPURR); ··· 285 285 static unsigned long vtime_delta_scaled(struct cpu_accounting_data *acct, 286 286 unsigned long now, unsigned long stime) 287 287 { 288 - unsigned long stime_scaled; 288 + unsigned long stime_scaled = 0; 289 + #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 289 290 unsigned long nowscaled, deltascaled; 290 291 unsigned long utime, utime_scaled; 291 292 ··· 317 316 } 318 317 } 319 318 acct->utime_scaled += utime_scaled; 319 + #endif 320 320 321 321 return stime_scaled; 322 322 } ··· 354 352 355 353 if ((tsk->flags & PF_VCPU) && !irq_count()) { 356 354 acct->gtime += stime; 355 + #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 357 356 acct->utime_scaled += stime_scaled; 357 + #endif 358 358 } else { 359 359 if (hardirq_count()) 360 360 acct->hardirq_time += stime; ··· 365 361 else 366 362 acct->stime += stime; 367 363 364 + #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 368 365 acct->stime_scaled += stime_scaled; 366 + #endif 369 367 } 370 368 } 371 369 EXPORT_SYMBOL_GPL(vtime_account_system); ··· 384 378 static void vtime_flush_scaled(struct task_struct *tsk, 385 379 struct cpu_accounting_data *acct) 386 380 { 381 + #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 387 382 if (acct->utime_scaled) 388 383 tsk->utimescaled += cputime_to_nsecs(acct->utime_scaled); 389 384 if (acct->stime_scaled) ··· 393 386 acct->utime_scaled = 0; 394 387 acct->utime_sspurr = 0; 395 388 acct->stime_scaled = 0; 389 + #endif 396 390 } 397 391 398 392 /*
+4
arch/powerpc/xmon/xmon.c
··· 2454 2454 2455 2455 DUMP(p, accounting.utime, "%#-*lx"); 2456 2456 DUMP(p, accounting.stime, "%#-*lx"); 2457 + #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 2457 2458 DUMP(p, accounting.utime_scaled, "%#-*lx"); 2459 + #endif 2458 2460 DUMP(p, accounting.starttime, "%#-*lx"); 2459 2461 DUMP(p, accounting.starttime_user, "%#-*lx"); 2462 + #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 2460 2463 DUMP(p, accounting.startspurr, "%#-*lx"); 2461 2464 DUMP(p, accounting.utime_sspurr, "%#-*lx"); 2465 + #endif 2462 2466 DUMP(p, accounting.steal_time, "%#-*lx"); 2463 2467 #undef DUMP 2464 2468