From owner-freebsd-current Tue Mar 12 14:45:17 2002 Delivered-To: freebsd-current@freebsd.org Received: from InterJet.dellroad.org (adsl-63-194-81-26.dsl.snfc21.pacbell.net [63.194.81.26]) by hub.freebsd.org (Postfix) with ESMTP id 8D41A37B404 for ; Tue, 12 Mar 2002 14:45:03 -0800 (PST) Received: from arch20m.dellroad.org (arch20m.dellroad.org [10.1.1.20]) by InterJet.dellroad.org (8.9.1a/8.9.1) with ESMTP id OAA39254; Tue, 12 Mar 2002 14:38:22 -0800 (PST) Received: (from archie@localhost) by arch20m.dellroad.org (8.11.6/8.11.6) id g2CMbbY67802; Tue, 12 Mar 2002 14:37:37 -0800 (PST) (envelope-from archie) From: Archie Cobbs Message-Id: <200203122237.g2CMbbY67802@arch20m.dellroad.org> Subject: Re: Adding realloc() In-Reply-To: <20020312215305.GL92565@elvis.mu.org> "from Alfred Perlstein at Mar 12, 2002 01:53:05 pm" To: Alfred Perlstein Date: Tue, 12 Mar 2002 14:37:37 -0800 (PST) Cc: freebsd-current@freebsd.org X-Mailer: ELM [version 2.4ME+ PL88 (25)] MIME-Version: 1.0 Content-Type: multipart/mixed; boundary=ELM72051456-67788-0_ Content-Transfer-Encoding: 7bit Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG --ELM72051456-67788-0_ Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII 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 --ELM72051456-67788-0_ Content-Transfer-Encoding: 7bit Content-Type: text/x-patch Content-Disposition: attachment; filename=REALLOC.patch Content-Description: 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 -0000 1.93 +++ kern_malloc.c 12 Mar 2002 22:34:35 -0000 @@ -57,6 +57,16 @@ #include #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 -0000 1.54 +++ malloc.h 12 Mar 2002 22:34:46 -0000 @@ -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 -0000 1.21 +++ malloc.9 12 Mar 2002 22:34:57 -0000 @@ -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 differ from +.Fa addr . +If the requested memory cannot be allocated, +.Dv NULL +is returned and the memory referenced by +.Fa addr +is valid and unchanged. +If +.Fa addr +is +.Dv NULL , +the +.Fn realloc +function behaves identically to +.Fn malloc +for the specified size. +.Pp +The +.Fn reallocf +function call is identical to the realloc function call, except that it +will free the passed pointer when the requested memory cannot be allocated. +.Pp The .Fn MALLOC macro variant is functionally equivalent to @@ -92,26 +137,35 @@ Causes the allocated memory to be set to all zeros. .It Dv M_NOWAIT Causes -.Fn malloc +.Fn malloc , +.Fn realloc , +or +.Fn reallocf to return .Dv NULL if the request cannot be immediately fulfilled due to resource shortage. -Otherwise, -.Fn malloc -may call sleep to wait for resources to be released by other processes. +Otherwise, the current process may be put to sleep to wait for +resources to be released by other processes. If this flag is set, .Fn malloc will return .Dv NULL -rather then block. Note that +rather then block. +Note that .Dv M_WAITOK is defined to be 0, meaning that blocking operation is the default. +Also note that +.Dv M_NOWAIT +is required when running in an interrupt context. .It Dv M_WAITOK Indicates that it is Ok to wait for resources. It is unconveniently defined as 0 so care should be taken never to compare against this value directly or try to AND it as a flag. The default operation is to block until the memory allocation succeeds. -.Fn malloc +.Fn malloc , +.Fn realloc , +and +.Fn reallocf can only return .Dv NULL if @@ -157,13 +211,22 @@ .Ed .Sh RETURN VALUES -.Fn malloc -returns a kernel virtual address that is suitably aligned for storage of +.Fn malloc , +.Fn realloc , +and +.Fn reallocf +return a kernel virtual address that is suitably aligned for storage of any type of object, or .Dv NULL -if the request could not be satisfied and +if the request could not be satisfied (implying that .Dv M_NOWAIT -was set. +was set). +.Sh IMPLEMENTATION NOTES +The memory allocator allocates memory in chunks that have size a power +of two for requests up to the size of a page of memory. +For larger requests, one or more pages is allocated. +While it should not be relied upon, this information may be useful for +optimizing the efficiency of memory use. .Sh SEE ALSO .Xr vmstat 8 .Sh DIAGNOSTICS Index: share/man/man9/Makefile =================================================================== RCS file: /home/ncvs/src/share/man/man9/Makefile,v retrieving revision 1.153 diff -u -r1.153 Makefile --- Makefile 6 Mar 2002 01:53:35 -0000 1.153 +++ Makefile 12 Mar 2002 22:36:52 -0000 @@ -156,6 +156,7 @@ MLINKS+=make_dev.9 destroy_dev.9 MLINKS+=make_dev.9 make_dev_alias.9 MLINKS+=malloc.9 FREE.9 malloc.9 MALLOC.9 malloc.9 free.9 +MLINKS+=malloc.9 realloc.9 malloc.9 reallocf.9 MLINKS+=mi_switch.9 cpu_switch.9 mi_switch.9 cpu_throw.9 MLINKS+=namei.9 NDINIT.9 MLINKS+=namei.9 NDFREE.9 --ELM72051456-67788-0_-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message