From 1a913f6bf2ac33426f889900b75afa471cc4cee5 Mon Sep 17 00:00:00 2001 From: MovingtoMars Date: Thu, 28 Jan 2016 12:39:02 +1300 Subject: [PATCH 1/4] simple malloc and free using mmap --- CMakeLists.txt | 1 + std/mem.zig | 21 +++++++++++++++++++++ std/syscall.zig | 36 ++++++++++++++++++++++++++++++++++++ test/run_tests.cpp | 18 ++++++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 std/mem.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index a745cf1faa..5e06248ac6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,6 +123,7 @@ set(ZIG_STD_SRC "${CMAKE_SOURCE_DIR}/std/syscall.zig" "${CMAKE_SOURCE_DIR}/std/errno.zig" "${CMAKE_SOURCE_DIR}/std/rand.zig" + "${CMAKE_SOURCE_DIR}/std/mem.zig" ) set(C_HEADERS_DEST "lib/zig/include") diff --git a/std/mem.zig b/std/mem.zig new file mode 100644 index 0000000000..d19dad9f9e --- /dev/null +++ b/std/mem.zig @@ -0,0 +1,21 @@ +import "syscall.zig"; +import "std.zig"; + +pub fn malloc(bytes: isize) -> ?&u8 { + if (bytes > 4096) { + %%stderr.printf("TODO alloc sizes > 4096B\n"); + return null; + } + + const result = mmap(0, 4096, MMAP_PROT_READ|MMAP_PROT_WRITE, MMAP_MAP_ANON|MMAP_MAP_SHARED, -1, 0); + + if (result == -1) { + return null; + } + + (&u8)(result) +} + +pub fn free(ptr: &u8) { + munmap(isize(ptr), 4096); +} diff --git a/std/syscall.zig b/std/syscall.zig index eeabd2a510..504f785fe6 100644 --- a/std/syscall.zig +++ b/std/syscall.zig @@ -1,8 +1,22 @@ const SYS_read = 0; const SYS_write = 1; +const SYS_mmap = 9; +const SYS_munmap = 11; const SYS_exit = 60; const SYS_getrandom = 318; +// mmap constants +pub const MMAP_PROT_NONE = 0; +pub const MMAP_PROT_READ = 1; +pub const MMAP_PROT_WRITE = 2; +pub const MMAP_PROT_EXEC = 4; + +pub const MMAP_MAP_FILE = 0; +pub const MMAP_MAP_SHARED = 1; +pub const MMAP_MAP_PRIVATE = 2; +pub const MMAP_MAP_FIXED = 16; +pub const MMAP_MAP_ANON = 32; + fn syscall1(number: isize, arg1: isize) -> isize { asm volatile ("syscall" : [ret] "={rax}" (-> isize) @@ -17,6 +31,28 @@ fn syscall3(number: isize, arg1: isize, arg2: isize, arg3: isize) -> isize { : "rcx", "r11") } +fn syscall2(number: isize, arg1: isize, arg2: isize) -> isize { + asm volatile ("syscall" + : [ret] "={rax}" (-> isize) + : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2) + : "rcx", "r11") +} + +fn syscall6(number: isize, arg1: isize, arg2: isize, arg3: isize, arg4: isize, arg5: isize, arg6: isize) -> isize { + asm volatile ("syscall" + : [ret] "={rax}" (-> isize) + : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3), [arg4] "{r10}" (arg4), [arg5] "{r8}" (arg5), [arg6] "{r9}" (arg6) + : "rcx", "r11") +} + +pub fn mmap(address: isize, length: isize, prot: isize, flags: isize, fd: isize, offset: isize) -> isize { + syscall6(SYS_mmap, address, length, prot, flags, fd, offset) +} + +pub fn munmap(address: isize, length: isize) -> isize { + syscall2(SYS_munmap, address, length) +} + pub fn read(fd: isize, buf: &u8, count: isize) -> isize { syscall3(SYS_read, isize(fd), isize(buf), count) } diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 2b80832e8b..73478c6b55 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -1344,6 +1344,24 @@ pub fn main(args: [][]u8) -> %void { %%stdout.printf("BAD\n"); } %%stdout.printf("OK\n"); +} + )SOURCE", "OK\n"); + + add_simple_case("malloc and free", R"SOURCE( +import "mem.zig"; +import "std.zig"; + +pub fn main(args: [][]u8) -> %void { + var ptr = malloc(1) ?? unreachable{}; + + *ptr = 6; + + if (*ptr != 6) { + %%stdout.printf("BAD\n"); + } + %%stdout.printf("OK\n"); + + free(ptr); } )SOURCE", "OK\n"); } From 04b721d53530c1de825f7d1df93f2e23916e092d Mon Sep 17 00:00:00 2001 From: MovingtoMars Date: Thu, 28 Jan 2016 13:18:29 +1300 Subject: [PATCH 2/4] malloc fails on proper errors --- std/mem.zig | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/std/mem.zig b/std/mem.zig index d19dad9f9e..dae3a091b1 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -1,5 +1,6 @@ import "syscall.zig"; import "std.zig"; +import "errno.zig"; pub fn malloc(bytes: isize) -> ?&u8 { if (bytes > 4096) { @@ -7,13 +8,28 @@ pub fn malloc(bytes: isize) -> ?&u8 { return null; } - const result = mmap(0, 4096, MMAP_PROT_READ|MMAP_PROT_WRITE, MMAP_MAP_ANON|MMAP_MAP_SHARED, -1, 0); + const result = mmap(isize(0), 4096, MMAP_PROT_READ|MMAP_PROT_WRITE, MMAP_MAP_ANON|MMAP_MAP_SHARED, -1, 0); - if (result == -1) { - return null; + const failed: bool = switch (-result) { + 0 => true, + EINVAL => true, + EACCES => true, + EAGAIN => true, + EBADF => true, + EMFILE => true, + ENODEV => true, + ENOMEM => true, + EOPNOTSUPP => true, + ENXIO => true, + EOVERFLOW => true, + else => false, + }; + + if (failed) { + null + } else { + (&u8)(result) } - - (&u8)(result) } pub fn free(ptr: &u8) { From 9c502030a1e42a0d2ef164b1f322674a66aa42c1 Mon Sep 17 00:00:00 2001 From: MovingtoMars Date: Thu, 28 Jan 2016 13:45:35 +1300 Subject: [PATCH 3/4] check mmap return against -1 --- std/mem.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/std/mem.zig b/std/mem.zig index dae3a091b1..803760fd34 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -12,6 +12,7 @@ pub fn malloc(bytes: isize) -> ?&u8 { const failed: bool = switch (-result) { 0 => true, + -1 => true, EINVAL => true, EACCES => true, EAGAIN => true, From 401a3361ea13e7b8e063cbad29d3c0d7cc0f86a9 Mon Sep 17 00:00:00 2001 From: MovingtoMars Date: Thu, 28 Jan 2016 16:01:52 +1300 Subject: [PATCH 4/4] malloc fails on mmap error code properly --- std/mem.zig | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/std/mem.zig b/std/mem.zig index 803760fd34..a10a6c9569 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -10,23 +10,7 @@ pub fn malloc(bytes: isize) -> ?&u8 { const result = mmap(isize(0), 4096, MMAP_PROT_READ|MMAP_PROT_WRITE, MMAP_MAP_ANON|MMAP_MAP_SHARED, -1, 0); - const failed: bool = switch (-result) { - 0 => true, - -1 => true, - EINVAL => true, - EACCES => true, - EAGAIN => true, - EBADF => true, - EMFILE => true, - ENODEV => true, - ENOMEM => true, - EOPNOTSUPP => true, - ENXIO => true, - EOVERFLOW => true, - else => false, - }; - - if (failed) { + if (-4096 < result && result <= 0) { null } else { (&u8)(result)