29 Jun, 2010

1 commit

  • 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

    Tejun Heo
     

09 Jun, 2010

1 commit

  • Concurrency managed workqueue needs to know when workers are going to
    sleep and waking up. Using these two hooks, cmwq keeps track of the
    current concurrency level and throttles execution of new works if it's
    too high and wakes up another worker from the sleep hook if it becomes
    too low.

    This patch introduces PF_WQ_WORKER to identify workqueue workers and
    adds the following two hooks.

    * wq_worker_waking_up(): called when a worker is woken up.

    * wq_worker_sleeping(): called when a worker is going to sleep and may
    return a pointer to a local task which should be woken up. The
    returned task is woken up using try_to_wake_up_local() which is
    simplified ttwu which is called under rq lock and can only wake up
    local tasks.

    Both hooks are currently defined as noop in kernel/workqueue_sched.h.
    Later cmwq implementation will replace them with proper
    implementation.

    These hooks are hard coded as they'll always be enabled.

    Signed-off-by: Tejun Heo
    Acked-by: Peter Zijlstra
    Cc: Mike Galbraith
    Cc: Ingo Molnar

    Tejun Heo