diff --git a/lib/libstand/Makefile b/lib/libstand/Makefile index fee2187ac341..38caa1cc05b1 100644 --- a/lib/libstand/Makefile +++ b/lib/libstand/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.2 1998/08/20 08:23:12 msmith Exp $ +# $Id: Makefile,v 1.3 1998/09/15 02:30:22 msmith Exp $ # # Originally from $NetBSD: Makefile,v 1.21 1997/10/26 22:08:38 lukem Exp $ # @@ -13,16 +13,17 @@ NOPIC= YES MAN3= libstand.3 # Mostly OK, some of the libc imports are a bit noisy -CFLAGS+= -Wall +CFLAGS+= -Wall -g .if ${MACHINE_ARCH} == "alpha" CFLAGS+= -mno-fp-regs .endif # standalone components and stuff we have modified locally -SRCS+= __main.c alloc.c bcd.c bswap.c environment.c getopt.c gets.c \ - globals.c pager.c printf.c strdup.c strerror.c strtol.c random.c \ - twiddle.c +SRCS+= __main.c bcd.c bswap.c environment.c getopt.c gets.c globals.c \ + pager.c printf.c strdup.c strerror.c strtol.c random.c sbrk.c \ + twiddle.c zalloc.c zalloc_malloc.c + # string functions from libc .PATH: ${.CURDIR}/../libc/string diff --git a/lib/libstand/alloc.c b/lib/libstand/alloc.c deleted file mode 100644 index 7fc63c18c687..000000000000 --- a/lib/libstand/alloc.c +++ /dev/null @@ -1,244 +0,0 @@ -/* $NetBSD: alloc.c,v 1.11 1997/09/17 16:24:00 drochner Exp $ */ - -/* - * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. - * Copyright (c) 1996 - * Matthias Drochner. All rights reserved. - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * The Mach Operating System project at Carnegie-Mellon University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)alloc.c 8.1 (Berkeley) 6/11/93 - * - * - * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University - * All Rights Reserved. - * - * Author: Alessandro Forin - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ - -/* - * Dynamic memory allocator. - * - * Compile options: - * - * ALLOC_TRACE enable tracing of allocations/deallocations - - * ALLOC_FIRST_FIT use a first-fit allocation algorithm, rather than - * the default best-fit algorithm. - * - * HEAP_LIMIT heap limit address (defaults to "no limit"). - * - * HEAP_START start address of heap (defaults to '&end'). - * - * DEBUG enable debugging sanity checks. - */ - -#include -#include "stand.h" - -/* Default to variable heap operation */ -#define HEAP_VARIABLE -#define DEBUG - -/* - * Each block actually has ALIGN(size_t) + ALIGN(size) bytes allocated - * to it, as follows: - * - * 0 ... (sizeof(size_t) - 1) - * allocated or unallocated: holds size of user-data part of block. - * - * sizeof(size_t) ... (ALIGN(sizeof(size_t)) - 1) - * allocated: unused - * unallocated: depends on packing of struct fl - * - * ALIGN(sizeof(size_t)) ... (ALIGN(sizeof(size_t)) + ALIGN(data size) - 1) - * allocated: user data - * unallocated: depends on packing of struct fl - * - * 'next' is only used when the block is unallocated (i.e. on the free list). - * However, note that ALIGN(sizeof(size_t)) + ALIGN(data size) must - * be at least 'sizeof(struct fl)', so that blocks can be used as structures - * when on the free list. - */ -struct fl { - size_t size; - struct fl *next; -} *freelist = (struct fl *)0; - -#ifdef HEAP_VARIABLE -static char *top, *heapstart, *heaplimit; -void setheap(start, limit) -void *start, *limit; -{ - heapstart = top = start; - heaplimit = limit; -} -#define HEAP_START heapstart -#define HEAP_LIMIT heaplimit -#else /* !HEAP_VARIABLE */ -#ifndef HEAP_START -extern char end[]; -#define HEAP_START end -#endif -static char *top = (char*)HEAP_START; -#endif /* HEAP_VARIABLE */ - -void * -malloc(size) - size_t size; -{ - register struct fl **f = &freelist, **bestf = NULL; - size_t bestsize = 0xffffffff; /* greater than any real size */ - char *help; - int failed; - -#ifdef ALLOC_TRACE - printf("alloc(%u)", size); -#endif - -#ifdef ALLOC_FIRST_FIT - while (*f != (struct fl *)0 && (*f)->size < size) - f = &((*f)->next); - bestf = f; - failed = (*bestf == (struct fl *)0); -#else - /* scan freelist */ - while (*f) { - if ((*f)->size >= size) { - if ((*f)->size == size) /* exact match */ - goto found; - - if ((*f)->size < bestsize) { - /* keep best fit */ - bestf = f; - bestsize = (*f)->size; - } - } - f = &((*f)->next); - } - - /* no match in freelist if bestsize unchanged */ - failed = (bestsize == 0xffffffff); -#endif - - if (failed) { /* nothing found */ - /* - * allocate from heap, keep chunk len in - * first word - */ - help = top; - - /* make _sure_ the region can hold a struct fl. */ - if (size < ALIGN(sizeof (struct fl *))) - size = ALIGN(sizeof (struct fl *)); - top += ALIGN(sizeof(size_t)) + ALIGN(size); -#ifdef HEAP_LIMIT - if (top > (char*)HEAP_LIMIT) - panic("heap full (0x%lx+%u)", help, size); -#endif - *(size_t *)help = ALIGN(size); -#ifdef ALLOC_TRACE - printf("=%lx\n", (u_long)help + ALIGN(sizeof(size_t))); - getchar(); -#endif - return(help + ALIGN(sizeof(size_t))); - } - - /* we take the best fit */ - f = bestf; - -found: - /* remove from freelist */ - help = (char*)*f; - *f = (*f)->next; -#ifdef ALLOC_TRACE - printf("=%lx (origsize %u)\n", (u_long)help + ALIGN(sizeof(size_t)), - *(size_t *)help); - getchar(); -#endif - return(help + ALIGN(sizeof(size_t))); -} - -void -free(ptr) - void *ptr; -{ - register struct fl *f = - (struct fl *)((char*)ptr - ALIGN(sizeof(size_t))); -#ifdef ALLOC_TRACE - printf("free(%lx, %u) (origsize %u)\n", (u_long)ptr, size, f->size); - getchar(); -#endif -#ifdef DEBUG - if (ptr < (void *)HEAP_START) - printf("free: %lx before start of heap.\n", (u_long)ptr); - -#ifdef HEAP_LIMIT - if (ptr > (void *)HEAP_LIMIT) - printf("free: %lx beyond end of heap.\n", (u_long)ptr); -#endif -#endif /* DEBUG */ - /* put into freelist */ - f->next = freelist; - freelist = f; -} - -/* - * Emulate sbrk(0) behaviour - */ -char * -sbrk(int junk) -{ - return((char *)top); -} diff --git a/lib/libstand/environment.c b/lib/libstand/environment.c index 007b6a2dc87b..72a9e06e5e80 100644 --- a/lib/libstand/environment.c +++ b/lib/libstand/environment.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: environment.c,v 1.1.1.1 1998/08/20 08:19:55 msmith Exp $ * */ @@ -70,7 +70,6 @@ env_setenv(const char *name, int flags, void *value, ev_sethook_t sethook, struct env_var *ev, *curr, *last; if ((ev = env_getenv(name)) != NULL) { - /* * If there's a set hook, let it do the work (unless we are working * for one already. @@ -78,12 +77,45 @@ env_setenv(const char *name, int flags, void *value, ev_sethook_t sethook, if ((ev->ev_sethook != NULL) && !(flags & EV_NOHOOK)) return(ev->ev_sethook(ev, flags, value)); } else { + + /* + * New variable; create and sort into list + */ ev = malloc(sizeof(struct env_var)); ev->ev_name = strdup(name); ev->ev_value = NULL; /* hooks can only be set when the variable is instantiated */ ev->ev_sethook = sethook; ev->ev_unsethook = unsethook; + + /* Sort into list */ + ev->ev_prev = NULL; + ev->ev_next = NULL; + /* Search for the record to insert before */ + for (last = NULL, curr = environ; + curr != NULL; + last = curr, curr = curr->ev_next) { + + if (strcmp(ev->ev_name, curr->ev_name) < 0) { + if (curr->ev_prev) { + curr->ev_prev->ev_next = ev; + } else { + environ = ev; + } + ev->ev_next = curr; + ev->ev_prev = curr->ev_prev; + curr->ev_prev = ev; + break; + } + } + if (curr == NULL) { + if (last == NULL) { + environ = ev; + } else { + last->ev_next = ev; + ev->ev_prev = last; + } + } } /* If there is data in the variable, discard it */ @@ -100,35 +132,6 @@ env_setenv(const char *name, int flags, void *value, ev_sethook_t sethook, /* Keep the flag components that are relevant */ ev->ev_flags = flags & (EV_DYNAMIC); - /* Sort into list */ - ev->ev_prev = NULL; - ev->ev_next = NULL; - - /* Search for the record to insert before */ - for (last = NULL, curr = environ; - curr != NULL; - last = curr, curr = curr->ev_next) { - - if (strcmp(ev->ev_name, curr->ev_name) < 0) { - if (curr->ev_prev) { - curr->ev_prev->ev_next = ev; - } else { - environ = ev; - } - ev->ev_next = curr; - ev->ev_prev = curr->ev_prev; - curr->ev_prev = ev; - break; - } - } - if (curr == NULL) { - if (last == NULL) { - environ = ev; - } else { - last->ev_next = ev; - ev->ev_prev = last; - } - } return(0); } @@ -158,11 +161,15 @@ setenv(const char *name, char *value, int overwrite) int putenv(const char *string) { - char *value; + char *value, *copy; + int result; - if ((value = strchr(string, '=')) != NULL) + copy = strdup(string); + if ((value = strchr(copy, '=')) != NULL) *(value++) = 0; - return(setenv(string, value, 1)); + result = setenv(copy, value, 1); + free(copy); + return(result); } int diff --git a/lib/libstand/gzipfs.c b/lib/libstand/gzipfs.c index 3a9730ba0286..fb64665cc3a2 100644 --- a/lib/libstand/gzipfs.c +++ b/lib/libstand/gzipfs.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: zipfs.c,v 1.1.1.1 1998/08/20 08:19:55 msmith Exp $ + * $Id: zipfs.c,v 1.2 1998/09/18 22:58:01 msmith Exp $ * */ @@ -59,11 +59,13 @@ struct fs_ops zipfs_fsops = { zf_stat }; +#if 0 void * calloc(int items, size_t size) { return(malloc(items * size)); } +#endif static int zf_fill(struct z_file *zf) @@ -175,7 +177,7 @@ zf_open(const char *fname, struct open_file *f) return(ENOENT); /* Construct new name */ - zfname = malloc(strlen(fname) + 3); + zfname = malloc(strlen(fname) + 4); sprintf(zfname, "%s.gz", fname); /* Try to open the compressed datafile */ diff --git a/lib/libstand/sbrk.c b/lib/libstand/sbrk.c new file mode 100644 index 000000000000..0655c9a92781 --- /dev/null +++ b/lib/libstand/sbrk.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 1998 Michael Smith + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * Minimal sbrk() emulation required for malloc support. + */ + +#include +#include "stand.h" + +static size_t maxheap, heapsize = 0; +static void *heapbase; + +void +setheap(void *base, void *top) +{ + heapbase = base; + maxheap = top - base; +} + +char * +sbrk(int incr) +{ + char *ret; + + if ((heapsize + incr) <= maxheap) { + ret = heapbase + heapsize; + bzero(ret, incr); + heapsize += incr; + return(ret); + } + errno = ENOMEM; + return((char *)-1); +} + diff --git a/lib/libstand/stand.h b/lib/libstand/stand.h index e575ee4678e7..fb9ce4a1c8a9 100644 --- a/lib/libstand/stand.h +++ b/lib/libstand/stand.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: stand.h,v 1.3 1998/09/18 22:58:00 msmith Exp $ + * $Id: stand.h,v 1.4 1998/09/18 23:00:57 msmith Exp $ * From $NetBSD: stand.h,v 1.22 1997/06/26 19:17:40 drochner Exp $ */ @@ -66,6 +66,9 @@ #include #include +#define CHK(fmt, args...) printf("%s(%d): " fmt "\n", __FUNCTION__, __LINE__ , ##args) +#define PCHK(fmt, args...) {printf("%s(%d): " fmt "\n", __FUNCTION__, __LINE__ , ##args); getchar();} + #ifndef NULL #define NULL 0 #endif @@ -168,10 +171,18 @@ extern struct open_file files[]; #define toupper(c) ((c) - 'a' + 'A') #define tolower(c) ((c) - 'A' + 'a') -extern void setheap(void *, void *); -extern void *malloc(size_t); -extern void free(void *); -extern char *sbrk(int junk); +/* sbrk emulation */ +extern void setheap(void *base, void *top); +extern char *sbrk(int incr); + +/* Matt Dillon's zalloc/zmalloc */ +extern void *malloc(size_t bytes); +extern void free(void *ptr); +/*#define free(p) {CHK("free %p", p); free(p);} */ /* use for catching guard violations */ +extern void *calloc(size_t n1, size_t n2); +extern void *realloc(void *ptr, size_t size); +extern void *reallocf(void *ptr, size_t size); +extern void mallocstats(void); /* disklabel support (undocumented, may be junk) */ struct disklabel; diff --git a/lib/libstand/ufs.c b/lib/libstand/ufs.c index a32fe06eed37..bd7f8c712e8a 100644 --- a/lib/libstand/ufs.c +++ b/lib/libstand/ufs.c @@ -84,7 +84,6 @@ struct fs_ops ufs_fsops = { "ufs", ufs_open, ufs_close, ufs_read, null_write, ufs_seek, ufs_stat }; - /* * In-core open file. */ @@ -113,39 +112,6 @@ static int search_directory(char *, struct open_file *, ino_t *); static void ffs_oldfscompat(struct fs *); #endif -static void *buffers4 = 0; -static void *buffers8 = 0; - -static void * -getbuf(size_t size) -{ - void *p = 0; - if (size == 8192 && buffers8) { - p = buffers8; - buffers8 = *(void **) p; - } - if (size == 4096 && buffers4) { - p = buffers4; - buffers4 = *(void **) p; - } - if (!p) - p = malloc(size); - return p; -} - -static void -relbuf(void *p, size_t size) -{ - if (size == 8192) { - *(void**) p = buffers8; - buffers8 = p; - } else if (size == 4096) { - *(void**) p = buffers4; - buffers8 = p; - } else - free(p); -} - /* * Read a new inode into a file structure. */ @@ -160,10 +126,13 @@ read_inode(inumber, f) size_t rsize; int rc; + if (fs == NULL) + panic("fs == NULL"); + /* * Read inode and save it. */ - buf = getbuf(fs->fs_bsize); + buf = malloc(fs->fs_bsize); twiddle(); rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize, @@ -193,7 +162,7 @@ read_inode(inumber, f) fp->f_buf_blkno = -1; } out: - relbuf(buf, fs->fs_bsize); + free(buf); return (rc); } @@ -273,7 +242,7 @@ block_map(f, file_block, disk_block_p) if (fp->f_blkno[level] != ind_block_num) { if (fp->f_blk[level] == (char *)0) fp->f_blk[level] = - getbuf(fs->fs_bsize); + malloc(fs->fs_bsize); twiddle(); rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, fsbtodb(fp->f_fs, ind_block_num), @@ -331,7 +300,7 @@ buf_read_file(f, buf_p, size_p) return (rc); if (fp->f_buf == (char *)0) - fp->f_buf = getbuf(fs->fs_bsize); + fp->f_buf = malloc(fs->fs_bsize); if (disk_block == 0) { bzero(fp->f_buf, block_size); @@ -442,7 +411,7 @@ ufs_open(upath, f) f->f_fsdata = (void *)fp; /* allocate space and read super block */ - fs = getbuf(SBSIZE); + fs = malloc(SBSIZE); fp->f_fs = fs; twiddle(); rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, @@ -563,7 +532,7 @@ ufs_open(upath, f) register struct fs *fs = fp->f_fs; if (!buf) - buf = getbuf(fs->fs_bsize); + buf = malloc(fs->fs_bsize); rc = block_map(f, (daddr_t)0, &disk_block); if (rc) goto out; @@ -599,12 +568,12 @@ ufs_open(upath, f) rc = 0; out: if (buf) - relbuf(buf, fs->fs_bsize); + free(buf); if (path) free(path); if (rc) { if (fp->f_buf) - relbuf(fp->f_buf, fs->fs_bsize); + free(fp->f_buf); free(fp->f_fs); free(fp); } @@ -616,7 +585,6 @@ ufs_close(f) struct open_file *f; { register struct file *fp = (struct file *)f->f_fsdata; - struct fs *fs = fp->f_fs; int level; f->f_fsdata = (void *)0; @@ -625,11 +593,11 @@ ufs_close(f) for (level = 0; level < NIADDR; level++) { if (fp->f_blk[level]) - relbuf(fp->f_blk[level], fs->fs_bsize); + free(fp->f_blk[level]); } if (fp->f_buf) - relbuf(fp->f_buf, fs->fs_bsize); - relbuf(fp->f_fs, SBSIZE); + free(fp->f_buf); + free(fp->f_fs); free(fp); return (0); } diff --git a/lib/libstand/zalloc.c b/lib/libstand/zalloc.c new file mode 100644 index 000000000000..b441702b274f --- /dev/null +++ b/lib/libstand/zalloc.c @@ -0,0 +1,591 @@ +/* + * This module derived from code donated to the FreeBSD Project by + * Matthew Dillon + * + * Copyright (c) 1998 The FreeBSD Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * LIB/MEMORY/ZALLOC.C - self contained low-overhead memory pool/allocation + * subsystem + * + * This subsystem implements memory pools and memory allocation + * routines. + * + * Pools are managed via a linked list of 'free' areas. Allocating + * memory creates holes in the freelist, freeing memory fills them. + * Since the freelist consists only of free memory areas, it is possible + * to allocate the entire pool without incuring any structural overhead. + * + * The system works best when allocating similarly-sized chunks of + * memory. Care must be taken to avoid fragmentation when + * allocating/deallocating dissimilar chunks. + * + * When a memory pool is first allocated, the entire pool is marked as + * allocated. This is done mainly because we do not want to modify any + * portion of a pool's data area until we are given permission. The + * caller must explicitly deallocate portions of the pool to make them + * available. + * + * z[n]xalloc() works like z[n]alloc() but the allocation is made from + * within the specified address range. If the segment could not be + * allocated, NULL is returned. WARNING! The address range will be + * aligned to an 8 or 16 byte boundry depending on the cpu so if you + * give an unaligned address range, unexpected results may occur. + * + * If a standard allocation fails, the reclaim function will be called + * to recover some space. This usually causes other portions of the + * same pool to be released. Memory allocations at this low level + * should not block but you can do that too in your reclaim function + * if you want. Reclaim does not function when z[n]xalloc() is used, + * only for z[n]alloc(). + * + * Allocation and frees of 0 bytes are valid operations. + */ + +#include "zalloc_defs.h" + +Prototype struct MemPool *DummyStructMemPool; +Library void *znalloc(struct MemPool *mpool, iaddr_t bytes); +Library void *zalloc(struct MemPool *mpool, iaddr_t bytes); +Library void *zallocAlign(struct MemPool *mpool, iaddr_t bytes, iaddr_t align); +Library void *zxalloc(struct MemPool *mp, void *addr1, void *addr2, iaddr_t bytes); +Library void *znxalloc(struct MemPool *mp, void *addr1, void *addr2, iaddr_t bytes); +Library char *zallocStr(struct MemPool *mpool, const char *s, int slen); +Library void zfree(struct MemPool *mpool, void *ptr, iaddr_t bytes); +Library void zfreeStr(struct MemPool *mpool, char *s); +Library void zinitPool(struct MemPool *mp, const char *id, void (*fpanic)(const char *ctl, ...), int (*freclaim)(struct MemPool *memPool, iaddr_t bytes), void *pBase, iaddr_t pSize); +Library void zclearPool(struct MemPool *mp); +Library void znop(const char *ctl, ...); +Library int znot(struct MemPool *memPool, iaddr_t bytes); +Library void zallocstats(struct MemPool *mp); + +/* + * znop() - panic function if none supplied. + */ + +void +znop(const char *ctl, ...) +{ +} + +/* + * znot() - reclaim function if none supplied + */ + +int +znot(struct MemPool *memPool, iaddr_t bytes) +{ + return(-1); +} + +#ifndef MALLOCLIB + +/* + * zalloc() - allocate and zero memory from pool. Call reclaim + * and retry if appropriate, return NULL if unable to allocate + * memory. + */ + +void * +zalloc(MemPool *mp, iaddr_t bytes) +{ + void *ptr; + + if ((ptr = znalloc(mp, bytes)) != NULL) + bzero(ptr, bytes); + return(ptr); +} + +/* + * zallocAlign() - allocate and zero memory from pool, enforce specified + * alignment (must be power of 2) on allocated memory. + */ + +void * +zallocAlign(struct MemPool *mp, iaddr_t bytes, iaddr_t align) +{ + void *ptr; + + --align; + bytes = (bytes + align) & ~align; + + if ((ptr = znalloc(mp, bytes)) != NULL) { + bzero(ptr, bytes); + } + return(ptr); +} + +#endif + +/* + * znalloc() - allocate memory (without zeroing) from pool. Call reclaim + * and retry if appropriate, return NULL if unable to allocate + * memory. + */ + +void * +znalloc(MemPool *mp, iaddr_t bytes) +{ + /* + * align according to pool object size (can be 0). This is + * inclusive of the MEMNODE_SIZE_MASK minimum alignment. + * + */ + bytes = (bytes + MEMNODE_SIZE_MASK) & ~MEMNODE_SIZE_MASK; + + if (bytes == 0) + return((void *)-1); + + do { + /* + * locate freelist entry big enough to hold the object. If all objects + * are the same size, this is a constant-time function. + */ + + if (bytes <= mp->mp_Size - mp->mp_Used) { + MemNode **pmn; + MemNode *mn; + + for (pmn = &mp->mp_First; (mn=*pmn) != NULL; pmn = &mn->mr_Next) { + if (bytes > mn->mr_Bytes) + continue; + + /* + * Cut a chunk of memory out of the beginning of this + * block and fixup the link appropriately. + */ + + { + char *ptr = (char *)mn; + + if (mn->mr_Bytes == bytes) { + *pmn = mn->mr_Next; + } else { + mn = (MemNode *)((char *)mn + bytes); + mn->mr_Next = ((MemNode *)ptr)->mr_Next; + mn->mr_Bytes = ((MemNode *)ptr)->mr_Bytes - bytes; + *pmn = mn; + } + mp->mp_Used += bytes; + return(ptr); + } + } + } + } while (mp->mp_Reclaim(mp, bytes) == 0); + + /* + * Memory pool is full, return NULL. + */ + + return(NULL); +} + +#ifndef MALLOCLIB + +/* + * z[n]xalloc() - allocate memory from within a specific address region. + * If allocating AT a specific address, then addr2 must be + * set to addr1 + bytes (and this only works if addr1 is + * already aligned). addr1 and addr2 are aligned by + * MEMNODE_SIZE_MASK + 1 (i.e. they wlill be 8 or 16 byte + * aligned depending on the machine core). + */ + +void * +zxalloc(MemPool *mp, void *addr1, void *addr2, iaddr_t bytes) +{ + void *ptr; + + if ((ptr = znxalloc(mp, addr1, addr2, bytes)) != NULL) + bzero(ptr, bytes); + return(ptr); +} + +void * +znxalloc(MemPool *mp, void *addr1, void *addr2, iaddr_t bytes) +{ + /* + * align according to pool object size (can be 0). This is + * inclusive of the MEMNODE_SIZE_MASK minimum alignment. + */ + bytes = (bytes + MEMNODE_SIZE_MASK) & ~MEMNODE_SIZE_MASK; + addr1= (void *)(((iaddr_t)addr1 + MEMNODE_SIZE_MASK) & ~MEMNODE_SIZE_MASK); + addr2= (void *)(((iaddr_t)addr2 + MEMNODE_SIZE_MASK) & ~MEMNODE_SIZE_MASK); + + if (bytes == 0) + return((void *)addr1); + + /* + * Locate freelist entry big enough to hold the object that is within + * the allowed address range. + */ + + if (bytes <= mp->mp_Size - mp->mp_Used) { + MemNode **pmn; + MemNode *mn; + + for (pmn = &mp->mp_First; (mn = *pmn) != NULL; pmn = &mn->mr_Next) { + int mrbytes = mn->mr_Bytes; + int offset = 0; + + /* + * offset from base of mn to satisfy addr1. 0 or positive + */ + + if ((char *)mn < (char *)addr1) + offset = (char *)addr1 - (char *)mn; + + /* + * truncate mrbytes to satisfy addr2. mrbytes may go negative + * if the mn is beyond the last acceptable address. + */ + + if ((char *)mn + mrbytes > (char *)addr2) + mrbytes = (saddr_t)((iaddr_t)addr2 - (iaddr_t)mn); /* signed */ + + /* + * beyond last acceptable address. + * + * before first acceptable address (if offset > mrbytes, the + * second conditional will always succeed). + * + * area overlapping acceptable address range is not big enough. + */ + + if (mrbytes < 0) + break; + + if (mrbytes - offset < bytes) + continue; + + /* + * Cut a chunk of memory out of the block and fixup the link + * appropriately. + * + * If offset != 0, we have to cut a chunk out from the middle of + * the block. + */ + + if (offset) { + MemNode *mnew = (MemNode *)((char *)mn + offset); + + mnew->mr_Bytes = mn->mr_Bytes - offset; + mnew->mr_Next = mn->mr_Next; + mn->mr_Bytes = offset; + mn->mr_Next = mnew; + pmn = &mn->mr_Next; + mn = mnew; + } + { + char *ptr = (char *)mn; + if (mn->mr_Bytes == bytes) { + *pmn = mn->mr_Next; + } else { + mn = (MemNode *)((char *)mn + bytes); + mn->mr_Next = ((MemNode *)ptr)->mr_Next; + mn->mr_Bytes = ((MemNode *)ptr)->mr_Bytes - bytes; + *pmn = mn; + } + mp->mp_Used += bytes; + return(ptr); + } + } + } + return(NULL); +} + +#endif + +/* + * zfree() - free previously allocated memory + */ + +void +zfree(MemPool *mp, void *ptr, iaddr_t bytes) +{ + /* + * align according to pool object size (can be 0). This is + * inclusive of the MEMNODE_SIZE_MASK minimum alignment. + */ + bytes = (bytes + MEMNODE_SIZE_MASK) & ~MEMNODE_SIZE_MASK; + + if (bytes == 0) + return; + + /* + * panic if illegal pointer + */ + + if ((char *)ptr < (char *)mp->mp_Base || + (char *)ptr + bytes > (char *)mp->mp_End || + ((iaddr_t)ptr & MEMNODE_SIZE_MASK) != 0 + ) { + mp->mp_Panic( + "zfree(%s,0x%08lx,%d): wild pointer", + mp->mp_Ident, + (long)ptr, + bytes + ); + } + + /* + * free the segment + */ + + { + MemNode **pmn; + MemNode *mn; + + mp->mp_Used -= bytes; + + for (pmn = &mp->mp_First; (mn = *pmn) != NULL; pmn = &mn->mr_Next) { + /* + * If area between last node and current node + * - check range + * - check merge with next area + * - check merge with previous area + */ + if ((char *)ptr <= (char *)mn) { + /* + * range check + */ + if ((char *)ptr + bytes > (char *)mn) { + mp->mp_Panic("zfree(%s,0x%08lx,%d): corrupt memlist1", + mp->mp_Ident, + (long)ptr, + bytes + ); + } + + /* + * merge against next area or create independant area + */ + + if ((char *)ptr + bytes == (char *)mn) { + ((MemNode *)ptr)->mr_Next = mn->mr_Next; + ((MemNode *)ptr)->mr_Bytes= bytes + mn->mr_Bytes; + } else { + ((MemNode *)ptr)->mr_Next = mn; + ((MemNode *)ptr)->mr_Bytes= bytes; + } + *pmn = mn = (MemNode *)ptr; + + /* + * merge against previous area (if there is a previous + * area). + */ + + if (pmn != &mp->mp_First) { + if ((char*)pmn + ((MemNode*)pmn)->mr_Bytes == (char*)ptr) { + ((MemNode *)pmn)->mr_Next = mn->mr_Next; + ((MemNode *)pmn)->mr_Bytes += mn->mr_Bytes; + mn = (MemNode *)pmn; + } + } + return; + /* NOT REACHED */ + } + if ((char *)ptr < (char *)mn + mn->mr_Bytes) { + mp->mp_Panic("zfree(%s,0x%08lx,%d): corrupt memlist2", + mp->mp_Ident, + (long)ptr, + bytes + ); + } + } + /* + * We are beyond the last MemNode, append new MemNode. Merge against + * previous area if possible. + */ + if (pmn == &mp->mp_First || + (char *)pmn + ((MemNode *)pmn)->mr_Bytes != (char *)ptr + ) { + ((MemNode *)ptr)->mr_Next = NULL; + ((MemNode *)ptr)->mr_Bytes = bytes; + *pmn = (MemNode *)ptr; + mn = (MemNode *)ptr; + } else { + ((MemNode *)pmn)->mr_Bytes += bytes; + mn = (MemNode *)pmn; + } + } +} + +#ifndef MALLOCLIB + +/* + * zallocStr() - allocate memory and copy string. + */ + +char * +zallocStr(MemPool *mp, const char *s, int slen) +{ + char *ptr; + + if (slen < 0) + slen = strlen(s); + if ((ptr = znalloc(mp, slen + 1)) != NULL) { + bcopy(s, ptr, slen); + ptr[slen] = 0; + } + return(ptr); +} + +/* + * zfreeStr() - free memory associated with an allocated string. + */ + +void +zfreeStr(MemPool *mp, char *s) +{ + zfree(mp, s, strlen(s) + 1); +} + +#endif + +/* + * zinitpool() - initialize a memory pool + */ + +void +zinitPool( + MemPool *mp, + const char *id, + void (*fpanic)(const char *ctl, ...), + int (*freclaim)(MemPool *memPool, iaddr_t bytes), + void *pBase, + iaddr_t pSize +) { + if (fpanic == NULL) + fpanic = znop; + if (freclaim == NULL) + freclaim = znot; + + if (id != (const char *)-1) + mp->mp_Ident = id; + mp->mp_Base = pBase; + mp->mp_End = (char *)pBase + pSize; + mp->mp_First = NULL; + mp->mp_Size = pSize; + mp->mp_Used = pSize; + mp->mp_Panic = fpanic; + mp->mp_Reclaim = freclaim; +} + +/* + * zextendPool() - extend memory pool to cover additional space. + * + * Note: the added memory starts out as allocated, you + * must free it to make it available to the memory subsystem. + * + * Note: mp_Size may not reflect (mp_End - mp_Base) range + * due to other parts of the system doing their own sbrk() + * calls. + */ + +void +zextendPool(MemPool *mp, void *base, iaddr_t bytes) +{ + if (mp->mp_Size == 0) { + mp->mp_Base = base; + mp->mp_Used = bytes; + } else { + void *pend = (char *)mp->mp_Base + mp->mp_Size; + + if (base < mp->mp_Base) { + /* mp->mp_Size += (char *)mp->mp_Base - (char *)base; */ + mp->mp_Used += (char *)mp->mp_Base - (char *)base; + mp->mp_Base = base; + } + base = (char *)base + bytes; + if (base > pend) { + /* mp->mp_Size += (char *)base - (char *)pend; */ + mp->mp_Used += (char *)base - (char *)pend; + } + mp->mp_End = (char *)mp->mp_Base + mp->mp_Size; + } + mp->mp_Size += bytes; +} + +#ifndef MALLOCLIB + +/* + * zclearpool() - Free all memory associated with a memory pool, + * destroying any previous allocations. Commonly + * called afte zinitPool() to make a pool available + * for use. + */ + +void +zclearPool(MemPool *mp) +{ + MemNode *mn = mp->mp_Base; + + mn->mr_Next = NULL; + mn->mr_Bytes = mp->mp_Size; + mp->mp_First = mn; +} + +#endif + +#ifdef ZALLOCDEBUG + +void +zallocstats(MemPool *mp) +{ + int abytes = 0; + int hbytes = 0; + int fcount = 0; + MemNode *mn; + + printf("Pool %s, %d bytes reserved", mp->mp_Ident, mp->mp_Size); + + mn = mp->mp_First; + + if ((void *)mn != (void *)mp->mp_Base) { + abytes += (char *)mn - (char *)mp->mp_Base; + } + + while (mn) { + if ((char *)mn + mn->mr_Bytes != mp->mp_End) { + hbytes += mn->mr_Bytes; + ++fcount; + } + if (mn->mr_Next) + abytes += (char *)mn->mr_Next - ((char *)mn + mn->mr_Bytes); + mn = mn->mr_Next; + } + printf(" %d bytes allocated\n%d fragments (%d bytes fragmented)\n", + abytes, + fcount, + hbytes + ); +} + +#endif + diff --git a/lib/libstand/zalloc_defs.h b/lib/libstand/zalloc_defs.h new file mode 100644 index 000000000000..d80d3a02a4bf --- /dev/null +++ b/lib/libstand/zalloc_defs.h @@ -0,0 +1,83 @@ +/* + * This module derived from code donated to the FreeBSD Project by + * Matthew Dillon + * + * Copyright (c) 1998 The FreeBSD Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * DEFS.H + */ + +#define USEPANIC /* call panic() to register errors */ +#define USEGUARD /* use stard/end guard bytes */ +#define USEENDGUARD +#define DMALLOCDEBUG /* add debugging code to gather stats */ +#define ZALLOCDEBUG +#define MALLOCLIB /* don't build unnecessary zalloc parts */ + +#include +#include "stand.h" + +typedef unsigned int iaddr_t; /* unsigned int same size as pointer */ +typedef int saddr_t; /* signed int same size as pointer */ + +#include "zalloc_mem.h" + +#define Prototype extern +#define Library extern + +#ifndef NULL +#define NULL ((void *)0) +#endif + +/* + * block extension for sbrk() + */ + +#define BLKEXTEND (64 * 1024) +#define BLKEXTENDMASK (BLKEXTEND - 1) + +/* + * required malloc alignment. Use sizeof(long double) for architecture + * independance. + * + * Note: if we implement a more sophisticated realloc, we should ensure that + * MALLOCALIGN is at least as large as MemNode. + */ + +typedef struct Guard { + size_t ga_Bytes; + size_t ga_Magic; /* must be at least 32 bits */ +} Guard; + +#define MATYPE long double +#define MALLOCALIGN ((sizeof(MATYPE) > sizeof(Guard)) ? sizeof(MATYPE) : sizeof(Guard)) +#define GAMAGIC 0x55FF44FD + +#include "zalloc_protos.h" + diff --git a/lib/libstand/zalloc_malloc.c b/lib/libstand/zalloc_malloc.c new file mode 100644 index 000000000000..79e6c8017cee --- /dev/null +++ b/lib/libstand/zalloc_malloc.c @@ -0,0 +1,193 @@ +/* + * This module derived from code donated to the FreeBSD Project by + * Matthew Dillon + * + * Copyright (c) 1998 The FreeBSD Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * MALLOC.C - malloc equivalent, runs on top of zalloc and uses sbrk + */ + +#include "zalloc_defs.h" + +static MemPool MallocPool = INITPOOL("malloc", panic, znot); + +#ifdef DMALLOCDEBUG +static int MallocMax; +static int MallocCount; + +void mallocstats(void); +#endif + +void * +malloc(size_t bytes) +{ + Guard *res; + +#ifdef USEENDGUARD + bytes += MALLOCALIGN + 1; +#else + bytes += MALLOCALIGN; +#endif + + while ((res = znalloc(&MallocPool, bytes)) == NULL) { + int incr = (bytes + BLKEXTENDMASK) & ~BLKEXTENDMASK; + char *base; + + if ((base = sbrk(incr)) == (char *)-1) + return(NULL); + zextendPool(&MallocPool, base, incr); + zfree(&MallocPool, base, incr); + } +#ifdef DMALLOCDEBUG + if (++MallocCount > MallocMax) + MallocMax = MallocCount; +#endif +#ifdef USEGUARD + res->ga_Magic = GAMAGIC; +#endif + res->ga_Bytes = bytes; +#ifdef USEENDGUARD + *((char *)res + bytes - 1) = -2; +#endif + return((char *)res + MALLOCALIGN); +} + +void +free(void *ptr) +{ + size_t bytes; + + if (ptr != NULL) { + Guard *res = (void *)((char *)ptr - MALLOCALIGN); + +#ifdef USEGUARD + if (res->ga_Magic != GAMAGIC) { +#ifdef USEPANIC + panic("free(): guard1 fail @ %08lx\n", ptr); +#else + *(char *)0 = 1; +#endif + } + res->ga_Magic = -1; +#endif +#ifdef USEENDGUARD + if (*((char *)res + res->ga_Bytes - 1) != -2) { +#ifdef USEPANIC + panic("free(): guard2 fail @ %08lx + %d\n", ptr, res->ga_Bytes - MALLOCALIGN); +#else + *(char *)0 = 1; +#endif + } + *((char *)res + res->ga_Bytes - 1) = -1; +#endif + + bytes = res->ga_Bytes; + zfree(&MallocPool, res, bytes); +#ifdef DMALLOCDEBUG + --MallocCount; +#endif + } +} + + +void * +calloc(size_t n1, size_t n2) +{ + iaddr_t bytes = (iaddr_t)n1 * (iaddr_t)n2; + void *res; + + if ((res = malloc(bytes)) != NULL) { + bzero(res, bytes); +#ifdef DMALLOCDEBUG + if (++MallocCount > MallocMax) + MallocMax = MallocCount; +#endif + } + return(res); +} + +/* + * realloc() - I could be fancier here and free the old buffer before + * allocating the new one (saving potential fragmentation + * and potential buffer copies). But I don't bother. + */ + +void * +realloc(void *ptr, size_t size) +{ + void *res; + size_t old; + + if ((res = malloc(size)) != NULL) { + if (ptr) { + old = *(size_t *)((char *)ptr - MALLOCALIGN) - MALLOCALIGN; + if (old < size) + bcopy(ptr, res, old); + else + bcopy(ptr, res, size); + free(ptr); + } else { +#ifdef DMALLOCDEBUG + if (++MallocCount > MallocMax) + MallocMax = MallocCount; +#ifdef EXITSTATS + if (DidAtExit == 0) { + DidAtExit = 1; + atexit(mallocstats); + } +#endif +#endif + } + } + return(res); +} + +void * +reallocf(void *ptr, size_t size) +{ + void *res; + + if ((res = realloc(ptr, size)) == NULL) + free(ptr); + return(res); +} + +#ifdef DMALLOCDEBUG + +void +mallocstats(void) +{ + printf("Active Allocations: %d/%d\n", MallocCount, MallocMax); +#ifdef ZALLOCDEBUG + zallocstats(&MallocPool); +#endif +} + +#endif + diff --git a/lib/libstand/zalloc_mem.h b/lib/libstand/zalloc_mem.h new file mode 100644 index 000000000000..8655e7b6b9bc --- /dev/null +++ b/lib/libstand/zalloc_mem.h @@ -0,0 +1,60 @@ +/* + * This module derived from code donated to the FreeBSD Project by + * Matthew Dillon + * + * Copyright (c) 1998 The FreeBSD Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * H/MEM.H + * + * Basic memory pool / memory node structures. + */ + +typedef struct MemNode { + struct MemNode *mr_Next; + iaddr_t mr_Bytes; +} MemNode; + +typedef struct MemPool { + const char *mp_Ident; + void *mp_Base; + void *mp_End; + MemNode *mp_First; + void (*mp_Panic)(const char *ctl, ...); + int (*mp_Reclaim)(struct MemPool *memPool, iaddr_t bytes); + iaddr_t mp_Size; + iaddr_t mp_Used; +} MemPool; + +#define MEMNODE_SIZE_MASK ((sizeof(MemNode) <= 8) ? 7 : 15) + +#define INITPOOL(name,panic,reclaim) { name, NULL, NULL, NULL, panic, reclaim } + +#define ZNOTE_FREE 0 +#define ZNOTE_REUSE 1 + diff --git a/lib/libstand/zalloc_protos.h b/lib/libstand/zalloc_protos.h new file mode 100644 index 000000000000..e49a871d2688 --- /dev/null +++ b/lib/libstand/zalloc_protos.h @@ -0,0 +1,46 @@ +/* + * This module derived from code donated to the FreeBSD Project by + * Matthew Dillon + * + * Copyright (c) 1998 The FreeBSD Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +Prototype struct MemPool *DummyStructMemPool; +Library void *znalloc(struct MemPool *mpool, iaddr_t bytes); +Library void *zalloc(struct MemPool *mpool, iaddr_t bytes); +Library void *zallocAlign(struct MemPool *mpool, iaddr_t bytes, iaddr_t align); +Library void *zxalloc(struct MemPool *mp, void *addr1, void *addr2, iaddr_t bytes); +Library void *znxalloc(struct MemPool *mp, void *addr1, void *addr2, iaddr_t bytes); +Library char *zallocStr(struct MemPool *mpool, const char *s, int slen); +Library void zfree(struct MemPool *mpool, void *ptr, iaddr_t bytes); +Library void zfreeStr(struct MemPool *mpool, char *s); +Library void zinitPool(struct MemPool *mp, const char *id, void (*fpanic)(const char *ctl, ...), int (*freclaim)(struct MemPool *memPool, iaddr_t bytes), void *pBase, iaddr_t pSize); +Library void zextendPool(MemPool *mp, void *base, iaddr_t bytes); +Library void zclearPool(struct MemPool *mp); +Library void znop(const char *ctl, ...); +Library int znot(struct MemPool *memPool, iaddr_t bytes); +Library void zallocstats(struct MemPool *mp); diff --git a/lib/libstand/zipfs.c b/lib/libstand/zipfs.c index 3a9730ba0286..fb64665cc3a2 100644 --- a/lib/libstand/zipfs.c +++ b/lib/libstand/zipfs.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: zipfs.c,v 1.1.1.1 1998/08/20 08:19:55 msmith Exp $ + * $Id: zipfs.c,v 1.2 1998/09/18 22:58:01 msmith Exp $ * */ @@ -59,11 +59,13 @@ struct fs_ops zipfs_fsops = { zf_stat }; +#if 0 void * calloc(int items, size_t size) { return(malloc(items * size)); } +#endif static int zf_fill(struct z_file *zf) @@ -175,7 +177,7 @@ zf_open(const char *fname, struct open_file *f) return(ENOENT); /* Construct new name */ - zfname = malloc(strlen(fname) + 3); + zfname = malloc(strlen(fname) + 4); sprintf(zfname, "%s.gz", fname); /* Try to open the compressed datafile */