| ... | @@ -148,12 +148,56 @@ const CAllocator = struct { | ... | @@ -148,12 +148,56 @@ const CAllocator = struct { |
| 148 | } | 148 | } |
| 149 | }; | 149 | }; |
| 150 | | 150 | |
| | 151 | /// Supports the full Allocator interface, including alignment, and exploiting |
| | 152 | /// `malloc_usable_size` if available. For an allocator that directly calls |
| | 153 | /// `malloc`/`free`, see `raw_c_allocator`. |
| 151 | pub const c_allocator = &c_allocator_state; | 154 | pub const c_allocator = &c_allocator_state; |
| 152 | var c_allocator_state = Allocator{ | 155 | var c_allocator_state = Allocator{ |
| 153 | .allocFn = CAllocator.alloc, | 156 | .allocFn = CAllocator.alloc, |
| 154 | .resizeFn = CAllocator.resize, | 157 | .resizeFn = CAllocator.resize, |
| 155 | }; | 158 | }; |
| 156 | | 159 | |
| | 160 | /// Asserts allocations are within `@alignOf(std.c.max_align_t)` and directly calls |
| | 161 | /// `malloc`/`free`. Does not attempt to utilize `malloc_usable_size`. |
| | 162 | /// This allocator is safe to use as the backing allocator with |
| | 163 | /// `ArenaAllocator` and `GeneralPurposeAllocator`, and is more optimal in these cases |
| | 164 | /// than to using `c_allocator`. |
| | 165 | pub const raw_c_allocator = &raw_c_allocator_state; |
| | 166 | var raw_c_allocator_state = Allocator{ |
| | 167 | .allocFn = rawCAlloc, |
| | 168 | .resizeFn = rawCResize, |
| | 169 | }; |
| | 170 | |
| | 171 | fn rawCAlloc( |
| | 172 | self: *Allocator, |
| | 173 | len: usize, |
| | 174 | ptr_align: u29, |
| | 175 | len_align: u29, |
| | 176 | ret_addr: usize, |
| | 177 | ) Allocator.Error![]u8 { |
| | 178 | assert(ptr_align <= @alignOf(std.c.max_align_t)); |
| | 179 | const ptr = @ptrCast([*]u8, c.malloc(len) orelse return error.OutOfMemory); |
| | 180 | return ptr[0..len]; |
| | 181 | } |
| | 182 | |
| | 183 | fn rawCResize( |
| | 184 | self: *Allocator, |
| | 185 | buf: []u8, |
| | 186 | old_align: u29, |
| | 187 | new_len: usize, |
| | 188 | len_align: u29, |
| | 189 | ret_addr: usize, |
| | 190 | ) Allocator.Error!usize { |
| | 191 | if (new_len == 0) { |
| | 192 | c.free(buf.ptr); |
| | 193 | return 0; |
| | 194 | } |
| | 195 | if (new_len <= buf.len) { |
| | 196 | return mem.alignAllocLen(buf.len, new_len, len_align); |
| | 197 | } |
| | 198 | return error.OutOfMemory; |
| | 199 | } |
| | 200 | |
| 157 | /// This allocator makes a syscall directly for every allocation and free. | 201 | /// This allocator makes a syscall directly for every allocation and free. |
| 158 | /// Thread-safe and lock-free. | 202 | /// Thread-safe and lock-free. |
| 159 | pub const page_allocator = if (std.Target.current.isWasm()) | 203 | pub const page_allocator = if (std.Target.current.isWasm()) |
| ... | @@ -804,6 +848,12 @@ test "c_allocator" { | ... | @@ -804,6 +848,12 @@ test "c_allocator" { |
| 804 | } | 848 | } |
| 805 | } | 849 | } |
| 806 | | 850 | |
| | 851 | test "raw_c_allocator" { |
| | 852 | if (builtin.link_libc) { |
| | 853 | try testAllocator(raw_c_allocator); |
| | 854 | } |
| | 855 | } |
| | 856 | |
| 807 | test "WasmPageAllocator internals" { | 857 | test "WasmPageAllocator internals" { |
| 808 | if (comptime std.Target.current.isWasm()) { | 858 | if (comptime std.Target.current.isWasm()) { |
| 809 | const conventional_memsize = WasmPageAllocator.conventional.totalPages() * mem.page_size; | 859 | const conventional_memsize = WasmPageAllocator.conventional.totalPages() * mem.page_size; |
| ... | @@ -958,6 +1008,7 @@ test "ThreadSafeFixedBufferAllocator" { | ... | @@ -958,6 +1008,7 @@ test "ThreadSafeFixedBufferAllocator" { |
| 958 | try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator); | 1008 | try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator); |
| 959 | } | 1009 | } |
| 960 | | 1010 | |
| | 1011 | /// This one should not try alignments that exceed what C malloc can handle. |
| 961 | pub fn testAllocator(base_allocator: *mem.Allocator) !void { | 1012 | pub fn testAllocator(base_allocator: *mem.Allocator) !void { |
| 962 | var validationAllocator = mem.validationWrap(base_allocator); | 1013 | var validationAllocator = mem.validationWrap(base_allocator); |
| 963 | const allocator = &validationAllocator.allocator; | 1014 | const allocator = &validationAllocator.allocator; |