drop_monitor: dont sleep in atomic context
[firefly-linux-kernel-4.4.55.git] / kernel / signal.c
index ff7678603328b3ba5e00c74dc9fd08bcbf113987..43fee1cf50d01efe3e58a578906b16b6ae92ba07 100644 (file)
@@ -1178,18 +1178,25 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,
 {
        struct sighand_struct *sighand;
 
-       rcu_read_lock();
        for (;;) {
+               local_irq_save(*flags);
+               rcu_read_lock();
                sighand = rcu_dereference(tsk->sighand);
-               if (unlikely(sighand == NULL))
+               if (unlikely(sighand == NULL)) {
+                       rcu_read_unlock();
+                       local_irq_restore(*flags);
                        break;
+               }
 
-               spin_lock_irqsave(&sighand->siglock, *flags);
-               if (likely(sighand == tsk->sighand))
+               spin_lock(&sighand->siglock);
+               if (likely(sighand == tsk->sighand)) {
+                       rcu_read_unlock();
                        break;
-               spin_unlock_irqrestore(&sighand->siglock, *flags);
+               }
+               spin_unlock(&sighand->siglock);
+               rcu_read_unlock();
+               local_irq_restore(*flags);
        }
-       rcu_read_unlock();
 
        return sighand;
 }
@@ -1887,21 +1894,19 @@ static int do_signal_stop(int signr)
                 */
                if (!(sig->flags & SIGNAL_STOP_STOPPED))
                        sig->group_exit_code = signr;
-               else
-                       WARN_ON_ONCE(!task_ptrace(current));
 
                current->group_stop &= ~GROUP_STOP_SIGMASK;
                current->group_stop |= signr | gstop;
                sig->group_stop_count = 1;
                for (t = next_thread(current); t != current;
                     t = next_thread(t)) {
-                       t->group_stop &= ~GROUP_STOP_SIGMASK;
                        /*
                         * Setting state to TASK_STOPPED for a group
                         * stop is always done with the siglock held,
                         * so this check has no races.
                         */
                        if (!(t->flags & PF_EXITING) && !task_is_stopped(t)) {
+                               t->group_stop &= ~GROUP_STOP_SIGMASK;
                                t->group_stop |= signr | gstop;
                                sig->group_stop_count++;
                                signal_wake_up(t, 0);