| ... | ... | @@ -146,9 +146,6 @@ test defaultQueryPageSize { |
| 146 | 146 | /// possible, but large requested alignments may require larger buffers in order to |
| 147 | 147 | /// satisfy the request. As well as `malloc`, `realloc`, and `free`, the extension |
| 148 | 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 | 149 | pub const c_allocator: Allocator = .{ |
| 153 | 150 | .ptr = undefined, |
| 154 | 151 | .vtable = &c_allocator_impl.vtable, |
| ... | ... | @@ -228,8 +225,19 @@ const c_allocator_impl = struct { |
| 228 | 225 | assert(len > 0); |
| 229 | 226 | switch (allocStrat(alignment)) { |
| 230 | 227 | .raw => { |
| 231 | | // C only needs to respect `max_align_t` up to the allocation size due to object |
| 232 | | // alignment rules. If necessary, extend the allocation size. |
| 228 | // `std.c.max_align_t` isn't the whole story, because if `len` is smaller than |
| 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 | 241 | const actual_len = @max(len, @alignOf(std.c.max_align_t)); |
| 234 | 242 | const ptr = c.malloc(actual_len) orelse return null; |
| 235 | 243 | assert(alignment.check(@intFromPtr(ptr))); |
| ... | ... | @@ -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 | 345 | /// On operating systems that support memory mapping, this allocator makes a |
| 421 | 346 | /// syscall directly for every allocation and free. |
| 422 | 347 | /// |
| ... | ... | @@ -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 | 497 | test smp_allocator { |
| 579 | 498 | if (builtin.single_threaded) return; |
| 580 | 499 | try testAllocator(smp_allocator); |