Skip to content

Commit 94aafe6

Browse files
committed
Implement (m|mun)lockall for Linux and *nix libcs
1 parent 3e9f186 commit 94aafe6

File tree

9 files changed

+122
-0
lines changed

9 files changed

+122
-0
lines changed

lib/std/c/dragonfly.zig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ pub extern "c" fn lwp_gettid() c_int;
2222

2323
pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int;
2424

25+
pub extern "c" fn mlockall(flags: c_int) c_int;
26+
pub extern "c" fn munlockall() c_int;
27+
2528
pub const pthread_attr_t = extern struct { // copied from freebsd
2629
__size: [56]u8,
2730
__align: c_long,
@@ -937,6 +940,11 @@ pub const MADV = struct {
937940
pub const SETMAP = 11;
938941
};
939942

943+
pub const MCL = struct {
944+
pub const CURRENT = 0x01;
945+
pub const FUTURE = 0x02;
946+
};
947+
940948
pub const LOCK = struct {
941949
pub const SH = 1;
942950
pub const EX = 2;

lib/std/c/freebsd.zig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ pub extern "c" fn getpid() pid_t;
2525

2626
pub extern "c" fn kinfo_getfile(pid: pid_t, cntp: *c_int) ?[*]kinfo_file;
2727

28+
pub extern "c" fn mlockall(flags: c_int) c_int;
29+
pub extern "c" fn munlockall() c_int;
30+
2831
pub const sf_hdtr = extern struct {
2932
headers: [*]const iovec_const,
3033
hdr_cnt: c_int,
@@ -606,6 +609,11 @@ pub const MADV = struct {
606609
pub const PROTECT = 10;
607610
};
608611

612+
pub const MCL = struct {
613+
pub const CURRENT = 0x01;
614+
pub const FUTURE = 0x02;
615+
};
616+
609617
pub const MSF = struct {
610618
pub const ASYNC = 1;
611619
pub const INVALIDATE = 2;

lib/std/c/linux.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub const IOV_MAX = linux.IOV_MAX;
2323
pub const IPPROTO = linux.IPPROTO;
2424
pub const LOCK = linux.LOCK;
2525
pub const MADV = linux.MADV;
26+
pub const MCL = linux.MCL;
2627
pub const MSF = linux.MSF;
2728
pub const MMAP2_UNIT = linux.MMAP2_UNIT;
2829
pub const MSG = linux.MSG;
@@ -306,6 +307,9 @@ pub extern "c" fn madvise(
306307
advice: c_uint,
307308
) c_int;
308309

310+
pub extern "c" fn mlockall(flags: c_int) c_int;
311+
pub extern "c" fn munlockall() c_int;
312+
309313
pub const pthread_attr_t = extern struct {
310314
__size: [56]u8,
311315
__align: c_long,

lib/std/c/netbsd.zig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ pub const sigaltstack = __sigaltstack14;
2626

2727
pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int;
2828

29+
pub extern "c" fn mlockall(flags: c_int) c_int;
30+
pub extern "c" fn munlockall() c_int;
31+
2932
pub const pthread_spin_t = switch (builtin.cpu.arch) {
3033
.aarch64, .aarch64_be, .aarch64_32 => u8,
3134
.mips, .mipsel, .mips64, .mips64el => u32,
@@ -500,6 +503,11 @@ pub const CLOCK = struct {
500503
pub const PROCESS_CPUTIME_ID = 0x40000000;
501504
};
502505

506+
pub const MCL = struct {
507+
pub const CURRENT = 0x01;
508+
pub const FUTURE = 0x02;
509+
};
510+
503511
pub const MSF = struct {
504512
pub const ASYNC = 1;
505513
pub const INVALIDATE = 2;

lib/std/c/openbsd.zig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub extern "c" fn pipe2(fds: *[2]fd_t, flags: std.c.O) c_int;
1919
pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) c_int;
2020
pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
2121

22+
pub extern "c" fn mlockall(flags: c_int) c_int;
23+
pub extern "c" fn munlockall() c_int;
24+
2225
pub const pthread_spinlock_t = extern struct {
2326
inner: ?*anyopaque = null,
2427
};
@@ -425,6 +428,11 @@ pub const CLOCK = struct {
425428
pub const THREAD_CPUTIME_ID = 4;
426429
};
427430

431+
pub const MCL = struct {
432+
pub const CURRENT = 0x01;
433+
pub const FUTURE = 0x02;
434+
};
435+
428436
pub const MSF = struct {
429437
pub const ASYNC = 1;
430438
pub const INVALIDATE = 2;

lib/std/c/solaris.zig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: u
2020
pub extern "c" fn sysconf(sc: c_int) i64;
2121
pub extern "c" fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) c_int;
2222
pub extern "c" fn madvise(address: [*]u8, len: usize, advise: u32) c_int;
23+
pub extern "c" fn mlockall(flags: c_int) c_int;
24+
pub extern "c" fn munlockall() c_int;
2325

2426
pub const pthread_attr_t = extern struct {
2527
mutexattr: ?*anyopaque = null,
@@ -525,6 +527,11 @@ pub const MADV = struct {
525527
pub const PURGE = 9;
526528
};
527529

530+
pub const MCL = struct {
531+
pub const CURRENT = 0x01;
532+
pub const FUTURE = 0x02;
533+
};
534+
528535
pub const W = struct {
529536
pub const EXITED = 0o001;
530537
pub const TRAPPED = 0o002;

lib/std/os/linux.zig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,6 +2093,14 @@ pub fn madvise(address: [*]u8, len: usize, advice: u32) usize {
20932093
return syscall3(.madvise, @intFromPtr(address), len, advice);
20942094
}
20952095

2096+
pub fn mlockall(flags: i32) usize {
2097+
return syscall1(.mlockall, @as(usize, @bitCast(@as(isize, flags))));
2098+
}
2099+
2100+
pub fn munlockall() usize {
2101+
return syscall0(.munlockall);
2102+
}
2103+
20962104
pub fn pidfd_open(pid: pid_t, flags: u32) usize {
20972105
return syscall2(.pidfd_open, @as(usize, @bitCast(@as(isize, pid))), flags);
20982106
}
@@ -6051,6 +6059,16 @@ pub const MADV = struct {
60516059
pub const SOFT_OFFLINE = 101;
60526060
};
60536061

6062+
pub const MCL = if (is_ppc or is_ppc64 or is_sparc) struct {
6063+
pub const CURRENT = 0x2000;
6064+
pub const FUTURE = 0x4000;
6065+
pub const ONFAULT = 0x8000;
6066+
} else struct {
6067+
pub const CURRENT = 0x01;
6068+
pub const FUTURE = 0x02;
6069+
pub const ONFAULT = 0x04;
6070+
};
6071+
60546072
pub const POSIX_FADV = switch (native_arch) {
60556073
.s390x => if (@typeInfo(usize).Int.bits == 64) struct {
60566074
pub const NORMAL = 0;

lib/std/posix.zig

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ pub const Kevent = system.Kevent;
7272
pub const LOCK = system.LOCK;
7373
pub const MADV = system.MADV;
7474
pub const MAP = system.MAP;
75+
pub const MCL = system.MCL;
7576
pub const MSF = system.MSF;
7677
pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN;
7778
pub const MFD = system.MFD;
@@ -7075,6 +7076,47 @@ pub fn madvise(ptr: [*]align(mem.page_size) u8, length: usize, advice: u32) Madv
70757076
}
70767077
}
70777078

7079+
pub const MlockallError = error{
7080+
InvalidArgument,
7081+
LockedMemoryLimitExceeded,
7082+
NotImplemented,
7083+
PermissionDenied,
7084+
SystemResources,
7085+
} || UnexpectedError;
7086+
7087+
pub fn mlockall(flags: i32) MlockallError!void {
7088+
switch (native_os) {
7089+
.linux, .freebsd, .netbsd, .openbsd, .dragonfly, .solaris => {},
7090+
else => return error.NotImplemented,
7091+
}
7092+
switch (errno(system.mlockall(flags))) {
7093+
.SUCCESS => return,
7094+
.INVAL => return error.InvalidArgument,
7095+
.NOMEM => return error.LockedMemoryLimitExceeded,
7096+
.PERM => return error.PermissionDenied,
7097+
// Solaris and (Free|Net|Open)BSD, presumably no room to fault in locked stuff:
7098+
.AGAIN => return error.SystemResources,
7099+
else => |err| return unexpectedErrno(err),
7100+
}
7101+
}
7102+
7103+
pub const MunlockallError = error{
7104+
NotImplemented,
7105+
PermissionDenied,
7106+
} || UnexpectedError;
7107+
7108+
pub fn munlockall() MunlockallError!void {
7109+
switch (native_os) {
7110+
.linux, .freebsd, .netbsd, .openbsd, .dragonfly, .solaris => {},
7111+
else => return error.NotImplemented,
7112+
}
7113+
switch (errno(system.munlockall())) {
7114+
.SUCCESS => return,
7115+
.PERM => return error.PermissionDenied, // Solaris, possibly BSDs as well
7116+
else => |err| return unexpectedErrno(err),
7117+
}
7118+
}
7119+
70787120
pub const PerfEventOpenError = error{
70797121
/// Returned if the perf_event_attr size value is too small (smaller
70807122
/// than PERF_ATTR_SIZE_VER0), too big (larger than the page size),

lib/std/posix/test.zig

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,3 +1315,22 @@ const CommonOpenFlags = packed struct {
13151315
return result;
13161316
}
13171317
};
1318+
1319+
test "mlockall/munlockall basic smoke" {
1320+
// We can't test a "real" mlockall because of various system perms/limits
1321+
// on locked memory and/or possible adverse effects on the testing
1322+
// environment itself. What we can do safely, I think, is execute
1323+
// mlockall() with a very-invalid (across all known platforms) flags value
1324+
// and expect E.INVAL (or NotImplemented when testing on non-supporting
1325+
// platforms), so that we at least exercise the code paths here.
1326+
const ok_errors = [_]anyerror{ error.NotImplemented, error.InvalidArgument };
1327+
try testing.expectErrors(&ok_errors, posix.mlockall(0b0001111111111000));
1328+
1329+
// On Linux, munlockall seems to have no perms or limits issues, so it should
1330+
// always be successful. This at least lets us exercise the code in the
1331+
// posix wrapper on one platform to know it's not horribly broken. This
1332+
// could have a real effect on the testing environment if it were already
1333+
// holding locked memory, but it shouldn't be.
1334+
if (native_os == .linux)
1335+
try posix.munlockall();
1336+
}

0 commit comments

Comments
 (0)