git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@10001 626c5289-ae23-0410-ae9c-e8d60b6d4f22
174 lines
5.7 KiB
C
174 lines
5.7 KiB
C
/* -----------------------------------------------------------------------------
|
|
* memory.c
|
|
*
|
|
* This file provides simple mmap() based memory management for WAD. Since
|
|
* the process heap-allocator might be corrupted when WAD is invoked, we
|
|
* have to do all of our own memory management. However, since WAD mostly
|
|
* just collects data, we only provide the function wad_malloc(). To
|
|
* release all allocated memory, the wad_release_memory() function should
|
|
* be used.
|
|
*
|
|
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
|
*
|
|
* Copyright (C) 2000. The University of Chicago.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* See the file COPYING for a complete copy of the LGPL.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
#include "wad.h"
|
|
|
|
static char cvs[] = "$Id$";
|
|
|
|
typedef struct _WadMemory {
|
|
int npages; /* Number of pages */
|
|
int last; /* Last offset in page */
|
|
struct _WadMemory *next; /* Pointer to next allocation */
|
|
} WadMemory;
|
|
|
|
static WadMemory *current = 0; /* Current memory block */
|
|
static int pagesize = 0; /* System page size */
|
|
static int devzero = 0;
|
|
static int npalloc = 8; /* Number of pages per alloc */
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* wad_memory_init()
|
|
*
|
|
* Initialize the WAD allocator.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
int wad_memory_init() {
|
|
pagesize = getpagesize();
|
|
devzero = open("/dev/zero", O_RDWR);
|
|
if (devzero < 0) {
|
|
wad_printf("WAD: couldn't open /dev/zero.\n");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* wad_page_alloc()
|
|
*
|
|
* Allocate pages using mmap
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void *wad_page_alloc(int npages) {
|
|
void *m;
|
|
m = mmap(NULL, npages*pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE, devzero, 0);
|
|
if (((long) m) == -1) return 0;
|
|
/* printf("page_alloc: %x - %x\n", m, ((char *) m) + npages*pagesize); */
|
|
return m;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* wad_malloc()
|
|
*
|
|
* Allocate memory using mmap(). If the allocation is smaller than half a page,
|
|
* We'll look at current to see if there is enough space. If so, we'll just
|
|
* use that memory. Otherwise, we'll allocate a new page. If the allocation
|
|
* request is larger than a page, we'll round up to the nearest page size and
|
|
* do a special allocation.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void *wad_malloc(int nbytes) {
|
|
void *ptr;
|
|
WadMemory *wm;
|
|
char *c;
|
|
int npages;
|
|
/* wad_printf("wad_malloc: %d\n", nbytes); */
|
|
if (nbytes >= ((npalloc*pagesize) >> 2)) {
|
|
/* Large allocation. */
|
|
npages = ((nbytes + sizeof(WadMemory))/pagesize) + 1;
|
|
ptr = wad_page_alloc(npages);
|
|
if (!ptr) return 0;
|
|
wm = (WadMemory *)ptr;
|
|
wm->npages = npages;
|
|
wm->last = sizeof(WadMemory) + 8;
|
|
wm->next = current;
|
|
current = wm;
|
|
c = (char *) current + (current->last);
|
|
current->last += ((nbytes & ~0x7) + 8);
|
|
return c;
|
|
}
|
|
/* Small allocation. See if there are any regions big enough */
|
|
wm = current;
|
|
while (wm) {
|
|
if (((wm->npages*pagesize) - wm->last) > nbytes) {
|
|
/* Yep. Found a region */
|
|
break;
|
|
}
|
|
wm = wm->next;
|
|
}
|
|
if (!wm) {
|
|
/* wad_printf("wad_malloc: new page\n", nbytes);*/
|
|
wm = (WadMemory *) wad_page_alloc(npalloc);
|
|
if (!wm) return 0;
|
|
wm->npages = npalloc;
|
|
wm->last = sizeof(WadMemory) + 8;
|
|
wm->next = current;
|
|
current = wm;
|
|
}
|
|
c = ((char *) wm) + (wm->last);
|
|
wm->last += ((nbytes & ~0x7) + 8);
|
|
return c;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* wad_strdup()
|
|
*
|
|
* Duplicate a string
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
char *wad_strdup(const char *c) {
|
|
char *t;
|
|
if (!c) c = "";
|
|
t = (char *) wad_malloc(strlen(c)+1);
|
|
wad_strcpy(t,c);
|
|
return t;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* wad_memcpy()
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void wad_memcpy(void *t, const void *s, unsigned len) {
|
|
char *tc, *sc;
|
|
int i;
|
|
tc = (char *) t;
|
|
sc = (char *) s;
|
|
for (i = 0; i < len; i++, tc++, sc++)
|
|
*tc = *sc;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* wad_memory_debug()
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void wad_memory_debug() {
|
|
int total_alloc = 0;
|
|
int inuse = 0;
|
|
WadMemory *m;
|
|
if (wad_debug_mode & DEBUG_MEMORY) {
|
|
m = current;
|
|
while (m) {
|
|
total_alloc += (m->npages)*pagesize;
|
|
inuse += m->last;
|
|
m = m->next;
|
|
}
|
|
wad_printf("WAD: memory allocated %d bytes (%d bytes used).\n", total_alloc, inuse);
|
|
}
|
|
}
|