#include <signal.h>
#include "glib.h"
-#include "gthreadinit.h"
+#include "gthreadprivate.h"
#include "galias.h"
+#define MEM_PROFILE_TABLE_SIZE 4096
+
+
/* notes on macros:
* having G_DISABLE_CHECKS defined disables use of glib_mem_profiler_table and
* g_mem_profile().
* REALLOC_0_WORKS is defined if g_realloc (NULL, x) works.
* SANE_MALLOC_PROTOS is defined if the systems malloc() and friends functions
* match the corresponding GLib prototypes, keep configure.in and gmem.h in sync here.
- * if ENABLE_GC_FRIENDLY is defined, freed memory should be 0-wiped.
+ * g_mem_gc_friendly is TRUE, freed memory should be 0-wiped.
*/
-#define MEM_PROFILE_TABLE_SIZE 4096
+/* --- prototypes --- */
+static gboolean g_mem_initialized = FALSE;
+static void g_mem_init_nomessage (void);
+
+/* --- malloc wrappers --- */
#ifndef REALLOC_0_WORKS
static gpointer
standard_realloc (gpointer mem,
/* --- functions --- */
gpointer
-g_malloc (gulong n_bytes)
+g_malloc (gsize n_bytes)
{
- if (n_bytes)
+ if (G_UNLIKELY (!g_mem_initialized))
+ g_mem_init_nomessage();
+ if (G_LIKELY (n_bytes))
{
gpointer mem;
if (mem)
return mem;
- g_error ("%s: failed to allocate %lu bytes", G_STRLOC, n_bytes);
+ g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
+ G_STRLOC, n_bytes);
}
return NULL;
}
gpointer
-g_malloc0 (gulong n_bytes)
+g_malloc0 (gsize n_bytes)
{
- if (n_bytes)
+ if (G_UNLIKELY (!g_mem_initialized))
+ g_mem_init_nomessage();
+ if (G_LIKELY (n_bytes))
{
gpointer mem;
if (mem)
return mem;
- g_error ("%s: failed to allocate %lu bytes", G_STRLOC, n_bytes);
+ g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
+ G_STRLOC, n_bytes);
}
return NULL;
gpointer
g_realloc (gpointer mem,
- gulong n_bytes)
+ gsize n_bytes)
{
- if (n_bytes)
+ if (G_UNLIKELY (!g_mem_initialized))
+ g_mem_init_nomessage();
+ if (G_LIKELY (n_bytes))
{
mem = glib_mem_vtable.realloc (mem, n_bytes);
if (mem)
return mem;
- g_error ("%s: failed to allocate %lu bytes", G_STRLOC, n_bytes);
+ g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
+ G_STRLOC, n_bytes);
}
if (mem)
void
g_free (gpointer mem)
{
- if (mem)
+ if (G_UNLIKELY (!g_mem_initialized))
+ g_mem_init_nomessage();
+ if (G_LIKELY (mem))
glib_mem_vtable.free (mem);
}
gpointer
-g_try_malloc (gulong n_bytes)
+g_try_malloc (gsize n_bytes)
{
- if (n_bytes)
+ if (G_UNLIKELY (!g_mem_initialized))
+ g_mem_init_nomessage();
+ if (G_LIKELY (n_bytes))
return glib_mem_vtable.try_malloc (n_bytes);
else
return NULL;
}
gpointer
-g_try_malloc0 (gulong n_bytes)
+g_try_malloc0 (gsize n_bytes)
{
gpointer mem;
gpointer
g_try_realloc (gpointer mem,
- gulong n_bytes)
+ gsize n_bytes)
{
- if (n_bytes)
+ if (G_UNLIKELY (!g_mem_initialized))
+ g_mem_init_nomessage();
+ if (G_LIKELY (n_bytes))
return glib_mem_vtable.try_realloc (mem, n_bytes);
if (mem)
PROFILER_ZINIT = 4
} ProfilerJob;
static guint *profile_data = NULL;
-static gulong profile_allocs = 0;
-static gulong profile_zinit = 0;
-static gulong profile_frees = 0;
+static gsize profile_allocs = 0;
+static gsize profile_zinit = 0;
+static gsize profile_frees = 0;
static GMutex *gmem_profile_mutex = NULL;
#ifdef G_ENABLE_DEBUG
-static volatile gulong g_trap_free_size = 0;
-static volatile gulong g_trap_realloc_size = 0;
-static volatile gulong g_trap_malloc_size = 0;
+static volatile gsize g_trap_free_size = 0;
+static volatile gsize g_trap_realloc_size = 0;
+static volatile gsize g_trap_malloc_size = 0;
#endif /* G_ENABLE_DEBUG */
#define PROFILE_TABLE(f1,f2,f3) ( ( ((f3) << 2) | ((f2) << 1) | (f1) ) * (MEM_PROFILE_TABLE_SIZE + 1))
static void
profiler_log (ProfilerJob job,
- gulong n_bytes,
+ gsize n_bytes,
gboolean success)
{
g_mutex_lock (gmem_profile_mutex);
if (!profile_data)
{
- profile_data = standard_malloc ((MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof (profile_data[0]));
+ profile_data = standard_calloc ((MEM_PROFILE_TABLE_SIZE + 1) * 8,
+ sizeof (profile_data[0]));
if (!profile_data) /* memory system kiddin' me, eh? */
{
g_mutex_unlock (gmem_profile_mutex);
g_mem_profile (void)
{
guint local_data[(MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof (profile_data[0])];
- gulong local_allocs;
- gulong local_zinit;
- gulong local_frees;
+ gsize local_allocs;
+ gsize local_zinit;
+ gsize local_frees;
+
+ if (G_UNLIKELY (!g_mem_initialized))
+ g_mem_init_nomessage();
g_mutex_lock (gmem_profile_mutex);
profile_print_locked (local_data, TRUE);
g_print ("GLib Memory statistics (failing operations):\n");
profile_print_locked (local_data, FALSE);
- g_print ("Total bytes: allocated=%lu, zero-initialized=%lu (%.2f%%), freed=%lu (%.2f%%), remaining=%lu\n",
+ g_print ("Total bytes: allocated=%"G_GSIZE_FORMAT", "
+ "zero-initialized=%"G_GSIZE_FORMAT" (%.2f%%), "
+ "freed=%"G_GSIZE_FORMAT" (%.2f%%), "
+ "remaining=%"G_GSIZE_FORMAT"\n",
local_allocs,
local_zinit,
((gdouble) local_zinit) / local_allocs * 100.0,
static gpointer
profiler_try_malloc (gsize n_bytes)
{
- gulong *p;
+ gsize *p;
#ifdef G_ENABLE_DEBUG
if (g_trap_malloc_size == n_bytes)
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
- p = standard_malloc (sizeof (gulong) * 2 + n_bytes);
+ p = standard_malloc (sizeof (gsize) * 2 + n_bytes);
if (p)
{
gsize n_block_bytes)
{
gsize l = n_blocks * n_block_bytes;
- gulong *p;
+ gsize *p;
#ifdef G_ENABLE_DEBUG
if (g_trap_malloc_size == l)
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
- p = standard_calloc (1, sizeof (gulong) * 2 + l);
+ p = standard_calloc (1, sizeof (gsize) * 2 + l);
if (p)
{
static void
profiler_free (gpointer mem)
{
- gulong *p = mem;
+ gsize *p = mem;
p -= 2;
if (p[0]) /* free count */
{
- g_warning ("free(%p): memory has been freed %lu times already", p + 2, p[0]);
+ g_warning ("free(%p): memory has been freed %"G_GSIZE_FORMAT" times already",
+ p + 2, p[0]);
profiler_log (PROFILER_FREE,
p[1], /* length */
FALSE);
profiler_try_realloc (gpointer mem,
gsize n_bytes)
{
- gulong *p = mem;
+ gsize *p = mem;
p -= 2;
if (mem && p[0]) /* free count */
{
- g_warning ("realloc(%p, %lu): memory has been freed %lu times already", p + 2, (gulong)n_bytes, p[0]);
+ g_warning ("realloc(%p, %"G_GSIZE_FORMAT"): "
+ "memory has been freed %"G_GSIZE_FORMAT" times already",
+ p + 2, (gsize) n_bytes, p[0]);
profiler_log (PROFILER_ALLOC | PROFILER_RELOC, n_bytes, FALSE);
return NULL;
}
else
{
- p = standard_realloc (mem ? p : NULL, sizeof (gulong) * 2 + n_bytes);
+ p = standard_realloc (mem ? p : NULL, sizeof (gsize) * 2 + n_bytes);
if (p)
{
GMemChunk*
g_mem_chunk_new (const gchar *name,
gint atom_size,
- gulong area_size,
+ gsize area_size,
gint type)
{
GMemChunk *mem_chunk;
g_allocator_new (const gchar *name,
guint n_preallocs)
{
- static const struct _GAllocator {
+ static struct _GAllocator {
gchar *name;
guint16 n_preallocs;
guint is_unused : 1;
{
}
+#ifdef ENABLE_GC_FRIENDLY_DEFAULT
+gboolean g_mem_gc_friendly = TRUE;
+#else
+gboolean g_mem_gc_friendly = FALSE;
+#endif
+
+static void
+g_mem_init_nomessage (void)
+{
+ gchar buffer[1024];
+ const gchar *val;
+ const GDebugKey keys[] = {
+ { "gc-friendly", 1 },
+ };
+ gint flags;
+ if (g_mem_initialized)
+ return;
+ /* don't use g_malloc/g_message here */
+ val = _g_getenv_nomalloc ("G_DEBUG", buffer);
+ flags = !val ? 0 : g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
+ if (flags & 1) /* gc-friendly */
+ {
+ g_mem_gc_friendly = TRUE;
+ }
+ g_mem_initialized = TRUE;
+}
+
void
_g_mem_thread_init_noprivate_nomessage (void)
{
- /* we may only create mutexes here, locking/unlocking itself
- * does not yet work.
+ /* we may only create mutexes here, locking/
+ * unlocking a mutex does not yet work.
*/
+ g_mem_init_nomessage();
#ifndef G_DISABLE_CHECKS
gmem_profile_mutex = g_mutex_new ();
#endif