2025-12-03 11:38:11 +09:00
|
|
|
/**
|
|
|
|
|
* @file tiny_layout_box.h
|
|
|
|
|
* @brief Box: Tiny Allocator Layout Definitions
|
|
|
|
|
*
|
|
|
|
|
* MISSION: Single source of truth for class size and header layout
|
|
|
|
|
*
|
|
|
|
|
* Current Design (Phase E1-CORRECT):
|
|
|
|
|
* - All classes (0-7) have 1-byte header
|
2025-12-13 18:46:11 +09:00
|
|
|
* - User pointer = base + 1 for ALL classes (0-7)
|
|
|
|
|
* - Freed blocks store next pointers intrusively:
|
|
|
|
|
* - C0/C7: next at base+0 (header overwritten while free)
|
|
|
|
|
* - C1-C6: next at base+1 (header preserved while free)
|
|
|
|
|
* - No external code should hardcode offsets; use this box API
|
2025-12-03 11:38:11 +09:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef TINY_LAYOUT_BOX_H
|
|
|
|
|
#define TINY_LAYOUT_BOX_H
|
|
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
#include "../hakmem_tiny_config.h" // For g_tiny_class_sizes and TINY_NUM_CLASSES
|
|
|
|
|
|
2025-12-03 12:11:27 +09:00
|
|
|
// A/B Toggle: Headerless mode
|
|
|
|
|
// ENV: HAKMEM_TINY_HEADERLESS=1 to enable
|
|
|
|
|
// Default: 0 (Phase 1 compatible)
|
|
|
|
|
#ifndef HAKMEM_TINY_HEADERLESS
|
|
|
|
|
#define HAKMEM_TINY_HEADERLESS 0
|
|
|
|
|
#endif
|
|
|
|
|
|
2025-12-13 18:46:11 +09:00
|
|
|
#include "../hakmem_build_flags.h"
|
|
|
|
|
|
2025-12-03 11:38:11 +09:00
|
|
|
// Define all class-specific layout parameters
|
|
|
|
|
// Current: Defined in g_tiny_class_sizes[8] in hakmem_tiny.c
|
|
|
|
|
// This file makes them accessible via a unified Box API
|
|
|
|
|
|
2025-12-03 12:11:27 +09:00
|
|
|
// Header size
|
|
|
|
|
static inline size_t tiny_header_size(int class_idx) {
|
|
|
|
|
#if HAKMEM_TINY_HEADERLESS
|
|
|
|
|
(void)class_idx;
|
|
|
|
|
return 0;
|
2025-12-13 18:46:11 +09:00
|
|
|
#elif HAKMEM_TINY_HEADER_CLASSIDX
|
|
|
|
|
(void)class_idx;
|
|
|
|
|
return 1;
|
2025-12-03 12:11:27 +09:00
|
|
|
#else
|
2025-12-13 18:46:11 +09:00
|
|
|
(void)class_idx;
|
|
|
|
|
return 0;
|
2025-12-03 12:11:27 +09:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Legacy macro for backward compatibility (Phase 1)
|
2025-12-03 11:38:11 +09:00
|
|
|
#define TINY_HEADER_SIZE 1
|
|
|
|
|
|
|
|
|
|
// Validation macros
|
|
|
|
|
static inline int tiny_class_is_valid(int class_idx) {
|
|
|
|
|
return class_idx >= 0 && class_idx < TINY_NUM_CLASSES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline size_t tiny_class_stride(int class_idx) {
|
|
|
|
|
// Use the extern global definition from hakmem_tiny_config.h
|
|
|
|
|
// g_tiny_class_sizes is defined in core/hakmem_tiny_config_box.inc
|
|
|
|
|
return tiny_class_is_valid(class_idx) ? g_tiny_class_sizes[class_idx] : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Calculate user pointer offset from base pointer
|
|
|
|
|
// This logic centralizes the "User = Base + 1" vs "User = Base + 0" decision
|
|
|
|
|
static inline size_t tiny_user_offset(int class_idx) {
|
2025-12-03 12:11:27 +09:00
|
|
|
#if HAKMEM_TINY_HEADERLESS
|
|
|
|
|
(void)class_idx;
|
|
|
|
|
return 0; // Headerless: user = base
|
|
|
|
|
#elif HAKMEM_TINY_HEADER_CLASSIDX
|
2025-12-13 18:46:11 +09:00
|
|
|
(void)class_idx;
|
|
|
|
|
// Phase E1-CORRECT: All classes have 1-byte header → user = base + 1
|
|
|
|
|
return 1u;
|
|
|
|
|
#else
|
|
|
|
|
(void)class_idx;
|
|
|
|
|
return 0u;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Offset for storing the freelist next pointer inside a freed block.
|
|
|
|
|
// This is distinct from tiny_user_offset():
|
|
|
|
|
// - User offset is always +1 in header mode.
|
2025-12-15 00:32:25 +09:00
|
|
|
// - Next offset:
|
|
|
|
|
// - C0: always 0 (16B, cannot fit header+next)
|
|
|
|
|
// - C1-C6: always 1 (header-preserving)
|
|
|
|
|
// - C7: 0 (default) or 1 (Phase 13 v1: header-preserving)
|
2025-12-13 18:46:11 +09:00
|
|
|
static inline size_t tiny_nextptr_offset(int class_idx) {
|
|
|
|
|
#if HAKMEM_TINY_HEADERLESS
|
|
|
|
|
(void)class_idx;
|
|
|
|
|
return 0;
|
|
|
|
|
#elif HAKMEM_TINY_HEADER_CLASSIDX
|
2025-12-15 00:32:25 +09:00
|
|
|
// Phase 13 v1: C7 preserve header gate
|
|
|
|
|
// Bit pattern (default): C0=0, C1-C6=1, C7=0 → 0b01111110 = 0x7E
|
|
|
|
|
// Bit pattern (C7 preserve): C0=0, C1-C7=1 → 0b11111110 = 0xFE
|
|
|
|
|
unsigned int base_pattern = 0x7Eu; // default: C7 offset=0
|
|
|
|
|
|
|
|
|
|
// Phase 13 v1: Gate for C7 header-preserving layout
|
|
|
|
|
if (class_idx == 7) {
|
|
|
|
|
extern int tiny_c7_preserve_header_enabled(void);
|
|
|
|
|
if (tiny_c7_preserve_header_enabled()) {
|
|
|
|
|
base_pattern = 0xFEu; // C7 offset=1 (header-preserving)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (base_pattern >> ((unsigned)class_idx & 7u)) & 1u;
|
2025-12-03 11:38:11 +09:00
|
|
|
#else
|
|
|
|
|
(void)class_idx;
|
|
|
|
|
return 0u;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // TINY_LAYOUT_BOX_H
|