Index: kern/kern_malloc.c =================================================================== RCS file: /usr/repo/src/sys/kern/kern_malloc.c,v retrieving revision 1.149 diff -u -r1.149 kern_malloc.c --- kern/kern_malloc.c 3 Nov 2005 13:48:59 -0000 1.149 +++ kern/kern_malloc.c 30 Dec 2005 11:19:32 -0000 @@ -142,12 +142,6 @@ static uma_zone_t mt_zone; -#ifdef DEBUG_MEMGUARD -u_int vm_memguard_divisor; -SYSCTL_UINT(_vm, OID_AUTO, memguard_divisor, CTLFLAG_RD, &vm_memguard_divisor, - 0, "(kmem_size/memguard_divisor) == memguard submap size"); -#endif - u_int vm_kmem_size; SYSCTL_UINT(_vm, OID_AUTO, kmem_size, CTLFLAG_RD, &vm_kmem_size, 0, "Size of kernel memory"); @@ -304,8 +298,7 @@ ("malloc(M_WAITOK) in interrupt context")); #ifdef DEBUG_MEMGUARD - /* XXX CHANGEME! */ - if (mtp == M_SUBPROC) + if (memguard_cmp(mtp)) return memguard_alloc(size, flags); #endif @@ -359,8 +352,7 @@ return; #ifdef DEBUG_MEMGUARD - /* XXX CHANGEME! */ - if (mtp == M_SUBPROC) { + if (memguard_cmp(mtp)) { memguard_free(addr); return; } @@ -423,8 +415,7 @@ */ #ifdef DEBUG_MEMGUARD -/* XXX: CHANGEME! */ -if (mtp == M_SUBPROC) { +if (memguard_cmp(mtp)) { slab = NULL; alloc = size; } else { @@ -549,7 +540,7 @@ * scenarios as they occur. It is only used for debugging. */ vm_memguard_divisor = 10; - TUNABLE_INT_FETCH("vm.memguard_divisor", &vm_memguard_divisor); + TUNABLE_INT_FETCH("vm.memguard.divisor", &vm_memguard_divisor); /* Pick a conservative value if provided value sucks. */ if ((vm_memguard_divisor <= 0) || @@ -649,6 +640,19 @@ uma_zfree(mt_zone, mtip); } +struct malloc_type * +malloc_desc2type(const char *desc) +{ + struct malloc_type *mtp; + + mtx_assert(&malloc_mtx, MA_OWNED); + for (mtp = kmemstatistics; mtp != NULL; mtp = mtp->ks_next) { + if (strcmp(mtp->ks_shortdesc, desc) == 0) + return (mtp); + } + return (NULL); +} + static int sysctl_kern_malloc(SYSCTL_HANDLER_ARGS) { Index: sys/malloc.h =================================================================== RCS file: /usr/repo/src/sys/sys/malloc.h,v retrieving revision 1.82 diff -u -r1.82 malloc.h --- sys/malloc.h 23 Aug 2005 20:31:21 -0000 1.82 +++ sys/malloc.h 30 Dec 2005 10:36:21 -0000 @@ -189,6 +189,8 @@ int flags); void *reallocf(void *addr, unsigned long size, struct malloc_type *type, int flags); + +struct malloc_type *malloc_desc2type(const char *desc); #endif /* _KERNEL */ #endif /* !_SYS_MALLOC_H_ */ Index: vm/memguard.c =================================================================== RCS file: /usr/repo/src/sys/vm/memguard.c,v retrieving revision 1.5 diff -u -r1.5 memguard.c --- vm/memguard.c 16 Feb 2005 21:45:59 -0000 1.5 +++ vm/memguard.c 30 Dec 2005 11:07:04 -0000 @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,67 @@ */ #define MAX_PAGES_PER_ITEM 64 +SYSCTL_NODE(_vm, OID_AUTO, memguard, CTLFLAG_RW, NULL, "MemGuard data"); +/* + * The vm_memguard_divisor variable controls how much of kmem_map should be + * reserved for MemGuard. + */ +u_int vm_memguard_divisor; +SYSCTL_UINT(_vm_memguard, OID_AUTO, divisor, CTLFLAG_RD, &vm_memguard_divisor, + 0, "(kmem_size/memguard_divisor) == memguard submap size"); + +/* + * Short description (ks_shortdesc) of memory type to monitor. + */ +static char vm_memguard_desc[128] = ""; +static struct malloc_type *vm_memguard_mtype = NULL; +TUNABLE_STR("vm.memguard.desc", vm_memguard_desc, sizeof(vm_memguard_desc)); +static int +memguard_sysctl_desc(SYSCTL_HANDLER_ARGS) +{ + struct malloc_type_internal *mtip; + struct malloc_type_stats *mtsp; + struct malloc_type *mtp; + char desc[128]; + long bytes; + int error, i; + + strlcpy(desc, vm_memguard_desc, sizeof(desc)); + error = sysctl_handle_string(oidp, desc, sizeof(desc), req); + if (error != 0 || req->newptr == NULL) + return (error); + + /* + * We can change memory type when no memory has been allocated for it + * or when there is no such memory type yet (ie. it will be loaded with + * kernel module). + */ + bytes = 0; + mtx_lock(&malloc_mtx); + mtp = malloc_desc2type(desc); + if (mtp != NULL) { + mtip = mtp->ks_handle; + for (i = 0; i < MAXCPU; i++) { + mtsp = &mtip->mti_stats[i]; + bytes += mtsp->mts_memalloced; + bytes -= mtsp->mts_memfreed; + } + } + if (bytes > 0) + error = EBUSY; + else { + /* + * If mtp is NULL, it will be initialized in memguard_cmp(). + */ + vm_memguard_mtype = mtp; + strlcpy(vm_memguard_desc, desc, sizeof(vm_memguard_desc)); + } + mtx_unlock(&malloc_mtx); + return (error); +} +SYSCTL_PROC(_vm_memguard, OID_AUTO, desc, CTLTYPE_STRING | CTLFLAG_RW, 0, 0, + memguard_sysctl_desc, "A", "Short description of memory type to monitor"); + /* * Global MemGuard data. */ @@ -239,6 +301,34 @@ MEMGUARD_CRIT_SECTION_EXIT; } +int +memguard_cmp(struct malloc_type *mtp) +{ + +#if 1 + /* + * The safest way of comparsion is to always compare short description + * string of memory type, but it is also the slowest way. + */ + return (strcmp(mtp->ks_shortdesc, vm_memguard_desc) == 0); +#else + /* + * If we compare pointers, there are two possible problems: + * 1. Memory type was unloaded and new memory type was allocated at the + * same address. + * 2. Memory type was unloaded and loaded again, but allocated at a + * different address. + */ + if (vm_memguard_mtype != NULL) + return (mtp == vm_memguard_mtype); + if (strcmp(mtp->ks_shortdesc, vm_memguard_desc) == 0) { + vm_memguard_mtype = mtp; + return (1); + } + return (0); +#endif +} + /* * Guard a page containing specified object (make it read-only so that * future writes to it fail). Index: vm/memguard.h =================================================================== RCS file: /usr/repo/src/sys/vm/memguard.h,v retrieving revision 1.2 diff -u -r1.2 memguard.h --- vm/memguard.h 16 Feb 2005 21:45:59 -0000 1.2 +++ vm/memguard.h 30 Dec 2005 10:56:33 -0000 @@ -26,6 +26,9 @@ * $FreeBSD: src/sys/vm/memguard.h,v 1.2 2005/02/16 21:45:59 bmilekic Exp $ */ +extern u_int vm_memguard_divisor; + void memguard_init(vm_map_t parent_map, unsigned long size); void *memguard_alloc(unsigned long size, int flags); void memguard_free(void *addr); +int memguard_cmp(struct malloc_type *mtp);