From owner-freebsd-current Mon Mar 11 22: 0:10 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 0DF9837B405 for ; Mon, 11 Mar 2002 22:00: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 WAA33444 for ; Mon, 11 Mar 2002 22:00:02 -0800 (PST) Received: (from archie@localhost) by arch20m.dellroad.org (8.11.6/8.11.6) id g2C5xI364432 for freebsd-current@freebsd.org; Mon, 11 Mar 2002 21:59:18 -0800 (PST) (envelope-from archie) From: Archie Cobbs Message-Id: <200203120559.g2C5xI364432@arch20m.dellroad.org> Subject: Adding realloc() To: freebsd-current@freebsd.org Date: Mon, 11 Mar 2002 21:59:17 -0800 (PST) X-Mailer: ELM [version 2.4ME+ PL88 (25)] MIME-Version: 1.0 Content-Type: multipart/mixed; boundary=ELM720472082-64379-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 --ELM720472082-64379-0_ Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII 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 --ELM720472082-64379-0_ Content-Transfer-Encoding: 7bit Content-Type: text/x-patch Content-Disposition: attachment; filename=REALLOC.patch Content-Description: 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 -0000 1.93 +++ kern_malloc.c 12 Mar 2002 00:06:03 -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,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 -0000 1.54 +++ malloc.h 12 Mar 2002 00:06:12 -0000 @@ -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_ */ --ELM720472082-64379-0_-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message