/* Malloc implementation for multiple threads without lock contention.
- Copyright (C) 2001-2017 Free Software Foundation, Inc.
+ Copyright (C) 2001-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Wolfram Gloger <wg@malloc.de>, 2001.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
- not, see <http://www.gnu.org/licenses/>. */
+ not, see <https://www.gnu.org/licenses/>. */
#include <stdbool.h>
} while (0)
#define arena_lock(ptr, size) do { \
- if (ptr && !arena_is_corrupt (ptr)) \
+ if (ptr) \
__libc_lock_lock (ptr->mutex); \
else \
ptr = arena_get2 ((size), NULL); \
subsystem. */
void
-internal_function
__malloc_fork_lock_parent (void)
{
if (__malloc_initialized < 1)
}
void
-internal_function
__malloc_fork_unlock_parent (void)
{
if (__malloc_initialized < 1)
}
void
-internal_function
__malloc_fork_unlock_child (void)
{
if (__malloc_initialized < 1)
}
#if HAVE_TUNABLES
-static inline int do_set_mallopt_check (int32_t value);
void
-DL_TUNABLE_CALLBACK (set_mallopt_check) (void *valp)
+TUNABLE_CALLBACK (set_mallopt_check) (tunable_val_t *valp)
{
- int32_t value = *(int32_t *) valp;
- do_set_mallopt_check (value);
- if (check_action != 0)
+ int32_t value = (int32_t) valp->numval;
+ if (value != 0)
__malloc_check_init ();
}
-# define DL_TUNABLE_CALLBACK_FNDECL(__name, __type) \
+# define TUNABLE_CALLBACK_FNDECL(__name, __type) \
static inline int do_ ## __name (__type value); \
void \
-DL_TUNABLE_CALLBACK (__name) (void *valp) \
+TUNABLE_CALLBACK (__name) (tunable_val_t *valp) \
{ \
- __type value = *(__type *) valp; \
+ __type value = (__type) (valp)->numval; \
do_ ## __name (value); \
}
-DL_TUNABLE_CALLBACK_FNDECL (set_mmap_threshold, size_t)
-DL_TUNABLE_CALLBACK_FNDECL (set_mmaps_max, int32_t)
-DL_TUNABLE_CALLBACK_FNDECL (set_top_pad, size_t)
-DL_TUNABLE_CALLBACK_FNDECL (set_perturb_byte, int32_t)
-DL_TUNABLE_CALLBACK_FNDECL (set_trim_threshold, size_t)
-DL_TUNABLE_CALLBACK_FNDECL (set_arena_max, size_t)
-DL_TUNABLE_CALLBACK_FNDECL (set_arena_test, size_t)
+TUNABLE_CALLBACK_FNDECL (set_mmap_threshold, size_t)
+TUNABLE_CALLBACK_FNDECL (set_mmaps_max, int32_t)
+TUNABLE_CALLBACK_FNDECL (set_top_pad, size_t)
+TUNABLE_CALLBACK_FNDECL (set_perturb_byte, int32_t)
+TUNABLE_CALLBACK_FNDECL (set_trim_threshold, size_t)
+TUNABLE_CALLBACK_FNDECL (set_arena_max, size_t)
+TUNABLE_CALLBACK_FNDECL (set_arena_test, size_t)
+#if USE_TCACHE
+TUNABLE_CALLBACK_FNDECL (set_tcache_max, size_t)
+TUNABLE_CALLBACK_FNDECL (set_tcache_count, size_t)
+TUNABLE_CALLBACK_FNDECL (set_tcache_unsorted_limit, size_t)
+#endif
+TUNABLE_CALLBACK_FNDECL (set_mxfast, size_t)
#else
/* Initialization routine. */
#include <string.h>
extern char **_environ;
static char *
-internal_function
next_env_entry (char ***position)
{
char **current = *position;
thread_arena = &main_arena;
+ malloc_init_state (&main_arena);
+
#if HAVE_TUNABLES
- /* Ensure initialization/consolidation and do it under a lock so that a
- thread attempting to use the arena in parallel waits on us till we
- finish. */
- __libc_lock_lock (main_arena.mutex);
- malloc_consolidate (&main_arena);
-
- TUNABLE_SET_VAL_WITH_CALLBACK (check, NULL, set_mallopt_check);
- TUNABLE_SET_VAL_WITH_CALLBACK (top_pad, NULL, set_top_pad);
- TUNABLE_SET_VAL_WITH_CALLBACK (perturb, NULL, set_perturb_byte);
- TUNABLE_SET_VAL_WITH_CALLBACK (mmap_threshold, NULL, set_mmap_threshold);
- TUNABLE_SET_VAL_WITH_CALLBACK (trim_threshold, NULL, set_trim_threshold);
- TUNABLE_SET_VAL_WITH_CALLBACK (mmap_max, NULL, set_mmaps_max);
- TUNABLE_SET_VAL_WITH_CALLBACK (arena_max, NULL, set_arena_max);
- TUNABLE_SET_VAL_WITH_CALLBACK (arena_test, NULL, set_arena_test);
- __libc_lock_unlock (main_arena.mutex);
+ TUNABLE_GET (check, int32_t, TUNABLE_CALLBACK (set_mallopt_check));
+ TUNABLE_GET (top_pad, size_t, TUNABLE_CALLBACK (set_top_pad));
+ TUNABLE_GET (perturb, int32_t, TUNABLE_CALLBACK (set_perturb_byte));
+ TUNABLE_GET (mmap_threshold, size_t, TUNABLE_CALLBACK (set_mmap_threshold));
+ TUNABLE_GET (trim_threshold, size_t, TUNABLE_CALLBACK (set_trim_threshold));
+ TUNABLE_GET (mmap_max, int32_t, TUNABLE_CALLBACK (set_mmaps_max));
+ TUNABLE_GET (arena_max, size_t, TUNABLE_CALLBACK (set_arena_max));
+ TUNABLE_GET (arena_test, size_t, TUNABLE_CALLBACK (set_arena_test));
+# if USE_TCACHE
+ TUNABLE_GET (tcache_max, size_t, TUNABLE_CALLBACK (set_tcache_max));
+ TUNABLE_GET (tcache_count, size_t, TUNABLE_CALLBACK (set_tcache_count));
+ TUNABLE_GET (tcache_unsorted_limit, size_t,
+ TUNABLE_CALLBACK (set_tcache_unsorted_limit));
+# endif
+ TUNABLE_GET (mxfast, size_t, TUNABLE_CALLBACK (set_mxfast));
#else
const char *s = NULL;
if (__glibc_likely (_environ != NULL))
}
}
}
- if (s && s[0])
- {
- __libc_mallopt (M_CHECK_ACTION, (int) (s[0] - '0'));
- if (check_action != 0)
- __malloc_check_init ();
- }
+ if (s && s[0] != '\0' && s[0] != '0')
+ __malloc_check_init ();
#endif
#if HAVE_MALLOC_INIT_HOOK
of the page size. */
static heap_info *
-internal_function
new_heap (size_t size, size_t top_pad)
{
size_t pagesize = GLRO (dl_pagesize);
} while (0)
static int
-internal_function
heap_trim (heap_info *heap, size_t pad)
{
mstate ar_ptr = heap->ar_ptr;
unsigned long pagesz = GLRO (dl_pagesize);
- mchunkptr top_chunk = top (ar_ptr), p, bck, fwd;
+ mchunkptr top_chunk = top (ar_ptr), p;
heap_info *prev_heap;
long new_size, top_size, top_area, extra, prev_size, misalign;
if (!prev_inuse (p)) /* consolidate backward */
{
p = prev_chunk (p);
- unlink (ar_ptr, p, bck, fwd);
+ unlink_chunk (ar_ptr, p);
}
assert (((unsigned long) ((char *) p + new_size) & (pagesz - 1)) == 0);
assert (((char *) p + new_size) == ((char *) heap + heap->size));
result = next_to_use;
do
{
- if (!arena_is_corrupt (result) && !__libc_lock_trylock (result->mutex))
+ if (!__libc_lock_trylock (result->mutex))
goto out;
/* FIXME: This is a data race, see _int_new_arena. */
if (result == avoid_arena)
result = result->next;
- /* Make sure that the arena we get is not corrupted. */
- mstate begin = result;
- while (arena_is_corrupt (result) || result == avoid_arena)
- {
- result = result->next;
- if (result == begin)
- /* We looped around the arena list. We could not find any
- arena that was either not corrupted or not the one we
- wanted to avoid. */
- return NULL;
- }
-
/* No arena available without contention. Wait for the next in line. */
LIBC_PROBE (memory_arena_reuse_wait, 3, &result->mutex, result, avoid_arena);
__libc_lock_lock (result->mutex);
}
static mstate
-internal_function
arena_get2 (size_t size, mstate avoid_arena)
{
mstate a;
if (ar_ptr != &main_arena)
{
__libc_lock_unlock (ar_ptr->mutex);
- /* Don't touch the main arena if it is corrupt. */
- if (arena_is_corrupt (&main_arena))
- return NULL;
-
ar_ptr = &main_arena;
__libc_lock_lock (ar_ptr->mutex);
}
return ar_ptr;
}
-static void __attribute__ ((section ("__libc_thread_freeres_fn")))
-arena_thread_freeres (void)
+void
+__malloc_arena_thread_freeres (void)
{
+ /* Shut down the thread cache first. This could deallocate data for
+ the thread arena, so do this before we put the arena on the free
+ list. */
+ tcache_thread_shutdown ();
+
mstate a = thread_arena;
thread_arena = NULL;
__libc_lock_unlock (free_list_lock);
}
}
-text_set_element (__libc_thread_subfreeres, arena_thread_freeres);
/*
* Local variables: