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 }