authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-31 20:41:30-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-31 20:41:30-05:00
log0fb3e6608c160a0cd9db75fe1ba3d5bb7dac8fa8
tree763b53d7ddba82762ee32f4e7b724ffe9f97103d
parentc8c65b0168ae18f8bd8bf8f38590109a30df73a8
parent0c8ec369f051d616434cff309fe737c52fd98199
signature Commit is signed but in an unrecognized format.

Merge branch 'lun-4-linux-memfd-create'

Closes #3687

6 files changed, 111 insertions(+), 0 deletions(-)

lib/std/c/linux.zig+2
......@@ -76,6 +76,8 @@ pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_
7676
7777pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
7878
79pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int;
80
7981pub const pthread_attr_t = extern struct {
8082 __size: [56]u8,
8183 __align: c_long,
lib/std/os.zig+44
......@@ -3281,3 +3281,47 @@ pub fn setsockopt(fd: fd_t, level: u32, optname: u32, opt: []const u8) SetSockOp
32813281 else => |err| return unexpectedErrno(err),
32823282 }
32833283}
3284
3285pub const MemFdCreateError = error{
3286 SystemFdQuotaExceeded,
3287 ProcessFdQuotaExceeded,
3288 OutOfMemory,
3289
3290 /// memfd_create is available in Linux 3.17 and later. This error is returned
3291 /// for older kernel versions.
3292 SystemOutdated,
3293} || UnexpectedError;
3294
3295pub fn memfd_createC(name: [*:0]const u8, flags: u32) MemFdCreateError!fd_t {
3296 // memfd_create is available only in glibc versions starting with 2.27.
3297 const use_c = std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok;
3298 const sys = if (use_c) std.c else linux;
3299 const getErrno = if (use_c) std.c.getErrno else linux.getErrno;
3300 const rc = sys.memfd_create(name, flags);
3301 switch (getErrno(rc)) {
3302 0 => return @intCast(fd_t, rc),
3303 EFAULT => unreachable, // name has invalid memory
3304 EINVAL => unreachable, // name/flags are faulty
3305 ENFILE => return error.SystemFdQuotaExceeded,
3306 EMFILE => return error.ProcessFdQuotaExceeded,
3307 ENOMEM => return error.OutOfMemory,
3308 ENOSYS => return error.SystemOutdated,
3309 else => |err| return unexpectedErrno(err),
3310 }
3311}
3312
3313pub const MFD_NAME_PREFIX = "memfd:";
3314pub const MFD_MAX_NAME_LEN = NAME_MAX - MFD_NAME_PREFIX.len;
3315fn toMemFdPath(name: []const u8) ![MFD_MAX_NAME_LEN:0]u8 {
3316 var path_with_null: [MFD_MAX_NAME_LEN:0]u8 = undefined;
3317 // >= rather than > to make room for the null byte
3318 if (name.len >= MFD_MAX_NAME_LEN) return error.NameTooLong;
3319 mem.copy(u8, &path_with_null, name);
3320 path_with_null[name.len] = 0;
3321 return path_with_null;
3322}
3323
3324pub fn memfd_create(name: []const u8, flags: u32) !fd_t {
3325 const name_t = try toMemFdPath(name);
3326 return memfd_createC(&name_t, flags);
3327}
lib/std/os/bits/linux.zig+36
......@@ -26,6 +26,7 @@ pub const uid_t = i32;
2626pub const gid_t = u32;
2727pub const clock_t = isize;
2828
29pub const NAME_MAX = 255;
2930pub const PATH_MAX = 4096;
3031pub const IOV_MAX = 1024;
3132
......@@ -1417,3 +1418,38 @@ pub const POLLHUP = 0x010;
14171418pub const POLLNVAL = 0x020;
14181419pub const POLLRDNORM = 0x040;
14191420pub const POLLRDBAND = 0x080;
1421
1422pub const MFD_CLOEXEC = 0x0001;
1423pub const MFD_ALLOW_SEALING = 0x0002;
1424pub const MFD_HUGETLB = 0x0004;
1425pub const MFD_ALL_FLAGS = MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB;
1426
1427pub const HUGETLB_FLAG_ENCODE_SHIFT = 26;
1428pub const HUGETLB_FLAG_ENCODE_MASK = 0x3f;
1429pub const HUGETLB_FLAG_ENCODE_64KB = 16 << HUGETLB_FLAG_ENCODE_SHIFT;
1430pub const HUGETLB_FLAG_ENCODE_512KB = 19 << HUGETLB_FLAG_ENCODE_SHIFT;
1431pub const HUGETLB_FLAG_ENCODE_1MB = 20 << HUGETLB_FLAG_ENCODE_SHIFT;
1432pub const HUGETLB_FLAG_ENCODE_2MB = 21 << HUGETLB_FLAG_ENCODE_SHIFT;
1433pub const HUGETLB_FLAG_ENCODE_8MB = 23 << HUGETLB_FLAG_ENCODE_SHIFT;
1434pub const HUGETLB_FLAG_ENCODE_16MB = 24 << HUGETLB_FLAG_ENCODE_SHIFT;
1435pub const HUGETLB_FLAG_ENCODE_32MB = 25 << HUGETLB_FLAG_ENCODE_SHIFT;
1436pub const HUGETLB_FLAG_ENCODE_256MB = 28 << HUGETLB_FLAG_ENCODE_SHIFT;
1437pub const HUGETLB_FLAG_ENCODE_512MB = 29 << HUGETLB_FLAG_ENCODE_SHIFT;
1438pub const HUGETLB_FLAG_ENCODE_1GB = 30 << HUGETLB_FLAG_ENCODE_SHIFT;
1439pub const HUGETLB_FLAG_ENCODE_2GB = 31 << HUGETLB_FLAG_ENCODE_SHIFT;
1440pub const HUGETLB_FLAG_ENCODE_16GB = 34 << HUGETLB_FLAG_ENCODE_SHIFT;
1441
1442pub const MFD_HUGE_SHIFT = HUGETLB_FLAG_ENCODE_SHIFT;
1443pub const MFD_HUGE_MASK = HUGETLB_FLAG_ENCODE_MASK;
1444pub const MFD_HUGE_64KB = HUGETLB_FLAG_ENCODE_64KB;
1445pub const MFD_HUGE_512KB = HUGETLB_FLAG_ENCODE_512KB;
1446pub const MFD_HUGE_1MB = HUGETLB_FLAG_ENCODE_1MB;
1447pub const MFD_HUGE_2MB = HUGETLB_FLAG_ENCODE_2MB;
1448pub const MFD_HUGE_8MB = HUGETLB_FLAG_ENCODE_8MB;
1449pub const MFD_HUGE_16MB = HUGETLB_FLAG_ENCODE_16MB;
1450pub const MFD_HUGE_32MB = HUGETLB_FLAG_ENCODE_32MB;
1451pub const MFD_HUGE_256MB = HUGETLB_FLAG_ENCODE_256MB;
1452pub const MFD_HUGE_512MB = HUGETLB_FLAG_ENCODE_512MB;
1453pub const MFD_HUGE_1GB = HUGETLB_FLAG_ENCODE_1GB;
1454pub const MFD_HUGE_2GB = HUGETLB_FLAG_ENCODE_2GB;
1455pub const MFD_HUGE_16GB = HUGETLB_FLAG_ENCODE_16GB;
lib/std/os/linux.zig+4
......@@ -1110,6 +1110,10 @@ pub fn io_uring_register(fd: i32, opcode: u32, arg: ?*const c_void, nr_args: u32
11101110 return syscall4(SYS_io_uring_register, @bitCast(usize, @as(isize, fd)), opcode, @ptrToInt(arg), nr_args);
11111111}
11121112
1113pub fn memfd_create(name: [*:0]const u8, flags: u32) usize {
1114 return syscall2(SYS_memfd_create, @ptrToInt(name), flags);
1115}
1116
11131117test "" {
11141118 if (builtin.os == .linux) {
11151119 _ = @import("linux/test.zig");
lib/std/os/test.zig+18
......@@ -237,3 +237,21 @@ test "argsAlloc" {
237237 var args = try std.process.argsAlloc(std.heap.page_allocator);
238238 std.process.argsFree(std.heap.page_allocator, args);
239239}
240
241test "memfd_create" {
242 // memfd_create is linux specific.
243 if (builtin.os != .linux) return error.SkipZigTest;
244 const fd = std.os.memfd_create("test", 0) catch |err| switch (err) {
245 // Related: https://github.com/ziglang/zig/issues/4019
246 error.SystemOutdated => return error.SkipZigTest,
247 else => |e| return e,
248 };
249 defer std.os.close(fd);
250 try std.os.write(fd, "test");
251 try std.os.lseek_SET(fd, 0);
252
253 var buf: [10]u8 = undefined;
254 const bytes_read = try std.os.read(fd, &buf);
255 expect(bytes_read == 4);
256 expect(mem.eql(u8, buf[0..4], "test"));
257}
lib/std/target.zig+7
......@@ -597,6 +597,13 @@ pub const Target = union(enum) {
597597 };
598598 }
599599
600 pub fn isMusl(self: Target) bool {
601 return switch (self.getAbi()) {
602 .musl, .musleabi, .musleabihf => true,
603 else => false,
604 };
605 }
606
600607 pub fn isDarwin(self: Target) bool {
601608 return switch (self.getOs()) {
602609 .ios, .macosx, .watchos, .tvos => true,