linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tejun Heo <tj@kernel.org>
To: Lai Jiangshan <laijs@cn.fujitsu.com>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH V2 13/15] workqueue: also record worker in work->data if running&&queued
Date: Mon, 18 Feb 2013 11:50:23 -0800	[thread overview]
Message-ID: <20130218195023.GJ17414@htj.dyndns.org> (raw)
In-Reply-To: <1361203940-6300-14-git-send-email-laijs@cn.fujitsu.com>

Hello, Lai.

On Tue, Feb 19, 2013 at 12:12:14AM +0800, Lai Jiangshan wrote:
> +/**
> + * get_work_cwq - get cwq of the work
> + * @work: the work item of interest
> + *
> + * CONTEXT:
> + * spin_lock_irq(&pool->lock), the work must be queued on this pool
> + */
> +static struct cpu_workqueue_struct *get_work_cwq(struct work_struct *work)
> +{
> +	unsigned long data = atomic_long_read(&work->data);
> +	struct worker *worker;
> +
> +	if (data & WORK_STRUCT_CWQ) {
> +		return (void *)(data & WORK_STRUCT_WQ_DATA_MASK);
> +	} else if (data & WORK_OFFQ_REQUEUED) {
> +		worker = worker_by_id(data >> WORK_OFFQ_WORKER_SHIFT);
> +		BUG_ON(!worker || !worker->requeue);
> +		return worker->current_cwq;
> +	} else {
> +		BUG();
> +		return NULL;
> +	}
> +}

So, work->data points to the last worker ID if off-queue or on-queue
with another worker executing it and points to cwq if on-queue w/o
another worker executing.  If on-queue w/ concurrent execution, the
excuting worker updates work->data when it finishes execution, right?

Why no documentation about it at all?  The mechanism is convoluted
with interlocking from both work and worker sides.  Lack of
documentation makes things difficult for reviewers and later readers
of the code.

> @@ -1296,8 +1283,16 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
>  		worklist = &cwq->delayed_works;
>  	}
>  
> -	color_flags = work_color_to_flags(cwq->work_color);
> -	insert_work(cwq, work, worklist, color_flags | delayed_flags);
> +	if (worker) {
> +		worker->requeue = true;
> +		worker->requeue_color = cwq->work_color;
> +		set_work_worker_and_keep_pending(work, worker->id,
> +				delayed_flags | WORK_OFFQ_REQUEUED);
> +		list_add_tail(&work->entry, worklist);
> +	} else {
> +		color_flags = work_color_to_flags(cwq->work_color);
> +		insert_work(cwq, work, worklist, color_flags | delayed_flags);
> +	}

I can't say I like this.  In interlocks the work being queued and the
worker so that both have to watch out for each other.  It's kinda
nasty.

> @@ -2236,6 +2241,16 @@ __acquires(&pool->lock)
>  	worker->current_func = NULL;
>  	worker->current_cwq = NULL;
>  	cwq_dec_nr_in_flight(cwq, work_color);
> +
> +	if (unlikely(worker->requeue)) {
> +		unsigned long color_flags, keep_flags;
> +
> +		worker->requeue = false;
> +		keep_flags = atomic_long_read(&work->data);
> +		keep_flags &= WORK_STRUCT_LINKED | WORK_STRUCT_DELAYED;
> +		color_flags = work_color_to_flags(worker->requeue_color);
> +		set_work_cwq(work, cwq, color_flags | keep_flags);
> +	}

So, what was before mostly one way "is it still executing?" query
becomes three party handshake among the queuer, executing worker and
try_to_grab_pending(), and we end up shifting information from the
queuer through the executing worker because work->data can't hold both
workqueue and worker information.

I don't know, Lai.  While removal of busy_hash is nice, I'm not really
sure whether we're ending up with better or worse code by doing this.
It's more convoluted for sure.  Performance-wise, now that idr_find()
for pool costs almost nothing (because we're very unlikely to have
more than 256 pools), we're comparing one idr lookup (which can easily
blow through 256 single layer optimization limit) against two simple
hash table lookup.  I don't really think either would be noticeably
better than the other in any measureable way.

The trade-off, while doesn't seem too bad, doesn't seem much
beneficial either.  It's different from what we're currently doing but
I'm not sure we're making it better by doing this.

Hmmmmm....

-- 
tejun

  reply	other threads:[~2013-02-18 19:50 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-18 16:12 [PATCH V2 00/15] workqueue: enhance locking and lookup worker via ID Lai Jiangshan
2013-02-18 16:12 ` [PATCH V2 01/15] workqueue: add lock_work_pool() Lai Jiangshan
2013-02-18 16:12 ` [PATCH V2 02/15] workqueue: allow more work_pool id space Lai Jiangshan
2013-02-19 20:19   ` [PATCH 1/4] workqueue: allow more off-queue flag space Tejun Heo
2013-02-18 16:12 ` [PATCH V2 03/15] workqueue: remname current worker->id to worker->id_in_pool Lai Jiangshan
2013-02-18 16:12 ` [PATCH V2 04/15] workqueue: add worker's global worker ID Lai Jiangshan
2013-02-18 16:12 ` [PATCH V2 05/15] workqueue: only set pool id when the work is running Lai Jiangshan
2013-02-18 16:12 ` [PATCH V2 06/15] workqueue: use current instead of worker->task in worker_maybe_bind_and_lock() Lai Jiangshan
2013-02-19 20:20   ` [PATCH 2/4] workqueue: use %current " Tejun Heo
2013-02-18 16:12 ` [PATCH V2 07/15] workqueue: change argument of worker_maybe_bind_and_lock() to pool Lai Jiangshan
2013-02-19 20:20   ` [PATCH 3/4] workqueue: change argument of worker_maybe_bind_and_lock() to @pool Tejun Heo
2013-02-18 16:12 ` [PATCH V2 08/15] workqueue: only change worker->pool with pool lock held Lai Jiangshan
2013-02-19 20:22   ` [PATCH 4/4] workqueue: better define synchronization rule around rescuer->pool updates Tejun Heo
2013-02-18 16:12 ` [PATCH V2 09/15] workqueue: use worker id in work->data instead Lai Jiangshan
2013-02-18 16:12 ` [PATCH V2 10/15] workqueue: avoid unneeded calls to get_work_cwq() Lai Jiangshan
2013-02-18 16:12 ` [PATCH V2 11/15] workqueue: split work_flags to delayed_flags and color_flags in __queue_work() Lai Jiangshan
2013-02-18 16:12 ` [PATCH V2 12/15] workqueue: add extra flags to set_work_worker_and_keep_pending() Lai Jiangshan
2013-02-18 16:12 ` [PATCH V2 13/15] workqueue: also record worker in work->data if running&&queued Lai Jiangshan
2013-02-18 19:50   ` Tejun Heo [this message]
2013-02-19 15:04     ` Lai Jiangshan
2013-02-19 19:27       ` Tejun Heo
2013-02-19 20:24         ` Tejun Heo
2013-02-18 16:12 ` [PATCH V2 14/15] workqueue: convert busy hash to busy list Lai Jiangshan
2013-02-18 16:12 ` [PATCH V2 15/15] workqueue: queue worker to busy list outside process_one_work() Lai Jiangshan
2013-02-18 16:28 ` [PATCH V2 00/15] workqueue: enhance locking and lookup worker via ID Lai Jiangshan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130218195023.GJ17414@htj.dyndns.org \
    --to=tj@kernel.org \
    --cc=laijs@cn.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).