Add tiny_ptr_bridge_box for centralized pointer classification
Consolidates the logic for resolving Tiny BASE pointers into (SuperSlab*, slab_idx, TinySlabMeta*, class_idx) tuples. Box Theory compliance: - Single Responsibility: ptr→(ss,slab,meta,class) resolution only - No side effects: pure classification, no logging, no mutations - Clear API: 4 functions (classify_raw/base, validate_raw/base_class) - Fail-fast friendly: callers decide error handling policy Implementation: - core/box/tiny_ptr_bridge_box.h: New box (4.7 KB) - core/box/tls_sll_box.h: Integrated into sanitize_head/check_node Architecture: - Used in 3 call sites within TLS SLL Box - Ready for gradual migration to other code paths - Foundation for future centralized validation Testing: 150+ seconds stable (sh8bench) - 30s test: exit code 0, 0 crashes - 120s test: exit code 0, 0 crashes - Behavior: identical to previous hand-rolled implementation Benefits: - Single point of authority for ptr→(ss,slab,meta,class) logic - Easier to add validation rules in future (range check, magic, etc.) - Consistent API for all ptr classification needs - Foundation for removing code duplication across allocator 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
137
core/box/tiny_ptr_bridge_box.h
Normal file
137
core/box/tiny_ptr_bridge_box.h
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// tiny_ptr_bridge_box.h - Pointer→SuperSlab/Slab Bridge Box
|
||||||
|
// Purpose:
|
||||||
|
// Centralize the logic for resolving Tiny BASE pointers into
|
||||||
|
// (SuperSlab*, slab_idx, TinySlabMeta*, class_idx) with a single
|
||||||
|
// consistent contract.
|
||||||
|
//
|
||||||
|
// Box Theory:
|
||||||
|
// - Single Responsibility:
|
||||||
|
// "Given a Tiny pointer, tell me which SuperSlab/slab/meta it belongs to."
|
||||||
|
// - Clear Boundary:
|
||||||
|
// All ptr→(ss, slab_idx, meta, class) resolution goes through this box.
|
||||||
|
// - Fail‑Fast Friendly:
|
||||||
|
// Callers decide whether to abort/drop/log based on the result.
|
||||||
|
// This box itself stays side‑effect free (no logging by default).
|
||||||
|
// - Reversible / A/B:
|
||||||
|
// Call sites can be migrated gradually; old hand‑rolled lookups
|
||||||
|
// can be kept under #ifdef until fully retired.
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// - This box is intentionally "dumb": it does not know about TLS SLL,
|
||||||
|
// remote queues, or ownership. It only classifies pointers.
|
||||||
|
// - Validation (e.g. class match) is done via helpers that return bool.
|
||||||
|
|
||||||
|
#ifndef HAKMEM_TINY_PTR_BRIDGE_BOX_H
|
||||||
|
#define HAKMEM_TINY_PTR_BRIDGE_BOX_H
|
||||||
|
|
||||||
|
#include "../hakmem_tiny_superslab_internal.h" // SuperSlab, TinySlabMeta, slab_index_for, ss_slabs_capacity
|
||||||
|
|
||||||
|
// Classification result for a Tiny pointer.
|
||||||
|
typedef struct TinyPtrBridgeInfo {
|
||||||
|
SuperSlab* ss; // Owning SuperSlab (NULL if not Tiny)
|
||||||
|
TinySlabMeta* meta; // Per‑slab metadata (NULL if invalid)
|
||||||
|
int slab_idx; // Slab index within SuperSlab (‑1 if invalid)
|
||||||
|
uint8_t meta_cls; // meta->class_idx if valid, 0xff otherwise
|
||||||
|
} TinyPtrBridgeInfo;
|
||||||
|
|
||||||
|
// Internal helper: classify a raw pointer without applying any policy.
|
||||||
|
// Preconditions:
|
||||||
|
// - raw may be arbitrary (stack/heap/garbage).
|
||||||
|
// Postconditions:
|
||||||
|
// - On success: info.ss != NULL, info.meta != NULL, slab_idx >= 0, meta_cls set.
|
||||||
|
// - On failure: all fields are "empty" (ss/meta=NULL, slab_idx=-1, meta_cls=0xff).
|
||||||
|
static inline TinyPtrBridgeInfo tiny_ptr_bridge_classify_raw(void* raw)
|
||||||
|
{
|
||||||
|
TinyPtrBridgeInfo info;
|
||||||
|
info.ss = NULL;
|
||||||
|
info.meta = NULL;
|
||||||
|
info.slab_idx = -1;
|
||||||
|
info.meta_cls = 0xffu;
|
||||||
|
|
||||||
|
if (!raw) {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t addr = (uintptr_t)raw;
|
||||||
|
if (addr < 4096 || addr > 0x00007fffffffffffULL) {
|
||||||
|
// Non‑canonical (very small or non‑userspace) → treat as invalid.
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
SuperSlab* ss = hak_super_lookup(raw);
|
||||||
|
if (!ss || ss->magic != SUPERSLAB_MAGIC) {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cap = ss_slabs_capacity(ss);
|
||||||
|
if (cap <= 0) {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
int slab_idx = slab_index_for(ss, raw);
|
||||||
|
if (slab_idx < 0 || slab_idx >= cap) {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
TinySlabMeta* meta = &ss->slabs[slab_idx];
|
||||||
|
info.ss = ss;
|
||||||
|
info.meta = meta;
|
||||||
|
info.slab_idx = slab_idx;
|
||||||
|
info.meta_cls = meta->class_idx;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience: classify a BASE pointer (hak_base_ptr_t) into bridge info.
|
||||||
|
static inline TinyPtrBridgeInfo tiny_ptr_bridge_classify_base(hak_base_ptr_t base)
|
||||||
|
{
|
||||||
|
void* raw = HAK_BASE_TO_RAW(base);
|
||||||
|
return tiny_ptr_bridge_classify_raw(raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate that a BASE pointer belongs to a Tiny slab with the expected class.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// class_idx - Expected Tiny class index (‑1 to skip class check).
|
||||||
|
// base - BASE pointer to classify.
|
||||||
|
// out_info - Optional; filled on success with full classification.
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// true - Pointer classified successfully and (if class_idx>=0) meta_cls matches.
|
||||||
|
// false - Pointer is not within any valid Tiny slab or class mismatch.
|
||||||
|
static inline bool tiny_ptr_bridge_validate_base_class(int class_idx,
|
||||||
|
hak_base_ptr_t base,
|
||||||
|
TinyPtrBridgeInfo* out_info)
|
||||||
|
{
|
||||||
|
TinyPtrBridgeInfo info = tiny_ptr_bridge_classify_base(base);
|
||||||
|
if (!info.ss || !info.meta) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (class_idx >= 0 && info.meta_cls != (uint8_t)class_idx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (out_info) {
|
||||||
|
*out_info = info;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience wrapper for raw pointers (used by legacy code).
|
||||||
|
static inline bool tiny_ptr_bridge_validate_raw_class(int class_idx,
|
||||||
|
void* raw,
|
||||||
|
TinyPtrBridgeInfo* out_info)
|
||||||
|
{
|
||||||
|
TinyPtrBridgeInfo info = tiny_ptr_bridge_classify_raw(raw);
|
||||||
|
if (!info.ss || !info.meta) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (class_idx >= 0 && info.meta_cls != (uint8_t)class_idx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (out_info) {
|
||||||
|
*out_info = info;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HAKMEM_TINY_PTR_BRIDGE_BOX_H
|
||||||
|
|
||||||
@ -37,6 +37,7 @@
|
|||||||
#include "../hakmem_super_registry.h"
|
#include "../hakmem_super_registry.h"
|
||||||
#include "ss_addr_map_box.h"
|
#include "ss_addr_map_box.h"
|
||||||
#include "../superslab/superslab_inline.h"
|
#include "../superslab/superslab_inline.h"
|
||||||
|
#include "tiny_ptr_bridge_box.h" // Box: ptr→(ss,slab,meta,class) bridge
|
||||||
#include "tiny_next_ptr_box.h"
|
#include "tiny_next_ptr_box.h"
|
||||||
#include "tiny_header_box.h" // Header Box: Single Source of Truth for header operations
|
#include "tiny_header_box.h" // Header Box: Single Source of Truth for header operations
|
||||||
|
|
||||||
@ -190,13 +191,13 @@ static inline void tls_sll_sanitize_head(int class_idx, const char* stage)
|
|||||||
if (hak_base_is_null(head)) return;
|
if (hak_base_is_null(head)) return;
|
||||||
|
|
||||||
void* raw = HAK_BASE_TO_RAW(head);
|
void* raw = HAK_BASE_TO_RAW(head);
|
||||||
SuperSlab* ss = hak_super_lookup(raw);
|
TinyPtrBridgeInfo info = tiny_ptr_bridge_classify_raw(raw);
|
||||||
int cap = ss ? ss_slabs_capacity(ss) : 0;
|
SuperSlab* ss = info.ss;
|
||||||
int idx = (ss && ss->magic == SUPERSLAB_MAGIC) ? slab_index_for(ss, raw) : -1;
|
int idx = info.slab_idx;
|
||||||
uint8_t meta_cls = (idx >= 0 && idx < cap) ? ss->slabs[idx].class_idx : 0xff;
|
uint8_t meta_cls = info.meta_cls;
|
||||||
|
|
||||||
int reset = 0;
|
int reset = 0;
|
||||||
if (!ss || ss->magic != SUPERSLAB_MAGIC || idx < 0 || idx >= cap || meta_cls != (uint8_t)class_idx) {
|
if (!ss || !info.meta || idx < 0 || meta_cls != (uint8_t)class_idx) {
|
||||||
reset = 1;
|
reset = 1;
|
||||||
}
|
}
|
||||||
#if HAKMEM_TINY_HEADER_CLASSIDX
|
#if HAKMEM_TINY_HEADER_CLASSIDX
|
||||||
@ -226,15 +227,11 @@ static inline void tls_sll_sanitize_head(int class_idx, const char* stage)
|
|||||||
static inline int tls_sll_check_node(int class_idx, void* raw, void* from_base, const char* stage)
|
static inline int tls_sll_check_node(int class_idx, void* raw, void* from_base, const char* stage)
|
||||||
{
|
{
|
||||||
if (!raw) return 1;
|
if (!raw) return 1;
|
||||||
uintptr_t addr = (uintptr_t)raw;
|
TinyPtrBridgeInfo info = tiny_ptr_bridge_classify_raw(raw);
|
||||||
if (addr < 4096 || addr > 0x00007fffffffffffULL) {
|
SuperSlab* ss = info.ss;
|
||||||
goto bad;
|
int idx = info.slab_idx;
|
||||||
}
|
uint8_t meta_cls = info.meta_cls;
|
||||||
SuperSlab* ss = hak_super_lookup(raw);
|
if (!ss || !info.meta || idx < 0 || meta_cls != (uint8_t)class_idx) {
|
||||||
int cap = ss ? ss_slabs_capacity(ss) : 0;
|
|
||||||
int idx = (ss && ss->magic == SUPERSLAB_MAGIC) ? slab_index_for(ss, raw) : -1;
|
|
||||||
uint8_t meta_cls = (idx >= 0 && idx < cap) ? ss->slabs[idx].class_idx : 0xff;
|
|
||||||
if (!ss || ss->magic != SUPERSLAB_MAGIC || idx < 0 || idx >= cap || meta_cls != (uint8_t)class_idx) {
|
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
#if HAKMEM_TINY_HEADER_CLASSIDX
|
#if HAKMEM_TINY_HEADER_CLASSIDX
|
||||||
@ -258,12 +255,12 @@ bad:
|
|||||||
uint64_t from_meta_used = 0;
|
uint64_t from_meta_used = 0;
|
||||||
void* from_meta_freelist = NULL;
|
void* from_meta_freelist = NULL;
|
||||||
if (from_base) {
|
if (from_base) {
|
||||||
from_ss = hak_super_lookup(from_base);
|
TinyPtrBridgeInfo from_info = tiny_ptr_bridge_classify_raw(from_base);
|
||||||
int from_cap = from_ss ? ss_slabs_capacity(from_ss) : 0;
|
from_ss = from_info.ss;
|
||||||
from_idx = (from_ss && from_ss->magic == SUPERSLAB_MAGIC) ? slab_index_for(from_ss, from_base) : -1;
|
from_idx = from_info.slab_idx;
|
||||||
if (from_idx >= 0 && from_idx < from_cap) {
|
from_meta = from_info.meta;
|
||||||
from_meta = &from_ss->slabs[from_idx];
|
from_meta_cls = from_info.meta_cls;
|
||||||
from_meta_cls = from_meta->class_idx;
|
if (from_meta) {
|
||||||
from_meta_used = from_meta->used;
|
from_meta_used = from_meta->used;
|
||||||
from_meta_freelist = from_meta->freelist;
|
from_meta_freelist = from_meta->freelist;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user