Signed-off-by: Paolo 'Blaisorblade' Giarrusso --- um-linux-2.4.27-paolo/arch/um/include/user.h | 2 + um-linux-2.4.27-paolo/arch/um/kernel/process_kern.c | 6 +++ um-linux-2.4.27-paolo/arch/um/main.c | 38 +++++++++++++++++--- 3 files changed, 42 insertions(+), 4 deletions(-) diff -puN arch/um/include/user.h~malloc-use-vmalloc arch/um/include/user.h --- um-linux-2.4.27/arch/um/include/user.h~malloc-use-vmalloc 2005-04-15 11:12:53.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/include/user.h 2005-04-15 11:12:54.000000000 +0200 @@ -14,6 +14,8 @@ extern void *um_kmalloc_atomic(int size) extern void kfree(void *ptr); extern int in_aton(char *str); extern int open_gdb_chan(void); +extern void *um_vmalloc(int size); +extern void vfree(void *ptr); #endif diff -puN arch/um/kernel/process_kern.c~malloc-use-vmalloc arch/um/kernel/process_kern.c --- um-linux-2.4.27/arch/um/kernel/process_kern.c~malloc-use-vmalloc 2005-04-15 11:12:54.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/kernel/process_kern.c 2005-04-15 11:12:54.000000000 +0200 @@ -16,6 +16,7 @@ #include "linux/module.h" #include "linux/init.h" #include "linux/capability.h" +#include "linux/vmalloc.h" #include "asm/unistd.h" #include "asm/mman.h" #include "asm/segment.h" @@ -289,6 +290,11 @@ void *um_kmalloc_atomic(int size) return(kmalloc(size, GFP_ATOMIC)); } +void *um_vmalloc(int size) +{ + return(vmalloc(size)); +} + unsigned long get_fault_addr(void) { return((unsigned long) current->thread.fault_addr); diff -puN arch/um/main.c~malloc-use-vmalloc arch/um/main.c --- um-linux-2.4.27/arch/um/main.c~malloc-use-vmalloc 2005-04-15 11:12:54.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/main.c 2005-04-15 11:12:54.000000000 +0200 @@ -164,10 +164,21 @@ extern void *__real_malloc(int); void *__wrap_malloc(int size) { - if(CAN_KMALLOC()) - return(um_kmalloc(size)); - else + void *ret; + + if(!CAN_KMALLOC()) return(__real_malloc(size)); + else if(size < 128 * 1024) /* kmalloc is good for only 128K */ + ret = um_kmalloc(size); + else ret = um_vmalloc(size); + + /* glibc people insist that if malloc fails, errno should be + * set by malloc as well. So we do. + */ + if(ret == NULL) + errno = ENOMEM; + + return(ret); } void *__wrap_calloc(int n, int size) @@ -181,9 +192,28 @@ void *__wrap_calloc(int n, int size) extern void __real_free(void *); +extern unsigned long high_physmem; + void __wrap_free(void *ptr) { - if(CAN_KMALLOC()) kfree(ptr); + unsigned long addr = (unsigned long) ptr; + + /* We need to know how the allocation happened, so it can be correctly + * freed. This is done by seeing what region of memory the pointer is + * in - + * physical memory - kmalloc/kfree + * kernel virtual memory - vmalloc/vfree + * anywhere else - malloc/free + * If kmalloc is not yet possible, then the kernel memory regions + * may not be set up yet, and the variables not initialized. So, + * free is called. + */ + if(CAN_KMALLOC()){ + if((addr >= uml_physmem) && (addr <= high_physmem)) + kfree(ptr); + else if((addr >= start_vm) && (addr <= end_vm)) + vfree(ptr); + } else __real_free(ptr); } _