diff options
Diffstat (limited to 'arch/powerpc/kernel/time.c')
-rw-r--r-- | arch/powerpc/kernel/time.c | 63 |
1 files changed, 39 insertions, 24 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index e49e93191b69..c9986fd400d8 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -291,13 +291,12 @@ static inline u64 calculate_stolen_time(u64 stop_tb) | |||
291 | * Account time for a transition between system, hard irq | 291 | * Account time for a transition between system, hard irq |
292 | * or soft irq state. | 292 | * or soft irq state. |
293 | */ | 293 | */ |
294 | void account_system_vtime(struct task_struct *tsk) | 294 | static u64 vtime_delta(struct task_struct *tsk, |
295 | u64 *sys_scaled, u64 *stolen) | ||
295 | { | 296 | { |
296 | u64 now, nowscaled, delta, deltascaled; | 297 | u64 now, nowscaled, deltascaled; |
297 | unsigned long flags; | 298 | u64 udelta, delta, user_scaled; |
298 | u64 stolen, udelta, sys_scaled, user_scaled; | ||
299 | 299 | ||
300 | local_irq_save(flags); | ||
301 | now = mftb(); | 300 | now = mftb(); |
302 | nowscaled = read_spurr(now); | 301 | nowscaled = read_spurr(now); |
303 | get_paca()->system_time += now - get_paca()->starttime; | 302 | get_paca()->system_time += now - get_paca()->starttime; |
@@ -305,7 +304,7 @@ void account_system_vtime(struct task_struct *tsk) | |||
305 | deltascaled = nowscaled - get_paca()->startspurr; | 304 | deltascaled = nowscaled - get_paca()->startspurr; |
306 | get_paca()->startspurr = nowscaled; | 305 | get_paca()->startspurr = nowscaled; |
307 | 306 | ||
308 | stolen = calculate_stolen_time(now); | 307 | *stolen = calculate_stolen_time(now); |
309 | 308 | ||
310 | delta = get_paca()->system_time; | 309 | delta = get_paca()->system_time; |
311 | get_paca()->system_time = 0; | 310 | get_paca()->system_time = 0; |
@@ -322,35 +321,45 @@ void account_system_vtime(struct task_struct *tsk) | |||
322 | * the user ticks get saved up in paca->user_time_scaled to be | 321 | * the user ticks get saved up in paca->user_time_scaled to be |
323 | * used by account_process_tick. | 322 | * used by account_process_tick. |
324 | */ | 323 | */ |
325 | sys_scaled = delta; | 324 | *sys_scaled = delta; |
326 | user_scaled = udelta; | 325 | user_scaled = udelta; |
327 | if (deltascaled != delta + udelta) { | 326 | if (deltascaled != delta + udelta) { |
328 | if (udelta) { | 327 | if (udelta) { |
329 | sys_scaled = deltascaled * delta / (delta + udelta); | 328 | *sys_scaled = deltascaled * delta / (delta + udelta); |
330 | user_scaled = deltascaled - sys_scaled; | 329 | user_scaled = deltascaled - *sys_scaled; |
331 | } else { | 330 | } else { |
332 | sys_scaled = deltascaled; | 331 | *sys_scaled = deltascaled; |
333 | } | 332 | } |
334 | } | 333 | } |
335 | get_paca()->user_time_scaled += user_scaled; | 334 | get_paca()->user_time_scaled += user_scaled; |
336 | 335 | ||
337 | if (in_interrupt() || idle_task(smp_processor_id()) != tsk) { | 336 | return delta; |
338 | account_system_time(tsk, 0, delta, sys_scaled); | 337 | } |
339 | if (stolen) | 338 | |
340 | account_steal_time(stolen); | 339 | void vtime_account_system(struct task_struct *tsk) |
341 | } else { | 340 | { |
342 | account_idle_time(delta + stolen); | 341 | u64 delta, sys_scaled, stolen; |
343 | } | 342 | |
344 | local_irq_restore(flags); | 343 | delta = vtime_delta(tsk, &sys_scaled, &stolen); |
344 | account_system_time(tsk, 0, delta, sys_scaled); | ||
345 | if (stolen) | ||
346 | account_steal_time(stolen); | ||
347 | } | ||
348 | |||
349 | void vtime_account_idle(struct task_struct *tsk) | ||
350 | { | ||
351 | u64 delta, sys_scaled, stolen; | ||
352 | |||
353 | delta = vtime_delta(tsk, &sys_scaled, &stolen); | ||
354 | account_idle_time(delta + stolen); | ||
345 | } | 355 | } |
346 | EXPORT_SYMBOL_GPL(account_system_vtime); | ||
347 | 356 | ||
348 | /* | 357 | /* |
349 | * Transfer the user and system times accumulated in the paca | 358 | * Transfer the user and system times accumulated in the paca |
350 | * by the exception entry and exit code to the generic process | 359 | * by the exception entry and exit code to the generic process |
351 | * user and system time records. | 360 | * user and system time records. |
352 | * Must be called with interrupts disabled. | 361 | * Must be called with interrupts disabled. |
353 | * Assumes that account_system_vtime() has been called recently | 362 | * Assumes that vtime_account() has been called recently |
354 | * (i.e. since the last entry from usermode) so that | 363 | * (i.e. since the last entry from usermode) so that |
355 | * get_paca()->user_time_scaled is up to date. | 364 | * get_paca()->user_time_scaled is up to date. |
356 | */ | 365 | */ |
@@ -366,6 +375,12 @@ void account_process_tick(struct task_struct *tsk, int user_tick) | |||
366 | account_user_time(tsk, utime, utimescaled); | 375 | account_user_time(tsk, utime, utimescaled); |
367 | } | 376 | } |
368 | 377 | ||
378 | void vtime_task_switch(struct task_struct *prev) | ||
379 | { | ||
380 | vtime_account(prev); | ||
381 | account_process_tick(prev, 0); | ||
382 | } | ||
383 | |||
369 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ | 384 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ |
370 | #define calc_cputime_factors() | 385 | #define calc_cputime_factors() |
371 | #endif | 386 | #endif |
@@ -493,8 +508,6 @@ void timer_interrupt(struct pt_regs * regs) | |||
493 | */ | 508 | */ |
494 | may_hard_irq_enable(); | 509 | may_hard_irq_enable(); |
495 | 510 | ||
496 | trace_timer_interrupt_entry(regs); | ||
497 | |||
498 | __get_cpu_var(irq_stat).timer_irqs++; | 511 | __get_cpu_var(irq_stat).timer_irqs++; |
499 | 512 | ||
500 | #if defined(CONFIG_PPC32) && defined(CONFIG_PMAC) | 513 | #if defined(CONFIG_PPC32) && defined(CONFIG_PMAC) |
@@ -505,6 +518,8 @@ void timer_interrupt(struct pt_regs * regs) | |||
505 | old_regs = set_irq_regs(regs); | 518 | old_regs = set_irq_regs(regs); |
506 | irq_enter(); | 519 | irq_enter(); |
507 | 520 | ||
521 | trace_timer_interrupt_entry(regs); | ||
522 | |||
508 | if (test_irq_work_pending()) { | 523 | if (test_irq_work_pending()) { |
509 | clear_irq_work_pending(); | 524 | clear_irq_work_pending(); |
510 | irq_work_run(); | 525 | irq_work_run(); |
@@ -529,10 +544,10 @@ void timer_interrupt(struct pt_regs * regs) | |||
529 | } | 544 | } |
530 | #endif | 545 | #endif |
531 | 546 | ||
547 | trace_timer_interrupt_exit(regs); | ||
548 | |||
532 | irq_exit(); | 549 | irq_exit(); |
533 | set_irq_regs(old_regs); | 550 | set_irq_regs(old_regs); |
534 | |||
535 | trace_timer_interrupt_exit(regs); | ||
536 | } | 551 | } |
537 | 552 | ||
538 | /* | 553 | /* |