Tue May 13 16:41:49 CEST 2003 Paolo Molaro <lupus@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         union {
33                 double pad; /* to assure proper alignment */
34                 guint32 allocated;
35         } d;
36 };
37
38 /**
39  * mono_mempool_new:
40  *
41  * Returns: a new memory pool.
42  */
43 MonoMemPool *
44 mono_mempool_new ()
45 {
46         MonoMemPool *pool = g_malloc (MONO_MEMPOOL_PAGESIZE);
47
48         pool->next = NULL;
49         pool->pos = (char *)pool + sizeof (MonoMemPool);
50         pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool);
51         pool->d.allocated = MONO_MEMPOOL_PAGESIZE;
52         return pool;
53 }
54
55 /**
56  * mono_mempool_destroy:
57  * @pool: the momory pool to destroy
58  *
59  * Free all memory associated with this pool.
60  */
61 void
62 mono_mempool_destroy (MonoMemPool *pool)
63 {
64         MonoMemPool *p, *n;
65
66         p = pool;
67         while (p) {
68                 n = p->next;
69                 g_free (p);
70                 p = n;
71         }
72 }
73
74 void
75 mono_mempool_empty (MonoMemPool *pool)
76 {
77         pool->pos = (char *)pool + sizeof (MonoMemPool);
78         pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool);
79 }
80
81 /**
82  * mono_mempool_stats:
83  * @pool: the momory pool we need stats for
84  *
85  * Print a few stats about the mempool
86  */
87 void
88 mono_mempool_stats (MonoMemPool *pool)
89 {
90         MonoMemPool *p, *n;
91         int count = 0;
92         guint32 still_free = 0;
93
94         p = pool;
95         while (p) {
96                 still_free += p->rest;
97                 n = p->next;
98                 p = n;
99                 count++;
100         }
101         if (pool) {
102                 g_print ("Mempool %p stats:\n", pool);
103                 g_print ("Total mem allocated: %d\n", pool->d.allocated);
104                 g_print ("Num chunks: %d\n", count);
105                 g_print ("Free memory: %d\n", still_free);
106         }
107 }
108
109 /**
110  * mono_mempool_alloc:
111  * @pool: the momory pool to destroy
112  * @size: size of the momory block
113  *
114  * Allocates a new block of memory in @pool. @size must 
115  * be smaller than 256.
116  *
117  * Returns: the address of a newly allocated memory block.
118  */
119 gpointer
120 mono_mempool_alloc (MonoMemPool *pool, guint size)
121 {
122         gpointer rval;
123         
124         g_assert (pool != NULL);
125
126         size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1);
127
128         if (pool->rest < size) {
129                 if (size >= 4096) {
130                         MonoMemPool *np = g_malloc (sizeof (MonoMemPool) + size);
131                         np->next = pool->next;
132                         pool->next = np;
133                         pool->d.allocated += sizeof (MonoMemPool) + size;
134                         return (char *)np + sizeof (MonoMemPool);
135                 } else {
136                         MonoMemPool *np = g_malloc (MONO_MEMPOOL_PAGESIZE);
137                         np->next = pool->next;
138                         pool->next = np;
139                         pool->pos = (char *)np + sizeof (MonoMemPool);
140                         pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool);
141                         pool->d.allocated += MONO_MEMPOOL_PAGESIZE;
142                 }
143         }
144
145         rval = pool->pos;
146         pool->rest -= size;
147         pool->pos = (char *)pool->pos + size;
148
149         return rval;
150 }
151
152 /**
153  * mono_mempool_alloc0:
154  *
155  * same as mono_mempool_alloc, but fills memory with zero.
156  */
157 gpointer
158 mono_mempool_alloc0 (MonoMemPool *pool, guint size)
159 {
160         gpointer rval = mono_mempool_alloc (pool, size);
161         memset (rval, 0, size);
162         return rval;
163 }
164