Merge branch 'for-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 20 Feb 2013 06:01:33 +0000 (22:01 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 20 Feb 2013 06:01:33 +0000 (22:01 -0800)
Pull workqueue changes from Tejun Heo:
 "A lot of reorganization is going on mostly to prepare for worker pools
  with custom attributes so that workqueue can replace custom pool
  implementations in places including writeback and btrfs and make CPU
  assignment in crypto more flexible.

  workqueue evolved from purely per-cpu design and implementation, so
  there are a lot of assumptions regarding being bound to CPUs and even
  unbound workqueues are implemented as an extension of the model -
  workqueues running on the special unbound CPU.  Bulk of changes this
  round are about promoting worker_pools as the top level abstraction
  replacing global_cwq (global cpu workqueue).  At this point, I'm
  fairly confident about getting custom worker pools working pretty soon
  and ready for the next merge window.

  Lai's patches are replacing the convoluted mb() dancing workqueue has
  been doing with much simpler mechanism which only depends on
  assignment atomicity of long.  For details, please read the commit
  message of 0b3dae68ac ("workqueue: simplify is-work-item-queued-here
  test").  While the change ends up adding one pointer to struct
  delayed_work, the inflation in percentage is less than five percent
  and it decouples delayed_work logic a lot more cleaner from usual work
  handling, removes the unusual memory barrier dancing, and allows for
  further simplification, so I think the trade-off is acceptable.

  There will be two more workqueue related pull requests and there are
  some shared commits among them.  I'll write further pull requests
  assuming this pull request is pulled first."

* 'for-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq: (37 commits)
  workqueue: un-GPL function delayed_work_timer_fn()
  workqueue: rename cpu_workqueue to pool_workqueue
  workqueue: reimplement is_chained_work() using current_wq_worker()
  workqueue: fix is_chained_work() regression
  workqueue: pick cwq instead of pool in __queue_work()
  workqueue: make get_work_pool_id() cheaper
  workqueue: move nr_running into worker_pool
  workqueue: cosmetic update in try_to_grab_pending()
  workqueue: simplify is-work-item-queued-here test
  workqueue: make work->data point to pool after try_to_grab_pending()
  workqueue: add delayed_work->wq to simplify reentrancy handling
  workqueue: make work_busy() test WORK_STRUCT_PENDING first
  workqueue: replace WORK_CPU_NONE/LAST with WORK_CPU_END
  workqueue: post global_cwq removal cleanups
  workqueue: rename nr_running variables
  workqueue: remove global_cwq
  workqueue: remove worker_pool->gcwq
  workqueue: replace for_each_worker_pool() with for_each_std_worker_pool()
  workqueue: make freezing/thawing per-pool
  workqueue: make hotplug processing per-pool
  ...

1  2 
kernel/async.c
kernel/sched/core.c

diff --combined kernel/async.c
@@@ -57,6 -57,8 +57,8 @@@ asynchronous and synchronous parts of t
  #include <linux/slab.h>
  #include <linux/workqueue.h>
  
+ #include "workqueue_internal.h"
  static async_cookie_t next_cookie = 1;
  
  #define MAX_WORK      32768
@@@ -86,27 -88,18 +88,27 @@@ static atomic_t entry_count
   */
  static async_cookie_t  __lowest_in_progress(struct async_domain *running)
  {
 +      async_cookie_t first_running = next_cookie;     /* infinity value */
 +      async_cookie_t first_pending = next_cookie;     /* ditto */
        struct async_entry *entry;
  
 +      /*
 +       * Both running and pending lists are sorted but not disjoint.
 +       * Take the first cookies from both and return the min.
 +       */
        if (!list_empty(&running->domain)) {
                entry = list_first_entry(&running->domain, typeof(*entry), list);
 -              return entry->cookie;
 +              first_running = entry->cookie;
        }
  
 -      list_for_each_entry(entry, &async_pending, list)
 -              if (entry->running == running)
 -                      return entry->cookie;
 +      list_for_each_entry(entry, &async_pending, list) {
 +              if (entry->running == running) {
 +                      first_pending = entry->cookie;
 +                      break;
 +              }
 +      }
  
 -      return next_cookie;     /* "infinity" value */
 +      return min(first_running, first_pending);
  }
  
  static async_cookie_t  lowest_in_progress(struct async_domain *running)
@@@ -127,17 -120,13 +129,17 @@@ static void async_run_entry_fn(struct w
  {
        struct async_entry *entry =
                container_of(work, struct async_entry, work);
 +      struct async_entry *pos;
        unsigned long flags;
        ktime_t uninitialized_var(calltime), delta, rettime;
        struct async_domain *running = entry->running;
  
 -      /* 1) move self to the running queue */
 +      /* 1) move self to the running queue, make sure it stays sorted */
        spin_lock_irqsave(&async_lock, flags);
 -      list_move_tail(&entry->list, &running->domain);
 +      list_for_each_entry_reverse(pos, &running->domain, list)
 +              if (entry->cookie < pos->cookie)
 +                      break;
 +      list_move_tail(&entry->list, &pos->list);
        spin_unlock_irqrestore(&async_lock, flags);
  
        /* 2) run (and print duration) */
@@@ -209,9 -198,6 +211,9 @@@ static async_cookie_t __async_schedule(
        atomic_inc(&entry_count);
        spin_unlock_irqrestore(&async_lock, flags);
  
 +      /* mark that this task has queued an async job, used by module init */
 +      current->flags |= PF_USED_ASYNC;
 +
        /* schedule for execution */
        queue_work(system_unbound_wq, &entry->work);
  
@@@ -353,3 -339,15 +355,15 @@@ void async_synchronize_cookie(async_coo
        async_synchronize_cookie_domain(cookie, &async_running);
  }
  EXPORT_SYMBOL_GPL(async_synchronize_cookie);
+ /**
+  * current_is_async - is %current an async worker task?
+  *
+  * Returns %true if %current is an async worker task.
+  */
+ bool current_is_async(void)
+ {
+       struct worker *worker = current_wq_worker();
+       return worker && worker->current_func == async_run_entry_fn;
+ }
diff --combined kernel/sched/core.c
@@@ -83,7 -83,7 +83,7 @@@
  #endif
  
  #include "sched.h"
- #include "../workqueue_sched.h"
+ #include "../workqueue_internal.h"
  #include "../smpboot.h"
  
  #define CREATE_TRACE_POINTS
@@@ -1523,8 -1523,7 +1523,8 @@@ out
   */
  int wake_up_process(struct task_struct *p)
  {
 -      return try_to_wake_up(p, TASK_ALL, 0);
 +      WARN_ON(task_is_stopped_or_traced(p));
 +      return try_to_wake_up(p, TASK_NORMAL, 0);
  }
  EXPORT_SYMBOL(wake_up_process);
  
@@@ -4371,7 -4370,7 +4371,7 @@@ bool __sched yield_to(struct task_struc
        struct task_struct *curr = current;
        struct rq *rq, *p_rq;
        unsigned long flags;
 -      bool yielded = 0;
 +      int yielded = 0;
  
        local_irq_save(flags);
        rq = this_rq();
@@@ -4667,7 -4666,6 +4667,7 @@@ void __cpuinit init_idle(struct task_st
         */
        idle->sched_class = &idle_sched_class;
        ftrace_graph_init_idle_task(idle, cpu);
 +      vtime_init_idle(idle);
  #if defined(CONFIG_SMP)
        sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu);
  #endif
@@@ -7509,25 -7507,6 +7509,25 @@@ static int sched_rt_global_constraints(
  }
  #endif /* CONFIG_RT_GROUP_SCHED */
  
 +int sched_rr_handler(struct ctl_table *table, int write,
 +              void __user *buffer, size_t *lenp,
 +              loff_t *ppos)
 +{
 +      int ret;
 +      static DEFINE_MUTEX(mutex);
 +
 +      mutex_lock(&mutex);
 +      ret = proc_dointvec(table, write, buffer, lenp, ppos);
 +      /* make sure that internally we keep jiffies */
 +      /* also, writing zero resets timeslice to default */
 +      if (!ret && write) {
 +              sched_rr_timeslice = sched_rr_timeslice <= 0 ?
 +                      RR_TIMESLICE : msecs_to_jiffies(sched_rr_timeslice);
 +      }
 +      mutex_unlock(&mutex);
 +      return ret;
 +}
 +
  int sched_rt_handler(struct ctl_table *table, int write,
                void __user *buffer, size_t *lenp,
                loff_t *ppos)