This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: malloc probes for Systemtap
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: Andreas Jaeger <aj at suse dot com>, Roland McGrath <roland at hack dot frob dot com>
- Cc: libc-alpha at sourceware dot org
- Date: Tue, 02 Oct 2012 03:07:32 -0300
- Subject: Re: malloc probes for Systemtap
- References: <ork3w94at9.fsf@livre.localdomain> <20407326.zUUZoqzhOz@byrd>
On Sep 5, 2012, Andreas Jaeger <aj@suse.com> wrote:
> On Tuesday, September 04, 2012 20:39:46 Alexandre Oliva wrote:
>> I was asked to introduce probes in malloc to aid in debugging cases in
>> which our memory allocation code performs poorly.
>>
>> I've grouped the probes in separate patches, in which the probes are
>> logically connected. I'd appreciate feedback on the soundness of the
>> probe set: did I miss anything in these groups that is worth probing?
>> is any of the probes uselessly redundant? are they desirable at all?
>>
>> Are they ok for master? Do the docs look reasonable, description and
>> formatting-wise? (The only other probe docs I found in glibc were in
>> elf/rtld-debugger-interface.txt)
>>
>> The version of the patchset I pushed to lxoliva/malloc-probes-bz742038
>> depends on Siddhesh's patch that introduces get_another_arena.
>> Although I've just suggested changes to it, I decided to post the
>> patchset as it is, since most of it applies cleanly anyway, and
>> regardless of adjustments needed for Siddhesh's patch, I suspect we
>> might go through more than one round of review before my patchset can
>> go in anyway.
> Roland is the systemtap expert and I'd like him to review this
Roland, you got any comments on this?
Here's the updated patchset.
Add first set of malloc probes.
From: Alexandre Oliva <aoliva@redhat.com>
for ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* malloc/malloc.c: Include stap-probe.h.
(__libc_mallopt): Add mallopt probe.
* malloc/arena.c (_int_new_arena): Add malloc_arena_new probe.
* manual/malloc.texi: Document them.
---
malloc/arena.c | 1 +
malloc/malloc.c | 4 ++++
manual/memory.texi | 27 +++++++++++++++++++++++++++
3 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/malloc/arena.c b/malloc/arena.c
index b209e3b..6f012d6 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -741,6 +741,7 @@ _int_new_arena(size_t size)
top(a) = (mchunkptr)ptr;
set_head(top(a), (((char*)h + h->size) - ptr) | PREV_INUSE);
+ LIBC_PROBE (malloc_arena_new, 2, a, size);
tsd_setspecific(arena_key, (void *)a);
mutex_init(&a->mutex);
(void)mutex_lock(&a->mutex);
diff --git a/malloc/malloc.c b/malloc/malloc.c
index ca1d73f..236ae30 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1882,6 +1882,8 @@ static int perturb_byte;
#define free_perturb(p, n) memset (p, perturb_byte & 0xff, n)
+#include <stap-probe.h>
+
/* ------------------- Support for multiple arenas -------------------- */
#include "arena.c"
@@ -4681,6 +4683,8 @@ int __libc_mallopt(int param_number, int value)
/* Ensure initialization/consolidation */
malloc_consolidate(av);
+ LIBC_PROBE (mallopt, 2, param_number, value);
+
switch(param_number) {
case M_MXFAST:
if (value >= 0 && value <= MAX_FAST_SIZE) {
diff --git a/manual/memory.texi b/manual/memory.texi
index fba3a2c..714f4ad 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -286,6 +286,8 @@ any time (or never).
* Heap Consistency Checking:: Automatic checking for errors.
* Hooks for Malloc:: You can use these hooks for debugging
programs that use @code{malloc}.
+* Probes for Malloc:: You can use these probes to monitor some
+ internal behavior of @code{malloc}.
* Statistics of Malloc:: Getting information about how much
memory your program is using.
* Summary of Malloc:: Summary of @code{malloc} and related functions.
@@ -1019,6 +1021,31 @@ installing such hooks.
@c __morecore, __after_morecore_hook are undocumented
@c It's not clear whether to document them.
+@node Probes for Malloc
+@subsubsection Memory Allocation Probes
+@cindex allocation probes, for @code{malloc}
+
+These are nearly-zero-overhead probes available for monitoring internal
+@code{malloc} behavior, using Systemtap process marks with the
+@code{libc} provider. The probes assume a reasonable knowledge of the
+@code{malloc} implementation.
+
+@deftp Probe malloc_arena_new (void *@var{$arg1}, size_t @var{$arg2})
+This probe is hit when @code{malloc} allocated and initialized an
+additional allocation arena (not the main arena), but before it is
+assigned to the running thread and inserted in the internal linked list
+of arenas. The arena's @code{malloc_state} internal data structure is
+located at @var{$arg1}, within a newly-allocated heap big enough to hold
+at least @var{$arg2} bytes.
+@end deftp
+
+@deftp Probe mallopt (int @var{$arg1}, int @var{$arg2})
+This probe is hit when function @code{mallopt} is called to change
+@code{malloc} internal configuration parameters, before any change to
+the parameters is made. The arguments @var{$arg1} and @var{$arg2} are
+the ones passed to the @code{mallopt} function.
+@end deftp
+
@node Statistics of Malloc
@subsubsection Statistics for Memory Allocation with @code{malloc}
Add probes for all changes to malloc options.
From: Alexandre Oliva <aoliva@redhat.com>
for ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* malloc/malloc.c (__libc_free): Add
mallopt_free_dyn_thresholds probe.
(__libc_mallopt): Add multiple mallopt probes.
* manual/malloc.texi: Document them.
---
malloc/malloc.c | 30 +++++++++++++++++---
manual/memory.texi | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 103 insertions(+), 5 deletions(-)
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 236ae30..1739806 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -2900,6 +2900,8 @@ __libc_free(void* mem)
{
mp_.mmap_threshold = chunksize (p);
mp_.trim_threshold = 2 * mp_.mmap_threshold;
+ LIBC_PROBE (mallopt_free_dyn_thresholds, 2,
+ mp_.mmap_threshold, mp_.trim_threshold);
}
munmap_chunk(p);
return;
@@ -4687,19 +4689,25 @@ int __libc_mallopt(int param_number, int value)
switch(param_number) {
case M_MXFAST:
- if (value >= 0 && value <= MAX_FAST_SIZE) {
- set_max_fast(value);
- }
+ if (value >= 0 && value <= MAX_FAST_SIZE)
+ {
+ LIBC_PROBE (mallopt_mxfast, 2, value, get_max_fast ());
+ set_max_fast(value);
+ }
else
res = 0;
break;
case M_TRIM_THRESHOLD:
+ LIBC_PROBE (mallopt_trim_threshold, 3, value,
+ mp_.trim_threshold, mp_.no_dyn_threshold);
mp_.trim_threshold = value;
mp_.no_dyn_threshold = 1;
break;
case M_TOP_PAD:
+ LIBC_PROBE (mallopt_top_pad, 3, value,
+ mp_.top_pad, mp_.no_dyn_threshold);
mp_.top_pad = value;
mp_.no_dyn_threshold = 1;
break;
@@ -4710,33 +4718,45 @@ int __libc_mallopt(int param_number, int value)
res = 0;
else
{
+ LIBC_PROBE (mallopt_mmap_threshold, 3, value,
+ mp_.mmap_threshold, mp_.no_dyn_threshold);
mp_.mmap_threshold = value;
mp_.no_dyn_threshold = 1;
}
break;
case M_MMAP_MAX:
+ LIBC_PROBE (mallopt_mmap_max, 3, value,
+ mp_.mmap_threshold, mp_.no_dyn_threshold);
mp_.n_mmaps_max = value;
mp_.no_dyn_threshold = 1;
break;
case M_CHECK_ACTION:
+ LIBC_PROBE (mallopt_check_action, 2, value, check_action);
check_action = value;
break;
case M_PERTURB:
+ LIBC_PROBE (mallopt_perturb, 2, value, perturb_byte);
perturb_byte = value;
break;
#ifdef PER_THREAD
case M_ARENA_TEST:
if (value > 0)
- mp_.arena_test = value;
+ {
+ LIBC_PROBE (mallopt_arena_test, 2, value, mp_.arena_test);
+ mp_.arena_test = value;
+ }
break;
case M_ARENA_MAX:
if (value > 0)
- mp_.arena_max = value;
+ {
+ LIBC_PROBE (mallopt_arena_max, 2, value, mp_.arena_max);
+ mp_.arena_max = value;
+ }
break;
#endif
}
diff --git a/manual/memory.texi b/manual/memory.texi
index 714f4ad..dec957f8 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -1046,6 +1046,84 @@ the parameters is made. The arguments @var{$arg1} and @var{$arg2} are
the ones passed to the @code{mallopt} function.
@end deftp
+@deftp Probe mallopt_mxfast (int @var{$arg1}, int @var{$arg2})
+This probe is hit shortly after the @code{mallopt} probe, when the
+parameter to be changed is @code{M_MXFAST}, and the requested value is
+in an acceptable range. Argument @var{$arg1} is the requested value,
+and @var{$arg2} is the previous value of this @code{malloc} parameter.
+@end deftp
+
+@deftp Probe mallopt_trim_threshold (int @var{$arg1}, int @var{$arg2}, int @var{$arg3})
+This probe is hit shortly after the @code{mallopt} probe, when the
+parameter to be changed is @code{M_TRIM_THRESHOLD}. Argument
+@var{$arg1} is the requested value, @var{$arg2} is the previous value of
+this @code{malloc} parameter, and @var{$arg3} is nonzero if dynamic
+threshold adjustments was already disabled.
+@end deftp
+
+@deftp Probe mallopt_top_pad (int @var{$arg1}, int @var{$arg2}, int @var{$arg3})
+This probe is hit shortly after the @code{mallopt} probe, when the
+parameter to be changed is @code{M_TOP_PAD}. Argument @var{$arg1} is
+the requested value, @var{$arg2} is the previous value of this
+@code{malloc} parameter, and @var{$arg3} is nonzero if dynamic threshold
+adjustments was already disabled.
+@end deftp
+
+@deftp Probe mallopt_mmap_threshold (int @var{$arg1}, int @var{$arg2}, int @var{$arg3})
+This probe is hit shortly after the @code{mallopt} probe, when the
+parameter to be changed is @code{M_MMAP_THRESHOLD}, and the requested
+value is in an acceptable range. Argument @var{$arg1} is the requested
+value, @var{$arg2} is the previous value of this @code{malloc}
+parameter, and @var{$arg3} is nonzero if dynamic threshold adjustments
+was already disabled.
+@end deftp
+
+@deftp Probe mallopt_mmap_max (int @var{$arg1}, int @var{$arg2}, int @var{$arg3})
+This probe is hit shortly after the @code{mallopt} probe, when the
+parameter to be changed is @code{M_MMAP_MAX}. Argument @var{$arg1} is
+the requested value, @var{$arg2} is the previous value of this
+@code{malloc} parameter, and @var{$arg3} is nonzero if dynamic threshold
+adjustments was already disabled.
+@end deftp
+
+@deftp Probe mallopt_check_action (int @var{$arg1}, int @var{$arg2})
+This probe is hit shortly after the @code{mallopt} probe, when the
+parameter to be changed is @code{M_CHECK_ACTION}. Argument @var{$arg1}
+is the requested value, and @var{$arg2} is the previous value of this
+@code{malloc} parameter.
+@end deftp
+
+@deftp Probe mallopt_perturb (int @var{$arg1}, int @var{$arg2})
+This probe is hit shortly after the @code{mallopt} probe, when the
+parameter to be changed is @code{M_PERTURB}. Argument @var{$arg1} is
+the requested value, and @var{$arg2} is the previous value of this
+@code{malloc} parameter.
+@end deftp
+
+@deftp Probe mallopt_arena_test (int @var{$arg1}, int @var{$arg2})
+This probe is hit shortly after the @code{mallopt} probe, when the
+parameter to be changed is @code{M_ARENA_TEST}, and the requested value
+is in an acceptable range. Argument @var{$arg1} is the requested value,
+and @var{$arg2} is the previous value of this @code{malloc} parameter.
+This probe is not available if @code{malloc} is compiled without
+per-thread arenas (@samp{-DPER_THREAD}).
+@end deftp
+
+@deftp Probe mallopt_arena_max (int @var{$arg1}, int @var{$arg2})
+This probe is hit shortly after the @code{mallopt} probe, when the
+parameter to be changed is @code{M_ARENA_MAX}, and the requested value
+is in an acceptable range. Argument @var{$arg1} is the requested value,
+and @var{$arg2} is the previous value of this @code{malloc} parameter.
+This probe is not available if @code{malloc} is compiled without
+per-thread arenas (@samp{-DPER_THREAD}).
+@end deftp
+
+@deftp Probe mallopt_free_dyn_thresholds (int @var{$arg1}, int @var{$arg2})
+This probe is hit when function @code{free} decides to adjust the
+dynamic brk/mmap thresholds. Argument @var{$arg1} and @var{$arg2} are
+the adjusted mmap and trim thresholds, respectively.
+@end deftp
+
@node Statistics of Malloc
@subsubsection Statistics for Memory Allocation with @code{malloc}
Add probes for malloc arena changes.
From: Alexandre Oliva <aoliva@redhat.com>
for ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* malloc/arena.c (get_free_list): Add probe
malloc_arena_reuse_free_list.
(reused_arena) [PER_THREAD]: Add probes malloc_arena_reuse_wait
and malloc_arena_reuse.
(arena_get2) [!PER_THREAD]: Likewise.
* malloc/malloc.c (__libc_realloc) [!PER_THREAD]: Add probe
malloc_arena_reuse_realloc.
* manual/malloc.texi: Document them.
---
malloc/arena.c | 5 ++++
malloc/malloc.c | 1 +
manual/memory.texi | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/malloc/arena.c b/malloc/arena.c
index 6f012d6..fa5bf9c 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -780,6 +780,7 @@ get_free_list (void)
if (result != NULL)
{
+ LIBC_PROBE (malloc_arena_reuse_free_list, 1, result);
(void)mutex_lock(&result->mutex);
tsd_setspecific(arena_key, (void *)result);
THREAD_STAT(++(result->stat_lock_loop));
@@ -816,9 +817,11 @@ reused_arena (mstate avoid_arena)
result = result->next;
/* No arena available. Wait for the next in line. */
+ LIBC_PROBE (malloc_arena_reuse_wait, 3, &result->mutex, result, avoid_arena);
(void)mutex_lock(&result->mutex);
out:
+ LIBC_PROBE (malloc_arena_reuse, 2, result, avoid_arena);
tsd_setspecific(arena_key, (void *)result);
THREAD_STAT(++(result->stat_lock_loop));
next_to_use = result->next;
@@ -897,6 +900,7 @@ arena_get2(mstate a_tsd, size_t size, mstate avoid_arena)
if (retried)
(void)mutex_unlock(&list_lock);
THREAD_STAT(++(a->stat_lock_loop));
+ LIBC_PROBE (malloc_arena_reuse, 2, a, a_tsd);
tsd_setspecific(arena_key, (void *)a);
return a;
}
@@ -909,6 +913,7 @@ arena_get2(mstate a_tsd, size_t size, mstate avoid_arena)
locks. */
if(!retried && mutex_trylock(&list_lock)) {
/* We will block to not run in a busy loop. */
+ LIBC_PROBE (malloc_arena_reuse_wait, 3, &list_lock, NULL, a_tsd);
(void)mutex_lock(&list_lock);
/* Since we blocked there might be an arena available now. */
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 1739806..df69f7b 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -2981,6 +2981,7 @@ __libc_realloc(void* oldmem, size_t bytes)
#endif
#if !defined PER_THREAD
+ LIBC_PROBE (malloc_arena_reuse_realloc, 1, ar_ptr);
/* As in malloc(), remember this arena for the next allocation. */
tsd_setspecific(arena_key, (void *)ar_ptr);
#endif
diff --git a/manual/memory.texi b/manual/memory.texi
index dec957f8..9849bdc 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -1039,6 +1039,66 @@ located at @var{$arg1}, within a newly-allocated heap big enough to hold
at least @var{$arg2} bytes.
@end deftp
+@deftp Probe malloc_arena_reuse (void *@var{$arg1}, void *@var{$arg2})
+This probe is hit when @code{malloc} has just selected an existing arena
+to reuse, and (temporarily) reserved it for exclusive use. Argument
+@var{$arg1} is a pointer to the newly-selected arena, and @var{$arg2} is
+a pointer to the arena previously used by that thread.
+
+When per-thread arenas are enabled, this occurs within
+@code{reused_arena}, right after the mutex mentioned in probe
+@code{malloc_arena_reuse_wait} is acquired; argument @var{$arg1} will
+point to the same arena. In this configuration, this will usually only
+occur once per thread. The exception is when a thread first selected
+the main arena, but a subsequent allocation from it fails: then, and
+only then, may we switch to another arena to retry that allocations, and
+for further allocations within that thread.
+
+When per-thread arenas are disabled, this occurs within
+@code{arena_get2}, whenever the mutex for the previously-selected arena
+cannot be immediately acquired.
+@end deftp
+
+@deftp Probe malloc_arena_reuse_wait (void *@var{$arg1}, void *@var{$arg2}, void *@var{$arg3})
+This probe is hit when @code{malloc} is about to wait for an arena to
+become available for reuse. Argument @var{$arg1} holds a pointer to the
+mutex the thread is going to wait on, @var{$arg2} is a pointer to a
+newly-chosen arena to be reused, and @var{$arg3} is a pointer to the
+arena previously used by that thread.
+
+When per-thread arenas are enabled, this occurs within
+@code{reused_arena}, when a thread first tries to allocate memory or
+needs a retry after a failure to allocate from the main arena, there
+isn't any free arena, the maximum number of arenas has been reached, and
+an existing arena was chosen for reuse, but its mutex could not be
+immediately acquired. The mutex in @var{$arg1} is the mutex of the
+selected arena.
+
+When per-thread arenas are disabled, this occurs within
+@code{arena_get2}, when a thread first tries to allocate memory or the
+mutex of the arena it previously used could not be immediately acquired,
+and none of the existing arenas could be immediately reserved for
+exclusive use. The mutex in @var{$arg1} is that of the list of arenas,
+and since the arena won't have been selected yet, @var{$arg2} will be
+@code{NULL}.
+@end deftp
+
+@deftp Probe malloc_arena_reuse_free_list (void *@var{$arg1})
+This probe is hit when @code{malloc} has chosen an arena that is in the
+free list for use by a thread, within the @code{get_free_list} function.
+This probe is only available when @code{malloc} is configured to use
+per-thread arenas. The argument @var{$arg1} holds a pointer to the
+selected arena.
+@end deftp
+
+@deftp Probe malloc_arena_reuse_realloc (void *@var{$arg1})
+This probe is hit within @code{realloc}, as the arena of the current
+thread is changed to match that in which the given address was
+allocated. This probe is not available when @code{malloc} is configured
+to use per-thread arenas. The argument @var{$arg1} holds a pointer to
+the newly-selected arena.
+@end deftp
+
@deftp Probe mallopt (int @var{$arg1}, int @var{$arg2})
This probe is hit when function @code{mallopt} is called to change
@code{malloc} internal configuration parameters, before any change to
Add probes for malloc retries.
From: Alexandre Oliva <aoliva@redhat.com>
for ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* malloc/malloc.c (__libc_malloc): Add malloc_retry probe.
(__libc_realloc): Add realloc_retry probe.
(__libc_memalign): Add memalign_retry probe.
(__libc_valloc): Add valloc_retry probe.
(__libc_pvalloc): Add pvalloc_retry probe.
(__libc_calloc): Add calloc_retry probe.
* manual/malloc.texi: Document them.
---
malloc/malloc.c | 6 ++++++
manual/memory.texi | 20 ++++++++++++++++++++
2 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/malloc/malloc.c b/malloc/malloc.c
index df69f7b..9f75499 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -2860,6 +2860,7 @@ __libc_malloc(size_t bytes)
return 0;
victim = _int_malloc(ar_ptr, bytes);
if(!victim) {
+ LIBC_PROBE (malloc_retry, 1, bytes);
ar_ptr = arena_get_retry(ar_ptr, bytes);
if (__builtin_expect(ar_ptr != NULL, 1)) {
victim = _int_malloc(ar_ptr, bytes);
@@ -2995,6 +2996,7 @@ __libc_realloc(void* oldmem, size_t bytes)
if (newp == NULL)
{
/* Try harder to allocate memory in other arenas. */
+ LIBC_PROBE (realloc_retry, 2, bytes, oldmem);
newp = __libc_malloc(bytes);
if (newp != NULL)
{
@@ -3030,6 +3032,7 @@ __libc_memalign(size_t alignment, size_t bytes)
return 0;
p = _int_memalign(ar_ptr, alignment, bytes);
if(!p) {
+ LIBC_PROBE (memalign_retry, 2, bytes, alignment);
ar_ptr = arena_get_retry (ar_ptr, bytes);
if (__builtin_expect(ar_ptr != NULL, 1)) {
p = _int_memalign(ar_ptr, alignment, bytes);
@@ -3067,6 +3070,7 @@ __libc_valloc(size_t bytes)
return 0;
p = _int_valloc(ar_ptr, bytes);
if(!p) {
+ LIBC_PROBE (valloc_retry, 1, bytes);
ar_ptr = arena_get_retry (ar_ptr, bytes);
if (__builtin_expect(ar_ptr != NULL, 1)) {
p = _int_memalign(ar_ptr, pagesz, bytes);
@@ -3102,6 +3106,7 @@ __libc_pvalloc(size_t bytes)
arena_get(ar_ptr, bytes + 2*pagesz + MINSIZE);
p = _int_pvalloc(ar_ptr, bytes);
if(!p) {
+ LIBC_PROBE (pvalloc_retry, 1, bytes);
ar_ptr = arena_get_retry (ar_ptr, bytes + 2*pagesz + MINSIZE);
if (__builtin_expect(ar_ptr != NULL, 1)) {
p = _int_memalign(ar_ptr, pagesz, rounded_bytes);
@@ -3178,6 +3183,7 @@ __libc_calloc(size_t n, size_t elem_size)
av == arena_for_chunk(mem2chunk(mem)));
if (mem == 0) {
+ LIBC_PROBE (calloc_retry, 1, sz);
av = arena_get_retry (av, sz);
if (__builtin_expect(av != NULL, 1)) {
mem = _int_malloc(av, sz);
diff --git a/manual/memory.texi b/manual/memory.texi
index 9849bdc..592a954 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -1030,6 +1030,26 @@ These are nearly-zero-overhead probes available for monitoring internal
@code{libc} provider. The probes assume a reasonable knowledge of the
@code{malloc} implementation.
+@deftp Probe malloc_retry (size_t @var{$arg1})
+@deftpx Probe realloc_retry (size_t @var{$arg1}, void *@var{$arg2})
+@deftpx Probe memalign_retry (size_t @var{$arg1}, size_t @var{$arg2})
+@deftpx Probe valloc_retry (size_t @var{$arg1})
+@deftpx Probe pvalloc_retry (size_t @var{$arg1})
+@deftpx Probe calloc_retry (size_t @var{$arg1})
+These probes are hit when the corresponding functions fail to obtain the
+requested amount of memory from the arena in use, before it retries on
+another arena. Argument @var{$arg1} is the amount of memory requested
+by the user; in the @code{calloc} case, that is the total size computed
+from both function arguments. In the @code{realloc} case, @var{$arg2}
+is the pointer to the memory area being resized. In the @code{memalign}
+case, @var{$arg2} is the alignment to be used for the request, which may
+be stricter than the value passed to the @code{memalign} function.
+
+Note that the argument order does NOT match that of the corresponding
+two-argument functions, so that in all of these probes the
+user-requested allocation size is in @var{$arg1}.
+@end deftp
+
@deftp Probe malloc_arena_new (void *@var{$arg1}, size_t @var{$arg2})
This probe is hit when @code{malloc} allocated and initialized an
additional allocation arena (not the main arena), but before it is
Add catch-all alloc retry probe.
From: Alexandre Oliva <aoliva@redhat.com>
for ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* malloc/arena.c (arena_get_retry): Add malloc_all_retry probe.
* manual/malloc.texi: Document it.
---
malloc/arena.c | 1 +
manual/memory.texi | 12 ++++++++++++
2 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/malloc/arena.c b/malloc/arena.c
index fa5bf9c..1043499 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -937,6 +937,7 @@ arena_get2(mstate a_tsd, size_t size, mstate avoid_arena)
static mstate
arena_get_retry (mstate ar_ptr, size_t bytes)
{
+ LIBC_PROBE (malloc_all_retry, 2, bytes, ar_ptr);
if(ar_ptr != &main_arena) {
(void)mutex_unlock(&ar_ptr->mutex);
ar_ptr = &main_arena;
diff --git a/manual/memory.texi b/manual/memory.texi
index 592a954..ad1415c 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -1050,6 +1050,18 @@ two-argument functions, so that in all of these probes the
user-requested allocation size is in @var{$arg1}.
@end deftp
+@deftp Probe malloc_all_retry (size_t @var{$arg1}, void *@var{$arg2})
+This probe is hit within @code{get_another_arena}, the function used by
+all of the corresponding functions above to select the alternate arena
+in which to retry the allocation, before the selection takes place.
+This probe is redundant, but much easier to use when it's not important
+to determine which memory allocation functions are failing to allocate
+in the first try. Argument @var{$arg1} is the same as in the
+function-specific probes, except for extra room for padding introduced
+by functions that have to ensure stricter alignment. Argument
+@var{$arg2} is the arena in which allocation failed.
+@end deftp
+
@deftp Probe malloc_arena_new (void *@var{$arg1}, size_t @var{$arg2})
This probe is hit when @code{malloc} allocated and initialized an
additional allocation arena (not the main arena), but before it is
Add malloc probes for sbrk and heap resizing.
From: Alexandre Oliva <aoliva@redhat.com>
for ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* malloc/arena.c (new_heap): New heap_new probe.
(grow_heap): New heap_more probe.
(shrink_heap): New heap_less probe.
(heap_trim): New heap_free probe.
* malloc/malloc.c (sysmalloc): New sbrk_more probe.
(systrim): New sbrk_less probe.
* manual/malloc.texi: Document them.
---
malloc/arena.c | 4 ++++
malloc/malloc.c | 6 +++++-
manual/memory.texi | 40 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 49 insertions(+), 1 deletions(-)
diff --git a/malloc/arena.c b/malloc/arena.c
index 1043499..bfd9495 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -586,6 +586,7 @@ new_heap(size_t size, size_t top_pad)
h->size = size;
h->mprotect_size = size;
THREAD_STAT(stat_n_heaps++);
+ LIBC_PROBE (heap_new, 2, h, h->size);
return h;
}
@@ -611,6 +612,7 @@ grow_heap(heap_info *h, long diff)
}
h->size = new_size;
+ LIBC_PROBE (heap_more, 2, h, h->size);
return 0;
}
@@ -638,6 +640,7 @@ shrink_heap(heap_info *h, long diff)
/*fprintf(stderr, "shrink %p %08lx\n", h, new_size);*/
h->size = new_size;
+ LIBC_PROBE (heap_less, 2, h, h->size);
return 0;
}
@@ -679,6 +682,7 @@ heap_trim(heap_info *heap, size_t pad)
break;
ar_ptr->system_mem -= heap->size;
arena_mem -= heap->size;
+ LIBC_PROBE (heap_free, 2, heap, heap->size);
delete_heap(heap);
heap = prev_heap;
if(!prev_inuse(p)) { /* consolidate backward */
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 9f75499..7e63201 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -2452,8 +2452,10 @@ static void* sysmalloc(INTERNAL_SIZE_T nb, mstate av)
below even if we cannot call MORECORE.
*/
- if (size > 0)
+ if (size > 0) {
brk = (char*)(MORECORE(size));
+ LIBC_PROBE (sbrk_more, 2, brk, size);
+ }
if (brk != (char*)(MORECORE_FAILURE)) {
/* Call the `morecore' hook if necessary. */
@@ -2751,6 +2753,8 @@ static int systrim(size_t pad, mstate av)
(*hook) ();
new_brk = (char*)(MORECORE(0));
+ LIBC_PROBE (sbrk_less, 2, new_brk, extra);
+
if (new_brk != (char*)MORECORE_FAILURE) {
released = (long)(current_brk - new_brk);
diff --git a/manual/memory.texi b/manual/memory.texi
index ad1415c..c940d5b 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -1030,6 +1030,46 @@ These are nearly-zero-overhead probes available for monitoring internal
@code{libc} provider. The probes assume a reasonable knowledge of the
@code{malloc} implementation.
+@deftp Probe sbrk_more (void *@var{$arg1}, size_t @var{$arg2})
+This probe is hit after the main arena is extended by calling
+@code{sbrk}. Argument @var{$arg1} is the additional size requested to
+@code{sbrk}, and @var{$arg2} is the pointer that marks the end of the
+@code{sbrk} area, returned in response to the request.
+@end deftp
+
+@deftp Probe sbrk_less (void *@var{$arg1}, size_t @var{$arg2})
+This probe is hit after the main arena is shortened by calling
+@code{sbrk}. Argument @var{$arg1} is the size released by @code{sbrk}
+(the positive value, rather than the negated number passed to
+@code{sbrk}), and @var{$arg2} is the pointer that marks the end of the
+@code{sbrk} area, returned in response to the request.
+@end deftp
+
+@deftp Probe heap_new (void *@var{$arg1}, size_t @var{$arg2})
+This probe is hit after a new heap is @code{mmap}ed. Argument
+@var{$arg1} is a pointer to the base of the memory area, where the
+@code{heap_info} data structure is held, and @var{$arg2} is the size of
+the heap.
+@end deftp
+
+@deftp Probe heap_free (void *@var{$arg1}, size_t @var{$arg2})
+This probe is hit before (unlike the other sbrk and heap probes) a heap
+is completely un@code{mmap}ped. Argument @var{$arg1} is a pointer to
+the heap, and @var{$arg2} is the size of the heap.
+@end deftp
+
+@deftp Probe heap_less (void *@var{$arg1}, size_t @var{$arg2})
+This probe is hit after a trailing portion of an @code{mmap}ed heap is
+released. Argument @var{$arg1} is a pointer to the heap, and
+@var{$arg2} is the new size of the heap.
+@end deftp
+
+@deftp Probe heap_more (void *@var{$arg1}, size_t @var{$arg2})
+This probe is hit after a trailing portion of an @code{mmap}ed heap is
+extended. Argument @var{$arg1} is a pointer to the heap, and
+@var{$arg2} is the new size of the heap.
+@end deftp
+
@deftp Probe malloc_retry (size_t @var{$arg1})
@deftpx Probe realloc_retry (size_t @var{$arg1}, void *@var{$arg2})
@deftpx Probe memalign_retry (size_t @var{$arg1}, size_t @var{$arg2})
--
Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/ FSF Latin America board member
Free Software Evangelist Red Hat Brazil Compiler Engineer