18#define HUGE_PAGE_SIZE (2UL * 1024UL * 1024UL)
21typedef struct ck_huge_alloc_entry {
25 struct ck_huge_alloc_entry *next;
26} ck_huge_alloc_entry_t;
33 if (align == 0)
return n;
34 return (n + align - 1) & ~(align - 1);
39 ck_huge_alloc_entry_t *entry = malloc(
sizeof(*entry));
45 entry->was_mmap = was_mmap;
58 if ((*node)->ptr == ptr) {
59 ck_huge_alloc_entry_t *entry = *node;
64 node = &(*node)->next;
79 void *p = mmap(NULL, len,
80 PROT_READ | PROT_WRITE,
81 MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
83 if (p != MAP_FAILED) {
94 fprintf(stderr,
"ck_huge_alloc: aligned_alloc failed for %zu bytes: %s\n",
95 len, strerror(errno));
100 (void)madvise(q, len, MADV_HUGEPAGE);
110 if (!ptr || bytes == 0) {
121 if (entry->was_mmap) {
122 munmap(ptr, entry->len);
132 const char *value = getenv(name);
133 if (!value || !*value) {
136 if (strcmp(value,
"0") == 0 || strcasecmp(value,
"false") == 0 || strcasecmp(value,
"no") == 0) {
157static int ck_bump_alloc_try_mixed(
ck_bump_alloc_t *alloc,
const char *weights_path)
159 long page_size_raw = sysconf(_SC_PAGESIZE);
160 size_t page_size = page_size_raw > 0 ? (size_t)page_size_raw : 4096U;
161 size_t mapped_len = 0;
162 size_t weights_len = 0;
163 size_t weights_file_len = 0;
164 size_t boundary_len = 0;
165 size_t runtime_map_start = 0;
168 uint8_t *base = NULL;
170 if (!alloc || !weights_path || !*weights_path) {
174 fprintf(stderr,
"ck_bump_alloc_init: invalid bump layout for mixed fallback\n");
178 if (alloc->
total_size > SIZE_MAX - (page_size - 1)) {
179 fprintf(stderr,
"ck_bump_alloc_init: bump size overflows page alignment\n");
184 weights_file_len = weights_len - weights_len % page_size;
185 boundary_len = weights_len - weights_file_len;
188 fd = open(weights_path, O_RDONLY | O_CLOEXEC);
190 fprintf(stderr,
"ck_bump_alloc_init: failed to open %s: %s\n", weights_path, strerror(errno));
193 if (fstat(fd, &st) != 0) {
194 fprintf(stderr,
"ck_bump_alloc_init: fstat failed for %s: %s\n", weights_path, strerror(errno));
198 if (!S_ISREG(st.st_mode)) {
199 fprintf(stderr,
"ck_bump_alloc_init: %s is not a regular file\n", weights_path);
207 "ck_bump_alloc_init: weights file too small for mixed mapping (%zu < %zu bytes)\n",
213 base = mmap(NULL, mapped_len, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
214 if (base == MAP_FAILED) {
215 fprintf(stderr,
"ck_bump_alloc_init: reserve mmap failed for %zu bytes: %s\n",
216 mapped_len, strerror(errno));
221 if (weights_file_len > 0) {
222 void *mapped = mmap(base, weights_file_len,
223 PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0);
224 if (mapped == MAP_FAILED) {
225 fprintf(stderr,
"ck_bump_alloc_init: weights mmap failed: %s\n", strerror(errno));
226 munmap(base, mapped_len);
232 if (boundary_len > 0) {
233 uint8_t *boundary = mmap(base + weights_file_len, page_size,
234 PROT_READ | PROT_WRITE,
235 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
237 if (boundary == MAP_FAILED) {
238 fprintf(stderr,
"ck_bump_alloc_init: boundary mmap failed: %s\n", strerror(errno));
239 munmap(base, mapped_len);
245 size_t copy_len = available < boundary_len ? available : boundary_len;
246 while (copied < copy_len) {
247 ssize_t
count = pread(fd, boundary + copied, copy_len - copied,
248 (off_t)(weights_file_len + copied));
249 if (
count < 0 && errno == EINTR) {
253 fprintf(stderr,
"ck_bump_alloc_init: boundary read failed: %s\n",
254 count < 0 ? strerror(errno) :
"unexpected EOF");
255 munmap(base, mapped_len);
259 copied += (size_t)
count;
263 if (runtime_map_start < mapped_len) {
264 void *runtime = mmap(base + runtime_map_start, mapped_len - runtime_map_start,
265 PROT_READ | PROT_WRITE,
266 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
267 if (runtime == MAP_FAILED) {
268 fprintf(stderr,
"ck_bump_alloc_init: runtime mmap failed: %s\n", strerror(errno));
269 munmap(base, mapped_len);
280 "ck_bump_alloc_init: fallback to mixed-backed bump (%zu MiB total, weights file-backed=%zu MiB)\n",
281 alloc->
total_size / (1024U * 1024U), weights_len / (1024U * 1024U));
287 const char *weights_path,
290 size_t activations_base)
293 int disable_mixed = 0;
295 if (!alloc || total_size == 0 ||
297 fprintf(stderr,
"ck_bump_alloc_init: invalid arguments\n");
308 if (weights_base > activations_base || activations_base > total_size) {
310 "ck_bump_alloc_init: invalid bump layout weights=%zu activations=%zu total=%zu\n",
311 weights_base, activations_base, total_size);
319 alloc->
base = (uint8_t *)anon;
327 if (!disable_mixed) {
328 if (ck_bump_alloc_try_mixed(alloc, weights_path) == 0) {
337 "ck_bump_alloc_init: failed to allocate bump arena (%zu bytes, %.2f MiB)\n",
338 total_size, (
double)total_size / (1024.0 * 1024.0));
345 if (!alloc || !alloc->
base) {
void ck_bump_alloc_free(ck_bump_alloc_t *alloc)
int ck_bump_alloc_init(ck_bump_alloc_t *alloc, const char *weights_path, size_t total_size, size_t weights_base, size_t activations_base)
static size_t align_up_bytes(size_t n, size_t align)
static ck_huge_alloc_entry_t * g_alloc_list
static int record_allocation(void *ptr, size_t len, int was_mmap)
static void ck_bump_alloc_reset(ck_bump_alloc_t *alloc)
static int env_flag_enabled(const char *name)
static ck_huge_alloc_entry_t * detach_allocation(void *ptr)
void * ck_huge_alloc(size_t bytes)
static pthread_mutex_t g_alloc_mutex
void ck_huge_free(void *ptr, size_t bytes)
int ck_bump_alloc_needs_weight_materialization(const ck_bump_alloc_t *alloc)
@ CK_BUMP_MODE_MIXED_FILE_BACKED
@ CK_BUMP_MODE_UNINITIALIZED
const uint8_t size_t count