| 214 | } |
| 215 | |
| 216 | static void emit_line(const char *line) { |
| 217 | /* Load ONCE: re-reading the global between the test and the call would |
| 218 | * let a concurrent cbm_log_set_sink turn a checked pointer into a NULL |
| 219 | * call. */ |
| 220 | cbm_log_sink_fn sink = atomic_load_explicit(&g_log_sink, memory_order_relaxed); |
| 221 | if (sink) { |
| 222 | sink(line); |
| 223 | if (atomic_load_explicit(&g_log_sink_mode, memory_order_relaxed) == CBM_LOG_SINK_REPLACE) { |
| 224 | return; |
| 225 | } |
| 226 | } |
| 227 | (void)fprintf(stderr, "%s\n", line); |
| 228 | } |
| 229 | |
| 230 | void cbm_log(CBMLogLevel level, const char *msg, ...) { |
| 231 | if (level < atomic_load_explicit(&g_log_level, memory_order_relaxed)) { |
no outgoing calls
no test coverage detected