| ... | ... | @@ -64,9 +64,9 @@ const Header = packed struct(u64) { |
| 64 | 64 | }; |
| 65 | 65 | |
| 66 | 66 | fn malloc(n: usize) callconv(.c) ?[*]align(alignment_bytes) u8 { |
| 67 | | const size = std.math.cast(Header.Size, n) orelse return null; |
| 67 | const size = std.math.cast(Header.Size, n) orelse return nomem(); |
| 68 | 68 | const ptr: [*]align(alignment_bytes) u8 = @alignCast( |
| 69 | | vtable.alloc(no_context, n + alignment_bytes, alignment, no_ra) orelse return null, |
| 69 | vtable.alloc(no_context, n + alignment_bytes, alignment, no_ra) orelse return nomem(), |
| 70 | 70 | ); |
| 71 | 71 | const base = ptr + alignment_bytes; |
| 72 | 72 | const header: *Header = .fromBase(base); |
| ... | ... | @@ -78,6 +78,11 @@ fn malloc(n: usize) callconv(.c) ?[*]align(alignment_bytes) u8 { |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | 80 | fn aligned_alloc(alloc_alignment: usize, n: usize) callconv(.c) ?[*]align(alignment_bytes) u8 { |
| 81 | return aligned_alloc_inner(alloc_alignment, n) orelse return nomem(); |
| 82 | } |
| 83 | |
| 84 | /// Avoids setting errno so it can be called by `posix_memalign`. |
| 85 | fn aligned_alloc_inner(alloc_alignment: usize, n: usize) ?[*]align(alignment_bytes) u8 { |
| 81 | 86 | const size = std.math.cast(Header.Size, n) orelse return null; |
| 82 | 87 | const max_align = alignment.max(.fromByteUnits(alloc_alignment)); |
| 83 | 88 | const max_align_bytes = max_align.toByteUnits(); |
| ... | ... | @@ -94,7 +99,7 @@ fn aligned_alloc(alloc_alignment: usize, n: usize) callconv(.c) ?[*]align(alignm |
| 94 | 99 | } |
| 95 | 100 | |
| 96 | 101 | fn calloc(elems: usize, len: usize) callconv(.c) ?[*]align(alignment_bytes) u8 { |
| 97 | | const n = std.math.mul(usize, elems, len) catch return null; |
| 102 | const n = std.math.mul(usize, elems, len) catch return nomem(); |
| 98 | 103 | const base = malloc(n) orelse return null; |
| 99 | 104 | @memset(base[0..n], 0); |
| 100 | 105 | return base; |
| ... | ... | @@ -106,7 +111,7 @@ fn realloc(opt_old_base: ?[*]align(alignment_bytes) u8, n: usize) callconv(.c) ? |
| 106 | 111 | return null; |
| 107 | 112 | } |
| 108 | 113 | const old_base = opt_old_base orelse return malloc(n); |
| 109 | | const new_size = std.math.cast(Header.Size, n) orelse return null; |
| 114 | const new_size = std.math.cast(Header.Size, n) orelse return nomem(); |
| 110 | 115 | const old_header: *Header = .fromBase(old_base); |
| 111 | 116 | assert(old_header.padding == 0); |
| 112 | 117 | const old_size = old_header.size; |
| ... | ... | @@ -122,7 +127,8 @@ fn realloc(opt_old_base: ?[*]align(alignment_bytes) u8, n: usize) callconv(.c) ? |
| 122 | 127 | no_ra, |
| 123 | 128 | )) |new_ptr| @alignCast(new_ptr + old_alignment_bytes) else b: { |
| 124 | 129 | const new_ptr: [*]align(alignment_bytes) u8 = @alignCast( |
| 125 | | vtable.alloc(no_context, n + old_alignment_bytes, old_alignment, no_ra) orelse return null, |
| 130 | vtable.alloc(no_context, n + old_alignment_bytes, old_alignment, no_ra) orelse |
| 131 | return nomem(), |
| 126 | 132 | ); |
| 127 | 133 | const new_base: [*]align(alignment_bytes) u8 = @alignCast(new_ptr + old_alignment_bytes); |
| 128 | 134 | const copy_len = @min(new_size, old_size); |
| ... | ... | @@ -139,7 +145,7 @@ fn realloc(opt_old_base: ?[*]align(alignment_bytes) u8, n: usize) callconv(.c) ? |
| 139 | 145 | } |
| 140 | 146 | |
| 141 | 147 | fn reallocarray(opt_base: ?[*]align(alignment_bytes) u8, elems: usize, len: usize) callconv(.c) ?[*]align(alignment_bytes) u8 { |
| 142 | | const n = std.math.mul(usize, elems, len) catch return null; |
| 148 | const n = std.math.mul(usize, elems, len) catch return nomem(); |
| 143 | 149 | return realloc(opt_base, n); |
| 144 | 150 | } |
| 145 | 151 | |
| ... | ... | @@ -173,10 +179,14 @@ fn memalign(alloc_alignment: usize, n: usize) callconv(.c) ?[*]align(alignment_b |
| 173 | 179 | |
| 174 | 180 | fn posix_memalign(result: *?[*]align(alignment_bytes) u8, alloc_alignment: usize, n: usize) callconv(.c) c_int { |
| 175 | 181 | if (alloc_alignment < @sizeOf(*anyopaque)) return @intFromEnum(std.c.E.INVAL); |
| 176 | | if (n == 0) { |
| 177 | | result.* = null; |
| 178 | | } else { |
| 179 | | result.* = aligned_alloc(alloc_alignment, n) orelse return @intFromEnum(std.c.E.NOMEM); |
| 180 | | } |
| 182 | result.* = aligned_alloc_inner(alloc_alignment, n) orelse return @intFromEnum(std.c.E.NOMEM); |
| 181 | 183 | return 0; |
| 182 | 184 | } |
| 185 | |
| 186 | /// Libc memory allocation functions must set errno in addition to returning |
| 187 | /// `null`. |
| 188 | fn nomem() ?[*]align(alignment_bytes) u8 { |
| 189 | @branchHint(.cold); |
| 190 | std.c._errno().* = @intFromEnum(std.c.E.NOMEM); |
| 191 | return null; |
| 192 | } |