aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/exec.c6
-rw-r--r--fs/proc/array.c6
-rw-r--r--include/linux/sched.h5
-rw-r--r--include/linux/timer.h2
-rw-r--r--kernel/exit.c2
-rw-r--r--kernel/fork.c6
-rw-r--r--kernel/itimer.c106
7 files changed, 65 insertions, 68 deletions
diff --git a/fs/exec.c b/fs/exec.c
index fd02ea4a81e9..b5bcf1aae0ab 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -632,10 +632,10 @@ static inline int de_thread(struct task_struct *tsk)
632 * synchronize with any firing (by calling del_timer_sync) 632 * synchronize with any firing (by calling del_timer_sync)
633 * before we can safely let the old group leader die. 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 spin_unlock_irq(lock); 636 spin_unlock_irq(lock);
637 if (del_timer_sync(&sig->real_timer)) 637 if (hrtimer_cancel(&sig->real_timer))
638 add_timer(&sig->real_timer); 638 hrtimer_restart(&sig->real_timer);
639 spin_lock_irq(lock); 639 spin_lock_irq(lock);
640 } 640 }
641 while (atomic_read(&sig->count) > count) { 641 while (atomic_read(&sig->count) > count) {
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 5e9251f65317..7eb1bd7f800c 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -330,7 +330,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
330 unsigned long min_flt = 0, maj_flt = 0; 330 unsigned long min_flt = 0, maj_flt = 0;
331 cputime_t cutime, cstime, utime, stime; 331 cputime_t cutime, cstime, utime, stime;
332 unsigned long rsslim = 0; 332 unsigned long rsslim = 0;
333 unsigned long it_real_value = 0; 333 DEFINE_KTIME(it_real_value);
334 struct task_struct *t; 334 struct task_struct *t;
335 char tcomm[sizeof(task->comm)]; 335 char tcomm[sizeof(task->comm)];
336 336
@@ -386,7 +386,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
386 utime = cputime_add(utime, task->signal->utime); 386 utime = cputime_add(utime, task->signal->utime);
387 stime = cputime_add(stime, task->signal->stime); 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 ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0; 391 ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
392 read_unlock(&tasklist_lock); 392 read_unlock(&tasklist_lock);
@@ -435,7 +435,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
435 priority, 435 priority,
436 nice, 436 nice,
437 num_threads, 437 num_threads,
438 jiffies_to_clock_t(it_real_value), 438 (long) ktime_to_clock_t(it_real_value),
439 start_time, 439 start_time,
440 vsize, 440 vsize,
441 mm ? get_mm_rss(mm) : 0, 441 mm ? get_mm_rss(mm) : 0,
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 85b53f87c703..ee4677ad204e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -105,6 +105,7 @@ extern unsigned long nr_iowait(void);
105#include <linux/param.h> 105#include <linux/param.h>
106#include <linux/resource.h> 106#include <linux/resource.h>
107#include <linux/timer.h> 107#include <linux/timer.h>
108#include <linux/hrtimer.h>
108 109
109#include <asm/processor.h> 110#include <asm/processor.h>
110 111
@@ -398,8 +399,8 @@ struct signal_struct {
398 struct list_head posix_timers; 399 struct list_head posix_timers;
399 400
400 /* ITIMER_REAL timer for the process */ 401 /* ITIMER_REAL timer for the process */
401 struct timer_list real_timer; 402 struct hrtimer real_timer;
402 unsigned long it_real_value, it_real_incr; 403 ktime_t it_real_incr;
403 404
404 /* ITIMER_PROF and ITIMER_VIRTUAL timers for the process */ 405 /* ITIMER_PROF and ITIMER_VIRTUAL timers for the process */
405 cputime_t it_prof_expires, it_virt_expires; 406 cputime_t it_prof_expires, it_virt_expires;
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 72f3a7781106..9b9877fd2505 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -96,6 +96,6 @@ static inline void add_timer(struct timer_list *timer)
96 96
97extern void init_timers(void); 97extern void init_timers(void);
98extern void run_local_timers(void); 98extern void run_local_timers(void);
99extern void it_real_fn(unsigned long); 99extern int it_real_fn(void *);
100 100
101#endif 101#endif
diff --git a/kernel/exit.c b/kernel/exit.c
index 309a46fa16f8..e75a51f33768 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -842,7 +842,7 @@ fastcall NORET_TYPE void do_exit(long code)
842 } 842 }
843 group_dead = atomic_dec_and_test(&tsk->signal->live); 843 group_dead = atomic_dec_and_test(&tsk->signal->live);
844 if (group_dead) { 844 if (group_dead) {
845 del_timer_sync(&tsk->signal->real_timer); 845 hrtimer_cancel(&tsk->signal->real_timer);
846 exit_itimers(tsk->signal); 846 exit_itimers(tsk->signal);
847 acct_process(code); 847 acct_process(code);
848 } 848 }
diff --git a/kernel/fork.c b/kernel/fork.c
index b18d64554feb..3bdcab49998d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -801,10 +801,10 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
801 init_sigpending(&sig->shared_pending); 801 init_sigpending(&sig->shared_pending);
802 INIT_LIST_HEAD(&sig->posix_timers); 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 sig->real_timer.function = it_real_fn; 806 sig->real_timer.function = it_real_fn;
806 sig->real_timer.data = (unsigned long) tsk; 807 sig->real_timer.data = tsk;
807 init_timer(&sig->real_timer);
808 808
809 sig->it_virt_expires = cputime_zero; 809 sig->it_virt_expires = cputime_zero;
810 sig->it_virt_incr = cputime_zero; 810 sig->it_virt_incr = cputime_zero;
diff --git a/kernel/itimer.c b/kernel/itimer.c
index 7c1b25e25e47..c2c05c4ff28d 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -12,36 +12,46 @@
12#include <linux/syscalls.h> 12#include <linux/syscalls.h>
13#include <linux/time.h> 13#include <linux/time.h>
14#include <linux/posix-timers.h> 14#include <linux/posix-timers.h>
15#include <linux/hrtimer.h>
15 16
16#include <asm/uaccess.h> 17#include <asm/uaccess.h>
17 18
18static 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 */
27static struct timeval itimer_get_remtime(struct hrtimer *timer)
19{ 28{
20 unsigned long val = 0; 29 ktime_t rem = hrtimer_get_remaining(timer);
21 if (timer_pending(&sig->real_timer)) {
22 val = sig->real_timer.expires - jiffies;
23 30
24 /* look out for negative/zero itimer.. */ 31 /*
25 if ((long) val <= 0) 32 * Racy but safe: if the itimer expires after the above
26 val = 1; 33 * hrtimer_get_remtime() call but before this condition
27 } 34 * then we return 0 - which is correct.
28 return val; 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
31int do_getitimer(int which, struct itimerval *value) 45int do_getitimer(int which, struct itimerval *value)
32{ 46{
33 struct task_struct *tsk = current; 47 struct task_struct *tsk = current;
34 unsigned long interval, val;
35 cputime_t cinterval, cval; 48 cputime_t cinterval, cval;
36 49
37 switch (which) { 50 switch (which) {
38 case ITIMER_REAL: 51 case ITIMER_REAL:
39 spin_lock_irq(&tsk->sighand->siglock); 52 value->it_value = itimer_get_remtime(&tsk->signal->real_timer);
40 interval = tsk->signal->it_real_incr; 53 value->it_interval =
41 val = it_real_value(tsk->signal); 54 ktime_to_timeval(tsk->signal->it_real_incr);
42 spin_unlock_irq(&tsk->sighand->siglock);
43 jiffies_to_timeval(val, &value->it_value);
44 jiffies_to_timeval(interval, &value->it_interval);
45 break; 55 break;
46 case ITIMER_VIRTUAL: 56 case ITIMER_VIRTUAL:
47 read_lock(&tasklist_lock); 57 read_lock(&tasklist_lock);
@@ -113,59 +123,45 @@ asmlinkage long sys_getitimer(int which, struct itimerval __user *value)
113} 123}
114 124
115 125
116void it_real_fn(unsigned long __data) 126/*
127 * The timer is automagically restarted, when interval != 0
128 */
129int it_real_fn(void *data)
117{ 130{
118 struct task_struct * p = (struct task_struct *) __data; 131 struct task_struct *tsk = (struct task_struct *) data;
119 unsigned long inc = p->signal->it_real_incr;
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 /* 135 if (tsk->signal->it_real_incr.tv64 != 0) {
124 * Now restart the timer if necessary. We don't need any locking 136 hrtimer_forward(&tsk->signal->real_timer,
125 * here because do_setitimer makes sure we have finished running 137 tsk->signal->it_real_incr);
126 * before it touches anything. 138
127 * Note, we KNOW we are (or should be) at a jiffie edge here so 139 return HRTIMER_RESTART;
128 * we don't need the +1 stuff. Also, we want to use the prior 140 }
129 * expire value so as to not "slip" a jiffie if we are late. 141 return HRTIMER_NORESTART;
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);
138} 142}
139 143
140int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) 144int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
141{ 145{
142 struct task_struct *tsk = current; 146 struct task_struct *tsk = current;
143 unsigned long val, interval, expires; 147 struct hrtimer *timer;
148 ktime_t expires;
144 cputime_t cval, cinterval, nval, ninterval; 149 cputime_t cval, cinterval, nval, ninterval;
145 150
146 switch (which) { 151 switch (which) {
147 case ITIMER_REAL: 152 case ITIMER_REAL:
148again: 153 timer = &tsk->signal->real_timer;
149 spin_lock_irq(&tsk->sighand->siglock); 154 hrtimer_cancel(timer);
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);
164 if (ovalue) { 155 if (ovalue) {
165 jiffies_to_timeval(val, &ovalue->it_value); 156 ovalue->it_value = itimer_get_remtime(timer);
166 jiffies_to_timeval(interval, 157 ovalue->it_interval
167 &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 break; 165 break;
170 case ITIMER_VIRTUAL: 166 case ITIMER_VIRTUAL:
171 nval = timeval_to_cputime(&value->it_value); 167 nval = timeval_to_cputime(&value->it_value);