Safe for concurrent callers: only publishes INITED after cbm_mutex_init() * has completed. Callers that lose the CAS race spin until init finishes. */
| 412 | /* Safe for concurrent callers: only publishes INITED after cbm_mutex_init() |
| 413 | * has completed. Callers that lose the CAS race spin until init finishes. */ |
| 414 | void cbm_ui_log_init(void) { |
| 415 | int state = atomic_load(&g_log_mutex_init); |
| 416 | if (state == CBM_LOG_MUTEX_INITED) |
| 417 | return; |
| 418 | |
| 419 | state = CBM_LOG_MUTEX_UNINIT; |
| 420 | if (atomic_compare_exchange_strong(&g_log_mutex_init, &state, CBM_LOG_MUTEX_INITING)) { |
| 421 | cbm_mutex_init(&g_log_mutex); |
| 422 | atomic_store(&g_log_mutex_init, CBM_LOG_MUTEX_INITED); |
| 423 | return; |
| 424 | } |
| 425 | |
| 426 | /* Another thread is initializing — spin until done */ |
| 427 | while (atomic_load(&g_log_mutex_init) != CBM_LOG_MUTEX_INITED) { |
| 428 | cbm_usleep(1000); /* 1ms */ |
| 429 | } |
| 430 | } |
| 431 | |
| 432 | /* Called from a log hook — appends a line to the ring buffer (thread-safe) */ |
| 433 | void cbm_ui_log_append(const char *line) { |
no test coverage detected