Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions libdd-profiling-heap-sampler/include/datadog/heap/probes.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ void dd_probe_alloc(void *user, uint64_t size, uint64_t weight);
/*
* Emits the `ddheap:free` USDT.
* ptr - user-visible pointer being freed
*
* The symbol always exists, but the USDT is only emitted when compiled
* with live-heap tracking. The absence of the `ddheap:free` note in
* .note.stapsdt signals to external profilers that this binary does not
* support live-heap correlation.
*/
void dd_probe_free(void *ptr);

Expand Down
7 changes: 5 additions & 2 deletions libdd-profiling-heap-sampler/src/allocation_freed.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
* dd_sample_flag_check_and_clear confirmed that ptr carries the sample flag,
* meaning this allocation was previously sampled.
*
* Fires the ddheap:free USDT with the user-visible pointer, then returns
* Fires the ddheap:free USDT (when live-heap tracking is enabled) with the
* user-visible pointer, then returns
* the raw pointer and adjusted size that the caller must forward to the
* real deallocator. On x86-64 the size grows by DD_HEADER_BYTES to cover
* the header that was reserved at allocation time; on arm64 the size is
Expand All @@ -21,7 +22,9 @@
dd_alloc_freed_t dd_allocation_freed_slow(void *ptr, void *raw, size_t size,
size_t alignment) {
/* Fire with the user-visible pointer, matching what was reported at alloc
* time, so the profiler can correlate the two events by address. */
* time, so the profiler can correlate the two events by address. Safe to
* call unconditionally: dd_probe_free is a no-op USDT-wise when live-heap

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a test for this

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

* tracking is off. */
dd_probe_free(ptr);

dd_alloc_freed_t out = {
Expand Down
32 changes: 32 additions & 0 deletions libdd-profiling-heap-sampler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,38 @@ mod tests {
}
}

// With live-heap tracking compiled out, dd_allocation_freed is a
// straight passthrough: it never inspects the sample-flag header and
// never fires ddheap:free. Verify this even when the underlying
// memory happens to contain the magic pattern that *would* trigger
// the slow path if live-heap were enabled.
#[cfg(not(feature = "live-heap"))]
#[test]
fn freed_is_passthrough_when_live_heap_disabled() {
const MAGIC: u64 = 0xfab1eddec0dedca7;
const HEADER_BYTES: usize = 16;

// Set up a buffer with the magic header so that, if the flag-check
// were compiled in, it would consider this allocation sampled.
let mut buf = vec![0u8; 128];
let base = buf.as_mut_ptr() as usize;
let user_addr = base + HEADER_BYTES;

// Stamp magic at ptr - HEADER_BYTES
buf[0..8].copy_from_slice(&MAGIC.to_ne_bytes());
// Stamp a plausible offset
buf[8..16].copy_from_slice(&(HEADER_BYTES as u64).to_ne_bytes());

let ptr = user_addr as *mut c_void;
unsafe {
let freed = dd_allocation_freed(ptr, 64, 8);
// Without live-heap the pointer is returned unchanged (no
// flag-check, no raw-pointer recovery).
assert_eq!(freed.ptr, ptr);
assert_eq!(freed.size, 64);
}
}

#[test]
fn zero_sampling_interval_disables_sampling() {
let mut tl = dd_tl_state_t {
Expand Down
5 changes: 5 additions & 0 deletions libdd-profiling-heap-sampler/src/probes.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

#include <datadog/heap/probes.h>
#include <datadog/heap/sample_flag.h>

#include <errno.h>

Expand All @@ -29,7 +30,11 @@ void dd_probe_alloc(void *user, uint64_t size, uint64_t weight) {
}

void dd_probe_free(void *ptr) {
#if DD_HEAP_LIVE_TRACKING
int saved_errno = errno;
USDT(ddheap, free, ptr);
errno = saved_errno;
#else
(void)ptr;
Comment thread
scottgerring marked this conversation as resolved.
#endif
}
Loading