Skip to content

Commit 6a6e72f

Browse files
authored
Merge pull request #20511 from archbirdplus
runtime page size detection rework GeneralPurposeAllocator to reduce active mapping count Allocator VTable API update
2 parents 8ad0732 + b8f5cfe commit 6a6e72f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2981
-2710
lines changed

lib/fuzzer.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ pub const MemoryMappedList = struct {
480480
/// of this ArrayList in accordance with the respective documentation. In
481481
/// all cases, "invalidated" means that the memory has been passed to this
482482
/// allocator's resize or free function.
483-
items: []align(std.mem.page_size) volatile u8,
483+
items: []align(std.heap.page_size_min) volatile u8,
484484
/// How many bytes this list can hold without allocating additional memory.
485485
capacity: usize,
486486

lib/std/Build/Fuzz/WebServer.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const fuzzer_arch_os_abi = "wasm32-freestanding";
4141
const fuzzer_cpu_features = "baseline+atomics+bulk_memory+multivalue+mutable_globals+nontrapping_fptoint+reference_types+sign_ext";
4242

4343
const CoverageMap = struct {
44-
mapped_memory: []align(std.mem.page_size) const u8,
44+
mapped_memory: []align(std.heap.page_size_min) const u8,
4545
coverage: Coverage,
4646
source_locations: []Coverage.SourceLocation,
4747
/// Elements are indexes into `source_locations` pointing to the unit tests that are being fuzz tested.

lib/std/Thread.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ const PosixThreadImpl = struct {
769769
// Use the same set of parameters used by the libc-less impl.
770770
const stack_size = @max(config.stack_size, 16 * 1024);
771771
assert(c.pthread_attr_setstacksize(&attr, stack_size) == .SUCCESS);
772-
assert(c.pthread_attr_setguardsize(&attr, std.mem.page_size) == .SUCCESS);
772+
assert(c.pthread_attr_setguardsize(&attr, std.heap.pageSize()) == .SUCCESS);
773773

774774
var handle: c.pthread_t = undefined;
775775
switch (c.pthread_create(
@@ -1155,7 +1155,7 @@ const LinuxThreadImpl = struct {
11551155
completion: Completion = Completion.init(.running),
11561156
child_tid: std.atomic.Value(i32) = std.atomic.Value(i32).init(1),
11571157
parent_tid: i32 = undefined,
1158-
mapped: []align(std.mem.page_size) u8,
1158+
mapped: []align(std.heap.page_size_min) u8,
11591159

11601160
/// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`).
11611161
/// Ported over from musl libc's pthread detached implementation:
@@ -1362,7 +1362,7 @@ const LinuxThreadImpl = struct {
13621362
};
13631363

13641364
fn spawn(config: SpawnConfig, comptime f: anytype, args: anytype) !Impl {
1365-
const page_size = std.mem.page_size;
1365+
const page_size = std.heap.pageSize();
13661366
const Args = @TypeOf(args);
13671367
const Instance = struct {
13681368
fn_args: Args,

lib/std/array_list.zig

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -105,21 +105,19 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
105105
return result;
106106
}
107107

108-
/// The caller owns the returned memory. Empties this ArrayList,
109-
/// Its capacity is cleared, making deinit() safe but unnecessary to call.
108+
/// The caller owns the returned memory. Empties this ArrayList.
109+
/// Its capacity is cleared, making `deinit` safe but unnecessary to call.
110110
pub fn toOwnedSlice(self: *Self) Allocator.Error!Slice {
111111
const allocator = self.allocator;
112112

113113
const old_memory = self.allocatedSlice();
114-
if (allocator.resize(old_memory, self.items.len)) {
115-
const result = self.items;
114+
if (allocator.remap(old_memory, self.items.len)) |new_items| {
116115
self.* = init(allocator);
117-
return result;
116+
return new_items;
118117
}
119118

120119
const new_memory = try allocator.alignedAlloc(T, alignment, self.items.len);
121120
@memcpy(new_memory, self.items);
122-
@memset(self.items, undefined);
123121
self.clearAndFree();
124122
return new_memory;
125123
}
@@ -185,8 +183,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
185183
// extra capacity.
186184
const new_capacity = growCapacity(self.capacity, new_len);
187185
const old_memory = self.allocatedSlice();
188-
if (self.allocator.resize(old_memory, new_capacity)) {
189-
self.capacity = new_capacity;
186+
if (self.allocator.remap(old_memory, new_capacity)) |new_memory| {
187+
self.items.ptr = new_memory.ptr;
188+
self.capacity = new_memory.len;
190189
return addManyAtAssumeCapacity(self, index, count);
191190
}
192191

@@ -468,8 +467,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
468467
// the allocator implementation would pointlessly copy our
469468
// extra capacity.
470469
const old_memory = self.allocatedSlice();
471-
if (self.allocator.resize(old_memory, new_capacity)) {
472-
self.capacity = new_capacity;
470+
if (self.allocator.remap(old_memory, new_capacity)) |new_memory| {
471+
self.items.ptr = new_memory.ptr;
472+
self.capacity = new_memory.len;
473473
} else {
474474
const new_memory = try self.allocator.alignedAlloc(T, alignment, new_capacity);
475475
@memcpy(new_memory[0..self.items.len], self.items);
@@ -707,15 +707,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
707707
/// Its capacity is cleared, making deinit() safe but unnecessary to call.
708708
pub fn toOwnedSlice(self: *Self, allocator: Allocator) Allocator.Error!Slice {
709709
const old_memory = self.allocatedSlice();
710-
if (allocator.resize(old_memory, self.items.len)) {
711-
const result = self.items;
710+
if (allocator.remap(old_memory, self.items.len)) |new_items| {
712711
self.* = .empty;
713-
return result;
712+
return new_items;
714713
}
715714

716715
const new_memory = try allocator.alignedAlloc(T, alignment, self.items.len);
717716
@memcpy(new_memory, self.items);
718-
@memset(self.items, undefined);
719717
self.clearAndFree(allocator);
720718
return new_memory;
721719
}
@@ -1031,9 +1029,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
10311029
}
10321030

10331031
const old_memory = self.allocatedSlice();
1034-
if (allocator.resize(old_memory, new_len)) {
1035-
self.capacity = new_len;
1036-
self.items.len = new_len;
1032+
if (allocator.remap(old_memory, new_len)) |new_items| {
1033+
self.capacity = new_items.len;
1034+
self.items = new_items;
10371035
return;
10381036
}
10391037

@@ -1099,8 +1097,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
10991097
// the allocator implementation would pointlessly copy our
11001098
// extra capacity.
11011099
const old_memory = self.allocatedSlice();
1102-
if (allocator.resize(old_memory, new_capacity)) {
1103-
self.capacity = new_capacity;
1100+
if (allocator.remap(old_memory, new_capacity)) |new_memory| {
1101+
self.items.ptr = new_memory.ptr;
1102+
self.capacity = new_memory.len;
11041103
} else {
11051104
const new_memory = try allocator.alignedAlloc(T, alignment, new_capacity);
11061105
@memcpy(new_memory[0..self.items.len], self.items);

lib/std/c.zig

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const builtin = @import("builtin");
33
const c = @This();
44
const maxInt = std.math.maxInt;
55
const assert = std.debug.assert;
6-
const page_size = std.mem.page_size;
6+
const page_size = std.heap.page_size_min;
77
const native_abi = builtin.abi;
88
const native_arch = builtin.cpu.arch;
99
const native_os = builtin.os.tag;
@@ -2227,6 +2227,39 @@ pub const SC = switch (native_os) {
22272227
.linux => linux.SC,
22282228
else => void,
22292229
};
2230+
2231+
pub const _SC = switch (native_os) {
2232+
.driverkit, .ios, .macos, .tvos, .visionos, .watchos => enum(c_int) {
2233+
PAGESIZE = 29,
2234+
},
2235+
.dragonfly => enum(c_int) {
2236+
PAGESIZE = 47,
2237+
},
2238+
.freebsd => enum(c_int) {
2239+
PAGESIZE = 47,
2240+
},
2241+
.fuchsia => enum(c_int) {
2242+
PAGESIZE = 30,
2243+
},
2244+
.haiku => enum(c_int) {
2245+
PAGESIZE = 27,
2246+
},
2247+
.linux => enum(c_int) {
2248+
PAGESIZE = 30,
2249+
},
2250+
.netbsd => enum(c_int) {
2251+
PAGESIZE = 28,
2252+
},
2253+
.openbsd => enum(c_int) {
2254+
PAGESIZE = 28,
2255+
},
2256+
.solaris, .illumos => enum(c_int) {
2257+
PAGESIZE = 11,
2258+
NPROCESSORS_ONLN = 15,
2259+
},
2260+
else => void,
2261+
};
2262+
22302263
pub const SEEK = switch (native_os) {
22312264
.linux => linux.SEEK,
22322265
.emscripten => emscripten.SEEK,
@@ -7834,6 +7867,11 @@ pub const MAP = switch (native_os) {
78347867
else => void,
78357868
};
78367869

7870+
pub const MREMAP = switch (native_os) {
7871+
.linux => linux.MREMAP,
7872+
else => void,
7873+
};
7874+
78377875
/// Used by libc to communicate failure. Not actually part of the underlying syscall.
78387876
pub const MAP_FAILED: *anyopaque = @ptrFromInt(maxInt(usize));
78397877

@@ -9232,7 +9270,7 @@ pub extern "c" fn getpwnam(name: [*:0]const u8) ?*passwd;
92329270
pub extern "c" fn getpwuid(uid: uid_t) ?*passwd;
92339271
pub extern "c" fn getrlimit64(resource: rlimit_resource, rlim: *rlimit) c_int;
92349272
pub extern "c" fn lseek64(fd: fd_t, offset: i64, whence: c_int) i64;
9235-
pub extern "c" fn mmap64(addr: ?*align(std.mem.page_size) anyopaque, len: usize, prot: c_uint, flags: c_uint, fd: fd_t, offset: i64) *anyopaque;
9273+
pub extern "c" fn mmap64(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: c_uint, fd: fd_t, offset: i64) *anyopaque;
92369274
pub extern "c" fn open64(path: [*:0]const u8, oflag: O, ...) c_int;
92379275
pub extern "c" fn openat64(fd: c_int, path: [*:0]const u8, oflag: O, ...) c_int;
92389276
pub extern "c" fn pread64(fd: fd_t, buf: [*]u8, nbyte: usize, offset: i64) isize;
@@ -9324,13 +9362,13 @@ pub extern "c" fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) c_int;
93249362

93259363
pub extern "c" fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: *const rlimit, old_limit: *rlimit) c_int;
93269364
pub extern "c" fn mincore(
9327-
addr: *align(std.mem.page_size) anyopaque,
9365+
addr: *align(page_size) anyopaque,
93289366
length: usize,
93299367
vec: [*]u8,
93309368
) c_int;
93319369

93329370
pub extern "c" fn madvise(
9333-
addr: *align(std.mem.page_size) anyopaque,
9371+
addr: *align(page_size) anyopaque,
93349372
length: usize,
93359373
advice: u32,
93369374
) c_int;
@@ -9428,6 +9466,10 @@ pub const posix_memalign = switch (native_os) {
94289466
.dragonfly, .netbsd, .freebsd, .solaris, .openbsd, .linux, .macos, .ios, .tvos, .watchos, .visionos => private.posix_memalign,
94299467
else => {},
94309468
};
9469+
pub const sysconf = switch (native_os) {
9470+
.solaris => solaris.sysconf,
9471+
else => private.sysconf,
9472+
};
94319473

94329474
pub const sf_hdtr = switch (native_os) {
94339475
.freebsd, .macos, .ios, .tvos, .watchos, .visionos => extern struct {
@@ -9471,6 +9513,7 @@ pub extern "c" fn write(fd: fd_t, buf: [*]const u8, nbyte: usize) isize;
94719513
pub extern "c" fn pwrite(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: off_t) isize;
94729514
pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: MAP, fd: fd_t, offset: off_t) *anyopaque;
94739515
pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int;
9516+
pub extern "c" fn mremap(addr: ?*align(page_size) const anyopaque, old_len: usize, new_len: usize, flags: MREMAP, ...) *anyopaque;
94749517
pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int;
94759518
pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) c_int;
94769519
pub extern "c" fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: c_int) c_int;
@@ -9823,7 +9866,6 @@ pub const SCM = solaris.SCM;
98239866
pub const SETCONTEXT = solaris.SETCONTEXT;
98249867
pub const SETUSTACK = solaris.GETUSTACK;
98259868
pub const SFD = solaris.SFD;
9826-
pub const _SC = solaris._SC;
98279869
pub const cmsghdr = solaris.cmsghdr;
98289870
pub const ctid_t = solaris.ctid_t;
98299871
pub const file_obj = solaris.file_obj;
@@ -9840,7 +9882,6 @@ pub const priority = solaris.priority;
98409882
pub const procfs = solaris.procfs;
98419883
pub const projid_t = solaris.projid_t;
98429884
pub const signalfd_siginfo = solaris.signalfd_siginfo;
9843-
pub const sysconf = solaris.sysconf;
98449885
pub const taskid_t = solaris.taskid_t;
98459886
pub const zoneid_t = solaris.zoneid_t;
98469887

@@ -9997,6 +10038,7 @@ pub const host_t = darwin.host_t;
999710038
pub const ipc_space_t = darwin.ipc_space_t;
999810039
pub const ipc_space_port_t = darwin.ipc_space_port_t;
999910040
pub const kern_return_t = darwin.kern_return_t;
10041+
pub const vm_size_t = darwin.vm_size_t;
1000010042
pub const kevent64 = darwin.kevent64;
1000110043
pub const kevent64_s = darwin.kevent64_s;
1000210044
pub const mach_absolute_time = darwin.mach_absolute_time;
@@ -10168,6 +10210,7 @@ const private = struct {
1016810210
extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int;
1016910211
extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *Stat) c_int;
1017010212
extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
10213+
extern "c" fn sysconf(sc: c_int) c_long;
1017110214

1017210215
extern "c" fn pthread_setname_np(thread: pthread_t, name: [*:0]const u8) c_int;
1017310216
extern "c" fn getcontext(ucp: *ucontext_t) c_int;
@@ -10202,7 +10245,7 @@ const private = struct {
1020210245
extern "c" fn __getrusage50(who: c_int, usage: *rusage) c_int;
1020310246
extern "c" fn __gettimeofday50(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;
1020410247
extern "c" fn __libc_thr_yield() c_int;
10205-
extern "c" fn __msync13(addr: *align(std.mem.page_size) const anyopaque, len: usize, flags: c_int) c_int;
10248+
extern "c" fn __msync13(addr: *align(page_size) const anyopaque, len: usize, flags: c_int) c_int;
1020610249
extern "c" fn __nanosleep50(rqtp: *const timespec, rmtp: ?*timespec) c_int;
1020710250
extern "c" fn __sigaction14(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int;
1020810251
extern "c" fn __sigfillset14(set: ?*sigset_t) void;

lib/std/c/solaris.zig

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,6 @@ pub const AF_SUN = struct {
154154
pub const NOPLM = 0x00000004;
155155
};
156156

157-
pub const _SC = struct {
158-
pub const NPROCESSORS_ONLN = 15;
159-
};
160-
161157
pub const procfs = struct {
162158
pub const misc_header = extern struct {
163159
size: u32,

lib/std/crypto/tlcsprng.zig

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ var install_atfork_handler = std.once(struct {
4242
}
4343
}.do);
4444

45-
threadlocal var wipe_mem: []align(mem.page_size) u8 = &[_]u8{};
45+
threadlocal var wipe_mem: []align(std.heap.page_size_min) u8 = &[_]u8{};
4646

4747
fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void {
4848
if (os_has_arc4random) {
@@ -77,15 +77,15 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void {
7777
} else {
7878
// Use a static thread-local buffer.
7979
const S = struct {
80-
threadlocal var buf: Context align(mem.page_size) = .{
80+
threadlocal var buf: Context align(std.heap.page_size_min) = .{
8181
.init_state = .uninitialized,
8282
.rng = undefined,
8383
};
8484
};
8585
wipe_mem = mem.asBytes(&S.buf);
8686
}
8787
}
88-
const ctx = @as(*Context, @ptrCast(wipe_mem.ptr));
88+
const ctx: *Context = @ptrCast(wipe_mem.ptr);
8989

9090
switch (ctx.init_state) {
9191
.uninitialized => {
@@ -141,7 +141,7 @@ fn childAtForkHandler() callconv(.c) void {
141141
}
142142

143143
fn fillWithCsprng(buffer: []u8) void {
144-
const ctx = @as(*Context, @ptrCast(wipe_mem.ptr));
144+
const ctx: *Context = @ptrCast(wipe_mem.ptr);
145145
return ctx.rng.fill(buffer);
146146
}
147147

@@ -157,7 +157,7 @@ fn initAndFill(buffer: []u8) void {
157157
// the `std.options.cryptoRandomSeed` function is provided.
158158
std.options.cryptoRandomSeed(&seed);
159159

160-
const ctx = @as(*Context, @ptrCast(wipe_mem.ptr));
160+
const ctx: *Context = @ptrCast(wipe_mem.ptr);
161161
ctx.rng = Rng.init(seed);
162162
std.crypto.secureZero(u8, &seed);
163163

0 commit comments

Comments
 (0)