Bladeren bron

Map stacks based on provided size.

Jeremy Soller 6 jaren geleden
bovenliggende
commit
42d40da973
7 gewijzigde bestanden met toevoegingen van 138 en 32 verwijderingen
  1. 6 6
      Cargo.lock
  2. 1 1
      Cargo.toml
  3. 1 0
      src/lib.rs
  4. 40 11
      src/platform/linux/mod.rs
  5. 1 1
      src/platform/pal/mod.rs
  6. 49 4
      src/platform/pte.rs
  7. 40 9
      src/platform/redox/mod.rs

+ 6 - 6
Cargo.lock

@@ -173,7 +173,7 @@ dependencies = [
 name = "ralloc_shim"
 version = "0.1.1"
 dependencies = [
- "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)",
  "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -220,7 +220,7 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.1.51"
+version = "0.1.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -228,7 +228,7 @@ name = "redox_termios"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -243,7 +243,7 @@ dependencies = [
  "posix-regex 0.1.0",
  "ralloc 1.0.0",
  "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.52 (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.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "va_list 0.1.0",
@@ -378,7 +378,7 @@ version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -480,7 +480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372"
 "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db"
 "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
-"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
+"checksum redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)" = "d32b3053e5ced86e4bc0411fec997389532bf56b000e66cb4884eeeb41413d69"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
 "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
 "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"

+ 1 - 1
Cargo.toml

@@ -37,7 +37,7 @@ optional = true
 sc = "0.2.2"
 
 [target.'cfg(target_os = "redox")'.dependencies]
-redox_syscall = "0.1"
+redox_syscall = "0.1.52"
 spin = "0.4.10"
 
 [features]

+ 1 - 0
src/lib.rs

@@ -4,6 +4,7 @@
 #![allow(unused_variables)]
 #![feature(alloc)]
 #![feature(allocator_api)]
+#![feature(asm)]
 #![feature(const_fn)]
 #![feature(const_raw_ptr_deref)]
 #![feature(const_str_as_bytes)]

+ 40 - 11
src/platform/linux/mod.rs

@@ -23,6 +23,7 @@ const AT_FDCWD: c_int = -100;
 const AT_EMPTY_PATH: c_int = 0x1000;
 const AT_REMOVEDIR: c_int = 0x200;
 
+const SYS_CLONE: usize = 56;
 const CLONE_VM: usize = 0x0100;
 const CLONE_FS: usize = 0x0200;
 const CLONE_FILES: usize = 0x0400;
@@ -326,17 +327,45 @@ impl Pal for Sys {
         e(unsafe { syscall!(POLL, fds, nfds, timeout) }) as c_int
     }
 
-    fn pte_clone() -> pid_t {
-        e(unsafe {
-            syscall!(
-                CLONE,
-                CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
-                0,
-                0,
-                0,
-                0
-            )
-        }) as pid_t
+    #[cfg(target_arch = "x86_64")]
+    unsafe fn pte_clone(stack: *mut usize) -> pid_t {
+        let flags =
+            CLONE_VM |
+            CLONE_FS |
+            CLONE_FILES |
+            CLONE_SIGHAND;
+        let pid;
+        asm!("
+            # Call clone syscall
+            syscall
+
+            # Check if child or parent
+            test rax, rax
+            jnz .parent
+
+            # Call entry point
+            pop rdi
+            pop rax
+            call rax
+
+            # Exit
+            mov rax, 60
+            xor rdi, rdi
+            syscall
+
+            # Invalid instruction on failure to exit
+            ud2
+
+            # Return PID if parent
+            .parent:
+            "
+            : "={rax}"(pid)
+            : "{rax}"(SYS_CLONE), "{rdi}"(flags), "{rsi}"(stack), "{rdx}"(0), "{rcx}"(0), "{r8}"(0)
+            : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8",
+              "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+            : "intel", "volatile"
+        );
+        e(pid) as pid_t
     }
 
     fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t {

+ 1 - 1
src/platform/pal/mod.rs

@@ -117,7 +117,7 @@ pub trait Pal {
 
     fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int;
 
-    fn pte_clone() -> pid_t;
+    unsafe fn pte_clone(stack: *mut usize) -> pid_t;
 
     fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t;
 

+ 49 - 4
src/platform/pte.rs

@@ -5,9 +5,10 @@ use alloc::collections::BTreeMap;
 use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
 use core::{intrinsics, ptr};
 
+use header::sys_mman;
 use header::time::timespec;
 use mutex::{FUTEX_WAIT, FUTEX_WAKE};
-use platform::types::{c_int, c_uint, c_void, pid_t};
+use platform::types::{c_int, c_uint, c_void, pid_t, size_t};
 use platform::{Pal, Sys};
 
 pub struct Semaphore {
@@ -36,6 +37,9 @@ use self::pte_osResult::*;
 static mut pid_mutexes: Option<BTreeMap<pte_osThreadHandle, pte_osMutexHandle>> = None;
 static mut pid_mutexes_lock: i32 = 0;
 
+static mut pid_stacks: Option<BTreeMap<pte_osThreadHandle, (*mut c_void, size_t)>> = None;
+static mut pid_stacks_lock: i32 = 0;
+
 #[thread_local]
 static mut LOCALS: *mut BTreeMap<c_uint, *mut c_void> = ptr::null_mut();
 
@@ -57,17 +61,41 @@ pub unsafe extern "C" fn pte_osInit() -> pte_osResult {
 #[no_mangle]
 pub unsafe extern "C" fn pte_osThreadCreate(
     entryPoint: pte_osThreadEntryPoint,
-    _stackSize: c_int,
+    stackSize: c_int,
     _initialPriority: c_int,
     argv: *mut c_void,
     ppte_osThreadHandle: *mut pte_osThreadHandle,
 ) -> pte_osResult {
-    // XXX error handling
+    let stack_size = if stackSize == 0 {
+        1024 * 1024
+    } else {
+        stackSize as usize
+    };
+    let stack_base = sys_mman::mmap(
+        ptr::null_mut(),
+        stack_size,
+        sys_mman::PROT_READ | sys_mman::PROT_WRITE,
+        sys_mman::MAP_SHARED | sys_mman::MAP_ANONYMOUS,
+        -1,
+        0
+    );
+    if stack_base as isize == -1 {
+        return PTE_OS_GENERAL_FAILURE;
+    }
+    let stack_end = stack_base.add(stack_size);
+    let mut stack = stack_end as *mut usize;
+    {
+        stack = stack.offset(-1);
+        *stack = entryPoint as usize;
+
+        stack = stack.offset(-1);
+        *stack = argv as usize;
+    }
 
     // Create a locked mutex, unlocked by pte_osThreadStart
     let mutex = Box::into_raw(Box::new(2));
     {
-        let id = Sys::pte_clone();
+        let id = Sys::pte_clone(stack);
         if id < 0 {
             return PTE_OS_GENERAL_FAILURE;
         }
@@ -84,6 +112,14 @@ pub unsafe extern "C" fn pte_osThreadCreate(
             }
             pid_mutexes.as_mut().unwrap().insert(id, mutex);
             pte_osMutexUnlock(&mut pid_mutexes_lock);
+
+            pte_osMutexLock(&mut pid_stacks_lock);
+            if pid_stacks.is_none() {
+                pid_stacks = Some(BTreeMap::new());
+            }
+            pid_stacks.as_mut().unwrap().insert(id, (stack_base, stack_size));
+            pte_osMutexUnlock(&mut pid_stacks_lock);
+
             *ppte_osThreadHandle = id;
         }
     }
@@ -129,6 +165,15 @@ pub unsafe extern "C" fn pte_osThreadDelete(handle: pte_osThreadHandle) -> pte_o
         }
     }
     pte_osMutexUnlock(&mut pid_mutexes_lock);
+
+    pte_osMutexLock(&mut pid_stacks_lock);
+    if let Some(ref mut stacks) = pid_stacks {
+        if let Some((stack_base, stack_size)) = stacks.remove(&handle) {
+            sys_mman::munmap(stack_base, stack_size);
+        }
+    }
+    pte_osMutexUnlock(&mut pid_stacks_lock);
+
     PTE_OS_OK
 }
 

+ 40 - 9
src/platform/redox/mod.rs

@@ -815,15 +815,46 @@ impl Pal for Sys {
         total
     }
 
-    fn pte_clone() -> pid_t {
-        e(unsafe {
-            syscall::clone(
-                syscall::CLONE_VM
-                    | syscall::CLONE_FS
-                    | syscall::CLONE_FILES
-                    | syscall::CLONE_SIGHAND,
-            )
-        }) as pid_t
+    #[cfg(target_arch = "x86_64")]
+    unsafe fn pte_clone(stack: *mut usize) -> pid_t {
+        let flags =
+            syscall::CLONE_VM |
+            syscall::CLONE_FS |
+            syscall::CLONE_FILES |
+            syscall::CLONE_SIGHAND |
+            syscall::CLONE_STACK;
+        let pid;
+        asm!("
+            # Call clone syscall
+            syscall
+
+            # Check if child or parent
+            test rax, rax
+            jnz .parent
+
+            # Call entry point
+            pop rdi
+            pop rax
+            call rax
+
+            # Exit
+            mov rax, 1
+            xor rdi, rdi
+            syscall
+
+            # Invalid instruction on failure to exit
+            ud2
+
+            # Return PID if parent
+            .parent:
+            "
+            : "={rax}"(pid)
+            : "{rax}"(syscall::SYS_CLONE), "{rdi}"(flags), "{rsi}"(stack)
+            : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8",
+              "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+            : "intel", "volatile"
+        );
+        e(syscall::Error::demux(pid)) as pid_t
     }
 
     fn read(fd: c_int, buf: &mut [u8]) -> ssize_t {