authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-14 20:12:54-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-15 14:18:20-08:00
logc917f619f041f5494e1c2d13c28ce1b04cec11f7
tree94147a6fa971063c2fa28ef72cf482e540768cfb
parenteb163361d9d7b61ee0b93b6f49efd24943c6027d

std: fix compilation failures on various targets


6 files changed, 77 insertions(+), 35 deletions(-)

lib/std/Io.zig+1-1
...@@ -656,7 +656,7 @@ pub const VTable = struct {...@@ -656,7 +656,7 @@ pub const VTable = struct {
656656
657 fileMemoryMapCreate: *const fn (?*anyopaque, File, File.MemoryMap.CreateOptions) File.MemoryMap.CreateError!File.MemoryMap,657 fileMemoryMapCreate: *const fn (?*anyopaque, File, File.MemoryMap.CreateOptions) File.MemoryMap.CreateError!File.MemoryMap,
658 fileMemoryMapDestroy: *const fn (?*anyopaque, *File.MemoryMap) void,658 fileMemoryMapDestroy: *const fn (?*anyopaque, *File.MemoryMap) void,
659 fileMemoryMapSetLength: *const fn (?*anyopaque, *File.MemoryMap, n: usize) File.MemoryMap.SetLengthError!void,659 fileMemoryMapSetLength: *const fn (?*anyopaque, *File.MemoryMap, File.MemoryMap.CreateOptions) File.MemoryMap.SetLengthError!void,
660 fileMemoryMapRead: *const fn (?*anyopaque, *File.MemoryMap) File.ReadPositionalError!void,660 fileMemoryMapRead: *const fn (?*anyopaque, *File.MemoryMap) File.ReadPositionalError!void,
661 fileMemoryMapWrite: *const fn (?*anyopaque, *File.MemoryMap) File.WritePositionalError!void,661 fileMemoryMapWrite: *const fn (?*anyopaque, *File.MemoryMap) File.WritePositionalError!void,
662662
lib/std/Io/File/MemoryMap.zig+19-9
...@@ -52,7 +52,9 @@ pub const CreateOptions = struct {...@@ -52,7 +52,9 @@ pub const CreateOptions = struct {
52 /// undefined, and bytes unwritten before calling `write` to write52 /// undefined, and bytes unwritten before calling `write` to write
53 /// undefined memory to the file.53 /// undefined memory to the file.
54 undefined_contents: bool = false,54 undefined_contents: bool = false,
55 /// Prefault the pages.55 /// Prefault the pages. If this option is unsupported, it is silently
56 /// ignored. Aside from custom Io implementations, this option is only
57 /// supported on Linux.
56 populate: bool = true,58 populate: bool = true,
57 /// Asserted to be a multiple of page size which can be obtained via59 /// Asserted to be a multiple of page size which can be obtained via
58 /// `std.heap.pageSize`.60 /// `std.heap.pageSize`.
...@@ -72,21 +74,29 @@ pub fn destroy(mm: *MemoryMap, io: Io) void {...@@ -72,21 +74,29 @@ pub fn destroy(mm: *MemoryMap, io: Io) void {
72}74}
7375
74pub const SetLengthError = error{76pub const SetLengthError = error{
77 /// One of the following:
78 /// * The `File.Kind` is not `file`.
79 /// * The file is not open for reading and read access protections enabled.
80 /// * The file is not open for writing and write access protections enabled.
81 AccessDenied,
82 /// The `prot` argument asks for `PROT_EXEC` but the mapped area belongs to a file on
83 /// a filesystem that was mounted no-exec.
84 PermissionDenied,
75 LockedMemoryLimitExceeded,85 LockedMemoryLimitExceeded,
86 ProcessFdQuotaExceeded,
87 SystemFdQuotaExceeded,
76} || Allocator.Error || File.SetLengthError;88} || Allocator.Error || File.SetLengthError;
7789
78/// Change the size of the mapping. This does not sync the contents. The size90/// Change the size of the mapping. This does not sync the contents. The size
79/// of the file after calling this is unspecified until `write` is called.91/// of the file after calling this is unspecified until `write` is called.
80///92///
81/// May change the pointer address of `memory`.93/// May change the pointer address of `memory`.
82pub fn setLength(94///
83 mm: *MemoryMap,95/// `options` is needed because the mapping may need to be destroyed and
84 io: Io,96/// re-created. All the same options must be provided except for `len` which is
85 /// New size of the mapping, in bytes. If this is longer than the file97/// the new length.
86 /// size, it will be filled with zeroes. No alignment requirement.98pub fn setLength(mm: *MemoryMap, io: Io, options: CreateOptions) SetLengthError!void {
87 new_length: usize,99 return io.vtable.fileMemoryMapSetLength(io.userdata, mm, options);
88) SetLengthError!void {
89 return io.vtable.fileMemoryMapSetLength(io.userdata, mm, new_length);
90}100}
91101
92/// Synchronizes the contents of `memory` from `file`.102/// Synchronizes the contents of `memory` from `file`.
lib/std/Io/Threaded.zig+52-22
...@@ -7998,7 +7998,7 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: []const []u8)...@@ -7998,7 +7998,7 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: []const []u8)
7998 .FAULT => |err| return errnoBug(err),7998 .FAULT => |err| return errnoBug(err),
7999 .AGAIN => return error.WouldBlock,7999 .AGAIN => return error.WouldBlock,
8000 .BADF => |err| {8000 .BADF => |err| {
8001 if (native_os == .wasi) return error.NotOpenForReading; // File operation on directory.8001 if (native_os == .wasi) return error.IsDir; // File operation on directory.
8002 return errnoBug(err); // File descriptor used after closed.8002 return errnoBug(err); // File descriptor used after closed.
8003 },8003 },
8004 .IO => return error.InputOutput,8004 .IO => return error.InputOutput,
...@@ -8089,7 +8089,7 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: File, data: []const []u8...@@ -8089,7 +8089,7 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: File, data: []const []u8
8089 syscall.finish();8089 syscall.finish();
8090 return nread;8090 return nread;
8091 },8091 },
8092 .INTR => {8092 .INTR, .TIMEDOUT => {
8093 try syscall.checkCancel();8093 try syscall.checkCancel();
8094 continue;8094 continue;
8095 },8095 },
...@@ -8103,7 +8103,6 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: File, data: []const []u8...@@ -8103,7 +8103,6 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: File, data: []const []u8
8103 .ISDIR => return syscall.fail(error.IsDir),8103 .ISDIR => return syscall.fail(error.IsDir),
8104 .NOBUFS => return syscall.fail(error.SystemResources),8104 .NOBUFS => return syscall.fail(error.SystemResources),
8105 .NOMEM => return syscall.fail(error.SystemResources),8105 .NOMEM => return syscall.fail(error.SystemResources),
8106 .TIMEDOUT => return syscall.fail(error.Timeout),
8107 .NXIO => return syscall.fail(error.Unseekable),8106 .NXIO => return syscall.fail(error.Unseekable),
8108 .SPIPE => return syscall.fail(error.Unseekable),8107 .SPIPE => return syscall.fail(error.Unseekable),
8109 .OVERFLOW => return syscall.fail(error.Unseekable),8108 .OVERFLOW => return syscall.fail(error.Unseekable),
...@@ -12588,7 +12587,7 @@ fn statFromPosix(st: *const posix.Stat) File.Stat {...@@ -12588,7 +12587,7 @@ fn statFromPosix(st: *const posix.Stat) File.Stat {
12588 .atime = timestampFromPosix(&atime),12587 .atime = timestampFromPosix(&atime),
12589 .mtime = timestampFromPosix(&mtime),12588 .mtime = timestampFromPosix(&mtime),
12590 .ctime = timestampFromPosix(&ctime),12589 .ctime = timestampFromPosix(&ctime),
12591 .block_size = st.blksize,12590 .block_size = @intCast(st.blksize),
12592 };12591 };
12593}12592}
1259412593
...@@ -16292,9 +16291,14 @@ fn createFileMap(...@@ -16292,9 +16291,14 @@ fn createFileMap(
16292 .WRITE = protection.write,16291 .WRITE = protection.write,
16293 .EXEC = protection.execute,16292 .EXEC = protection.execute,
16294 };16293 };
16295 const flags: posix.MAP = .{16294 const flags: posix.MAP = switch (native_os) {
16296 .TYPE = if (native_os == .linux) .SHARED_VALIDATE else .SHARED,16295 .linux => .{
16297 .POPULATE = populate,16296 .TYPE = .SHARED_VALIDATE,
16297 .POPULATE = populate,
16298 },
16299 else => .{
16300 .TYPE = .SHARED,
16301 },
16298 };16302 };
1629916303
16300 const page_align = std.heap.page_size_min;16304 const page_align = std.heap.page_size_min;
...@@ -16348,20 +16352,20 @@ fn createFileMap(...@@ -16348,20 +16352,20 @@ fn createFileMap(
16348fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {16352fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {
16349 const t: *Threaded = @ptrCast(@alignCast(userdata));16353 const t: *Threaded = @ptrCast(@alignCast(userdata));
16350 const memory = mm.memory;16354 const memory = mm.memory;
16351 if (mm.section) |section| {16355 if (mm.section) |section| switch (native_os) {
16352 if (is_windows) {16356 .windows => {
16353 const current_process: windows.HANDLE = @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))));16357 const current_process: windows.HANDLE = @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))));
16354 _ = windows.ntdll.NtUnmapViewOfSection(current_process, memory.ptr);16358 _ = windows.ntdll.NtUnmapViewOfSection(current_process, memory.ptr);
16355 windows.CloseHandle(section);16359 windows.CloseHandle(section);
16356 } else {16360 },
16357 switch (posix.errno(posix.system.munmap(memory.ptr, memory.len))) {16361 .wasi => unreachable,
16358 .SUCCESS => {},16362 else => switch (posix.errno(posix.system.munmap(memory.ptr, memory.len))) {
16359 else => |e| {16363 .SUCCESS => {},
16360 if (builtin.mode == .Debug)16364 else => |e| {
16361 std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, e });16365 if (builtin.mode == .Debug)
16362 },16366 std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, e });
16363 }16367 },
16364 }16368 },
16365 } else {16369 } else {
16366 const gpa = t.allocator;16370 const gpa = t.allocator;
16367 gpa.rawFree(memory, .fromByteUnits(std.heap.pageSize()), @returnAddress());16371 gpa.rawFree(memory, .fromByteUnits(std.heap.pageSize()), @returnAddress());
...@@ -16372,15 +16376,17 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {...@@ -16372,15 +16376,17 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {
16372fn fileMemoryMapSetLength(16376fn fileMemoryMapSetLength(
16373 userdata: ?*anyopaque,16377 userdata: ?*anyopaque,
16374 mm: *File.MemoryMap,16378 mm: *File.MemoryMap,
16375 new_len: usize,16379 options: File.MemoryMap.CreateOptions,
16376) File.MemoryMap.SetLengthError!void {16380) File.MemoryMap.SetLengthError!void {
16377 const t: *Threaded = @ptrCast(@alignCast(userdata));16381 const t: *Threaded = @ptrCast(@alignCast(userdata));
16378 const page_size = std.heap.pageSize();16382 const page_size = std.heap.pageSize();
16379 const alignment: Alignment = .fromByteUnits(page_size);16383 const alignment: Alignment = .fromByteUnits(page_size);
16380 const page_align = std.heap.page_size_min;16384 const page_align = std.heap.page_size_min;
16385 const old_memory = mm.memory;
16386 const new_len = options.len;
1638116387
16382 if (mm.section) |section| {16388 if (mm.section) |section| {
16383 if (alignment.forward(new_len) == alignment.forward(mm.memory.len)) {16389 if (alignment.forward(new_len) == alignment.forward(old_memory.len)) {
16384 mm.memory.len = new_len;16390 mm.memory.len = new_len;
16385 return;16391 return;
16386 }16392 }
...@@ -16390,12 +16396,12 @@ fn fileMemoryMapSetLength(...@@ -16390,12 +16396,12 @@ fn fileMemoryMapSetLength(
16390 @panic("TODO");16396 @panic("TODO");
16391 },16397 },
16392 .wasi => unreachable,16398 .wasi => unreachable,
16393 else => {16399 .linux => {
16394 const flags: posix.MREMAP = .{ .MAYMOVE = true };16400 const flags: posix.MREMAP = .{ .MAYMOVE = true };
16395 const addr_hint: ?[*]const u8 = null;16401 const addr_hint: ?[*]const u8 = null;
16396 const new_memory = while (true) {16402 const new_memory = while (true) {
16397 const syscall: Syscall = try .start();16403 const syscall: Syscall = try .start();
16398 const rc = posix.system.mremap(mm.memory.ptr, mm.memory.len, new_len, flags, addr_hint);16404 const rc = posix.system.mremap(old_memory.ptr, old_memory.len, new_len, flags, addr_hint);
16399 syscall.finish();16405 syscall.finish();
16400 const err: posix.E = if (builtin.link_libc) e: {16406 const err: posix.E = if (builtin.link_libc) e: {
16401 if (rc != std.c.MAP_FAILED) break @as([*]align(page_align) u8, @ptrCast(@alignCast(rc)))[0..new_len];16407 if (rc != std.c.MAP_FAILED) break @as([*]align(page_align) u8, @ptrCast(@alignCast(rc)))[0..new_len];
...@@ -16417,6 +16423,30 @@ fn fileMemoryMapSetLength(...@@ -16417,6 +16423,30 @@ fn fileMemoryMapSetLength(
16417 };16423 };
16418 mm.memory = new_memory;16424 mm.memory = new_memory;
16419 },16425 },
16426 else => {
16427 switch (posix.errno(posix.system.munmap(old_memory.ptr, old_memory.len))) {
16428 .SUCCESS => {},
16429 else => |e| {
16430 if (builtin.mode == .Debug) std.log.err("failed to unmap {d} bytes at {*}: {t}", .{
16431 old_memory.len, old_memory.ptr, e,
16432 });
16433 // munmap must be infallible, or we cannot design reliable software.
16434 return error.Unexpected;
16435 },
16436 }
16437 if (createFileMap(mm.file, options.protection, mm.offset, options.populate, new_len)) |result| {
16438 mm.* = result;
16439 return;
16440 } else |err| switch (err) {
16441 error.OperationUnsupported,
16442 error.Unseekable,
16443 error.SectionOversize,
16444 error.MappingAlreadyExists,
16445 error.FileLockConflict,
16446 => return error.Unexpected, // It worked before on the same open file.
16447 else => |e| return e,
16448 }
16449 },
16420 }16450 }
16421 } else {16451 } else {
16422 const gpa = t.allocator;16452 const gpa = t.allocator;
lib/std/Io/Threaded/test.zig+1-1
...@@ -255,7 +255,7 @@ test "memory mapping fallback" {...@@ -255,7 +255,7 @@ test "memory mapping fallback" {
255255
256 try testing.expectEqualStrings("this9is9my", mm.memory);256 try testing.expectEqualStrings("this9is9my", mm.memory);
257257
258 try mm.setLength(io, "this9is9my data123".len);258 try mm.setLength(io, .{ .len = "this9is9my data123".len });
259 try mm.read(io);259 try mm.read(io);
260260
261 try testing.expectEqualStrings("this9is9my data123", mm.memory);261 try testing.expectEqualStrings("this9is9my data123", mm.memory);
lib/std/Io/test.zig+3-1
...@@ -594,6 +594,8 @@ test "randomSecure" {...@@ -594,6 +594,8 @@ test "randomSecure" {
594}594}
595595
596test "memory mapping" {596test "memory mapping" {
597 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; // mmap returned EINVAL
598
597 const io = testing.io;599 const io = testing.io;
598600
599 var tmp = tmpDir(.{});601 var tmp = tmpDir(.{});
...@@ -634,7 +636,7 @@ test "memory mapping" {...@@ -634,7 +636,7 @@ test "memory mapping" {
634636
635 try expectEqualStrings("this9is9my", mm.memory);637 try expectEqualStrings("this9is9my", mm.memory);
636638
637 try mm.setLength(io, "this9is9my data123".len);639 try mm.setLength(io, .{ .len = "this9is9my data123".len });
638 try mm.read(io);640 try mm.read(io);
639641
640 try expectEqualStrings("this9is9my data123", mm.memory);642 try expectEqualStrings("this9is9my data123", mm.memory);
lib/std/c.zig+1-1
...@@ -10334,7 +10334,7 @@ pub extern "c" fn getgrgid(gid: gid_t) ?*group;...@@ -10334,7 +10334,7 @@ pub extern "c" fn getgrgid(gid: gid_t) ?*group;
10334pub extern "c" fn getgrgid_r(gid: gid_t, grp: *group, buf: [*]u8, buflen: usize, result: *?*group) c_int;10334pub extern "c" fn getgrgid_r(gid: gid_t, grp: *group, buf: [*]u8, buflen: usize, result: *?*group) c_int;
10335pub extern "c" fn getrlimit64(resource: rlimit_resource, rlim: *rlimit) c_int;10335pub extern "c" fn getrlimit64(resource: rlimit_resource, rlim: *rlimit) c_int;
10336pub extern "c" fn lseek64(fd: fd_t, offset: i64, whence: c_int) i64;10336pub extern "c" fn lseek64(fd: fd_t, offset: i64, whence: c_int) i64;
10337pub extern "c" fn mmap64(addr: ?*align(page_size) anyopaque, len: usize, prot: PROT, flags: c_uint, fd: fd_t, offset: i64) *anyopaque;10337pub extern "c" fn mmap64(addr: ?*align(page_size) anyopaque, len: usize, prot: PROT, flags: MAP, fd: fd_t, offset: i64) *anyopaque;
10338pub extern "c" fn open64(path: [*:0]const u8, oflag: O, ...) c_int;10338pub extern "c" fn open64(path: [*:0]const u8, oflag: O, ...) c_int;
10339pub extern "c" fn openat64(fd: c_int, path: [*:0]const u8, oflag: O, ...) c_int;10339pub extern "c" fn openat64(fd: c_int, path: [*:0]const u8, oflag: O, ...) c_int;
10340pub extern "c" fn pread64(fd: fd_t, buf: [*]u8, nbyte: usize, offset: i64) isize;10340pub extern "c" fn pread64(fd: fd_t, buf: [*]u8, nbyte: usize, offset: i64) isize;