Line data Source code
1 : /* src/mm/memory.cpp - memory management
2 :
3 : Copyright (C) 1996-2013
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 : #include "mm/memory.hpp"
26 : #include <assert.h> // for assert
27 : #include <stdint.h> // for int32_t
28 : #include <stdlib.h> // for realloc
29 : #include "config.h" // for ENABLE_MEMCHECK, etc
30 : #include "threads/thread.hpp" // for threads_sleep, etc
31 : #include "toolbox/logging.hpp" // for log_text
32 : #include "vm/options.hpp" // for opt_ProfileGCMemoryUsage, etc
33 : #include "vm/os.hpp" // for os
34 : #include "vm/types.hpp" // for u1
35 : #include "vm/utf8.hpp" // for Utf8String
36 : #include "vm/vm.hpp" // for vm_abort
37 : #include "vm/statistics.hpp"
38 :
39 : #if defined(__DARWIN__)
40 : /* If we compile with -ansi on darwin, <sys/types.h> is not
41 : included. So let's do it here. */
42 : # include <sys/types.h>
43 : #endif
44 :
45 : STAT_DECLARE_GROUP(memory_stat)
46 : STAT_REGISTER_SUBGROUP(max_mem_stat,"max. mem","max. memory",memory_stat)
47 : STAT_REGISTER_SUBGROUP(not_freed_mem_stat,"not freed","not freed",memory_stat)
48 : STAT_REGISTER_GROUP_VAR(s4,maxmemusage,0,"maxmemusage","max. heap memory",max_mem_stat)
49 : STAT_REGISTER_GROUP_VAR(s4,memoryusage,0,"memoryusage","heap memory not freed",not_freed_mem_stat)
50 : /* memory_mprotect *************************************************************
51 :
52 : Convenience function for mprotect. This function also does error
53 : checking.
54 :
55 : *******************************************************************************/
56 :
57 0 : void memory_mprotect(void *addr, size_t len, int prot)
58 : {
59 0 : if (os::mprotect(addr, len, prot) != 0)
60 0 : os::abort_errno("memory_mprotect: os::mprotect failed");
61 0 : }
62 :
63 :
64 : /* memory_checked_alloc ********************************************************
65 :
66 : Allocated zeroed-out memory and does an OOM check.
67 :
68 : ERROR HANDLING:
69 : XXX If no memory could be allocated, this function justs *exists*.
70 :
71 : *******************************************************************************/
72 :
73 8077857 : void *memory_checked_alloc(size_t size)
74 : {
75 : /* always allocate memory zeroed out */
76 :
77 8077857 : void *p = os::calloc(size, 1);
78 :
79 8077844 : if (p == NULL)
80 0 : vm_abort("memory_checked_alloc: calloc failed: out of memory");
81 :
82 8077844 : return p;
83 : }
84 :
85 :
86 6962729 : void *mem_alloc(int32_t size)
87 : {
88 : void *m;
89 :
90 6962729 : if (size == 0)
91 430499 : return NULL;
92 :
93 : STATISTICS(memoryusage += size);
94 : STATISTICS(maxmemusage.max(memoryusage.get()));
95 :
96 6532230 : m = memory_checked_alloc(size);
97 :
98 : #if defined(ENABLE_MEMCHECK)
99 : /* XXX we would like to poison the memory, but callers rely on */
100 : /* the zeroing. This should change sooner or later. */
101 : /* memset(m, MEMORY_CLEAR_BYTE, size); */
102 : #endif
103 :
104 6532230 : return m;
105 : }
106 :
107 :
108 65179 : void *mem_realloc(void *src, int32_t len1, int32_t len2)
109 : {
110 : void *dst;
111 :
112 : /* prevent compiler warnings */
113 :
114 65179 : dst = NULL;
115 :
116 65179 : if (src == NULL)
117 158 : if (len1 != 0)
118 0 : vm_abort("mem_realloc: reallocating memoryblock with address NULL, length != 0");
119 :
120 : STATISTICS(memoryusage += len2 - len1);
121 :
122 : #if defined(ENABLE_MEMCHECK)
123 : if (len2 < len1)
124 : os::memset((u1*)dst + len2, MEMORY_CLEAR_BYTE, len1 - len2);
125 : #endif
126 :
127 65179 : dst = realloc(src, len2);
128 :
129 65179 : if (dst == NULL)
130 0 : vm_abort("mem_realloc: realloc failed: out of memory");
131 :
132 : #if defined(ENABLE_MEMCHECK)
133 : if (len2 > len1)
134 : os::memset((u1*)dst + len1, MEMORY_CLEAR_BYTE, len2 - len1);
135 : #endif
136 :
137 65179 : return dst;
138 : }
139 :
140 :
141 2196160 : void mem_free(void *m, int32_t size)
142 : {
143 2196160 : if (!m) {
144 2116 : if (size == 0)
145 2116 : return;
146 :
147 0 : log_text("returned memoryblock with address NULL, length != 0");
148 0 : assert(0);
149 : }
150 :
151 : STATISTICS(memoryusage -= size);
152 :
153 : #if defined(ENABLE_MEMCHECK)
154 : /* destroy the contents */
155 : os::memset(m, MEMORY_CLEAR_BYTE, size);
156 : #endif
157 :
158 2194044 : os::free(m);
159 : }
160 :
161 :
162 : /* memory_thread ***************************************************************
163 :
164 : Prints regularly memory statistics.
165 :
166 : *******************************************************************************/
167 :
168 0 : static void memory_thread(void)
169 : {
170 : int32_t seconds;
171 :
172 : /* Prevent compiler warning. */
173 :
174 0 : seconds = 1;
175 :
176 : /* If both arguments are specified, use the value of
177 : ProfileMemoryUsage. */
178 :
179 0 : if (opt_ProfileGCMemoryUsage)
180 0 : seconds = opt_ProfileGCMemoryUsage;
181 :
182 0 : if (opt_ProfileMemoryUsage)
183 0 : seconds = opt_ProfileMemoryUsage;
184 :
185 0 : while (true) {
186 : /* sleep thread */
187 :
188 0 : threads_sleep(seconds * 1000, 0);
189 :
190 : # if 0 && defined(ENABLE_STATISTICS)
191 : /* Print current date and time (only when we print to the
192 : stdout). */
193 :
194 : if (!opt_ProfileMemoryUsageGNUPlot)
195 : statistics_print_date();
196 :
197 : /* print memory usage */
198 :
199 : if (opt_ProfileMemoryUsage)
200 : statistics_print_memory_usage();
201 :
202 : /* print GC memory usage */
203 :
204 : if (opt_ProfileGCMemoryUsage)
205 : statistics_print_gc_memory_usage();
206 : # endif
207 : }
208 : }
209 :
210 :
211 : /* memory_start_thread *********************************************************
212 :
213 : Starts the memory profiling thread.
214 :
215 : *******************************************************************************/
216 :
217 0 : bool memory_start_thread(void)
218 : {
219 0 : Utf8String name = Utf8String::from_utf8("Memory Profiler");
220 :
221 : /* start the memory profiling thread */
222 :
223 0 : if (!threads_thread_start_internal(name, memory_thread))
224 0 : return false;
225 :
226 : /* everything's ok */
227 :
228 0 : return true;
229 : }
230 :
231 :
232 : /*
233 : * These are local overrides for various environment variables in Emacs.
234 : * Please do not remove this and leave it at the end of the file, where
235 : * Emacs will automagically detect them.
236 : * ---------------------------------------------------------------------
237 : * Local variables:
238 : * mode: c++
239 : * indent-tabs-mode: t
240 : * c-basic-offset: 4
241 : * tab-width: 4
242 : * End:
243 : * vim:noexpandtab:sw=4:ts=4:
244 : */
|