Commit 2ff678b8da6478d861c1b0ecb3ac14575760e906

Authored by Thomas Gleixner
Committed by Linus Torvalds
1 parent df78488de7

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

Showing 7 changed files with 65 additions and 68 deletions Side-by-side Diff

... ... @@ -632,10 +632,10 @@
632 632 * synchronize with any firing (by calling del_timer_sync)
633 633 * before we can safely let the old group leader die.
634 634 */
635   - sig->real_timer.data = (unsigned long)current;
  635 + sig->real_timer.data = current;
636 636 spin_unlock_irq(lock);
637   - if (del_timer_sync(&sig->real_timer))
638   - add_timer(&sig->real_timer);
  637 + if (hrtimer_cancel(&sig->real_timer))
  638 + hrtimer_restart(&sig->real_timer);
639 639 spin_lock_irq(lock);
640 640 }
641 641 while (atomic_read(&sig->count) > count) {
... ... @@ -330,7 +330,7 @@
330 330 unsigned long min_flt = 0, maj_flt = 0;
331 331 cputime_t cutime, cstime, utime, stime;
332 332 unsigned long rsslim = 0;
333   - unsigned long it_real_value = 0;
  333 + DEFINE_KTIME(it_real_value);
334 334 struct task_struct *t;
335 335 char tcomm[sizeof(task->comm)];
336 336  
... ... @@ -386,7 +386,7 @@
386 386 utime = cputime_add(utime, task->signal->utime);
387 387 stime = cputime_add(stime, task->signal->stime);
388 388 }
389   - it_real_value = task->signal->it_real_value;
  389 + it_real_value = task->signal->real_timer.expires;
390 390 }
391 391 ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
392 392 read_unlock(&tasklist_lock);
... ... @@ -435,7 +435,7 @@
435 435 priority,
436 436 nice,
437 437 num_threads,
438   - jiffies_to_clock_t(it_real_value),
  438 + (long) ktime_to_clock_t(it_real_value),
439 439 start_time,
440 440 vsize,
441 441 mm ? get_mm_rss(mm) : 0,
include/linux/sched.h
... ... @@ -105,6 +105,7 @@
105 105 #include <linux/param.h>
106 106 #include <linux/resource.h>
107 107 #include <linux/timer.h>
  108 +#include <linux/hrtimer.h>
108 109  
109 110 #include <asm/processor.h>
110 111  
... ... @@ -398,8 +399,8 @@
398 399 struct list_head posix_timers;
399 400  
400 401 /* ITIMER_REAL timer for the process */
401   - struct timer_list real_timer;
402   - unsigned long it_real_value, it_real_incr;
  402 + struct hrtimer real_timer;
  403 + ktime_t it_real_incr;
403 404  
404 405 /* ITIMER_PROF and ITIMER_VIRTUAL timers for the process */
405 406 cputime_t it_prof_expires, it_virt_expires;
include/linux/timer.h
... ... @@ -96,7 +96,7 @@
96 96  
97 97 extern void init_timers(void);
98 98 extern void run_local_timers(void);
99   -extern void it_real_fn(unsigned long);
  99 +extern int it_real_fn(void *);
100 100  
101 101 #endif
... ... @@ -842,7 +842,7 @@
842 842 }
843 843 group_dead = atomic_dec_and_test(&tsk->signal->live);
844 844 if (group_dead) {
845   - del_timer_sync(&tsk->signal->real_timer);
  845 + hrtimer_cancel(&tsk->signal->real_timer);
846 846 exit_itimers(tsk->signal);
847 847 acct_process(code);
848 848 }
... ... @@ -801,10 +801,10 @@
801 801 init_sigpending(&sig->shared_pending);
802 802 INIT_LIST_HEAD(&sig->posix_timers);
803 803  
804   - sig->it_real_value = sig->it_real_incr = 0;
  804 + hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC);
  805 + sig->it_real_incr.tv64 = 0;
805 806 sig->real_timer.function = it_real_fn;
806   - sig->real_timer.data = (unsigned long) tsk;
807   - init_timer(&sig->real_timer);
  807 + sig->real_timer.data = tsk;
808 808  
809 809 sig->it_virt_expires = cputime_zero;
810 810 sig->it_virt_incr = cputime_zero;
... ... @@ -12,36 +12,46 @@
12 12 #include <linux/syscalls.h>
13 13 #include <linux/time.h>
14 14 #include <linux/posix-timers.h>
  15 +#include <linux/hrtimer.h>
15 16  
16 17 #include <asm/uaccess.h>
17 18  
18   -static unsigned long it_real_value(struct signal_struct *sig)
  19 +/**
  20 + * itimer_get_remtime - get remaining time for the timer
  21 + *
  22 + * @timer: the timer to read
  23 + *
  24 + * Returns the delta between the expiry time and now, which can be
  25 + * less than zero or 1usec for an pending expired timer
  26 + */
  27 +static struct timeval itimer_get_remtime(struct hrtimer *timer)
19 28 {
20   - unsigned long val = 0;
21   - if (timer_pending(&sig->real_timer)) {
22   - val = sig->real_timer.expires - jiffies;
  29 + ktime_t rem = hrtimer_get_remaining(timer);
23 30  
24   - /* look out for negative/zero itimer.. */
25   - if ((long) val <= 0)
26   - val = 1;
27   - }
28   - return val;
  31 + /*
  32 + * Racy but safe: if the itimer expires after the above
  33 + * hrtimer_get_remtime() call but before this condition
  34 + * then we return 0 - which is correct.
  35 + */
  36 + if (hrtimer_active(timer)) {
  37 + if (rem.tv64 <= 0)
  38 + rem.tv64 = NSEC_PER_USEC;
  39 + } else
  40 + rem.tv64 = 0;
  41 +
  42 + return ktime_to_timeval(rem);
29 43 }
30 44  
31 45 int do_getitimer(int which, struct itimerval *value)
32 46 {
33 47 struct task_struct *tsk = current;
34   - unsigned long interval, val;
35 48 cputime_t cinterval, cval;
36 49  
37 50 switch (which) {
38 51 case ITIMER_REAL:
39   - spin_lock_irq(&tsk->sighand->siglock);
40   - interval = tsk->signal->it_real_incr;
41   - val = it_real_value(tsk->signal);
42   - spin_unlock_irq(&tsk->sighand->siglock);
43   - jiffies_to_timeval(val, &value->it_value);
44   - jiffies_to_timeval(interval, &value->it_interval);
  52 + value->it_value = itimer_get_remtime(&tsk->signal->real_timer);
  53 + value->it_interval =
  54 + ktime_to_timeval(tsk->signal->it_real_incr);
45 55 break;
46 56 case ITIMER_VIRTUAL:
47 57 read_lock(&tasklist_lock);
48 58  
49 59  
50 60  
51 61  
52 62  
53 63  
54 64  
... ... @@ -113,59 +123,45 @@
113 123 }
114 124  
115 125  
116   -void it_real_fn(unsigned long __data)
  126 +/*
  127 + * The timer is automagically restarted, when interval != 0
  128 + */
  129 +int it_real_fn(void *data)
117 130 {
118   - struct task_struct * p = (struct task_struct *) __data;
119   - unsigned long inc = p->signal->it_real_incr;
  131 + struct task_struct *tsk = (struct task_struct *) data;
120 132  
121   - send_group_sig_info(SIGALRM, SEND_SIG_PRIV, p);
  133 + send_group_sig_info(SIGALRM, SEND_SIG_PRIV, tsk);
122 134  
123   - /*
124   - * Now restart the timer if necessary. We don't need any locking
125   - * here because do_setitimer makes sure we have finished running
126   - * before it touches anything.
127   - * Note, we KNOW we are (or should be) at a jiffie edge here so
128   - * we don't need the +1 stuff. Also, we want to use the prior
129   - * expire value so as to not "slip" a jiffie if we are late.
130   - * Deal with requesting a time prior to "now" here rather than
131   - * in add_timer.
132   - */
133   - if (!inc)
134   - return;
135   - while (time_before_eq(p->signal->real_timer.expires, jiffies))
136   - p->signal->real_timer.expires += inc;
137   - add_timer(&p->signal->real_timer);
  135 + if (tsk->signal->it_real_incr.tv64 != 0) {
  136 + hrtimer_forward(&tsk->signal->real_timer,
  137 + tsk->signal->it_real_incr);
  138 +
  139 + return HRTIMER_RESTART;
  140 + }
  141 + return HRTIMER_NORESTART;
138 142 }
139 143  
140 144 int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
141 145 {
142 146 struct task_struct *tsk = current;
143   - unsigned long val, interval, expires;
  147 + struct hrtimer *timer;
  148 + ktime_t expires;
144 149 cputime_t cval, cinterval, nval, ninterval;
145 150  
146 151 switch (which) {
147 152 case ITIMER_REAL:
148   -again:
149   - spin_lock_irq(&tsk->sighand->siglock);
150   - interval = tsk->signal->it_real_incr;
151   - val = it_real_value(tsk->signal);
152   - /* We are sharing ->siglock with it_real_fn() */
153   - if (try_to_del_timer_sync(&tsk->signal->real_timer) < 0) {
154   - spin_unlock_irq(&tsk->sighand->siglock);
155   - goto again;
156   - }
157   - tsk->signal->it_real_incr =
158   - timeval_to_jiffies(&value->it_interval);
159   - expires = timeval_to_jiffies(&value->it_value);
160   - if (expires)
161   - mod_timer(&tsk->signal->real_timer,
162   - jiffies + 1 + expires);
163   - spin_unlock_irq(&tsk->sighand->siglock);
  153 + timer = &tsk->signal->real_timer;
  154 + hrtimer_cancel(timer);
164 155 if (ovalue) {
165   - jiffies_to_timeval(val, &ovalue->it_value);
166   - jiffies_to_timeval(interval,
167   - &ovalue->it_interval);
  156 + ovalue->it_value = itimer_get_remtime(timer);
  157 + ovalue->it_interval
  158 + = ktime_to_timeval(tsk->signal->it_real_incr);
168 159 }
  160 + tsk->signal->it_real_incr =
  161 + timeval_to_ktime(value->it_interval);
  162 + expires = timeval_to_ktime(value->it_value);
  163 + if (expires.tv64 != 0)
  164 + hrtimer_start(timer, expires, HRTIMER_REL);
169 165 break;
170 166 case ITIMER_VIRTUAL:
171 167 nval = timeval_to_cputime(&value->it_value);