aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/workqueue.h
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-06-29 04:07:14 -0400
committerTejun Heo <tj@kernel.org>2010-06-29 04:07:14 -0400
commite22bee782b3b00bd4534ae9b1c5fb2e8e6573c5c (patch)
tree9854d22294699d9ec27e28f70c05f479e5640abd /include/linux/workqueue.h
parentd302f0178223802a1e496ba90c66193b7721c9c1 (diff)
workqueue: implement concurrency managed dynamic worker pool
Instead of creating a worker for each cwq and putting it into the shared pool, manage per-cpu workers dynamically. Works aren't supposed to be cpu cycle hogs and maintaining just enough concurrency to prevent work processing from stalling due to lack of processing context is optimal. gcwq keeps the number of concurrent active workers to minimum but no less. As long as there's one or more running workers on the cpu, no new worker is scheduled so that works can be processed in batch as much as possible but when the last running worker blocks, gcwq immediately schedules new worker so that the cpu doesn't sit idle while there are works to be processed. gcwq always keeps at least single idle worker around. When a new worker is necessary and the worker is the last idle one, the worker assumes the role of "manager" and manages the worker pool - ie. creates another worker. Forward-progress is guaranteed by having dedicated rescue workers for workqueues which may be necessary while creating a new worker. When the manager is having problem creating a new worker, mayday timer activates and rescue workers are summoned to the cpu and execute works which might be necessary to create new workers. Trustee is expanded to serve the role of manager while a CPU is being taken down and stays down. As no new works are supposed to be queued on a dead cpu, it just needs to drain all the existing ones. Trustee continues to try to create new workers and summon rescuers as long as there are pending works. If the CPU is brought back up while the trustee is still trying to drain the gcwq from the previous offlining, the trustee will kill all idles ones and tell workers which are still busy to rebind to the cpu, and pass control over to gcwq which assumes the manager role as necessary. Concurrency managed worker pool reduces the number of workers drastically. Only workers which are necessary to keep the processing going are created and kept. Also, it reduces cache footprint by avoiding unnecessarily switching contexts between different workers. Please note that this patch does not increase max_active of any workqueue. All workqueues can still only process one work per cpu. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'include/linux/workqueue.h')
-rw-r--r--include/linux/workqueue.h8
1 files changed, 5 insertions, 3 deletions
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 07cf5e5f91cb..b8f4ec45c40a 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -226,6 +226,7 @@ enum {
226 WQ_FREEZEABLE = 1 << 0, /* freeze during suspend */ 226 WQ_FREEZEABLE = 1 << 0, /* freeze during suspend */
227 WQ_SINGLE_CPU = 1 << 1, /* only single cpu at a time */ 227 WQ_SINGLE_CPU = 1 << 1, /* only single cpu at a time */
228 WQ_NON_REENTRANT = 1 << 2, /* guarantee non-reentrance */ 228 WQ_NON_REENTRANT = 1 << 2, /* guarantee non-reentrance */
229 WQ_RESCUER = 1 << 3, /* has an rescue worker */
229}; 230};
230 231
231extern struct workqueue_struct * 232extern struct workqueue_struct *
@@ -252,11 +253,12 @@ __create_workqueue_key(const char *name, unsigned int flags, int max_active,
252#endif 253#endif
253 254
254#define create_workqueue(name) \ 255#define create_workqueue(name) \
255 __create_workqueue((name), 0, 1) 256 __create_workqueue((name), WQ_RESCUER, 1)
256#define create_freezeable_workqueue(name) \ 257#define create_freezeable_workqueue(name) \
257 __create_workqueue((name), WQ_FREEZEABLE | WQ_SINGLE_CPU, 1) 258 __create_workqueue((name), \
259 WQ_FREEZEABLE | WQ_SINGLE_CPU | WQ_RESCUER, 1)
258#define create_singlethread_workqueue(name) \ 260#define create_singlethread_workqueue(name) \
259 __create_workqueue((name), WQ_SINGLE_CPU, 1) 261 __create_workqueue((name), WQ_SINGLE_CPU | WQ_RESCUER, 1)
260 262
261extern void destroy_workqueue(struct workqueue_struct *wq); 263extern void destroy_workqueue(struct workqueue_struct *wq);
262 264