]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - kernel/posix-cpu-timers.c
itimers: Simplify arm_timer() code a bit
[net-next-2.6.git] / kernel / posix-cpu-timers.c
index 9b2d5e4dc8c4a5f61ca8cbb285e15487f901dacb..69c92374355fb84bc432aed4e825f6f16d260dac 100644 (file)
@@ -541,6 +541,17 @@ static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now)
                                             now);
 }
 
+static inline int expires_gt(cputime_t expires, cputime_t new_exp)
+{
+       return cputime_eq(expires, cputime_zero) ||
+              cputime_gt(expires, new_exp);
+}
+
+static inline int expires_le(cputime_t expires, cputime_t new_exp)
+{
+       return !cputime_eq(expires, cputime_zero) &&
+              cputime_le(expires, new_exp);
+}
 /*
  * Insert the timer on the appropriate list before any timers that
  * expire later.  This must be called with the tasklist_lock held
@@ -585,31 +596,26 @@ static void arm_timer(struct k_itimer *timer, union cpu_time_count now)
                 */
 
                if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+                       union cpu_time_count *exp = &nt->expires;
+
                        switch (CPUCLOCK_WHICH(timer->it_clock)) {
                        default:
                                BUG();
                        case CPUCLOCK_PROF:
-                               if (cputime_eq(p->cputime_expires.prof_exp,
-                                              cputime_zero) ||
-                                   cputime_gt(p->cputime_expires.prof_exp,
-                                              nt->expires.cpu))
-                                       p->cputime_expires.prof_exp =
-                                               nt->expires.cpu;
+                               if (expires_gt(p->cputime_expires.prof_exp,
+                                              exp->cpu))
+                                       p->cputime_expires.prof_exp = exp->cpu;
                                break;
                        case CPUCLOCK_VIRT:
-                               if (cputime_eq(p->cputime_expires.virt_exp,
-                                              cputime_zero) ||
-                                   cputime_gt(p->cputime_expires.virt_exp,
-                                              nt->expires.cpu))
-                                       p->cputime_expires.virt_exp =
-                                               nt->expires.cpu;
+                               if (expires_gt(p->cputime_expires.virt_exp,
+                                              exp->cpu))
+                                       p->cputime_expires.virt_exp = exp->cpu;
                                break;
                        case CPUCLOCK_SCHED:
                                if (p->cputime_expires.sched_exp == 0 ||
-                                   p->cputime_expires.sched_exp >
-                                                       nt->expires.sched)
+                                   p->cputime_expires.sched_exp > exp->sched)
                                        p->cputime_expires.sched_exp =
-                                               nt->expires.sched;
+                                                               exp->sched;
                                break;
                        }
                } else {
@@ -623,17 +629,13 @@ static void arm_timer(struct k_itimer *timer, union cpu_time_count now)
                        default:
                                BUG();
                        case CPUCLOCK_VIRT:
-                               if (!cputime_eq(sig->it[CPUCLOCK_VIRT].expires,
-                                               cputime_zero) &&
-                                   cputime_lt(sig->it[CPUCLOCK_VIRT].expires,
+                               if (expires_le(sig->it[CPUCLOCK_VIRT].expires,
                                               exp->cpu))
                                        break;
                                sig->cputime_expires.virt_exp = exp->cpu;
                                break;
                        case CPUCLOCK_PROF:
-                               if (!cputime_eq(sig->it[CPUCLOCK_PROF].expires,
-                                               cputime_zero) &&
-                                   cputime_lt(sig->it[CPUCLOCK_PROF].expires,
+                               if (expires_le(sig->it[CPUCLOCK_PROF].expires,
                                               exp->cpu))
                                        break;
                                i = sig->rlim[RLIMIT_CPU].rlim_cur;
@@ -1070,6 +1072,8 @@ static void stop_process_timers(struct task_struct *tsk)
        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)
 {
@@ -1077,9 +1081,16 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,
                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);
        }
@@ -1696,10 +1707,15 @@ static __init int init_posix_cpu_timers(void)
                .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);