ftrace: Update the kconfig for DYNAMIC_FTRACE
[linux-2.6.git] / kernel / posix-cpu-timers.c
index d01e0a3..acbb79c 100644 (file)
  * siglock protection since other code may update expiration cache as
  * well.
  */
-void update_rlimit_cpu(unsigned long rlim_new)
+void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new)
 {
        cputime_t cputime = secs_to_cputime(rlim_new);
 
-       spin_lock_irq(&current->sighand->siglock);
-       set_process_cpu_timer(current, CPUCLOCK_PROF, &cputime, NULL);
-       spin_unlock_irq(&current->sighand->siglock);
+       spin_lock_irq(&task->sighand->siglock);
+       set_process_cpu_timer(task, CPUCLOCK_PROF, &cputime, NULL);
+       spin_unlock_irq(&task->sighand->siglock);
 }
 
 static int check_clock(const clockid_t which_clock)
@@ -37,13 +37,13 @@ static int check_clock(const clockid_t which_clock)
        if (pid == 0)
                return 0;
 
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
        p = find_task_by_vpid(pid);
        if (!p || !(CPUCLOCK_PERTHREAD(which_clock) ?
-                  same_thread_group(p, current) : thread_group_leader(p))) {
+                  same_thread_group(p, current) : has_group_leader_pid(p))) {
                error = -EINVAL;
        }
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
 
        return error;
 }
@@ -78,7 +78,7 @@ static inline int cpu_time_before(const clockid_t which_clock,
        if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
                return now.sched < then.sched;
        }  else {
-               return cputime_lt(now.cpu, then.cpu);
+               return now.cpu < then.cpu;
        }
 }
 static inline void cpu_time_add(const clockid_t which_clock,
@@ -88,7 +88,7 @@ static inline void cpu_time_add(const clockid_t which_clock,
        if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
                acc->sched += val.sched;
        }  else {
-               acc->cpu = cputime_add(acc->cpu, val.cpu);
+               acc->cpu += val.cpu;
        }
 }
 static inline union cpu_time_count cpu_time_sub(const clockid_t which_clock,
@@ -98,25 +98,12 @@ static inline union cpu_time_count cpu_time_sub(const clockid_t which_clock,
        if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
                a.sched -= b.sched;
        }  else {
-               a.cpu = cputime_sub(a.cpu, b.cpu);
+               a.cpu -= b.cpu;
        }
        return a;
 }
 
 /*
- * Divide and limit the result to res >= 1
- *
- * This is necessary to prevent signal delivery starvation, when the result of
- * the division would be rounded down to 0.
- */
-static inline cputime_t cputime_div_non_zero(cputime_t time, unsigned long div)
-{
-       cputime_t res = cputime_div(time, div);
-
-       return max_t(cputime_t, res, 1);
-}
-
-/*
  * Update expiry time from increment, and increase overrun count,
  * given the current clock sample.
  */
@@ -148,35 +135,34 @@ static void bump_cpu_timer(struct k_itimer *timer,
        } else {
                cputime_t delta, incr;
 
-               if (cputime_lt(now.cpu, timer->it.cpu.expires.cpu))
+               if (now.cpu < timer->it.cpu.expires.cpu)
                        return;
                incr = timer->it.cpu.incr.cpu;
-               delta = cputime_sub(cputime_add(now.cpu, incr),
-                                   timer->it.cpu.expires.cpu);
+               delta = now.cpu + incr - timer->it.cpu.expires.cpu;
                /* Don't use (incr*2 < delta), incr*2 might overflow. */
-               for (i = 0; cputime_lt(incr, cputime_sub(delta, incr)); i++)
-                            incr = cputime_add(incr, incr);
-               for (; i >= 0; incr = cputime_halve(incr), i--) {
-                       if (cputime_lt(delta, incr))
+               for (i = 0; incr < delta - incr; i++)
+                            incr += incr;
+               for (; i >= 0; incr = incr >> 1, i--) {
+                       if (delta < incr)
                                continue;
-                       timer->it.cpu.expires.cpu =
-                               cputime_add(timer->it.cpu.expires.cpu, incr);
+                       timer->it.cpu.expires.cpu += incr;
                        timer->it_overrun += 1 << i;
-                       delta = cputime_sub(delta, incr);
+                       delta -= incr;
                }
        }
 }
 
 static inline cputime_t prof_ticks(struct task_struct *p)
 {
-       return cputime_add(p->utime, p->stime);
+       return p->utime + p->stime;
 }
 static inline cputime_t virt_ticks(struct task_struct *p)
 {
        return p->utime;
 }
 
-int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
+static int
+posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
 {
        int error = check_clock(which_clock);
        if (!error) {
@@ -194,7 +180,8 @@ int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
        return error;
 }
 
-int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp)
+static int
+posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp)
 {
        /*
         * You can never reset a CPU clock, but we check for other errors
@@ -232,41 +219,34 @@ static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p,
 
 void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times)
 {
-       struct sighand_struct *sighand;
-       struct signal_struct *sig;
+       struct signal_struct *sig = tsk->signal;
        struct task_struct *t;
 
-       *times = INIT_CPUTIME;
+       times->utime = sig->utime;
+       times->stime = sig->stime;
+       times->sum_exec_runtime = sig->sum_sched_runtime;
 
        rcu_read_lock();
-       sighand = rcu_dereference(tsk->sighand);
-       if (!sighand)
+       /* make sure we can trust tsk->thread_group list */
+       if (!likely(pid_alive(tsk)))
                goto out;
 
-       sig = tsk->signal;
-
        t = tsk;
        do {
-               times->utime = cputime_add(times->utime, t->utime);
-               times->stime = cputime_add(times->stime, t->stime);
-               times->sum_exec_runtime += t->se.sum_exec_runtime;
-
-               t = next_thread(t);
-       } while (t != tsk);
-
-       times->utime = cputime_add(times->utime, sig->utime);
-       times->stime = cputime_add(times->stime, sig->stime);
-       times->sum_exec_runtime += sig->sum_sched_runtime;
+               times->utime += t->utime;
+               times->stime += t->stime;
+               times->sum_exec_runtime += task_sched_runtime(t);
+       } while_each_thread(tsk, t);
 out:
        rcu_read_unlock();
 }
 
 static void update_gt_cputime(struct task_cputime *a, struct task_cputime *b)
 {
-       if (cputime_gt(b->utime, a->utime))
+       if (b->utime > a->utime)
                a->utime = b->utime;
 
-       if (cputime_gt(b->stime, a->stime))
+       if (b->stime > a->stime)
                a->stime = b->stime;
 
        if (b->sum_exec_runtime > a->sum_exec_runtime)
@@ -279,9 +259,7 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
        struct task_cputime sum;
        unsigned long flags;
 
-       spin_lock_irqsave(&cputimer->lock, flags);
        if (!cputimer->running) {
-               cputimer->running = 1;
                /*
                 * The POSIX timer interface allows for absolute time expiry
                 * values through the TIMER_ABSTIME flag, therefore we have
@@ -289,10 +267,13 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
                 * it.
                 */
                thread_group_cputime(tsk, &sum);
+               raw_spin_lock_irqsave(&cputimer->lock, flags);
+               cputimer->running = 1;
                update_gt_cputime(&cputimer->cputime, &sum);
-       }
+       } else
+               raw_spin_lock_irqsave(&cputimer->lock, flags);
        *times = cputimer->cputime;
-       spin_unlock_irqrestore(&cputimer->lock, flags);
+       raw_spin_unlock_irqrestore(&cputimer->lock, flags);
 }
 
 /*
@@ -310,21 +291,22 @@ static int cpu_clock_sample_group(const clockid_t which_clock,
                return -EINVAL;
        case CPUCLOCK_PROF:
                thread_group_cputime(p, &cputime);
-               cpu->cpu = cputime_add(cputime.utime, cputime.stime);
+               cpu->cpu = cputime.utime + cputime.stime;
                break;
        case CPUCLOCK_VIRT:
                thread_group_cputime(p, &cputime);
                cpu->cpu = cputime.utime;
                break;
        case CPUCLOCK_SCHED:
-               cpu->sched = thread_group_sched_runtime(p);
+               thread_group_cputime(p, &cputime);
+               cpu->sched = cputime.sum_exec_runtime;
                break;
        }
        return 0;
 }
 
 
-int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
+static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
 {
        const pid_t pid = CPUCLOCK_PID(which_clock);
        int error = -EINVAL;
@@ -363,7 +345,7 @@ int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
                                }
                        } else {
                                read_lock(&tasklist_lock);
-                               if (thread_group_leader(p) && p->signal) {
+                               if (thread_group_leader(p) && p->sighand) {
                                        error =
                                            cpu_clock_sample_group(which_clock,
                                                                   p, &rtn);
@@ -386,7 +368,7 @@ int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
  * This is called from sys_timer_create() and do_cpu_nanosleep() with the
  * new timer already all-zeros initialized.
  */
-int posix_cpu_timer_create(struct k_itimer *new_timer)
+static int posix_cpu_timer_create(struct k_itimer *new_timer)
 {
        int ret = 0;
        const pid_t pid = CPUCLOCK_PID(new_timer->it_clock);
@@ -397,7 +379,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
 
        INIT_LIST_HEAD(&new_timer->it.cpu.entry);
 
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
        if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) {
                if (pid == 0) {
                        p = current;
@@ -411,7 +393,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
                        p = current->group_leader;
                } else {
                        p = find_task_by_vpid(pid);
-                       if (p && !thread_group_leader(p))
+                       if (p && !has_group_leader_pid(p))
                                p = NULL;
                }
        }
@@ -421,7 +403,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
        } else {
                ret = -EINVAL;
        }
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
 
        return ret;
 }
@@ -432,14 +414,14 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
  * If we return TIMER_RETRY, it's necessary to release the timer's lock
  * and try again.  (This happens when the timer is in the middle of firing.)
  */
-int posix_cpu_timer_del(struct k_itimer *timer)
+static int posix_cpu_timer_del(struct k_itimer *timer)
 {
        struct task_struct *p = timer->it.cpu.task;
        int ret = 0;
 
        if (likely(p != NULL)) {
                read_lock(&tasklist_lock);
-               if (unlikely(p->signal == NULL)) {
+               if (unlikely(p->sighand == NULL)) {
                        /*
                         * We raced with the reaping of the task.
                         * The deletion should have cleared us off the list.
@@ -473,26 +455,24 @@ static void cleanup_timers(struct list_head *head,
                           unsigned long long sum_exec_runtime)
 {
        struct cpu_timer_list *timer, *next;
-       cputime_t ptime = cputime_add(utime, stime);
+       cputime_t ptime = utime + stime;
 
        list_for_each_entry_safe(timer, next, head, entry) {
                list_del_init(&timer->entry);
-               if (cputime_lt(timer->expires.cpu, ptime)) {
-                       timer->expires.cpu = cputime_zero;
+               if (timer->expires.cpu < ptime) {
+                       timer->expires.cpu = 0;
                } else {
-                       timer->expires.cpu = cputime_sub(timer->expires.cpu,
-                                                        ptime);
+                       timer->expires.cpu -= ptime;
                }
        }
 
        ++head;
        list_for_each_entry_safe(timer, next, head, entry) {
                list_del_init(&timer->entry);
-               if (cputime_lt(timer->expires.cpu, utime)) {
-                       timer->expires.cpu = cputime_zero;
+               if (timer->expires.cpu < utime) {
+                       timer->expires.cpu = 0;
                } else {
-                       timer->expires.cpu = cputime_sub(timer->expires.cpu,
-                                                        utime);
+                       timer->expires.cpu -= utime;
                }
        }
 
@@ -523,8 +503,7 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk)
        struct signal_struct *const sig = tsk->signal;
 
        cleanup_timers(tsk->signal->cpu_timers,
-                      cputime_add(tsk->utime, sig->utime),
-                      cputime_add(tsk->stime, sig->stime),
+                      tsk->utime + sig->utime, tsk->stime + sig->stime,
                       tsk->se.sum_exec_runtime + sig->sum_sched_runtime);
 }
 
@@ -543,105 +522,65 @@ static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now)
 
 static inline int expires_gt(cputime_t expires, cputime_t new_exp)
 {
-       return cputime_eq(expires, cputime_zero) ||
-              cputime_gt(expires, new_exp);
+       return expires == 0 || 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
- * for reading, and interrupts disabled.
+ * for reading, interrupts disabled and p->sighand->siglock taken.
  */
-static void arm_timer(struct k_itimer *timer, union cpu_time_count now)
+static void arm_timer(struct k_itimer *timer)
 {
        struct task_struct *p = timer->it.cpu.task;
        struct list_head *head, *listpos;
+       struct task_cputime *cputime_expires;
        struct cpu_timer_list *const nt = &timer->it.cpu;
        struct cpu_timer_list *next;
 
-       head = (CPUCLOCK_PERTHREAD(timer->it_clock) ?
-               p->cpu_timers : p->signal->cpu_timers);
+       if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+               head = p->cpu_timers;
+               cputime_expires = &p->cputime_expires;
+       } else {
+               head = p->signal->cpu_timers;
+               cputime_expires = &p->signal->cputime_expires;
+       }
        head += CPUCLOCK_WHICH(timer->it_clock);
 
-       BUG_ON(!irqs_disabled());
-       spin_lock(&p->sighand->siglock);
-
        listpos = head;
-       if (CPUCLOCK_WHICH(timer->it_clock) == CPUCLOCK_SCHED) {
-               list_for_each_entry(next, head, entry) {
-                       if (next->expires.sched > nt->expires.sched)
-                               break;
-                       listpos = &next->entry;
-               }
-       } else {
-               list_for_each_entry(next, head, entry) {
-                       if (cputime_gt(next->expires.cpu, nt->expires.cpu))
-                               break;
-                       listpos = &next->entry;
-               }
+       list_for_each_entry(next, head, entry) {
+               if (cpu_time_before(timer->it_clock, nt->expires, next->expires))
+                       break;
+               listpos = &next->entry;
        }
        list_add(&nt->entry, listpos);
 
        if (listpos == head) {
+               union cpu_time_count *exp = &nt->expires;
+
                /*
-                * We are the new earliest-expiring timer.
-                * If we are a thread timer, there can always
-                * be a process timer telling us to stop earlier.
+                * We are the new earliest-expiring POSIX 1.b timer, hence
+                * need to update expiration cache. Take into account that
+                * for process timers we share expiration cache with itimers
+                * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME.
                 */
 
-               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 (expires_gt(p->cputime_expires.prof_exp,
-                                              exp->cpu))
-                                       p->cputime_expires.prof_exp = exp->cpu;
-                               break;
-                       case CPUCLOCK_VIRT:
-                               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 > exp->sched)
-                                       p->cputime_expires.sched_exp =
-                                                               exp->sched;
-                               break;
-                       }
-               } else {
-                       struct signal_struct *const sig = p->signal;
-                       union cpu_time_count *exp = &timer->it.cpu.expires;
-
-                       /*
-                        * For a process timer, set the cached expiration time.
-                        */
-                       switch (CPUCLOCK_WHICH(timer->it_clock)) {
-                       default:
-                               BUG();
-                       case CPUCLOCK_VIRT:
-                               if (expires_gt(sig->cputime_expires.virt_exp, exp->cpu))
-                                       sig->cputime_expires.virt_exp = exp->cpu;
-                       case CPUCLOCK_PROF:
-                               if (expires_gt(sig->cputime_expires.prof_exp, exp->cpu))
-                                       sig->cputime_expires.prof_exp = exp->cpu;
-                               break;
-                       case CPUCLOCK_SCHED:
-                               sig->cputime_expires.sched_exp = exp->sched;
-                               break;
-                       }
+               switch (CPUCLOCK_WHICH(timer->it_clock)) {
+               case CPUCLOCK_PROF:
+                       if (expires_gt(cputime_expires->prof_exp, exp->cpu))
+                               cputime_expires->prof_exp = exp->cpu;
+                       break;
+               case CPUCLOCK_VIRT:
+                       if (expires_gt(cputime_expires->virt_exp, exp->cpu))
+                               cputime_expires->virt_exp = exp->cpu;
+                       break;
+               case CPUCLOCK_SCHED:
+                       if (cputime_expires->sched_exp == 0 ||
+                           cputime_expires->sched_exp > exp->sched)
+                               cputime_expires->sched_exp = exp->sched;
+                       break;
                }
        }
-
-       spin_unlock(&p->sighand->siglock);
 }
 
 /*
@@ -649,7 +588,12 @@ static void arm_timer(struct k_itimer *timer, union cpu_time_count now)
  */
 static void cpu_timer_fire(struct k_itimer *timer)
 {
-       if (unlikely(timer->sigq == NULL)) {
+       if ((timer->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
+               /*
+                * User don't want any signal.
+                */
+               timer->it.cpu.expires.sched = 0;
+       } else if (unlikely(timer->sigq == NULL)) {
                /*
                 * This a special case for clock_nanosleep,
                 * not a normal timer from sys_timer_create.
@@ -688,7 +632,7 @@ static int cpu_timer_sample_group(const clockid_t which_clock,
        default:
                return -EINVAL;
        case CPUCLOCK_PROF:
-               cpu->cpu = cputime_add(cputime.utime, cputime.stime);
+               cpu->cpu = cputime.utime + cputime.stime;
                break;
        case CPUCLOCK_VIRT:
                cpu->cpu = cputime.utime;
@@ -706,11 +650,11 @@ static int cpu_timer_sample_group(const clockid_t which_clock,
  * If we return TIMER_RETRY, it's necessary to release the timer's lock
  * and try again.  (This happens when the timer is in the middle of firing.)
  */
-int posix_cpu_timer_set(struct k_itimer *timer, int flags,
-                       struct itimerspec *new, struct itimerspec *old)
+static int posix_cpu_timer_set(struct k_itimer *timer, int flags,
+                              struct itimerspec *new, struct itimerspec *old)
 {
        struct task_struct *p = timer->it.cpu.task;
-       union cpu_time_count old_expires, new_expires, val;
+       union cpu_time_count old_expires, new_expires, old_incr, val;
        int ret;
 
        if (unlikely(p == NULL)) {
@@ -725,10 +669,10 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags,
        read_lock(&tasklist_lock);
        /*
         * We need the tasklist_lock to protect against reaping that
-        * clears p->signal.  If p has just been reaped, we can no
+        * clears p->sighand.  If p has just been reaped, we can no
         * longer get any information about it at all.
         */
-       if (unlikely(p->signal == NULL)) {
+       if (unlikely(p->sighand == NULL)) {
                read_unlock(&tasklist_lock);
                put_task_struct(p);
                timer->it.cpu.task = NULL;
@@ -741,6 +685,7 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags,
        BUG_ON(!irqs_disabled());
 
        ret = 0;
+       old_incr = timer->it.cpu.incr;
        spin_lock(&p->sighand->siglock);
        old_expires = timer->it.cpu.expires;
        if (unlikely(timer->it.cpu.firing)) {
@@ -748,7 +693,6 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags,
                ret = TIMER_RETRY;
        } else
                list_del_init(&timer->it.cpu.entry);
-       spin_unlock(&p->sighand->siglock);
 
        /*
         * We need to sample the current value to convert the new
@@ -802,6 +746,7 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags,
                 * disable this firing since we are already reporting
                 * it as an overrun (thanks to bump_cpu_timer above).
                 */
+               spin_unlock(&p->sighand->siglock);
                read_unlock(&tasklist_lock);
                goto out;
        }
@@ -817,11 +762,11 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags,
         */
        timer->it.cpu.expires = new_expires;
        if (new_expires.sched != 0 &&
-           (timer->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE &&
            cpu_time_before(timer->it_clock, val, new_expires)) {
-               arm_timer(timer, val);
+               arm_timer(timer);
        }
 
+       spin_unlock(&p->sighand->siglock);
        read_unlock(&tasklist_lock);
 
        /*
@@ -842,7 +787,6 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags,
        timer->it_overrun = -1;
 
        if (new_expires.sched != 0 &&
-           (timer->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE &&
            !cpu_time_before(timer->it_clock, val, new_expires)) {
                /*
                 * The designated time already passed, so we notify
@@ -856,12 +800,12 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags,
  out:
        if (old) {
                sample_to_timespec(timer->it_clock,
-                                  timer->it.cpu.incr, &old->it_interval);
+                                  old_incr, &old->it_interval);
        }
        return ret;
 }
 
-void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
+static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
 {
        union cpu_time_count now;
        struct task_struct *p = timer->it.cpu.task;
@@ -897,7 +841,7 @@ void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
                clear_dead = p->exit_state;
        } else {
                read_lock(&tasklist_lock);
-               if (unlikely(p->signal == NULL)) {
+               if (unlikely(p->sighand == NULL)) {
                        /*
                         * The process has been reaped.
                         * We can't even collect a sample any more.
@@ -916,25 +860,6 @@ void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
                read_unlock(&tasklist_lock);
        }
 
-       if ((timer->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
-               if (timer->it.cpu.incr.sched == 0 &&
-                   cpu_time_before(timer->it_clock,
-                                   timer->it.cpu.expires, now)) {
-                       /*
-                        * Do-nothing timer expired and has no reload,
-                        * so it's as if it was never set.
-                        */
-                       timer->it.cpu.expires.sched = 0;
-                       itp->it_value.tv_sec = itp->it_value.tv_nsec = 0;
-                       return;
-               }
-               /*
-                * Account for any expirations and reloads that should
-                * have happened.
-                */
-               bump_cpu_timer(timer, now);
-       }
-
        if (unlikely(clear_dead)) {
                /*
                 * We've noticed that the thread is dead, but
@@ -974,12 +899,12 @@ static void check_thread_timers(struct task_struct *tsk,
        unsigned long soft;
 
        maxfire = 20;
-       tsk->cputime_expires.prof_exp = cputime_zero;
+       tsk->cputime_expires.prof_exp = 0;
        while (!list_empty(timers)) {
                struct cpu_timer_list *t = list_first_entry(timers,
                                                      struct cpu_timer_list,
                                                      entry);
-               if (!--maxfire || cputime_lt(prof_ticks(tsk), t->expires.cpu)) {
+               if (!--maxfire || prof_ticks(tsk) < t->expires.cpu) {
                        tsk->cputime_expires.prof_exp = t->expires.cpu;
                        break;
                }
@@ -989,12 +914,12 @@ static void check_thread_timers(struct task_struct *tsk,
 
        ++timers;
        maxfire = 20;
-       tsk->cputime_expires.virt_exp = cputime_zero;
+       tsk->cputime_expires.virt_exp = 0;
        while (!list_empty(timers)) {
                struct cpu_timer_list *t = list_first_entry(timers,
                                                      struct cpu_timer_list,
                                                      entry);
-               if (!--maxfire || cputime_lt(virt_ticks(tsk), t->expires.cpu)) {
+               if (!--maxfire || virt_ticks(tsk) < t->expires.cpu) {
                        tsk->cputime_expires.virt_exp = t->expires.cpu;
                        break;
                }
@@ -1050,17 +975,14 @@ static void check_thread_timers(struct task_struct *tsk,
        }
 }
 
-static void stop_process_timers(struct task_struct *tsk)
+static void stop_process_timers(struct signal_struct *sig)
 {
-       struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
+       struct thread_group_cputimer *cputimer = &sig->cputimer;
        unsigned long flags;
 
-       if (!cputimer->running)
-               return;
-
-       spin_lock_irqsave(&cputimer->lock, flags);
+       raw_spin_lock_irqsave(&cputimer->lock, flags);
        cputimer->running = 0;
-       spin_unlock_irqrestore(&cputimer->lock, flags);
+       raw_spin_unlock_irqrestore(&cputimer->lock, flags);
 }
 
 static u32 onecputick;
@@ -1068,20 +990,19 @@ 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)
 {
-       if (cputime_eq(it->expires, cputime_zero))
+       if (!it->expires)
                return;
 
-       if (cputime_ge(cur_time, it->expires)) {
-               if (!cputime_eq(it->incr, cputime_zero)) {
-                       it->expires = cputime_add(it->expires, it->incr);
+       if (cur_time >= it->expires) {
+               if (it->incr) {
+                       it->expires += it->incr;
                        it->error += it->incr_error;
                        if (it->error >= onecputick) {
-                               it->expires = cputime_sub(it->expires,
-                                                         cputime_one_jiffy);
+                               it->expires -= cputime_one_jiffy;
                                it->error -= onecputick;
                        }
                } else {
-                       it->expires = cputime_zero;
+                       it->expires = 0;
                }
 
                trace_itimer_expire(signo == SIGPROF ?
@@ -1090,13 +1011,26 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,
                __group_send_sig_info(signo, SEND_SIG_PRIV, tsk);
        }
 
-       if (!cputime_eq(it->expires, cputime_zero) &&
-           (cputime_eq(*expires, cputime_zero) ||
-            cputime_lt(it->expires, *expires))) {
+       if (it->expires && (!*expires || it->expires < *expires)) {
                *expires = it->expires;
        }
 }
 
+/**
+ * task_cputime_zero - Check a task_cputime struct for all zero fields.
+ *
+ * @cputime:   The struct to compare.
+ *
+ * Checks @cputime to see if all fields are zero.  Returns true if all fields
+ * are zero, false if any field is nonzero.
+ */
+static inline int task_cputime_zero(const struct task_cputime *cputime)
+{
+       if (!cputime->utime && !cputime->stime && !cputime->sum_exec_runtime)
+               return 1;
+       return 0;
+}
+
 /*
  * 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
@@ -1114,32 +1048,19 @@ static void check_process_timers(struct task_struct *tsk,
        unsigned long soft;
 
        /*
-        * Don't sample the current process CPU clocks if there are no timers.
-        */
-       if (list_empty(&timers[CPUCLOCK_PROF]) &&
-           cputime_eq(sig->it[CPUCLOCK_PROF].expires, cputime_zero) &&
-           sig->rlim[RLIMIT_CPU].rlim_cur == RLIM_INFINITY &&
-           list_empty(&timers[CPUCLOCK_VIRT]) &&
-           cputime_eq(sig->it[CPUCLOCK_VIRT].expires, cputime_zero) &&
-           list_empty(&timers[CPUCLOCK_SCHED])) {
-               stop_process_timers(tsk);
-               return;
-       }
-
-       /*
         * Collect the current process totals.
         */
        thread_group_cputimer(tsk, &cputime);
        utime = cputime.utime;
-       ptime = cputime_add(utime, cputime.stime);
+       ptime = utime + cputime.stime;
        sum_sched_runtime = cputime.sum_exec_runtime;
        maxfire = 20;
-       prof_expires = cputime_zero;
+       prof_expires = 0;
        while (!list_empty(timers)) {
                struct cpu_timer_list *tl = list_first_entry(timers,
                                                      struct cpu_timer_list,
                                                      entry);
-               if (!--maxfire || cputime_lt(ptime, tl->expires.cpu)) {
+               if (!--maxfire || ptime < tl->expires.cpu) {
                        prof_expires = tl->expires.cpu;
                        break;
                }
@@ -1149,12 +1070,12 @@ static void check_process_timers(struct task_struct *tsk,
 
        ++timers;
        maxfire = 20;
-       virt_expires = cputime_zero;
+       virt_expires = 0;
        while (!list_empty(timers)) {
                struct cpu_timer_list *tl = list_first_entry(timers,
                                                      struct cpu_timer_list,
                                                      entry);
-               if (!--maxfire || cputime_lt(utime, tl->expires.cpu)) {
+               if (!--maxfire || utime < tl->expires.cpu) {
                        virt_expires = tl->expires.cpu;
                        break;
                }
@@ -1209,24 +1130,16 @@ static void check_process_timers(struct task_struct *tsk,
                        }
                }
                x = secs_to_cputime(soft);
-               if (cputime_eq(prof_expires, cputime_zero) ||
-                   cputime_lt(x, prof_expires)) {
+               if (!prof_expires || x < prof_expires) {
                        prof_expires = x;
                }
        }
 
-       if (!cputime_eq(prof_expires, cputime_zero) &&
-           (cputime_eq(sig->cputime_expires.prof_exp, cputime_zero) ||
-            cputime_gt(sig->cputime_expires.prof_exp, prof_expires)))
-               sig->cputime_expires.prof_exp = prof_expires;
-       if (!cputime_eq(virt_expires, cputime_zero) &&
-           (cputime_eq(sig->cputime_expires.virt_exp, cputime_zero) ||
-            cputime_gt(sig->cputime_expires.virt_exp, virt_expires)))
-               sig->cputime_expires.virt_exp = virt_expires;
-       if (sched_expires != 0 &&
-           (sig->cputime_expires.sched_exp == 0 ||
-            sig->cputime_expires.sched_exp > sched_expires))
-               sig->cputime_expires.sched_exp = sched_expires;
+       sig->cputime_expires.prof_exp = prof_expires;
+       sig->cputime_expires.virt_exp = virt_expires;
+       sig->cputime_expires.sched_exp = sched_expires;
+       if (task_cputime_zero(&sig->cputime_expires))
+               stop_process_timers(sig);
 }
 
 /*
@@ -1255,9 +1168,10 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)
                        goto out;
                }
                read_lock(&tasklist_lock); /* arm_timer needs it.  */
+               spin_lock(&p->sighand->siglock);
        } else {
                read_lock(&tasklist_lock);
-               if (unlikely(p->signal == NULL)) {
+               if (unlikely(p->sighand == NULL)) {
                        /*
                         * The process has been reaped.
                         * We can't even collect a sample any more.
@@ -1275,6 +1189,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)
                        clear_dead_task(timer, now);
                        goto out_unlock;
                }
+               spin_lock(&p->sighand->siglock);
                cpu_timer_sample_group(timer->it_clock, p, &now);
                bump_cpu_timer(timer, now);
                /* Leave the tasklist_lock locked for the call below.  */
@@ -1283,7 +1198,9 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)
        /*
         * Now re-arm for the new expiry time.
         */
-       arm_timer(timer, now);
+       BUG_ON(!irqs_disabled());
+       arm_timer(timer);
+       spin_unlock(&p->sighand->siglock);
 
 out_unlock:
        read_unlock(&tasklist_lock);
@@ -1295,23 +1212,6 @@ out:
 }
 
 /**
- * task_cputime_zero - Check a task_cputime struct for all zero fields.
- *
- * @cputime:   The struct to compare.
- *
- * Checks @cputime to see if all fields are zero.  Returns true if all fields
- * are zero, false if any field is nonzero.
- */
-static inline int task_cputime_zero(const struct task_cputime *cputime)
-{
-       if (cputime_eq(cputime->utime, cputime_zero) &&
-           cputime_eq(cputime->stime, cputime_zero) &&
-           cputime->sum_exec_runtime == 0)
-               return 1;
-       return 0;
-}
-
-/**
  * task_cputime_expired - Compare two task_cputime entities.
  *
  * @sample:    The task_cputime structure to be checked for expiration.
@@ -1324,12 +1224,9 @@ static inline int task_cputime_zero(const struct task_cputime *cputime)
 static inline int task_cputime_expired(const struct task_cputime *sample,
                                        const struct task_cputime *expires)
 {
-       if (!cputime_eq(expires->utime, cputime_zero) &&
-           cputime_ge(sample->utime, expires->utime))
+       if (expires->utime && sample->utime >= expires->utime)
                return 1;
-       if (!cputime_eq(expires->stime, cputime_zero) &&
-           cputime_ge(cputime_add(sample->utime, sample->stime),
-                      expires->stime))
+       if (expires->stime && sample->utime + sample->stime >= expires->stime)
                return 1;
        if (expires->sum_exec_runtime != 0 &&
            sample->sum_exec_runtime >= expires->sum_exec_runtime)
@@ -1351,10 +1248,6 @@ static inline int fastpath_timer_check(struct task_struct *tsk)
 {
        struct signal_struct *sig;
 
-       /* tsk == current, ensure it is safe to use ->signal/sighand */
-       if (unlikely(tsk->exit_state))
-               return 0;
-
        if (!task_cputime_zero(&tsk->cputime_expires)) {
                struct task_cputime task_sample = {
                        .utime = tsk->utime,
@@ -1367,10 +1260,13 @@ static inline int fastpath_timer_check(struct task_struct *tsk)
        }
 
        sig = tsk->signal;
-       if (!task_cputime_zero(&sig->cputime_expires)) {
+       if (sig->cputimer.running) {
                struct task_cputime group_sample;
 
-               thread_group_cputimer(tsk, &group_sample);
+               raw_spin_lock(&sig->cputimer.lock);
+               group_sample = sig->cputimer.cputime;
+               raw_spin_unlock(&sig->cputimer.lock);
+
                if (task_cputime_expired(&group_sample, &sig->cputime_expires))
                        return 1;
        }
@@ -1387,6 +1283,7 @@ void run_posix_cpu_timers(struct task_struct *tsk)
 {
        LIST_HEAD(firing);
        struct k_itimer *timer, *next;
+       unsigned long flags;
 
        BUG_ON(!irqs_disabled());
 
@@ -1397,14 +1294,20 @@ void run_posix_cpu_timers(struct task_struct *tsk)
        if (!fastpath_timer_check(tsk))
                return;
 
-       spin_lock(&tsk->sighand->siglock);
+       if (!lock_task_sighand(tsk, &flags))
+               return;
        /*
         * Here we take off tsk->signal->cpu_timers[N] and
         * tsk->cpu_timers[N] all the timers that are firing, and
         * put them on the firing list.
         */
        check_thread_timers(tsk, &firing);
-       check_process_timers(tsk, &firing);
+       /*
+        * If there are any active process wide timers (POSIX 1.b, itimers,
+        * RLIMIT_CPU) cputimer must be running.
+        */
+       if (tsk->signal->cputimer.running)
+               check_process_timers(tsk, &firing);
 
        /*
         * We must release these locks before taking any timer's lock.
@@ -1414,11 +1317,11 @@ void run_posix_cpu_timers(struct task_struct *tsk)
         * that gets the timer lock before we do will give it up and
         * spin until we've taken care of that timer below.
         */
-       spin_unlock(&tsk->sighand->siglock);
+       unlock_task_sighand(tsk, &flags);
 
        /*
         * Now that all the timers on our list have the firing flag,
-        * noone will touch their list entries but us.  We'll take
+        * no one will touch their list entries but us.  We'll take
         * each timer's lock before clearing its firing flag, so no
         * timer call will interfere.
         */
@@ -1458,18 +1361,18 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
                 * it to be relative, *newval argument is relative and we update
                 * it to be absolute.
                 */
-               if (!cputime_eq(*oldval, cputime_zero)) {
-                       if (cputime_le(*oldval, now.cpu)) {
+               if (*oldval) {
+                       if (*oldval <= now.cpu) {
                                /* Just about to fire. */
                                *oldval = cputime_one_jiffy;
                        } else {
-                               *oldval = cputime_sub(*oldval, now.cpu);
+                               *oldval -= now.cpu;
                        }
                }
 
-               if (cputime_eq(*newval, cputime_zero))
+               if (!*newval)
                        return;
-               *newval = cputime_add(*newval, now.cpu);
+               *newval += now.cpu;
        }
 
        /*
@@ -1519,8 +1422,10 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
                while (!signal_pending(current)) {
                        if (timer.it.cpu.expires.sched == 0) {
                                /*
-                                * Our timer fired and was reset.
+                                * Our timer fired and was reset, below
+                                * deletion can not fail.
                                 */
+                               posix_cpu_timer_del(&timer);
                                spin_unlock_irq(&timer.it_lock);
                                return 0;
                        }
@@ -1538,9 +1443,26 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
                 * We were interrupted by a signal.
                 */
                sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
-               posix_cpu_timer_set(&timer, 0, &zero_it, it);
+               error = posix_cpu_timer_set(&timer, 0, &zero_it, it);
+               if (!error) {
+                       /*
+                        * Timer is now unarmed, deletion can not fail.
+                        */
+                       posix_cpu_timer_del(&timer);
+               }
                spin_unlock_irq(&timer.it_lock);
 
+               while (error == TIMER_RETRY) {
+                       /*
+                        * We need to handle case when timer was or is in the
+                        * middle of firing. In other cases we already freed
+                        * resources.
+                        */
+                       spin_lock_irq(&timer.it_lock);
+                       error = posix_cpu_timer_del(&timer);
+                       spin_unlock_irq(&timer.it_lock);
+               }
+
                if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) {
                        /*
                         * It actually did fire already.
@@ -1554,11 +1476,13 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
        return error;
 }
 
-int posix_cpu_nsleep(const clockid_t which_clock, int flags,
-                    struct timespec *rqtp, struct timespec __user *rmtp)
+static long posix_cpu_nsleep_restart(struct restart_block *restart_block);
+
+static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
+                           struct timespec *rqtp, struct timespec __user *rmtp)
 {
        struct restart_block *restart_block =
-           &current_thread_info()->restart_block;
+               &current_thread_info()->restart_block;
        struct itimerspec it;
        int error;
 
@@ -1574,56 +1498,47 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
 
        if (error == -ERESTART_RESTARTBLOCK) {
 
-               if (flags & TIMER_ABSTIME)
+               if (flags & TIMER_ABSTIME)
                        return -ERESTARTNOHAND;
                /*
-                * Report back to the user the time still remaining.
-                */
-               if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
+                * Report back to the user the time still remaining.
+                */
+               if (rmtp && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
                        return -EFAULT;
 
                restart_block->fn = posix_cpu_nsleep_restart;
-               restart_block->arg0 = which_clock;
-               restart_block->arg1 = (unsigned long) rmtp;
-               restart_block->arg2 = rqtp->tv_sec;
-               restart_block->arg3 = rqtp->tv_nsec;
+               restart_block->nanosleep.clockid = which_clock;
+               restart_block->nanosleep.rmtp = rmtp;
+               restart_block->nanosleep.expires = timespec_to_ns(rqtp);
        }
        return error;
 }
 
-long posix_cpu_nsleep_restart(struct restart_block *restart_block)
+static long posix_cpu_nsleep_restart(struct restart_block *restart_block)
 {
-       clockid_t which_clock = restart_block->arg0;
-       struct timespec __user *rmtp;
+       clockid_t which_clock = restart_block->nanosleep.clockid;
        struct timespec t;
        struct itimerspec it;
        int error;
 
-       rmtp = (struct timespec __user *) restart_block->arg1;
-       t.tv_sec = restart_block->arg2;
-       t.tv_nsec = restart_block->arg3;
+       t = ns_to_timespec(restart_block->nanosleep.expires);
 
-       restart_block->fn = do_no_restart_syscall;
        error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it);
 
        if (error == -ERESTART_RESTARTBLOCK) {
+               struct timespec __user *rmtp = restart_block->nanosleep.rmtp;
                /*
-                * Report back to the user the time still remaining.
-                */
-               if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
+                * Report back to the user the time still remaining.
+                */
+               if (rmtp && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
                        return -EFAULT;
 
-               restart_block->fn = posix_cpu_nsleep_restart;
-               restart_block->arg0 = which_clock;
-               restart_block->arg1 = (unsigned long) rmtp;
-               restart_block->arg2 = t.tv_sec;
-               restart_block->arg3 = t.tv_nsec;
+               restart_block->nanosleep.expires = timespec_to_ns(&t);
        }
        return error;
 
 }
 
-
 #define PROCESS_CLOCK  MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED)
 #define THREAD_CLOCK   MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED)
 
@@ -1667,38 +1582,37 @@ static int thread_cpu_timer_create(struct k_itimer *timer)
        timer->it_clock = THREAD_CLOCK;
        return posix_cpu_timer_create(timer);
 }
-static int thread_cpu_nsleep(const clockid_t which_clock, int flags,
-                             struct timespec *rqtp, struct timespec __user *rmtp)
-{
-       return -EINVAL;
-}
-static long thread_cpu_nsleep_restart(struct restart_block *restart_block)
-{
-       return -EINVAL;
-}
+
+struct k_clock clock_posix_cpu = {
+       .clock_getres   = posix_cpu_clock_getres,
+       .clock_set      = posix_cpu_clock_set,
+       .clock_get      = posix_cpu_clock_get,
+       .timer_create   = posix_cpu_timer_create,
+       .nsleep         = posix_cpu_nsleep,
+       .nsleep_restart = posix_cpu_nsleep_restart,
+       .timer_set      = posix_cpu_timer_set,
+       .timer_del      = posix_cpu_timer_del,
+       .timer_get      = posix_cpu_timer_get,
+};
 
 static __init int init_posix_cpu_timers(void)
 {
        struct k_clock process = {
-               .clock_getres = process_cpu_clock_getres,
-               .clock_get = process_cpu_clock_get,
-               .clock_set = do_posix_clock_nosettime,
-               .timer_create = process_cpu_timer_create,
-               .nsleep = process_cpu_nsleep,
-               .nsleep_restart = process_cpu_nsleep_restart,
+               .clock_getres   = process_cpu_clock_getres,
+               .clock_get      = process_cpu_clock_get,
+               .timer_create   = process_cpu_timer_create,
+               .nsleep         = process_cpu_nsleep,
+               .nsleep_restart = process_cpu_nsleep_restart,
        };
        struct k_clock thread = {
-               .clock_getres = thread_cpu_clock_getres,
-               .clock_get = thread_cpu_clock_get,
-               .clock_set = do_posix_clock_nosettime,
-               .timer_create = thread_cpu_timer_create,
-               .nsleep = thread_cpu_nsleep,
-               .nsleep_restart = thread_cpu_nsleep_restart,
+               .clock_getres   = thread_cpu_clock_getres,
+               .clock_get      = thread_cpu_clock_get,
+               .timer_create   = thread_cpu_timer_create,
        };
        struct timespec ts;
 
-       register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
-       register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &thread);
+       posix_timers_register_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
+       posix_timers_register_clock(CLOCK_THREAD_CPUTIME_ID, &thread);
 
        cputime_to_timespec(cputime_one_jiffy, &ts);
        onecputick = ts.tv_nsec;