X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgmem.c;h=5363751f241450ee690bc74bf3df874b5600f590;hb=f2ceb74e91e05e9556622bc2cde7ab57cbc30ea3;hp=ee87a1ec75f92c702243f0e850dd65e7771a782d;hpb=2c7388c19a3f7895ee49a5bc7219822a50b5b514;p=platform%2Fupstream%2Fglib.git diff --git a/glib/gmem.c b/glib/gmem.c index ee87a1e..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 . */ /* @@ -42,84 +40,23 @@ #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, }; /** @@ -129,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 --- */ @@ -156,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; @@ -188,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; @@ -210,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 @@ -227,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); @@ -250,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. @@ -258,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. * @@ -279,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 @@ -306,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 @@ -321,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 @@ -336,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 @@ -372,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); } @@ -399,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); } @@ -411,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 * @@ -428,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); } @@ -482,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 * @@ -521,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 @@ -531,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) @@ -543,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) @@ -600,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 = G_MUTEX_INIT; -#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)) @@ -617,8 +566,8 @@ profiler_log (ProfilerJob job, 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); @@ -686,7 +635,6 @@ profile_print_locked (guint *local_data, /** * g_mem_profile: - * @void: * * Outputs a summary of memory usage. * @@ -703,14 +651,11 @@ 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); local_allocs = profile_allocs; @@ -749,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) { @@ -787,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) { @@ -826,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. */ @@ -851,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 */ { @@ -868,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) { @@ -909,45 +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(); -}