149 lines
5.1 KiB
C
149 lines
5.1 KiB
C
|
|
#ifndef HAKMEM_TINY_MINI_MAG_H
|
||
|
|
#define HAKMEM_TINY_MINI_MAG_H
|
||
|
|
|
||
|
|
#include <stddef.h>
|
||
|
|
#include <stdint.h>
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Page Mini-Magazine: Fast LIFO Cache (Data Plane)
|
||
|
|
// ============================================================================
|
||
|
|
//
|
||
|
|
// Purpose: Provide O(1) allocation/free on page level
|
||
|
|
// Design: Intrusive LIFO free-list (mimalloc-style)
|
||
|
|
// Cost: 1-2 ns per operation (vs 5-6 ns bitmap scan)
|
||
|
|
//
|
||
|
|
// Key Insight: Free blocks store next-pointer in first 8 bytes
|
||
|
|
// No separate metadata needed (zero overhead)
|
||
|
|
//
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
// Intrusive LIFO Block
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
typedef struct MiniMagBlock {
|
||
|
|
struct MiniMagBlock* next; // Next free block in LIFO stack
|
||
|
|
} MiniMagBlock;
|
||
|
|
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
// Mini-Magazine Metadata
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
MiniMagBlock* head; // LIFO stack head (NULL if empty)
|
||
|
|
uint16_t count; // Current item count [0, capacity]
|
||
|
|
uint16_t capacity; // Maximum items (16-32 typical)
|
||
|
|
} PageMiniMag;
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Core Operations (Always Inlined for Speed)
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
// Pop from Mini-Magazine (Fast Path: 1-2 ns)
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
//
|
||
|
|
// Returns: Pointer to free block, or NULL if empty
|
||
|
|
// Cost: 1-2 ns (two pointer operations in L1 cache)
|
||
|
|
//
|
||
|
|
static inline void* mini_mag_pop(PageMiniMag* mag) __attribute__((always_inline));
|
||
|
|
static inline void* mini_mag_pop(PageMiniMag* mag) {
|
||
|
|
MiniMagBlock* b = mag->head;
|
||
|
|
if (!b) return NULL; // Empty
|
||
|
|
|
||
|
|
// Pop from LIFO stack
|
||
|
|
mag->head = b->next;
|
||
|
|
mag->count--;
|
||
|
|
|
||
|
|
return (void*)b;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
// Push to Mini-Magazine (Fast Path: 1-2 ns)
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
//
|
||
|
|
// Returns: 1 on success, 0 if magazine is full
|
||
|
|
// Cost: 1-2 ns (two pointer operations + count check)
|
||
|
|
//
|
||
|
|
static inline int mini_mag_push(PageMiniMag* mag, void* ptr) __attribute__((always_inline));
|
||
|
|
static inline int mini_mag_push(PageMiniMag* mag, void* ptr) {
|
||
|
|
if (mag->count >= mag->capacity) return 0; // Full
|
||
|
|
|
||
|
|
// Push to LIFO stack (intrusive next-pointer)
|
||
|
|
MiniMagBlock* b = (MiniMagBlock*)ptr;
|
||
|
|
b->next = mag->head;
|
||
|
|
mag->head = b;
|
||
|
|
mag->count++;
|
||
|
|
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
// Query Operations
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
// Check if mini-magazine is empty
|
||
|
|
static inline int mini_mag_is_empty(const PageMiniMag* mag) {
|
||
|
|
return mag->count == 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if mini-magazine is full
|
||
|
|
static inline int mini_mag_is_full(const PageMiniMag* mag) {
|
||
|
|
return mag->count >= mag->capacity;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get available space
|
||
|
|
static inline int mini_mag_space(const PageMiniMag* mag) {
|
||
|
|
return mag->capacity - mag->count;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Initialization
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
// Initialize mini-magazine (call on slab creation)
|
||
|
|
static inline void mini_mag_init(PageMiniMag* mag, uint16_t capacity) {
|
||
|
|
mag->head = NULL;
|
||
|
|
mag->count = 0;
|
||
|
|
mag->capacity = capacity;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Reset mini-magazine (clear all items without freeing)
|
||
|
|
static inline void mini_mag_reset(PageMiniMag* mag) {
|
||
|
|
mag->head = NULL;
|
||
|
|
mag->count = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Design Notes
|
||
|
|
// ============================================================================
|
||
|
|
//
|
||
|
|
// 1. LIFO Order (Temporal Locality):
|
||
|
|
// - Most recently freed block = next allocated
|
||
|
|
// - Excellent L1 cache hit rate (95%+)
|
||
|
|
// - Hot blocks stay hot (cache-friendly)
|
||
|
|
//
|
||
|
|
// 2. Intrusive Design (Zero Overhead):
|
||
|
|
// - Next-pointer stored in free block itself
|
||
|
|
// - No separate metadata array needed
|
||
|
|
// - Memory overhead: 0 bytes
|
||
|
|
//
|
||
|
|
// 3. Thread Safety:
|
||
|
|
// - Owner-only access (no locks needed)
|
||
|
|
// - Thread-local page has thread-local mini-magazine
|
||
|
|
// - Remote frees go to separate MPSC queue
|
||
|
|
//
|
||
|
|
// 4. Capacity Tuning:
|
||
|
|
// - Small (8-16): Lower memory, frequent refills
|
||
|
|
// - Medium (16-32): Balanced (recommended)
|
||
|
|
// - Large (32-64): Fewer refills, more memory
|
||
|
|
//
|
||
|
|
// 5. Integration with Bitmap:
|
||
|
|
// - Mini-magazine = Data plane (fast path)
|
||
|
|
// - Bitmap = Control plane (truth)
|
||
|
|
// - Batch refill amortizes bitmap scan cost
|
||
|
|
//
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
#endif // HAKMEM_TINY_MINI_MAG_H
|