| 186 | } |
| 187 | |
| 188 | static void diag_write_allocator_stats(void) { |
| 189 | char flag[CBM_SZ_16]; |
| 190 | if (cbm_safe_getenv("CBM_MEM_STATS", flag, sizeof(flag), NULL) == NULL || flag[0] != '1') { |
| 191 | return; |
| 192 | } |
| 193 | char path[CBM_PATH_MAX]; |
| 194 | /* Deliberately NOT inside the diagnostics directory: that tree is |
| 195 | * owner-private with anchored (openat-based) writes on POSIX, which a plain |
| 196 | * path-based open does not satisfy. This file is a developer diagnostic, so |
| 197 | * a predictable temp path keeps it working identically on every platform — |
| 198 | * diag_open_private_stats_file is what makes that path safe to write. */ |
| 199 | int written = |
| 200 | snprintf(path, sizeof(path), "%s/cbm-allocator-stats-%d.txt", cbm_tmpdir(), (int)getpid()); |
| 201 | if (written <= 0 || (size_t)written >= sizeof(path)) { |
| 202 | return; |
| 203 | } |
| 204 | FILE *sink = diag_open_private_stats_file(path); |
| 205 | if (!sink) { |
| 206 | return; |
| 207 | } |
| 208 | mi_stats_print_out(diag_stats_write, sink); |
| 209 | /* Arena slice map: the legend distinguishes free-committed (retained, "_") |
| 210 | * from free-reserved (already returned to the OS, ".") and free-purgeable |
| 211 | * ("~"). That is what localises retained memory to a specific arena state |
| 212 | * instead of inferring it from totals. mi_debug_show_arenas writes through |
| 213 | * mimalloc's own output hook, so redirect that into this file. */ |
| 214 | (void)fputs("\n--- arenas ---\n", sink); |
| 215 | mi_register_output(diag_stats_write, sink); |
| 216 | mi_debug_show_arenas(); |
| 217 | mi_register_output(NULL, NULL); |
| 218 | (void)fputs("\n--- options ---\n", sink); |
| 219 | mi_options_print_out(diag_stats_write, sink); |
| 220 | (void)fclose(sink); |
| 221 | } |
| 222 | |
| 223 | static bool diag_set_output_paths(void) { |
| 224 | int snapshot = snprintf(g_diag_path, sizeof(g_diag_path), "%s/%s", g_diag_directory_path, |
no test coverage detected