[PATCH] futex: Apply recent futex fixes to futex_compat
[powerpc.git] / kernel / posix-cpu-timers.c
index abf6990..d38d9ec 100644 (file)
@@ -555,9 +555,6 @@ static void arm_timer(struct k_itimer *timer, union cpu_time_count now)
        struct cpu_timer_list *next;
        unsigned long i;
 
-       if (CPUCLOCK_PERTHREAD(timer->it_clock) && (p->flags & PF_EXITING))
-               return;
-
        head = (CPUCLOCK_PERTHREAD(timer->it_clock) ?
                p->cpu_timers : p->signal->cpu_timers);
        head += CPUCLOCK_WHICH(timer->it_clock);
@@ -1173,6 +1170,9 @@ static void check_process_timers(struct task_struct *tsk,
                }
                t = tsk;
                do {
+                       if (unlikely(t->flags & PF_EXITING))
+                               continue;
+
                        ticks = cputime_add(cputime_add(t->utime, t->stime),
                                            prof_left);
                        if (!cputime_eq(prof_expires, cputime_zero) &&
@@ -1193,11 +1193,7 @@ static void check_process_timers(struct task_struct *tsk,
                                              t->it_sched_expires > sched)) {
                                t->it_sched_expires = sched;
                        }
-
-                       do {
-                               t = next_thread(t);
-                       } while (unlikely(t->flags & PF_EXITING));
-               } while (t != tsk);
+               } while ((t = next_thread(t)) != tsk);
        }
 }
 
@@ -1289,30 +1285,30 @@ void run_posix_cpu_timers(struct task_struct *tsk)
 
 #undef UNEXPIRED
 
-       BUG_ON(tsk->exit_state);
-
        /*
         * Double-check with locks held.
         */
        read_lock(&tasklist_lock);
-       spin_lock(&tsk->sighand->siglock);
+       if (likely(tsk->signal != NULL)) {
+               spin_lock(&tsk->sighand->siglock);
 
-       /*
-        * Here we take off tsk->cpu_timers[N] and tsk->signal->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);
+               /*
+                * Here we take off tsk->cpu_timers[N] and tsk->signal->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.
-        */
-       spin_unlock(&tsk->sighand->siglock);
+               /*
+                * 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);
+       }
        read_unlock(&tasklist_lock);
 
        /*
@@ -1400,7 +1396,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 static long posix_cpu_clock_nanosleep_restart(struct restart_block *);
 
 int posix_cpu_nsleep(const clockid_t which_clock, int flags,
-                    struct timespec *rqtp)
+                    struct timespec *rqtp, struct timespec __user *rmtp)
 {
        struct restart_block *restart_block =
            &current_thread_info()->restart_block;
@@ -1425,7 +1421,6 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
        error = posix_cpu_timer_create(&timer);
        timer.it_process = current;
        if (!error) {
-               struct timespec __user *rmtp;
                static struct itimerspec zero_it;
                struct itimerspec it = { .it_value = *rqtp,
                                         .it_interval = {} };
@@ -1472,7 +1467,6 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
                /*
                 * Report back to the user the time still remaining.
                 */
-               rmtp = (struct timespec __user *) restart_block->arg1;
                if (rmtp != NULL && !(flags & TIMER_ABSTIME) &&
                    copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
                        return -EFAULT;
@@ -1480,6 +1474,7 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
                restart_block->fn = posix_cpu_clock_nanosleep_restart;
                /* Caller already set restart_block->arg1 */
                restart_block->arg0 = which_clock;
+               restart_block->arg1 = (unsigned long) rmtp;
                restart_block->arg2 = rqtp->tv_sec;
                restart_block->arg3 = rqtp->tv_nsec;
 
@@ -1493,10 +1488,15 @@ static long
 posix_cpu_clock_nanosleep_restart(struct restart_block *restart_block)
 {
        clockid_t which_clock = restart_block->arg0;
-       struct timespec t = { .tv_sec = restart_block->arg2,
-                             .tv_nsec = restart_block->arg3 };
+       struct timespec __user *rmtp;
+       struct timespec t;
+
+       rmtp = (struct timespec __user *) restart_block->arg1;
+       t.tv_sec = restart_block->arg2;
+       t.tv_nsec = restart_block->arg3;
+
        restart_block->fn = do_no_restart_syscall;
-       return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t);
+       return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t, rmtp);
 }
 
 
@@ -1519,9 +1519,10 @@ static int process_cpu_timer_create(struct k_itimer *timer)
        return posix_cpu_timer_create(timer);
 }
 static int process_cpu_nsleep(const clockid_t which_clock, int flags,
-                             struct timespec *rqtp)
+                             struct timespec *rqtp,
+                             struct timespec __user *rmtp)
 {
-       return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp);
+       return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp);
 }
 static int thread_cpu_clock_getres(const clockid_t which_clock,
                                   struct timespec *tp)
@@ -1539,7 +1540,7 @@ static int thread_cpu_timer_create(struct k_itimer *timer)
        return posix_cpu_timer_create(timer);
 }
 static int thread_cpu_nsleep(const clockid_t which_clock, int flags,
-                             struct timespec *rqtp)
+                             struct timespec *rqtp, struct timespec __user *rmtp)
 {
        return -EINVAL;
 }