93 lines
2.5 KiB
C
93 lines
2.5 KiB
C
|
|
// smallobject_cold_iface_v6.c - SmallObject ColdIface v6 実装(Phase v6-3)
|
|||
|
|
|
|||
|
|
#include <stdlib.h>
|
|||
|
|
#include <string.h>
|
|||
|
|
#include <stdint.h>
|
|||
|
|
#include "box/smallobject_cold_iface_v6.h"
|
|||
|
|
#include "box/smallsegment_v6_box.h"
|
|||
|
|
|
|||
|
|
#ifndef likely
|
|||
|
|
#define likely(x) __builtin_expect(!!(x), 1)
|
|||
|
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
// Refill page for given class (C6-only in v6-3)
|
|||
|
|
SmallPageMetaV6* small_cold_v6_refill_page(uint32_t class_idx) {
|
|||
|
|
// v6-3: C6-only implementation
|
|||
|
|
if (unlikely(class_idx != SMALL_V6_C6_CLASS_IDX)) {
|
|||
|
|
return NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Get or acquire TLS segment
|
|||
|
|
SmallSegmentV6* seg = small_segment_v6_acquire_for_thread();
|
|||
|
|
if (unlikely(!seg)) {
|
|||
|
|
return NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Find an available page (simple linear scan)
|
|||
|
|
SmallPageMetaV6* page = NULL;
|
|||
|
|
for (uint32_t i = 0; i < seg->num_pages; i++) {
|
|||
|
|
if (seg->page_meta[i].capacity == 0) {
|
|||
|
|
page = &seg->page_meta[i];
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (unlikely(!page)) {
|
|||
|
|
return NULL; // All pages in use
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Initialize page metadata for C6
|
|||
|
|
page->class_idx = (uint8_t)class_idx;
|
|||
|
|
page->capacity = SMALL_PAGE_V6_SIZE / SMALL_V6_C6_BLOCK_SIZE; // 128 blocks
|
|||
|
|
page->used = 0;
|
|||
|
|
page->flags = 0;
|
|||
|
|
|
|||
|
|
// Build freelist for the page
|
|||
|
|
uintptr_t page_offset = (uintptr_t)page->page_idx * SMALL_PAGE_V6_SIZE;
|
|||
|
|
uintptr_t page_base = seg->base + page_offset;
|
|||
|
|
uint8_t* base = (uint8_t*)page_base;
|
|||
|
|
|
|||
|
|
// Build intrusive freelist (last to first for cache locality)
|
|||
|
|
void* freelist = NULL;
|
|||
|
|
for (int i = (int)page->capacity - 1; i >= 0; i--) {
|
|||
|
|
uint8_t* block = base + ((size_t)i * SMALL_V6_C6_BLOCK_SIZE);
|
|||
|
|
|
|||
|
|
// Build freelist using BASE pointers
|
|||
|
|
void* next = freelist;
|
|||
|
|
memcpy(block, &next, sizeof(void*));
|
|||
|
|
freelist = block;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
page->free_list = freelist;
|
|||
|
|
|
|||
|
|
return page;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Retire page (simple reset for v6-2)
|
|||
|
|
void small_cold_v6_retire_page(SmallPageMetaV6* page) {
|
|||
|
|
if (unlikely(!page)) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// v6-2: Simple reset (no actual deallocation)
|
|||
|
|
page->free_list = NULL;
|
|||
|
|
page->used = 0;
|
|||
|
|
page->capacity = 0;
|
|||
|
|
page->class_idx = 0;
|
|||
|
|
page->flags = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Remote operations (dummy for v6-2, C6-heavy is mostly same-thread)
|
|||
|
|
void small_cold_v6_remote_push(SmallPageMetaV6* page, void* ptr, uint32_t tid) {
|
|||
|
|
(void)page;
|
|||
|
|
(void)ptr;
|
|||
|
|
(void)tid;
|
|||
|
|
// Not implemented in v6-2
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void small_cold_v6_remote_drain(SmallHeapCtxV6* ctx) {
|
|||
|
|
(void)ctx;
|
|||
|
|
// Not implemented in v6-2
|
|||
|
|
}
|