// tiny_c7_ultra.c - UF-2: C7 ULTRA TLS freelist (coldは既存 v3 を使用) #include #include #include #include "box/tiny_c7_ultra_box.h" #include "box/smallobject_hotbox_v3_box.h" #include "box/tiny_geometry_box.h" #include "tiny_region_id.h" #include "box/tiny_c7_ultra_segment_box.h" static __thread tiny_c7_ultra_tls_t g_tiny_c7_ultra_tls; static inline void tiny_c7_ultra_clear(tiny_c7_ultra_tls_t* tls) { tls->page_base = NULL; tls->block_size = 0; tls->capacity = 0; tls->used = 0; tls->freelist = NULL; tls->page_idx = 0; tls->page_meta = NULL; } tiny_c7_ultra_tls_t* tiny_c7_ultra_tls_get(void) { return &g_tiny_c7_ultra_tls; } // セグメントから C7 ページを 1 枚借りて自前で carve する static bool tiny_c7_ultra_lease_page(tiny_c7_ultra_tls_t* tls) { tiny_c7_ultra_segment_t* seg = tls->seg; if (!seg) { seg = tiny_c7_ultra_segment_acquire(); if (!seg) return false; tls->seg = seg; } size_t block_sz = tls->block_size ? tls->block_size : (size_t)tiny_stride_for_class(7); if (block_sz == 0) return false; uint32_t capacity = (uint32_t)(seg->page_size / block_sz); if (capacity == 0) return false; // 空きページを 1 枚だけ拾う(UF-3 では最初の空きを線形探索) uint32_t chosen = seg->num_pages; for (uint32_t i = 0; i < seg->num_pages; i++) { tiny_c7_ultra_page_meta_t* pm = &seg->pages[i]; if (pm->capacity == 0 || pm->used == 0) { chosen = i; break; } } if (chosen == seg->num_pages) { return false; } tiny_c7_ultra_page_meta_t* page = &seg->pages[chosen]; uint8_t* base = (uint8_t*)seg->base + ((size_t)chosen * seg->page_size); // freelist を自前で carve void* head = NULL; for (int i = (int)capacity - 1; i >= 0; i--) { uint8_t* blk = base + ((size_t)i * block_sz); *(void**)blk = head; head = blk; } if (!head) { return false; } page->freelist = head; page->capacity = capacity; page->used = 0; tls->page_base = base; tls->block_size = block_sz; tls->capacity = capacity; tls->used = 0; tls->freelist = head; tls->page_idx = chosen; tls->page_meta = page; return true; } void* tiny_c7_ultra_alloc(size_t size) { (void)size; // C7 専用のため未使用 tiny_c7_ultra_tls_t* tls = tiny_c7_ultra_tls_get(); // 1) freelist hit void* p = tls->freelist; if (__builtin_expect(p != NULL, 1)) { void* next = *(void**)p; tls->freelist = next; if (tls->page_meta) { tls->page_meta->freelist = next; if (tls->page_meta->used < tls->page_meta->capacity) { tls->page_meta->used++; } } if (tls->used < tls->capacity) { tls->used++; } return tiny_region_id_write_header(p, 7); } // 2) lease page from existing v3 cold path if (!tiny_c7_ultra_lease_page(tls)) { // safety fallback to v3 return so_alloc(7); } p = tls->freelist; if (__builtin_expect(p == NULL, 0)) { return so_alloc(7); } void* next = *(void**)p; tls->freelist = next; if (tls->page_meta) { tls->page_meta->freelist = next; if (tls->page_meta->used < tls->page_meta->capacity) { tls->page_meta->used++; } } if (tls->used < tls->capacity) { tls->used++; } return tiny_region_id_write_header(p, 7); } void tiny_c7_ultra_free(void* ptr) { tiny_c7_ultra_tls_t* tls = tiny_c7_ultra_tls_get(); if (!ptr) { so_free(7, ptr); return; } tiny_c7_ultra_segment_t* seg = tiny_c7_ultra_segment_from_ptr(ptr); if (!seg) { so_free(7, ptr); return; } uint32_t page_idx = 0; tiny_c7_ultra_page_meta_t* page = tiny_c7_ultra_page_of(ptr, &seg, &page_idx); if (!page) { so_free(7, ptr); return; } const size_t block_sz = tls->block_size ? tls->block_size : (size_t)tiny_stride_for_class(7); const uint32_t cap = page->capacity ? page->capacity : (uint32_t)(seg->page_size / block_sz); uintptr_t base = (uintptr_t)seg->base + ((size_t)page_idx * seg->page_size); uintptr_t paddr = (uintptr_t)ptr; size_t span = block_sz * (size_t)cap; if (paddr < base || paddr >= base + span || ((paddr - base) % block_sz) != 0) { so_free(7, ptr); return; } *(void**)ptr = page->freelist; page->freelist = ptr; if (page->used > 0) { page->used--; } tls->page_meta = page; tls->page_idx = page_idx; tls->page_base = (void*)base; tls->capacity = cap; tls->block_size = block_sz; tls->freelist = page->freelist; tls->used = page->used; }