107 lines
3.0 KiB
C
107 lines
3.0 KiB
C
|
|
// tiny_c7_ultra_segment.c - C7 ULTRA 専用セグメント管理(UF-3)
|
|||
|
|
|
|||
|
|
#include "box/tiny_c7_ultra_segment_box.h"
|
|||
|
|
|
|||
|
|
#include <errno.h>
|
|||
|
|
#include <stdint.h>
|
|||
|
|
#include <stdlib.h>
|
|||
|
|
#include <string.h>
|
|||
|
|
#include <sys/mman.h>
|
|||
|
|
|
|||
|
|
// 2MiB セグメントを 64KiB ページに分割(C7 専用、pow2 で mask しやすく)
|
|||
|
|
#define TINY_C7_ULTRA_SEG_SIZE ((size_t)(2 * 1024 * 1024))
|
|||
|
|
#define TINY_C7_ULTRA_PAGE_SIZE ((size_t)(64 * 1024))
|
|||
|
|
|
|||
|
|
static __thread tiny_c7_ultra_segment_t* g_ultra_seg;
|
|||
|
|
|
|||
|
|
static inline void tiny_c7_ultra_segment_clear(tiny_c7_ultra_segment_t* seg) {
|
|||
|
|
if (!seg) return;
|
|||
|
|
seg->base = NULL;
|
|||
|
|
seg->seg_size = 0;
|
|||
|
|
seg->page_size = 0;
|
|||
|
|
seg->num_pages = 0;
|
|||
|
|
seg->pages = NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
tiny_c7_ultra_segment_t* tiny_c7_ultra_segment_acquire(void) {
|
|||
|
|
if (g_ultra_seg) {
|
|||
|
|
return g_ultra_seg;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
tiny_c7_ultra_segment_t* seg =
|
|||
|
|
(tiny_c7_ultra_segment_t*)calloc(1, sizeof(tiny_c7_ultra_segment_t));
|
|||
|
|
if (!seg) {
|
|||
|
|
return NULL;
|
|||
|
|
}
|
|||
|
|
seg->seg_size = TINY_C7_ULTRA_SEG_SIZE;
|
|||
|
|
seg->page_size = TINY_C7_ULTRA_PAGE_SIZE;
|
|||
|
|
seg->num_pages = (uint32_t)(seg->seg_size / seg->page_size);
|
|||
|
|
|
|||
|
|
seg->pages = (tiny_c7_ultra_page_meta_t*)calloc(seg->num_pages,
|
|||
|
|
sizeof(tiny_c7_ultra_page_meta_t));
|
|||
|
|
if (!seg->pages) {
|
|||
|
|
free(seg);
|
|||
|
|
return NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void* base = mmap(NULL, seg->seg_size, PROT_READ | PROT_WRITE,
|
|||
|
|
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
|||
|
|
if (base == MAP_FAILED) {
|
|||
|
|
int saved = errno;
|
|||
|
|
free(seg->pages);
|
|||
|
|
free(seg);
|
|||
|
|
(void)saved;
|
|||
|
|
return NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
seg->base = base;
|
|||
|
|
g_ultra_seg = seg;
|
|||
|
|
return seg;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void tiny_c7_ultra_segment_release(tiny_c7_ultra_segment_t* seg) {
|
|||
|
|
if (!seg) return;
|
|||
|
|
if (seg->base && seg->seg_size) {
|
|||
|
|
munmap(seg->base, seg->seg_size);
|
|||
|
|
}
|
|||
|
|
free(seg->pages);
|
|||
|
|
if (seg == g_ultra_seg) {
|
|||
|
|
g_ultra_seg = NULL;
|
|||
|
|
}
|
|||
|
|
free(seg);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
tiny_c7_ultra_segment_t* tiny_c7_ultra_segment_from_ptr(void* p) {
|
|||
|
|
tiny_c7_ultra_segment_t* seg = g_ultra_seg;
|
|||
|
|
if (!seg || !seg->base || seg->seg_size == 0) return NULL;
|
|||
|
|
uintptr_t base = (uintptr_t)seg->base;
|
|||
|
|
uintptr_t addr = (uintptr_t)p;
|
|||
|
|
if (addr < base || addr >= base + seg->seg_size) {
|
|||
|
|
return NULL;
|
|||
|
|
}
|
|||
|
|
return seg;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
tiny_c7_ultra_page_meta_t* tiny_c7_ultra_page_of(void* p,
|
|||
|
|
tiny_c7_ultra_segment_t** out_seg,
|
|||
|
|
uint32_t* out_page_idx) {
|
|||
|
|
tiny_c7_ultra_segment_t* seg = tiny_c7_ultra_segment_from_ptr(p);
|
|||
|
|
if (!seg) {
|
|||
|
|
return NULL;
|
|||
|
|
}
|
|||
|
|
uintptr_t base = (uintptr_t)seg->base;
|
|||
|
|
uintptr_t addr = (uintptr_t)p;
|
|||
|
|
size_t offset = (size_t)(addr - base);
|
|||
|
|
uint32_t idx = (uint32_t)(offset / seg->page_size);
|
|||
|
|
if (idx >= seg->num_pages) {
|
|||
|
|
return NULL;
|
|||
|
|
}
|
|||
|
|
if (out_seg) {
|
|||
|
|
*out_seg = seg;
|
|||
|
|
}
|
|||
|
|
if (out_page_idx) {
|
|||
|
|
*out_page_idx = idx;
|
|||
|
|
}
|
|||
|
|
return &seg->pages[idx];
|
|||
|
|
}
|