)]}'
{
  "commit": "dbf2576e37da0fcc7aacbfbb9fd5d3de7888a3c1",
  "tree": "abbebfe5aa155bda6ea41ab00e7f2c417e1eee6b",
  "parents": [
    "044c782ce3a901fbd17cbe701c592f582381174d"
  ],
  "author": {
    "name": "Tejun Heo",
    "email": "tj@kernel.org",
    "time": "Mon Aug 20 14:51:23 2012 -0700"
  },
  "committer": {
    "name": "Tejun Heo",
    "email": "tj@kernel.org",
    "time": "Mon Aug 20 14:51:23 2012 -0700"
  },
  "message": "workqueue: make all workqueues non-reentrant\n\nBy default, each per-cpu part of a bound workqueue operates separately\nand a work item may be executing concurrently on different CPUs.  The\nbehavior avoids some cross-cpu traffic but leads to subtle weirdities\nand not-so-subtle contortions in the API.\n\n* There\u0027s no sane usefulness in allowing a single work item to be\n  executed concurrently on multiple CPUs.  People just get the\n  behavior unintentionally and get surprised after learning about it.\n  Most either explicitly synchronize or use non-reentrant/ordered\n  workqueue but this is error-prone.\n\n* flush_work() can\u0027t wait for multiple instances of the same work item\n  on different CPUs.  If a work item is executing on cpu0 and then\n  queued on cpu1, flush_work() can only wait for the one on cpu1.\n\n  Unfortunately, work items can easily cross CPU boundaries\n  unintentionally when the queueing thread gets migrated.  This means\n  that if multiple queuers compete, flush_work() can\u0027t even guarantee\n  that the instance queued right before it is finished before\n  returning.\n\n* flush_work_sync() was added to work around some of the deficiencies\n  of flush_work().  In addition to the usual flushing, it ensures that\n  all currently executing instances are finished before returning.\n  This operation is expensive as it has to walk all CPUs and at the\n  same time fails to address competing queuer case.\n\n  Incorrectly using flush_work() when flush_work_sync() is necessary\n  is an easy error to make and can lead to bugs which are difficult to\n  reproduce.\n\n* Similar problems exist for flush_delayed_work[_sync]().\n\nOther than the cross-cpu access concern, there\u0027s no benefit in\nallowing parallel execution and it\u0027s plain silly to have this level of\ncontortion for workqueue which is widely used from core code to\nextremely obscure drivers.\n\nThis patch makes all workqueues non-reentrant.  If a work item is\nexecuting on a different CPU when queueing is requested, it is always\nqueued to that CPU.  This guarantees that any given work item can be\nexecuting on one CPU at maximum and if a work item is queued and\nexecuting, both are on the same CPU.\n\nThe only behavior change which may affect workqueue users negatively\nis that non-reentrancy overrides the affinity specified by\nqueue_work_on().  On a reentrant workqueue, the affinity specified by\nqueue_work_on() is always followed.  Now, if the work item is\nexecuting on one of the CPUs, the work item will be queued there\nregardless of the requested affinity.  I\u0027ve reviewed all workqueue\nusers which request explicit affinity, and, fortunately, none seems to\nbe crazy enough to exploit parallel execution of the same work item.\n\nThis adds an additional busy_hash lookup if the work item was\npreviously queued on a different CPU.  This shouldn\u0027t be noticeable\nunder any sane workload.  Work item queueing isn\u0027t a very\nhigh-frequency operation and they don\u0027t jump across CPUs all the time.\nIn a micro benchmark to exaggerate this difference - measuring the\ntime it takes for two work items to repeatedly jump between two CPUs a\nnumber (10M) of times with busy_hash table densely populated, the\ndifference was around 3%.\n\nWhile the overhead is measureable, it is only visible in pathological\ncases and the difference isn\u0027t huge.  This change brings much needed\nsanity to workqueue and makes its behavior consistent with timer.  I\nthink this is the right tradeoff to make.\n\nThis enables significant simplification of workqueue API.\nSimplification patches will follow.\n\nSigned-off-by: Tejun Heo \u003ctj@kernel.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "de429ba000ee685a7cfcaf2cc820c86369c20064",
      "old_mode": 33188,
      "old_path": "kernel/workqueue.c",
      "new_id": "c4feef9798eaf64024f7ecbb3031bcb614374d55",
      "new_mode": 33188,
      "new_path": "kernel/workqueue.c"
    }
  ]
}
