summaryrefslogtreecommitdiff
path: root/src/sys/mman.rs
diff options
context:
space:
mode:
authorPhil Vachon <pvachon@12sidedtech.com>2014-10-24 17:18:44 -0400
committerPhil Vachon <pvachon@12sidedtech.com>2014-10-27 20:11:43 -0400
commitbcf2f5e137740b5491070f15c0ea3470ce85025e (patch)
tree6ef6144bcd98c2a94c3995f804ac989c6eeb7cbb /src/sys/mman.rs
parent5510805c82f6ec1e25966eb639624529d1ae9bc7 (diff)
downloadnix-bcf2f5e137740b5491070f15c0ea3470ce85025e.zip
Add mmap, shm_open and other mman relatives
Add various wrappers to make interacting with Rust a bit more pleasant for memory management. Additionally, provide ftruncate(2), which is useful when working with shared memory. Allow managing CPU affinity of a Rust Task living in a system thread.
Diffstat (limited to 'src/sys/mman.rs')
-rw-r--r--src/sys/mman.rs134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/sys/mman.rs b/src/sys/mman.rs
new file mode 100644
index 00000000..2c23a13d
--- /dev/null
+++ b/src/sys/mman.rs
@@ -0,0 +1,134 @@
+use errno::{SysResult, SysError};
+use std::io::FilePermission;
+use fcntl::{Fd, OFlag};
+use libc::{c_void, size_t, off_t, mode_t};
+
+pub use self::consts::*;
+
+#[cfg(target_os = "linux")]
+mod consts {
+ use libc::c_int;
+
+ pub type MmapFlag = c_int;
+
+ pub const MAP_SHARED: MmapFlag = 0x00001;
+ pub const MAP_PRIVATE: MmapFlag = 0x00002;
+ pub const MAP_FIXED: MmapFlag = 0x00010;
+
+ pub const MAP_FILE: MmapFlag = 0x00000;
+ pub const MAP_ANONYMOUS: MmapFlag = 0x00020;
+ pub const MAP_ANON: MmapFlag = MAP_ANONYMOUS;
+ pub const MAP_32BIT: MmapFlag = 0x00040;
+
+ pub const MAP_GROWSDOWN: MmapFlag = 0x00100;
+ pub const MAP_DENYWRITE: MmapFlag = 0x00800;
+ pub const MAP_EXECUTABLE: MmapFlag = 0x01000;
+ pub const MAP_LOCKED: MmapFlag = 0x02000;
+ pub const MAP_NORESERVE: MmapFlag = 0x04000;
+ pub const MAP_POPULATE: MmapFlag = 0x08000;
+ pub const MAP_NONBLOCK: MmapFlag = 0x10000;
+ pub const MAP_STACK: MmapFlag = 0x20000;
+ pub const MAP_HUGETLB: MmapFlag = 0x40000;
+
+ pub type MmapProt = c_int;
+
+ pub const PROT_READ: MmapProt = 0x1;
+ pub const PROT_WRITE: MmapProt = 0x2;
+ pub const PROT_EXEC: MmapProt = 0x4;
+ pub const PROT_NONE: MmapProt = 0x0;
+ pub const PROT_GROWSDOWN: MmapProt = 0x01000000;
+ pub const PROT_GROWSUP: MmapProt = 0x02000000;
+
+ pub const MAP_FAILED: int = -1;
+}
+
+#[cfg(target_os = "macos")]
+mod consts {
+ use libc::c_int;
+
+ pub type MmapFlag = c_int;
+
+ pub const MAP_SHARED: MmapFlag = 0x00001;
+ pub const MAP_PRIVATE: MmapFlag = 0x00002;
+ pub const MAP_FIXED: MmapFlag = 0x00010;
+
+ pub const MAP_NOCACHE: MmapFlag = 0x00400;
+ pub const MAP_JIT: MmapFlag = 0x00800;
+
+ pub type MmapProt = c_int;
+
+ pub const PROT_READ: MmapProt = 0x1;
+ pub const PROT_WRITE: MmapProt = 0x2;
+ pub const PROT_EXEC: MmapProt = 0x4;
+ pub const PROT_NONE: MmapProt = 0x0;
+
+ pub const MAP_FAILED: int = -1;
+}
+
+mod ffi {
+ use libc::{c_void, size_t, c_int, c_char, mode_t};
+
+ pub use libc::{mmap, munmap};
+
+
+ extern {
+ pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int;
+ pub fn shm_unlink(name: *const c_char) -> c_int;
+ pub fn mlock(addr: *const c_void, len: size_t) -> c_int;
+ pub fn munlock(addr: *const c_void, len: size_t) -> c_int;
+ }
+}
+
+pub unsafe fn mlock(addr: *const c_void, length: size_t) -> SysResult<()> {
+ match ffi::mlock(addr, length) {
+ 0 => Ok(()),
+ _ => Err(SysError::last())
+ }
+}
+
+pub fn munlock(addr: *const c_void, length: size_t) -> SysResult<()> {
+ match unsafe { ffi::munlock(addr, length) } {
+ 0 => Ok(()),
+ _ => Err(SysError::last())
+ }
+}
+
+/// Calls to mmap are inherently unsafe, so they must be made in an unsafe block. Typically
+/// a higher-level abstraction will hide the unsafe interactions with the mmap'd region.
+pub fn mmap(addr: *mut c_void, length: size_t, prot: MmapProt, flags: MmapFlag, fd: Fd, offset: off_t) -> SysResult<*mut c_void> {
+ let ret = unsafe { ffi::mmap(addr, length, prot, flags, fd, offset) };
+
+ if ret as int == MAP_FAILED {
+ Err(SysError::last())
+ } else {
+ Ok(ret)
+ }
+}
+
+pub fn munmap(addr: *mut c_void, len: size_t) -> SysResult<()> {
+ match unsafe { ffi::munmap(addr, len) } {
+ 0 => Ok(()),
+ _ => Err(SysError::last())
+ }
+}
+
+pub fn shm_open(name: &String, flag: OFlag, mode: FilePermission) -> SysResult<Fd> {
+ let ret = unsafe { ffi::shm_open(name.to_c_str().as_ptr(), flag.bits(), mode.bits() as mode_t) };
+
+ if ret < 0 {
+ Err(SysError::last())
+ } else {
+ Ok(ret)
+ }
+}
+
+pub fn shm_unlink(name: &String) -> SysResult<()> {
+ let ret = unsafe { ffi::shm_unlink(name.to_c_str().as_ptr()) };
+
+ if ret < 0 {
+ Err(SysError::last())
+ } else {
+ Ok(())
+ }
+}
+