diff --git a/lib/std/c.zig b/lib/std/c.zig index 9d5e5bf9ab..a8ad12212d 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -1599,6 +1599,25 @@ pub const MADV = switch (native_os) { }, else => void, }; +pub const MCL = switch (native_os) { + .linux => linux.MCL, + // https://github.com/freebsd/freebsd-src/blob/39fea5c8dc598021e900c4feaf0e18111fda57b2/sys/sys/mman.h#L133 + // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/088552723935447397400336f5ddb7aa5f5de660/sys/sys/mman.h#L118 + // https://github.com/NetBSD/src/blob/fd2741deca927c18e3ba15acdf78b8b14b2abe36/sys/sys/mman.h#L179 + // https://github.com/openbsd/src/blob/39404228f6d36c0ca4be5f04ab5385568ebd6aa3/sys/sys/mman.h#L129 + // https://github.com/kofemann/opensolaris/blob/80192cd83bf665e708269dae856f9145f7190f74/usr/src/uts/common/sys/mman.h#L379 + // https://github.com/illumos/illumos-gate/blob/5280477614f83fea20fc938729df6adb3e44340d/usr/src/uts/common/sys/mman.h#L343 + .freebsd, .dragonfly, .netbsd, .openbsd, .solaris, .illumos => packed struct(c_int) { + CURRENT: bool = 0, + FUTURE: bool = 0, + _: std.meta.Int(.unsigned, @bitSizeOf(c_int) - 2) = 0, + }, + else => void, +}; +pub const MLOCK = switch (native_os) { + .linux => linux.MLOCK, + else => void, +}; pub const MSF = switch (native_os) { .linux => linux.MSF, .emscripten => emscripten.MSF, @@ -10425,6 +10444,31 @@ pub const gettimeofday = switch (native_os) { else => private.gettimeofday, }; +pub const mlock = switch (native_os) { + .windows, .wasi => {}, + else => private.mlock, +}; + +pub const mlock2 = switch (native_os) { + linux => private.mlock2, + else => {}, +}; + +pub const munlock = switch (native_os) { + .windows, .wasi => {}, + else => private.munlock, +}; + +pub const mlockall = switch (native_os) { + .linux, .freebsd, .dragonfly, .netbsd, .openbsd, .solaris, .illumos => private.mlockall, + else => {}, +}; + +pub const munlockall = switch (native_os) { + .linux, .freebsd, .dragonfly, .netbsd, .openbsd, .solaris, .illumos => private.munlockall, + else => {}, +}; + pub const msync = switch (native_os) { .netbsd => private.__msync13, else => private.msync, @@ -11314,6 +11358,12 @@ const private = struct { extern "c" fn malloc_usable_size(?*const anyopaque) usize; extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int; + extern "c" fn mlock(addr: *align(page_size) const anyopaque, len: usize) c_int; + extern "c" fn mlock2(addr: *align(page_size) const anyopaque, len: usize, flags: MLOCK) c_int; + extern "c" fn munlock(addr: *align(page_size) const anyopaque, len: usize) c_int; + extern "c" fn mlockall(flags: MCL) c_int; + extern "c" fn munlockall() c_int; + /// macos modernized symbols. /// x86_64 links to $INODE64 suffix for 64-bit support. /// Note these are not necessary on aarch64. diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 90ab157f0c..256ed036c5 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -81,7 +81,9 @@ pub const Kevent = system.Kevent; pub const MADV = system.MADV; pub const MAP = system.MAP; pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN; +pub const MCL = system.MCL; pub const MFD = system.MFD; +pub const MLOCK = system.MLOCK; pub const MREMAP = system.MREMAP; pub const MSF = system.MSF; pub const MSG = system.MSG; @@ -4745,6 +4747,76 @@ pub fn fanotify_markZ( } } +pub const MlockError = error{ + PermissionDenied, + LockedMemoryLimitExceeded, + SystemResources, +} || UnexpectedError; + +pub fn mlock(memory: []align(page_size_min) const u8) MlockError!void { + if (@TypeOf(system.mlock) == void) + @compileError("mlock not supported on this OS"); + return switch (errno(system.mlock(memory.ptr, memory.len))) { + .SUCCESS => {}, + .INVAL => unreachable, // unaligned, negative, runs off end of addrspace + .PERM => error.PermissionDenied, + .NOMEM => error.LockedMemoryLimitExceeded, + .AGAIN => error.SystemResources, + else => |err| unexpectedErrno(err), + }; +} + +pub fn mlock2(memory: []align(page_size_min) const u8, flags: MLOCK) MlockError!void { + if (@TypeOf(system.mlock2) == void) + @compileError("mlock2 not supported on this OS"); + return switch (errno(system.mlock2(memory.ptr, memory.len, flags))) { + .SUCCESS => {}, + .INVAL => unreachable, // bad memory or bad flags + .PERM => error.PermissionDenied, + .NOMEM => error.LockedMemoryLimitExceeded, + .AGAIN => error.SystemResources, + else => |err| unexpectedErrno(err), + }; +} + +pub fn munlock(memory: []align(page_size_min) const u8) MlockError!void { + if (@TypeOf(system.munlock) == void) + @compileError("munlock not supported on this OS"); + return switch (errno(system.munlock(memory.ptr, memory.len))) { + .SUCCESS => {}, + .INVAL => unreachable, // unaligned or runs off end of addr space + .PERM => return error.PermissionDenied, + .NOMEM => return error.LockedMemoryLimitExceeded, + .AGAIN => return error.SystemResources, + else => |err| unexpectedErrno(err), + }; +} + +pub fn mlockall(flags: MCL) MlockError!void { + if (@TypeOf(system.mlockall) == void) + @compileError("mlockall not supported on this OS"); + return switch (errno(system.mlockall(flags))) { + .SUCCESS => {}, + .INVAL => unreachable, // bad flags + .PERM => error.PermissionDenied, + .NOMEM => error.LockedMemoryLimitExceeded, + .AGAIN => error.SystemResources, + else => |err| unexpectedErrno(err), + }; +} + +pub fn munlockall() MlockError!void { + if (@TypeOf(system.munlockall) == void) + @compileError("munlockall not supported on this OS"); + return switch (errno(system.munlockall())) { + .SUCCESS => {}, + .PERM => error.PermissionDenied, + .NOMEM => error.LockedMemoryLimitExceeded, + .AGAIN => error.SystemResources, + else => |err| unexpectedErrno(err), + }; +} + pub const MProtectError = error{ /// The memory cannot be given the specified access. This can happen, for example, if you /// mmap(2) a file to which you have read-only access, then ask mprotect() to mark it