Memory Binding API
Subsystems (6)
PATCH 1/1 Memory Binding API
Here is a Memory Binding API. This allows processes to bind themselves to particular blocks of memory in a multi-memory block system. This patch is based on top of the Simple Topology API I posted a few moments ago. The calls take a simple bitmask of memblocks.
This is a scaled down version of a full NUMA API I posted several times in the past, to a distinct lack of fanfare. I hope that this smaller patch holds more interest to the community...
Enjoy!
-Matt
arch/i386/config.in +4 -0
@@ -165,6 +165,10 @@ fi else bool 'Multiquad NUMA system' CONFIG_MULTIQUAD + if [ "$CONFIG_MULTIQUAD" = y ]; then + bool 'Memory Binding API Support' CONFIG_MEMBIND + bool 'IBM/Sequent NUMA-Q Hardware Support' CONFIG_IBMNUMAQ + fi fi bool 'Machine Check Exception' CONFIG_X86_MCE
include/asm-i386/smp.h +6 -0
@@ -55,6 +55,7 @@extern void smp_alloc_memory (void );extern unsigned long phys_cpu_present_map;extern unsigned long cpu_online_map; +extern unsigned long memblk_online_map;extern volatile unsigned long smp_invalidate_needed;extern int pic_mode;extern int smp_num_siblings;
@@ -99,6 +100,11 @@return hweight32 (cpu_online_map); } +extern inline unsigned int num_online_memblks (void ) +{ +return hweight32 (memblk_online_map); +} +extern inline int any_online_cpu (unsigned int mask) {if (mask & cpu_online_map)
include/linux/init_task.h +1 -0
@@ -59,6 +59,7 @@ children: LIST_HEAD_INIT(tsk.children), \ sibling: LIST_HEAD_INIT(tsk.sibling), \ thread_group: LIST_HEAD_INIT(tsk.thread_group), \ + memblk_binding: { MEMBLK_NO_BINDING, MPOL_STRICT }, \ wait_chldexit: __WAIT_QUEUE_HEAD_INITIALIZER(tsk.wait_chldexit),\ real_timer: { \ function: it_real_fn \
include/linux/membind.h +29 -0
@@ -27,6 +27,35 @@#ifndef _LINUX_MEMBIND_H_#define _LINUX_MEMBIND_H_ +#include <linux/types.h> + +#ifdef CONFIG_MEMBIND +#define NR_MEMBLKS 32/* Max number of Memory Blocks */ +#else +#define NR_MEMBLKS 1 +#endif + +typedef unsigned long memblk_bitmask_t ; +#define MEMBLK_NO_BINDING ((memblk_bitmask_t) 0)/* A '0' means use the memblk +and a '1' means *don't* */ + +#define MPOL_STRICT 0/* Memory MUST be allocated according to binding */ +#define MPOL_LOOSE 1/* Memory will be allocated according to binding, +but can fall back to other memory blocks if necessary. */ +#define MPOL_FIRST 2/* UNUSED FOR NOW */ +#define MPOL_STRIPE 4/* UNUSED FOR NOW */ +#define MPOL_RR 8/* UNUSED FOR NOW */ + + +typedef struct memblk_list { +memblk_bitmask_t bitmask; +int behavior; +rwlock_t lock; +}memblk_list_t ; + + +int set_memblk_binding (memblk_bitmask_t ,int ); +memblk_bitmask_t get_memblk_binding (void );int cpu_to_node (int );int memblk_to_node (int );int node_to_node (int );
include/linux/mmzone.h +5 -3
@@ -136,6 +136,7 @@unsigned long node_start_mapnr;unsigned long node_size;int node_id; +int memblk_id;/* A unique ID for each memory block */ struct pglist_data *node_next; } pg_data_t;
@@ -169,14 +170,15 @@#define NODE_MEM_MAP (nid) mem_map#define MAX_NR_NODES 1 -#else /* !CONFIG_DISCONTIGMEM */ +#endif /* !CONFIG_DISCONTIGMEM */ -#include <asm/mmzone.h> +#if defined (CONFIG_DISCONTIGMEM ) || defined (CONFIG_MEMBIND ) +#include <asm/mmzone.h> /* page->zone is currently 8 bits ... */ #define MAX_NR_NODES (255 / MAX_NR_ZONES) -#endif /* !CONFIG_DISCONTIGMEM */ +#endif /* CONFIG_DISCONTIGMEM || CONFIG_MEMBIND */ #define MAP_ALIGN (x) ((((x) % sizeof(struct page)) == 0) ? (x) : ((x) + \ sizeof(struct page) - ((x) % sizeof(struct page))))
include/linux/prctl.h +4 -0
@@ -26,6 +26,10 @@# define PR_FPEMU_NOPRINT 1/* silently emulate fp operations accesses */ # define PR_FPEMU_SIGFPE 2/* don't emulate fp operations, send SIGFPE instead */ +/* Get/Set MemBlk Binding */ +#define PR_SET_MEMBLK_BINDING 11 +#define PR_GET_MEMBLK_BINDING 12 +/* Get CPU/Node */ #define PR_GET_CURR_CPU 13#define PR_GET_CURR_NODE 14
include/linux/sched.h +4 -0
@@ -27,6 +27,7 @@#include <linux/securebits.h> #include <linux/fs_struct.h> #include <linux/compiler.h> +#include <linux/membind.h> struct exec_domain ;
@@ -302,6 +303,9 @@struct task_struct *pidhash_next;struct task_struct **pidhash_pprev; +/* additional Memory Binding stuff */ +memblk_list_t memblk_binding; +wait_queue_head_t wait_chldexit;/* for wait4() */ struct completion *vfork_done;/* for vfork() */
include/linux/smp.h +1 -0
@@ -86,6 +86,7 @@#define smp_call_function (func,info,retry,wait) ({ 0; })static inline void smp_send_reschedule (int cpu) { }static inline void smp_send_reschedule_all (void ) { } +#define memblk_online_map 1#define cpu_online_map 1#define cpu_online (cpu) 1#define num_online_cpus () 1
kernel/Makefile +1 -1
@@ -15,7 +15,7 @@ obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \ module.o exit.o itimer.o time.o softirq.o resource.o \ sysctl.o capability.o ptrace.o timer.o user.o \ - signal.o sys.o kmod.o context.o futex.o platform.o + signal.o sys.o kmod.o context.o futex.o platform.o membind.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += ksyms.o
kernel/membind.c +61 -0
70 lines not on this page · raw message
kernel/sys.c +6 -0
@@ -1292,6 +1292,12 @@ } current->keep_capabilities = arg2;break ; +case PR_SET_MEMBLK_BINDING : + error = (long )set_memblk_binding ((memblk_bitmask_t )arg2, (int )arg3); +break ; +case PR_GET_MEMBLK_BINDING : + error = (long )get_memblk_binding (); +break ;case PR_GET_CURR_CPU : error = (long )get_curr_cpu ();break ;
mm/numa.c +63 -13
123 lines not on this page · raw message
mm/page_alloc.c +5 -0
@@ -41,6 +41,8 @@static int zone_balance_min[MAX_NR_ZONES ]__initdata = {20 ,20 ,20 , };static int zone_balance_max[MAX_NR_ZONES ]__initdata = {255 ,255 ,255 , }; +extern unsigned long memblk_online_map; +/* * Temporary debugging check for pages not lying within a given zone. */
@@ -921,6 +923,9 @@void __init free_area_init (unsigned long *zones_size) {free_area_init_core (0 , &contig_page_data, &mem_map, zones_size,0 ,0 ,0 ); + contig_page_data.node_id =0 ; + contig_page_data.memblk_id =0 ; + memblk_online_map =1UL ; }static int __init setup_mem_frac (char *str)