Upstream version 1.3.40
[profile/ivi/swig.git] / Tools / WAD / Wad / memory.c
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
34 static char cvs[] = "$Id: memory.c 10001 2007-10-17 21:33:57Z wsfulton $";
35
36 typedef 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
42 static WadMemory *current = 0;                /* Current memory block        */
43 static int        pagesize = 0;               /* System page size            */
44 static int        devzero = 0;
45 static int        npalloc = 8;                 /* Number of pages per alloc   */
46
47 /* -----------------------------------------------------------------------------
48  * wad_memory_init()
49  *
50  * Initialize the WAD allocator.
51  * ----------------------------------------------------------------------------- */
52
53 int 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
69 void *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
87 void *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
136 char *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
148 void 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
161 void 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 }