aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/itimer.c24
-rw-r--r--kernel/posix-cpu-timers.c20
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
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
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);