159 lines
6.6 KiB
C
159 lines
6.6 KiB
C
|
|
// smallsegment_v7_box.h - SmallSegment v7 (Phase v7-2: C6-only implementation)
|
||
|
|
//
|
||
|
|
// Purpose:
|
||
|
|
// - SmallObject v7 segment structure with 2MiB/64KiB geometry
|
||
|
|
// - Supports free_page stack for page management
|
||
|
|
// - RegionIdBox integration via REGION_KIND_SMALL_V7
|
||
|
|
|
||
|
|
#ifndef HAKMEM_SMALLSEGMENT_V7_BOX_H
|
||
|
|
#define HAKMEM_SMALLSEGMENT_V7_BOX_H
|
||
|
|
|
||
|
|
#include <stdint.h>
|
||
|
|
#include <stddef.h>
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Segment Constants (same geometry as V6/ULTRA)
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
#define SMALL_SEGMENT_V7_SIZE (2u * 1024u * 1024u) // 2 MiB
|
||
|
|
#define SMALL_PAGE_V7_SIZE (64u * 1024u) // 64 KiB
|
||
|
|
#define SMALL_PAGES_PER_SEG_V7 (SMALL_SEGMENT_V7_SIZE / SMALL_PAGE_V7_SIZE) // 32
|
||
|
|
#define SMALL_PAGE_V7_SHIFT 16 // log2(64KiB)
|
||
|
|
#define SMALL_SEGMENT_V7_MAGIC 0xC07E57u // C0(re) v7
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// C6 Class Configuration (v7-2: C6-only)
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
#define SMALL_V7_C6_CLASS_IDX 6
|
||
|
|
#define SMALL_V7_C6_BLOCK_SIZE 512
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Page Index Calculation
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
#define SMALL_V7_PAGE_IDX(seg, addr) (((uintptr_t)(addr) - (seg)->base) >> SMALL_PAGE_V7_SHIFT)
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Forward Declarations
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
typedef struct SmallSegment_v7 SmallSegment_v7;
|
||
|
|
typedef struct SmallPageMeta_v7 SmallPageMeta_v7;
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// SmallPageMeta_v7 - Page metadata (per-page hot/cold fields)
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
typedef struct SmallPageMeta_v7 {
|
||
|
|
// ---- Hot fields (cache line 0, accessed in alloc/free) ----
|
||
|
|
void* free_list; // LIFO freelist: block -> next
|
||
|
|
uint32_t used; // Current used slot count
|
||
|
|
uint32_t capacity; // Total block slots in this page
|
||
|
|
|
||
|
|
uint16_t class_idx; // Size class (C0..C7)
|
||
|
|
uint16_t flags; // HOT/PARTIAL/FULL/REMOTE_PENDING
|
||
|
|
uint16_t page_idx; // Index within segment (0..31)
|
||
|
|
uint16_t reserved0; // Alignment padding
|
||
|
|
|
||
|
|
SmallSegment_v7* segment; // Back pointer to owning segment
|
||
|
|
|
||
|
|
// Intrusive list pointer for partial pages (optional)
|
||
|
|
SmallPageMeta_v7* segment_next_partial;
|
||
|
|
|
||
|
|
// ---- Cold fields (Stats/Policy, cache line 1+) ----
|
||
|
|
uint64_t alloc_count; // Cumulative alloc count
|
||
|
|
uint64_t free_count; // Cumulative free count
|
||
|
|
uint64_t remote_free_count; // Cumulative remote free count
|
||
|
|
|
||
|
|
uint16_t live_current; // Current live objects
|
||
|
|
uint16_t peak_live; // Lifetime peak live
|
||
|
|
uint16_t remote_burst_max; // Max remote drain in one pass
|
||
|
|
uint16_t reserved1;
|
||
|
|
|
||
|
|
uint32_t epoch_first_alloc; // Coarse epoch (for L3/Learner)
|
||
|
|
uint32_t epoch_last_free; // Coarse epoch (for L3/Learner)
|
||
|
|
} SmallPageMeta_v7;
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// SmallSegment_v7 - 2MiB segment with page metadata
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
typedef struct SmallSegment_v7 {
|
||
|
|
uintptr_t base; // Segment base address (2MiB aligned)
|
||
|
|
uint32_t num_pages; // Number of pages (32)
|
||
|
|
uint32_t owner_tid; // Owner thread ID
|
||
|
|
|
||
|
|
uint32_t flags; // SEGMENT_IN_USE / RETIRED etc.
|
||
|
|
uint32_t magic; // SMALL_SEGMENT_V7_MAGIC
|
||
|
|
uint32_t region_kind; // REGION_KIND_SMALL_V7
|
||
|
|
uint32_t segment_idx; // RegionIdBox index
|
||
|
|
|
||
|
|
uint32_t free_page_head; // Free page stack head (page_idx, 0xFFFFFFFF = empty)
|
||
|
|
uint32_t free_page_count; // Number of free pages
|
||
|
|
|
||
|
|
SmallPageMeta_v7 page_meta[SMALL_PAGES_PER_SEG_V7];
|
||
|
|
} SmallSegment_v7;
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Inline Helper Functions
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
/// Check if page is valid and active
|
||
|
|
static inline int small_page_v7_valid(SmallPageMeta_v7* page) {
|
||
|
|
return page != NULL && page->capacity > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Check if pointer is within segment bounds
|
||
|
|
static inline int small_ptr_in_segment_v7(SmallSegment_v7* seg, void* ptr) {
|
||
|
|
uintptr_t addr = (uintptr_t)ptr;
|
||
|
|
return addr >= seg->base && addr < seg->base + SMALL_SEGMENT_V7_SIZE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Check if segment is valid and initialized
|
||
|
|
static inline int small_segment_v7_valid(SmallSegment_v7* seg) {
|
||
|
|
return seg != NULL && seg->magic == SMALL_SEGMENT_V7_MAGIC;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Segment API (Cold Path)
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
/// Allocate a new segment for thread
|
||
|
|
/// @param owner_tid: Thread ID of owner
|
||
|
|
/// @return: Segment pointer on success, NULL on failure
|
||
|
|
SmallSegment_v7* small_segment_alloc_v7(uint32_t owner_tid);
|
||
|
|
|
||
|
|
/// Free a segment and unmap memory
|
||
|
|
/// @param seg: Segment to free
|
||
|
|
void small_segment_free_v7(SmallSegment_v7* seg);
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Page API (Cold Path - called from ColdIface)
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
/// Take a page from segment's free stack
|
||
|
|
/// @param seg: Segment to take page from
|
||
|
|
/// @param class_idx: Size class for the page
|
||
|
|
/// @return: Page metadata pointer on success, NULL if no free pages
|
||
|
|
SmallPageMeta_v7* small_segment_take_page_v7(SmallSegment_v7* seg, uint32_t class_idx);
|
||
|
|
|
||
|
|
/// Release a page back to segment's free stack
|
||
|
|
/// @param seg: Segment owning the page
|
||
|
|
/// @param page: Page to release
|
||
|
|
void small_segment_release_page_v7(SmallSegment_v7* seg, SmallPageMeta_v7* page);
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// TLS Segment Access
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
/// Get or acquire TLS segment for current thread
|
||
|
|
SmallSegment_v7* small_segment_v7_get_tls(void);
|
||
|
|
|
||
|
|
/// Get page metadata for a pointer (O(1) via TLS segment)
|
||
|
|
/// @param ptr: Pointer to lookup (USER or BASE pointer)
|
||
|
|
/// @return: Page metadata if ptr is in v7 segment, NULL otherwise
|
||
|
|
SmallPageMeta_v7* small_page_meta_v7_of(void* ptr);
|
||
|
|
|
||
|
|
#endif // HAKMEM_SMALLSEGMENT_V7_BOX_H
|