X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgmem.c;h=5363751f241450ee690bc74bf3df874b5600f590;hb=d217429729aad360f372633f2ec99778c0fc08d5;hp=a79684f72449d07ec29e27e33c4e6bfe18c8aca8;hpb=a2ea02d01ee7b0fe8f2be7f9a34decb17ec8193b;p=platform%2Fupstream%2Fglib.git
diff --git a/glib/gmem.c b/glib/gmem.c
index a79684f..5363751 100644
--- a/glib/gmem.c
+++ b/glib/gmem.c
@@ -12,9 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library; if not, see .
*/
/*
@@ -36,89 +34,29 @@
#include
#include
+#include "gslice.h"
#include "gbacktrace.h"
#include "gtestutils.h"
#include "gthread.h"
#include "glib_trace.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.ac and gmem.h in sync here.
- * g_mem_gc_friendly is TRUE, freed memory should be 0-wiped.
+ * If g_mem_gc_friendly is TRUE, freed memory should be 0-wiped.
*/
-/* --- 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,
- gsize n_bytes)
-{
- if (!mem)
- return malloc (n_bytes);
- else
- return realloc (mem, n_bytes);
-}
-#endif /* !REALLOC_0_WORKS */
-
-#ifdef SANE_MALLOC_PROTOS
-# define standard_malloc malloc
-# ifdef REALLOC_0_WORKS
-# define standard_realloc realloc
-# endif /* REALLOC_0_WORKS */
-# define standard_free free
-# define standard_calloc calloc
-# define standard_try_malloc malloc
-# define standard_try_realloc realloc
-#else /* !SANE_MALLOC_PROTOS */
-static gpointer
-standard_malloc (gsize n_bytes)
-{
- return malloc (n_bytes);
-}
-# ifdef REALLOC_0_WORKS
-static gpointer
-standard_realloc (gpointer mem,
- gsize n_bytes)
-{
- return realloc (mem, n_bytes);
-}
-# endif /* REALLOC_0_WORKS */
-static void
-standard_free (gpointer mem)
-{
- free (mem);
-}
-static gpointer
-standard_calloc (gsize n_blocks,
- gsize n_bytes)
-{
- return calloc (n_blocks, n_bytes);
-}
-#define standard_try_malloc standard_malloc
-#define standard_try_realloc standard_realloc
-#endif /* !SANE_MALLOC_PROTOS */
-
-
/* --- variables --- */
static GMemVTable glib_mem_vtable = {
- standard_malloc,
- standard_realloc,
- standard_free,
- standard_calloc,
- standard_try_malloc,
- standard_try_realloc,
+ malloc,
+ realloc,
+ free,
+ calloc,
+ malloc,
+ realloc,
};
/**
@@ -128,18 +66,15 @@ static GMemVTable glib_mem_vtable = {
*
* These functions provide support for allocating and freeing memory.
*
- *
* 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.
- *
- *
- *
- * 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().
- *
+ *
+ * It's important to match g_malloc() (and wrappers such as g_new()) with
+ * g_free(), g_slice_alloc() and wrappers such as g_slice_new()) with
+ * g_slice_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().
*/
/* --- functions --- */
@@ -155,8 +90,6 @@ static GMemVTable glib_mem_vtable = {
gpointer
g_malloc (gsize n_bytes)
{
- if (G_UNLIKELY (!g_mem_initialized))
- g_mem_init_nomessage();
if (G_LIKELY (n_bytes))
{
gpointer mem;
@@ -187,8 +120,6 @@ g_malloc (gsize n_bytes)
gpointer
g_malloc0 (gsize n_bytes)
{
- if (G_UNLIKELY (!g_mem_initialized))
- g_mem_init_nomessage();
if (G_LIKELY (n_bytes))
{
gpointer mem;
@@ -209,7 +140,7 @@ g_malloc0 (gsize n_bytes)
/**
* g_realloc:
- * @mem: the memory to reallocate
+ * @mem: (allow-none): 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
@@ -226,8 +157,6 @@ g_realloc (gpointer mem,
{
gpointer newmem;
- if (G_UNLIKELY (!g_mem_initialized))
- g_mem_init_nomessage();
if (G_LIKELY (n_bytes))
{
newmem = glib_mem_vtable.realloc (mem, n_bytes);
@@ -249,7 +178,7 @@ g_realloc (gpointer mem,
/**
* g_free:
- * @mem: the memory to free
+ * @mem: (allow-none): the memory to free
*
* Frees the memory pointed to by @mem.
* If @mem is %NULL it simply returns.
@@ -257,14 +186,51 @@ g_realloc (gpointer mem,
void
g_free (gpointer mem)
{
- if (G_UNLIKELY (!g_mem_initialized))
- g_mem_init_nomessage();
if (G_LIKELY (mem))
glib_mem_vtable.free (mem);
TRACE(GLIB_MEM_FREE((void*) mem));
}
/**
+ * g_clear_pointer: (skip)
+ * @pp: a pointer to a variable, struct member etc. holding a pointer
+ * @destroy: a function to which a gpointer can be passed, to destroy *@pp
+ *
+ * Clears a reference to a variable.
+ *
+ * @pp must not be %NULL.
+ *
+ * If the reference is %NULL then this function does nothing.
+ * Otherwise, the variable is destroyed using @destroy and the
+ * pointer is set to %NULL.
+ *
+ * This function is threadsafe and modifies the pointer atomically,
+ * using memory barriers where needed.
+ *
+ * A macro is also included that allows this function to be used without
+ * pointer casts.
+ *
+ * Since: 2.34
+ **/
+#undef g_clear_pointer
+void
+g_clear_pointer (gpointer *pp,
+ GDestroyNotify destroy)
+{
+ gpointer _p;
+
+ /* This is a little frustrating.
+ * Would be nice to have an atomic exchange (with no compare).
+ */
+ do
+ _p = g_atomic_pointer_get (pp);
+ while G_UNLIKELY (!g_atomic_pointer_compare_and_exchange (pp, _p, NULL));
+
+ if (_p)
+ destroy (_p);
+}
+
+/**
* g_try_malloc:
* @n_bytes: number of bytes to allocate.
*
@@ -278,8 +244,6 @@ g_try_malloc (gsize n_bytes)
{
gpointer mem;
- if (G_UNLIKELY (!g_mem_initialized))
- g_mem_init_nomessage();
if (G_LIKELY (n_bytes))
mem = glib_mem_vtable.try_malloc (n_bytes);
else
@@ -305,8 +269,6 @@ g_try_malloc0 (gsize n_bytes)
{
gpointer mem;
- if (G_UNLIKELY (!g_mem_initialized))
- g_mem_init_nomessage();
if (G_LIKELY (n_bytes))
mem = glib_mem_vtable.try_malloc (n_bytes);
else
@@ -320,7 +282,7 @@ g_try_malloc0 (gsize n_bytes)
/**
* g_try_realloc:
- * @mem: previously-allocated memory, or %NULL.
+ * @mem: (allow-none): 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
@@ -335,8 +297,6 @@ g_try_realloc (gpointer mem,
{
gpointer newmem;
- if (G_UNLIKELY (!g_mem_initialized))
- g_mem_init_nomessage();
if (G_LIKELY (n_bytes))
newmem = glib_mem_vtable.try_realloc (mem, n_bytes);
else
@@ -371,9 +331,6 @@ g_malloc_n (gsize n_blocks,
{
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
{
- if (G_UNLIKELY (!g_mem_initialized))
- g_mem_init_nomessage();
-
g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
G_STRLOC, n_blocks, n_block_bytes);
}
@@ -398,9 +355,6 @@ g_malloc0_n (gsize n_blocks,
{
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
{
- if (G_UNLIKELY (!g_mem_initialized))
- g_mem_init_nomessage();
-
g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
G_STRLOC, n_blocks, n_block_bytes);
}
@@ -410,7 +364,7 @@ g_malloc0_n (gsize n_blocks,
/**
* g_realloc_n:
- * @mem: the memory to reallocate
+ * @mem: (allow-none): the memory to reallocate
* @n_blocks: the number of blocks to allocate
* @n_block_bytes: the size of each block in bytes
*
@@ -427,9 +381,6 @@ g_realloc_n (gpointer mem,
{
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
{
- if (G_UNLIKELY (!g_mem_initialized))
- g_mem_init_nomessage();
-
g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
G_STRLOC, n_blocks, n_block_bytes);
}
@@ -481,7 +432,7 @@ g_try_malloc0_n (gsize n_blocks,
/**
* g_try_realloc_n:
- * @mem: previously-allocated memory, or %NULL.
+ * @mem: (allow-none): previously-allocated memory, or %NULL.
* @n_blocks: the number of blocks to allocate
* @n_block_bytes: the size of each block in bytes
*
@@ -520,7 +471,7 @@ fallback_calloc (gsize n_blocks,
static gboolean vtable_set = FALSE;
/**
- * g_mem_is_system_malloc
+ * g_mem_is_system_malloc:
*
* Checks whether the allocator used by g_malloc() is the system's
* malloc implementation. If it returns %TRUE memory allocated with
@@ -530,7 +481,7 @@ static gboolean vtable_set = FALSE;
*
* A different allocator can be set using g_mem_set_vtable().
*
- * Return value: if %TRUE, malloc() and g_malloc() can be mixed.
+ * Returns: if %TRUE, malloc() and g_malloc() can be mixed.
**/
gboolean
g_mem_is_system_malloc (void)
@@ -542,13 +493,17 @@ g_mem_is_system_malloc (void)
* 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. This function must be called
- * before using any other GLib functions. 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.
+ * Sets the #GMemVTable to use for memory allocation. You can use this
+ * to provide custom memory allocation routines.
+ *
+ * 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.
+ *
+ * Note that this function must be called before using any other GLib
+ * functions.
*/
void
g_mem_set_vtable (GMemVTable *vtable)
@@ -599,12 +554,7 @@ static guint *profile_data = NULL;
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 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 */
+static GMutex gmem_profile_mutex;
#define PROFILE_TABLE(f1,f2,f3) ( ( ((f3) << 2) | ((f2) << 1) | (f1) ) * (MEM_PROFILE_TABLE_SIZE + 1))
@@ -613,14 +563,14 @@ profiler_log (ProfilerJob job,
gsize n_bytes,
gboolean success)
{
- g_mutex_lock (gmem_profile_mutex);
+ g_mutex_lock (&gmem_profile_mutex);
if (!profile_data)
{
- profile_data = standard_calloc ((MEM_PROFILE_TABLE_SIZE + 1) * 8,
- sizeof (profile_data[0]));
+ profile_data = 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_mutex_unlock (&gmem_profile_mutex);
return;
}
}
@@ -644,7 +594,7 @@ profiler_log (ProfilerJob job,
else
profile_frees += n_bytes;
}
- g_mutex_unlock (gmem_profile_mutex);
+ g_mutex_unlock (&gmem_profile_mutex);
}
static void
@@ -685,7 +635,6 @@ profile_print_locked (guint *local_data,
/**
* g_mem_profile:
- * @void:
*
* Outputs a summary of memory usage.
*
@@ -702,15 +651,12 @@ profile_print_locked (guint *local_data,
void
g_mem_profile (void)
{
- guint local_data[(MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof (profile_data[0])];
+ guint local_data[(MEM_PROFILE_TABLE_SIZE + 1) * 8];
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);
+ g_mutex_lock (&gmem_profile_mutex);
local_allocs = profile_allocs;
local_zinit = profile_zinit;
@@ -718,14 +664,14 @@ g_mem_profile (void)
if (!profile_data)
{
- g_mutex_unlock (gmem_profile_mutex);
+ g_mutex_unlock (&gmem_profile_mutex);
return;
}
memcpy (local_data, profile_data,
(MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof (profile_data[0]));
- g_mutex_unlock (gmem_profile_mutex);
+ g_mutex_unlock (&gmem_profile_mutex);
g_print ("GLib Memory statistics (successful operations):\n");
profile_print_locked (local_data, TRUE);
@@ -748,12 +694,7 @@ profiler_try_malloc (gsize n_bytes)
{
gsize *p;
-#ifdef G_ENABLE_DEBUG
- if (g_trap_malloc_size == n_bytes)
- G_BREAKPOINT ();
-#endif /* G_ENABLE_DEBUG */
-
- p = standard_malloc (sizeof (gsize) * 2 + n_bytes);
+ p = malloc (sizeof (gsize) * 2 + n_bytes);
if (p)
{
@@ -786,12 +727,7 @@ profiler_calloc (gsize n_blocks,
gsize l = n_blocks * n_block_bytes;
gsize *p;
-#ifdef G_ENABLE_DEBUG
- if (g_trap_malloc_size == l)
- G_BREAKPOINT ();
-#endif /* G_ENABLE_DEBUG */
-
- p = standard_calloc (1, sizeof (gsize) * 2 + l);
+ p = calloc (1, sizeof (gsize) * 2 + l);
if (p)
{
@@ -825,17 +761,12 @@ profiler_free (gpointer mem)
}
else
{
-#ifdef G_ENABLE_DEBUG
- if (g_trap_free_size == p[1])
- G_BREAKPOINT ();
-#endif /* G_ENABLE_DEBUG */
-
profiler_log (PROFILER_FREE,
p[1], /* length */
TRUE);
memset (p + 2, 0xaa, p[1]);
- /* for all those that miss standard_free (p); in this place, yes,
+ /* for all those that miss free (p); in this place, yes,
* we do leak all memory when profiling, and that is intentional
* to catch double frees. patch submissions are futile.
*/
@@ -850,11 +781,6 @@ profiler_try_realloc (gpointer mem,
gsize *p = mem;
p -= 2;
-
-#ifdef G_ENABLE_DEBUG
- if (g_trap_realloc_size == n_bytes)
- G_BREAKPOINT ();
-#endif /* G_ENABLE_DEBUG */
if (mem && p[0]) /* free count */
{
@@ -867,7 +793,7 @@ profiler_try_realloc (gpointer mem,
}
else
{
- p = standard_realloc (mem ? p : NULL, sizeof (gsize) * 2 + n_bytes);
+ p = realloc (mem ? p : NULL, sizeof (gsize) * 2 + n_bytes);
if (p)
{
@@ -908,48 +834,3 @@ static GMemVTable profiler_table = {
GMemVTable *glib_mem_profiler_table = &profiler_table;
#endif /* !G_DISABLE_CHECKS */
-
-#ifdef ENABLE_GC_FRIENDLY_DEFAULT
-gboolean g_mem_gc_friendly = TRUE;
-#else
-/**
- * g_mem_gc_friendly:
- *
- * This variable is %TRUE if the G_DEBUG environment variable
- * includes the key gc-friendly.
- */
-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 a mutex does not yet work.
- */
- g_mem_init_nomessage();
-#ifndef G_DISABLE_CHECKS
- gmem_profile_mutex = g_mutex_new ();
-#endif
-}