Merge branch 'concurrent-cancellable'
[platform/upstream/glib.git] / glib / gmem.c
index 36e04dd..a657f73 100644 (file)
 
 #include "config.h"
 
+#include "gmem.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
 
-#include "glib.h"
-#include "gthreadprivate.h"
+#include "gbacktrace.h"
+#include "gtestutils.h"
+#include "gthread.h"
+#include "glib_trace.h"
 
-#include "galias.h"
 
 #define MEM_PROFILE_TABLE_SIZE 4096
 
@@ -47,7 +50,7 @@
  * 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.
+ * match the corresponding GLib prototypes, keep configure.ac and gmem.h in sync here.
  * g_mem_gc_friendly is TRUE, freed memory should be 0-wiped.
  */
 
@@ -118,8 +121,37 @@ static GMemVTable glib_mem_vtable = {
   standard_try_realloc,
 };
 
+/**
+ * SECTION:memory
+ * @Short_Description: general memory-handling
+ * @Title: Memory Allocation
+ * 
+ * These functions provide support for allocating and freeing memory.
+ * 
+ * <note>
+ * If any call to allocate memory fails, the application is terminated.
+ * This also means that there is no need to check if the call succeeded.
+ * </note>
+ * 
+ * <note>
+ * It's important to match g_malloc() with g_free(), plain malloc() with free(),
+ * and (if you're using C++) new with delete and new[] with delete[]. Otherwise
+ * bad things can happen, since these allocators may use different memory
+ * pools (and new/delete call constructors and destructors). See also
+ * g_mem_set_vtable().
+ * </note>
+ */
 
 /* --- functions --- */
+/**
+ * g_malloc:
+ * @n_bytes: the number of bytes to allocate
+ * 
+ * Allocates @n_bytes bytes of memory.
+ * If @n_bytes is 0 it returns %NULL.
+ * 
+ * Returns: a pointer to the allocated memory
+ */
 gpointer
 g_malloc (gsize n_bytes)
 {
@@ -130,6 +162,7 @@ g_malloc (gsize n_bytes)
       gpointer mem;
 
       mem = glib_mem_vtable.malloc (n_bytes);
+      TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 0, 0));
       if (mem)
        return mem;
 
@@ -137,9 +170,20 @@ g_malloc (gsize n_bytes)
                G_STRLOC, n_bytes);
     }
 
+  TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 0, 0));
+
   return NULL;
 }
 
+/**
+ * g_malloc0:
+ * @n_bytes: the number of bytes to allocate
+ * 
+ * Allocates @n_bytes bytes of memory, initialized to 0's.
+ * If @n_bytes is 0 it returns %NULL.
+ * 
+ * Returns: a pointer to the allocated memory
+ */
 gpointer
 g_malloc0 (gsize n_bytes)
 {
@@ -150,6 +194,7 @@ g_malloc0 (gsize n_bytes)
       gpointer mem;
 
       mem = glib_mem_vtable.calloc (1, n_bytes);
+      TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 1, 0));
       if (mem)
        return mem;
 
@@ -157,20 +202,38 @@ g_malloc0 (gsize n_bytes)
                G_STRLOC, n_bytes);
     }
 
+  TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 1, 0));
+
   return NULL;
 }
 
+/**
+ * g_realloc:
+ * @mem: the memory to reallocate
+ * @n_bytes: new size of the memory in bytes
+ * 
+ * Reallocates the memory pointed to by @mem, so that it now has space for
+ * @n_bytes bytes of memory. It returns the new address of the memory, which may
+ * have been moved. @mem may be %NULL, in which case it's considered to
+ * have zero-length. @n_bytes may be 0, in which case %NULL will be returned
+ * and @mem will be freed unless it is %NULL.
+ * 
+ * Returns: the new address of the allocated memory
+ */
 gpointer
 g_realloc (gpointer mem,
           gsize    n_bytes)
 {
+  gpointer newmem;
+
   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;
+      newmem = glib_mem_vtable.realloc (mem, n_bytes);
+      TRACE (GLIB_MEM_REALLOC((void*) newmem, (void*)mem, (unsigned int) n_bytes, 0));
+      if (newmem)
+       return newmem;
 
       g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
                G_STRLOC, n_bytes);
@@ -179,9 +242,18 @@ g_realloc (gpointer mem,
   if (mem)
     glib_mem_vtable.free (mem);
 
+  TRACE (GLIB_MEM_REALLOC((void*) NULL, (void*)mem, 0, 0));
+
   return NULL;
 }
 
+/**
+ * g_free:
+ * @mem: the memory to free
+ * 
+ * Frees the memory pointed to by @mem.
+ * If @mem is %NULL it simply returns.
+ */
 void
 g_free (gpointer mem)
 {
@@ -189,25 +261,56 @@ g_free (gpointer mem)
     g_mem_init_nomessage();
   if (G_LIKELY (mem))
     glib_mem_vtable.free (mem);
+  TRACE(GLIB_MEM_FREE((void*) mem));
 }
 
+/**
+ * g_try_malloc:
+ * @n_bytes: number of bytes to allocate.
+ * 
+ * Attempts to allocate @n_bytes, and returns %NULL on failure.
+ * Contrast with g_malloc(), which aborts the program on failure.
+ * 
+ * Returns: the allocated memory, or %NULL.
+ */
 gpointer
 g_try_malloc (gsize n_bytes)
 {
+  gpointer mem;
+
   if (G_UNLIKELY (!g_mem_initialized))
     g_mem_init_nomessage();
   if (G_LIKELY (n_bytes))
-    return glib_mem_vtable.try_malloc (n_bytes);
+    mem = glib_mem_vtable.try_malloc (n_bytes);
   else
-    return NULL;
+    mem = NULL;
+
+  TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 0, 1));
+
+  return mem;
 }
 
+/**
+ * g_try_malloc0:
+ * @n_bytes: number of bytes to allocate
+ * 
+ * Attempts to allocate @n_bytes, initialized to 0's, and returns %NULL on
+ * failure. Contrast with g_malloc0(), which aborts the program on failure.
+ * 
+ * Since: 2.8
+ * Returns: the allocated memory, or %NULL
+ */
 gpointer
 g_try_malloc0 (gsize n_bytes)
 {
   gpointer mem;
 
-  mem = g_try_malloc (n_bytes);
+  if (G_UNLIKELY (!g_mem_initialized))
+    g_mem_init_nomessage();
+  if (G_LIKELY (n_bytes))
+    mem = glib_mem_vtable.try_malloc (n_bytes);
+  else
+    mem = NULL;
 
   if (mem)
     memset (mem, 0, n_bytes);
@@ -215,24 +318,53 @@ g_try_malloc0 (gsize n_bytes)
   return mem;
 }
 
+/**
+ * g_try_realloc:
+ * @mem: previously-allocated memory, or %NULL.
+ * @n_bytes: number of bytes to allocate.
+ * 
+ * Attempts to realloc @mem to a new size, @n_bytes, and returns %NULL
+ * on failure. Contrast with g_realloc(), which aborts the program
+ * on failure. If @mem is %NULL, behaves the same as g_try_malloc().
+ * 
+ * Returns: the allocated memory, or %NULL.
+ */
 gpointer
 g_try_realloc (gpointer mem,
               gsize    n_bytes)
 {
+  gpointer newmem;
+
   if (G_UNLIKELY (!g_mem_initialized))
     g_mem_init_nomessage();
   if (G_LIKELY (n_bytes))
-    return glib_mem_vtable.try_realloc (mem, n_bytes);
+    newmem = glib_mem_vtable.try_realloc (mem, n_bytes);
+  else
+    {
+      newmem = NULL;
+      if (mem)
+       glib_mem_vtable.free (mem);
+    }
 
-  if (mem)
-    glib_mem_vtable.free (mem);
+  TRACE (GLIB_MEM_REALLOC((void*) newmem, (void*)mem, (unsigned int) n_bytes, 1));
 
-  return NULL;
+  return newmem;
 }
 
 
-#define SIZE_OVERFLOWS(a,b) (G_UNLIKELY ((a) > G_MAXSIZE / (b)))
+#define SIZE_OVERFLOWS(a,b) (G_UNLIKELY ((b) > 0 && (a) > G_MAXSIZE / (b)))
 
+/**
+ * g_malloc_n:
+ * @n_blocks: the number of blocks to allocate
+ * @n_block_bytes: the size of each block in bytes
+ * 
+ * This function is similar to g_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
+ * but care is taken to detect possible overflow during multiplication.
+ * 
+ * Since: 2.24
+ * Returns: a pointer to the allocated memory
+ */
 gpointer
 g_malloc_n (gsize n_blocks,
            gsize n_block_bytes)
@@ -249,6 +381,17 @@ g_malloc_n (gsize n_blocks,
   return g_malloc (n_blocks * n_block_bytes);
 }
 
+/**
+ * g_malloc0_n:
+ * @n_blocks: the number of blocks to allocate
+ * @n_block_bytes: the size of each block in bytes
+ * 
+ * This function is similar to g_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
+ * but care is taken to detect possible overflow during multiplication.
+ * 
+ * Since: 2.24
+ * Returns: a pointer to the allocated memory
+ */
 gpointer
 g_malloc0_n (gsize n_blocks,
             gsize n_block_bytes)
@@ -265,6 +408,18 @@ g_malloc0_n (gsize n_blocks,
   return g_malloc0 (n_blocks * n_block_bytes);
 }
 
+/**
+ * g_realloc_n:
+ * @mem: the memory to reallocate
+ * @n_blocks: the number of blocks to allocate
+ * @n_block_bytes: the size of each block in bytes
+ * 
+ * This function is similar to g_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
+ * but care is taken to detect possible overflow during multiplication.
+ * 
+ * Since: 2.24
+ * Returns: the new address of the allocated memory
+ */
 gpointer
 g_realloc_n (gpointer mem,
             gsize    n_blocks,
@@ -282,6 +437,17 @@ g_realloc_n (gpointer mem,
   return g_realloc (mem, n_blocks * n_block_bytes);
 }
 
+/**
+ * g_try_malloc_n:
+ * @n_blocks: the number of blocks to allocate
+ * @n_block_bytes: the size of each block in bytes
+ * 
+ * This function is similar to g_try_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
+ * but care is taken to detect possible overflow during multiplication.
+ * 
+ * Since: 2.24
+ * Returns: the allocated memory, or %NULL.
+ */
 gpointer
 g_try_malloc_n (gsize n_blocks,
                gsize n_block_bytes)
@@ -292,6 +458,17 @@ g_try_malloc_n (gsize n_blocks,
   return g_try_malloc (n_blocks * n_block_bytes);
 }
 
+/**
+ * g_try_malloc0_n:
+ * @n_blocks: the number of blocks to allocate
+ * @n_block_bytes: the size of each block in bytes
+ * 
+ * This function is similar to g_try_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
+ * but care is taken to detect possible overflow during multiplication.
+ * 
+ * Since: 2.24
+ * Returns: the allocated memory, or %NULL
+ */
 gpointer
 g_try_malloc0_n (gsize n_blocks,
                 gsize n_block_bytes)
@@ -302,6 +479,18 @@ g_try_malloc0_n (gsize n_blocks,
   return g_try_malloc0 (n_blocks * n_block_bytes);
 }
 
+/**
+ * g_try_realloc_n:
+ * @mem: previously-allocated memory, or %NULL.
+ * @n_blocks: the number of blocks to allocate
+ * @n_block_bytes: the size of each block in bytes
+ * 
+ * This function is similar to g_try_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
+ * but care is taken to detect possible overflow during multiplication.
+ * 
+ * Since: 2.24
+ * Returns: the allocated memory, or %NULL.
+ */
 gpointer
 g_try_realloc_n (gpointer mem,
                 gsize    n_blocks,
@@ -335,7 +524,7 @@ static gboolean vtable_set = FALSE;
  * 
  * Checks whether the allocator used by g_malloc() is the system's
  * malloc implementation. If it returns %TRUE memory allocated with
- * malloc() can be used interchangeable with memory allocated using g_malloc(). 
+ * malloc() can be used interchangeable with memory allocated using g_malloc().
  * This function is useful for avoiding an extra copy of allocated memory returned
  * by a non-GLib-based API.
  *
@@ -349,6 +538,18 @@ g_mem_is_system_malloc (void)
   return !vtable_set;
 }
 
+/**
+ * g_mem_set_vtable:
+ * @vtable: table of memory allocation routines.
+ * 
+ * Sets the #GMemVTable to use for memory allocation. You can use this to provide
+ * custom memory allocation routines. <emphasis>This function must be called
+ * before using any other GLib functions.</emphasis> The @vtable only needs to
+ * provide malloc(), realloc(), and free() functions; GLib can provide default
+ * implementations of the others. The malloc() and realloc() implementations
+ * should return %NULL on failure, GLib will handle error-checking for you.
+ * @vtable is copied, so need not persist after this function has been called.
+ */
 void
 g_mem_set_vtable (GMemVTable *vtable)
 {
@@ -374,6 +575,14 @@ g_mem_set_vtable (GMemVTable *vtable)
 
 /* --- memory profiling and checking --- */
 #ifdef G_DISABLE_CHECKS
+/**
+ * glib_mem_profiler_table:
+ * 
+ * A #GMemVTable containing profiling variants of the memory
+ * allocation functions. Use them together with g_mem_profile()
+ * in order to get information about the memory allocation pattern
+ * of your program.
+ */
 GMemVTable *glib_mem_profiler_table = &glib_mem_vtable;
 void
 g_mem_profile (void)
@@ -474,6 +683,22 @@ profile_print_locked (guint   *local_data,
     g_print (" --- none ---\n");
 }
 
+/**
+ * g_mem_profile:
+ * @void:
+ * 
+ * Outputs a summary of memory usage.
+ * 
+ * It outputs the frequency of allocations of different sizes,
+ * the total number of bytes which have been allocated,
+ * the total number of bytes which have been freed,
+ * and the difference between the previous two values, i.e. the number of bytes
+ * still in use.
+ * 
+ * Note that this function will not output anything unless you have
+ * previously installed the #glib_mem_profiler_table with g_mem_set_vtable().
+ */
+
 void
 g_mem_profile (void)
 {
@@ -686,7 +911,7 @@ GMemVTable *glib_mem_profiler_table = &profiler_table;
 
 /* --- MemChunks --- */
 /**
- * SECTION: allocators
+ * SECTION:allocators
  * @title: Memory Allocators
  * @short_description: deprecated way to allocate chunks of memory for
  *                     GList, GSList and GNode
@@ -699,7 +924,7 @@ GMemVTable *glib_mem_profiler_table = &profiler_table;
  **/
 
 /**
- * SECTION: memory_chunks
+ * SECTION:memory_chunks
  * @title: Memory Chunks
  * @short_description: deprecated way to allocate groups of equal-sized
  *                     chunks of memory
@@ -1129,6 +1354,12 @@ g_allocator_free (GAllocator *allocator)
 #ifdef ENABLE_GC_FRIENDLY_DEFAULT
 gboolean g_mem_gc_friendly = TRUE;
 #else
+/**
+ * g_mem_gc_friendly:
+ * 
+ * This variable is %TRUE if the <envar>G_DEBUG</envar> environment variable
+ * includes the key <link linkend="G_DEBUG">gc-friendly</link>.
+ */
 gboolean g_mem_gc_friendly = FALSE;
 #endif
 
@@ -1164,6 +1395,3 @@ _g_mem_thread_init_noprivate_nomessage (void)
   gmem_profile_mutex = g_mutex_new ();
 #endif
 }
-
-#define __G_MEM_C__
-#include "galiasdef.c"