aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/vtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/vtime.c')
-rw-r--r--arch/s390/kernel/vtime.c67
1 files changed, 35 insertions, 32 deletions
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index ecf0304e61c1..38ea92ff04f9 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -134,6 +134,8 @@ void vtime_start_cpu(void)
134 /* Account time spent with enabled wait psw loaded as idle time. */ 134 /* Account time spent with enabled wait psw loaded as idle time. */
135 idle_time = S390_lowcore.int_clock - idle->idle_enter; 135 idle_time = S390_lowcore.int_clock - idle->idle_enter;
136 account_idle_time(idle_time); 136 account_idle_time(idle_time);
137 S390_lowcore.steal_timer +=
138 idle->idle_enter - S390_lowcore.last_update_clock;
137 S390_lowcore.last_update_clock = S390_lowcore.int_clock; 139 S390_lowcore.last_update_clock = S390_lowcore.int_clock;
138 140
139 /* Account system time spent going idle. */ 141 /* Account system time spent going idle. */
@@ -425,17 +427,7 @@ void add_virt_timer_periodic(void *new)
425} 427}
426EXPORT_SYMBOL(add_virt_timer_periodic); 428EXPORT_SYMBOL(add_virt_timer_periodic);
427 429
428/* 430int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic)
429 * If we change a pending timer the function must be called on the CPU
430 * where the timer is running on, e.g. by smp_call_function_single()
431 *
432 * The original mod_timer adds the timer if it is not pending. For
433 * compatibility we do the same. The timer will be added on the current
434 * CPU as a oneshot timer.
435 *
436 * returns whether it has modified a pending timer (1) or not (0)
437 */
438int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
439{ 431{
440 struct vtimer_queue *vq; 432 struct vtimer_queue *vq;
441 unsigned long flags; 433 unsigned long flags;
@@ -444,39 +436,35 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
444 BUG_ON(!timer->function); 436 BUG_ON(!timer->function);
445 BUG_ON(!expires || expires > VTIMER_MAX_SLICE); 437 BUG_ON(!expires || expires > VTIMER_MAX_SLICE);
446 438
447 /*
448 * This is a common optimization triggered by the
449 * networking code - if the timer is re-modified
450 * to be the same thing then just return:
451 */
452 if (timer->expires == expires && vtimer_pending(timer)) 439 if (timer->expires == expires && vtimer_pending(timer))
453 return 1; 440 return 1;
454 441
455 cpu = get_cpu(); 442 cpu = get_cpu();
456 vq = &per_cpu(virt_cpu_timer, cpu); 443 vq = &per_cpu(virt_cpu_timer, cpu);
457 444
458 /* check if we run on the right CPU */
459 BUG_ON(timer->cpu != cpu);
460
461 /* disable interrupts before test if timer is pending */ 445 /* disable interrupts before test if timer is pending */
462 spin_lock_irqsave(&vq->lock, flags); 446 spin_lock_irqsave(&vq->lock, flags);
463 447
464 /* if timer isn't pending add it on the current CPU */ 448 /* if timer isn't pending add it on the current CPU */
465 if (!vtimer_pending(timer)) { 449 if (!vtimer_pending(timer)) {
466 spin_unlock_irqrestore(&vq->lock, flags); 450 spin_unlock_irqrestore(&vq->lock, flags);
467 /* we do not activate an interval timer with mod_virt_timer */ 451
468 timer->interval = 0; 452 if (periodic)
453 timer->interval = expires;
454 else
455 timer->interval = 0;
469 timer->expires = expires; 456 timer->expires = expires;
470 timer->cpu = cpu; 457 timer->cpu = cpu;
471 internal_add_vtimer(timer); 458 internal_add_vtimer(timer);
472 return 0; 459 return 0;
473 } 460 }
474 461
462 /* check if we run on the right CPU */
463 BUG_ON(timer->cpu != cpu);
464
475 list_del_init(&timer->entry); 465 list_del_init(&timer->entry);
476 timer->expires = expires; 466 timer->expires = expires;
477 467 if (periodic)
478 /* also change the interval if we have an interval timer */
479 if (timer->interval)
480 timer->interval = expires; 468 timer->interval = expires;
481 469
482 /* the timer can't expire anymore so we can release the lock */ 470 /* the timer can't expire anymore so we can release the lock */
@@ -484,9 +472,32 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
484 internal_add_vtimer(timer); 472 internal_add_vtimer(timer);
485 return 1; 473 return 1;
486} 474}
475
476/*
477 * If we change a pending timer the function must be called on the CPU
478 * where the timer is running on.
479 *
480 * returns whether it has modified a pending timer (1) or not (0)
481 */
482int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
483{
484 return __mod_vtimer(timer, expires, 0);
485}
487EXPORT_SYMBOL(mod_virt_timer); 486EXPORT_SYMBOL(mod_virt_timer);
488 487
489/* 488/*
489 * If we change a pending timer the function must be called on the CPU
490 * where the timer is running on.
491 *
492 * returns whether it has modified a pending timer (1) or not (0)
493 */
494int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires)
495{
496 return __mod_vtimer(timer, expires, 1);
497}
498EXPORT_SYMBOL(mod_virt_timer_periodic);
499
500/*
490 * delete a virtual timer 501 * delete a virtual timer
491 * 502 *
492 * returns whether the deleted timer was pending (1) or not (0) 503 * returns whether the deleted timer was pending (1) or not (0)
@@ -516,16 +527,8 @@ EXPORT_SYMBOL(del_virt_timer);
516 */ 527 */
517void init_cpu_vtimer(void) 528void init_cpu_vtimer(void)
518{ 529{
519 struct thread_info *ti = current_thread_info();
520 struct vtimer_queue *vq; 530 struct vtimer_queue *vq;
521 531
522 S390_lowcore.user_timer = ti->user_timer;
523 S390_lowcore.system_timer = ti->system_timer;
524
525 /* kick the virtual timer */
526 asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock));
527 asm volatile ("STPT %0" : "=m" (S390_lowcore.last_update_timer));
528
529 /* initialize per cpu vtimer structure */ 532 /* initialize per cpu vtimer structure */
530 vq = &__get_cpu_var(virt_cpu_timer); 533 vq = &__get_cpu_var(virt_cpu_timer);
531 INIT_LIST_HEAD(&vq->list); 534 INIT_LIST_HEAD(&vq->list);