[PATCH] hrtimer: switch itimers to hrtimer
switch itimers to a hrtimers-based implementation Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
committed by
Linus Torvalds
parent
df78488de7
commit
2ff678b8da
106
kernel/itimer.c
106
kernel/itimer.c
@@ -12,36 +12,46 @@
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/posix-timers.h>
|
||||
#include <linux/hrtimer.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
static unsigned long it_real_value(struct signal_struct *sig)
|
||||
/**
|
||||
* itimer_get_remtime - get remaining time for the timer
|
||||
*
|
||||
* @timer: the timer to read
|
||||
*
|
||||
* Returns the delta between the expiry time and now, which can be
|
||||
* less than zero or 1usec for an pending expired timer
|
||||
*/
|
||||
static struct timeval itimer_get_remtime(struct hrtimer *timer)
|
||||
{
|
||||
unsigned long val = 0;
|
||||
if (timer_pending(&sig->real_timer)) {
|
||||
val = sig->real_timer.expires - jiffies;
|
||||
ktime_t rem = hrtimer_get_remaining(timer);
|
||||
|
||||
/* look out for negative/zero itimer.. */
|
||||
if ((long) val <= 0)
|
||||
val = 1;
|
||||
}
|
||||
return val;
|
||||
/*
|
||||
* Racy but safe: if the itimer expires after the above
|
||||
* hrtimer_get_remtime() call but before this condition
|
||||
* then we return 0 - which is correct.
|
||||
*/
|
||||
if (hrtimer_active(timer)) {
|
||||
if (rem.tv64 <= 0)
|
||||
rem.tv64 = NSEC_PER_USEC;
|
||||
} else
|
||||
rem.tv64 = 0;
|
||||
|
||||
return ktime_to_timeval(rem);
|
||||
}
|
||||
|
||||
int do_getitimer(int which, struct itimerval *value)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
unsigned long interval, val;
|
||||
cputime_t cinterval, cval;
|
||||
|
||||
switch (which) {
|
||||
case ITIMER_REAL:
|
||||
spin_lock_irq(&tsk->sighand->siglock);
|
||||
interval = tsk->signal->it_real_incr;
|
||||
val = it_real_value(tsk->signal);
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
jiffies_to_timeval(val, &value->it_value);
|
||||
jiffies_to_timeval(interval, &value->it_interval);
|
||||
value->it_value = itimer_get_remtime(&tsk->signal->real_timer);
|
||||
value->it_interval =
|
||||
ktime_to_timeval(tsk->signal->it_real_incr);
|
||||
break;
|
||||
case ITIMER_VIRTUAL:
|
||||
read_lock(&tasklist_lock);
|
||||
@@ -113,59 +123,45 @@ asmlinkage long sys_getitimer(int which, struct itimerval __user *value)
|
||||
}
|
||||
|
||||
|
||||
void it_real_fn(unsigned long __data)
|
||||
/*
|
||||
* The timer is automagically restarted, when interval != 0
|
||||
*/
|
||||
int it_real_fn(void *data)
|
||||
{
|
||||
struct task_struct * p = (struct task_struct *) __data;
|
||||
unsigned long inc = p->signal->it_real_incr;
|
||||
struct task_struct *tsk = (struct task_struct *) data;
|
||||
|
||||
send_group_sig_info(SIGALRM, SEND_SIG_PRIV, p);
|
||||
send_group_sig_info(SIGALRM, SEND_SIG_PRIV, tsk);
|
||||
|
||||
/*
|
||||
* Now restart the timer if necessary. We don't need any locking
|
||||
* here because do_setitimer makes sure we have finished running
|
||||
* before it touches anything.
|
||||
* Note, we KNOW we are (or should be) at a jiffie edge here so
|
||||
* we don't need the +1 stuff. Also, we want to use the prior
|
||||
* expire value so as to not "slip" a jiffie if we are late.
|
||||
* Deal with requesting a time prior to "now" here rather than
|
||||
* in add_timer.
|
||||
*/
|
||||
if (!inc)
|
||||
return;
|
||||
while (time_before_eq(p->signal->real_timer.expires, jiffies))
|
||||
p->signal->real_timer.expires += inc;
|
||||
add_timer(&p->signal->real_timer);
|
||||
if (tsk->signal->it_real_incr.tv64 != 0) {
|
||||
hrtimer_forward(&tsk->signal->real_timer,
|
||||
tsk->signal->it_real_incr);
|
||||
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
unsigned long val, interval, expires;
|
||||
struct hrtimer *timer;
|
||||
ktime_t expires;
|
||||
cputime_t cval, cinterval, nval, ninterval;
|
||||
|
||||
switch (which) {
|
||||
case ITIMER_REAL:
|
||||
again:
|
||||
spin_lock_irq(&tsk->sighand->siglock);
|
||||
interval = tsk->signal->it_real_incr;
|
||||
val = it_real_value(tsk->signal);
|
||||
/* We are sharing ->siglock with it_real_fn() */
|
||||
if (try_to_del_timer_sync(&tsk->signal->real_timer) < 0) {
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
goto again;
|
||||
timer = &tsk->signal->real_timer;
|
||||
hrtimer_cancel(timer);
|
||||
if (ovalue) {
|
||||
ovalue->it_value = itimer_get_remtime(timer);
|
||||
ovalue->it_interval
|
||||
= ktime_to_timeval(tsk->signal->it_real_incr);
|
||||
}
|
||||
tsk->signal->it_real_incr =
|
||||
timeval_to_jiffies(&value->it_interval);
|
||||
expires = timeval_to_jiffies(&value->it_value);
|
||||
if (expires)
|
||||
mod_timer(&tsk->signal->real_timer,
|
||||
jiffies + 1 + expires);
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
if (ovalue) {
|
||||
jiffies_to_timeval(val, &ovalue->it_value);
|
||||
jiffies_to_timeval(interval,
|
||||
&ovalue->it_interval);
|
||||
}
|
||||
timeval_to_ktime(value->it_interval);
|
||||
expires = timeval_to_ktime(value->it_value);
|
||||
if (expires.tv64 != 0)
|
||||
hrtimer_start(timer, expires, HRTIMER_REL);
|
||||
break;
|
||||
case ITIMER_VIRTUAL:
|
||||
nval = timeval_to_cputime(&value->it_value);
|
||||
|
Reference in New Issue
Block a user