aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/posix-cpu-timers.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/posix-cpu-timers.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/posix-cpu-timers.c')
-rw-r--r--kernel/posix-cpu-timers.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 9b2d5e4dc8c4..b60d644ea4b3 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -1070,6 +1070,8 @@ static void stop_process_timers(struct task_struct *tsk)
1070 spin_unlock_irqrestore(&cputimer->lock, flags); 1070 spin_unlock_irqrestore(&cputimer->lock, flags);
1071} 1071}
1072 1072
1073static u32 onecputick;
1074
1073static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, 1075static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,
1074 cputime_t *expires, cputime_t cur_time, int signo) 1076 cputime_t *expires, cputime_t cur_time, int signo)
1075{ 1077{
@@ -1077,9 +1079,16 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,
1077 return; 1079 return;
1078 1080
1079 if (cputime_ge(cur_time, it->expires)) { 1081 if (cputime_ge(cur_time, it->expires)) {
1080 it->expires = it->incr; 1082 if (!cputime_eq(it->incr, cputime_zero)) {
1081 if (!cputime_eq(it->expires, cputime_zero)) 1083 it->expires = cputime_add(it->expires, it->incr);
1082 it->expires = cputime_add(it->expires, cur_time); 1084 it->error += it->incr_error;
1085 if (it->error >= onecputick) {
1086 it->expires = cputime_sub(it->expires,
1087 jiffies_to_cputime(1));
1088 it->error -= onecputick;
1089 }
1090 } else
1091 it->expires = cputime_zero;
1083 1092
1084 __group_send_sig_info(signo, SEND_SIG_PRIV, tsk); 1093 __group_send_sig_info(signo, SEND_SIG_PRIV, tsk);
1085 } 1094 }
@@ -1696,10 +1705,15 @@ static __init int init_posix_cpu_timers(void)
1696 .nsleep = thread_cpu_nsleep, 1705 .nsleep = thread_cpu_nsleep,
1697 .nsleep_restart = thread_cpu_nsleep_restart, 1706 .nsleep_restart = thread_cpu_nsleep_restart,
1698 }; 1707 };
1708 struct timespec ts;
1699 1709
1700 register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process); 1710 register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
1701 register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &thread); 1711 register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &thread);
1702 1712
1713 cputime_to_timespec(jiffies_to_cputime(1), &ts);
1714 onecputick = ts.tv_nsec;
1715 WARN_ON(ts.tv_sec != 0);
1716
1703 return 0; 1717 return 0;
1704} 1718}
1705__initcall(init_posix_cpu_timers); 1719__initcall(init_posix_cpu_timers);