Bug 556186 – gpoll.h breaks gmain.h inclusion
[platform/upstream/glib.git] / glib / gmem.c
index 849ade5..b9ce0a6 100644 (file)
 #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,
@@ -113,9 +120,11 @@ static GMemVTable glib_mem_vtable = {
 
 /* --- 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;
 
@@ -123,16 +132,19 @@ g_malloc (gulong 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);
     }
 
   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;
 
@@ -140,7 +152,8 @@ g_malloc0 (gulong 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);
     }
 
   return NULL;
@@ -148,15 +161,18 @@ g_malloc0 (gulong n_bytes)
 
 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)
@@ -168,21 +184,25 @@ g_realloc (gpointer 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;
 
@@ -196,9 +216,11 @@ g_try_malloc0 (gulong n_bytes)
 
 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)
@@ -279,27 +301,28 @@ typedef enum {
   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);
@@ -369,9 +392,12 @@ void
 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);
 
@@ -394,7 +420,10 @@ g_mem_profile (void)
   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,
@@ -406,14 +435,14 @@ g_mem_profile (void)
 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)
     {
@@ -444,14 +473,14 @@ profiler_calloc (gsize n_blocks,
                 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)
     {
@@ -472,12 +501,13 @@ profiler_calloc (gsize n_blocks,
 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);
@@ -506,7 +536,7 @@ static gpointer
 profiler_try_realloc (gpointer mem,
                      gsize    n_bytes)
 {
-  gulong *p = mem;
+  gsize *p = mem;
 
   p -= 2;
 
@@ -517,14 +547,16 @@ profiler_try_realloc (gpointer mem,
   
   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)
        {
@@ -581,7 +613,7 @@ struct _GMemChunk {
 GMemChunk*
 g_mem_chunk_new (const gchar  *name,
                 gint          atom_size,
-                gulong        area_size,
+                gsize         area_size,
                 gint          type)
 {
   GMemChunk *mem_chunk;
@@ -635,7 +667,7 @@ GAllocator*
 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;
@@ -655,12 +687,40 @@ g_allocator_free (GAllocator *allocator)
 {
 }
 
+#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