lib/alloc/src/diagnostics.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const build_options = @import("build_options");
3 const deadalloc = @import("deadalloc");
4 const sys = @import("sys");
5
6 const Allocator = std.mem.Allocator;
7
8 pub const mode: ?deadalloc.Mode = parseMode();
9
10 var lock: std.atomic.Mutex = .unlocked;
11 var initialized = false;
12 var storage: deadalloc.DeadAllocator = undefined;
13
14 pub fn config() ?deadalloc.Config {
15 const diagnostics_mode = mode orelse return null;
16 return deadalloc.Config.diagnostic(diagnostics_mode);
17 }
18
19 pub fn report() ?deadalloc.Report {
20 if (comptime mode == null) return null;
21 lockInit();
22 defer unlockInit();
23 if (!initialized) return .{};
24 return storage.report();
25 }
26
27 pub fn processAllocator(diagnostic_config: deadalloc.Config) Allocator {
28 lockInit();
29 defer unlockInit();
30 if (!initialized) {
31 storage = deadalloc.DeadAllocator.init(baseProcessAllocator(), diagnostic_config);
32 initialized = true;
33 }
34 return storage.allocator();
35 }
36
37 pub fn baseProcessAllocator() Allocator {
38 return sys.allocator.processAllocator();
39 }
40
41 fn parseMode() ?deadalloc.Mode {
42 if (std.mem.eql(u8, build_options.allocator_diagnostics, "off")) return null;
43 if (std.mem.eql(u8, build_options.allocator_diagnostics, "diehard")) return .diehard;
44 if (std.mem.eql(u8, build_options.allocator_diagnostics, "dieharder")) return .dieharder;
45 if (std.mem.eql(u8, build_options.allocator_diagnostics, "exterminator")) return .exterminator;
46 @compileError("unknown allocator diagnostics mode");
47 }
48
49 fn lockInit() void {
50 while (!lock.tryLock()) std.atomic.spinLoopHint();
51 }
52
53 fn unlockInit() void {
54 lock.unlock();
55 }