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

[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>

authored by

Jan Glauber and committed by
Martin Schwidefsky
b6ecfa92 04362301

+34 -24
+1
arch/s390/include/asm/timer.h
··· 41 41 extern void add_virt_timer(void *new); 42 42 extern void add_virt_timer_periodic(void *new); 43 43 extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires); 44 + extern int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires); 44 45 extern int del_virt_timer(struct vtimer_list *timer); 45 46 46 47 extern void init_cpu_vtimer(void);
+33 -24
arch/s390/kernel/vtime.c
··· 425 425 } 426 426 EXPORT_SYMBOL(add_virt_timer_periodic); 427 427 428 - /* 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 - */ 438 - int mod_virt_timer(struct vtimer_list *timer, __u64 expires) 428 + int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic) 439 429 { 440 430 struct vtimer_queue *vq; 441 431 unsigned long flags; ··· 434 444 BUG_ON(!timer->function); 435 445 BUG_ON(!expires || expires > VTIMER_MAX_SLICE); 436 446 437 - /* 438 - * This is a common optimization triggered by the 439 - * networking code - if the timer is re-modified 440 - * to be the same thing then just return: 441 - */ 442 447 if (timer->expires == expires && vtimer_pending(timer)) 443 448 return 1; 444 449 445 450 cpu = get_cpu(); 446 451 vq = &per_cpu(virt_cpu_timer, cpu); 447 - 448 - /* check if we run on the right CPU */ 449 - BUG_ON(timer->cpu != cpu); 450 452 451 453 /* disable interrupts before test if timer is pending */ 452 454 spin_lock_irqsave(&vq->lock, flags); ··· 446 464 /* if timer isn't pending add it on the current CPU */ 447 465 if (!vtimer_pending(timer)) { 448 466 spin_unlock_irqrestore(&vq->lock, flags); 449 - /* we do not activate an interval timer with mod_virt_timer */ 450 - timer->interval = 0; 467 + 468 + if (periodic) 469 + timer->interval = expires; 470 + else 471 + timer->interval = 0; 451 472 timer->expires = expires; 452 473 timer->cpu = cpu; 453 474 internal_add_vtimer(timer); 454 475 return 0; 455 476 } 456 477 478 + /* check if we run on the right CPU */ 479 + BUG_ON(timer->cpu != cpu); 480 + 457 481 list_del_init(&timer->entry); 458 482 timer->expires = expires; 459 - 460 - /* also change the interval if we have an interval timer */ 461 - if (timer->interval) 483 + if (periodic) 462 484 timer->interval = expires; 463 485 464 486 /* the timer can't expire anymore so we can release the lock */ ··· 470 484 internal_add_vtimer(timer); 471 485 return 1; 472 486 } 487 + 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 + */ 494 + int mod_virt_timer(struct vtimer_list *timer, __u64 expires) 495 + { 496 + return __mod_vtimer(timer, expires, 0); 497 + } 473 498 EXPORT_SYMBOL(mod_virt_timer); 499 + 500 + /* 501 + * If we change a pending timer the function must be called on the CPU 502 + * where the timer is running on. 503 + * 504 + * returns whether it has modified a pending timer (1) or not (0) 505 + */ 506 + int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires) 507 + { 508 + return __mod_vtimer(timer, expires, 1); 509 + } 510 + EXPORT_SYMBOL(mod_virt_timer_periodic); 474 511 475 512 /* 476 513 * delete a virtual timer