diff --git a/mapmalloc.c b/mapmalloc.c deleted file mode 100644 index 90f8c30..0000000 --- a/mapmalloc.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - * Memory allocation routines using mmap(). - * - * Derived from mm-1.1.3 by Gunnar Ritter, Freiburg i. Br., Germany, - * September 2001. - */ - -/* Sccsid @(#)mapmalloc.c 1.15 (gritter) 2/17/05 */ - -/* ==================================================================== - * Copyright (c) 1999-2000 Ralf S. Engelschall. 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. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by - * Ralf S. Engelschall ." - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by - * Ralf S. Engelschall ." - * - * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY - * EXPRESSED 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 RALF S. ENGELSCHALL OR - * ITS 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. - * ==================================================================== - */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef __GLIBC__ -/* - * Broken GNU libc will include stdlib.h with conflicting - * malloc() types otherwise. - */ -#ifndef __NO_STRING_INLINES -#define __NO_STRING_INLINES -#endif /* !__NO_STRING_INLINES */ -#endif /* __GLIBC__ */ -#include - -#include "config.h" - -#ifdef LANGMSG -#include -extern nl_catd catd; -#else -#define catgets(a, b, c, d) (d) -#endif - -#ifndef min_of -#define min_of(a, b) ((a) < (b) ? (a) : (b)) -#endif -#ifndef max_of -#define max_of(a, b) ((a) > (b) ? (a) : (b)) -#endif - -#ifndef MAP_ANON -#ifdef MAP_ANONYMOUS -#define MAP_ANON MAP_ANONYMOUS -#endif -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((char *)-1) -#endif - -#define MM_ALLOC_MINSIZE 8192 - -/* - * Define a union with types which are likely to have the longest - * *relevant* CPU-specific memory word alignment restrictions... - */ -union mem_word { - char (*mw_fp)(int); - char *mw_cp; - long mw_l; - double mw_d; - intptr_t mw_it; -}; - -typedef union mem_word mem_word; - -#define SIZEOF_mem_word (sizeof(mem_word)) - -/* - * Define the structure used for memory chunks - */ -union mem_chunk_mc_u { - struct mem_chunk *mc_next; /* really used when it's free */ - mem_word mc_base;/* virtually used when it's allocated */ -}; - -struct mem_chunk { - size_t mc_size; /* physical size */ - size_t mc_usize; /* user known size */ - struct mem_pool *mc_pool; - union mem_chunk_mc_u mc_u; -}; - -typedef struct mem_chunk mem_chunk; - -#define SIZEOF_mem_chunk (sizeof(mem_chunk)-sizeof(union mem_chunk_mc_u)) - -/* - * Define the structure describing a memory pool - */ -struct mem_pool { - struct mem_pool *mp_prev; - struct mem_pool *mp_next; - size_t mp_size; - size_t mp_offset; - int mp_users; - mem_chunk mp_freechunks; - mem_word mp_base; -}; - -typedef struct mem_pool mem_pool; - -#define SIZEOF_mem_pool (sizeof(mem_pool)-SIZEOF_mem_word) - -/* - * Define the structure describing a shared memory core area - * (the actual contents depends on the shared memory and - * semaphore/mutex type and is stripped down to a minimum - * required) - */ -struct mem_core { - size_t mo_size; - size_t mo_usize; - mem_word mo_base; -}; - -typedef struct mem_core mem_core; - -#define SIZEOF_mem_core (sizeof(mem_core)-SIZEOF_mem_word) - -typedef mem_pool MM; - -static MM *mm_global = NULL; -#ifndef MAP_ANON -static int zerofd = -1; -#endif - -extern int error(char *, ...); - -/* - * Determine memory page size of OS - */ -static size_t -mm_core_pagesize(void) -{ - static int pagesize = 0; - - if (pagesize == 0) -#ifdef _SC_PAGESIZE - pagesize = sysconf(_SC_PAGESIZE); -#else - pagesize = 8192; -#endif - return pagesize; -} - -/* - * Align a size to the next page or word boundary - */ -static size_t -mm_core_align2page(size_t size) -{ - int psize = mm_core_pagesize(); - return ((size) % (psize) > 0 ? - ((size) / (psize) + 1) * (psize) : (size)); -} - -static size_t -mm_core_align2word(size_t size) -{ - return ((1 + ((size - 1) / SIZEOF_mem_word)) * SIZEOF_mem_word); -} - -/* - * Create a shared memory area - */ -static char -*mm_core_create(size_t usersize) -{ - mem_core *mo; - char *area = ((char *)-1); - size_t size; - - if (usersize <= 0) { - errno = EINVAL; - return NULL; - } - size = mm_core_align2page(usersize + SIZEOF_mem_core); -#ifdef MAP_ANON - if ((area = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, -1, 0)) == (char *)MAP_FAILED) - error(catgets(catd, 1, 243, - "failed to memory map anonymous area")); -#else /* !MAP_ANON */ - if (zerofd == -1 && ((zerofd = open("/dev/zero", O_RDWR)) == -1 -#ifdef F_SETFD -#ifndef FD_CLOEXEC -#define FD_CLOEXEC 1 -#endif /* !FD_CLOEXEC */ - || fcntl(zerofd, F_SETFD, FD_CLOEXEC) == -1 -#endif /* F_SETFD */ - )) - error(catgets(catd, 1, 244, - "failed to open /dev/zero")); - if ((area = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE, - MAP_PRIVATE, zerofd, (off_t)0)) == (char *)MAP_FAILED) - error(catgets(catd, 1, 245, - "failed to memory map /dev/zero")); -#endif /* !MAP_ANON */ - /* - * Configure the memory core parameters - */ - mo = (mem_core *)area; - mo->mo_size = size; - mo->mo_usize = usersize; - /* - * Return successfully established core - */ - return ((char *)&(mo->mo_base.mw_cp)); -} - -/* - * Create a memory pool - */ -static MM * -mm_create(MM *mmPrev, size_t usize) -{ - MM *mm = NULL; - char *core; - size_t size; - - /* - * defaults - */ - if (usize < MM_ALLOC_MINSIZE) - usize = MM_ALLOC_MINSIZE; - /* - * determine size - */ - size = usize + SIZEOF_mem_pool; - /* - * get a shared memory area - */ - if ((core = mm_core_create(size)) == NULL) - return NULL; - /* - * fill in the memory pool structure - */ - mm = (MM *)core; - mm->mp_prev = mmPrev; - mm->mp_next = NULL; - mm->mp_size = size; - mm->mp_offset = SIZEOF_mem_pool; - mm->mp_users = 0; - /* - * first element of list of free chunks counts existing chunks - */ - mm->mp_freechunks.mc_size = 0; /* has to be 0 forever */ - mm->mp_freechunks.mc_usize = 0; /* counts chunks */ - mm->mp_freechunks.mc_u.mc_next = NULL; - return mm; -} - -/* - * Insert a chunk to the list of free chunks. Algorithm used is: - * Insert in sorted manner to the list and merge with previous - * and/or next chunk when possible to form larger chunks out of - * smaller ones. - */ -static void -mm_insert_chunk(MM *mm, mem_chunk *mcInsert) -{ - mem_chunk *mc; - mem_chunk *mcPrev; - mem_chunk *mcNext; - - mc = &(mm->mp_freechunks); - while (mc->mc_u.mc_next != NULL && - (char *)(mc->mc_u.mc_next) < (char *)mcInsert) - mc = mc->mc_u.mc_next; - mcPrev = mc; - mcNext = mc->mc_u.mc_next; - if (mcPrev == mcInsert || mcNext == mcInsert) - error(catgets(catd, 1, 246, - "chunk of memory already in free list")); - if ((char *)mcPrev + (mcPrev->mc_size) == (char *)mcInsert && - (mcNext != NULL && - (char *)mcInsert + (mcInsert->mc_size) == - (char *)mcNext)) { - /* - * merge with previous and next chunk - */ - mcPrev->mc_size += mcInsert->mc_size + mcNext->mc_size; - mcPrev->mc_u.mc_next = mcNext->mc_u.mc_next; - mm->mp_freechunks.mc_usize -= 1; - } else if ((char *)mcPrev + (mcPrev->mc_size) == - (char *)mcInsert) { - /* - * merge with previous chunk - */ - mcPrev->mc_size += mcInsert->mc_size; - } else if (mcNext != NULL && - (char *)mcInsert + (mcInsert->mc_size) == - (char *)mcNext) { - /* - * merge with next chunk - */ - mcInsert->mc_size += mcNext->mc_size; - mcInsert->mc_u.mc_next = mcNext->mc_u.mc_next; - mcPrev->mc_u.mc_next = mcInsert; - } else { - /* - * no merging possible, so insert as new chunk - */ - mcInsert->mc_u.mc_next = mcNext; - mcPrev->mc_u.mc_next = mcInsert; - mm->mp_freechunks.mc_usize += 1; - } -} - -/* - * Retrieve a chunk from the list of free chunks. Algorithm used - * is: Search for minimal-sized chunk which is larger or equal - * than the request size. But when the retrieved chunk is still a - * lot larger than the requested size, split out the requested - * size to not waste memory. - */ -static mem_chunk * -mm_retrieve_chunk(MM *mm, size_t size) -{ - mem_chunk *mc; - mem_chunk **pmcMin; - mem_chunk *mcRes; - size_t sMin; - size_t s; - - if (size == 0) - return NULL; - if (mm->mp_freechunks.mc_usize == 0) - return NULL; - /* - * find best-fitting chunk - */ - pmcMin = NULL; - sMin = mm->mp_size; /* initialize with maximum possible */ - mc = &(mm->mp_freechunks); - while (mc->mc_u.mc_next != NULL) { - s = mc->mc_u.mc_next->mc_size; - if (s >= size && s < sMin) { - pmcMin = &(mc->mc_u.mc_next); - sMin = s; - if (s == size) - break; - } - mc = mc->mc_u.mc_next; - } - /* - * create result chunk - */ - if (pmcMin == NULL) - mcRes = NULL; - else { - mcRes = *pmcMin; - if (mcRes->mc_size >= (size + min_of(2 * size, 128))) { - /* - * split out in part - */ - s = mcRes->mc_size - size; - mcRes->mc_size = size; - /* - * add back remaining chunk part as new chunk - */ - mc = (mem_chunk *)((char *)mcRes + size); - mc->mc_size = s; - mc->mc_u.mc_next = mcRes->mc_u.mc_next; - *pmcMin = mc; - } else { - /* - * split out as a whole - */ - *pmcMin = mcRes->mc_u.mc_next; - mm->mp_freechunks.mc_usize--; - } - } - return mcRes; -} - -/* - * Allocate a chunk of memory - */ -char * -malloc(size_t usize) -{ - MM *mm; - mem_chunk *mc; - size_t size; - - size = mm_core_align2word(SIZEOF_mem_chunk + usize); - if (mm_global == NULL && (mm_global = mm_create(NULL, size)) == NULL) - return NULL; - mm = mm_global; -nextpool: - if ((mc = mm_retrieve_chunk(mm, size)) != NULL) { - mc->mc_usize = usize; - mc->mc_pool = mm; - mm->mp_users++; - return (char *)&(mc->mc_u.mc_base.mw_cp); - } - if ((mm->mp_size - mm->mp_offset) < size) { - if (mm->mp_next != NULL || - (mm->mp_next = mm_create(mm, size)) != NULL) { - mm = mm->mp_next; - goto nextpool; - } - error(catgets(catd, 1, 247, "out of memory")); - errno = ENOMEM; - return NULL; - } - mc = (mem_chunk *)((char *)mm + mm->mp_offset); - mc->mc_size = size; - mc->mc_usize = usize; - mc->mc_pool = mm; - mm->mp_offset += size; - mm->mp_users++; - return (char *)&(mc->mc_u.mc_base.mw_cp); -} - -/* - * Free a chunk of memory - */ -void -free(char *ptr) -{ - MM *mm; - mem_chunk *mc; - - if (mm_global == NULL || ptr == NULL) - return; - mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk); - mm = mc->mc_pool; - mm_insert_chunk(mm, mc); - if (--mm->mp_users == 0) { - mem_core *mo = (mem_core *)((char *)mm - SIZEOF_mem_core); - if (mm == mm_global) - mm_global = mm->mp_next; - if (mm->mp_prev != NULL) - mm->mp_prev->mp_next = mm->mp_next; - if (mm->mp_next != NULL) - mm->mp_next->mp_prev = mm->mp_prev; - munmap((char *)mo, mo->mo_size); - } -} - -/* - * Reallocate a chunk of memory - */ -char * -realloc(char *ptr, size_t usize) -{ - size_t size; - mem_chunk *mc; - char *vp; - - if (ptr == NULL) - return malloc(usize); /* POSIX.1 semantics */ - mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk); - if (usize <= mc->mc_usize) { - mc->mc_usize = usize; - return ptr; - } - size = mm_core_align2word(SIZEOF_mem_chunk + usize); - if (size <= mc->mc_size) { - mc->mc_usize = usize; - return ptr; - } - if ((vp = malloc(usize)) == NULL) - return NULL; - memcpy(vp, ptr, mc->mc_usize); - free(ptr); - return vp; -} - -/* - * Allocate and initialize a chunk of memory - */ -char * -calloc(size_t number, size_t usize) -{ - char *vp; - - if ((vp = malloc(number * usize)) == NULL) - return NULL; - memset(vp, 0, number * usize); - return vp; -} - -/*ARGSUSED*/ -void -cfree(char *p, size_t num, size_t size) -{ - free(p); -} - -#ifdef notdef -/*ARGSUSED*/ -char * -memalign(size_t alignment, size_t size) -{ - return NULL; -} - -/*ARGSUSED*/ -char * -valloc(size_t size) -{ - return NULL; -} - -char * -mallinfo(void) -{ - return NULL; -} - -int -mallopt(void) -{ - return -1; -} -#endif /* notdef */ - -/*ARGSUSED*/ -char * -poolsbrk(intptr_t val) -{ - return NULL; -}