Re: Adding realloc()
* Archie Cobbs [EMAIL PROTECTED] [020311 22:00] wrote: Hi, I've had the need for a realloc() in the kernel several times before and am having it once again. Finally figured it's time to do something about it. Does anyone have problems with the attached patch? This patch adds realloc() and also fixes the semantics of free() to be consistent with userland, in that free(NULL) is legal and does nothing. This will make it possible to simplify some netgraph code and probably other stuff too. Reviews appreciated as well. Where is the update to malloc(9)? What about reallocf? -Alfred To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: Adding realloc()
Alfred Perlstein writes: I've had the need for a realloc() in the kernel several times before and am having it once again. Finally figured it's time to do something about it. Where is the update to malloc(9)? What about reallocf? Good points, thanks.. try this one instead. -Archie __ Archie Cobbs * Packet Design * http://www.packetdesign.com Index: sys/kern/kern_malloc.c === RCS file: /home/ncvs/src/sys/kern/kern_malloc.c,v retrieving revision 1.93 diff -u -r1.93 kern_malloc.c --- kern_malloc.c 12 Sep 2001 08:37:44 - 1.93 +++ kern_malloc.c 12 Mar 2002 22:34:35 - -57,6 +57,16 #include machine/cpu.h #endif +/* + * When realloc() is called, if the new size is sufficiently smaller than + * the old size, realloc() will allocate a new, smaller block to avoid + * wasting memory. 'Sufficiently smaller' is defined as: newsize = + * oldsize / 2^n, where REALLOC_FRACTION defines the value of 'n'. + */ +#ifndef REALLOC_FRACTION +#define REALLOC_FRACTION 1 /* new block if = half the size */ +#endif + MALLOC_DEFINE(M_CACHE, cache, Various Dynamically allocated caches); MALLOC_DEFINE(M_DEVBUF, devbuf, device driver memory); MALLOC_DEFINE(M_TEMP, temp, misc temporary data buffers); -294,6 +304,10 #endif register struct malloc_type *ksp = type; + /* free(NULL, ...) does nothing */ + if (addr == NULL) + return; + KASSERT(kmembase = (char *)addr (char *)addr kmemlimit, (free: address %p out of range, (void *)addr)); kup = btokup(addr); -397,6 +411,66 #endif splx(s); mtx_unlock(malloc_mtx); +} + +/* + * realloc: change the size of a memory block + */ +void * +realloc(addr, size, type, flags) + void *addr; + unsigned long size; + struct malloc_type *type; + int flags; +{ + struct kmemusage *kup; + unsigned long alloc; + void *newaddr; + + /* realloc(NULL, ...) is equivalent to malloc(...) */ + if (addr == NULL) + return (malloc(size, type, flags)); + + /* Sanity check */ + KASSERT(kmembase = (char *)addr (char *)addr kmemlimit, + (realloc: address %p out of range, (void *)addr)); + + /* Get the size of the original block */ + kup = btokup(addr); + alloc = 1 kup-ku_indx; + if (alloc MAXALLOCSAVE) + alloc = kup-ku_pagecnt PAGE_SHIFT; + + /* Reuse the original block if appropriate */ + if (size = alloc + (size (alloc REALLOC_FRACTION) || alloc == MINALLOCSIZE)) + return (addr); + + /* Allocate a new, bigger (or smaller) block */ + if ((newaddr = malloc(size, type, flags)) == NULL) + return (NULL); + + /* Copy over original contents */ + bcopy(addr, newaddr, min(size, alloc)); + free(addr, type); + return (newaddr); +} + +/* + * reallocf: same as realloc() but free memory on failure. + */ +void * +reallocf(addr, size, type, flags) + void *addr; + unsigned long size; + struct malloc_type *type; + int flags; +{ + void *mem; + + if ((mem = realloc(addr, size, type, flags)) == NULL) + free(addr, type); + return (mem); } /* Index: sys/sys/malloc.h === RCS file: /home/ncvs/src/sys/sys/malloc.h,v retrieving revision 1.54 diff -u -r1.54 malloc.h --- malloc.h 10 Aug 2001 06:37:04 - 1.54 +++ malloc.h 12 Mar 2002 22:34:46 - -173,6 +173,10 void *malloc __P((unsigned long size, struct malloc_type *type, int flags)); void malloc_init __P((void *)); void malloc_uninit __P((void *)); +void *realloc __P((void *addr, unsigned long size, + struct malloc_type *type, int flags)); +void *reallocf __P((void *addr, unsigned long size, + struct malloc_type *type, int flags)); #endif /* _KERNEL */ #endif /* !_SYS_MALLOC_H_ */ Index: share/man/man9/malloc.9 === RCS file: /home/ncvs/src/share/man/man9/malloc.9,v retrieving revision 1.21 diff -u -r1.21 malloc.9 --- malloc.9 1 Oct 2001 16:09:25 - 1.21 +++ malloc.9 12 Mar 2002 22:34:57 - -54,18 +54,63 .Ft void .Fn free void *addr struct malloc_type *type .Fn FREE void *addr struct malloc_type *type +.Ft void * +.Fn realloc void *addr unsigned long size struct malloc_type *type int flags +.Ft void * +.Fn reallocf void *addr unsigned long size struct malloc_type *type int flags .Sh DESCRIPTION The .Fn malloc function allocates uninitialized memory in kernel address space for an object whose size is specified by .Fa size . +.Pp .Fn free releases memory at address .Fa addr that was previously allocated by .Fn malloc -for re-use. The memory is not zeroed. +for re-use. +The memory is not zeroed. +If +.Fa addr +is +.Dv NULL , +then +.Fn free +does nothing. +.Pp +The +.Fn realloc +function changes the size of the previously allocated memory referenced by +.Fa addr +to +.Fa size +bytes. +The contents of the memory are unchanged up to the lesser of the new and +old sizes. +Note that the returned value may
Re: Adding realloc()
* Archie Cobbs [EMAIL PROTECTED] [020312 14:45] wrote: Alfred Perlstein writes: I've had the need for a realloc() in the kernel several times before and am having it once again. Finally figured it's time to do something about it. Where is the update to malloc(9)? What about reallocf? Good points, thanks.. try this one instead. That looks ok, afaik you could do some vm tricks to avoid having to malloc/free when doing realloc()'s that are larger than PAGE_SIZE. -Alfred To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: Adding realloc()
Alfred Perlstein writes: I've had the need for a realloc() in the kernel several times before and am having it once again. Finally figured it's time to do something about it. Where is the update to malloc(9)? What about reallocf? Good points, thanks.. try this one instead. That looks ok, afaik you could do some vm tricks to avoid having to malloc/free when doing realloc()'s that are larger than PAGE_SIZE. Yeah I was wondering about that how hard it would be. That'd be the next step I guess.. thanks for the comments. -Archie __ Archie Cobbs * Packet Design * http://www.packetdesign.com To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Adding realloc()
Hi, I've had the need for a realloc() in the kernel several times before and am having it once again. Finally figured it's time to do something about it. Does anyone have problems with the attached patch? This patch adds realloc() and also fixes the semantics of free() to be consistent with userland, in that free(NULL) is legal and does nothing. This will make it possible to simplify some netgraph code and probably other stuff too. Reviews appreciated as well. Thanks, -Archie __ Archie Cobbs * Packet Design * http://www.packetdesign.com Index: kern/kern_malloc.c === RCS file: /home/ncvs/src/sys/kern/kern_malloc.c,v retrieving revision 1.93 diff -u -r1.93 kern_malloc.c --- kern_malloc.c 12 Sep 2001 08:37:44 - 1.93 +++ kern_malloc.c 12 Mar 2002 00:06:03 - -57,6 +57,16 #include machine/cpu.h #endif +/* + * When realloc() is called, if the new size is sufficiently smaller than + * the old size, realloc() will allocate a new, smaller block to avoid + * wasting memory. 'Sufficiently smaller' is defined as: newsize = + * oldsize / 2^n, where REALLOC_FRACTION defines the value of 'n'. + */ +#ifndef REALLOC_FRACTION +#define REALLOC_FRACTION 1 /* new block if = half the size */ +#endif + MALLOC_DEFINE(M_CACHE, cache, Various Dynamically allocated caches); MALLOC_DEFINE(M_DEVBUF, devbuf, device driver memory); MALLOC_DEFINE(M_TEMP, temp, misc temporary data buffers); -294,6 +304,10 #endif register struct malloc_type *ksp = type; + /* free(NULL, ...) does nothing */ + if (addr == NULL) + return; + KASSERT(kmembase = (char *)addr (char *)addr kmemlimit, (free: address %p out of range, (void *)addr)); kup = btokup(addr); -397,6 +411,49 #endif splx(s); mtx_unlock(malloc_mtx); +} + +/* + * realloc: change the size of a memory block + */ +void * +realloc(addr, size, type, flags) + void *addr; + unsigned long size; + struct malloc_type *type; + int flags; +{ + struct kmemusage *kup; + unsigned long alloc; + void *newaddr; + + /* realloc(NULL, ...) is equivalent to malloc(...) */ + if (addr == NULL) + return (malloc(size, type, flags)); + + /* Sanity check */ + KASSERT(kmembase = (char *)addr (char *)addr kmemlimit, + (realloc: address %p out of range, (void *)addr)); + + /* Get the size of the original block */ + kup = btokup(addr); + alloc = 1 kup-ku_indx; + if (alloc MAXALLOCSAVE) + alloc = kup-ku_pagecnt PAGE_SHIFT; + + /* Reuse the original block if appropriate */ + if (size = alloc + (size (alloc REALLOC_FRACTION) || alloc == MINALLOCSIZE)) + return (addr); + + /* Allocate a new, bigger (or smaller) block */ + if ((newaddr = malloc(size, type, flags)) == NULL) + return (NULL); + + /* Copy over original contents */ + bcopy(addr, newaddr, min(size, alloc)); + free(addr, type); + return (newaddr); } /* Index: sys/malloc.h === RCS file: /home/ncvs/src/sys/sys/malloc.h,v retrieving revision 1.54 diff -u -r1.54 malloc.h --- malloc.h 10 Aug 2001 06:37:04 - 1.54 +++ malloc.h 12 Mar 2002 00:06:12 - -173,6 +173,8 void *malloc __P((unsigned long size, struct malloc_type *type, int flags)); void malloc_init __P((void *)); void malloc_uninit __P((void *)); +void *realloc __P((void *addr, unsigned long size, + struct malloc_type *type, int flags)); #endif /* _KERNEL */ #endif /* !_SYS_MALLOC_H_ */