| 419 | #endif /* CBM_BIND_TS_ALLOCATOR */ |
| 420 | |
| 421 | void cbm_alloc_init(void) { |
| 422 | #if defined(CBM_BIND_TS_ALLOCATOR) && CBM_BIND_TS_ALLOCATOR |
| 423 | static int alloc_bound = 0; /* single-threaded startup; plain int is fine */ |
| 424 | if (alloc_bound) { |
| 425 | return; |
| 426 | } |
| 427 | alloc_bound = 1; |
| 428 | |
| 429 | /* tree-sitter runtime (was previously bound in cbm_init; consolidated here). */ |
| 430 | ts_set_allocator(cbm_ts_malloc, cbm_ts_calloc, cbm_ts_realloc, cbm_ts_free); |
| 431 | |
| 432 | /* sqlite3. SQLITE_CONFIG_MALLOC MUST run before sqlite3_initialize / the |
| 433 | * first sqlite3_open* — otherwise sqlite3_config returns SQLITE_MISUSE |
| 434 | * silently and the binding is ignored. cbm_alloc_init() runs as the very |
| 435 | * first statement of main(), before cbm_mcp_server_new → cbm_store_open*. */ |
| 436 | static sqlite3_mem_methods cbm_sqlite_mem = { |
| 437 | cbm_sqlite_malloc, /* xMalloc */ |
| 438 | cbm_sqlite_free, /* xFree */ |
| 439 | cbm_sqlite_realloc, /* xRealloc */ |
| 440 | cbm_sqlite_size, /* xSize */ |
| 441 | cbm_sqlite_roundup, /* xRoundup */ |
| 442 | cbm_sqlite_meminit, /* xInit */ |
| 443 | cbm_sqlite_memshutdown, /* xShutdown */ |
| 444 | NULL, /* pAppData */ |
| 445 | }; |
| 446 | int sqlite_rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &cbm_sqlite_mem); |
| 447 | assert(sqlite_rc == SQLITE_OK && "SQLITE_CONFIG_MALLOC must run before sqlite3_initialize"); |
| 448 | (void)sqlite_rc; |
| 449 | #endif /* CBM_BIND_TS_ALLOCATOR */ |
| 450 | } |
| 451 | |
| 452 | // --- Init/Shutdown --- |
| 453 | |