/tags/wad-0-2-1/SWIG/Tools/WAD/Wad/memory.c
C | 174 lines | 92 code | 16 blank | 66 comment | 13 complexity | 5a426c89cdffafe00844f5374cbfc1e2 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
1/* ----------------------------------------------------------------------------- 2 * memory.c 3 * 4 * This file provides simple mmap() based memory management for WAD. Since 5 * the process heap-allocator might be corrupted when WAD is invoked, we 6 * have to do all of our own memory management. However, since WAD mostly 7 * just collects data, we only provide the function wad_malloc(). To 8 * release all allocated memory, the wad_release_memory() function should 9 * be used. 10 * 11 * Author(s) : David Beazley (beazley@cs.uchicago.edu) 12 * 13 * Copyright (C) 2000. The University of Chicago. 14 * 15 * This library is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU Lesser General Public 17 * License as published by the Free Software Foundation; either 18 * version 2.1 of the License, or (at your option) any later version. 19 * 20 * This library is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 * Lesser General Public License for more details. 24 * 25 * You should have received a copy of the GNU Lesser General Public 26 * License along with this library; if not, write to the Free Software 27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 28 * 29 * See the file COPYING for a complete copy of the LGPL. 30 * ----------------------------------------------------------------------------- */ 31 32#include "wad.h" 33 34static char cvs[] = "$Header$"; 35 36typedef struct _WadMemory { 37 int npages; /* Number of pages */ 38 int last; /* Last offset in page */ 39 struct _WadMemory *next; /* Pointer to next allocation */ 40} WadMemory; 41 42static WadMemory *current = 0; /* Current memory block */ 43static int pagesize = 0; /* System page size */ 44static int devzero = 0; 45static int npalloc = 8; /* Number of pages per alloc */ 46 47/* ----------------------------------------------------------------------------- 48 * wad_memory_init() 49 * 50 * Initialize the WAD allocator. 51 * ----------------------------------------------------------------------------- */ 52 53int wad_memory_init() { 54 pagesize = getpagesize(); 55 devzero = open("/dev/zero", O_RDWR); 56 if (devzero < 0) { 57 wad_printf("WAD: couldn't open /dev/zero.\n"); 58 return -1; 59 } 60 return 0; 61} 62 63/* ----------------------------------------------------------------------------- 64 * wad_page_alloc() 65 * 66 * Allocate pages using mmap 67 * ----------------------------------------------------------------------------- */ 68 69void *wad_page_alloc(int npages) { 70 void *m; 71 m = mmap(NULL, npages*pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE, devzero, 0); 72 if (((long) m) == -1) return 0; 73 /* printf("page_alloc: %x - %x\n", m, ((char *) m) + npages*pagesize); */ 74 return m; 75} 76 77/* ----------------------------------------------------------------------------- 78 * wad_malloc() 79 * 80 * Allocate memory using mmap(). If the allocation is smaller than half a page, 81 * We'll look at current to see if there is enough space. If so, we'll just 82 * use that memory. Otherwise, we'll allocate a new page. If the allocation 83 * request is larger than a page, we'll round up to the nearest page size and 84 * do a special allocation. 85 * ----------------------------------------------------------------------------- */ 86 87void *wad_malloc(int nbytes) { 88 void *ptr; 89 WadMemory *wm; 90 char *c; 91 int npages; 92 /* wad_printf("wad_malloc: %d\n", nbytes); */ 93 if (nbytes >= ((npalloc*pagesize) >> 2)) { 94 /* Large allocation. */ 95 npages = ((nbytes + sizeof(WadMemory))/pagesize) + 1; 96 ptr = wad_page_alloc(npages); 97 if (!ptr) return 0; 98 wm = (WadMemory *)ptr; 99 wm->npages = npages; 100 wm->last = sizeof(WadMemory) + 8; 101 wm->next = current; 102 current = wm; 103 c = (char *) current + (current->last); 104 current->last += ((nbytes & ~0x7) + 8); 105 return c; 106 } 107 /* Small allocation. See if there are any regions big enough */ 108 wm = current; 109 while (wm) { 110 if (((wm->npages*pagesize) - wm->last) > nbytes) { 111 /* Yep. Found a region */ 112 break; 113 } 114 wm = wm->next; 115 } 116 if (!wm) { 117 /* wad_printf("wad_malloc: new page\n", nbytes);*/ 118 wm = (WadMemory *) wad_page_alloc(npalloc); 119 if (!wm) return 0; 120 wm->npages = npalloc; 121 wm->last = sizeof(WadMemory) + 8; 122 wm->next = current; 123 current = wm; 124 } 125 c = ((char *) wm) + (wm->last); 126 wm->last += ((nbytes & ~0x7) + 8); 127 return c; 128} 129 130/* ----------------------------------------------------------------------------- 131 * wad_strdup() 132 * 133 * Duplicate a string 134 * ----------------------------------------------------------------------------- */ 135 136char *wad_strdup(const char *c) { 137 char *t; 138 if (!c) c = ""; 139 t = (char *) wad_malloc(strlen(c)+1); 140 wad_strcpy(t,c); 141 return t; 142} 143 144/* ----------------------------------------------------------------------------- 145 * wad_memcpy() 146 * ----------------------------------------------------------------------------- */ 147 148void wad_memcpy(void *t, const void *s, unsigned len) { 149 char *tc, *sc; 150 int i; 151 tc = (char *) t; 152 sc = (char *) s; 153 for (i = 0; i < len; i++, tc++, sc++) 154 *tc = *sc; 155} 156 157/* ----------------------------------------------------------------------------- 158 * wad_memory_debug() 159 * ----------------------------------------------------------------------------- */ 160 161void wad_memory_debug() { 162 int total_alloc = 0; 163 int inuse = 0; 164 WadMemory *m; 165 if (wad_debug_mode & DEBUG_MEMORY) { 166 m = current; 167 while (m) { 168 total_alloc += (m->npages)*pagesize; 169 inuse += m->last; 170 m = m->next; 171 } 172 wad_printf("WAD: memory allocated %d bytes (%d bytes used).\n", total_alloc, inuse); 173 } 174}