| 609 | } tokenize_ctx_t; |
| 610 | |
| 611 | static void tokenize_worker(int worker_id, void *ctx_ptr) { |
| 612 | tokenize_ctx_t *tc = ctx_ptr; |
| 613 | while (true) { |
| 614 | int f = atomic_fetch_add_explicit(&tc->next_idx, SKIP_ONE, memory_order_relaxed); |
| 615 | if (f >= tc->func_count) { |
| 616 | break; |
| 617 | } |
| 618 | |
| 619 | const cbm_gbuf_node_t *n = tc->node_ptrs[f]; |
| 620 | /* Write directly into the shared buffer slice for this function — the |
| 621 | * strdup'd tokens are owned by all_tokens[] from the moment they land |
| 622 | * in this slot, which avoids a spurious analyzer "leak" diagnostic on |
| 623 | * the previous stack-local relay pattern. */ |
| 624 | char **dst = &tc->all_tokens[(ptrdiff_t)f * CBM_SEM_MAX_TOKENS]; |
| 625 | int count = tokenize_node(n, tc->gbuf, dst, CBM_SEM_MAX_TOKENS); |
| 626 | count = inject_pattern_tokens(n, tc->gbuf, dst, count, CBM_SEM_MAX_TOKENS); |
| 627 | if (tc->pools && tc->pools[worker_id]) { |
| 628 | CBMHashTable *pool = tc->pools[worker_id]; |
| 629 | for (int t = 0; t < count; t++) { |
| 630 | char *canon = cbm_ht_get(pool, dst[t]); |
| 631 | if (canon) { |
| 632 | free(dst[t]); |
| 633 | dst[t] = canon; |
| 634 | } else { |
| 635 | cbm_ht_set(pool, dst[t], dst[t]); /* key borrows the value */ |
| 636 | } |
| 637 | } |
| 638 | } |
| 639 | tc->token_counts[f] = count; |
| 640 | } |
| 641 | } |
| 642 | |
| 643 | /* ── Parallel Phase 4: Build per-function vectors ────────────────── */ |
| 644 |
nothing calls this directly
no test coverage detected