/[zanavi_public1]/navit/navit/support/glib/gmem.c
ZANavi

Diff of /navit/navit/support/glib/gmem.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 30 Revision 31
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 --- */
54static gboolean g_mem_initialized = FALSE; 74static gboolean g_mem_initialized = FALSE;
55static void g_mem_init_nomessage (void); 75static 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
60static gpointer 79static gpointer standard_realloc(gpointer mem, gsize n_bytes)
61standard_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 */
81static gpointer
82standard_malloc (gsize n_bytes) 98static 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
87static gpointer 103static gpointer
88standard_realloc (gpointer mem, 104standard_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 */
94static void
95standard_free (gpointer mem) 110static void standard_free(gpointer mem)
96{ 111{
97 free (mem); 112 free(mem);
98} 113}
99static gpointer 114static gpointer standard_calloc(gsize n_blocks, gsize n_bytes)
100standard_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 --- */
111static GMemVTable glib_mem_vtable = { 123static 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 --- */
122gpointer
123g_malloc (gsize n_bytes) 126gpointer 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
147gpointer 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
168gpointer 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
190void 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
210void 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
218void
219g_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
234gpointer 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
244gpointer 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
144gpointer 256gpointer g_try_realloc(gpointer mem, gsize n_bytes)
145g_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
269static 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
166gpointer
167g_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
190void
191g_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
199gpointer
200g_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
210gpointer
211g_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
223gpointer
224g_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
238static gpointer
239fallback_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
251static gboolean vtable_set = FALSE; 280static 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 **/
266gboolean
267g_mem_is_system_malloc (void) 295gboolean g_mem_is_system_malloc(void)
268{ 296{
269 return !vtable_set; 297 return !vtable_set;
270} 298}
271 299
272void
273g_mem_set_vtable (GMemVTable *vtable) 300void 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
301GMemVTable *glib_mem_profiler_table = &glib_mem_vtable; 332GMemVTable *glib_mem_profiler_table = &glib_mem_vtable;
302void 333void
303g_mem_profile (void) 334g_mem_profile (void)
304{ 335{
305} 336}
306#else /* !G_DISABLE_CHECKS */ 337#else /* !G_DISABLE_CHECKS */
307typedef enum { 338typedef 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;
313static guint *profile_data = NULL; 342static guint *profile_data = NULL;
314static gsize profile_allocs = 0; 343static gsize profile_allocs = 0;
315static gsize profile_zinit = 0; 344static gsize profile_zinit = 0;
316static gsize profile_frees = 0; 345static gsize profile_frees = 0;
321static volatile gsize g_trap_malloc_size = 0; 350static 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
326static void 355static void profiler_log(ProfilerJob job, gsize n_bytes, gboolean success)
327profiler_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
365static void 395static void profile_print_locked(guint *local_data, gboolean success)
366profile_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
401void
402g_mem_profile (void) 447void 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
445static gpointer
446profiler_try_malloc (gsize n_bytes) 499static 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
470static gpointer
471profiler_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
481static gpointer
482profiler_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
511static void
512profiler_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
545static gpointer 520 return p;
546profiler_try_realloc (gpointer mem, 521}
547 gsize n_bytes)
548{
549 gsize *p = mem;
550 522
551 p -= 2; 523static 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
533static 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
561static 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
604static 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
587static gpointer 630 if (p)
588profiler_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
646static 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
599static GMemVTable profiler_table = { 656static 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};
607GMemVTable *glib_mem_profiler_table = &profiler_table; 657GMemVTable *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
613typedef struct _GAllocator GAllocator; 663typedef struct _GAllocator GAllocator;
614typedef struct _GMemChunk GMemChunk; 664typedef 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
619struct _GMemChunk { 669struct _GMemChunk
670{
620 guint alloc_size; /* the size of an atom */ 671 guint alloc_size; /* the size of an atom */
621}; 672};
622 673
623GMemChunk* 674GMemChunk*
624g_mem_chunk_new (const gchar *name, 675g_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
637void
638g_mem_chunk_destroy (GMemChunk *mem_chunk) 685void 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
645gpointer
646g_mem_chunk_alloc (GMemChunk *mem_chunk) 692gpointer 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
653gpointer
654g_mem_chunk_alloc0 (GMemChunk *mem_chunk) 699gpointer 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
661void
662g_mem_chunk_free (GMemChunk *mem_chunk, 706void 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
670void g_mem_chunk_clean (GMemChunk *mem_chunk) {} 713void g_mem_chunk_clean(GMemChunk *mem_chunk)
714{
715}
671void g_mem_chunk_reset (GMemChunk *mem_chunk) {} 716void g_mem_chunk_reset(GMemChunk *mem_chunk)
717{
718}
672void g_mem_chunk_print (GMemChunk *mem_chunk) {} 719void g_mem_chunk_print(GMemChunk *mem_chunk)
720{
721}
673void g_mem_chunk_info (void) {} 722void g_mem_chunk_info(void)
723{
724}
674void g_blow_chunks (void) {} 725void g_blow_chunks(void)
726{
727}
675 728
676GAllocator* 729GAllocator*
677g_allocator_new (const gchar *name, 730g_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
695void
696g_allocator_free (GAllocator *allocator) 746void g_allocator_free(GAllocator *allocator)
697{ 747{
698} 748}
699 749
700#ifdef ENABLE_GC_FRIENDLY_DEFAULT 750#ifdef ENABLE_GC_FRIENDLY_DEFAULT
701gboolean g_mem_gc_friendly = TRUE; 751gboolean g_mem_gc_friendly = TRUE;
702#else 752#else
703gboolean g_mem_gc_friendly = FALSE; 753gboolean g_mem_gc_friendly = FALSE;
704#endif 754#endif
705 755
706static void
707g_mem_init_nomessage (void) 756static 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
729void
730_g_mem_thread_init_noprivate_nomessage (void) 779void _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"

Legend:
Removed from v.30  
changed lines
  Added in v.31

   
Visit the ZANavi Wiki