linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Frederic Weisbecker <fweisbec@gmail.com>
To: Tejun Heo <tj@kernel.org>
Cc: torvalds@linux-foundation.org, mingo@elte.hu,
	linux-kernel@vger.kernel.org, jeff@garzik.org,
	akpm@linux-foundation.org, rusty@rustcorp.com.au,
	cl@linux-foundation.org, dhowells@redhat.com,
	arjan@linux.intel.com, oleg@redhat.com, axboe@kernel.dk,
	dwalker@codeaurora.org, stefanr@s5r6.in-berlin.de,
	florian@mickler.org, andi@firstfloor.org, mst@redhat.com,
	randy.dunlap@oracle.com
Subject: Re: [PATCH 12/35] workqueue: update cwq alignement
Date: Tue, 29 Jun 2010 00:47:57 +0200	[thread overview]
Message-ID: <20100628224755.GA10104@nowhere> (raw)
In-Reply-To: <1277759063-24607-13-git-send-email-tj@kernel.org>

On Mon, Jun 28, 2010 at 11:04:00PM +0200, Tejun Heo wrote:
> work->data field is used for two purposes.  It points to cwq it's
> queued on and the lower bits are used for flags.  Currently, two bits
> are reserved which is always safe as 4 byte alignment is guaranteed on
> every architecture.  However, future changes will need more flag bits.
> 
> On SMP, the percpu allocator is capable of honoring larger alignment
> (there are other users which depend on it) and larger alignment works
> just fine.  On UP, percpu allocator is a thin wrapper around
> kzalloc/kfree() and don't honor alignment request.
> 
> This patch introduces WORK_STRUCT_FLAG_BITS and implements
> alloc/free_cwqs() which guarantees (1 << WORK_STRUCT_FLAG_BITS)
> alignment both on SMP and UP.  On SMP, simply wrapping percpu
> allocator is enouhg.  On UP, extra space is allocated so that cwq can
> be aligned and the original pointer can be stored after it which is
> used in the free path.
> 
> While at it, as cwqs are now forced aligned, make sure the resulting
> alignment is at least equal to or larger than that of long long.
> 
> Alignment problem on UP is reported by Michal Simek.
> 
> Signed-off-by: Tejun Heo <tj@kernel.org>
> Cc: Christoph Lameter <cl@linux-foundation.org>
> Cc: Ingo Molnar <mingo@elte.hu>
> Reported-by: Michal Simek <michal.simek@petalogix.com>
> ---
>  include/linux/workqueue.h |    5 +++-
>  kernel/workqueue.c        |   62 +++++++++++++++++++++++++++++++++++++++++---
>  2 files changed, 61 insertions(+), 6 deletions(-)
> 
> diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
> index d60c570..b90958a 100644
> --- a/include/linux/workqueue.h
> +++ b/include/linux/workqueue.h
> @@ -26,6 +26,9 @@ enum {
>  	WORK_STRUCT_PENDING_BIT	= 0,	/* work item is pending execution */
>  #ifdef CONFIG_DEBUG_OBJECTS_WORK
>  	WORK_STRUCT_STATIC_BIT	= 1,	/* static initializer (debugobjects) */
> +	WORK_STRUCT_FLAG_BITS	= 2,
> +#else
> +	WORK_STRUCT_FLAG_BITS	= 1,
>  #endif
>  
>  	WORK_STRUCT_PENDING	= 1 << WORK_STRUCT_PENDING_BIT,
> @@ -35,7 +38,7 @@ enum {
>  	WORK_STRUCT_STATIC	= 0,
>  #endif
>  
> -	WORK_STRUCT_FLAG_MASK	= 3UL,
> +	WORK_STRUCT_FLAG_MASK	= (1UL << WORK_STRUCT_FLAG_BITS) - 1,
>  	WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK,
>  };
>  
> diff --git a/kernel/workqueue.c b/kernel/workqueue.c
> index dc78956..878546e 100644
> --- a/kernel/workqueue.c
> +++ b/kernel/workqueue.c
> @@ -46,7 +46,9 @@
>  
>  /*
>   * The per-CPU workqueue (if single thread, we always use the first
> - * possible cpu).
> + * possible cpu).  The lower WORK_STRUCT_FLAG_BITS of
> + * work_struct->data are used for flags and thus cwqs need to be
> + * aligned at two's power of the number of flag bits.
>   */
>  struct cpu_workqueue_struct {
>  
> @@ -59,7 +61,7 @@ struct cpu_workqueue_struct {
>  
>  	struct workqueue_struct *wq;		/* I: the owning workqueue */
>  	struct task_struct	*thread;
> -} ____cacheline_aligned;
> +};
>  
>  /*
>   * The externally visible workqueue abstraction is an array of
> @@ -967,6 +969,47 @@ int current_is_keventd(void)
>  
>  }
>  
> +static struct cpu_workqueue_struct *alloc_cwqs(void)
> +{
> +	const size_t size = sizeof(struct cpu_workqueue_struct);
> +	const size_t align = 1 << WORK_STRUCT_FLAG_BITS;
> +	struct cpu_workqueue_struct *cwqs;
> +#ifndef CONFIG_SMP
> +	void *ptr;
> +
> +	/*
> +	 * On UP, percpu allocator doesn't honor alignment parameter
> +	 * and simply uses arch-dependent default.  Allocate enough
> +	 * room to align cwq and put an extra pointer at the end
> +	 * pointing back to the originally allocated pointer which
> +	 * will be used for free.
> +	 *
> +	 * FIXME: This really belongs to UP percpu code.  Update UP
> +	 * percpu code to honor alignment and remove this ugliness.
> +	 */
> +	ptr = __alloc_percpu(size + align + sizeof(void *), 1);
> +	cwqs = PTR_ALIGN(ptr, align);
> +	*(void **)per_cpu_ptr(cwqs + 1, 0) = ptr;
> +#else
> +	/* On SMP, percpu allocator can do it itself */
> +	cwqs = __alloc_percpu(size, align);
> +#endif
> +	/* just in case, make sure it's actually aligned */
> +	BUG_ON(!IS_ALIGNED((unsigned long)cwqs, align));
> +	return cwqs;
> +}
> +
> +static void free_cwqs(struct cpu_workqueue_struct *cwqs)
> +{
> +#ifndef CONFIG_SMP
> +	/* on UP, the pointer to free is stored right after the cwq */
> +	if (cwqs)
> +		free_percpu(*(void **)per_cpu_ptr(cwqs + 1, 0));
> +#else
> +	free_percpu(cwqs);
> +#endif
> +}
> +
>  static int create_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
>  {
>  	struct workqueue_struct *wq = cwq->wq;
> @@ -1012,7 +1055,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
>  	if (!wq)
>  		goto err;
>  
> -	wq->cpu_wq = alloc_percpu(struct cpu_workqueue_struct);
> +	wq->cpu_wq = alloc_cwqs();
>  	if (!wq->cpu_wq)
>  		goto err;
>  
> @@ -1031,6 +1074,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
>  	for_each_possible_cpu(cpu) {
>  		struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq);
>  
> +		BUG_ON((unsigned long)cwq & WORK_STRUCT_FLAG_MASK);
>  		cwq->wq = wq;
>  		cwq->cpu = cpu;
>  		spin_lock_init(&cwq->lock);
> @@ -1059,7 +1103,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
>  	return wq;
>  err:
>  	if (wq) {
> -		free_percpu(wq->cpu_wq);
> +		free_cwqs(wq->cpu_wq);
>  		kfree(wq);
>  	}
>  	return NULL;
> @@ -1112,7 +1156,7 @@ void destroy_workqueue(struct workqueue_struct *wq)
>  	for_each_possible_cpu(cpu)
>  		cleanup_workqueue_thread(get_cwq(cpu, wq));
>  
> -	free_percpu(wq->cpu_wq);
> +	free_cwqs(wq->cpu_wq);
>  	kfree(wq);
>  }
>  EXPORT_SYMBOL_GPL(destroy_workqueue);
> @@ -1194,6 +1238,14 @@ EXPORT_SYMBOL_GPL(work_on_cpu);
>  
>  void __init init_workqueues(void)
>  {
> +	/*
> +	 * cwqs are forced aligned according to WORK_STRUCT_FLAG_BITS.
> +	 * Make sure that the alignment isn't lower than that of
> +	 * unsigned long long.
> +	 */
> +	BUILD_BUG_ON(__alignof__(struct cpu_workqueue_struct) <
> +		     __alignof__(unsigned long long));
> +


But they are not allocated contiguously as we use the per cpu offsets.
So why does the struct itself need to be aligned? Only the base pointer
of its dynamic allocation needs to be aligned. Or am I missing something?


This is crashing my build in x86-32, unless I force an alignment to 8, or
I just remove this build check.


  reply	other threads:[~2010-06-28 22:47 UTC|newest]

Thread overview: 98+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-06-28 21:03 [PATCHSET] workqueue: concurrency managed workqueue, take#6 Tejun Heo
2010-06-28 21:03 ` [PATCH 01/35] kthread: implement kthread_worker Tejun Heo
2010-06-28 21:03 ` [PATCH 02/35] ivtv: use kthread_worker instead of workqueue Tejun Heo
2010-07-05 17:11   ` Andy Walls
2010-07-06  7:01     ` Tejun Heo
2010-07-09 13:15       ` Andy Walls
2010-06-28 21:03 ` [PATCH 03/35] kthread: implement kthread_data() Tejun Heo
2010-06-28 21:03 ` [PATCH 04/35] acpi: use queue_work_on() instead of binding workqueue worker to cpu0 Tejun Heo
2010-06-28 21:03 ` [PATCH 05/35] workqueue: kill RT workqueue Tejun Heo
2010-06-28 21:03 ` [PATCH 06/35] workqueue: misc/cosmetic updates Tejun Heo
2010-06-28 21:03 ` [PATCH 07/35] workqueue: merge feature parameters into flags Tejun Heo
2010-06-28 21:03 ` [PATCH 08/35] workqueue: define masks for work flags and conditionalize STATIC flags Tejun Heo
2010-06-28 21:03 ` [PATCH 09/35] workqueue: separate out process_one_work() Tejun Heo
2010-06-28 21:03 ` [PATCH 10/35] workqueue: temporarily remove workqueue tracing Tejun Heo
2010-06-28 21:03 ` [PATCH 11/35] workqueue: kill cpu_populated_map Tejun Heo
2010-06-28 21:04 ` [PATCH 12/35] workqueue: update cwq alignement Tejun Heo
2010-06-28 22:47   ` Frederic Weisbecker [this message]
2010-06-29  7:39     ` Tejun Heo
2010-06-29 12:36       ` Frederic Weisbecker
2010-06-29 15:42         ` Tejun Heo
2010-06-29 15:47           ` Frederic Weisbecker
2010-06-29 15:51             ` Tejun Heo
2010-06-29 16:01               ` Frederic Weisbecker
2010-06-29 16:09                 ` Tejun Heo
2010-06-29 16:17                   ` Frederic Weisbecker
2010-07-06 14:22                   ` Christoph Lameter
2010-07-06 14:26                     ` Tejun Heo
2010-06-29  8:12     ` [PATCH UPDATED " Tejun Heo
2010-06-29 13:39       ` Frederic Weisbecker
2010-06-28 21:04 ` [PATCH 13/35] workqueue: reimplement workqueue flushing using color coded works Tejun Heo
2010-06-28 21:04 ` [PATCH 14/35] workqueue: introduce worker Tejun Heo
2010-06-28 21:04 ` [PATCH 15/35] workqueue: reimplement work flushing using linked works Tejun Heo
2010-06-28 21:04 ` [PATCH 16/35] workqueue: implement per-cwq active work limit Tejun Heo
2010-06-28 21:04 ` [PATCH 17/35] workqueue: reimplement workqueue freeze using max_active Tejun Heo
2010-06-28 21:04 ` [PATCH 18/35] workqueue: introduce global cwq and unify cwq locks Tejun Heo
2010-06-28 21:04 ` [PATCH 19/35] workqueue: implement worker states Tejun Heo
2010-06-28 21:04 ` [PATCH 20/35] workqueue: reimplement CPU hotplugging support using trustee Tejun Heo
2010-06-28 21:04 ` [PATCH 21/35] workqueue: make single thread workqueue shared worker pool friendly Tejun Heo
2010-06-28 21:04 ` [PATCH 22/35] workqueue: add find_worker_executing_work() and track current_cwq Tejun Heo
2010-06-28 21:04 ` [PATCH 23/35] workqueue: carry cpu number in work data once execution starts Tejun Heo
2010-06-28 21:04 ` [PATCH 24/35] workqueue: implement WQ_NON_REENTRANT Tejun Heo
2010-06-28 21:04 ` [PATCH 25/35] workqueue: use shared worklist and pool all workers per cpu Tejun Heo
2010-06-28 21:04 ` [PATCH 26/35] workqueue: implement worker_{set|clr}_flags() Tejun Heo
2010-06-28 21:04 ` [PATCH 27/35] workqueue: implement concurrency managed dynamic worker pool Tejun Heo
2010-07-09  9:11   ` Yong Zhang
2010-07-12  8:53     ` [PATCH] workqueue: fix locking in retry path of maybe_create_worker() Tejun Heo
2010-07-12 13:23       ` Yong Zhang
2010-07-14  9:37         ` Tejun Heo
2010-06-28 21:04 ` [PATCH 28/35] workqueue: increase max_active of keventd and kill current_is_keventd() Tejun Heo
2010-06-28 21:04 ` [PATCH 29/35] workqueue: s/__create_workqueue()/alloc_workqueue()/, and add system workqueues Tejun Heo
2010-06-28 21:04 ` [PATCH 30/35] workqueue: implement several utility APIs Tejun Heo
2010-06-28 21:04 ` [PATCH 31/35] workqueue: implement high priority workqueue Tejun Heo
2010-06-28 21:04 ` [PATCH 32/35] workqueue: implement cpu intensive workqueue Tejun Heo
2010-06-28 21:04 ` [PATCH 33/35] libata: take advantage of cmwq and remove concurrency limitations Tejun Heo
2010-06-28 22:32   ` Jeff Garzik
2010-06-29  7:00     ` Tejun Heo
2010-06-28 21:04 ` [PATCH 34/35] async: use workqueue for worker pool Tejun Heo
2010-06-28 22:55   ` Frederic Weisbecker
2010-06-29  7:25     ` Tejun Heo
2010-06-29 12:18       ` Frederic Weisbecker
2010-06-29 15:46         ` Tejun Heo
2010-06-29 15:52           ` Frederic Weisbecker
2010-06-29 15:55             ` Tejun Heo
2010-06-29 16:40               ` Arjan van de Ven
2010-06-29 16:59                 ` Tejun Heo
2010-06-29 17:12                   ` Tejun Heo
2010-06-29 18:08                     ` Arjan van de Ven
2010-06-29 18:07                   ` Arjan van de Ven
2010-06-29 18:15                     ` Tejun Heo
2010-06-29 18:22                       ` Arjan van de Ven
2010-06-29 18:34                         ` Tejun Heo
2010-06-29 18:41                           ` Arjan van de Ven
2010-06-29 18:59                             ` Tejun Heo
2010-06-29 21:37                   ` David Howells
2010-07-02  9:17                     ` [PATCHSET] workqueue: implement and use WQ_UNBOUND Tejun Heo
2010-07-02  9:19                       ` [PATCH 1/4] workqueue: prepare for WQ_UNBOUND implementation Tejun Heo
2010-07-02  9:24                       ` [PATCH 3/4] workqueue: remove WQ_SINGLE_CPU and use WQ_UNBOUND instead Tejun Heo
2010-07-02  9:25                       ` [PATCH 4/4] async: use workqueue for worker pool Tejun Heo
2010-07-02 15:09                         ` Stefan Richter
2010-07-02 16:26                           ` Tejun Heo
2010-07-02 16:25                         ` [PATCH UPDATED " Tejun Heo
2010-07-02  9:28                       ` [PATCH 2/4] workqueue: implement unbound workqueue Tejun Heo
2010-07-02  9:32                       ` [PATCHSET] workqueue: implement and use WQ_UNBOUND Tejun Heo
2010-07-07  5:41                       ` Tejun Heo
2010-07-14  9:39                         ` Tejun Heo
2010-07-20 22:01                       ` David Howells
2010-07-02  9:20                     ` [PATCH 2/4] workqueue: implement unbound workqueue Tejun Heo
2010-06-28 21:04 ` [PATCH 35/35] pcrypt: use HIGHPRI and CPU_INTENSIVE workqueues for padata Tejun Heo
2010-06-28 23:18 ` [PATCHSET] workqueue: concurrency managed workqueue, take#6 Frederic Weisbecker
2010-06-29  7:05   ` Tejun Heo
2010-07-02  8:32 ` [PATCHSET] workqueue: fixes on top of cmwq take#6 Tejun Heo
2010-07-02  8:33   ` [PATCH 1/4] workqueue: use worker_set/clr_flags() only from worker itself Tejun Heo
2010-07-02  8:34   ` [PATCH 2/4] workqueue: fix race condition in flush_workqueue() Tejun Heo
2010-07-02  8:35   ` [PATCH 3/4] workqueue: fix incorrect cpu number BUG_ON() in get_work_gcwq() Tejun Heo
2010-07-02  8:35   ` [PATCH 4/4] workqueue: fix worker management invocation without pending works Tejun Heo
2010-07-19 14:51 ` [PATCHSET] workqueue: concurrency managed workqueue, take#6 Tejun Heo
2010-07-21 13:23 ` David Howells
2010-07-21 14:52   ` Tejun Heo

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=20100628224755.GA10104@nowhere \
    --to=fweisbec@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=andi@firstfloor.org \
    --cc=arjan@linux.intel.com \
    --cc=axboe@kernel.dk \
    --cc=cl@linux-foundation.org \
    --cc=dhowells@redhat.com \
    --cc=dwalker@codeaurora.org \
    --cc=florian@mickler.org \
    --cc=jeff@garzik.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=mst@redhat.com \
    --cc=oleg@redhat.com \
    --cc=randy.dunlap@oracle.com \
    --cc=rusty@rustcorp.com.au \
    --cc=stefanr@s5r6.in-berlin.de \
    --cc=tj@kernel.org \
    --cc=torvalds@linux-foundation.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).