diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 15ace45669c8c0a1a9e5f167b07d694dd0a675a0..1ed5bda1cf2ec4119ef95c0c90ed3cc5cecea2a0 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -10,9 +10,9 @@ use crate::{ fs::File, header::{ dirent::dirent, - errno::{EINVAL, EIO, EPERM, ERANGE}, + errno::{EINVAL, EIO, ENOMEM, EPERM, ERANGE}, fcntl, - sys_mman::MAP_ANON, + sys_mman::{PROT_READ, PROT_WRITE, MAP_ANONYMOUS}, sys_random, sys_resource::{rlimit, RLIM_INFINITY}, sys_stat::stat, @@ -28,6 +28,9 @@ use crate::{ use super::{errno, types::*, Pal, Read}; +static mut BRK_CUR: *mut c_void = ptr::null_mut(); +static mut BRK_END: *mut c_void = ptr::null_mut(); + mod epoll; mod extra; mod ptrace; @@ -95,7 +98,41 @@ impl Pal for Sys { } fn brk(addr: *mut c_void) -> *mut c_void { - unsafe { syscall::brk(addr as usize).unwrap_or(0) as *mut c_void } + unsafe { + // On first invocation, allocate a buffer for brk + if BRK_CUR.is_null() { + // 4 megabytes of RAM ought to be enough for anybody + const BRK_MAX_SIZE: usize = 4 * 1024 * 1024; + + let allocated = Self::mmap( + ptr::null_mut(), + BRK_MAX_SIZE, + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS, + 0, + 0, + ); + if allocated == !0 as *mut c_void /* MAP_FAILED */ { + return !0 as *mut c_void; + } + + BRK_CUR = allocated; + BRK_END = (allocated as *mut u8).add(BRK_MAX_SIZE) as *mut c_void; + } + + if addr.is_null() { + // Lookup what previous brk() invocations have set the address to + BRK_CUR + } else if BRK_CUR <= addr && addr < BRK_END { + // It's inside buffer, return + BRK_CUR = addr; + addr + } else { + // It was outside of valid range + errno = ENOMEM; + ptr::null_mut() + } + } } fn chdir(path: &CStr) -> c_int { @@ -674,7 +711,7 @@ impl Pal for Sys { address: addr as usize, }; - if flags & MAP_ANON == MAP_ANON { + if flags & MAP_ANONYMOUS == MAP_ANONYMOUS { let fd = e(syscall::open( "memory:", syscall::O_STAT | syscall::O_CLOEXEC,