xfs: remove nr_to_write writeback windup.
[safe/jmp/linux-2.6] / kernel / posix-cpu-timers.c
index d01e0a3..9829646 100644 (file)
@@ -363,7 +363,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);
@@ -439,7 +439,7 @@ int posix_cpu_timer_del(struct k_itimer *timer)
 
        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.
@@ -547,101 +547,62 @@ static inline int expires_gt(cputime_t expires, cputime_t new_exp)
               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
- * 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 +610,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.
@@ -710,7 +676,7 @@ 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 +691,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 +707,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 +715,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 +768,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 +784,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 +809,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,7 +822,7 @@ 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;
 }
@@ -897,7 +863,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 +882,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
@@ -1050,14 +997,11 @@ 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);
        cputimer->running = 0;
        spin_unlock_irqrestore(&cputimer->lock, flags);
@@ -1097,6 +1041,23 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,
        }
 }
 
+/**
+ * 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;
+}
+
 /*
  * 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,19 +1075,6 @@ 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);
@@ -1215,18 +1163,11 @@ static void check_process_timers(struct task_struct *tsk,
                }
        }
 
-       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 +1196,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 +1217,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 +1226,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 +1240,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.
@@ -1367,7 +1295,7 @@ 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);
@@ -1404,7 +1332,12 @@ void run_posix_cpu_timers(struct task_struct *tsk)
         * 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.