lkml.org 
[lkml]   [2012]   [Mar]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectPatch workqueue: create new slab cache instead of hacking
    How about this instead?

    Subject: workqueues: Use new kmem cache to get aligned memory for workqueues

    The workqueue logic currently improvises by doing a kmalloc allocation and
    then aligning the object. Create a slab cache for that purpose with the
    proper alignment instead.

    Cleans up the code and makes things much simpler. No need anymore to carry
    an additional pointer to the beginning of the kmalloc object.

    Signed-off-by: Christoph Lameter <cl@linux.com>


    ---
    kernel/workqueue.c | 50 +++++++++++++++++++++-----------------------------
    1 file changed, 21 insertions(+), 29 deletions(-)

    Index: linux-2.6/kernel/workqueue.c
    ===================================================================
    --- linux-2.6.orig/kernel/workqueue.c 2012-03-21 09:07:07.000000000 -0500
    +++ linux-2.6/kernel/workqueue.c 2012-03-21 09:07:24.000000000 -0500
    @@ -2884,36 +2884,27 @@ int keventd_up(void)
    return system_wq != NULL;
    }

    +/*
    + * cwqs are forced aligned according to WORK_STRUCT_FLAG_BITS.
    + * Make sure that the alignment isn't lower than that of
    + * unsigned long long.
    + */
    +
    +#define WQ_ALIGN (max_t(size_t, 1 << WORK_STRUCT_FLAG_BITS, \
    + __alignof__(unsigned long long)))
    +
    +struct kmem_cache *wq_slab;
    +
    static int alloc_cwqs(struct workqueue_struct *wq)
    {
    - /*
    - * cwqs are forced aligned according to WORK_STRUCT_FLAG_BITS.
    - * Make sure that the alignment isn't lower than that of
    - * unsigned long long.
    - */
    - const size_t size = sizeof(struct cpu_workqueue_struct);
    - const size_t align = max_t(size_t, 1 << WORK_STRUCT_FLAG_BITS,
    - __alignof__(unsigned long long));
    -
    if (!(wq->flags & WQ_UNBOUND))
    - wq->cpu_wq.pcpu = __alloc_percpu(size, align);
    - else {
    - void *ptr;
    -
    - /*
    - * 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.
    - */
    - ptr = kzalloc(size + align + sizeof(void *), GFP_KERNEL);
    - if (ptr) {
    - wq->cpu_wq.single = PTR_ALIGN(ptr, align);
    - *(void **)(wq->cpu_wq.single + 1) = ptr;
    - }
    - }
    + wq->cpu_wq.pcpu = __alloc_percpu(sizeof(struct cpu_workqueue_struct),
    + WQ_ALIGN);
    + else
    + wq->cpu_wq.single = kmem_cache_zalloc(wq_slab, GFP_KERNEL);

    /* just in case, make sure it's actually aligned */
    - BUG_ON(!IS_ALIGNED(wq->cpu_wq.v, align));
    + BUG_ON(!IS_ALIGNED(wq->cpu_wq.v, WQ_ALIGN));
    return wq->cpu_wq.v ? 0 : -ENOMEM;
    }

    @@ -2921,10 +2912,8 @@ static void free_cwqs(struct workqueue_s
    {
    if (!(wq->flags & WQ_UNBOUND))
    free_percpu(wq->cpu_wq.pcpu);
    - else if (wq->cpu_wq.single) {
    - /* the pointer to free is stored right after the cwq */
    - kfree(*(void **)(wq->cpu_wq.single + 1));
    - }
    + else if (wq->cpu_wq.single)
    + kmem_cache_free(wq_slab, wq->cpu_wq.single);
    }

    static int wq_clamp_max_active(int max_active, unsigned int flags,
    @@ -3770,6 +3759,9 @@ static int __init init_workqueues(void)
    unsigned int cpu;
    int i;

    + wq_slab = kmem_cache_create("workqueue", sizeof(struct cpu_workqueue_struct),
    + WQ_ALIGN, SLAB_PANIC, NULL);
    +
    cpu_notifier(workqueue_cpu_callback, CPU_PRI_WORKQUEUE);

    /* initialize gcwqs */

    \
     
     \ /
      Last update: 2012-03-21 15:33    [W:0.024 / U:29.844 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site