aboutsummaryrefslogtreecommitdiff
path: root/malloc/arena.c
diff options
context:
space:
mode:
Diffstat (limited to 'malloc/arena.c')
-rw-r--r--malloc/arena.c81
1 files changed, 74 insertions, 7 deletions
diff --git a/malloc/arena.c b/malloc/arena.c
index 090e3c1dd6..27d2d9e058 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -136,6 +136,11 @@ int __malloc_initialized = -1;
static __malloc_ptr_t (*save_malloc_hook) __MALLOC_P ((size_t __size,
__const __malloc_ptr_t));
+# if !defined _LIBC || !defined USE_TLS || (defined SHARED && !USE___THREAD)
+static __malloc_ptr_t (*save_memalign_hook) __MALLOC_P ((size_t __align,
+ size_t __size,
+ __const __malloc_ptr_t));
+# endif
static void (*save_free_hook) __MALLOC_P ((__malloc_ptr_t __ptr,
__const __malloc_ptr_t));
static Void_t* save_arena;
@@ -322,6 +327,51 @@ next_env_entry (char ***position)
}
#endif /* _LIBC */
+/* Set up basic state so that _int_malloc et al can work. */
+static void
+ptmalloc_init_minimal __MALLOC_P((void))
+{
+#if DEFAULT_TOP_PAD != 0
+ mp_.top_pad = DEFAULT_TOP_PAD;
+#endif
+ mp_.n_mmaps_max = DEFAULT_MMAP_MAX;
+ mp_.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
+ mp_.trim_threshold = DEFAULT_TRIM_THRESHOLD;
+ mp_.pagesize = malloc_getpagesize;
+}
+
+#ifdef _LIBC
+# if defined SHARED && defined USE_TLS && !USE___THREAD
+# include <stdbool.h>
+
+/* This is called by __pthread_initialize_minimal when it needs to use
+ malloc to set up the TLS state. We cannot do the full work of
+ ptmalloc_init (below) until __pthread_initialize_minimal has finished,
+ so it has to switch to using the special startup-time hooks while doing
+ those allocations. */
+void
+__libc_malloc_pthread_startup (bool first_time)
+{
+ if (first_time)
+ {
+ ptmalloc_init_minimal ();
+ save_malloc_hook = __malloc_hook;
+ save_memalign_hook = __memalign_hook;
+ save_free_hook = __free_hook;
+ __malloc_hook = malloc_starter;
+ __memalign_hook = memalign_starter;
+ __free_hook = free_starter;
+ }
+ else
+ {
+ __malloc_hook = save_malloc_hook;
+ __memalign_hook = save_memalign_hook;
+ __free_hook = save_free_hook;
+ }
+}
+# endif
+#endif
+
static void
ptmalloc_init __MALLOC_P((void))
{
@@ -335,25 +385,37 @@ ptmalloc_init __MALLOC_P((void))
if(__malloc_initialized >= 0) return;
__malloc_initialized = 0;
- mp_.top_pad = DEFAULT_TOP_PAD;
- mp_.n_mmaps_max = DEFAULT_MMAP_MAX;
- mp_.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
- mp_.trim_threshold = DEFAULT_TRIM_THRESHOLD;
- mp_.pagesize = malloc_getpagesize;
+#ifdef _LIBC
+# if defined SHARED && defined USE_TLS && !USE___THREAD
+ /* ptmalloc_init_minimal may already have been called via
+ __libc_malloc_pthread_startup, above. */
+ if (mp_.pagesize == 0)
+# endif
+#endif
+ ptmalloc_init_minimal();
#ifndef NO_THREADS
+# if defined _LIBC && defined USE_TLS
+ /* We know __pthread_initialize_minimal has already been called,
+ and that is enough. */
+# define NO_STARTER
+# endif
+# ifndef NO_STARTER
/* With some threads implementations, creating thread-specific data
or initializing a mutex may call malloc() itself. Provide a
simple starter version (realloc() won't work). */
save_malloc_hook = __malloc_hook;
+ save_memalign_hook = __memalign_hook;
save_free_hook = __free_hook;
__malloc_hook = malloc_starter;
+ __memalign_hook = memalign_starter;
__free_hook = free_starter;
-#ifdef _LIBC
+# ifdef _LIBC
/* Initialize the pthreads interface. */
if (__pthread_initialize != NULL)
__pthread_initialize();
-#endif
+# endif /* !defined _LIBC */
+# endif /* !defined NO_STARTER */
#endif /* !defined NO_THREADS */
mutex_init(&main_arena.mutex);
main_arena.next = &main_arena;
@@ -363,8 +425,13 @@ ptmalloc_init __MALLOC_P((void))
tsd_setspecific(arena_key, (Void_t *)&main_arena);
thread_atfork(ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2);
#ifndef NO_THREADS
+# ifndef NO_STARTER
__malloc_hook = save_malloc_hook;
+ __memalign_hook = save_memalign_hook;
__free_hook = save_free_hook;
+# else
+# undef NO_STARTER
+# endif
#endif
#ifdef _LIBC
secure = __libc_enable_secure;