| ... | @@ -146,9 +146,6 @@ test defaultQueryPageSize { | ... | @@ -146,9 +146,6 @@ test defaultQueryPageSize { |
| 146 | /// possible, but large requested alignments may require larger buffers in order to | 146 | /// possible, but large requested alignments may require larger buffers in order to |
| 147 | /// satisfy the request. As well as `malloc`, `realloc`, and `free`, the extension | 147 | /// satisfy the request. As well as `malloc`, `realloc`, and `free`, the extension |
| 148 | /// functions `malloc_usable_size` and `posix_memalign` are used when available. | 148 | /// functions `malloc_usable_size` and `posix_memalign` are used when available. |
| 149 | /// | | |
| 150 | /// For an allocator that directly calls `malloc`/`realloc`/`free`, with no padding | | |
| 151 | /// or special handling, see `raw_c_allocator`. | | |
| 152 | pub const c_allocator: Allocator = .{ | 149 | pub const c_allocator: Allocator = .{ |
| 153 | .ptr = undefined, | 150 | .ptr = undefined, |
| 154 | .vtable = &c_allocator_impl.vtable, | 151 | .vtable = &c_allocator_impl.vtable, |
| ... | @@ -228,8 +225,19 @@ const c_allocator_impl = struct { | ... | @@ -228,8 +225,19 @@ const c_allocator_impl = struct { |
| 228 | assert(len > 0); | 225 | assert(len > 0); |
| 229 | switch (allocStrat(alignment)) { | 226 | switch (allocStrat(alignment)) { |
| 230 | .raw => { | 227 | .raw => { |
| 231 | // C only needs to respect `max_align_t` up to the allocation size due to object | 228 | // `std.c.max_align_t` isn't the whole story, because if `len` is smaller than |
| 232 | // alignment rules. If necessary, extend the allocation size. | 229 | // every C type with alignment `max_align_t`, the allocation can be less-aligned. |
| | 230 | // The implementation need only guarantee that any type of length `len` would be |
| | 231 | // suitably aligned. |
| | 232 | // |
| | 233 | // For instance, if `len == 8` and `alignment == .@"16"`, then `malloc` may not |
| | 234 | // fulfil this request, because there is necessarily no C type with 8-byte size |
| | 235 | // but 16-byte alignment. |
| | 236 | // |
| | 237 | // In theory, the resulting rule here would be target-specific, but in practice, |
| | 238 | // the smallest type with an alignment of `max_align_t` has the same size (it's |
| | 239 | // usually `c_longdouble`), so we can just extend the allocation size up to the |
| | 240 | // alignment of `max_align_t` if necessary. |
| 233 | const actual_len = @max(len, @alignOf(std.c.max_align_t)); | 241 | const actual_len = @max(len, @alignOf(std.c.max_align_t)); |
| 234 | const ptr = c.malloc(actual_len) orelse return null; | 242 | const ptr = c.malloc(actual_len) orelse return null; |
| 235 | assert(alignment.check(@intFromPtr(ptr))); | 243 | assert(alignment.check(@intFromPtr(ptr))); |
| ... | @@ -334,89 +342,6 @@ const c_allocator_impl = struct { | ... | @@ -334,89 +342,6 @@ const c_allocator_impl = struct { |
| 334 | } | 342 | } |
| 335 | }; | 343 | }; |
| 336 | | 344 | |
| 337 | /// Asserts that allocations have alignments which `malloc` can satisfy. This means that | | |
| 338 | /// the requested alignment is no greater than `@min(@alignOf(std.c.max_align_t), size)`. | | |
| 339 | /// | | |
| 340 | /// This allocator is rarely appropriate to use. In general, prefer `c_allocator`, which | | |
| 341 | /// does not have any special requirements of its input, but is still highly efficient for | | |
| 342 | /// allocation requests which obey `malloc` alignment rules. | | |
| 343 | pub const raw_c_allocator: Allocator = .{ | | |
| 344 | .ptr = undefined, | | |
| 345 | .vtable = &raw_c_allocator_vtable, | | |
| 346 | }; | | |
| 347 | const raw_c_allocator_vtable: Allocator.VTable = .{ | | |
| 348 | .alloc = rawCAlloc, | | |
| 349 | .resize = rawCResize, | | |
| 350 | .remap = rawCRemap, | | |
| 351 | .free = rawCFree, | | |
| 352 | }; | | |
| 353 | | | |
| 354 | fn rawCAlloc( | | |
| 355 | context: *anyopaque, | | |
| 356 | len: usize, | | |
| 357 | alignment: Alignment, | | |
| 358 | return_address: usize, | | |
| 359 | ) ?[*]u8 { | | |
| 360 | _ = context; | | |
| 361 | _ = return_address; | | |
| 362 | // `std.c.max_align_t` isn't the whole story, because if `len` is smaller than | | |
| 363 | // every C type with alignment `max_align_t`, the allocation can be less-aligned. | | |
| 364 | // The implementation need only guarantee that any type of length `len` would be | | |
| 365 | // suitably aligned. | | |
| 366 | // | | |
| 367 | // For instance, if `len == 8` and `alignment == .@"16"`, then `malloc` may not | | |
| 368 | // fulfil this request, because there is necessarily no C type with 8-byte size | | |
| 369 | // but 16-byte alignment. | | |
| 370 | // | | |
| 371 | // In theory, the resulting rule here would be target-specific, but in practice, | | |
| 372 | // the smallest type with an alignment of `max_align_t` has the same size (it's | | |
| 373 | // usually `c_longdouble`), so we can just check that `alignment <= len`. | | |
| 374 | assert(alignment.toByteUnits() <= len); | | |
| 375 | assert(Alignment.compare(alignment, .lte, .of(std.c.max_align_t))); | | |
| 376 | return @ptrCast(c.malloc(len)); | | |
| 377 | } | | |
| 378 | | | |
| 379 | fn rawCResize( | | |
| 380 | context: *anyopaque, | | |
| 381 | memory: []u8, | | |
| 382 | alignment: Alignment, | | |
| 383 | new_len: usize, | | |
| 384 | return_address: usize, | | |
| 385 | ) bool { | | |
| 386 | _ = context; | | |
| 387 | _ = memory; | | |
| 388 | _ = alignment; | | |
| 389 | _ = new_len; | | |
| 390 | _ = return_address; | | |
| 391 | return false; | | |
| 392 | } | | |
| 393 | | | |
| 394 | fn rawCRemap( | | |
| 395 | context: *anyopaque, | | |
| 396 | memory: []u8, | | |
| 397 | alignment: Alignment, | | |
| 398 | new_len: usize, | | |
| 399 | return_address: usize, | | |
| 400 | ) ?[*]u8 { | | |
| 401 | _ = context; | | |
| 402 | _ = return_address; | | |
| 403 | // See `rawCMalloc` for an explanation of this `assert` call. | | |
| 404 | assert(alignment.toByteUnits() <= new_len); | | |
| 405 | return @ptrCast(c.realloc(memory.ptr, new_len)); | | |
| 406 | } | | |
| 407 | | | |
| 408 | fn rawCFree( | | |
| 409 | context: *anyopaque, | | |
| 410 | memory: []u8, | | |
| 411 | alignment: Alignment, | | |
| 412 | return_address: usize, | | |
| 413 | ) void { | | |
| 414 | _ = context; | | |
| 415 | _ = alignment; | | |
| 416 | _ = return_address; | | |
| 417 | c.free(memory.ptr); | | |
| 418 | } | | |
| 419 | | | |
| 420 | /// On operating systems that support memory mapping, this allocator makes a | 345 | /// On operating systems that support memory mapping, this allocator makes a |
| 421 | /// syscall directly for every allocation and free. | 346 | /// syscall directly for every allocation and free. |
| 422 | /// | 347 | /// |
| ... | @@ -569,12 +494,6 @@ test c_allocator { | ... | @@ -569,12 +494,6 @@ test c_allocator { |
| 569 | } | 494 | } |
| 570 | } | 495 | } |
| 571 | | 496 | |
| 572 | test raw_c_allocator { | | |
| 573 | if (builtin.link_libc) { | | |
| 574 | try testAllocator(raw_c_allocator); | | |
| 575 | } | | |
| 576 | } | | |
| 577 | | | |
| 578 | test smp_allocator { | 497 | test smp_allocator { |
| 579 | if (builtin.single_threaded) return; | 498 | if (builtin.single_threaded) return; |
| 580 | try testAllocator(smp_allocator); | 499 | try testAllocator(smp_allocator); |