feature. See also
. The project being documented here (as the example) is the Zig library itself.
Threaded.fileMemoryMapSetLength
fn fileMemoryMapSetLength(
userdata: ?*anyopaque,
mm: *File.MemoryMap,
new_len: usize,
) File.MemoryMap.SetLengthError!void
File
Code
fn fileMemoryMapSetLength(
userdata: ?*anyopaque,
mm: *File.MemoryMap,
new_len: usize,
) File.MemoryMap.SetLengthError!void {
const t: *Threaded = @ptrCast(@alignCast(userdata));
const page_size = std.heap.pageSize();
const alignment: Alignment = .fromByteUnits(page_size);
const page_align = std.heap.page_size_min;
const old_memory = mm.memory;
if (mm.section) |section| {
_ = section;
if (alignment.forward(new_len) == alignment.forward(old_memory.len)) {
mm.memory.len = new_len;
return;
}
switch (native_os) {
.wasi => unreachable,
.linux => {
const flags: posix.MREMAP = .{ .MAYMOVE = true };
const addr_hint: ?[*]const u8 = null;
const new_memory = while (true) {
const syscall: Syscall = try .start();
const rc = posix.system.mremap(old_memory.ptr, old_memory.len, new_len, flags, addr_hint);
syscall.finish();
const err: posix.E = if (builtin.link_libc) e: {
if (rc != std.c.MAP_FAILED) break @as([*]align(page_align) u8, @ptrCast(@alignCast(rc)))[0..new_len];
break :e @fromBackingInt(@intCast(posix.system._errno().*));
} else e: {
const err = posix.errno(rc);
if (err == .SUCCESS) break @as([*]align(page_align) u8, @ptrFromInt(rc))[0..new_len];
break :e err;
};
switch (err) {
.SUCCESS => unreachable,
.INTR => continue,
.AGAIN => return error.LockedMemoryLimitExceeded,
.NOMEM => return error.OutOfMemory,
.INVAL => return errnoBug(err),
.FAULT => return errnoBug(err),
else => return posix.unexpectedErrno(err),
}
};
mm.memory = new_memory;
return;
},
else => return error.OperationUnsupported,
}
} else {
const gpa = t.allocator;
if (gpa.rawRemap(old_memory, alignment, new_len, @returnAddress())) |new_ptr| {
mm.memory = @alignCast(new_ptr[0..new_len]);
} else {
const new_ptr: [*]align(page_align) u8 = @alignCast(
gpa.rawAlloc(new_len, alignment, @returnAddress()) orelse return error.OutOfMemory,
);
const copy_len = @min(new_len, old_memory.len);
@memcpy(new_ptr[0..copy_len], old_memory[0..copy_len]);
mm.memory = new_ptr[0..new_len];
gpa.rawFree(old_memory, alignment, @returnAddress());
}
}
}