Add H1 dealloc hook and record_dealloc machinery (Phase 3.1) - #6
Merged
Merged
Conversation
- New snmalloc::profile::record_dealloc<Config>(void*) free function in src/snmalloc/profile/record.h. Compiles to a no-op for configs whose ClientMeta is not LazyArrayClientMetaDataProvider<SampledAlloc-slot>, so the default snmalloc::Config sees zero cost. - record_dealloc body splits into find_profile_slot (Config-specific pagemap walk) and clear_profile_slot (Config-agnostic atomic-CAS + SampledList::remove + NodePool::release), with the latter callable directly from tests. - H1 hook installed at the dealloc waist in Allocator::dealloc(void*) (mem/corealloc.h:1025), gated by SNMALLOC_PROFILE. Fires before any existing dealloc logic so profile-side cleanup observes the live pagemap, and is itself safe under recursive entry via the per-thread ReentrancyGuard. - record.h is intentionally lightweight; including commonconfig.h there would create a cycle (commonconfig -> mem/mem -> corealloc -> record). Instead corealloc.h forward-declares the template, and backend_helpers/backend_helpers.h pulls the full definition in once LazyArrayClientMetaDataProvider is visible. - record_alloc stays a stub: full alloc-side wiring lands in Phase 3.3. - New test src/test/func/profile_record/profile_record.cc covers the null-slot no-op, populated-slot drain, multi-threaded double-free CAS race, default-config compile-time no-op, ReentrancyGuard short-circuit and end-to-end libc::malloc/libc::free crash-freedom. - Default (OFF) build remains byte-identical to pre-Phase-3.1: the H1 call site is behind #ifdef SNMALLOC_PROFILE, and SNMALLOC_PROFILE=ON with the default NoClientMetaDataProvider Config inlines the if-constexpr branch into nothing (verified: same binary size for the default-config test executable in OFF vs ON builds). - All existing tests pass under both -DSNMALLOC_PROFILE=OFF (88/88) and -DSNMALLOC_PROFILE=ON (88/88), -fast and -check variants.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 3.1 — H1 dealloc hook at the waist (
Allocator::dealloc, 100% of public free entry points). Gated bySNMALLOC_PROFILE. Default (OFF) build is byte-identical.snmalloc::profile::record_dealloc<Config>(void*)insrc/snmalloc/profile/record.h. Compiles to no-op whenConfig::ClientMetais notLazyArrayClientMetaDataProvider<SampledAlloc*>slot type.find_profile_slot(Config-specific pagemap walk) +clear_profile_slot(Config-agnostic atomic-CAS +SampledList::remove+NodePool::release). Second function unit-testable without a real Backend.corealloc.h:1025, fires BEFORE existing dealloc logic so profile cleanup sees live pagemap entry. Re-entrancy-safe viaReentrancyGuard.record.his intentionally lightweight (forward-declared incorealloc.h, full definition pulled in bybackend_helpers.honceLazyArrayClientMetaDataProvidervisible) — avoids cyclecommonconfig.h → mem/mem.h → corealloc.h → record.h.record_allocstays a stub; full alloc-side wiring is Phase 3.3.Test plan
SNMALLOC_PROFILE=OFF(default)SNMALLOC_PROFILE=ONfunc-malloc-fasttest binary byte-identical OFF vs ON (216240 bytes)test_clear_null_slot— clear on null is no-optest_clear_populated_slot— published sample → cleared → live count drops, second clear no-optest_double_free_race— 2048 iters × 2 threads, exactly one CAS winner eachtest_default_config_compiletime_noop—static_assert(!config_has_profile_slot_v<snmalloc::Config>)test_reentrancy_short_circuit— slot untouched whileprofile_in_progress=1test_e2e_dealloc_does_not_crash— 1024 mixed-size libc malloc/free pairs through H1Ticket: 86ahrfww6