* configure.ac: Define automake conditinal ENABLE_TLH if SSA enabled.
[cacao.git] / src / mm / memory.c
1 /* src/mm/memory.c - memory management
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <errno.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34
35 #if defined(__DARWIN__)
36 /* If we compile with -ansi on darwin, <sys/types.h> is not
37    included. So let's do it here. */
38 # include <sys/types.h>
39 #endif
40
41 #include "vm/types.h"
42
43 #include "arch.h"
44
45 #include "mm/memory.h"
46
47 #include "native/native.h"
48
49 #include "threads/lock-common.h"
50 #include "threads/thread.h"
51
52 #include "toolbox/logging.h"
53
54 #include "vm/exceptions.h"
55 #include "vm/global.h"
56 #include "vm/stringlocal.h"
57 #include "vm/vm.h"
58
59 #include "vmcore/options.h"
60
61 #if defined(ENABLE_STATISTICS)
62 # include "vmcore/statistics.h"
63 #endif
64
65 #include "vmcore/system.h"
66
67
68 /* memory_mprotect *************************************************************
69
70    Convenience function for mprotect.  This function also does error
71    checking.
72
73 *******************************************************************************/
74
75 void memory_mprotect(void *addr, size_t len, int prot)
76 {
77         if (system_mprotect(addr, len, prot) != 0)
78                 vm_abort("memory_mprotect: system_mprotect failed: %s",
79                                  strerror(errno));
80 }
81
82
83 /* memory_checked_alloc ********************************************************
84
85    Allocated zeroed-out memory and does an OOM check.
86
87    ERROR HANDLING:
88       XXX If no memory could be allocated, this function justs *exists*.
89
90 *******************************************************************************/
91
92 void *memory_checked_alloc(size_t size)
93 {
94         /* always allocate memory zeroed out */
95
96         void *p = calloc(size, 1);
97
98         if (p == NULL)
99                 vm_abort("memory_checked_alloc: calloc failed: out of memory");
100
101         return p;
102 }
103
104
105 void *mem_alloc(int32_t size)
106 {
107         void *m;
108
109         if (size == 0)
110                 return NULL;
111
112 #if defined(ENABLE_STATISTICS)
113         if (opt_stat) {
114                 memoryusage += size;
115
116                 if (memoryusage > maxmemusage)
117                         maxmemusage = memoryusage;
118         }
119 #endif
120
121         m = memory_checked_alloc(size);
122
123 #if defined(ENABLE_MEMCHECK)
124         /* XXX we would like to poison the memory, but callers rely on */
125         /* the zeroing. This should change sooner or later.            */
126         /* memset(m, MEMORY_CLEAR_BYTE, size); */
127 #endif
128
129         return m;
130 }
131
132
133 void *mem_realloc(void *src, int32_t len1, int32_t len2)
134 {
135         void *dst;
136
137         /* prevent compiler warnings */
138
139         dst = NULL;
140
141         if (src == NULL)
142                 if (len1 != 0)
143                         vm_abort("mem_realloc: reallocating memoryblock with address NULL, length != 0");
144
145 #if defined(ENABLE_STATISTICS)
146         if (opt_stat)
147                 memoryusage = (memoryusage - len1) + len2;
148 #endif
149
150 #if defined(ENABLE_MEMCHECK)
151         if (len2 < len1)
152                 memset((u1*)dst + len2, MEMORY_CLEAR_BYTE, len1 - len2);
153 #endif
154
155         dst = realloc(src, len2);
156
157         if (dst == NULL)
158                 vm_abort("mem_realloc: realloc failed: out of memory");
159
160 #if defined(ENABLE_MEMCHECK)
161         if (len2 > len1)
162                 memset((u1*)dst + len1, MEMORY_CLEAR_BYTE, len2 - len1);
163 #endif
164
165         return dst;
166 }
167
168
169 void mem_free(void *m, int32_t size)
170 {
171         if (!m) {
172                 if (size == 0)
173                         return;
174
175                 log_text("returned memoryblock with address NULL, length != 0");
176                 assert(0);
177         }
178
179 #if defined(ENABLE_STATISTICS)
180         if (opt_stat)
181                 memoryusage -= size;
182 #endif
183
184 #if defined(ENABLE_MEMCHECK)
185         /* destroy the contents */
186         memset(m, MEMORY_CLEAR_BYTE, size);
187 #endif
188
189         free(m);
190 }
191
192
193 /* memory_thread ***************************************************************
194
195    Prints regularly memory statistics.
196
197 *******************************************************************************/
198
199 #if defined(ENABLE_THREADS) && !defined(NDEBUG)
200 static void memory_thread(void)
201 {
202         int32_t seconds;
203
204         /* Prevent compiler warning. */
205
206         seconds = 1;
207
208         /* If both arguments are specified, use the value of
209            ProfileMemoryUsage. */
210
211         if (opt_ProfileGCMemoryUsage)
212                 seconds = opt_ProfileGCMemoryUsage;
213
214         if (opt_ProfileMemoryUsage)
215                 seconds = opt_ProfileMemoryUsage;
216
217         while (true) {
218                 /* sleep thread */
219
220                 threads_sleep(seconds * 1000, 0);
221
222 # if defined(ENABLE_STATISTICS)
223                 /* Print current date and time (only when we print to the
224                    stdout). */
225
226                 if (!opt_ProfileMemoryUsageGNUPlot)
227                         statistics_print_date();
228
229                 /* print memory usage */
230
231                 if (opt_ProfileMemoryUsage)
232                         statistics_print_memory_usage();
233
234                 /* print GC memory usage */
235
236                 if (opt_ProfileGCMemoryUsage)
237                         statistics_print_gc_memory_usage();
238 # endif
239         }
240 }
241 #endif
242
243
244 /* memory_start_thread *********************************************************
245
246    Starts the memory profiling thread.
247
248 *******************************************************************************/
249
250 #if defined(ENABLE_THREADS) && !defined(NDEBUG)
251 bool memory_start_thread(void)
252 {
253         utf *name;
254
255         name = utf_new_char("Memory Profiler");
256
257         /* start the memory profiling thread */
258
259         if (!threads_thread_start_internal(name, memory_thread))
260                 return false;
261
262         /* everything's ok */
263
264         return true;
265 }
266 #endif
267
268
269 /*
270  * These are local overrides for various environment variables in Emacs.
271  * Please do not remove this and leave it at the end of the file, where
272  * Emacs will automagically detect them.
273  * ---------------------------------------------------------------------
274  * Local variables:
275  * mode: c
276  * indent-tabs-mode: t
277  * c-basic-offset: 4
278  * tab-width: 4
279  * End:
280  * vim:noexpandtab:sw=4:ts=4:
281  */