Safe for concurrent callers: only publishes INITED after cbm_mutex_init() * has completed. Callers that lose the CAS race spin until init finishes. */
| 371 | /* Safe for concurrent callers: only publishes INITED after cbm_mutex_init() |
| 372 | * has completed. Callers that lose the CAS race spin until init finishes. */ |
| 373 | void cbm_ui_log_init(void) { |
| 374 | int state = atomic_load(&g_log_mutex_init); |
| 375 | if (state == CBM_LOG_MUTEX_INITED) |
| 376 | return; |
| 377 | |
| 378 | state = CBM_LOG_MUTEX_UNINIT; |
| 379 | if (atomic_compare_exchange_strong(&g_log_mutex_init, &state, CBM_LOG_MUTEX_INITING)) { |
| 380 | cbm_mutex_init(&g_log_mutex); |
| 381 | atomic_store(&g_log_mutex_init, CBM_LOG_MUTEX_INITED); |
| 382 | return; |
| 383 | } |
| 384 | |
| 385 | /* Another thread is initializing — spin until done */ |
| 386 | while (atomic_load(&g_log_mutex_init) != CBM_LOG_MUTEX_INITED) { |
| 387 | cbm_usleep(1000); /* 1ms */ |
| 388 | } |
| 389 | } |
| 390 | |
| 391 | /* Called from a log hook — appends a line to the ring buffer (thread-safe) */ |
| 392 | void cbm_ui_log_append(const char *line) { |
no test coverage detected