• Lai Jiangshan's avatar
    workqueue: simplify is-work-item-queued-here test · 0b3dae68
    Lai Jiangshan authored
    Currently, determining whether a work item is queued on a locked pool
    involves somewhat convoluted memory barrier dancing.  It goes like the
    following.
    
    * When a work item is queued on a pool, work->data is updated before
      work->entry is linked to the pending list with a wmb() inbetween.
    
    * When trying to determine whether a work item is currently queued on
      a pool pointed to by work->data, it locks the pool and looks at
      work->entry.  If work->entry is linked, we then do rmb() and then
      check whether work->data points to the current pool.
    
    This works because, work->data can only point to a pool if it
    currently is or were on the pool and,
    
    * If it currently is on the pool, the tests would obviously succeed.
    
    * It it left the pool, its work->entry was cleared under pool->lock,
      so if we're seeing non-empty work->entry, it has to be from the work
      item being linked on another pool.  Because work->data is updated
      before work->entry is linked with wmb() inbetween, work->data update
      from another pool is guaranteed to be visible if we do rmb() after
      seeing non-empty work->entry.  So, we either see empty work->entry
      or we see updated work->data pointin to another pool.
    
    While this works, it's convoluted, to put it mildly.  With recent
    updates, it's now guaranteed that work->data points to cwq only while
    the work item is queued and that updating work->data to point to cwq
    or back to pool is done under pool->lock, so we can simply test
    whether work->data points to cwq which is associated with the
    currently locked pool instead of the convoluted memory barrier
    dancing.
    
    This patch replaces the memory barrier based "are you still here,
    really?" test with much simpler "does work->data points to me?" test -
    if work->data points to a cwq which is associated with the currently
    locked pool, the work item is guaranteed to be queued on the pool as
    work->data can start and stop pointing to such cwq only under
    pool->lock and the start and stop coincide with queue and dequeue.
    
    tj: Rewrote the comments and description.
    Signed-off-by: default avatarLai Jiangshan <laijs@cn.fujitsu.com>
    Signed-off-by: default avatarTejun Heo <tj@kernel.org>
    0b3dae68
workqueue.c 105 KB