]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/posix-cpu-timers.c
Fix accidental implicit cast in HR-timer conversion
[linux-2.6-omap-h63xx.git] / kernel / posix-cpu-timers.c
index 9a7ea049fcdcab38d43203a61d137775e170bd16..153dcb2639c3df614c7862041a9d485b7dbe6614 100644 (file)
@@ -7,50 +7,46 @@
 #include <linux/errno.h>
 #include <linux/math64.h>
 #include <asm/uaccess.h>
+#include <linux/kernel_stat.h>
 
-#ifdef CONFIG_SMP
 /*
- * Allocate the thread_group_cputime structure appropriately for SMP kernels
- * and fill in the current values of the fields.  Called from copy_signal()
- * via thread_group_cputime_clone_thread() when adding a second or subsequent
+ * Allocate the thread_group_cputime structure appropriately and fill in the
+ * current values of the fields.  Called from copy_signal() via
+ * thread_group_cputime_clone_thread() when adding a second or subsequent
  * thread to a thread group.  Assumes interrupts are enabled when called.
  */
-int thread_group_cputime_alloc_smp(struct task_struct *tsk)
+int thread_group_cputime_alloc(struct task_struct *tsk)
 {
        struct signal_struct *sig = tsk->signal;
        struct task_cputime *cputime;
 
        /*
         * If we have multiple threads and we don't already have a
-        * per-CPU task_cputime struct, allocate one and fill it in with
-        * the times accumulated so far.
+        * per-CPU task_cputime struct (checked in the caller), allocate
+        * one and fill it in with the times accumulated so far.  We may
+        * race with another thread so recheck after we pick up the sighand
+        * lock.
         */
-       if (sig->cputime.totals)
-               return 0;
        cputime = alloc_percpu(struct task_cputime);
        if (cputime == NULL)
                return -ENOMEM;
-       read_lock(&tasklist_lock);
        spin_lock_irq(&tsk->sighand->siglock);
        if (sig->cputime.totals) {
                spin_unlock_irq(&tsk->sighand->siglock);
-               read_unlock(&tasklist_lock);
                free_percpu(cputime);
                return 0;
        }
        sig->cputime.totals = cputime;
-       cputime = per_cpu_ptr(sig->cputime.totals, get_cpu());
+       cputime = per_cpu_ptr(sig->cputime.totals, smp_processor_id());
        cputime->utime = tsk->utime;
        cputime->stime = tsk->stime;
        cputime->sum_exec_runtime = tsk->se.sum_exec_runtime;
-       put_cpu_no_resched();
        spin_unlock_irq(&tsk->sighand->siglock);
-       read_unlock(&tasklist_lock);
        return 0;
 }
 
 /**
- * thread_group_cputime_smp - Sum the thread group time fields across all CPUs.
+ * thread_group_cputime - Sum the thread group time fields across all CPUs.
  *
  * @tsk:       The task we use to identify the thread group.
  * @times:     task_cputime structure in which we return the summed fields.
@@ -58,7 +54,7 @@ int thread_group_cputime_alloc_smp(struct task_struct *tsk)
  * Walk the list of CPUs to sum the per-CPU time fields in the thread group
  * time structure.
  */
-void thread_group_cputime_smp(
+void thread_group_cputime(
        struct task_struct *tsk,
        struct task_cputime *times)
 {
@@ -83,8 +79,6 @@ void thread_group_cputime_smp(
        }
 }
 
-#endif /* CONFIG_SMP */
-
 /*
  * Called after updating RLIMIT_CPU to set timer expiration if necessary.
  */
@@ -300,7 +294,7 @@ static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p,
                cpu->cpu = virt_ticks(p);
                break;
        case CPUCLOCK_SCHED:
-               cpu->sched = task_sched_runtime(p);
+               cpu->sched = p->se.sum_exec_runtime + task_delta_exec(p);
                break;
        }
        return 0;
@@ -309,16 +303,15 @@ static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p,
 /*
  * Sample a process (thread group) clock for the given group_leader task.
  * Must be called with tasklist_lock held for reading.
- * Must be called with tasklist_lock held for reading, and p->sighand->siglock.
  */
-static int cpu_clock_sample_group_locked(unsigned int clock_idx,
-                                        struct task_struct *p,
-                                        union cpu_time_count *cpu)
+static int cpu_clock_sample_group(const clockid_t which_clock,
+                                 struct task_struct *p,
+                                 union cpu_time_count *cpu)
 {
        struct task_cputime cputime;
 
        thread_group_cputime(p, &cputime);
-       switch (clock_idx) {
+       switch (which_clock) {
        default:
                return -EINVAL;
        case CPUCLOCK_PROF:
@@ -328,29 +321,12 @@ static int cpu_clock_sample_group_locked(unsigned int clock_idx,
                cpu->cpu = cputime.utime;
                break;
        case CPUCLOCK_SCHED:
-               cpu->sched = thread_group_sched_runtime(p);
+               cpu->sched = cputime.sum_exec_runtime + task_delta_exec(p);
                break;
        }
        return 0;
 }
 
-/*
- * Sample a process (thread group) clock for the given group_leader task.
- * Must be called with tasklist_lock held for reading.
- */
-static int cpu_clock_sample_group(const clockid_t which_clock,
-                                 struct task_struct *p,
-                                 union cpu_time_count *cpu)
-{
-       int ret;
-       unsigned long flags;
-       spin_lock_irqsave(&p->sighand->siglock, flags);
-       ret = cpu_clock_sample_group_locked(CPUCLOCK_WHICH(which_clock), p,
-                                           cpu);
-       spin_unlock_irqrestore(&p->sighand->siglock, flags);
-       return ret;
-}
-
 
 int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
 {
@@ -1324,29 +1300,37 @@ static inline int task_cputime_expired(const struct task_cputime *sample,
  * fastpath_timer_check - POSIX CPU timers fast path.
  *
  * @tsk:       The task (thread) being checked.
- * @sig:       The signal pointer for that task.
  *
- * If there are no timers set return false.  Otherwise snapshot the task and
- * thread group timers, then compare them with the corresponding expiration
- # times.  Returns true if a timer has expired, else returns false.
+ * Check the task and thread group timers.  If both are zero (there are no
+ * timers set) return false.  Otherwise snapshot the task and thread group
+ * timers and compare them with the corresponding expiration times.  Return
+ * true if a timer has expired, else return false.
  */
-static inline int fastpath_timer_check(struct task_struct *tsk,
-                                       struct signal_struct *sig)
+static inline int fastpath_timer_check(struct task_struct *tsk)
 {
-       struct task_cputime task_sample = {
-               .utime = tsk->utime,
-               .stime = tsk->stime,
-               .sum_exec_runtime = tsk->se.sum_exec_runtime
-       };
-       struct task_cputime group_sample;
+       struct signal_struct *sig = tsk->signal;
 
-       if (task_cputime_zero(&tsk->cputime_expires) &&
-           task_cputime_zero(&sig->cputime_expires))
+       if (unlikely(!sig))
                return 0;
-       if (task_cputime_expired(&task_sample, &tsk->cputime_expires))
-               return 1;
-       thread_group_cputime(tsk, &group_sample);
-       return task_cputime_expired(&group_sample, &sig->cputime_expires);
+
+       if (!task_cputime_zero(&tsk->cputime_expires)) {
+               struct task_cputime task_sample = {
+                       .utime = tsk->utime,
+                       .stime = tsk->stime,
+                       .sum_exec_runtime = tsk->se.sum_exec_runtime
+               };
+
+               if (task_cputime_expired(&task_sample, &tsk->cputime_expires))
+                       return 1;
+       }
+       if (!task_cputime_zero(&sig->cputime_expires)) {
+               struct task_cputime group_sample;
+
+               thread_group_cputime(tsk, &group_sample);
+               if (task_cputime_expired(&group_sample, &sig->cputime_expires))
+                       return 1;
+       }
+       return 0;
 }
 
 /*
@@ -1358,43 +1342,34 @@ void run_posix_cpu_timers(struct task_struct *tsk)
 {
        LIST_HEAD(firing);
        struct k_itimer *timer, *next;
-       struct signal_struct *sig;
-       struct sighand_struct *sighand;
-       unsigned long flags;
 
        BUG_ON(!irqs_disabled());
 
-       /* Pick up tsk->signal and make sure it's valid. */
-       sig = tsk->signal;
        /*
         * The fast path checks that there are no expired thread or thread
-        * group timers.  If that's so, just return.  Also check that
-        * tsk->signal is non-NULL; this probably can't happen but cover the
-        * possibility anyway.
+        * group timers.  If that's so, just return.
         */
-       if (unlikely(!sig) || !fastpath_timer_check(tsk, sig))
+       if (!fastpath_timer_check(tsk))
                return;
 
-       sighand = lock_task_sighand(tsk, &flags);
-       if (likely(sighand)) {
-               /*
-                * 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);
+       spin_lock(&tsk->sighand->siglock);
+       /*
+        * 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);
 
-               /*
-                * We must release these locks before taking any timer's lock.
-                * There is a potential race with timer deletion here, as the
-                * siglock now protects our private firing list.  We have set
-                * the firing flag in each timer, so that a deletion attempt
-                * that gets the timer lock before we do will give it up and
-                * spin until we've taken care of that timer below.
-                */
-       }
-       unlock_task_sighand(tsk, &flags);
+       /*
+        * We must release these locks before taking any timer's lock.
+        * There is a potential race with timer deletion here, as the
+        * siglock now protects our private firing list.  We have set
+        * the firing flag in each timer, so that a deletion attempt
+        * 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);
 
        /*
         * Now that all the timers on our list have the firing flag,
@@ -1433,7 +1408,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
        struct list_head *head;
 
        BUG_ON(clock_idx == CPUCLOCK_SCHED);
-       cpu_clock_sample_group_locked(clock_idx, tsk, &now);
+       cpu_clock_sample_group(clock_idx, tsk, &now);
 
        if (oldval) {
                if (!cputime_eq(*oldval, cputime_zero)) {