xfs: remove nr_to_write writeback windup.
[safe/jmp/linux-2.6] / kernel / posix-cpu-timers.c
index 7c7166f..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.
@@ -550,7 +550,7 @@ static inline int expires_gt(cputime_t expires, cputime_t 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)
 {
@@ -569,9 +569,6 @@ static void arm_timer(struct k_itimer *timer)
        }
        head += CPUCLOCK_WHICH(timer->it_clock);
 
-       BUG_ON(!irqs_disabled());
-       spin_lock(&p->sighand->siglock);
-
        listpos = head;
        list_for_each_entry(next, head, entry) {
                if (cpu_time_before(timer->it_clock, nt->expires, next->expires))
@@ -606,8 +603,6 @@ static void arm_timer(struct k_itimer *timer)
                        break;
                }
        }
-
-       spin_unlock(&p->sighand->siglock);
 }
 
 /*
@@ -615,7 +610,12 @@ static void arm_timer(struct k_itimer *timer)
  */
 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.
@@ -676,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)) {
@@ -691,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;
@@ -707,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)) {
@@ -714,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
@@ -768,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;
        }
@@ -783,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);
        }
 
+       spin_unlock(&p->sighand->siglock);
        read_unlock(&tasklist_lock);
 
        /*
@@ -808,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
@@ -822,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;
 }
@@ -863,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.
@@ -882,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
@@ -1016,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);
@@ -1063,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
@@ -1080,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);
@@ -1181,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);
 }
 
 /*
@@ -1221,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.
@@ -1241,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.  */
@@ -1249,7 +1226,9 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)
        /*
         * Now re-arm for the new expiry time.
         */
+       BUG_ON(!irqs_disabled());
        arm_timer(timer);
+       spin_unlock(&p->sighand->siglock);
 
 out_unlock:
        read_unlock(&tasklist_lock);
@@ -1261,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.
@@ -1333,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);
@@ -1370,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.