|
|
1 | /** |
|
|
2 | * ZANavi, Zoff Android Navigation system. |
|
|
3 | * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc> |
|
|
4 | * |
|
|
5 | * This program is free software; you can redistribute it and/or |
|
|
6 | * modify it under the terms of the GNU General Public License |
|
|
7 | * version 2 as published by the Free Software Foundation. |
|
|
8 | * |
|
|
9 | * This program is distributed in the hope that it will be useful, |
|
|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
12 | * GNU General Public License for more details. |
|
|
13 | * |
|
|
14 | * You should have received a copy of the GNU General Public License |
|
|
15 | * along with this program; if not, write to the |
|
|
16 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
|
17 | * Boston, MA 02110-1301, USA. |
|
|
18 | */ |
|
|
19 | |
1 | /* GLIB - Library of useful routines for C programming |
20 | /* GLIB - Library of useful routines for C programming |
2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
21 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
3 | * |
22 | * |
4 | * This library is free software; you can redistribute it and/or |
23 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
24 | * modify it under the terms of the GNU Lesser General Public |
… | |
… | |
36 | |
55 | |
37 | #include "glib.h" |
56 | #include "glib.h" |
38 | #include "gthreadprivate.h" |
57 | #include "gthreadprivate.h" |
39 | #include "galias.h" |
58 | #include "galias.h" |
40 | |
59 | |
|
|
60 | #include "debug.h" |
|
|
61 | |
41 | #define MEM_PROFILE_TABLE_SIZE 4096 |
62 | #define MEM_PROFILE_TABLE_SIZE 4096 |
42 | |
|
|
43 | |
63 | |
44 | /* notes on macros: |
64 | /* notes on macros: |
45 | * having G_DISABLE_CHECKS defined disables use of glib_mem_profiler_table and |
65 | * having G_DISABLE_CHECKS defined disables use of glib_mem_profiler_table and |
46 | * g_mem_profile(). |
66 | * g_mem_profile(). |
47 | * REALLOC_0_WORKS is defined if g_realloc (NULL, x) works. |
67 | * REALLOC_0_WORKS is defined if g_realloc (NULL, x) works. |
… | |
… | |
50 | * g_mem_gc_friendly is TRUE, freed memory should be 0-wiped. |
70 | * g_mem_gc_friendly is TRUE, freed memory should be 0-wiped. |
51 | */ |
71 | */ |
52 | |
72 | |
53 | /* --- prototypes --- */ |
73 | /* --- prototypes --- */ |
54 | static gboolean g_mem_initialized = FALSE; |
74 | static gboolean g_mem_initialized = FALSE; |
55 | static void g_mem_init_nomessage (void); |
75 | static void g_mem_init_nomessage(void); |
56 | |
|
|
57 | |
76 | |
58 | /* --- malloc wrappers --- */ |
77 | /* --- malloc wrappers --- */ |
59 | #ifndef REALLOC_0_WORKS |
78 | #ifndef REALLOC_0_WORKS |
60 | static gpointer |
79 | static gpointer standard_realloc(gpointer mem, gsize n_bytes) |
61 | standard_realloc (gpointer mem, |
|
|
62 | gsize n_bytes) |
|
|
63 | { |
80 | { |
64 | if (!mem) |
81 | if (!mem) |
65 | return malloc (n_bytes); |
82 | return malloc(n_bytes); |
66 | else |
83 | else |
67 | return realloc (mem, n_bytes); |
84 | return realloc(mem, n_bytes); |
68 | } |
85 | } |
69 | #endif /* !REALLOC_0_WORKS */ |
86 | #endif /* !REALLOC_0_WORKS */ |
70 | |
87 | |
71 | #ifdef SANE_MALLOC_PROTOS |
88 | #ifdef SANE_MALLOC_PROTOS |
72 | # define standard_malloc malloc |
89 | # define standard_malloc malloc |
… | |
… | |
76 | # define standard_free free |
93 | # define standard_free free |
77 | # define standard_calloc calloc |
94 | # define standard_calloc calloc |
78 | # define standard_try_malloc malloc |
95 | # define standard_try_malloc malloc |
79 | # define standard_try_realloc realloc |
96 | # define standard_try_realloc realloc |
80 | #else /* !SANE_MALLOC_PROTOS */ |
97 | #else /* !SANE_MALLOC_PROTOS */ |
81 | static gpointer |
|
|
82 | standard_malloc (gsize n_bytes) |
98 | static gpointer standard_malloc(gsize n_bytes) |
83 | { |
99 | { |
84 | return malloc (n_bytes); |
100 | return malloc(n_bytes); |
85 | } |
101 | } |
86 | # ifdef REALLOC_0_WORKS |
102 | # ifdef REALLOC_0_WORKS |
87 | static gpointer |
103 | static gpointer |
88 | standard_realloc (gpointer mem, |
104 | standard_realloc (gpointer mem, |
89 | gsize n_bytes) |
105 | gsize n_bytes) |
90 | { |
106 | { |
91 | return realloc (mem, n_bytes); |
107 | return realloc (mem, n_bytes); |
92 | } |
108 | } |
93 | # endif /* REALLOC_0_WORKS */ |
109 | # endif /* REALLOC_0_WORKS */ |
94 | static void |
|
|
95 | standard_free (gpointer mem) |
110 | static void standard_free(gpointer mem) |
96 | { |
111 | { |
97 | free (mem); |
112 | free(mem); |
98 | } |
113 | } |
99 | static gpointer |
114 | static gpointer standard_calloc(gsize n_blocks, gsize n_bytes) |
100 | standard_calloc (gsize n_blocks, |
|
|
101 | gsize n_bytes) |
|
|
102 | { |
115 | { |
103 | return calloc (n_blocks, n_bytes); |
116 | return calloc(n_blocks, n_bytes); |
104 | } |
117 | } |
105 | #define standard_try_malloc standard_malloc |
118 | #define standard_try_malloc standard_malloc |
106 | #define standard_try_realloc standard_realloc |
119 | #define standard_try_realloc standard_realloc |
107 | #endif /* !SANE_MALLOC_PROTOS */ |
120 | #endif /* !SANE_MALLOC_PROTOS */ |
108 | |
121 | |
109 | |
|
|
110 | /* --- variables --- */ |
122 | /* --- variables --- */ |
111 | static GMemVTable glib_mem_vtable = { |
123 | static GMemVTable glib_mem_vtable = { standard_malloc, standard_realloc, standard_free, standard_calloc, standard_try_malloc, standard_try_realloc, }; |
112 | standard_malloc, |
|
|
113 | standard_realloc, |
|
|
114 | standard_free, |
|
|
115 | standard_calloc, |
|
|
116 | standard_try_malloc, |
|
|
117 | standard_try_realloc, |
|
|
118 | }; |
|
|
119 | |
|
|
120 | |
124 | |
121 | /* --- functions --- */ |
125 | /* --- functions --- */ |
122 | gpointer |
|
|
123 | g_malloc (gsize n_bytes) |
126 | gpointer g_malloc(gsize n_bytes) |
124 | { |
127 | { |
|
|
128 | if (G_UNLIKELY(!g_mem_initialized)) |
|
|
129 | g_mem_init_nomessage(); |
|
|
130 | if (G_LIKELY(n_bytes)) |
|
|
131 | { |
|
|
132 | gpointer mem; |
|
|
133 | |
|
|
134 | mem = glib_mem_vtable.malloc(n_bytes); |
|
|
135 | if (mem) |
|
|
136 | return mem; |
|
|
137 | |
|
|
138 | #if NOT_NEEDED_FOR_NAVIT |
|
|
139 | g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes", |
|
|
140 | G_STRLOC, n_bytes); |
|
|
141 | #endif /* NOT_NEEDED_FOR_NAVIT */ |
|
|
142 | } |
|
|
143 | |
|
|
144 | return NULL; |
|
|
145 | } |
|
|
146 | |
|
|
147 | gpointer g_malloc0(gsize n_bytes) |
|
|
148 | { |
|
|
149 | if (G_UNLIKELY(!g_mem_initialized)) |
|
|
150 | g_mem_init_nomessage(); |
|
|
151 | if (G_LIKELY(n_bytes)) |
|
|
152 | { |
|
|
153 | gpointer mem; |
|
|
154 | |
|
|
155 | mem = glib_mem_vtable.calloc(1, n_bytes); |
|
|
156 | if (mem) |
|
|
157 | return mem; |
|
|
158 | |
|
|
159 | #if NOT_NEEDED_FOR_NAVIT |
|
|
160 | g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes", |
|
|
161 | G_STRLOC, n_bytes); |
|
|
162 | #endif /* NOT_NEEDED_FOR_NAVIT */ |
|
|
163 | } |
|
|
164 | |
|
|
165 | return NULL; |
|
|
166 | } |
|
|
167 | |
|
|
168 | gpointer g_realloc(gpointer mem, gsize n_bytes) |
|
|
169 | { |
|
|
170 | if (G_UNLIKELY(!g_mem_initialized)) |
|
|
171 | g_mem_init_nomessage(); |
|
|
172 | if (G_LIKELY(n_bytes)) |
|
|
173 | { |
|
|
174 | mem = glib_mem_vtable.realloc(mem, n_bytes); |
|
|
175 | if (mem) |
|
|
176 | return mem; |
|
|
177 | |
|
|
178 | #if NOT_NEEDED_FOR_NAVIT |
|
|
179 | g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes", |
|
|
180 | G_STRLOC, n_bytes); |
|
|
181 | #endif /* NOT_NEEDED_FOR_NAVIT */ |
|
|
182 | } |
|
|
183 | |
|
|
184 | if (mem) |
|
|
185 | glib_mem_vtable.free(mem); |
|
|
186 | |
|
|
187 | return NULL; |
|
|
188 | } |
|
|
189 | |
|
|
190 | void g_free_debug_func(const char *file, const int line, const char *function, gpointer mem) |
|
|
191 | { |
|
|
192 | #ifdef HAVE_API_ANDROID |
|
|
193 | #ifdef DEBUG_GLIB_MEM_FUNCTIONS |
|
|
194 | gsize *p = mem; |
|
|
195 | p -= 2; |
|
|
196 | gsize n_bytes = p[1]; |
|
|
197 | dbg(0,"%s:%s:%d: g_free %p size=%"G_GSIZE_FORMAT" bytes\n", file, function, line, mem, n_bytes); |
|
|
198 | #else |
|
|
199 | dbg(0,"%s:%s:%d: g_free %p\n", file, function, line, mem); |
|
|
200 | #endif |
|
|
201 | #endif |
|
|
202 | |
|
|
203 | if (G_UNLIKELY(!g_mem_initialized)) |
|
|
204 | g_mem_init_nomessage(); |
|
|
205 | if (G_LIKELY(mem)) |
|
|
206 | glib_mem_vtable.free(mem); |
|
|
207 | } |
|
|
208 | |
|
|
209 | #ifndef DEBUG_GLIB_FREE |
|
|
210 | void g_free(gpointer mem) |
|
|
211 | { |
|
|
212 | if (G_UNLIKELY(!g_mem_initialized)) |
|
|
213 | g_mem_init_nomessage(); |
|
|
214 | if (G_LIKELY(mem)) |
|
|
215 | glib_mem_vtable.free(mem); |
|
|
216 | } |
|
|
217 | #else |
|
|
218 | void |
|
|
219 | g_debug_free_func(gpointer mem) |
|
|
220 | { |
|
|
221 | // g_free_debug_func("unknown",0,"unknown",mem); |
|
|
222 | |
|
|
223 | #ifdef HAVE_API_ANDROID |
|
|
224 | dbg(0,"%s:%s:%d: g_free %p\n", "unknown", "unknown", "0", mem); |
|
|
225 | #endif |
|
|
226 | |
125 | if (G_UNLIKELY (!g_mem_initialized)) |
227 | if (G_UNLIKELY (!g_mem_initialized)) |
126 | g_mem_init_nomessage(); |
228 | g_mem_init_nomessage(); |
|
|
229 | if (G_LIKELY (mem)) |
|
|
230 | glib_mem_vtable.free (mem); |
|
|
231 | } |
|
|
232 | #endif |
|
|
233 | |
|
|
234 | gpointer g_try_malloc(gsize n_bytes) |
|
|
235 | { |
|
|
236 | if (G_UNLIKELY(!g_mem_initialized)) |
|
|
237 | g_mem_init_nomessage(); |
127 | if (G_LIKELY (n_bytes)) |
238 | if (G_LIKELY(n_bytes)) |
128 | { |
239 | return glib_mem_vtable.try_malloc(n_bytes); |
|
|
240 | else |
|
|
241 | return NULL; |
|
|
242 | } |
|
|
243 | |
|
|
244 | gpointer g_try_malloc0(gsize n_bytes) |
|
|
245 | { |
129 | gpointer mem; |
246 | gpointer mem; |
130 | |
247 | |
131 | mem = glib_mem_vtable.malloc (n_bytes); |
248 | mem = g_try_malloc(n_bytes); |
132 | if (mem) |
249 | |
|
|
250 | if (mem) |
|
|
251 | memset(mem, 0, n_bytes); |
|
|
252 | |
133 | return mem; |
253 | return mem; |
134 | |
|
|
135 | #if NOT_NEEDED_FOR_NAVIT |
|
|
136 | g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes", |
|
|
137 | G_STRLOC, n_bytes); |
|
|
138 | #endif /* NOT_NEEDED_FOR_NAVIT */ |
|
|
139 | } |
|
|
140 | |
|
|
141 | return NULL; |
|
|
142 | } |
254 | } |
143 | |
255 | |
144 | gpointer |
256 | gpointer g_try_realloc(gpointer mem, gsize n_bytes) |
145 | g_malloc0 (gsize n_bytes) |
|
|
146 | { |
257 | { |
147 | if (G_UNLIKELY (!g_mem_initialized)) |
258 | if (G_UNLIKELY(!g_mem_initialized)) |
148 | g_mem_init_nomessage(); |
259 | g_mem_init_nomessage(); |
149 | if (G_LIKELY (n_bytes)) |
260 | if (G_LIKELY(n_bytes)) |
150 | { |
261 | return glib_mem_vtable.try_realloc(mem, n_bytes); |
151 | gpointer mem; |
|
|
152 | |
262 | |
153 | mem = glib_mem_vtable.calloc (1, n_bytes); |
263 | if (mem) |
154 | if (mem) |
264 | glib_mem_vtable.free(mem); |
|
|
265 | |
|
|
266 | return NULL; |
|
|
267 | } |
|
|
268 | |
|
|
269 | static gpointer fallback_calloc(gsize n_blocks, gsize n_block_bytes) |
|
|
270 | { |
|
|
271 | gsize l = n_blocks * n_block_bytes; |
|
|
272 | gpointer mem = glib_mem_vtable.malloc(l); |
|
|
273 | |
|
|
274 | if (mem) |
|
|
275 | memset(mem, 0, l); |
|
|
276 | |
155 | return mem; |
277 | return mem; |
156 | |
|
|
157 | #if NOT_NEEDED_FOR_NAVIT |
|
|
158 | g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes", |
|
|
159 | G_STRLOC, n_bytes); |
|
|
160 | #endif /* NOT_NEEDED_FOR_NAVIT */ |
|
|
161 | } |
|
|
162 | |
|
|
163 | return NULL; |
|
|
164 | } |
|
|
165 | |
|
|
166 | gpointer |
|
|
167 | g_realloc (gpointer mem, |
|
|
168 | gsize n_bytes) |
|
|
169 | { |
|
|
170 | if (G_UNLIKELY (!g_mem_initialized)) |
|
|
171 | g_mem_init_nomessage(); |
|
|
172 | if (G_LIKELY (n_bytes)) |
|
|
173 | { |
|
|
174 | mem = glib_mem_vtable.realloc (mem, n_bytes); |
|
|
175 | if (mem) |
|
|
176 | return mem; |
|
|
177 | |
|
|
178 | #if NOT_NEEDED_FOR_NAVIT |
|
|
179 | g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes", |
|
|
180 | G_STRLOC, n_bytes); |
|
|
181 | #endif /* NOT_NEEDED_FOR_NAVIT */ |
|
|
182 | } |
|
|
183 | |
|
|
184 | if (mem) |
|
|
185 | glib_mem_vtable.free (mem); |
|
|
186 | |
|
|
187 | return NULL; |
|
|
188 | } |
|
|
189 | |
|
|
190 | void |
|
|
191 | g_free (gpointer mem) |
|
|
192 | { |
|
|
193 | if (G_UNLIKELY (!g_mem_initialized)) |
|
|
194 | g_mem_init_nomessage(); |
|
|
195 | if (G_LIKELY (mem)) |
|
|
196 | glib_mem_vtable.free (mem); |
|
|
197 | } |
|
|
198 | |
|
|
199 | gpointer |
|
|
200 | g_try_malloc (gsize n_bytes) |
|
|
201 | { |
|
|
202 | if (G_UNLIKELY (!g_mem_initialized)) |
|
|
203 | g_mem_init_nomessage(); |
|
|
204 | if (G_LIKELY (n_bytes)) |
|
|
205 | return glib_mem_vtable.try_malloc (n_bytes); |
|
|
206 | else |
|
|
207 | return NULL; |
|
|
208 | } |
|
|
209 | |
|
|
210 | gpointer |
|
|
211 | g_try_malloc0 (gsize n_bytes) |
|
|
212 | { |
|
|
213 | gpointer mem; |
|
|
214 | |
|
|
215 | mem = g_try_malloc (n_bytes); |
|
|
216 | |
|
|
217 | if (mem) |
|
|
218 | memset (mem, 0, n_bytes); |
|
|
219 | |
|
|
220 | return mem; |
|
|
221 | } |
|
|
222 | |
|
|
223 | gpointer |
|
|
224 | g_try_realloc (gpointer mem, |
|
|
225 | gsize n_bytes) |
|
|
226 | { |
|
|
227 | if (G_UNLIKELY (!g_mem_initialized)) |
|
|
228 | g_mem_init_nomessage(); |
|
|
229 | if (G_LIKELY (n_bytes)) |
|
|
230 | return glib_mem_vtable.try_realloc (mem, n_bytes); |
|
|
231 | |
|
|
232 | if (mem) |
|
|
233 | glib_mem_vtable.free (mem); |
|
|
234 | |
|
|
235 | return NULL; |
|
|
236 | } |
|
|
237 | |
|
|
238 | static gpointer |
|
|
239 | fallback_calloc (gsize n_blocks, |
|
|
240 | gsize n_block_bytes) |
|
|
241 | { |
|
|
242 | gsize l = n_blocks * n_block_bytes; |
|
|
243 | gpointer mem = glib_mem_vtable.malloc (l); |
|
|
244 | |
|
|
245 | if (mem) |
|
|
246 | memset (mem, 0, l); |
|
|
247 | |
|
|
248 | return mem; |
|
|
249 | } |
278 | } |
250 | |
279 | |
251 | static gboolean vtable_set = FALSE; |
280 | static gboolean vtable_set = FALSE; |
252 | |
281 | |
253 | /** |
282 | /** |
… | |
… | |
261 | * |
290 | * |
262 | * A different allocator can be set using g_mem_set_vtable(). |
291 | * A different allocator can be set using g_mem_set_vtable(). |
263 | * |
292 | * |
264 | * Return value: if %TRUE, malloc() and g_malloc() can be mixed. |
293 | * Return value: if %TRUE, malloc() and g_malloc() can be mixed. |
265 | **/ |
294 | **/ |
266 | gboolean |
|
|
267 | g_mem_is_system_malloc (void) |
295 | gboolean g_mem_is_system_malloc(void) |
268 | { |
296 | { |
269 | return !vtable_set; |
297 | return !vtable_set; |
270 | } |
298 | } |
271 | |
299 | |
272 | void |
|
|
273 | g_mem_set_vtable (GMemVTable *vtable) |
300 | void g_mem_set_vtable(GMemVTable *vtable) |
274 | { |
301 | { |
275 | if (!vtable_set) |
302 | if (!vtable_set) |
276 | { |
303 | { |
277 | if (vtable->malloc && vtable->realloc && vtable->free) |
304 | if (vtable->malloc && vtable->realloc && vtable->free) |
278 | { |
305 | { |
279 | glib_mem_vtable.malloc = vtable->malloc; |
306 | glib_mem_vtable.malloc = vtable->malloc; |
280 | glib_mem_vtable.realloc = vtable->realloc; |
307 | glib_mem_vtable.realloc = vtable->realloc; |
281 | glib_mem_vtable.free = vtable->free; |
308 | glib_mem_vtable.free = vtable->free; |
282 | glib_mem_vtable.calloc = vtable->calloc ? vtable->calloc : fallback_calloc; |
309 | glib_mem_vtable.calloc = vtable->calloc ? vtable->calloc : fallback_calloc; |
283 | glib_mem_vtable.try_malloc = vtable->try_malloc ? vtable->try_malloc : glib_mem_vtable.malloc; |
310 | glib_mem_vtable.try_malloc = vtable->try_malloc ? vtable->try_malloc : glib_mem_vtable.malloc; |
284 | glib_mem_vtable.try_realloc = vtable->try_realloc ? vtable->try_realloc : glib_mem_vtable.realloc; |
311 | glib_mem_vtable.try_realloc = vtable->try_realloc ? vtable->try_realloc : glib_mem_vtable.realloc; |
285 | vtable_set = TRUE; |
312 | vtable_set = TRUE; |
286 | } |
313 | } |
287 | #if NOT_NEEDED_FOR_NAVIT |
314 | //#if NOT_NEEDED_FOR_NAVIT |
288 | else |
315 | else |
|
|
316 | { |
289 | g_warning (G_STRLOC ": memory allocation vtable lacks one of malloc(), realloc() or free()"); |
317 | //g_warning (G_STRLOC ": memory allocation vtable lacks one of malloc(), realloc() or free()"); |
|
|
318 | } |
|
|
319 | //#endif /* NOT_NEEDED_FOR_NAVIT */ |
|
|
320 | } |
|
|
321 | //#if NOT_NEEDED_FOR_NAVIT |
|
|
322 | else |
|
|
323 | { |
|
|
324 | //g_warning (G_STRLOC ": memory allocation vtable can only be set once at startup"); |
|
|
325 | } |
290 | #endif /* NOT_NEEDED_FOR_NAVIT */ |
326 | //#endif /* NOT_NEEDED_FOR_NAVIT */ |
291 | } |
|
|
292 | #if NOT_NEEDED_FOR_NAVIT |
|
|
293 | else |
|
|
294 | g_warning (G_STRLOC ": memory allocation vtable can only be set once at startup"); |
|
|
295 | #endif /* NOT_NEEDED_FOR_NAVIT */ |
|
|
296 | } |
327 | } |
297 | |
|
|
298 | |
328 | |
299 | /* --- memory profiling and checking --- */ |
329 | /* --- memory profiling and checking --- */ |
|
|
330 | |
300 | #ifdef G_DISABLE_CHECKS |
331 | #ifdef G_DISABLE_CHECKS_X |
301 | GMemVTable *glib_mem_profiler_table = &glib_mem_vtable; |
332 | GMemVTable *glib_mem_profiler_table = &glib_mem_vtable; |
302 | void |
333 | void |
303 | g_mem_profile (void) |
334 | g_mem_profile (void) |
304 | { |
335 | { |
305 | } |
336 | } |
306 | #else /* !G_DISABLE_CHECKS */ |
337 | #else /* !G_DISABLE_CHECKS */ |
307 | typedef enum { |
338 | typedef enum |
308 | PROFILER_FREE = 0, |
339 | { |
309 | PROFILER_ALLOC = 1, |
340 | PROFILER_FREE = 0, PROFILER_ALLOC = 1, PROFILER_RELOC = 2, PROFILER_ZINIT = 4 |
310 | PROFILER_RELOC = 2, |
|
|
311 | PROFILER_ZINIT = 4 |
|
|
312 | } ProfilerJob; |
341 | } ProfilerJob; |
313 | static guint *profile_data = NULL; |
342 | static guint *profile_data = NULL; |
314 | static gsize profile_allocs = 0; |
343 | static gsize profile_allocs = 0; |
315 | static gsize profile_zinit = 0; |
344 | static gsize profile_zinit = 0; |
316 | static gsize profile_frees = 0; |
345 | static gsize profile_frees = 0; |
… | |
… | |
321 | static volatile gsize g_trap_malloc_size = 0; |
350 | static volatile gsize g_trap_malloc_size = 0; |
322 | #endif /* G_ENABLE_DEBUG */ |
351 | #endif /* G_ENABLE_DEBUG */ |
323 | |
352 | |
324 | #define PROFILE_TABLE(f1,f2,f3) ( ( ((f3) << 2) | ((f2) << 1) | (f1) ) * (MEM_PROFILE_TABLE_SIZE + 1)) |
353 | #define PROFILE_TABLE(f1,f2,f3) ( ( ((f3) << 2) | ((f2) << 1) | (f1) ) * (MEM_PROFILE_TABLE_SIZE + 1)) |
325 | |
354 | |
326 | static void |
355 | static void profiler_log(ProfilerJob job, gsize n_bytes, gboolean success) |
327 | profiler_log (ProfilerJob job, |
|
|
328 | gsize n_bytes, |
|
|
329 | gboolean success) |
|
|
330 | { |
356 | { |
331 | g_mutex_lock (gmem_profile_mutex); |
357 | g_mutex_lock(gmem_profile_mutex); |
332 | if (!profile_data) |
358 | if (!profile_data) |
333 | { |
359 | { |
334 | profile_data = standard_calloc ((MEM_PROFILE_TABLE_SIZE + 1) * 8, |
360 | profile_data = standard_calloc((MEM_PROFILE_TABLE_SIZE + 1) * 8, sizeof(profile_data[0])); |
335 | sizeof (profile_data[0])); |
|
|
336 | if (!profile_data) /* memory system kiddin' me, eh? */ |
361 | if (!profile_data) /* memory system kiddin' me, eh? */ |
337 | { |
362 | { |
338 | g_mutex_unlock (gmem_profile_mutex); |
363 | g_mutex_unlock(gmem_profile_mutex); |
339 | return; |
364 | return; |
340 | } |
365 | } |
341 | } |
366 | } |
342 | |
367 | |
343 | if (n_bytes < MEM_PROFILE_TABLE_SIZE) |
368 | if (n_bytes < MEM_PROFILE_TABLE_SIZE) |
|
|
369 | { |
344 | profile_data[n_bytes + PROFILE_TABLE ((job & PROFILER_ALLOC) != 0, |
370 | profile_data[n_bytes + PROFILE_TABLE ((job & PROFILER_ALLOC) != 0, |
345 | (job & PROFILER_RELOC) != 0, |
371 | (job & PROFILER_RELOC) != 0, |
346 | success != 0)] += 1; |
372 | success != 0)] += 1; |
347 | else |
373 | } |
|
|
374 | else |
|
|
375 | { |
348 | profile_data[MEM_PROFILE_TABLE_SIZE + PROFILE_TABLE ((job & PROFILER_ALLOC) != 0, |
376 | profile_data[MEM_PROFILE_TABLE_SIZE + PROFILE_TABLE ((job & PROFILER_ALLOC) != 0, |
349 | (job & PROFILER_RELOC) != 0, |
377 | (job & PROFILER_RELOC) != 0, |
350 | success != 0)] += 1; |
378 | success != 0)] += 1; |
|
|
379 | } |
|
|
380 | |
351 | if (success) |
381 | if (success) |
352 | { |
382 | { |
353 | if (job & PROFILER_ALLOC) |
383 | if (job & PROFILER_ALLOC) |
354 | { |
384 | { |
355 | profile_allocs += n_bytes; |
385 | profile_allocs += n_bytes; |
356 | if (job & PROFILER_ZINIT) |
386 | if (job & PROFILER_ZINIT) |
357 | profile_zinit += n_bytes; |
387 | profile_zinit += n_bytes; |
358 | } |
388 | } |
359 | else |
389 | else |
360 | profile_frees += n_bytes; |
390 | profile_frees += n_bytes; |
361 | } |
391 | } |
362 | g_mutex_unlock (gmem_profile_mutex); |
392 | g_mutex_unlock(gmem_profile_mutex); |
363 | } |
393 | } |
364 | |
394 | |
365 | static void |
395 | static void profile_print_locked(guint *local_data, gboolean success) |
366 | profile_print_locked (guint *local_data, |
|
|
367 | gboolean success) |
|
|
368 | { |
396 | { |
369 | gboolean need_header = TRUE; |
397 | gboolean need_header = TRUE; |
370 | guint i; |
398 | guint i; |
371 | |
399 | |
372 | for (i = 0; i <= MEM_PROFILE_TABLE_SIZE; i++) |
400 | for (i = 0; i <= MEM_PROFILE_TABLE_SIZE; i++) |
373 | { |
401 | { |
374 | glong t_malloc = local_data[i + PROFILE_TABLE (1, 0, success)]; |
402 | glong t_malloc = local_data[i + PROFILE_TABLE (1, 0, success)]; |
375 | glong t_realloc = local_data[i + PROFILE_TABLE (1, 1, success)]; |
403 | glong t_realloc = local_data[i + PROFILE_TABLE (1, 1, success)]; |
376 | glong t_free = local_data[i + PROFILE_TABLE (0, 0, success)]; |
404 | glong t_free = local_data[i + PROFILE_TABLE (0, 0, success)]; |
377 | glong t_refree = local_data[i + PROFILE_TABLE (0, 1, success)]; |
405 | glong t_refree = local_data[i + PROFILE_TABLE (0, 1, success)]; |
378 | |
406 | |
379 | if (!t_malloc && !t_realloc && !t_free && !t_refree) |
407 | if (!t_malloc && !t_realloc && !t_free && !t_refree) |
|
|
408 | { |
380 | continue; |
409 | continue; |
|
|
410 | } |
381 | else if (need_header) |
411 | else if (need_header) |
382 | { |
412 | { |
383 | need_header = FALSE; |
413 | need_header = FALSE; |
|
|
414 | #ifdef HAVE_API_ANDROID |
384 | g_print (" blocks of | allocated | freed | allocated | freed | n_bytes \n"); |
415 | dbg(0, " blocks of | allocated | freed | allocated | freed | n_bytes \n"); |
385 | g_print (" n_bytes | n_times by | n_times by | n_times by | n_times by | remaining \n"); |
416 | dbg(0, " n_bytes | n_times by | n_times by | n_times by | n_times by | remaining \n"); |
386 | g_print (" | malloc() | free() | realloc() | realloc() | \n"); |
417 | dbg(0, " | malloc() | free() | realloc() | realloc() | \n"); |
387 | g_print ("===========|============|============|============|============|===========\n"); |
418 | dbg(0, "===========|============|============|============|============|===========\n"); |
|
|
419 | #endif |
388 | } |
420 | } |
|
|
421 | |
389 | if (i < MEM_PROFILE_TABLE_SIZE) |
422 | if (i < MEM_PROFILE_TABLE_SIZE) |
|
|
423 | { |
|
|
424 | #ifdef HAVE_API_ANDROID |
390 | g_print ("%10u | %10ld | %10ld | %10ld | %10ld |%+11ld\n", |
425 | dbg(0, "%10u | %10ld | %10ld | %10ld | %10ld |%+11ld\n", |
391 | i, t_malloc, t_free, t_realloc, t_refree, |
426 | i, t_malloc, t_free, t_realloc, t_refree, |
392 | (t_malloc - t_free + t_realloc - t_refree) * i); |
427 | (t_malloc - t_free + t_realloc - t_refree) * i); |
|
|
428 | #endif |
|
|
429 | } |
393 | else if (i >= MEM_PROFILE_TABLE_SIZE) |
430 | else if (i >= MEM_PROFILE_TABLE_SIZE) |
|
|
431 | { |
|
|
432 | #ifdef HAVE_API_ANDROID |
394 | g_print (" >%6u | %10ld | %10ld | %10ld | %10ld | ***\n", |
433 | dbg(0, " >%6u | %10ld | %10ld | %10ld | %10ld | ***\n", |
395 | i, t_malloc, t_free, t_realloc, t_refree); |
434 | i, t_malloc, t_free, t_realloc, t_refree); |
396 | } |
435 | #endif |
|
|
436 | } |
|
|
437 | } |
|
|
438 | |
397 | if (need_header) |
439 | if (need_header) |
398 | g_print (" --- none ---\n"); |
440 | { |
|
|
441 | #ifdef HAVE_API_ANDROID |
|
|
442 | dbg(0, " --- none ---\n"); |
|
|
443 | #endif |
|
|
444 | } |
399 | } |
445 | } |
400 | |
446 | |
401 | void |
|
|
402 | g_mem_profile (void) |
447 | void g_mem_profile(void) |
403 | { |
448 | { |
404 | guint local_data[(MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof (profile_data[0])]; |
449 | guint local_data[(MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof(profile_data[0])]; |
405 | gsize local_allocs; |
450 | gsize local_allocs; |
406 | gsize local_zinit; |
451 | gsize local_zinit; |
407 | gsize local_frees; |
452 | gsize local_frees; |
408 | |
453 | |
409 | if (G_UNLIKELY (!g_mem_initialized)) |
454 | if (G_UNLIKELY(!g_mem_initialized)) |
410 | g_mem_init_nomessage(); |
455 | g_mem_init_nomessage(); |
411 | |
456 | |
412 | g_mutex_lock (gmem_profile_mutex); |
457 | g_mutex_lock(gmem_profile_mutex); |
413 | |
458 | |
414 | local_allocs = profile_allocs; |
459 | local_allocs = profile_allocs; |
415 | local_zinit = profile_zinit; |
460 | local_zinit = profile_zinit; |
416 | local_frees = profile_frees; |
461 | local_frees = profile_frees; |
417 | |
462 | |
418 | if (!profile_data) |
463 | if (!profile_data) |
419 | { |
464 | { |
420 | g_mutex_unlock (gmem_profile_mutex); |
465 | g_mutex_unlock(gmem_profile_mutex); |
421 | return; |
466 | return; |
422 | } |
467 | } |
423 | |
468 | |
424 | memcpy (local_data, profile_data, |
|
|
425 | (MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof (profile_data[0])); |
469 | memcpy(local_data, profile_data, (MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof(profile_data[0])); |
426 | |
470 | |
427 | g_mutex_unlock (gmem_profile_mutex); |
471 | g_mutex_unlock(gmem_profile_mutex); |
428 | |
472 | |
|
|
473 | // |
|
|
474 | #ifdef HAVE_API_ANDROID |
429 | g_print ("GLib Memory statistics (successful operations):\n"); |
475 | // dbg(0, "GLib Memory statistics (successful operations):\n"); |
|
|
476 | #endif |
|
|
477 | // |
|
|
478 | // dont print the table for successful memory stats |
430 | profile_print_locked (local_data, TRUE); |
479 | // profile_print_locked (local_data, TRUE); |
|
|
480 | |
|
|
481 | #ifdef HAVE_API_ANDROID |
431 | g_print ("GLib Memory statistics (failing operations):\n"); |
482 | dbg(0, "GLib Memory statistics (failing operations):\n"); |
|
|
483 | #endif |
432 | profile_print_locked (local_data, FALSE); |
484 | profile_print_locked(local_data, FALSE); |
|
|
485 | #ifdef HAVE_API_ANDROID |
433 | g_print ("Total bytes: allocated=%"G_GSIZE_FORMAT", " |
486 | dbg(0, "Total bytes: allocated=%"G_GSIZE_FORMAT", " |
434 | "zero-initialized=%"G_GSIZE_FORMAT" (%.2f%%), " |
487 | "zero-initialized=%"G_GSIZE_FORMAT" (%.2f%%), " |
435 | "freed=%"G_GSIZE_FORMAT" (%.2f%%), " |
488 | "freed=%"G_GSIZE_FORMAT" (%.2f%%), " |
436 | "remaining=%"G_GSIZE_FORMAT"\n", |
489 | "remaining=%"G_GSIZE_FORMAT"\n", |
437 | local_allocs, |
490 | local_allocs, |
438 | local_zinit, |
491 | local_zinit, |
439 | ((gdouble) local_zinit) / local_allocs * 100.0, |
492 | ((gdouble) local_zinit) / local_allocs * 100.0, |
440 | local_frees, |
493 | local_frees, |
441 | ((gdouble) local_frees) / local_allocs * 100.0, |
494 | ((gdouble) local_frees) / local_allocs * 100.0, |
442 | local_allocs - local_frees); |
495 | local_allocs - local_frees); |
|
|
496 | #endif |
443 | } |
497 | } |
444 | |
498 | |
445 | static gpointer |
|
|
446 | profiler_try_malloc (gsize n_bytes) |
499 | static gpointer profiler_try_malloc(gsize n_bytes) |
447 | { |
500 | { |
448 | gsize *p; |
501 | gsize *p; |
449 | |
502 | |
450 | #ifdef G_ENABLE_DEBUG |
503 | #ifdef G_ENABLE_DEBUG |
451 | if (g_trap_malloc_size == n_bytes) |
504 | if (g_trap_malloc_size == n_bytes) |
452 | G_BREAKPOINT (); |
|
|
453 | #endif /* G_ENABLE_DEBUG */ |
|
|
454 | |
|
|
455 | p = standard_malloc (sizeof (gsize) * 2 + n_bytes); |
|
|
456 | |
|
|
457 | if (p) |
|
|
458 | { |
|
|
459 | p[0] = 0; /* free count */ |
|
|
460 | p[1] = n_bytes; /* length */ |
|
|
461 | profiler_log (PROFILER_ALLOC, n_bytes, TRUE); |
|
|
462 | p += 2; |
|
|
463 | } |
|
|
464 | else |
|
|
465 | profiler_log (PROFILER_ALLOC, n_bytes, FALSE); |
|
|
466 | |
|
|
467 | return p; |
|
|
468 | } |
|
|
469 | |
|
|
470 | static gpointer |
|
|
471 | profiler_malloc (gsize n_bytes) |
|
|
472 | { |
|
|
473 | gpointer mem = profiler_try_malloc (n_bytes); |
|
|
474 | |
|
|
475 | if (!mem) |
|
|
476 | g_mem_profile (); |
|
|
477 | |
|
|
478 | return mem; |
|
|
479 | } |
|
|
480 | |
|
|
481 | static gpointer |
|
|
482 | profiler_calloc (gsize n_blocks, |
|
|
483 | gsize n_block_bytes) |
|
|
484 | { |
|
|
485 | gsize l = n_blocks * n_block_bytes; |
|
|
486 | gsize *p; |
|
|
487 | |
|
|
488 | #ifdef G_ENABLE_DEBUG |
|
|
489 | if (g_trap_malloc_size == l) |
|
|
490 | G_BREAKPOINT (); |
|
|
491 | #endif /* G_ENABLE_DEBUG */ |
|
|
492 | |
|
|
493 | p = standard_calloc (1, sizeof (gsize) * 2 + l); |
|
|
494 | |
|
|
495 | if (p) |
|
|
496 | { |
|
|
497 | p[0] = 0; /* free count */ |
|
|
498 | p[1] = l; /* length */ |
|
|
499 | profiler_log (PROFILER_ALLOC | PROFILER_ZINIT, l, TRUE); |
|
|
500 | p += 2; |
|
|
501 | } |
|
|
502 | else |
|
|
503 | { |
|
|
504 | profiler_log (PROFILER_ALLOC | PROFILER_ZINIT, l, FALSE); |
|
|
505 | g_mem_profile (); |
|
|
506 | } |
|
|
507 | |
|
|
508 | return p; |
|
|
509 | } |
|
|
510 | |
|
|
511 | static void |
|
|
512 | profiler_free (gpointer mem) |
|
|
513 | { |
|
|
514 | gsize *p = mem; |
|
|
515 | |
|
|
516 | p -= 2; |
|
|
517 | if (p[0]) /* free count */ |
|
|
518 | { |
|
|
519 | g_warning ("free(%p): memory has been freed %"G_GSIZE_FORMAT" times already", |
|
|
520 | p + 2, p[0]); |
|
|
521 | profiler_log (PROFILER_FREE, |
|
|
522 | p[1], /* length */ |
|
|
523 | FALSE); |
|
|
524 | } |
|
|
525 | else |
|
|
526 | { |
|
|
527 | #ifdef G_ENABLE_DEBUG |
|
|
528 | if (g_trap_free_size == p[1]) |
|
|
529 | G_BREAKPOINT (); |
505 | G_BREAKPOINT (); |
530 | #endif /* G_ENABLE_DEBUG */ |
506 | #endif /* G_ENABLE_DEBUG */ |
531 | |
507 | |
532 | profiler_log (PROFILER_FREE, |
508 | p = standard_malloc(sizeof(gsize) * 2 + n_bytes); |
533 | p[1], /* length */ |
|
|
534 | TRUE); |
|
|
535 | memset (p + 2, 0xaa, p[1]); |
|
|
536 | |
509 | |
537 | /* for all those that miss standard_free (p); in this place, yes, |
510 | if (p) |
538 | * we do leak all memory when profiling, and that is intentional |
511 | { |
539 | * to catch double frees. patch submissions are futile. |
512 | p[0] = 0; /* free count */ |
540 | */ |
513 | p[1] = n_bytes; /* length */ |
541 | } |
514 | profiler_log(PROFILER_ALLOC, n_bytes, TRUE); |
542 | p[0] += 1; |
515 | p += 2; |
543 | } |
516 | } |
|
|
517 | else |
|
|
518 | profiler_log(PROFILER_ALLOC, n_bytes, FALSE); |
544 | |
519 | |
545 | static gpointer |
520 | return p; |
546 | profiler_try_realloc (gpointer mem, |
521 | } |
547 | gsize n_bytes) |
|
|
548 | { |
|
|
549 | gsize *p = mem; |
|
|
550 | |
522 | |
551 | p -= 2; |
523 | static gpointer profiler_malloc(gsize n_bytes) |
|
|
524 | { |
|
|
525 | gpointer mem = profiler_try_malloc(n_bytes); |
|
|
526 | |
|
|
527 | if (!mem) |
|
|
528 | g_mem_profile(); |
|
|
529 | |
|
|
530 | return mem; |
|
|
531 | } |
|
|
532 | |
|
|
533 | static gpointer profiler_calloc(gsize n_blocks, gsize n_block_bytes) |
|
|
534 | { |
|
|
535 | gsize l = n_blocks * n_block_bytes; |
|
|
536 | gsize *p; |
552 | |
537 | |
553 | #ifdef G_ENABLE_DEBUG |
538 | #ifdef G_ENABLE_DEBUG |
554 | if (g_trap_realloc_size == n_bytes) |
539 | if (g_trap_malloc_size == l) |
555 | G_BREAKPOINT (); |
540 | G_BREAKPOINT (); |
556 | #endif /* G_ENABLE_DEBUG */ |
541 | #endif /* G_ENABLE_DEBUG */ |
557 | |
542 | |
|
|
543 | p = standard_calloc(1, sizeof(gsize) * 2 + l); |
|
|
544 | |
|
|
545 | if (p) |
|
|
546 | { |
|
|
547 | p[0] = 0; /* free count */ |
|
|
548 | p[1] = l; /* length */ |
|
|
549 | profiler_log(PROFILER_ALLOC | PROFILER_ZINIT, l, TRUE); |
|
|
550 | p += 2; |
|
|
551 | } |
|
|
552 | else |
|
|
553 | { |
|
|
554 | profiler_log(PROFILER_ALLOC | PROFILER_ZINIT, l, FALSE); |
|
|
555 | g_mem_profile(); |
|
|
556 | } |
|
|
557 | |
|
|
558 | return p; |
|
|
559 | } |
|
|
560 | |
|
|
561 | static void profiler_free(gpointer mem) |
|
|
562 | { |
|
|
563 | gsize *p = mem; |
|
|
564 | |
|
|
565 | p -= 2; |
|
|
566 | if (p[0]) /* free count */ |
|
|
567 | { |
|
|
568 | #ifdef HAVE_API_ANDROID |
|
|
569 | dbg (0, "free(%p): memory has been freed %"G_GSIZE_FORMAT" times already", |
|
|
570 | p + 2, p[0]); |
|
|
571 | #endif |
|
|
572 | profiler_log(PROFILER_FREE, p[1], /* length */ |
|
|
573 | FALSE); |
|
|
574 | } |
|
|
575 | else |
|
|
576 | { |
|
|
577 | #ifdef G_ENABLE_DEBUG |
|
|
578 | if (g_trap_free_size == p[1]) |
|
|
579 | G_BREAKPOINT (); |
|
|
580 | #endif /* G_ENABLE_DEBUG */ |
|
|
581 | |
|
|
582 | profiler_log(PROFILER_FREE, p[1], /* length */ |
|
|
583 | TRUE); |
|
|
584 | memset(p + 2, 0xaa, p[1]); |
|
|
585 | |
|
|
586 | #ifdef DEBUG_GLIB_REALLY_FREE |
|
|
587 | /* for all those that miss standard_free (p); in this place, yes, |
|
|
588 | * we do leak all memory when profiling, and that is intentional |
|
|
589 | * to catch double frees. patch submissions are futile. |
|
|
590 | */ |
|
|
591 | // update: we want to free the mem! (Zoff) |
|
|
592 | standard_free(p); |
|
|
593 | #endif |
|
|
594 | |
|
|
595 | } |
|
|
596 | |
|
|
597 | #ifndef DEBUG_GLIB_REALLY_FREE |
|
|
598 | // update: we want to free the mem! (Zoff) |
|
|
599 | p[0] += 1; |
|
|
600 | #endif |
|
|
601 | |
|
|
602 | } |
|
|
603 | |
|
|
604 | static gpointer profiler_try_realloc(gpointer mem, gsize n_bytes) |
|
|
605 | { |
|
|
606 | gsize *p = mem; |
|
|
607 | |
|
|
608 | p -= 2; |
|
|
609 | |
|
|
610 | #ifdef G_ENABLE_DEBUG |
|
|
611 | if (g_trap_realloc_size == n_bytes) |
|
|
612 | G_BREAKPOINT (); |
|
|
613 | #endif /* G_ENABLE_DEBUG */ |
|
|
614 | |
558 | if (mem && p[0]) /* free count */ |
615 | if (mem && p[0]) /* free count */ |
559 | { |
616 | { |
|
|
617 | #ifdef HAVE_API_ANDROID |
560 | g_warning ("realloc(%p, %"G_GSIZE_FORMAT"): " |
618 | dbg(0, "realloc(%p, %"G_GSIZE_FORMAT"): " |
561 | "memory has been freed %"G_GSIZE_FORMAT" times already", |
619 | "memory has been freed %"G_GSIZE_FORMAT" times already", |
562 | p + 2, (gsize) n_bytes, p[0]); |
620 | p + 2, (gsize) n_bytes, p[0]); |
563 | profiler_log (PROFILER_ALLOC | PROFILER_RELOC, n_bytes, FALSE); |
621 | #endif |
564 | |
|
|
565 | return NULL; |
|
|
566 | } |
|
|
567 | else |
|
|
568 | { |
|
|
569 | p = standard_realloc (mem ? p : NULL, sizeof (gsize) * 2 + n_bytes); |
|
|
570 | |
|
|
571 | if (p) |
|
|
572 | { |
|
|
573 | if (mem) |
|
|
574 | profiler_log (PROFILER_FREE | PROFILER_RELOC, p[1], TRUE); |
|
|
575 | p[0] = 0; |
|
|
576 | p[1] = n_bytes; |
|
|
577 | profiler_log (PROFILER_ALLOC | PROFILER_RELOC, p[1], TRUE); |
|
|
578 | p += 2; |
|
|
579 | } |
|
|
580 | else |
|
|
581 | profiler_log (PROFILER_ALLOC | PROFILER_RELOC, n_bytes, FALSE); |
622 | profiler_log(PROFILER_ALLOC | PROFILER_RELOC, n_bytes, FALSE); |
582 | |
623 | |
583 | return p; |
624 | return NULL; |
584 | } |
625 | } |
585 | } |
626 | else |
|
|
627 | { |
|
|
628 | p = standard_realloc(mem ? p : NULL, sizeof(gsize) * 2 + n_bytes); |
586 | |
629 | |
587 | static gpointer |
630 | if (p) |
588 | profiler_realloc (gpointer mem, |
631 | { |
589 | gsize n_bytes) |
632 | if (mem) |
|
|
633 | profiler_log(PROFILER_FREE | PROFILER_RELOC, p[1], TRUE); |
|
|
634 | p[0] = 0; |
|
|
635 | p[1] = n_bytes; |
|
|
636 | profiler_log(PROFILER_ALLOC | PROFILER_RELOC, p[1], TRUE); |
|
|
637 | p += 2; |
|
|
638 | } |
|
|
639 | else |
|
|
640 | profiler_log(PROFILER_ALLOC | PROFILER_RELOC, n_bytes, FALSE); |
|
|
641 | |
|
|
642 | return p; |
|
|
643 | } |
|
|
644 | } |
|
|
645 | |
|
|
646 | static gpointer profiler_realloc(gpointer mem, gsize n_bytes) |
590 | { |
647 | { |
591 | mem = profiler_try_realloc (mem, n_bytes); |
648 | mem = profiler_try_realloc(mem, n_bytes); |
592 | |
649 | |
593 | if (!mem) |
650 | if (!mem) |
594 | g_mem_profile (); |
651 | g_mem_profile(); |
595 | |
652 | |
596 | return mem; |
653 | return mem; |
597 | } |
654 | } |
598 | |
655 | |
599 | static GMemVTable profiler_table = { |
656 | static GMemVTable profiler_table = { profiler_malloc, profiler_realloc, profiler_free, profiler_calloc, profiler_try_malloc, profiler_try_realloc, }; |
600 | profiler_malloc, |
|
|
601 | profiler_realloc, |
|
|
602 | profiler_free, |
|
|
603 | profiler_calloc, |
|
|
604 | profiler_try_malloc, |
|
|
605 | profiler_try_realloc, |
|
|
606 | }; |
|
|
607 | GMemVTable *glib_mem_profiler_table = &profiler_table; |
657 | GMemVTable *glib_mem_profiler_table = &profiler_table; |
608 | |
658 | |
609 | #endif /* !G_DISABLE_CHECKS */ |
659 | #endif /* !G_DISABLE_CHECKS */ |
610 | |
660 | |
611 | /* --- MemChunks --- */ |
661 | /* --- MemChunks --- */ |
612 | #ifndef G_ALLOC_AND_FREE |
662 | #ifndef G_ALLOC_AND_FREE |
613 | typedef struct _GAllocator GAllocator; |
663 | typedef struct _GAllocator GAllocator; |
614 | typedef struct _GMemChunk GMemChunk; |
664 | typedef struct _GMemChunk GMemChunk; |
615 | #define G_ALLOC_ONLY 1 |
665 | #define G_ALLOC_ONLY 1 |
616 | #define G_ALLOC_AND_FREE 2 |
666 | #define G_ALLOC_AND_FREE 2 |
617 | #endif |
667 | #endif |
618 | |
668 | |
619 | struct _GMemChunk { |
669 | struct _GMemChunk |
|
|
670 | { |
620 | guint alloc_size; /* the size of an atom */ |
671 | guint alloc_size; /* the size of an atom */ |
621 | }; |
672 | }; |
622 | |
673 | |
623 | GMemChunk* |
674 | GMemChunk* |
624 | g_mem_chunk_new (const gchar *name, |
675 | g_mem_chunk_new(const gchar *name, gint atom_size, gsize area_size, gint type) |
625 | gint atom_size, |
|
|
626 | gsize area_size, |
|
|
627 | gint type) |
|
|
628 | { |
676 | { |
629 | GMemChunk *mem_chunk; |
677 | GMemChunk *mem_chunk; |
630 | g_return_val_if_fail (atom_size > 0, NULL); |
678 | g_return_val_if_fail(atom_size > 0, NULL); |
631 | |
679 | |
632 | mem_chunk = g_slice_new (GMemChunk); |
680 | mem_chunk = g_slice_new(GMemChunk); |
633 | mem_chunk->alloc_size = atom_size; |
681 | mem_chunk->alloc_size = atom_size; |
634 | return mem_chunk; |
682 | return mem_chunk; |
635 | } |
683 | } |
636 | |
684 | |
637 | void |
|
|
638 | g_mem_chunk_destroy (GMemChunk *mem_chunk) |
685 | void g_mem_chunk_destroy(GMemChunk *mem_chunk) |
639 | { |
686 | { |
640 | g_return_if_fail (mem_chunk != NULL); |
687 | g_return_if_fail(mem_chunk != NULL); |
641 | |
688 | |
642 | g_slice_free (GMemChunk, mem_chunk); |
689 | g_slice_free(GMemChunk, mem_chunk); |
643 | } |
690 | } |
644 | |
691 | |
645 | gpointer |
|
|
646 | g_mem_chunk_alloc (GMemChunk *mem_chunk) |
692 | gpointer g_mem_chunk_alloc(GMemChunk *mem_chunk) |
647 | { |
693 | { |
648 | g_return_val_if_fail (mem_chunk != NULL, NULL); |
694 | g_return_val_if_fail(mem_chunk != NULL, NULL); |
649 | |
695 | |
650 | return g_slice_alloc (mem_chunk->alloc_size); |
696 | return g_slice_alloc(mem_chunk->alloc_size); |
651 | } |
697 | } |
652 | |
698 | |
653 | gpointer |
|
|
654 | g_mem_chunk_alloc0 (GMemChunk *mem_chunk) |
699 | gpointer g_mem_chunk_alloc0(GMemChunk *mem_chunk) |
655 | { |
700 | { |
656 | g_return_val_if_fail (mem_chunk != NULL, NULL); |
701 | g_return_val_if_fail(mem_chunk != NULL, NULL); |
657 | |
702 | |
658 | return g_slice_alloc0 (mem_chunk->alloc_size); |
703 | return g_slice_alloc0(mem_chunk->alloc_size); |
659 | } |
704 | } |
660 | |
705 | |
661 | void |
|
|
662 | g_mem_chunk_free (GMemChunk *mem_chunk, |
706 | void g_mem_chunk_free(GMemChunk *mem_chunk, gpointer mem) |
663 | gpointer mem) |
|
|
664 | { |
707 | { |
665 | g_return_if_fail (mem_chunk != NULL); |
708 | g_return_if_fail(mem_chunk != NULL); |
666 | |
709 | |
667 | g_slice_free1 (mem_chunk->alloc_size, mem); |
710 | g_slice_free1(mem_chunk->alloc_size, mem); |
668 | } |
711 | } |
669 | |
712 | |
670 | void g_mem_chunk_clean (GMemChunk *mem_chunk) {} |
713 | void g_mem_chunk_clean(GMemChunk *mem_chunk) |
|
|
714 | { |
|
|
715 | } |
671 | void g_mem_chunk_reset (GMemChunk *mem_chunk) {} |
716 | void g_mem_chunk_reset(GMemChunk *mem_chunk) |
|
|
717 | { |
|
|
718 | } |
672 | void g_mem_chunk_print (GMemChunk *mem_chunk) {} |
719 | void g_mem_chunk_print(GMemChunk *mem_chunk) |
|
|
720 | { |
|
|
721 | } |
673 | void g_mem_chunk_info (void) {} |
722 | void g_mem_chunk_info(void) |
|
|
723 | { |
|
|
724 | } |
674 | void g_blow_chunks (void) {} |
725 | void g_blow_chunks(void) |
|
|
726 | { |
|
|
727 | } |
675 | |
728 | |
676 | GAllocator* |
729 | GAllocator* |
677 | g_allocator_new (const gchar *name, |
730 | g_allocator_new(const gchar *name, guint n_preallocs) |
678 | guint n_preallocs) |
|
|
679 | { |
731 | { |
680 | static struct _GAllocator { |
732 | static struct _GAllocator |
681 | gchar *name; |
733 | { |
|
|
734 | gchar *name; |
682 | guint16 n_preallocs; |
735 | guint16 n_preallocs; |
683 | guint is_unused : 1; |
736 | guint is_unused :1; |
684 | guint type : 4; |
737 | guint type :4; |
685 | GAllocator *last; |
738 | GAllocator *last; |
686 | GMemChunk *mem_chunk; |
739 | GMemChunk *mem_chunk; |
687 | gpointer free_list; |
740 | gpointer free_list; |
688 | } dummy = { |
|
|
689 | "GAllocator is deprecated", 1, TRUE, 0, NULL, NULL, NULL, |
741 | } dummy = { "GAllocator is deprecated", 1, TRUE, 0, NULL, NULL, NULL, }; |
690 | }; |
|
|
691 | /* some (broken) GAllocator uses depend on non-NULL allocators */ |
742 | /* some (broken) GAllocator uses depend on non-NULL allocators */ |
692 | return (void*) &dummy; |
743 | return (void*) &dummy; |
693 | } |
744 | } |
694 | |
745 | |
695 | void |
|
|
696 | g_allocator_free (GAllocator *allocator) |
746 | void g_allocator_free(GAllocator *allocator) |
697 | { |
747 | { |
698 | } |
748 | } |
699 | |
749 | |
700 | #ifdef ENABLE_GC_FRIENDLY_DEFAULT |
750 | #ifdef ENABLE_GC_FRIENDLY_DEFAULT |
701 | gboolean g_mem_gc_friendly = TRUE; |
751 | gboolean g_mem_gc_friendly = TRUE; |
702 | #else |
752 | #else |
703 | gboolean g_mem_gc_friendly = FALSE; |
753 | gboolean g_mem_gc_friendly = FALSE; |
704 | #endif |
754 | #endif |
705 | |
755 | |
706 | static void |
|
|
707 | g_mem_init_nomessage (void) |
756 | static void g_mem_init_nomessage(void) |
708 | { |
757 | { |
709 | #if NOT_NEEDED_FOR_NAVIT |
758 | #if NOT_NEEDED_FOR_NAVIT |
710 | gchar buffer[1024]; |
759 | gchar buffer[1024]; |
711 | const gchar *val; |
760 | const gchar *val; |
712 | const GDebugKey keys[] = { |
761 | const GDebugKey keys[] = |
|
|
762 | { |
713 | { "gc-friendly", 1 }, |
763 | { "gc-friendly", 1}, |
714 | }; |
764 | }; |
715 | gint flags; |
765 | gint flags; |
716 | if (g_mem_initialized) |
766 | if (g_mem_initialized) |
717 | return; |
767 | return; |
718 | /* don't use g_malloc/g_message here */ |
768 | /* don't use g_malloc/g_message here */ |
719 | val = _g_getenv_nomalloc ("G_DEBUG", buffer); |
769 | val = _g_getenv_nomalloc ("G_DEBUG", buffer); |
720 | flags = !val ? 0 : g_parse_debug_string (val, keys, G_N_ELEMENTS (keys)); |
770 | flags = !val ? 0 : g_parse_debug_string (val, keys, G_N_ELEMENTS (keys)); |
721 | if (flags & 1) /* gc-friendly */ |
771 | if (flags & 1) /* gc-friendly */ |
722 | { |
772 | { |
723 | g_mem_gc_friendly = TRUE; |
773 | g_mem_gc_friendly = TRUE; |
724 | } |
774 | } |
725 | #endif /* NOT_NEEDED_FOR_NAVIT */ |
775 | #endif /* NOT_NEEDED_FOR_NAVIT */ |
726 | g_mem_initialized = TRUE; |
776 | g_mem_initialized = TRUE; |
727 | } |
777 | } |
728 | |
778 | |
729 | void |
|
|
730 | _g_mem_thread_init_noprivate_nomessage (void) |
779 | void _g_mem_thread_init_noprivate_nomessage(void) |
731 | { |
780 | { |
732 | /* we may only create mutexes here, locking/ |
781 | /* we may only create mutexes here, locking/ |
733 | * unlocking a mutex does not yet work. |
782 | * unlocking a mutex does not yet work. |
734 | */ |
783 | */ |
735 | g_mem_init_nomessage(); |
784 | g_mem_init_nomessage(); |
736 | #ifndef G_DISABLE_CHECKS |
785 | #ifndef G_DISABLE_CHECKS_X |
737 | gmem_profile_mutex = g_mutex_new (); |
786 | gmem_profile_mutex = g_mutex_new(); |
738 | #endif |
787 | #endif |
739 | } |
788 | } |
740 | |
789 | |
741 | #define __G_MEM_C__ |
790 | #define __G_MEM_C__ |
742 | #include "galiasdef.c" |
791 | #include "galiasdef.c" |