| 286 | #endif /* CBM_BIND_TS_ALLOCATOR */ |
| 287 | |
| 288 | void cbm_alloc_init(void) { |
| 289 | #if defined(CBM_BIND_TS_ALLOCATOR) && CBM_BIND_TS_ALLOCATOR |
| 290 | static int alloc_bound = 0; /* single-threaded startup; plain int is fine */ |
| 291 | if (alloc_bound) { |
| 292 | return; |
| 293 | } |
| 294 | alloc_bound = 1; |
| 295 | |
| 296 | /* tree-sitter runtime (was previously bound in cbm_init; consolidated here). */ |
| 297 | ts_set_allocator(mi_malloc, mi_calloc, mi_realloc, mi_free); |
| 298 | |
| 299 | /* sqlite3. SQLITE_CONFIG_MALLOC MUST run before sqlite3_initialize / the |
| 300 | * first sqlite3_open* — otherwise sqlite3_config returns SQLITE_MISUSE |
| 301 | * silently and the binding is ignored. cbm_alloc_init() runs as the very |
| 302 | * first statement of main(), before cbm_mcp_server_new → cbm_store_open*. */ |
| 303 | static sqlite3_mem_methods cbm_sqlite_mem = { |
| 304 | cbm_sqlite_malloc, /* xMalloc */ |
| 305 | cbm_sqlite_free, /* xFree */ |
| 306 | cbm_sqlite_realloc, /* xRealloc */ |
| 307 | cbm_sqlite_size, /* xSize */ |
| 308 | cbm_sqlite_roundup, /* xRoundup */ |
| 309 | cbm_sqlite_meminit, /* xInit */ |
| 310 | cbm_sqlite_memshutdown, /* xShutdown */ |
| 311 | NULL, /* pAppData */ |
| 312 | }; |
| 313 | int sqlite_rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &cbm_sqlite_mem); |
| 314 | assert(sqlite_rc == SQLITE_OK && "SQLITE_CONFIG_MALLOC must run before sqlite3_initialize"); |
| 315 | (void)sqlite_rc; |
| 316 | #endif /* CBM_BIND_TS_ALLOCATOR */ |
| 317 | } |
| 318 | |
| 319 | // --- Init/Shutdown --- |
| 320 | |