about summary refs log tree commit diff
path: root/malloc
diff options
context:
space:
mode:
Diffstat (limited to 'malloc')
-rw-r--r--malloc/arena.c81
-rw-r--r--malloc/hooks.c26
-rw-r--r--malloc/malloc.c11
3 files changed, 111 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;
diff --git a/malloc/hooks.c b/malloc/hooks.c
index 7643e36714..0bd3e2a9ca 100644
--- a/malloc/hooks.c
+++ b/malloc/hooks.c
@@ -395,6 +395,17 @@ memalign_check(alignment, bytes, caller)
 
 #ifndef NO_THREADS
 
+# ifdef _LIBC
+#  if USE___THREAD || (defined USE_TLS && !defined SHARED)
+    /* These routines are never needed in this configuration.  */
+#   define NO_STARTER
+#  endif
+# endif
+
+# ifdef NO_STARTER
+#  undef NO_STARTER
+# else
+
 /* The following hooks are used when the global initialization in
    ptmalloc_init() hasn't completed yet. */
 
@@ -412,6 +423,20 @@ malloc_starter(sz, caller) size_t sz; const Void_t *caller;
   return victim ? BOUNDED_N(victim, sz) : 0;
 }
 
+static Void_t*
+#if __STD_C
+memalign_starter(size_t align, size_t sz, const Void_t *caller)
+#else
+memalign_starter(align, sz, caller) size_t align, sz; const Void_t *caller;
+#endif
+{
+  Void_t* victim;
+
+  victim = _int_memalign(&main_arena, align, sz);
+
+  return victim ? BOUNDED_N(victim, sz) : 0;
+}
+
 static void
 #if __STD_C
 free_starter(Void_t* mem, const Void_t *caller)
@@ -432,6 +457,7 @@ free_starter(mem, caller) Void_t* mem; const Void_t *caller;
   _int_free(&main_arena, mem);
 }
 
+# endif	/* !defiend NO_STARTER */
 #endif /* NO_THREADS */
 
 
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 757e65a37f..36a244dad7 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1498,8 +1498,19 @@ static Void_t*   realloc_check(Void_t* oldmem, size_t bytes,
 static Void_t*   memalign_check(size_t alignment, size_t bytes,
 				const Void_t *caller);
 #ifndef NO_THREADS
+# ifdef _LIBC
+#  if USE___THREAD || (defined USE_TLS && !defined SHARED)
+    /* These routines are never needed in this configuration.  */
+#   define NO_STARTER
+#  endif
+# endif
+# ifdef NO_STARTER
+#  undef NO_STARTER
+# else
 static Void_t*   malloc_starter(size_t sz, const Void_t *caller);
+static Void_t*   memalign_starter(size_t aln, size_t sz, const Void_t *caller);
 static void      free_starter(Void_t* mem, const Void_t *caller);
+# endif
 static Void_t*   malloc_atfork(size_t sz, const Void_t *caller);
 static void      free_atfork(Void_t* mem, const Void_t *caller);
 #endif