Thread-safe lazy init of the pretrained token lookup map. * Uses double-checked locking: fast path reads an atomic flag. */
| 397 | /* Thread-safe lazy init of the pretrained token lookup map. |
| 398 | * Uses double-checked locking: fast path reads an atomic flag. */ |
| 399 | static void ensure_pretrained_map(void) { |
| 400 | if (atomic_load_explicit(&g_pretrained_ready, memory_order_acquire)) { |
| 401 | return; |
| 402 | } |
| 403 | /* First-time init of the mutex itself (also needs to be thread-safe) */ |
| 404 | int expected = MTX_STATE_UNINIT; |
| 405 | if (atomic_compare_exchange_strong_explicit(&g_pretrained_mtx_init, &expected, |
| 406 | MTX_STATE_INITIALIZING, memory_order_acq_rel, |
| 407 | memory_order_acquire)) { |
| 408 | cbm_mutex_init(&g_pretrained_mtx); |
| 409 | atomic_store_explicit(&g_pretrained_mtx_init, MTX_STATE_READY, memory_order_release); |
| 410 | } else { |
| 411 | /* Spin until another thread finishes initializing the mutex */ |
| 412 | while (atomic_load_explicit(&g_pretrained_mtx_init, memory_order_acquire) != |
| 413 | MTX_STATE_READY) { |
| 414 | /* brief spin */ |
| 415 | } |
| 416 | } |
| 417 | cbm_mutex_lock(&g_pretrained_mtx); |
| 418 | if (!atomic_load_explicit(&g_pretrained_ready, memory_order_acquire)) { |
| 419 | g_pretrained_map = cbm_ht_create(PRETRAINED_TOKEN_COUNT); |
| 420 | char idx_buf[CBM_SZ_16]; |
| 421 | for (int i = 0; i < PRETRAINED_TOKEN_COUNT; i++) { |
| 422 | const char *tok = PRETRAINED_TOKENS[i]; |
| 423 | if (tok && tok[0]) { |
| 424 | snprintf(idx_buf, sizeof(idx_buf), "%d", i); |
| 425 | cbm_ht_set(g_pretrained_map, strdup(tok), strdup(idx_buf)); |
| 426 | } |
| 427 | } |
| 428 | atomic_store_explicit(&g_pretrained_ready, MAP_READY, memory_order_release); |
| 429 | } |
| 430 | cbm_mutex_unlock(&g_pretrained_mtx); |
| 431 | } |
| 432 | |
| 433 | void cbm_sem_ensure_ready(void) { |
| 434 | ensure_pretrained_map(); |
no test coverage detected