• Lai Jiangshan's avatar
    workqueue: Mark barrier work with WORK_STRUCT_INACTIVE · 018f3a13
    Lai Jiangshan authored
    Currently, WORK_NO_COLOR has two meanings:
    	Not participate in flushing
    	Not participate in nr_active
    
    And only non-barrier work items are marked with WORK_STRUCT_INACTIVE
    when they are in inactive_works list.  The barrier work items are not
    marked INACTIVE even linked in inactive_works list since these tail
    items are always moved together with the head work item.
    
    These definitions are simple, clean and practical. (Except a small
    blemish that only the first meaning of WORK_NO_COLOR is documented in
    include/linux/workqueue.h while both meanings are in workqueue.c)
    
    But dual-purpose WORK_NO_COLOR used for barrier work items has proven to
    be problematical[1].  Only the second purpose is obligatory.  So we plan
    to make barrier work items participate in flushing but keep them still
    not participating in nr_active.
    
    So the plan is to mark barrier work items inactive without using
    WORK_NO_COLOR in this patch so that we can assign a flushing color to
    them in next patch.
    
    The reasonable way is to add or reuse a bit in work data of the work
    item.  But adding a bit will double the size of pool_workqueue.
    
    Currently, WORK_STRUCT_INACTIVE is only used in try_to_grab_pending()
    for user-queued work items and try_to_grab_pending() can't work for
    barrier work items.  So we extend WORK_STRUCT_INACTIVE to also mark
    barrier work items no matter which list they are in because we don't
    need to determind which list a barrier work item is in.
    
    So the meaning of WORK_STRUCT_INACTIVE becomes just "the work items don't
    participate in nr_active" (no matter whether it is a barrier work item or
    a user-queued work item).  And WORK_STRUCT_INACTIVE for user-queued work
    items means they are in inactive_works list.
    
    This patch does it by setting WORK_STRUCT_INACTIVE for barrier work items
    in insert_wq_barrier() and checking WORK_STRUCT_INACTIVE first in
    pwq_dec_nr_in_flight().  And the meaning of WORK_NO_COLOR is reduced to
    only "not participating in flushing".
    
    There is no functionality change intended in this patch.  Because
    WORK_NO_COLOR+WORK_STRUCT_INACTIVE represents the previous WORK_NO_COLOR
    in meaning and try_to_grab_pending() doesn't use for barrier work items
    and avoids being confused by this extended WORK_STRUCT_INACTIVE.
    
    A bunch of comment for nr_active & WORK_STRUCT_INACTIVE is also added for
    documenting how WORK_STRUCT_INACTIVE works in nr_active management.
    
    [1]: https://lore.kernel.org/lkml/20210812083814.32453-1-lizhe.67@bytedance.com/Signed-off-by: default avatarLai Jiangshan <laijs@linux.alibaba.com>
    Signed-off-by: default avatarTejun Heo <tj@kernel.org>
    018f3a13
workqueue.c 168 KB