mm: NUMA aware alloc_task_struct_node()
authorEric Dumazet <eric.dumazet@gmail.com>
Tue, 22 Mar 2011 23:30:41 +0000 (16:30 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 23 Mar 2011 00:44:01 +0000 (17:44 -0700)
All kthreads being created from a single helper task, they all use memory
from a single node for their kernel stack and task struct.

This patch suite creates kthread_create_on_cpu(), adding a 'cpu' parameter
to parameters already used by kthread_create().

This parameter serves in allocating memory for the new kthread on its
memory node if available.

Users of this new function are : ksoftirqd, kworker, migration, pktgend...

This patch:

Add a node parameter to alloc_task_struct(), and change its name to
alloc_task_struct_node()

This change is needed to allow NUMA aware kthread_create_on_cpu()

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Acked-by: David S. Miller <davem@davemloft.net>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Tejun Heo <tj@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: David Howells <dhowells@redhat.com>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/frv/include/asm/processor.h
arch/frv/kernel/process.c
arch/ia64/include/asm/thread_info.h
arch/um/include/asm/processor-generic.h
kernel/fork.c

index 3744f2e47f48fcd92fe03e9e89b550b841736e6d..4b789ab182b0879e008cb4a8b63943e3390c3bb2 100644 (file)
@@ -137,7 +137,7 @@ unsigned long get_wchan(struct task_struct *p);
 #define        KSTK_ESP(tsk)   ((tsk)->thread.frame0->sp)
 
 /* Allocation and freeing of basic task resources. */
-extern struct task_struct *alloc_task_struct(void);
+extern struct task_struct *alloc_task_struct_node(int node);
 extern void free_task_struct(struct task_struct *p);
 
 #define cpu_relax()    barrier()
index efad12071c2e7b95324e9a1f0a8f7e88a6a7d645..9d359752646741b426596f4fb43671e6000cf18d 100644 (file)
@@ -44,9 +44,10 @@ asmlinkage void ret_from_fork(void);
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
-struct task_struct *alloc_task_struct(void)
+struct task_struct *alloc_task_struct_node(int node)
 {
-       struct task_struct *p = kmalloc(THREAD_SIZE, GFP_KERNEL);
+       struct task_struct *p = kmalloc_node(THREAD_SIZE, GFP_KERNEL, node);
+
        if (p)
                atomic_set((atomic_t *)(p+1), 1);
        return p;
index b6a5ba2aca3429f7bd4a7602c21f81f011bf0205..342004bbefe72344a28d03506cd3a5cf6cbc9218 100644 (file)
@@ -84,7 +84,14 @@ struct thread_info {
 #define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET)
 
 #define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
-#define alloc_task_struct()    ((struct task_struct *)__get_free_pages(GFP_KERNEL | __GFP_COMP, KERNEL_STACK_SIZE_ORDER))
+#define alloc_task_struct_node(node)                                           \
+({                                                                             \
+       struct page *page = alloc_pages_node(node, GFP_KERNEL | __GFP_COMP,     \
+                                            KERNEL_STACK_SIZE_ORDER);          \
+       struct task_struct *ret = page ? page_address(page) : NULL;             \
+                                                                               \
+       ret;
+})
 #define free_task_struct(tsk)  free_pages((unsigned long) (tsk), KERNEL_STACK_SIZE_ORDER)
 
 #endif /* !__ASSEMBLY */
index bed668824b5f94529c8d28e7209078d181f87d4b..d1d1b0d8a0cd9c66d754243f636425e4c942ee46 100644 (file)
@@ -66,7 +66,7 @@ struct thread_struct {
        .request                = { 0 } \
 }
 
-extern struct task_struct *alloc_task_struct(void);
+extern struct task_struct *alloc_task_struct_node(int node);
 
 static inline void release_thread(struct task_struct *task)
 {
index 05b92c457010700a7578bb4fb418e612a8332fa3..cffbe8a4e1fc185da3628a45ecdd381651f8ca00 100644 (file)
@@ -109,8 +109,10 @@ int nr_processes(void)
 }
 
 #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
-# define alloc_task_struct()   kmem_cache_alloc(task_struct_cachep, GFP_KERNEL)
-# define free_task_struct(tsk) kmem_cache_free(task_struct_cachep, (tsk))
+# define alloc_task_struct_node(node)          \
+               kmem_cache_alloc_node(task_struct_cachep, GFP_KERNEL, node)
+# define free_task_struct(tsk)                 \
+               kmem_cache_free(task_struct_cachep, (tsk))
 static struct kmem_cache *task_struct_cachep;
 #endif
 
@@ -249,12 +251,12 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
        struct task_struct *tsk;
        struct thread_info *ti;
        unsigned long *stackend;
-
+       int node = numa_node_id();
        int err;
 
        prepare_to_copy(orig);
 
-       tsk = alloc_task_struct();
+       tsk = alloc_task_struct_node(node);
        if (!tsk)
                return NULL;