| ... | @@ -142,6 +142,11 @@ pub const Config = struct { | ... | @@ -142,6 +142,11 @@ pub const Config = struct { |
| 142 | | 142 | |
| 143 | /// Whether the allocator may be used simultaneously from multiple threads. | 143 | /// Whether the allocator may be used simultaneously from multiple threads. |
| 144 | thread_safe: bool = !std.builtin.single_threaded, | 144 | thread_safe: bool = !std.builtin.single_threaded, |
| | 145 | |
| | 146 | /// This is a temporary debugging trick you can use to turn segfaults into more helpful |
| | 147 | /// logged error messages with stack trace details. The downside is that every allocation |
| | 148 | /// will be leaked! |
| | 149 | never_unmap: bool = false, |
| 145 | }; | 150 | }; |
| 146 | | 151 | |
| 147 | pub fn GeneralPurposeAllocator(comptime config: Config) type { | 152 | pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| ... | @@ -416,7 +421,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -416,7 +421,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 416 | bucket.prev.next = bucket.next; | 421 | bucket.prev.next = bucket.next; |
| 417 | self.buckets[bucket_index] = bucket.prev; | 422 | self.buckets[bucket_index] = bucket.prev; |
| 418 | } | 423 | } |
| 419 | self.backing_allocator.free(bucket.page[0..page_size]); | 424 | if (!config.never_unmap) { |
| | 425 | self.backing_allocator.free(bucket.page[0..page_size]); |
| | 426 | } |
| 420 | const bucket_size = bucketSize(size_class); | 427 | const bucket_size = bucketSize(size_class); |
| 421 | const bucket_slice = @ptrCast([*]align(@alignOf(BucketHeader)) u8, bucket)[0..bucket_size]; | 428 | const bucket_slice = @ptrCast([*]align(@alignOf(BucketHeader)) u8, bucket)[0..bucket_size]; |
| 422 | self.backing_allocator.free(bucket_slice); | 429 | self.backing_allocator.free(bucket_slice); |