]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 6 Dec 2015 16:35:05 +0000 (08:35 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 6 Dec 2015 16:35:05 +0000 (08:35 -0800)
Pull scheduler fixes from Thomas Gleixner:
 "This updates contains the following changes:

   - Fix a signal handling regression in the bit wait functions.

   - Avoid false positive warnings in the wakeup path.

   - Initialize the scheduler root domain properly.

   - Handle gtime calculations in proc/$PID/stat proper.

   - Add more documentation for the barriers in try_to_wake_up().

   - Fix a subtle race in try_to_wake_up() which might cause a task to
     be scheduled on two cpus

   - Compile static helper function only when it is used"

* 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  sched/core: Fix an SMP ordering race in try_to_wake_up() vs. schedule()
  sched/core: Better document the try_to_wake_up() barriers
  sched/cputime: Fix invalid gtime in proc
  sched/core: Clear the root_domain cpumasks in init_rootdomain()
  sched/core: Remove false-positive warning from wake_up_process()
  sched/wait: Fix signal handling in bit wait helpers
  sched/rt: Hide the push_irq_work_func() declaration

kernel/sched/core.c
kernel/sched/cputime.c
kernel/sched/rt.c
kernel/sched/sched.h
kernel/sched/wait.c

index 4d568ac9319eaf04c9d00673483678bc5e14f22e..7063c6a0744055c367eb82159677cfe6522b6c60 100644 (file)
@@ -1946,6 +1946,25 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
                goto stat;
 
 #ifdef CONFIG_SMP
+       /*
+        * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be
+        * possible to, falsely, observe p->on_cpu == 0.
+        *
+        * One must be running (->on_cpu == 1) in order to remove oneself
+        * from the runqueue.
+        *
+        *  [S] ->on_cpu = 1;   [L] ->on_rq
+        *      UNLOCK rq->lock
+        *                      RMB
+        *      LOCK   rq->lock
+        *  [S] ->on_rq = 0;    [L] ->on_cpu
+        *
+        * Pairs with the full barrier implied in the UNLOCK+LOCK on rq->lock
+        * from the consecutive calls to schedule(); the first switching to our
+        * task, the second putting it to sleep.
+        */
+       smp_rmb();
+
        /*
         * If the owning (remote) cpu is still in the middle of schedule() with
         * this task as prev, wait until its done referencing the task.
@@ -1953,7 +1972,13 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
        while (p->on_cpu)
                cpu_relax();
        /*
-        * Pairs with the smp_wmb() in finish_lock_switch().
+        * Combined with the control dependency above, we have an effective
+        * smp_load_acquire() without the need for full barriers.
+        *
+        * Pairs with the smp_store_release() in finish_lock_switch().
+        *
+        * This ensures that tasks getting woken will be fully ordered against
+        * their previous state and preserve Program Order.
         */
        smp_rmb();
 
@@ -2039,7 +2064,6 @@ out:
  */
 int wake_up_process(struct task_struct *p)
 {
-       WARN_ON(task_is_stopped_or_traced(p));
        return try_to_wake_up(p, TASK_NORMAL, 0);
 }
 EXPORT_SYMBOL(wake_up_process);
@@ -5847,13 +5871,13 @@ static int init_rootdomain(struct root_domain *rd)
 {
        memset(rd, 0, sizeof(*rd));
 
-       if (!alloc_cpumask_var(&rd->span, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&rd->span, GFP_KERNEL))
                goto out;
-       if (!alloc_cpumask_var(&rd->online, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&rd->online, GFP_KERNEL))
                goto free_span;
-       if (!alloc_cpumask_var(&rd->dlo_mask, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&rd->dlo_mask, GFP_KERNEL))
                goto free_online;
-       if (!alloc_cpumask_var(&rd->rto_mask, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&rd->rto_mask, GFP_KERNEL))
                goto free_dlo_mask;
 
        init_dl_bw(&rd->dl_bw);
index 26a54461bf59ca46ce7f68d7a926b03840ca8711..05de80b48586e9fa3241c708c7e6fd7c9b6fb24a 100644 (file)
@@ -788,6 +788,9 @@ cputime_t task_gtime(struct task_struct *t)
        unsigned int seq;
        cputime_t gtime;
 
+       if (!context_tracking_is_enabled())
+               return t->gtime;
+
        do {
                seq = read_seqbegin(&t->vtime_seqlock);
 
index e3cc16312046689fd04db8748304210c0d9fc8df..8ec86abe0ea188369ee4e7efd21789d8cb127c14 100644 (file)
@@ -64,7 +64,7 @@ static void start_rt_bandwidth(struct rt_bandwidth *rt_b)
        raw_spin_unlock(&rt_b->rt_runtime_lock);
 }
 
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) && defined(HAVE_RT_PUSH_IPI)
 static void push_irq_work_func(struct irq_work *work);
 #endif
 
index efd3bfc7e34722883e2f08ca82f91cffde812963..b242775bf670e116233862c590915e06132485ca 100644 (file)
@@ -1073,6 +1073,9 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev)
         * We must ensure this doesn't happen until the switch is completely
         * finished.
         *
+        * In particular, the load of prev->state in finish_task_switch() must
+        * happen before this.
+        *
         * Pairs with the control dependency and rmb in try_to_wake_up().
         */
        smp_store_release(&prev->on_cpu, 0);
index 052e02672d12428ce1e9e1f7266c7cd754ace5af..f10bd873e6840441ed4750a5eb1c2d462ad0b436 100644 (file)
@@ -583,18 +583,18 @@ EXPORT_SYMBOL(wake_up_atomic_t);
 
 __sched int bit_wait(struct wait_bit_key *word)
 {
-       if (signal_pending_state(current->state, current))
-               return 1;
        schedule();
+       if (signal_pending(current))
+               return -EINTR;
        return 0;
 }
 EXPORT_SYMBOL(bit_wait);
 
 __sched int bit_wait_io(struct wait_bit_key *word)
 {
-       if (signal_pending_state(current->state, current))
-               return 1;
        io_schedule();
+       if (signal_pending(current))
+               return -EINTR;
        return 0;
 }
 EXPORT_SYMBOL(bit_wait_io);
@@ -602,11 +602,11 @@ EXPORT_SYMBOL(bit_wait_io);
 __sched int bit_wait_timeout(struct wait_bit_key *word)
 {
        unsigned long now = READ_ONCE(jiffies);
-       if (signal_pending_state(current->state, current))
-               return 1;
        if (time_after_eq(now, word->timeout))
                return -EAGAIN;
        schedule_timeout(word->timeout - now);
+       if (signal_pending(current))
+               return -EINTR;
        return 0;
 }
 EXPORT_SYMBOL_GPL(bit_wait_timeout);
@@ -614,11 +614,11 @@ EXPORT_SYMBOL_GPL(bit_wait_timeout);
 __sched int bit_wait_io_timeout(struct wait_bit_key *word)
 {
        unsigned long now = READ_ONCE(jiffies);
-       if (signal_pending_state(current->state, current))
-               return 1;
        if (time_after_eq(now, word->timeout))
                return -EAGAIN;
        io_schedule_timeout(word->timeout - now);
+       if (signal_pending(current))
+               return -EINTR;
        return 0;
 }
 EXPORT_SYMBOL_GPL(bit_wait_io_timeout);