From face6f07f3f342d17caec1806962a6b8fe054492 Mon Sep 17 00:00:00 2001
From: jD91mZM2 <me@krake.one>
Date: Thu, 9 Aug 2018 10:54:44 +0200
Subject: [PATCH] Implement mmap

---
 Cargo.lock                    |  1 +
 include/bits/sys/mman.h       |  6 +++++
 include/limits.h              |  6 ++++-
 include/stddef.h              |  2 ++
 src/fcntl/src/linux.rs        |  1 +
 src/platform/Cargo.toml       |  1 +
 src/platform/src/lib.rs       |  9 ++++---
 src/platform/src/linux/mod.rs | 15 +++++++++++
 src/platform/src/redox/mod.rs | 50 ++++++++++++++++++++++++++++++++---
 src/sys_mman/cbindgen.toml    |  1 +
 src/sys_mman/src/lib.rs       | 12 ++++-----
 src/sys_mman/src/linux.rs     |  2 ++
 src/sys_mman/src/redox.rs     | 10 +++++++
 13 files changed, 103 insertions(+), 13 deletions(-)
 create mode 100644 include/bits/sys/mman.h

diff --git a/Cargo.lock b/Cargo.lock
index ca2660b0..5750edb8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -247,6 +247,7 @@ dependencies = [
  "ralloc 1.0.0",
  "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "spin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
diff --git a/include/bits/sys/mman.h b/include/bits/sys/mman.h
new file mode 100644
index 00000000..e2ece78c
--- /dev/null
+++ b/include/bits/sys/mman.h
@@ -0,0 +1,6 @@
+#ifndef _BITS_SYS_MMAN_H
+#define _BITS_SYS_MMAN_H
+
+#define MAP_FAILED ((void *) -1)
+
+#endif
diff --git a/include/limits.h b/include/limits.h
index a8a750bb..1b2de46f 100644
--- a/include/limits.h
+++ b/include/limits.h
@@ -1,7 +1,11 @@
 #define MB_LEN_MAX 4 // unicode
 
 #define CHAR_BIT __CHAR_BIT__
-#define CHAR_MAX __CHAR_MAX__
+#ifdef __CHAR_MAX__
+# define CHAR_MAX __CHAR_MAX__
+#else
+# define CHAR_MAX 0xFF
+#endif
 #define CHAR_MIN 0
 #define INT_MAX __INT_MAX__
 #define INT_MIN (-INT_MAX - 1)
diff --git a/include/stddef.h b/include/stddef.h
index 1dc7f60f..0ee2d471 100644
--- a/include/stddef.h
+++ b/include/stddef.h
@@ -10,4 +10,6 @@ typedef int32_t wchar_t;
 
 typedef unsigned long long size_t;
 
+#define offsetof(type, member) __builtin_offsetof(type, member)
+
 #endif /* _STDDEF_H */
diff --git a/src/fcntl/src/linux.rs b/src/fcntl/src/linux.rs
index 98a5f8a2..05948a6d 100644
--- a/src/fcntl/src/linux.rs
+++ b/src/fcntl/src/linux.rs
@@ -10,3 +10,4 @@ pub const O_APPEND: c_int = 0o2000;
 pub const O_CLOEXEC: c_int = 0o2_000_000;
 pub const O_DIRECTORY: c_int = 0o200_000;
 pub const O_EXCL: c_int = 0o200;
+pub const O_NONBLOCK: c_int = 0o4000;
diff --git a/src/platform/Cargo.toml b/src/platform/Cargo.toml
index 3a1ecfbf..6c179a9f 100644
--- a/src/platform/Cargo.toml
+++ b/src/platform/Cargo.toml
@@ -13,3 +13,4 @@ sc = "0.2"
 
 [target.'cfg(target_os = "redox")'.dependencies]
 redox_syscall = "0.1"
+spin = "0.4"
diff --git a/src/platform/src/lib.rs b/src/platform/src/lib.rs
index 37964737..2a634a4e 100644
--- a/src/platform/src/lib.rs
+++ b/src/platform/src/lib.rs
@@ -6,13 +6,16 @@
 #[cfg_attr(target_os = "redox", macro_use)]
 extern crate alloc;
 
-#[cfg(all(not(feature = "no_std"), target_os = "linux"))]
+#[cfg(target_os = "linux")]
 #[macro_use]
 extern crate sc;
 
-#[cfg(all(not(feature = "no_std"), target_os = "redox"))]
+#[cfg(target_os = "redox")]
 extern crate syscall;
 
+#[cfg(target_os = "redox")]
+extern crate spin;
+
 pub use allocator::*;
 
 #[cfg(not(feature = "ralloc"))]
@@ -38,7 +41,7 @@ pub mod types;
 
 pub use rawfile::RawFile;
 
-use alloc::Vec;
+use alloc::vec::Vec;
 use core::{fmt, ptr};
 
 use types::*;
diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs
index be108e8d..5446a52f 100644
--- a/src/platform/src/linux/mod.rs
+++ b/src/platform/src/linux/mod.rs
@@ -284,6 +284,21 @@ pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int {
     e(unsafe { syscall!(MKNODAT, AT_FDCWD, path, mode, 0) }) as c_int
 }
 
+pub unsafe fn mmap(
+    addr: *mut c_void,
+    len: usize,
+    prot: c_int,
+    flags: c_int,
+    fildes: c_int,
+    off: off_t,
+) -> *mut c_void {
+    e(syscall!(MMAP, addr, len, prot, flags, fildes, off)) as *mut c_void
+}
+
+pub unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int {
+    e(syscall!(MUNMAP, addr, len)) as c_int
+}
+
 pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
     e(unsafe { syscall!(NANOSLEEP, rqtp, rmtp) }) as c_int
 }
diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs
index 789e7748..6d9afdb3 100644
--- a/src/platform/src/redox/mod.rs
+++ b/src/platform/src/redox/mod.rs
@@ -1,9 +1,9 @@
 //! sys/socket implementation, following http://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/socket.h.html
 
+use alloc::btree_map::BTreeMap;
 use core::fmt::Write;
-use core::mem;
-use core::ptr;
-use core::slice;
+use core::{mem, ptr, slice};
+use spin::{Once, Mutex, MutexGuard};
 use syscall::data::Stat as redox_stat;
 use syscall::data::TimeSpec as redox_timespec;
 use syscall::flag::*;
@@ -13,10 +13,17 @@ use types::*;
 use *;
 
 const EINVAL: c_int = 22;
+const MAP_ANON: c_int = 1;
 
 #[thread_local]
 static mut SIG_HANDLER: Option<extern "C" fn(c_int)> = None;
 
+static ANONYMOUS_MAPS: Once<Mutex<BTreeMap<usize, usize>>> = Once::new();
+
+fn anonymous_maps() -> MutexGuard<'static, BTreeMap<usize, usize>> {
+    ANONYMOUS_MAPS.call_once(|| Mutex::new(BTreeMap::new())).lock()
+}
+
 extern "C" fn sig_handler(sig: usize) {
     if let Some(ref callback) = unsafe { SIG_HANDLER } {
         callback(sig as c_int);
@@ -640,6 +647,43 @@ pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int {
     }
 }
 
+pub unsafe fn mmap(
+    _addr: *mut c_void,
+    len: usize,
+    _prot: c_int,
+    flags: c_int,
+    fildes: c_int,
+    off: off_t,
+) -> *mut c_void {
+    if flags & MAP_ANON == MAP_ANON {
+        let fd = e(syscall::open("memory:", 0)); // flags don't matter currently
+        if fd == !0 {
+            return !0 as *mut c_void;
+        }
+
+        let addr = e(syscall::fmap(fd, off as usize, len as usize));
+        if addr == !0 {
+            let _ = syscall::close(fd);
+            return !0 as *mut c_void;
+        }
+
+        anonymous_maps().insert(addr as usize, fd);
+        addr as *mut c_void
+    } else {
+        e(syscall::fmap(fildes as usize, off as usize, len as usize)) as *mut c_void
+    }
+}
+
+pub unsafe fn munmap(addr: *mut c_void, _len: usize) -> c_int {
+    if e(syscall::funmap(addr as usize)) == !0 {
+        return !0;
+    }
+    if let Some(fd) = anonymous_maps().remove(&(addr as usize)) {
+        let _ = syscall::close(fd);
+    }
+    0
+}
+
 pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
     let redox_rqtp = unsafe { redox_timespec::from(&*rqtp) };
     let mut redox_rmtp: redox_timespec;
diff --git a/src/sys_mman/cbindgen.toml b/src/sys_mman/cbindgen.toml
index baaa5325..1fecef57 100644
--- a/src/sys_mman/cbindgen.toml
+++ b/src/sys_mman/cbindgen.toml
@@ -1,5 +1,6 @@
 sys_includes = ["stdint.h", "sys/types.h"]
 include_guard = "_SYS_MMAN_H"
+trailer = "#include <bits/sys/mman.h>"
 language = "C"
 style = "Tag"
 
diff --git a/src/sys_mman/src/lib.rs b/src/sys_mman/src/lib.rs
index 4c47b135..c2151e40 100644
--- a/src/sys_mman/src/lib.rs
+++ b/src/sys_mman/src/lib.rs
@@ -24,8 +24,8 @@ pub extern "C" fn mlockall(flags: c_int) -> c_int {
     unimplemented!();
 }
 
-// #[no_mangle]
-pub extern "C" fn mmap(
+#[no_mangle]
+pub unsafe extern "C" fn mmap(
     addr: *mut c_void,
     len: usize,
     prot: c_int,
@@ -33,7 +33,7 @@ pub extern "C" fn mmap(
     fildes: c_int,
     off: off_t,
 ) -> *mut c_void {
-    unimplemented!();
+    platform::mmap(addr, len, prot, flags, fildes, off)
 }
 
 // #[no_mangle]
@@ -56,9 +56,9 @@ pub extern "C" fn munlockall() -> c_int {
     unimplemented!();
 }
 
-// #[no_mangle]
-pub extern "C" fn munmap(addr: *mut c_void, len: usize) -> c_int {
-    unimplemented!();
+#[no_mangle]
+pub unsafe extern "C" fn munmap(addr: *mut c_void, len: usize) -> c_int {
+    platform::munmap(addr, len)
 }
 
 // #[no_mangle]
diff --git a/src/sys_mman/src/linux.rs b/src/sys_mman/src/linux.rs
index 1e002271..0a6933af 100644
--- a/src/sys_mman/src/linux.rs
+++ b/src/sys_mman/src/linux.rs
@@ -7,3 +7,5 @@ pub const PROT_NONE: c_int = 0x0;
 
 pub const MAP_SHARED: c_int = 0x1;
 pub const MAP_PRIVATE: c_int = 0x2;
+pub const MAP_ANON: c_int = 0x20;
+pub const MAP_ANONYMOUS: c_int = MAP_ANON;
diff --git a/src/sys_mman/src/redox.rs b/src/sys_mman/src/redox.rs
index 8b137891..1822e152 100644
--- a/src/sys_mman/src/redox.rs
+++ b/src/sys_mman/src/redox.rs
@@ -1 +1,11 @@
+use platform::types::*;
 
+pub const PROT_READ: c_int = 0;
+pub const PROT_WRITE: c_int = 0;
+pub const PROT_EXEC: c_int = 0;
+pub const PROT_NONE: c_int = 0;
+
+pub const MAP_SHARED: c_int = 0;
+pub const MAP_PRIVATE: c_int = 0;
+pub const MAP_ANON: c_int = 1;
+pub const MAP_ANONYMOUS: c_int = MAP_ANON;
-- 
GitLab