aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/itimer.c
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2009-07-29 06:15:27 -0400
committerIngo Molnar <mingo@elte.hu>2009-08-03 08:48:35 -0400
commit8356b5f9c424e5831715abbce747197c30d1fd71 (patch)
tree87de74cc86f6eebf88eba9a4c335614787d984c5 /kernel/itimer.c
parent42c4ab41a176ee784c0f28c0b29025a8fc34f05a (diff)
itimers: Fix periodic tics precision
Measure ITIMER_PROF and ITIMER_VIRT timers interval error between real ticks and requested by user. Take it into account when scheduling next tick. This patch introduce possibility where time between two consecutive tics is smaller then requested interval, it preserve however dependency that n tick is generated not earlier than n*interval time - counting from the beginning of periodic signal generation. Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Thomas Gleixner <tglx@linutronix.de> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> LKML-Reference: <1248862529-6063-3-git-send-email-sgruszka@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/itimer.c')
-rw-r--r--kernel/itimer.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/kernel/itimer.c b/kernel/itimer.c
index 852c88ddd1f0..21adff7b2a17 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -42,7 +42,7 @@ static struct timeval itimer_get_remtime(struct hrtimer *timer)
42} 42}
43 43
44static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, 44static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
45 struct itimerval *value) 45 struct itimerval *const value)
46{ 46{
47 cputime_t cval, cinterval; 47 cputime_t cval, cinterval;
48 struct cpu_itimer *it = &tsk->signal->it[clock_id]; 48 struct cpu_itimer *it = &tsk->signal->it[clock_id];
@@ -127,14 +127,32 @@ enum hrtimer_restart it_real_fn(struct hrtimer *timer)
127 return HRTIMER_NORESTART; 127 return HRTIMER_NORESTART;
128} 128}
129 129
130static inline u32 cputime_sub_ns(cputime_t ct, s64 real_ns)
131{
132 struct timespec ts;
133 s64 cpu_ns;
134
135 cputime_to_timespec(ct, &ts);
136 cpu_ns = timespec_to_ns(&ts);
137
138 return (cpu_ns <= real_ns) ? 0 : cpu_ns - real_ns;
139}
140
130static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, 141static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
131 struct itimerval *value, struct itimerval *ovalue) 142 const struct itimerval *const value,
143 struct itimerval *const ovalue)
132{ 144{
133 cputime_t cval, cinterval, nval, ninterval; 145 cputime_t cval, nval, cinterval, ninterval;
146 s64 ns_ninterval, ns_nval;
134 struct cpu_itimer *it = &tsk->signal->it[clock_id]; 147 struct cpu_itimer *it = &tsk->signal->it[clock_id];
135 148
136 nval = timeval_to_cputime(&value->it_value); 149 nval = timeval_to_cputime(&value->it_value);
150 ns_nval = timeval_to_ns(&value->it_value);
137 ninterval = timeval_to_cputime(&value->it_interval); 151 ninterval = timeval_to_cputime(&value->it_interval);
152 ns_ninterval = timeval_to_ns(&value->it_interval);
153
154 it->incr_error = cputime_sub_ns(ninterval, ns_ninterval);
155 it->error = cputime_sub_ns(nval, ns_nval);
138 156
139 spin_lock_irq(&tsk->sighand->siglock); 157 spin_lock_irq(&tsk->sighand->siglock);
140 158