Skip to content

introduce std.heap.SmpAllocator #22808

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ int main(int argc, char **argv) {
"pub const enable_tracy = false;\n"
"pub const value_tracing = false;\n"
"pub const skip_non_native = false;\n"
"pub const force_gpa = false;\n"
"pub const debug_gpa = false;\n"
"pub const dev = .core;\n"
"pub const value_interpret_mode = .direct;\n"
, zig_version);
Expand Down
6 changes: 3 additions & 3 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ pub fn build(b: *std.Build) !void {
const tracy_callstack = b.option(bool, "tracy-callstack", "Include callstack information with Tracy data. Does nothing if -Dtracy is not provided") orelse (tracy != null);
const tracy_allocation = b.option(bool, "tracy-allocation", "Include allocation information with Tracy data. Does nothing if -Dtracy is not provided") orelse (tracy != null);
const tracy_callstack_depth: u32 = b.option(u32, "tracy-callstack-depth", "Declare callstack depth for Tracy data. Does nothing if -Dtracy_callstack is not provided") orelse 10;
const force_gpa = b.option(bool, "force-gpa", "Force the compiler to use GeneralPurposeAllocator") orelse false;
const debug_gpa = b.option(bool, "debug-allocator", "Force the compiler to use DebugAllocator") orelse false;
const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse (enable_llvm or only_c);
const sanitize_thread = b.option(bool, "sanitize-thread", "Enable thread-sanitization") orelse false;
const strip = b.option(bool, "strip", "Omit debug information");
Expand Down Expand Up @@ -233,7 +233,7 @@ pub fn build(b: *std.Build) !void {
exe_options.addOption(bool, "llvm_has_csky", llvm_has_csky);
exe_options.addOption(bool, "llvm_has_arc", llvm_has_arc);
exe_options.addOption(bool, "llvm_has_xtensa", llvm_has_xtensa);
exe_options.addOption(bool, "force_gpa", force_gpa);
exe_options.addOption(bool, "debug_gpa", debug_gpa);
exe_options.addOption(DevEnv, "dev", b.option(DevEnv, "dev", "Build a compiler with a reduced feature set for development of specific features") orelse if (only_c) .bootstrap else .full);
exe_options.addOption(ValueInterpretMode, "value_interpret_mode", value_interpret_mode);

Expand Down Expand Up @@ -608,7 +608,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {

exe_options.addOption(u32, "mem_leak_frames", 0);
exe_options.addOption(bool, "have_llvm", false);
exe_options.addOption(bool, "force_gpa", false);
exe_options.addOption(bool, "debug_gpa", false);
exe_options.addOption([:0]const u8, "version", version);
exe_options.addOption(std.SemanticVersion, "semver", semver);
exe_options.addOption(bool, "enable_debug_extensions", false);
Expand Down
2 changes: 2 additions & 0 deletions lib/libc/musl/src/thread/riscv32/clone.s
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
.global __clone
.type __clone, %function
__clone:
andi a1, a1, -16

# Save func and arg to stack
addi a1, a1, -16
sw a0, 0(a1)
Expand Down
2 changes: 2 additions & 0 deletions lib/libc/musl/src/thread/riscv64/clone.s
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
.global __clone
.type __clone, %function
__clone:
andi a1, a1, -16

# Save func and arg to stack
addi a1, a1, -16
sd a0, 0(a1)
Expand Down
25 changes: 20 additions & 5 deletions lib/std/heap.zig
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ const Allocator = std.mem.Allocator;
const windows = std.os.windows;

pub const ArenaAllocator = @import("heap/arena_allocator.zig").ArenaAllocator;
pub const WasmAllocator = @import("heap/WasmAllocator.zig");
pub const SmpAllocator = @import("heap/SmpAllocator.zig");
pub const FixedBufferAllocator = @import("heap/FixedBufferAllocator.zig");
pub const PageAllocator = @import("heap/PageAllocator.zig");
pub const ThreadSafeAllocator = @import("heap/ThreadSafeAllocator.zig");
pub const SbrkAllocator = @import("heap/sbrk_allocator.zig").SbrkAllocator;
pub const FixedBufferAllocator = @import("heap/FixedBufferAllocator.zig");
pub const ThreadSafeAllocator = @import("heap/ThreadSafeAllocator.zig");
pub const WasmAllocator = @import("heap/WasmAllocator.zig");

pub const DebugAllocatorConfig = @import("heap/debug_allocator.zig").Config;
pub const DebugAllocator = @import("heap/debug_allocator.zig").DebugAllocator;
Expand Down Expand Up @@ -358,6 +359,11 @@ else if (builtin.target.isWasm()) .{
.vtable = &PageAllocator.vtable,
};

pub const smp_allocator: Allocator = .{
.ptr = undefined,
.vtable = &SmpAllocator.vtable,
};

/// This allocator is fast, small, and specific to WebAssembly. In the future,
/// this will be the implementation automatically selected by
/// `GeneralPurposeAllocator` when compiling in `ReleaseSmall` mode for wasm32
Expand Down Expand Up @@ -475,7 +481,7 @@ pub fn StackFallbackAllocator(comptime size: usize) type {
};
}

test "c_allocator" {
test c_allocator {
if (builtin.link_libc) {
try testAllocator(c_allocator);
try testAllocatorAligned(c_allocator);
Expand All @@ -484,12 +490,20 @@ test "c_allocator" {
}
}

test "raw_c_allocator" {
test raw_c_allocator {
if (builtin.link_libc) {
try testAllocator(raw_c_allocator);
}
}

test smp_allocator {
if (builtin.single_threaded) return;
try testAllocator(smp_allocator);
try testAllocatorAligned(smp_allocator);
try testAllocatorLargeAlignment(smp_allocator);
try testAllocatorAlignedShrink(smp_allocator);
}

test PageAllocator {
const allocator = page_allocator;
try testAllocator(allocator);
Expand Down Expand Up @@ -978,4 +992,5 @@ test {
if (builtin.target.isWasm()) {
_ = WasmAllocator;
}
if (!builtin.single_threaded) _ = smp_allocator;
}
30 changes: 18 additions & 12 deletions lib/std/heap/PageAllocator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ pub const vtable: Allocator.VTable = .{
.free = free,
};

fn alloc(context: *anyopaque, n: usize, alignment: mem.Alignment, ra: usize) ?[*]u8 {
_ = context;
_ = ra;
assert(n > 0);

pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 {
const page_size = std.heap.pageSize();
if (n >= maxInt(usize) - page_size) return null;
const alignment_bytes = alignment.toByteUnits();
Expand Down Expand Up @@ -101,6 +97,13 @@ fn alloc(context: *anyopaque, n: usize, alignment: mem.Alignment, ra: usize) ?[*
return result_ptr;
}

fn alloc(context: *anyopaque, n: usize, alignment: mem.Alignment, ra: usize) ?[*]u8 {
_ = context;
_ = ra;
assert(n > 0);
return map(n, alignment);
}

fn resize(
context: *anyopaque,
memory: []u8,
Expand All @@ -114,7 +117,7 @@ fn resize(
return realloc(memory, new_len, false) != null;
}

pub fn remap(
fn remap(
context: *anyopaque,
memory: []u8,
alignment: mem.Alignment,
Expand All @@ -127,21 +130,24 @@ pub fn remap(
return realloc(memory, new_len, true);
}

fn free(context: *anyopaque, slice: []u8, alignment: mem.Alignment, return_address: usize) void {
fn free(context: *anyopaque, memory: []u8, alignment: mem.Alignment, return_address: usize) void {
_ = context;
_ = alignment;
_ = return_address;
return unmap(@alignCast(memory));
}

pub fn unmap(memory: []align(page_size_min) u8) void {
if (native_os == .windows) {
windows.VirtualFree(slice.ptr, 0, windows.MEM_RELEASE);
windows.VirtualFree(memory.ptr, 0, windows.MEM_RELEASE);
} else {
const buf_aligned_len = mem.alignForward(usize, slice.len, std.heap.pageSize());
posix.munmap(@alignCast(slice.ptr[0..buf_aligned_len]));
const page_aligned_len = mem.alignForward(usize, memory.len, std.heap.pageSize());
posix.munmap(memory.ptr[0..page_aligned_len]);
}
}

fn realloc(uncasted_memory: []u8, new_len: usize, may_move: bool) ?[*]u8 {
const memory: []align(std.heap.page_size_min) u8 = @alignCast(uncasted_memory);
pub fn realloc(uncasted_memory: []u8, new_len: usize, may_move: bool) ?[*]u8 {
const memory: []align(page_size_min) u8 = @alignCast(uncasted_memory);
const page_size = std.heap.pageSize();
const new_size_aligned = mem.alignForward(usize, new_len, page_size);

Expand Down
Loading
Loading