Messages in this thread Patch in this message | | | Date | Thu, 2 Apr 2009 14:11:46 +0200 | From | Stanislaw Gruszka <> | Subject | [PATCH 1/2] itimers: merge ITIMER_VIRT and ITIMER_PROF common code |
| |
Both cpu itimers have same data flow in the few places, this patch make unification of code related with VIRT and PROF itimers.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> --- include/linux/sched.h | 6 +- kernel/fork.c | 8 +- kernel/itimer.c | 136 +++++++++++++++++++-------------------------- kernel/posix-cpu-timers.c | 81 ++++++++++++++------------- 4 files changed, 107 insertions(+), 124 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h index 29df637..b4c19c2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -440,6 +440,8 @@ struct pacct_struct { unsigned long ac_minflt, ac_majflt; }; +enum itimer_number {IT_VIRT = 0, IT_PROF = 1}; + /** * struct task_cputime - collected CPU time counts * @utime: time spent in user mode, in &cputime_t units @@ -526,8 +528,8 @@ struct signal_struct { ktime_t it_real_incr; /* ITIMER_PROF and ITIMER_VIRTUAL timers for the process */ - cputime_t it_prof_expires, it_virt_expires; - cputime_t it_prof_incr, it_virt_incr; + cputime_t it_expires[2]; + cputime_t it_incr[2]; /* * Thread group totals for process CPU timers. diff --git a/kernel/fork.c b/kernel/fork.c index 47c1584..6c7044a 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -803,10 +803,10 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig) thread_group_cputime_init(sig); /* Expiration times and increments. */ - sig->it_virt_expires = cputime_zero; - sig->it_virt_incr = cputime_zero; - sig->it_prof_expires = cputime_zero; - sig->it_prof_incr = cputime_zero; + sig->it_expires[IT_VIRT] = cputime_zero; + sig->it_expires[IT_PROF] = cputime_zero; + sig->it_incr[IT_VIRT] = cputime_zero; + sig->it_incr[IT_PROF] = cputime_zero; /* Cached expiration times. */ sig->cputime_expires.prof_exp = cputime_zero; diff --git a/kernel/itimer.c b/kernel/itimer.c index 58762f7..ec64fea 100644 --- a/kernel/itimer.c +++ b/kernel/itimer.c @@ -41,10 +41,34 @@ static struct timeval itimer_get_remtime(struct hrtimer *timer) return ktime_to_timeval(rem); } +static void get_cpu_itimer(struct task_struct *tsk, enum itimer_number i, + struct itimerval *value) +{ + cputime_t cval, cinterval; + + spin_lock_irq(&tsk->sighand->siglock); + cval = tsk->signal->it_expires[i]; + cinterval = tsk->signal->it_incr[i]; + if (!cputime_eq(cval, cputime_zero)) { + struct task_cputime cputime; + cputime_t utime; + + thread_group_cputimer(tsk, &cputime); + utime = cputime.utime; + if (cputime_le(cval, utime)) { /* about to fire */ + cval = jiffies_to_cputime(1); + } else { + cval = cputime_sub(cval, utime); + } + } + spin_unlock_irq(&tsk->sighand->siglock); + cputime_to_timeval(cval, &value->it_value); + cputime_to_timeval(cinterval, &value->it_interval); +} + int do_getitimer(int which, struct itimerval *value) { struct task_struct *tsk = current; - cputime_t cinterval, cval; switch (which) { case ITIMER_REAL: @@ -55,44 +79,10 @@ int do_getitimer(int which, struct itimerval *value) spin_unlock_irq(&tsk->sighand->siglock); break; case ITIMER_VIRTUAL: - spin_lock_irq(&tsk->sighand->siglock); - cval = tsk->signal->it_virt_expires; - cinterval = tsk->signal->it_virt_incr; - if (!cputime_eq(cval, cputime_zero)) { - struct task_cputime cputime; - cputime_t utime; - - thread_group_cputimer(tsk, &cputime); - utime = cputime.utime; - if (cputime_le(cval, utime)) { /* about to fire */ - cval = jiffies_to_cputime(1); - } else { - cval = cputime_sub(cval, utime); - } - } - spin_unlock_irq(&tsk->sighand->siglock); - cputime_to_timeval(cval, &value->it_value); - cputime_to_timeval(cinterval, &value->it_interval); + get_cpu_itimer(tsk, IT_VIRT, value); break; case ITIMER_PROF: - spin_lock_irq(&tsk->sighand->siglock); - cval = tsk->signal->it_prof_expires; - cinterval = tsk->signal->it_prof_incr; - if (!cputime_eq(cval, cputime_zero)) { - struct task_cputime times; - cputime_t ptime; - - thread_group_cputimer(tsk, ×); - ptime = cputime_add(times.utime, times.stime); - if (cputime_le(cval, ptime)) { /* about to fire */ - cval = jiffies_to_cputime(1); - } else { - cval = cputime_sub(cval, ptime); - } - } - spin_unlock_irq(&tsk->sighand->siglock); - cputime_to_timeval(cval, &value->it_value); - cputime_to_timeval(cinterval, &value->it_interval); + get_cpu_itimer(tsk, IT_PROF, value); break; default: return(-EINVAL); @@ -128,6 +118,35 @@ enum hrtimer_restart it_real_fn(struct hrtimer *timer) return HRTIMER_NORESTART; } +static void set_cpu_itimer(struct task_struct *tsk, enum itimer_number i, + struct itimerval *value, struct itimerval *ovalue) +{ + cputime_t cval, cinterval, nval, ninterval; + + nval = timeval_to_cputime(&value->it_value); + ninterval = timeval_to_cputime(&value->it_interval); + + spin_lock_irq(&tsk->sighand->siglock); + + cval = tsk->signal->it_expires[i]; + cinterval = tsk->signal->it_incr[i]; + if (!cputime_eq(cval, cputime_zero) || + !cputime_eq(nval, cputime_zero)) { + if (cputime_gt(nval, cputime_zero)) + nval = cputime_add(nval, jiffies_to_cputime(1)); + set_process_cpu_timer(tsk, i, &nval, &cval); + } + tsk->signal->it_expires[i] = nval; + tsk->signal->it_incr[i] = ninterval; + + spin_unlock_irq(&tsk->sighand->siglock); + + if (ovalue) { + cputime_to_timeval(cval, &ovalue->it_value); + cputime_to_timeval(cinterval, &ovalue->it_interval); + } +} + /* * Returns true if the timeval is in canonical form */ @@ -139,7 +158,6 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) struct task_struct *tsk = current; struct hrtimer *timer; ktime_t expires; - cputime_t cval, cinterval, nval, ninterval; /* * Validate the timevals in value. @@ -174,48 +192,10 @@ again: spin_unlock_irq(&tsk->sighand->siglock); break; case ITIMER_VIRTUAL: - nval = timeval_to_cputime(&value->it_value); - ninterval = timeval_to_cputime(&value->it_interval); - spin_lock_irq(&tsk->sighand->siglock); - cval = tsk->signal->it_virt_expires; - cinterval = tsk->signal->it_virt_incr; - if (!cputime_eq(cval, cputime_zero) || - !cputime_eq(nval, cputime_zero)) { - if (cputime_gt(nval, cputime_zero)) - nval = cputime_add(nval, - jiffies_to_cputime(1)); - set_process_cpu_timer(tsk, CPUCLOCK_VIRT, - &nval, &cval); - } - tsk->signal->it_virt_expires = nval; - tsk->signal->it_virt_incr = ninterval; - spin_unlock_irq(&tsk->sighand->siglock); - if (ovalue) { - cputime_to_timeval(cval, &ovalue->it_value); - cputime_to_timeval(cinterval, &ovalue->it_interval); - } + set_cpu_itimer(tsk, IT_VIRT, value, ovalue); break; case ITIMER_PROF: - nval = timeval_to_cputime(&value->it_value); - ninterval = timeval_to_cputime(&value->it_interval); - spin_lock_irq(&tsk->sighand->siglock); - cval = tsk->signal->it_prof_expires; - cinterval = tsk->signal->it_prof_incr; - if (!cputime_eq(cval, cputime_zero) || - !cputime_eq(nval, cputime_zero)) { - if (cputime_gt(nval, cputime_zero)) - nval = cputime_add(nval, - jiffies_to_cputime(1)); - set_process_cpu_timer(tsk, CPUCLOCK_PROF, - &nval, &cval); - } - tsk->signal->it_prof_expires = nval; - tsk->signal->it_prof_incr = ninterval; - spin_unlock_irq(&tsk->sighand->siglock); - if (ovalue) { - cputime_to_timeval(cval, &ovalue->it_value); - cputime_to_timeval(cinterval, &ovalue->it_interval); - } + set_cpu_itimer(tsk, IT_PROF, value, ovalue); break; default: return -EINVAL; diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 8e5d9a6..76e125c 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -17,8 +17,8 @@ void update_rlimit_cpu(unsigned long rlim_new) cputime_t cputime; cputime = secs_to_cputime(rlim_new); - if (cputime_eq(current->signal->it_prof_expires, cputime_zero) || - cputime_lt(current->signal->it_prof_expires, cputime)) { + if (cputime_eq(current->signal->it_expires[IT_PROF], cputime_zero) || + cputime_lt(current->signal->it_expires[IT_PROF], cputime)) { spin_lock_irq(¤t->sighand->siglock); set_process_cpu_timer(current, CPUCLOCK_PROF, &cputime, NULL); spin_unlock_irq(¤t->sighand->siglock); @@ -619,18 +619,18 @@ static void arm_timer(struct k_itimer *timer, union cpu_time_count now) default: BUG(); case CPUCLOCK_VIRT: - if (!cputime_eq(p->signal->it_virt_expires, + if (!cputime_eq(p->signal->it_expires[IT_VIRT], cputime_zero) && - cputime_lt(p->signal->it_virt_expires, + cputime_lt(p->signal->it_expires[IT_VIRT], timer->it.cpu.expires.cpu)) break; p->signal->cputime_expires.virt_exp = timer->it.cpu.expires.cpu; break; case CPUCLOCK_PROF: - if (!cputime_eq(p->signal->it_prof_expires, + if (!cputime_eq(p->signal->it_expires[IT_PROF], cputime_zero) && - cputime_lt(p->signal->it_prof_expires, + cputime_lt(p->signal->it_expires[IT_PROF], timer->it.cpu.expires.cpu)) break; i = p->signal->rlim[RLIMIT_CPU].rlim_cur; @@ -1069,6 +1069,36 @@ static void stop_process_timers(struct task_struct *tsk) spin_unlock_irqrestore(&cputimer->lock, flags); } +static cputime_t check_cpu_itimer(struct task_struct *tsk, enum itimer_number i, + cputime_t expires, cputime_t cur_time) +{ + struct signal_struct *const sig = tsk->signal; + + if (cputime_eq(sig->it_expires[i], cputime_zero)) + return expires; + + if (cputime_ge(cur_time, sig->it_expires[i])) { + int signo; + + sig->it_expires[i] = sig->it_incr[i]; + if (!cputime_eq(sig->it_expires[i], cputime_zero)) { + sig->it_expires[i] = cputime_add(sig->it_expires[i], + cur_time); + } + + signo = (i == IT_VIRT) ? SIGVTALRM : SIGPROF; + __group_send_sig_info(signo, SEND_SIG_PRIV, tsk); + } + + if (!cputime_eq(sig->it_expires[i], cputime_zero) && + (cputime_eq(expires, cputime_zero) || + cputime_lt(sig->it_expires[i], expires))) { + expires = sig->it_expires[i]; + } + + return expires; +} + /* * Check for any per-thread CPU timers that have fired and move them * off the tsk->*_timers list onto the firing list. Per-thread timers @@ -1088,10 +1118,10 @@ static void check_process_timers(struct task_struct *tsk, * Don't sample the current process CPU clocks if there are no timers. */ if (list_empty(&timers[CPUCLOCK_PROF]) && - cputime_eq(sig->it_prof_expires, cputime_zero) && + cputime_eq(sig->it_expires[IT_PROF], cputime_zero) && sig->rlim[RLIMIT_CPU].rlim_cur == RLIM_INFINITY && list_empty(&timers[CPUCLOCK_VIRT]) && - cputime_eq(sig->it_virt_expires, cputime_zero) && + cputime_eq(sig->it_expires[IT_VIRT], cputime_zero) && list_empty(&timers[CPUCLOCK_SCHED])) { stop_process_timers(tsk); return; @@ -1151,38 +1181,9 @@ static void check_process_timers(struct task_struct *tsk, /* * Check for the special case process timers. */ - if (!cputime_eq(sig->it_prof_expires, cputime_zero)) { - if (cputime_ge(ptime, sig->it_prof_expires)) { - /* ITIMER_PROF fires and reloads. */ - sig->it_prof_expires = sig->it_prof_incr; - if (!cputime_eq(sig->it_prof_expires, cputime_zero)) { - sig->it_prof_expires = cputime_add( - sig->it_prof_expires, ptime); - } - __group_send_sig_info(SIGPROF, SEND_SIG_PRIV, tsk); - } - if (!cputime_eq(sig->it_prof_expires, cputime_zero) && - (cputime_eq(prof_expires, cputime_zero) || - cputime_lt(sig->it_prof_expires, prof_expires))) { - prof_expires = sig->it_prof_expires; - } - } - if (!cputime_eq(sig->it_virt_expires, cputime_zero)) { - if (cputime_ge(utime, sig->it_virt_expires)) { - /* ITIMER_VIRTUAL fires and reloads. */ - sig->it_virt_expires = sig->it_virt_incr; - if (!cputime_eq(sig->it_virt_expires, cputime_zero)) { - sig->it_virt_expires = cputime_add( - sig->it_virt_expires, utime); - } - __group_send_sig_info(SIGVTALRM, SEND_SIG_PRIV, tsk); - } - if (!cputime_eq(sig->it_virt_expires, cputime_zero) && - (cputime_eq(virt_expires, cputime_zero) || - cputime_lt(sig->it_virt_expires, virt_expires))) { - virt_expires = sig->it_virt_expires; - } - } + prof_expires = check_cpu_itimer(tsk, IT_PROF, prof_expires, ptime); + virt_expires = check_cpu_itimer(tsk, IT_VIRT, virt_expires, utime); + if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) { unsigned long psecs = cputime_to_secs(ptime); cputime_t x; -- 1.6.0.6
| |