2004-09-01 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mono / metadata / mempool.c
1 /*
2  * mempool.c: efficient memory allocation
3  *
4  * MonoMemPool is for fast allocation of memory. We free
5  * all memory when the pool is destroyed.
6  *
7  * Author:
8  *   Dietmar Maurer (dietmar@ximian.com)
9  *
10  * (C) 2001 Ximian, Inc.
11  */
12
13 #include <config.h>
14 #include <glib.h>
15 #include <string.h>
16
17 #include "mempool.h"
18
19 /*
20  * MonoMemPool is for fast allocation of memory. We free
21  * all memory when the pool is destroyed.
22  */
23
24 #define MEM_ALIGN 8
25
26 #define MONO_MEMPOOL_PAGESIZE 8192
27
28 struct _MonoMemPool {
29         MonoMemPool *next;
30         gint rest;
31         gpointer pos;
32         guint32 size;
33         union {
34                 double pad; /* to assure proper alignment */
35                 guint32 allocated;
36         } d;
37 };
38
39 /**
40  * mono_mempool_new:
41  *
42  * Returns: a new memory pool.
43  */
44 MonoMemPool *
45 mono_mempool_new ()
46 {
47         MonoMemPool *pool = g_malloc (MONO_MEMPOOL_PAGESIZE);
48
49         pool->next = NULL;
50         pool->pos = (char *)pool + sizeof (MonoMemPool);
51         pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool);
52         pool->d.allocated = pool->size = MONO_MEMPOOL_PAGESIZE;
53         return pool;
54 }
55
56 /**
57  * mono_mempool_destroy:
58  * @pool: the memory pool to destroy
59  *
60  * Free all memory associated with this pool.
61  */
62 void
63 mono_mempool_destroy (MonoMemPool *pool)
64 {
65         MonoMemPool *p, *n;
66
67         p = pool;
68         while (p) {
69                 n = p->next;
70                 g_free (p);
71                 p = n;
72         }
73 }
74
75 /**
76  * mono_mempool_invalidate:
77  * @pool: the memory pool to invalidate
78  *
79  * Fill the memory associated with this pool to 0x2a (42). Useful for debugging.
80  */
81 void
82 mono_mempool_invalidate (MonoMemPool *pool)
83 {
84         MonoMemPool *p, *n;
85
86         p = pool;
87         while (p) {
88                 n = p->next;
89                 memset (p, 42, p->size);
90                 p = n;
91         }
92 }
93
94 void
95 mono_mempool_empty (MonoMemPool *pool)
96 {
97         pool->pos = (char *)pool + sizeof (MonoMemPool);
98         pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool);
99 }
100
101 /**
102  * mono_mempool_stats:
103  * @pool: the momory pool we need stats for
104  *
105  * Print a few stats about the mempool
106  */
107 void
108 mono_mempool_stats (MonoMemPool *pool)
109 {
110         MonoMemPool *p, *n;
111         int count = 0;
112         guint32 still_free = 0;
113
114         p = pool;
115         while (p) {
116                 still_free += p->rest;
117                 n = p->next;
118                 p = n;
119                 count++;
120         }
121         if (pool) {
122                 g_print ("Mempool %p stats:\n", pool);
123                 g_print ("Total mem allocated: %d\n", pool->d.allocated);
124                 g_print ("Num chunks: %d\n", count);
125                 g_print ("Free memory: %d\n", still_free);
126         }
127 }
128
129 /**
130  * mono_mempool_alloc:
131  * @pool: the momory pool to destroy
132  * @size: size of the momory block
133  *
134  * Allocates a new block of memory in @pool. @size must 
135  * be smaller than 256.
136  *
137  * Returns: the address of a newly allocated memory block.
138  */
139 gpointer
140 mono_mempool_alloc (MonoMemPool *pool, guint size)
141 {
142         gpointer rval;
143         
144         g_assert (pool != NULL);
145
146         size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1);
147
148         if (pool->rest < size) {
149                 if (size >= 4096) {
150                         MonoMemPool *np = g_malloc (sizeof (MonoMemPool) + size);
151                         np->next = pool->next;
152                         pool->next = np;
153                         np->size = sizeof (MonoMemPool) + size;
154                         pool->d.allocated += sizeof (MonoMemPool) + size;
155                         return (char *)np + sizeof (MonoMemPool);
156                 } else {
157                         MonoMemPool *np = g_malloc (MONO_MEMPOOL_PAGESIZE);
158                         np->next = pool->next;
159                         pool->next = np;
160                         pool->pos = (char *)np + sizeof (MonoMemPool);
161                         np->size = MONO_MEMPOOL_PAGESIZE;
162                         pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool);
163                         pool->d.allocated += MONO_MEMPOOL_PAGESIZE;
164                 }
165         }
166
167         rval = pool->pos;
168         pool->rest -= size;
169         pool->pos = (char *)pool->pos + size;
170
171         return rval;
172 }
173
174 /**
175  * mono_mempool_alloc0:
176  *
177  * same as mono_mempool_alloc, but fills memory with zero.
178  */
179 gpointer
180 mono_mempool_alloc0 (MonoMemPool *pool, guint size)
181 {
182         gpointer rval = mono_mempool_alloc (pool, size);
183         memset (rval, 0, size);
184         return rval;
185 }
186