Debug-only pointer tracing macros (PTR_NEXT_READ/WRITE) + integration in TLS-SLL box
- Add core/ptr_trace.h (ring buffer, env-controlled dump) - Use macros in box/tls_sll_box.h push/pop/splice - Default: enabled for debug builds, zero-overhead in release - How to use: build debug and run with HAKMEM_PTR_TRACE_DUMP=1
This commit is contained in:
@ -25,6 +25,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h> // For fprintf in debug
|
||||
#include <stdlib.h> // For abort in debug
|
||||
#include "../ptr_trace.h" // Debug-only: pointer next read/write tracing
|
||||
#include "../hakmem_tiny_config.h" // For TINY_NUM_CLASSES
|
||||
|
||||
// External TLS SLL state (defined elsewhere)
|
||||
@ -70,7 +71,7 @@ static inline bool tls_sll_push(int class_idx, void* ptr, uint32_t capacity) {
|
||||
#else
|
||||
const size_t next_offset = 0;
|
||||
#endif
|
||||
*(void**)((uint8_t*)ptr + next_offset) = g_tls_sll_head[class_idx];
|
||||
PTR_NEXT_WRITE("tls_push", class_idx, ptr, next_offset, g_tls_sll_head[class_idx]);
|
||||
g_tls_sll_head[class_idx] = ptr;
|
||||
g_tls_sll_count[class_idx]++;
|
||||
|
||||
@ -106,7 +107,7 @@ static inline bool tls_sll_pop(int class_idx, void** out) {
|
||||
#else
|
||||
const size_t next_offset = 0;
|
||||
#endif
|
||||
void* next = *(void**)((uint8_t*)base + next_offset);
|
||||
void* next; PTR_NEXT_READ("tls_pop", class_idx, base, next_offset, next);
|
||||
g_tls_sll_head[class_idx] = next;
|
||||
if (g_tls_sll_count[class_idx] > 0) {
|
||||
g_tls_sll_count[class_idx]--;
|
||||
@ -169,7 +170,7 @@ static inline uint32_t tls_sll_splice(int class_idx, void* chain_head, uint32_t
|
||||
const size_t next_offset = 0;
|
||||
#endif
|
||||
for (uint32_t i = 1; i < to_move; i++) {
|
||||
void* next = *(void**)((uint8_t*)tail + next_offset);
|
||||
void* next; PTR_NEXT_READ("tls_sp_trav", class_idx, tail, next_offset, next);
|
||||
if (!next) {
|
||||
// Chain shorter than expected, adjust to_move
|
||||
to_move = i;
|
||||
@ -179,7 +180,7 @@ static inline uint32_t tls_sll_splice(int class_idx, void* chain_head, uint32_t
|
||||
}
|
||||
|
||||
// Splice chain to SLL head
|
||||
*(void**)((uint8_t*)tail + next_offset) = g_tls_sll_head[class_idx];
|
||||
PTR_NEXT_WRITE("tls_sp_link", class_idx, tail, next_offset, g_tls_sll_head[class_idx]);
|
||||
g_tls_sll_head[class_idx] = chain_head;
|
||||
g_tls_sll_count[class_idx] += to_move;
|
||||
|
||||
|
||||
93
core/ptr_trace.h
Normal file
93
core/ptr_trace.h
Normal file
@ -0,0 +1,93 @@
|
||||
// ptr_trace.h - Pointer link read/write tracing (Debug-only, macro-replaceable)
|
||||
//
|
||||
// Purpose:
|
||||
// - Centrally instrument single-linked list next pointer reads/writes
|
||||
// - Zero overhead in release builds (macros devolve to raw ops)
|
||||
// - Compact TLS ring for triage; optional dump at exit via env
|
||||
//
|
||||
// Usage:
|
||||
// - Replace direct next ops with PTR_NEXT_WRITE / PTR_NEXT_READ
|
||||
// - Tag with a short literal (e.g., "tls_push", "tls_pop", "splice")
|
||||
// - Offsets should be header-aware (C0–C6: +1, C7: +0)
|
||||
//
|
||||
// Control:
|
||||
// - Compile-time: HAKMEM_PTR_TRACE (default: 1 for debug, 0 for release)
|
||||
// - Runtime dump: HAKMEM_PTR_TRACE_DUMP=1 (prints ring at exit)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef HAKMEM_PTR_TRACE
|
||||
# if !HAKMEM_BUILD_RELEASE
|
||||
# define HAKMEM_PTR_TRACE 1
|
||||
# else
|
||||
# define HAKMEM_PTR_TRACE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if HAKMEM_PTR_TRACE
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
const char* tag; // literal tag
|
||||
int class_idx; // tiny class (0..7)
|
||||
void* node; // node address (base)
|
||||
void* val; // written/read value
|
||||
size_t off; // offset used for access
|
||||
} ptr_trace_ev_t;
|
||||
|
||||
#ifndef PTR_TRACE_CAP
|
||||
# define PTR_TRACE_CAP 256
|
||||
#endif
|
||||
|
||||
static __thread ptr_trace_ev_t g_ptr_trace_ring[PTR_TRACE_CAP];
|
||||
static __thread uint32_t g_ptr_trace_idx = 0;
|
||||
static __thread int g_ptr_trace_dump_registered = 0;
|
||||
|
||||
static inline void ptr_trace_record(const char* tag, int cls, void* node, void* val, size_t off) {
|
||||
uint32_t i = g_ptr_trace_idx++;
|
||||
g_ptr_trace_ring[i & (PTR_TRACE_CAP - 1)] = (ptr_trace_ev_t){ tag, cls, node, val, off };
|
||||
}
|
||||
|
||||
static inline void ptr_trace_try_register_dump(void) {
|
||||
if (g_ptr_trace_dump_registered) return;
|
||||
g_ptr_trace_dump_registered = 1;
|
||||
const char* env = getenv("HAKMEM_PTR_TRACE_DUMP");
|
||||
if (!(env && *env && *env != '0')) return;
|
||||
static void __attribute__((destructor)) ptr_trace_dump(void) {
|
||||
fprintf(stderr, "\n[PTR_TRACE_DUMP] last=%u (cap=%u)\n", g_ptr_trace_idx, (unsigned)PTR_TRACE_CAP);
|
||||
uint32_t n = (g_ptr_trace_idx < PTR_TRACE_CAP) ? g_ptr_trace_idx : PTR_TRACE_CAP;
|
||||
for (uint32_t k = 0; k < n; k++) {
|
||||
const ptr_trace_ev_t* e = &g_ptr_trace_ring[(g_ptr_trace_idx - n + k) & (PTR_TRACE_CAP - 1)];
|
||||
fprintf(stderr, "[%3u] tag=%s cls=%d node=%p val=%p off=%zu\n",
|
||||
k, e->tag ? e->tag : "?", e->class_idx, e->node, e->val, e->off);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define PTR_NEXT_WRITE(tag, cls, node, off, value) do { \
|
||||
void** __p = (void**)((uint8_t*)(node) + (off)); \
|
||||
*__p = (value); \
|
||||
ptr_trace_record((tag), (cls), (node), (value), (off)); \
|
||||
ptr_trace_try_register_dump(); \
|
||||
} while(0)
|
||||
|
||||
#define PTR_NEXT_READ(tag, cls, node, off, out_var) do { \
|
||||
void** __p = (void**)((uint8_t*)(node) + (off)); \
|
||||
(out_var) = *__p; \
|
||||
ptr_trace_record((tag), (cls), (node), (out_var), (off)); \
|
||||
ptr_trace_try_register_dump(); \
|
||||
} while(0)
|
||||
|
||||
#else // HAKMEM_PTR_TRACE == 0
|
||||
|
||||
#define PTR_NEXT_WRITE(tag, cls, node, off, value) \
|
||||
(*(void**)((uint8_t*)(node) + (off)) = (value))
|
||||
|
||||
#define PTR_NEXT_READ(tag, cls, node, off, out_var) \
|
||||
((out_var) = *(void**)((uint8_t*)(node) + (off)))
|
||||
|
||||
#endif // HAKMEM_PTR_TRACE
|
||||
|
||||
6
hakmem.d
6
hakmem.d
@ -23,8 +23,9 @@ hakmem.o: core/hakmem.c core/hakmem.h core/hakmem_build_flags.h \
|
||||
core/box/hak_free_api.inc.h core/hakmem_tiny_superslab.h \
|
||||
core/box/../tiny_free_fast_v2.inc.h core/box/../tiny_region_id.h \
|
||||
core/box/../hakmem_build_flags.h core/box/../hakmem_tiny_config.h \
|
||||
core/box/../box/tls_sll_box.h core/box/../box/../hakmem_tiny_config.h \
|
||||
core/box/front_gate_classifier.h core/box/hak_wrappers.inc.h
|
||||
core/box/../box/tls_sll_box.h core/box/../box/../ptr_trace.h \
|
||||
core/box/../box/../hakmem_tiny_config.h core/box/front_gate_classifier.h \
|
||||
core/box/hak_wrappers.inc.h
|
||||
core/hakmem.h:
|
||||
core/hakmem_build_flags.h:
|
||||
core/hakmem_config.h:
|
||||
@ -82,6 +83,7 @@ core/box/../tiny_region_id.h:
|
||||
core/box/../hakmem_build_flags.h:
|
||||
core/box/../hakmem_tiny_config.h:
|
||||
core/box/../box/tls_sll_box.h:
|
||||
core/box/../box/../ptr_trace.h:
|
||||
core/box/../box/../hakmem_tiny_config.h:
|
||||
core/box/front_gate_classifier.h:
|
||||
core/box/hak_wrappers.inc.h:
|
||||
|
||||
Reference in New Issue
Block a user