mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-25 06:20:06 +00:00
malloc: Decorate malloc maps
Add anonymous mmap annotations on loader malloc, malloc when it allocates memory with mmap, and on malloc arena. The /proc/self/maps will now print: [anon: glibc: malloc arena] [anon: glibc: malloc] [anon: glibc: loader malloc] On arena allocation, glibc annotates only the read/write mapping. Checked on x86_64-linux-gnu and aarch64-linux-gnu. Reviewed-by: DJ Delorie <dj@redhat.com>
This commit is contained in:
parent
6afce56c19
commit
fee9e40a8d
@ -2983,3 +2983,7 @@ $(objpfx)tst-dlclose-lazy.out: \
|
|||||||
$(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so
|
$(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so
|
||||||
|
|
||||||
$(objpfx)tst-decorate-maps: $(shared-thread-library)
|
$(objpfx)tst-decorate-maps: $(shared-thread-library)
|
||||||
|
|
||||||
|
tst-decorate-maps-ENV = \
|
||||||
|
GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024
|
||||||
|
tst-decorate-maps-ARGS = 8
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ldsodefs.h>
|
#include <ldsodefs.h>
|
||||||
#include <malloc/malloc-internal.h>
|
#include <malloc/malloc-internal.h>
|
||||||
|
#include <setvmaname.h>
|
||||||
|
|
||||||
static void *alloc_ptr, *alloc_end, *alloc_last_block;
|
static void *alloc_ptr, *alloc_end, *alloc_last_block;
|
||||||
|
|
||||||
@ -60,6 +61,7 @@ __minimal_malloc (size_t n)
|
|||||||
MAP_ANON|MAP_PRIVATE, -1, 0);
|
MAP_ANON|MAP_PRIVATE, -1, 0);
|
||||||
if (page == MAP_FAILED)
|
if (page == MAP_FAILED)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
__set_vma_name (page, nup, " glibc: loader malloc");
|
||||||
if (page != alloc_end)
|
if (page != alloc_end)
|
||||||
alloc_ptr = page;
|
alloc_ptr = page;
|
||||||
alloc_end = page + nup;
|
alloc_end = page + nup;
|
||||||
|
@ -32,15 +32,21 @@
|
|||||||
|
|
||||||
static pthread_barrier_t b;
|
static pthread_barrier_t b;
|
||||||
|
|
||||||
|
static int expected_n_arenas;
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
tf (void *closure)
|
tf (void *closure)
|
||||||
{
|
{
|
||||||
|
void *p = xmalloc (1024);
|
||||||
|
|
||||||
/* Wait the thread startup, so thread stack is allocated. */
|
/* Wait the thread startup, so thread stack is allocated. */
|
||||||
xpthread_barrier_wait (&b);
|
xpthread_barrier_wait (&b);
|
||||||
|
|
||||||
/* Wait the test to read the process mapping. */
|
/* Wait the test to read the process mapping. */
|
||||||
xpthread_barrier_wait (&b);
|
xpthread_barrier_wait (&b);
|
||||||
|
|
||||||
|
free (p);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +54,9 @@ struct proc_maps_t
|
|||||||
{
|
{
|
||||||
int n_def_threads;
|
int n_def_threads;
|
||||||
int n_user_threads;
|
int n_user_threads;
|
||||||
|
int n_arenas;
|
||||||
|
int n_malloc_mmap;
|
||||||
|
int n_loader_malloc_mmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct proc_maps_t
|
static struct proc_maps_t
|
||||||
@ -69,6 +78,12 @@ read_proc_maps (void)
|
|||||||
r.n_def_threads++;
|
r.n_def_threads++;
|
||||||
else if (strstr (line, "[anon: glibc: pthread user stack:") != NULL)
|
else if (strstr (line, "[anon: glibc: pthread user stack:") != NULL)
|
||||||
r.n_user_threads++;
|
r.n_user_threads++;
|
||||||
|
else if (strstr (line, "[anon: glibc: malloc arena]") != NULL)
|
||||||
|
r.n_arenas++;
|
||||||
|
else if (strstr (line, "[anon: glibc: malloc]") != NULL)
|
||||||
|
r.n_malloc_mmap++;
|
||||||
|
else if (strstr (line, "[anon: glibc: loader malloc]") != NULL)
|
||||||
|
r.n_loader_malloc_mmap++;
|
||||||
}
|
}
|
||||||
free (line);
|
free (line);
|
||||||
xfclose (f);
|
xfclose (f);
|
||||||
@ -90,6 +105,9 @@ do_test_threads (bool set_guard)
|
|||||||
|
|
||||||
xpthread_barrier_init (&b, NULL, num_threads + 1);
|
xpthread_barrier_init (&b, NULL, num_threads + 1);
|
||||||
|
|
||||||
|
/* Issue a large malloc to trigger a mmap call. */
|
||||||
|
void *p = xmalloc (256 * 1024);
|
||||||
|
|
||||||
pthread_t thr[num_threads];
|
pthread_t thr[num_threads];
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -128,6 +146,10 @@ do_test_threads (bool set_guard)
|
|||||||
struct proc_maps_t r = read_proc_maps ();
|
struct proc_maps_t r = read_proc_maps ();
|
||||||
TEST_COMPARE (r.n_def_threads, num_def_threads);
|
TEST_COMPARE (r.n_def_threads, num_def_threads);
|
||||||
TEST_COMPARE (r.n_user_threads, num_user_threads);
|
TEST_COMPARE (r.n_user_threads, num_user_threads);
|
||||||
|
TEST_COMPARE (r.n_arenas, expected_n_arenas);
|
||||||
|
TEST_COMPARE (r.n_malloc_mmap, 1);
|
||||||
|
/* On some architectures the loader might use more than one page. */
|
||||||
|
TEST_VERIFY (r.n_loader_malloc_mmap >= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let the threads finish. */
|
/* Let the threads finish. */
|
||||||
@ -140,9 +162,23 @@ do_test_threads (bool set_guard)
|
|||||||
struct proc_maps_t r = read_proc_maps ();
|
struct proc_maps_t r = read_proc_maps ();
|
||||||
TEST_COMPARE (r.n_def_threads, 0);
|
TEST_COMPARE (r.n_def_threads, 0);
|
||||||
TEST_COMPARE (r.n_user_threads, 0);
|
TEST_COMPARE (r.n_user_threads, 0);
|
||||||
|
TEST_COMPARE (r.n_arenas, expected_n_arenas);
|
||||||
|
TEST_COMPARE (r.n_malloc_mmap, 1);
|
||||||
|
TEST_VERIFY (r.n_loader_malloc_mmap >= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_prepare (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
TEST_VERIFY_EXIT (argc == 2);
|
||||||
|
expected_n_arenas = strtol (argv[1], NULL, 10);
|
||||||
|
expected_n_arenas = expected_n_arenas - 1;
|
||||||
|
}
|
||||||
|
#define PREPARE do_prepare
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_test (void)
|
do_test (void)
|
||||||
{
|
{
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
not, see <https://www.gnu.org/licenses/>. */
|
not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <setvmaname.h>
|
||||||
|
|
||||||
#define TUNABLE_NAMESPACE malloc
|
#define TUNABLE_NAMESPACE malloc
|
||||||
#include <elf/dl-tunables.h>
|
#include <elf/dl-tunables.h>
|
||||||
@ -436,6 +437,9 @@ alloc_new_heap (size_t size, size_t top_pad, size_t pagesize,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Only considere the actual usable range. */
|
||||||
|
__set_vma_name (p2, size, " glibc: malloc arena");
|
||||||
|
|
||||||
madvise_thp (p2, size);
|
madvise_thp (p2, size);
|
||||||
|
|
||||||
h = (heap_info *) p2;
|
h = (heap_info *) p2;
|
||||||
|
@ -218,6 +218,7 @@
|
|||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
|
|
||||||
#include <ldsodefs.h>
|
#include <ldsodefs.h>
|
||||||
|
#include <setvmaname.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h> /* needed for malloc_stats */
|
#include <stdio.h> /* needed for malloc_stats */
|
||||||
@ -2428,6 +2429,8 @@ sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av)
|
|||||||
madvise_thp (mm, size);
|
madvise_thp (mm, size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
__set_vma_name (mm, size, " glibc: malloc");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The offset to the start of the mmapped region is stored in the prev_size
|
The offset to the start of the mmapped region is stored in the prev_size
|
||||||
field of the chunk. This allows us to adjust returned start address to
|
field of the chunk. This allows us to adjust returned start address to
|
||||||
@ -2513,6 +2516,8 @@ sysmalloc_mmap_fallback (long int *s, INTERNAL_SIZE_T nb,
|
|||||||
madvise_thp (mbrk, size);
|
madvise_thp (mbrk, size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
__set_vma_name (mbrk, size, " glibc: malloc");
|
||||||
|
|
||||||
/* Record that we no longer have a contiguous sbrk region. After the first
|
/* Record that we no longer have a contiguous sbrk region. After the first
|
||||||
time mmap is used as backup, we do not ever rely on contiguous space
|
time mmap is used as backup, we do not ever rely on contiguous space
|
||||||
since this could incorrectly bridge regions. */
|
since this could incorrectly bridge regions. */
|
||||||
|
@ -699,6 +699,10 @@ tst-audit-threads-ENV = LD_AUDIT=$(objpfx)tst-audit-threads-mod1.so
|
|||||||
tst-setuid1-static-ENV = \
|
tst-setuid1-static-ENV = \
|
||||||
LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx)elf:$(common-objpfx)nss
|
LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx)elf:$(common-objpfx)nss
|
||||||
|
|
||||||
|
tst-pthread-proc-maps-ENV = \
|
||||||
|
GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024
|
||||||
|
tst-pthread-proc-maps-ARGS = 8
|
||||||
|
|
||||||
# The tests here better do not run in parallel.
|
# The tests here better do not run in parallel.
|
||||||
ifeq ($(run-built-tests),yes)
|
ifeq ($(run-built-tests),yes)
|
||||||
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
|
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
|
||||||
|
Loading…
Reference in New Issue
Block a user