diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/itimer.c | 24 | ||||
-rw-r--r-- | kernel/posix-cpu-timers.c | 20 |
2 files changed, 38 insertions, 6 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 | ||
44 | static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, | 44 | static 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 | ||
130 | static 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 | |||
130 | static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, | 141 | static 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 | ||
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 | ||
1073 | static u32 onecputick; | ||
1074 | |||
1073 | static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, | 1075 | static 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); |