Commit 858cf3a8 authored by Frederic Weisbecker's avatar Frederic Weisbecker Committed by Ingo Molnar

timers/itimer: Convert internal cputime_t units to nsec

Use the new nsec based cputime accessors as part of the whole cputime
conversion from cputime_t to nsecs.

Also convert itimers to use nsec based internal counters. This simplifies
it and removes the whole game with error/inc_error which served to deal
with cputime_t random granularity.
Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Stanislaw Gruszka <sgruszka@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Wanpeng Li <wanpeng.li@hotmail.com>
Link: http://lkml.kernel.org/r/1485832191-26889-20-git-send-email-fweisbec@gmail.comSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent ebd7e7fc
...@@ -119,7 +119,7 @@ void run_posix_cpu_timers(struct task_struct *task); ...@@ -119,7 +119,7 @@ void run_posix_cpu_timers(struct task_struct *task);
void posix_cpu_timers_exit(struct task_struct *task); void posix_cpu_timers_exit(struct task_struct *task);
void posix_cpu_timers_exit_group(struct task_struct *task); void posix_cpu_timers_exit_group(struct task_struct *task);
void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx, void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
cputime_t *newval, cputime_t *oldval); u64 *newval, u64 *oldval);
long clock_nanosleep_restart(struct restart_block *restart_block); long clock_nanosleep_restart(struct restart_block *restart_block);
......
...@@ -568,10 +568,8 @@ struct pacct_struct { ...@@ -568,10 +568,8 @@ struct pacct_struct {
}; };
struct cpu_itimer { struct cpu_itimer {
cputime_t expires; u64 expires;
cputime_t incr; u64 incr;
u32 error;
u32 incr_error;
}; };
/** /**
......
...@@ -269,17 +269,17 @@ DEFINE_EVENT(hrtimer_class, hrtimer_cancel, ...@@ -269,17 +269,17 @@ DEFINE_EVENT(hrtimer_class, hrtimer_cancel,
TRACE_EVENT(itimer_state, TRACE_EVENT(itimer_state,
TP_PROTO(int which, const struct itimerval *const value, TP_PROTO(int which, const struct itimerval *const value,
cputime_t expires), unsigned long long expires),
TP_ARGS(which, value, expires), TP_ARGS(which, value, expires),
TP_STRUCT__entry( TP_STRUCT__entry(
__field( int, which ) __field( int, which )
__field( cputime_t, expires ) __field( unsigned long long, expires )
__field( long, value_sec ) __field( long, value_sec )
__field( long, value_usec ) __field( long, value_usec )
__field( long, interval_sec ) __field( long, interval_sec )
__field( long, interval_usec ) __field( long, interval_usec )
), ),
TP_fast_assign( TP_fast_assign(
...@@ -292,7 +292,7 @@ TRACE_EVENT(itimer_state, ...@@ -292,7 +292,7 @@ TRACE_EVENT(itimer_state,
), ),
TP_printk("which=%d expires=%llu it_value=%ld.%ld it_interval=%ld.%ld", TP_printk("which=%d expires=%llu it_value=%ld.%ld it_interval=%ld.%ld",
__entry->which, (unsigned long long)__entry->expires, __entry->which, __entry->expires,
__entry->value_sec, __entry->value_usec, __entry->value_sec, __entry->value_usec,
__entry->interval_sec, __entry->interval_usec) __entry->interval_sec, __entry->interval_usec)
); );
...@@ -305,14 +305,14 @@ TRACE_EVENT(itimer_state, ...@@ -305,14 +305,14 @@ TRACE_EVENT(itimer_state,
*/ */
TRACE_EVENT(itimer_expire, TRACE_EVENT(itimer_expire,
TP_PROTO(int which, struct pid *pid, cputime_t now), TP_PROTO(int which, struct pid *pid, unsigned long long now),
TP_ARGS(which, pid, now), TP_ARGS(which, pid, now),
TP_STRUCT__entry( TP_STRUCT__entry(
__field( int , which ) __field( int , which )
__field( pid_t, pid ) __field( pid_t, pid )
__field( cputime_t, now ) __field( unsigned long long, now )
), ),
TP_fast_assign( TP_fast_assign(
...@@ -322,7 +322,7 @@ TRACE_EVENT(itimer_expire, ...@@ -322,7 +322,7 @@ TRACE_EVENT(itimer_expire,
), ),
TP_printk("which=%d pid=%d now=%llu", __entry->which, TP_printk("which=%d pid=%d now=%llu", __entry->which,
(int) __entry->pid, (unsigned long long)__entry->now) (int) __entry->pid, __entry->now)
); );
#ifdef CONFIG_NO_HZ_COMMON #ifdef CONFIG_NO_HZ_COMMON
......
...@@ -45,35 +45,35 @@ static struct timeval itimer_get_remtime(struct hrtimer *timer) ...@@ -45,35 +45,35 @@ static struct timeval itimer_get_remtime(struct hrtimer *timer)
static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
struct itimerval *const value) struct itimerval *const value)
{ {
cputime_t cval, cinterval; u64 val, interval;
struct cpu_itimer *it = &tsk->signal->it[clock_id]; struct cpu_itimer *it = &tsk->signal->it[clock_id];
spin_lock_irq(&tsk->sighand->siglock); spin_lock_irq(&tsk->sighand->siglock);
cval = it->expires; val = it->expires;
cinterval = it->incr; interval = it->incr;
if (cval) { if (val) {
struct task_cputime cputime; struct task_cputime cputime;
cputime_t t; u64 t;
thread_group_cputimer(tsk, &cputime); thread_group_cputimer(tsk, &cputime);
if (clock_id == CPUCLOCK_PROF) if (clock_id == CPUCLOCK_PROF)
t = nsecs_to_cputime(cputime.utime + cputime.stime); t = cputime.utime + cputime.stime;
else else
/* CPUCLOCK_VIRT */ /* CPUCLOCK_VIRT */
t = nsecs_to_cputime(cputime.utime); t = cputime.utime;
if (cval < t) if (val < t)
/* about to fire */ /* about to fire */
cval = cputime_one_jiffy; val = TICK_NSEC;
else else
cval = cval - t; val -= t;
} }
spin_unlock_irq(&tsk->sighand->siglock); spin_unlock_irq(&tsk->sighand->siglock);
cputime_to_timeval(cval, &value->it_value); value->it_value = ns_to_timeval(val);
cputime_to_timeval(cinterval, &value->it_interval); value->it_interval = ns_to_timeval(interval);
} }
int do_getitimer(int which, struct itimerval *value) int do_getitimer(int which, struct itimerval *value)
...@@ -129,55 +129,35 @@ enum hrtimer_restart it_real_fn(struct hrtimer *timer) ...@@ -129,55 +129,35 @@ enum hrtimer_restart it_real_fn(struct hrtimer *timer)
return HRTIMER_NORESTART; 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, static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
const struct itimerval *const value, const struct itimerval *const value,
struct itimerval *const ovalue) struct itimerval *const ovalue)
{ {
cputime_t cval, nval, cinterval, ninterval; u64 oval, nval, ointerval, ninterval;
s64 ns_ninterval, ns_nval;
u32 error, incr_error;
struct cpu_itimer *it = &tsk->signal->it[clock_id]; struct cpu_itimer *it = &tsk->signal->it[clock_id];
nval = timeval_to_cputime(&value->it_value); nval = timeval_to_ns(&value->it_value);
ns_nval = timeval_to_ns(&value->it_value); ninterval = timeval_to_ns(&value->it_interval);
ninterval = timeval_to_cputime(&value->it_interval);
ns_ninterval = timeval_to_ns(&value->it_interval);
error = cputime_sub_ns(nval, ns_nval);
incr_error = cputime_sub_ns(ninterval, ns_ninterval);
spin_lock_irq(&tsk->sighand->siglock); spin_lock_irq(&tsk->sighand->siglock);
cval = it->expires; oval = it->expires;
cinterval = it->incr; ointerval = it->incr;
if (cval || nval) { if (oval || nval) {
if (nval > 0) if (nval > 0)
nval += cputime_one_jiffy; nval += TICK_NSEC;
set_process_cpu_timer(tsk, clock_id, &nval, &cval); set_process_cpu_timer(tsk, clock_id, &nval, &oval);
} }
it->expires = nval; it->expires = nval;
it->incr = ninterval; it->incr = ninterval;
it->error = error;
it->incr_error = incr_error;
trace_itimer_state(clock_id == CPUCLOCK_VIRT ? trace_itimer_state(clock_id == CPUCLOCK_VIRT ?
ITIMER_VIRTUAL : ITIMER_PROF, value, nval); ITIMER_VIRTUAL : ITIMER_PROF, value, nval);
spin_unlock_irq(&tsk->sighand->siglock); spin_unlock_irq(&tsk->sighand->siglock);
if (ovalue) { if (ovalue) {
cputime_to_timeval(cval, &ovalue->it_value); ovalue->it_value = ns_to_timeval(oval);
cputime_to_timeval(cinterval, &ovalue->it_interval); ovalue->it_interval = ns_to_timeval(ointerval);
} }
} }
......
...@@ -20,10 +20,10 @@ ...@@ -20,10 +20,10 @@
*/ */
void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new) void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new)
{ {
cputime_t cputime = secs_to_cputime(rlim_new); u64 nsecs = rlim_new * NSEC_PER_SEC;
spin_lock_irq(&task->sighand->siglock); spin_lock_irq(&task->sighand->siglock);
set_process_cpu_timer(task, CPUCLOCK_PROF, &cputime, NULL); set_process_cpu_timer(task, CPUCLOCK_PROF, &nsecs, NULL);
spin_unlock_irq(&task->sighand->siglock); spin_unlock_irq(&task->sighand->siglock);
} }
...@@ -860,17 +860,11 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, ...@@ -860,17 +860,11 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,
if (!it->expires) if (!it->expires)
return; return;
if (cur_time >= cputime_to_nsecs(it->expires)) { if (cur_time >= it->expires) {
if (it->incr) { if (it->incr)
it->expires += it->incr; it->expires += it->incr;
it->error += it->incr_error; else
if (it->error >= TICK_NSEC) {
it->expires -= cputime_one_jiffy;
it->error -= TICK_NSEC;
}
} else {
it->expires = 0; it->expires = 0;
}
trace_itimer_expire(signo == SIGPROF ? trace_itimer_expire(signo == SIGPROF ?
ITIMER_PROF : ITIMER_VIRTUAL, ITIMER_PROF : ITIMER_VIRTUAL,
...@@ -878,9 +872,8 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, ...@@ -878,9 +872,8 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,
__group_send_sig_info(signo, SEND_SIG_PRIV, tsk); __group_send_sig_info(signo, SEND_SIG_PRIV, tsk);
} }
if (it->expires && (!*expires || cputime_to_nsecs(it->expires) < *expires)) { if (it->expires && (!*expires || it->expires < *expires))
*expires = cputime_to_nsecs(it->expires); *expires = it->expires;
}
} }
/* /*
...@@ -1174,9 +1167,9 @@ void run_posix_cpu_timers(struct task_struct *tsk) ...@@ -1174,9 +1167,9 @@ void run_posix_cpu_timers(struct task_struct *tsk)
* The tsk->sighand->siglock must be held by the caller. * The tsk->sighand->siglock must be held by the caller.
*/ */
void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
cputime_t *newval, cputime_t *oldval) u64 *newval, u64 *oldval)
{ {
u64 now, new; u64 now;
WARN_ON_ONCE(clock_idx == CPUCLOCK_SCHED); WARN_ON_ONCE(clock_idx == CPUCLOCK_SCHED);
cpu_timer_sample_group(clock_idx, tsk, &now); cpu_timer_sample_group(clock_idx, tsk, &now);
...@@ -1188,33 +1181,31 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, ...@@ -1188,33 +1181,31 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
* it to be absolute. * it to be absolute.
*/ */
if (*oldval) { if (*oldval) {
if (cputime_to_nsecs(*oldval) <= now) { if (*oldval <= now) {
/* Just about to fire. */ /* Just about to fire. */
*oldval = cputime_one_jiffy; *oldval = TICK_NSEC;
} else { } else {
*oldval -= nsecs_to_cputime(now); *oldval -= now;
} }
} }
if (!*newval) if (!*newval)
return; return;
*newval += nsecs_to_cputime(now); *newval += now;
} }
new = cputime_to_nsecs(*newval);
/* /*
* Update expiration cache if we are the earliest timer, or eventually * Update expiration cache if we are the earliest timer, or eventually
* RLIMIT_CPU limit is earlier than prof_exp cpu timer expire. * RLIMIT_CPU limit is earlier than prof_exp cpu timer expire.
*/ */
switch (clock_idx) { switch (clock_idx) {
case CPUCLOCK_PROF: case CPUCLOCK_PROF:
if (expires_gt(tsk->signal->cputime_expires.prof_exp, new)) if (expires_gt(tsk->signal->cputime_expires.prof_exp, *newval))
tsk->signal->cputime_expires.prof_exp = new; tsk->signal->cputime_expires.prof_exp = *newval;
break; break;
case CPUCLOCK_VIRT: case CPUCLOCK_VIRT:
if (expires_gt(tsk->signal->cputime_expires.virt_exp, new)) if (expires_gt(tsk->signal->cputime_expires.virt_exp, *newval))
tsk->signal->cputime_expires.virt_exp = new; tsk->signal->cputime_expires.virt_exp = *newval;
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment