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(...@@ -16232,7 +16232,7 @@ fn createFileMap(
16232 protection: std.process.MemoryProtection,16232 protection: std.process.MemoryProtection,
16233 offset: u64,16233 offset: u64,
16234 populate: bool,16234 populate: bool,
16235 aligned_len: usize,16235 len: usize,
16236) CreateFileMapError!File.MemoryMap {16236) CreateFileMapError!File.MemoryMap {
16237 if (is_windows) {16237 if (is_windows) {
16238 try Thread.checkCancel();16238 try Thread.checkCancel();
...@@ -16251,7 +16251,7 @@ fn createFileMap(...@@ -16251,7 +16251,7 @@ fn createFileMap(
16251 .STANDARD = .{ .RIGHTS = .REQUIRED },16251 .STANDARD = .{ .RIGHTS = .REQUIRED },
16252 },16252 },
16253 null,16253 null,
16254 @constCast(&@as(i64, @intCast(aligned_len))),16254 @constCast(&@as(i64, @intCast(len))),
16255 .{ .READWRITE = true },16255 .{ .READWRITE = true },
16256 .{ .COMMIT = populate },16256 .{ .COMMIT = populate },
16257 file.handle,16257 file.handle,
...@@ -16261,12 +16261,11 @@ fn createFileMap(...@@ -16261,12 +16261,11 @@ fn createFileMap(
16261 .INVALID_FILE_FOR_SECTION => return error.OperationUnsupported,16261 .INVALID_FILE_FOR_SECTION => return error.OperationUnsupported,
16262 else => |status| return windows.unexpectedStatus(status),16262 else => |status| return windows.unexpectedStatus(status),
16263 }16263 }
16264 const current_process: windows.HANDLE = @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))));16264 var contents_ptr: ?[*]align(std.heap.page_size_min) u8 = null;
16265 var contents_ptr: ?[*]u8 = null;16265 var contents_len = len;
16266 var contents_len = aligned_len;
16267 switch (windows.ntdll.NtMapViewOfSection(16266 switch (windows.ntdll.NtMapViewOfSection(
16268 section,16267 section,
16269 current_process,16268 windows.current_process,
16270 @ptrCast(&contents_ptr),16269 @ptrCast(&contents_ptr),
16271 null,16270 null,
16272 0,16271 0,
...@@ -16284,7 +16283,7 @@ fn createFileMap(...@@ -16284,7 +16283,7 @@ fn createFileMap(
16284 return .{16283 return .{
16285 .file = file,16284 .file = file,
16286 .offset = offset,16285 .offset = offset,
16287 .memory = @alignCast(contents_ptr.?[0..contents_len]),16286 .memory = contents_ptr.?[0..contents_len],
16288 .section = section,16287 .section = section,
16289 };16288 };
16290 } else if (have_mmap) {16289 } else if (have_mmap) {
...@@ -16308,17 +16307,17 @@ fn createFileMap(...@@ -16308,17 +16307,17 @@ fn createFileMap(
16308 const contents = while (true) {16307 const contents = while (true) {
16309 const syscall: Syscall = try .start();16308 const syscall: Syscall = try .start();
16310 const casted_offset = std.math.cast(i64, offset) orelse return error.Unseekable;16309 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);
16312 syscall.finish();16311 syscall.finish();
16313 const err: posix.E = if (builtin.link_libc) e: {16312 const err: posix.E = if (builtin.link_libc) e: {
16314 if (rc != std.c.MAP_FAILED) {16313 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];
16316 }16315 }
16317 break :e @enumFromInt(posix.system._errno().*);16316 break :e @enumFromInt(posix.system._errno().*);
16318 } else e: {16317 } else e: {
16319 const err = posix.errno(rc);16318 const err = posix.errno(rc);
16320 if (err == .SUCCESS) {16319 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];
16322 }16321 }
16323 break :e err;16322 break :e err;
16324 };16323 };
...@@ -16356,8 +16355,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {...@@ -16356,8 +16355,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {
16356 const memory = mm.memory;16355 const memory = mm.memory;
16357 if (mm.section) |section| switch (native_os) {16356 if (mm.section) |section| switch (native_os) {
16358 .windows => {16357 .windows => {
16359 const current_process: windows.HANDLE = @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))));16358 _ = windows.ntdll.NtUnmapViewOfSection(windows.current_process, memory.ptr);
16360 _ = windows.ntdll.NtUnmapViewOfSection(current_process, memory.ptr);
16361 windows.CloseHandle(section);16359 windows.CloseHandle(section);
16362 },16360 },
16363 .wasi => unreachable,16361 .wasi => unreachable,
...@@ -16394,8 +16392,25 @@ fn fileMemoryMapSetLength(...@@ -16394,8 +16392,25 @@ fn fileMemoryMapSetLength(
16394 }16392 }
16395 switch (native_os) {16393 switch (native_os) {
16396 .windows => {16394 .windows => {
16397 _ = section;16395 var contents_ptr: ?[*]align(page_align) u8 = null;
16398 @panic("TODO");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];
16399 },16414 },
16400 .wasi => unreachable,16415 .wasi => unreachable,
16401 .linux => {16416 .linux => {
lib/std/Io/test.zig+3-2
...@@ -640,9 +640,10 @@ test "memory mapping" {...@@ -640,9 +640,10 @@ test "memory mapping" {
640640
641 try expectEqualStrings("this9is9my", mm.memory);641 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 });
644 try mm.read(io);645 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]);
647 }648 }
648}649}
lib/std/os/windows.zig+2
...@@ -28,6 +28,8 @@ pub const ws2_32 = @import("windows/ws2_32.zig");...@@ -28,6 +28,8 @@ pub const ws2_32 = @import("windows/ws2_32.zig");
28pub const crypt32 = @import("windows/crypt32.zig");28pub const crypt32 = @import("windows/crypt32.zig");
29pub const nls = @import("windows/nls.zig");29pub const nls = @import("windows/nls.zig");
3030
31pub const current_process: HANDLE = @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))));
32
31pub const FILE = struct {33pub const FILE = struct {
32 // ref: km/ntddk.h34 // ref: km/ntddk.h
3335