2025-12-18 08:39:48 +09:00
|
|
|
// tiny_c5_inline_slots.h - Phase 75-2: C5 Inline Slots Fast-Path API
|
|
|
|
|
//
|
|
|
|
|
// Goal: Zero-overhead fast-path API for C5 inline slot operations
|
|
|
|
|
// Scope: C5 class only (separate from C6, tested independently)
|
|
|
|
|
// Design: Always-inline, fail-fast to unified_cache on FULL/empty
|
|
|
|
|
//
|
|
|
|
|
// Performance Target:
|
|
|
|
|
// - Push: 1-2 cycles (ring index update, no bounds check)
|
|
|
|
|
// - Pop: 1-2 cycles (ring index update, null check)
|
|
|
|
|
// - Fallback: Silent delegation to unified_cache (existing path)
|
|
|
|
|
//
|
|
|
|
|
// Integration Points:
|
|
|
|
|
// - Alloc: Try c5_inline_pop() first, fallback to unified_cache_pop()
|
|
|
|
|
// - Free: Try c5_inline_push() first, fallback to unified_cache_push()
|
|
|
|
|
//
|
|
|
|
|
// Safety:
|
|
|
|
|
// - Caller must check c5_inline_enabled() before calling
|
|
|
|
|
// - Caller must handle NULL return (pop) or full condition (push)
|
|
|
|
|
// - No internal checks (fail-fast design)
|
|
|
|
|
|
|
|
|
|
#ifndef HAK_FRONT_TINY_C5_INLINE_SLOTS_H
|
|
|
|
|
#define HAK_FRONT_TINY_C5_INLINE_SLOTS_H
|
|
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
#include "../box/tiny_c5_inline_slots_env_box.h"
|
|
|
|
|
#include "../box/tiny_c5_inline_slots_tls_box.h"
|
2025-12-18 18:50:00 +09:00
|
|
|
#include "../box/tiny_inline_slots_fixed_mode_box.h"
|
2025-12-19 03:45:01 +09:00
|
|
|
#include "../box/tiny_inline_slots_overflow_stats_box.h"
|
2025-12-18 08:39:48 +09:00
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Fast-Path API (always_inline for zero branch overhead)
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
// Push to C5 inline slots (free path)
|
|
|
|
|
// Returns: 1 on success, 0 if full (caller must fallback to unified_cache)
|
|
|
|
|
// Precondition: ptr is valid BASE pointer for C5 class
|
|
|
|
|
__attribute__((always_inline))
|
|
|
|
|
static inline int c5_inline_push(TinyC5InlineSlots* slots, void* ptr) {
|
2025-12-19 03:45:01 +09:00
|
|
|
tiny_inline_slots_count_push_total(5); // Phase 87: Telemetry (all attempts)
|
|
|
|
|
|
2025-12-18 08:39:48 +09:00
|
|
|
// Full check (single branch, likely taken in steady state)
|
|
|
|
|
if (__builtin_expect(c5_inline_full(slots), 0)) {
|
2025-12-19 03:45:01 +09:00
|
|
|
tiny_inline_slots_count_push_full(5); // Phase 87: Telemetry (overflow)
|
2025-12-18 08:39:48 +09:00
|
|
|
return 0; // Full, caller must fallback
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Push to tail (FIFO producer)
|
|
|
|
|
slots->slots[slots->tail] = ptr;
|
|
|
|
|
slots->tail = (slots->tail + 1) % TINY_C5_INLINE_CAPACITY;
|
|
|
|
|
|
|
|
|
|
return 1; // Success
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pop from C5 inline slots (alloc path)
|
|
|
|
|
// Returns: BASE pointer on success, NULL if empty (caller must fallback to unified_cache)
|
|
|
|
|
// Precondition: slots is initialized and enabled
|
|
|
|
|
__attribute__((always_inline))
|
|
|
|
|
static inline void* c5_inline_pop(TinyC5InlineSlots* slots) {
|
2025-12-19 03:45:01 +09:00
|
|
|
tiny_inline_slots_count_pop_total(5); // Phase 87: Telemetry (all attempts)
|
|
|
|
|
|
2025-12-18 08:39:48 +09:00
|
|
|
// Empty check (single branch, likely NOT taken in steady state)
|
|
|
|
|
if (__builtin_expect(c5_inline_empty(slots), 0)) {
|
2025-12-19 03:45:01 +09:00
|
|
|
tiny_inline_slots_count_pop_empty(5); // Phase 87: Telemetry (underflow)
|
2025-12-18 08:39:48 +09:00
|
|
|
return NULL; // Empty, caller must fallback
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pop from head (FIFO consumer)
|
|
|
|
|
void* ptr = slots->slots[slots->head];
|
|
|
|
|
slots->head = (slots->head + 1) % TINY_C5_INLINE_CAPACITY;
|
|
|
|
|
|
|
|
|
|
return ptr; // BASE pointer (caller converts to USER)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Integration Helpers (for malloc_tiny_fast.h integration)
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
// Get TLS instance (wraps extern TLS variable)
|
|
|
|
|
static inline TinyC5InlineSlots* c5_inline_tls(void) {
|
|
|
|
|
return &g_tiny_c5_inline_slots;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if C5 inline is enabled AND initialized (combined gate)
|
|
|
|
|
// Returns: 1 if ready to use, 0 if disabled or uninitialized
|
|
|
|
|
static inline int c5_inline_ready(void) {
|
2025-12-18 18:50:00 +09:00
|
|
|
if (!tiny_c5_inline_slots_enabled_fast()) {
|
2025-12-18 08:39:48 +09:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TLS init check (once per thread)
|
|
|
|
|
// Note: In production, this check can be eliminated if TLS init is guaranteed
|
|
|
|
|
TinyC5InlineSlots* slots = c5_inline_tls();
|
|
|
|
|
return (slots->slots != NULL || slots->head == 0); // Initialized if zero or non-null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // HAK_FRONT_TINY_C5_INLINE_SLOTS_H
|