Commit a1c9db9f authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] in-kernel topology API

From Matthew Dobson <colpatch@us.ibm.com>

"This patch adds a 'simple' in-kernel topology API.  This API allows
 for three primary topology elements: CPUs, memory blocks, and nodes.
 The API allows for the discovery of which CPUs/Memory Blocks reside on
 which nodes, and vice versa.  Also implemented is a macro to get a
 bitmask of CPUs on a particular node.  This API is platform neutral."

We need this API for per-node-kswapd - without it there is no means by
which each kswapd can be bound to its node's CPUs.  And we rather need
per-node-kswapd...

The patch also uses the new API to bind each kswapd instance to its
node's CPUs
parent db7b0c9f
...@@ -107,15 +107,6 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n) ...@@ -107,15 +107,6 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
#ifdef CONFIG_NUMA_SCHED #ifdef CONFIG_NUMA_SCHED
#define NODE_SCHEDULE_DATA(nid) (&((PLAT_NODE_DATA(nid))->schedule_data)) #define NODE_SCHEDULE_DATA(nid) (&((PLAT_NODE_DATA(nid))->schedule_data))
#endif #endif
#ifdef CONFIG_ALPHA_WILDFIRE
/* With wildfire assume 4 CPUs per node */
#define cputonode(cpu) ((cpu) >> 2)
#else
#define cputonode(cpu) 0
#endif /* CONFIG_ALPHA_WILDFIRE */
#define numa_node_id() cputonode(smp_processor_id())
#endif /* CONFIG_NUMA */ #endif /* CONFIG_NUMA */
#endif /* CONFIG_DISCONTIGMEM */ #endif /* CONFIG_DISCONTIGMEM */
......
#ifndef _ASM_ALPHA_TOPOLOGY_H
#define _ASM_ALPHA_TOPOLOGY_H
#ifdef CONFIG_NUMA
#ifdef CONFIG_ALPHA_WILDFIRE
/* With wildfire assume 4 CPUs per node */
#define __cpu_to_node(cpu) ((cpu) >> 2)
#endif /* CONFIG_ALPHA_WILDFIRE */
#endif /* CONFIG_NUMA */
/* Get the rest of the topology definitions */
#include <asm-generic/topology.h>
#endif /* _ASM_ALPHA_TOPOLOGY_H */
#ifndef _ASM_ARM_TOPOLOGY_H
#define _ASM_ARM_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_ARM_TOPOLOGY_H */
#ifndef _ASM_CRIS_TOPOLOGY_H
#define _ASM_CRIS_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_CRIS_TOPOLOGY_H */
/*
* linux/include/asm-generic/topology.h
*
* Written by: Matthew Dobson, IBM Corporation
*
* Copyright (C) 2002, IBM Corp.
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <colpatch@us.ibm.com>
*/
#ifndef _ASM_GENERIC_TOPOLOGY_H
#define _ASM_GENERIC_TOPOLOGY_H
/* Other architectures wishing to use this simple topology API should fill
in the below functions as appropriate in their own <asm/topology.h> file. */
#ifndef __cpu_to_node
#define __cpu_to_node(cpu) (0)
#endif
#ifndef __memblk_to_node
#define __memblk_to_node(memblk) (0)
#endif
#ifndef __parent_node
#define __parent_node(nid) (0)
#endif
#ifndef __node_to_first_cpu
#define __node_to_first_cpu(node) (0)
#endif
#ifndef __node_to_cpu_mask
#define __node_to_cpu_mask(node) (cpu_online_map)
#endif
#ifndef __node_to_memblk
#define __node_to_memblk(node) (0)
#endif
#endif /* _ASM_GENERIC_TOPOLOGY_H */
...@@ -19,10 +19,6 @@ ...@@ -19,10 +19,6 @@
#endif /* CONFIG_NUMA */ #endif /* CONFIG_NUMA */
#endif /* CONFIG_X86_NUMAQ */ #endif /* CONFIG_X86_NUMAQ */
#ifdef CONFIG_NUMA
#define numa_node_id() _cpu_to_node(smp_processor_id())
#endif /* CONFIG_NUMA */
extern struct pglist_data *node_data[]; extern struct pglist_data *node_data[];
/* /*
......
/*
* linux/include/asm-i386/topology.h
*
* Written by: Matthew Dobson, IBM Corporation
*
* Copyright (C) 2002, IBM Corp.
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <colpatch@us.ibm.com>
*/
#ifndef _ASM_I386_TOPOLOGY_H
#define _ASM_I386_TOPOLOGY_H
#ifdef CONFIG_X86_NUMAQ
#include <asm/smpboot.h>
/* Returns the number of the node containing CPU 'cpu' */
#define __cpu_to_node(cpu) (cpu_to_logical_apicid(cpu) >> 4)
/* Returns the number of the node containing MemBlk 'memblk' */
#define __memblk_to_node(memblk) (memblk)
/* Returns the number of the node containing Node 'nid'. This architecture is flat,
so it is a pretty simple function! */
#define __parent_node(nid) (nid)
/* Returns the number of the first CPU on Node 'node'.
* This should be changed to a set of cached values
* but this will do for now.
*/
static inline int __node_to_first_cpu(int node)
{
int i, cpu, logical_apicid = node << 4;
for(i = 1; i < 16; i <<= 1)
/* check to see if the cpu is in the system */
if ((cpu = logical_apicid_to_cpu(logical_apicid | i)) >= 0)
/* if yes, return it to caller */
return cpu;
return 0;
}
/* Returns a bitmask of CPUs on Node 'node'.
* This should be changed to a set of cached bitmasks
* but this will do for now.
*/
static inline unsigned long __node_to_cpu_mask(int node)
{
int i, cpu, logical_apicid = node << 4;
unsigned long mask = 0UL;
for(i = 1; i < 16; i <<= 1)
/* check to see if the cpu is in the system */
if ((cpu = logical_apicid_to_cpu(logical_apicid | i)) >= 0)
/* if yes, add to bitmask */
mask |= 1 << cpu;
return mask;
}
/* Returns the number of the first MemBlk on Node 'node' */
#define __node_to_memblk(node) (node)
#else /* !CONFIG_X86_NUMAQ */
/*
* Other i386 platforms should define their own version of the
* above macros here.
*/
#include <asm-generic/topology.h>
#endif /* CONFIG_X86_NUMAQ */
#endif /* _ASM_I386_TOPOLOGY_H */
#ifndef _ASM_IA64_TOPOLOGY_H
#define _ASM_IA64_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_IA64_TOPOLOGY_H */
#ifndef _ASM_M68K_TOPOLOGY_H
#define _ASM_M68K_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_M68K_TOPOLOGY_H */
#ifndef _ASM_MIPS_TOPOLOGY_H
#define _ASM_MIPS_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_MIPS_TOPOLOGY_H */
...@@ -28,8 +28,6 @@ extern plat_pg_data_t *plat_node_data[]; ...@@ -28,8 +28,6 @@ extern plat_pg_data_t *plat_node_data[];
#define PLAT_NODE_DATA_LOCALNR(p, n) \ #define PLAT_NODE_DATA_LOCALNR(p, n) \
(((p) >> PAGE_SHIFT) - PLAT_NODE_DATA(n)->gendata.node_start_pfn) (((p) >> PAGE_SHIFT) - PLAT_NODE_DATA(n)->gendata.node_start_pfn)
#define numa_node_id() cputocnode(current->processor)
#ifdef CONFIG_DISCONTIGMEM #ifdef CONFIG_DISCONTIGMEM
/* /*
......
#ifndef _ASM_MIPS64_TOPOLOGY_H
#define _ASM_MIPS64_TOPOLOGY_H
#include <asm/mmzone.h>
#define __cpu_to_node(cpu) (cputocnode(cpu))
/* Get the rest of the topology definitions */
#include <asm-generic/topology.h>
#endif /* _ASM_MIPS64_TOPOLOGY_H */
#ifndef _ASM_PARISC_TOPOLOGY_H
#define _ASM_PARISC_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_PARISC_TOPOLOGY_H */
#ifndef _ASM_PPC_TOPOLOGY_H
#define _ASM_PPC_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_PPC_TOPOLOGY_H */
...@@ -72,7 +72,6 @@ static inline int __cpu_to_node(int cpu) ...@@ -72,7 +72,6 @@ static inline int __cpu_to_node(int cpu)
return node; return node;
} }
#define numa_node_id() __cpu_to_node(smp_processor_id())
#endif /* CONFIG_NUMA */ #endif /* CONFIG_NUMA */
/* /*
......
#ifndef _ASM_PPC64_TOPOLOGY_H
#define _ASM_PPC64_TOPOLOGY_H
#include <asm/mmzone.h>
#ifdef CONFIG_NUMA
/* XXX grab this from the device tree - Anton */
#define __cpu_to_node(cpu) ((cpu) >> CPU_SHIFT_BITS)
#endif /* CONFIG_NUMA */
/* Get the rest of the topology definitions */
#include <asm-generic/topology.h>
#endif /* _ASM_PPC64_TOPOLOGY_H */
#ifndef _ASM_S390_TOPOLOGY_H
#define _ASM_S390_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_S390_TOPOLOGY_H */
#ifndef _ASM_S390X_TOPOLOGY_H
#define _ASM_S390X_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_S390X_TOPOLOGY_H */
#ifndef _ASM_SH_TOPOLOGY_H
#define _ASM_SH_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_SH_TOPOLOGY_H */
#ifndef _ASM_SPARC_TOPOLOGY_H
#define _ASM_SPARC_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_SPARC_TOPOLOGY_H */
#ifndef _ASM_SPARC64_TOPOLOGY_H
#define _ASM_SPARC64_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_SPARC64_TOPOLOGY_H */
#ifndef _ASM_X86_64_TOPOLOGY_H
#define _ASM_X86_64_TOPOLOGY_H
#include <asm-generic/topology.h>
#endif /* _ASM_X86_64_TOPOLOGY_H */
...@@ -249,13 +249,23 @@ static inline struct zone *next_zone(struct zone *zone) ...@@ -249,13 +249,23 @@ static inline struct zone *next_zone(struct zone *zone)
#define for_each_zone(zone) \ #define for_each_zone(zone) \
for (zone = pgdat_list->node_zones; zone; zone = next_zone(zone)) for (zone = pgdat_list->node_zones; zone; zone = next_zone(zone))
#ifdef CONFIG_NUMA
#define MAX_NR_MEMBLKS BITS_PER_LONG /* Max number of Memory Blocks */
#else /* !CONFIG_NUMA */
#define MAX_NR_MEMBLKS 1
#endif /* CONFIG_NUMA */
#include <asm/topology.h>
/* Returns the number of the current Node. */
#define numa_node_id() (__cpu_to_node(smp_processor_id()))
#ifndef CONFIG_DISCONTIGMEM #ifndef CONFIG_DISCONTIGMEM
#define NODE_DATA(nid) (&contig_page_data) #define NODE_DATA(nid) (&contig_page_data)
#define NODE_MEM_MAP(nid) mem_map #define NODE_MEM_MAP(nid) mem_map
#define MAX_NR_NODES 1 #define MAX_NR_NODES 1
#else /* !CONFIG_DISCONTIGMEM */ #else /* CONFIG_DISCONTIGMEM */
#include <asm/mmzone.h> #include <asm/mmzone.h>
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/topology.h>
#include <linux/swapops.h> #include <linux/swapops.h>
/* /*
...@@ -739,6 +741,7 @@ int kswapd(void *p) ...@@ -739,6 +741,7 @@ int kswapd(void *p)
DECLARE_WAITQUEUE(wait, tsk); DECLARE_WAITQUEUE(wait, tsk);
daemonize(); daemonize();
set_cpus_allowed(tsk, __node_to_cpu_mask(pgdat->node_id));
sprintf(tsk->comm, "kswapd%d", pgdat->node_id); sprintf(tsk->comm, "kswapd%d", pgdat->node_id);
sigfillset(&tsk->blocked); sigfillset(&tsk->blocked);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment