authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-18 22:09:34-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-18 22:09:34-07:00
log13cccdd92cd89242801218aa808dec1df14f482d
treeb3ffb9359a45d4fbcbb9311828bfbb5c8a24c2ae
parent02a4e5a4bfc605fa8fc62a2d6ad58f0a52bc2ad0

add std.heap.raw_c_allocator

This API does what `std.heap.c_allocator` previously did. See the new doc comments for more details.

3 files changed, 62 insertions(+), 1 deletions(-)

lib/std/c.zig+10
......@@ -332,3 +332,13 @@ pub extern "c" fn prctl(option: c_int, ...) c_int;
332332
333333pub extern "c" fn getrlimit(resource: rlimit_resource, rlim: *rlimit) c_int;
334334pub extern "c" fn setrlimit(resource: rlimit_resource, rlim: *const rlimit) c_int;
335
336pub const max_align_t = if (std.Target.current.abi == .msvc)
337 f64
338else if (std.Target.current.isDarwin())
339 c_longdouble
340else
341 extern struct {
342 a: c_longlong,
343 b: c_longdouble,
344 };
lib/std/heap.zig+51
......@@ -148,12 +148,56 @@ const CAllocator = struct {
148148 }
149149};
150150
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`.
151154pub const c_allocator = &c_allocator_state;
152155var c_allocator_state = Allocator{
153156 .allocFn = CAllocator.alloc,
154157 .resizeFn = CAllocator.resize,
155158};
156159
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`.
165pub const raw_c_allocator = &raw_c_allocator_state;
166var raw_c_allocator_state = Allocator{
167 .allocFn = rawCAlloc,
168 .resizeFn = rawCResize,
169};
170
171fn 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
183fn 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
157201/// This allocator makes a syscall directly for every allocation and free.
158202/// Thread-safe and lock-free.
159203pub const page_allocator = if (std.Target.current.isWasm())
......@@ -804,6 +848,12 @@ test "c_allocator" {
804848 }
805849}
806850
851test "raw_c_allocator" {
852 if (builtin.link_libc) {
853 try testAllocator(raw_c_allocator);
854 }
855}
856
807857test "WasmPageAllocator internals" {
808858 if (comptime std.Target.current.isWasm()) {
809859 const conventional_memsize = WasmPageAllocator.conventional.totalPages() * mem.page_size;
......@@ -958,6 +1008,7 @@ test "ThreadSafeFixedBufferAllocator" {
9581008 try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator);
9591009}
9601010
1011/// This one should not try alignments that exceed what C malloc can handle.
9611012pub fn testAllocator(base_allocator: *mem.Allocator) !void {
9621013 var validationAllocator = mem.validationWrap(base_allocator);
9631014 const allocator = &validationAllocator.allocator;
src/main.zig+1-1
......@@ -103,7 +103,7 @@ pub fn log(
103103var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
104104
105105pub fn main() anyerror!void {
106 const gpa = if (std.builtin.link_libc) std.heap.c_allocator else &general_purpose_allocator.allocator;
106 const gpa = if (std.builtin.link_libc) std.heap.raw_c_allocator else &general_purpose_allocator.allocator;
107107 defer if (!std.builtin.link_libc) {
108108 _ = general_purpose_allocator.deinit();
109109 };