}
static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
- struct itimerval *value)
+ struct itimerval *const value)
{
cputime_t cval, cinterval;
struct cpu_itimer *it = &tsk->signal->it[clock_id];
return HRTIMER_NORESTART;
}
+static inline u32 cputime_sub_ns(cputime_t ct, s64 real_ns)
+{
+ struct timespec ts;
+ s64 cpu_ns;
+
+ cputime_to_timespec(ct, &ts);
+ cpu_ns = timespec_to_ns(&ts);
+
+ return (cpu_ns <= real_ns) ? 0 : cpu_ns - real_ns;
+}
+
static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
- struct itimerval *value, struct itimerval *ovalue)
+ const struct itimerval *const value,
+ struct itimerval *const ovalue)
{
- cputime_t cval, cinterval, nval, ninterval;
+ cputime_t cval, nval, cinterval, ninterval;
+ s64 ns_ninterval, ns_nval;
struct cpu_itimer *it = &tsk->signal->it[clock_id];
nval = timeval_to_cputime(&value->it_value);
+ ns_nval = timeval_to_ns(&value->it_value);
ninterval = timeval_to_cputime(&value->it_interval);
+ ns_ninterval = timeval_to_ns(&value->it_interval);
+
+ it->incr_error = cputime_sub_ns(ninterval, ns_ninterval);
+ it->error = cputime_sub_ns(nval, ns_nval);
spin_lock_irq(&tsk->sighand->siglock);
spin_unlock_irqrestore(&cputimer->lock, flags);
}
+static u32 onecputick;
+
static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,
cputime_t *expires, cputime_t cur_time, int signo)
{
return;
if (cputime_ge(cur_time, it->expires)) {
- it->expires = it->incr;
- if (!cputime_eq(it->expires, cputime_zero))
- it->expires = cputime_add(it->expires, cur_time);
+ if (!cputime_eq(it->incr, cputime_zero)) {
+ it->expires = cputime_add(it->expires, it->incr);
+ it->error += it->incr_error;
+ if (it->error >= onecputick) {
+ it->expires = cputime_sub(it->expires,
+ jiffies_to_cputime(1));
+ it->error -= onecputick;
+ }
+ } else
+ it->expires = cputime_zero;
__group_send_sig_info(signo, SEND_SIG_PRIV, tsk);
}
.nsleep = thread_cpu_nsleep,
.nsleep_restart = thread_cpu_nsleep_restart,
};
+ struct timespec ts;
register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &thread);
+ cputime_to_timespec(jiffies_to_cputime(1), &ts);
+ onecputick = ts.tv_nsec;
+ WARN_ON(ts.tv_sec != 0);
+
return 0;
}
__initcall(init_posix_cpu_timers);