diff options
author | Jan Glauber <jang@linux.vnet.ibm.com> | 2009-04-14 17:36:20 +0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-04-14 17:37:23 +0400 |
commit | b6ecfa9273e27b5c7ba04655eb44f78bf4db5b64 (patch) | |
tree | 559f0b436efd410625d8a7a502ca3a1503e3a1a2 /arch | |
parent | 0436230148c55e3afbe5c57775a1fb44ba4834ac (diff) | |
download | linux-b6ecfa9273e27b5c7ba04655eb44f78bf4db5b64.tar.xz |
[S390] extend virtual timer interface by mod_virt_timer_periodic
In case mod_virt_timer is used to add a non pending timer the timer
is always added as a one-shot timer. If mod_virt_timer is used for
periodic timers they may therfore be degraded to one-shot timers.
Add mod_virt_timer_periodic to the interface to allow safe re-programming
of the interval value.
Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/include/asm/timer.h | 1 | ||||
-rw-r--r-- | arch/s390/kernel/vtime.c | 57 |
2 files changed, 34 insertions, 24 deletions
diff --git a/arch/s390/include/asm/timer.h b/arch/s390/include/asm/timer.h index e4bcab739c19..814243cafdfe 100644 --- a/arch/s390/include/asm/timer.h +++ b/arch/s390/include/asm/timer.h @@ -41,6 +41,7 @@ extern void init_virt_timer(struct vtimer_list *timer); extern void add_virt_timer(void *new); extern void add_virt_timer_periodic(void *new); extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires); +extern int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires); extern int del_virt_timer(struct vtimer_list *timer); extern void init_cpu_vtimer(void); diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index ecf0304e61c1..694b44374a2b 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -425,17 +425,7 @@ void add_virt_timer_periodic(void *new) } EXPORT_SYMBOL(add_virt_timer_periodic); -/* - * If we change a pending timer the function must be called on the CPU - * where the timer is running on, e.g. by smp_call_function_single() - * - * The original mod_timer adds the timer if it is not pending. For - * compatibility we do the same. The timer will be added on the current - * CPU as a oneshot timer. - * - * returns whether it has modified a pending timer (1) or not (0) - */ -int mod_virt_timer(struct vtimer_list *timer, __u64 expires) +int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic) { struct vtimer_queue *vq; unsigned long flags; @@ -444,39 +434,35 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires) BUG_ON(!timer->function); BUG_ON(!expires || expires > VTIMER_MAX_SLICE); - /* - * This is a common optimization triggered by the - * networking code - if the timer is re-modified - * to be the same thing then just return: - */ if (timer->expires == expires && vtimer_pending(timer)) return 1; cpu = get_cpu(); vq = &per_cpu(virt_cpu_timer, cpu); - /* check if we run on the right CPU */ - BUG_ON(timer->cpu != cpu); - /* disable interrupts before test if timer is pending */ spin_lock_irqsave(&vq->lock, flags); /* if timer isn't pending add it on the current CPU */ if (!vtimer_pending(timer)) { spin_unlock_irqrestore(&vq->lock, flags); - /* we do not activate an interval timer with mod_virt_timer */ - timer->interval = 0; + + if (periodic) + timer->interval = expires; + else + timer->interval = 0; timer->expires = expires; timer->cpu = cpu; internal_add_vtimer(timer); return 0; } + /* check if we run on the right CPU */ + BUG_ON(timer->cpu != cpu); + list_del_init(&timer->entry); timer->expires = expires; - - /* also change the interval if we have an interval timer */ - if (timer->interval) + if (periodic) timer->interval = expires; /* the timer can't expire anymore so we can release the lock */ @@ -484,9 +470,32 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires) internal_add_vtimer(timer); return 1; } + +/* + * If we change a pending timer the function must be called on the CPU + * where the timer is running on. + * + * returns whether it has modified a pending timer (1) or not (0) + */ +int mod_virt_timer(struct vtimer_list *timer, __u64 expires) +{ + return __mod_vtimer(timer, expires, 0); +} EXPORT_SYMBOL(mod_virt_timer); /* + * If we change a pending timer the function must be called on the CPU + * where the timer is running on. + * + * returns whether it has modified a pending timer (1) or not (0) + */ +int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires) +{ + return __mod_vtimer(timer, expires, 1); +} +EXPORT_SYMBOL(mod_virt_timer_periodic); + +/* * delete a virtual timer * * returns whether the deleted timer was pending (1) or not (0) |