authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-15 10:30:25-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-15 14:18:20-08:00
logb2776d097d4407a8d76bea88e4289297eed65e3e
tree9d772c503043924da572cc4476e7dbe89e9dce25
parent8527ec9c7b229bcc8a15824e885d16abbab57534

std.Io.Threaded: implement MemoryMap.setLength for Windows


3 files changed, 34 insertions(+), 16 deletions(-)

lib/std/Io/Threaded.zig+29-14
......@@ -16232,7 +16232,7 @@ fn createFileMap(
1623216232 protection: std.process.MemoryProtection,
1623316233 offset: u64,
1623416234 populate: bool,
16235 aligned_len: usize,
16235 len: usize,
1623616236) CreateFileMapError!File.MemoryMap {
1623716237 if (is_windows) {
1623816238 try Thread.checkCancel();
......@@ -16251,7 +16251,7 @@ fn createFileMap(
1625116251 .STANDARD = .{ .RIGHTS = .REQUIRED },
1625216252 },
1625316253 null,
16254 @constCast(&@as(i64, @intCast(aligned_len))),
16254 @constCast(&@as(i64, @intCast(len))),
1625516255 .{ .READWRITE = true },
1625616256 .{ .COMMIT = populate },
1625716257 file.handle,
......@@ -16261,12 +16261,11 @@ fn createFileMap(
1626116261 .INVALID_FILE_FOR_SECTION => return error.OperationUnsupported,
1626216262 else => |status| return windows.unexpectedStatus(status),
1626316263 }
16264 const current_process: windows.HANDLE = @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))));
16265 var contents_ptr: ?[*]u8 = null;
16266 var contents_len = aligned_len;
16264 var contents_ptr: ?[*]align(std.heap.page_size_min) u8 = null;
16265 var contents_len = len;
1626716266 switch (windows.ntdll.NtMapViewOfSection(
1626816267 section,
16269 current_process,
16268 windows.current_process,
1627016269 @ptrCast(&contents_ptr),
1627116270 null,
1627216271 0,
......@@ -16284,7 +16283,7 @@ fn createFileMap(
1628416283 return .{
1628516284 .file = file,
1628616285 .offset = offset,
16287 .memory = @alignCast(contents_ptr.?[0..contents_len]),
16286 .memory = contents_ptr.?[0..contents_len],
1628816287 .section = section,
1628916288 };
1629016289 } else if (have_mmap) {
......@@ -16308,17 +16307,17 @@ fn createFileMap(
1630816307 const contents = while (true) {
1630916308 const syscall: Syscall = try .start();
1631016309 const casted_offset = std.math.cast(i64, offset) orelse return error.Unseekable;
16311 const rc = mmap_sym(null, aligned_len, prot, flags, file.handle, casted_offset);
16310 const rc = mmap_sym(null, len, prot, flags, file.handle, casted_offset);
1631216311 syscall.finish();
1631316312 const err: posix.E = if (builtin.link_libc) e: {
1631416313 if (rc != std.c.MAP_FAILED) {
16315 break @as([*]align(page_align) u8, @ptrCast(@alignCast(rc)))[0..aligned_len];
16314 break @as([*]align(page_align) u8, @ptrCast(@alignCast(rc)))[0..len];
1631616315 }
1631716316 break :e @enumFromInt(posix.system._errno().*);
1631816317 } else e: {
1631916318 const err = posix.errno(rc);
1632016319 if (err == .SUCCESS) {
16321 break @as([*]align(page_align) u8, @ptrFromInt(rc))[0..aligned_len];
16320 break @as([*]align(page_align) u8, @ptrFromInt(rc))[0..len];
1632216321 }
1632316322 break :e err;
1632416323 };
......@@ -16356,8 +16355,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {
1635616355 const memory = mm.memory;
1635716356 if (mm.section) |section| switch (native_os) {
1635816357 .windows => {
16359 const current_process: windows.HANDLE = @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))));
16360 _ = windows.ntdll.NtUnmapViewOfSection(current_process, memory.ptr);
16358 _ = windows.ntdll.NtUnmapViewOfSection(windows.current_process, memory.ptr);
1636116359 windows.CloseHandle(section);
1636216360 },
1636316361 .wasi => unreachable,
......@@ -16394,8 +16392,25 @@ fn fileMemoryMapSetLength(
1639416392 }
1639516393 switch (native_os) {
1639616394 .windows => {
16397 _ = section;
16398 @panic("TODO");
16395 var contents_ptr: ?[*]align(page_align) u8 = null;
16396 var contents_len = new_len;
16397 switch (windows.ntdll.NtMapViewOfSection(
16398 section,
16399 windows.current_process,
16400 @ptrCast(&contents_ptr),
16401 null,
16402 0,
16403 null,
16404 &contents_len,
16405 .Unmap,
16406 .{},
16407 .{ .READWRITE = true },
16408 )) {
16409 .SUCCESS => {},
16410 .SECTION_PROTECTION => return error.PermissionDenied,
16411 else => |status| return windows.unexpectedStatus(status),
16412 }
16413 mm.memory = contents_ptr.?[0..contents_len];
1639916414 },
1640016415 .wasi => unreachable,
1640116416 .linux => {
lib/std/Io/test.zig+3-2
......@@ -640,9 +640,10 @@ test "memory mapping" {
640640
641641 try expectEqualStrings("this9is9my", mm.memory);
642642
643 try mm.setLength(io, .{ .len = "this9is9my data123".len });
643 // Cross a page boundary to require an actual remap.
644 try mm.setLength(io, .{ .len = std.heap.pageSize() * 2 });
644645 try mm.read(io);
645646
646 try expectEqualStrings("this9is9my data123", mm.memory);
647 try expectEqualStrings("this9is9my data123\x00\x00", mm.memory[0.."this9is9my data123\x00\x00".len]);
647648 }
648649}
lib/std/os/windows.zig+2
......@@ -28,6 +28,8 @@ pub const ws2_32 = @import("windows/ws2_32.zig");
2828pub const crypt32 = @import("windows/crypt32.zig");
2929pub const nls = @import("windows/nls.zig");
3030
31pub const current_process: HANDLE = @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))));
32
3133pub const FILE = struct {
3234 // ref: km/ntddk.h
3335