| 313 | #endif /* CBM_BIND_TS_ALLOCATOR */ |
| 314 | |
| 315 | void cbm_alloc_init(void) { |
| 316 | #if defined(CBM_BIND_TS_ALLOCATOR) && CBM_BIND_TS_ALLOCATOR |
| 317 | static int alloc_bound = 0; /* single-threaded startup; plain int is fine */ |
| 318 | if (alloc_bound) { |
| 319 | return; |
| 320 | } |
| 321 | alloc_bound = 1; |
| 322 | |
| 323 | /* tree-sitter runtime (was previously bound in cbm_init; consolidated here). */ |
| 324 | ts_set_allocator(cbm_ts_malloc, cbm_ts_calloc, cbm_ts_realloc, cbm_ts_free); |
| 325 | |
| 326 | /* sqlite3. SQLITE_CONFIG_MALLOC MUST run before sqlite3_initialize / the |
| 327 | * first sqlite3_open* — otherwise sqlite3_config returns SQLITE_MISUSE |
| 328 | * silently and the binding is ignored. cbm_alloc_init() runs as the very |
| 329 | * first statement of main(), before cbm_mcp_server_new → cbm_store_open*. */ |
| 330 | static sqlite3_mem_methods cbm_sqlite_mem = { |
| 331 | cbm_sqlite_malloc, /* xMalloc */ |
| 332 | cbm_sqlite_free, /* xFree */ |
| 333 | cbm_sqlite_realloc, /* xRealloc */ |
| 334 | cbm_sqlite_size, /* xSize */ |
| 335 | cbm_sqlite_roundup, /* xRoundup */ |
| 336 | cbm_sqlite_meminit, /* xInit */ |
| 337 | cbm_sqlite_memshutdown, /* xShutdown */ |
| 338 | NULL, /* pAppData */ |
| 339 | }; |
| 340 | int sqlite_rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &cbm_sqlite_mem); |
| 341 | assert(sqlite_rc == SQLITE_OK && "SQLITE_CONFIG_MALLOC must run before sqlite3_initialize"); |
| 342 | (void)sqlite_rc; |
| 343 | #endif /* CBM_BIND_TS_ALLOCATOR */ |
| 344 | } |
| 345 | |
| 346 | // --- Init/Shutdown --- |
| 347 | |