diff --git a/rust/ares/Cargo.toml b/rust/ares/Cargo.toml index 50e6d39..319e8ea 100644 --- a/rust/ares/Cargo.toml +++ b/rust/ares/Cargo.toml @@ -27,10 +27,6 @@ assert_no_alloc = "1.1.2" [build-dependencies] cc = "1.0.79" -[[bin]] -name = "cue_pill" -path = "benches/cue_pill.rs" - [[bin]] name = "ares" path = "src/main.rs" diff --git a/rust/ares/build.rs b/rust/ares/build.rs index 805bab6..566a921 100644 --- a/rust/ares/build.rs +++ b/rust/ares/build.rs @@ -4,5 +4,6 @@ fn main() { cc::Build::new() .file("../pma_malloc/src/malloc.c") .file("../pma_malloc/src/includes/checksum.c") + .opt_level(3) .compile("pma_malloc"); } diff --git a/rust/ares/src/lib.rs b/rust/ares/src/lib.rs index 4c52e0b..d83ba1d 100644 --- a/rust/ares/src/lib.rs +++ b/rust/ares/src/lib.rs @@ -8,6 +8,7 @@ pub mod mem; pub mod mug; pub mod newt; pub mod noun; +pub mod pma; pub mod serf; //pub mod bytecode; pub mod hamt; diff --git a/rust/ares/src/main.rs b/rust/ares/src/main.rs index 19933b5..bace6be 100644 --- a/rust/ares/src/main.rs +++ b/rust/ares/src/main.rs @@ -3,11 +3,9 @@ use ares::mem::NockStack; use ares::noun::IndirectAtom; use ares::serf::serf; use ares::serialization::{cue, jam}; -use libc::{c_char, c_int, c_void, size_t}; use memmap::Mmap; use memmap::MmapMut; use std::env; -use std::ffi::CString; use std::fs::File; use std::fs::OpenOptions; use std::io; @@ -15,59 +13,6 @@ use std::mem; use std::ptr::copy_nonoverlapping; use std::ptr::write_bytes; -#[link(name = "pma_malloc", kind = "static")] -extern { - fn pma_init(path: *const c_char) -> c_int; - fn pma_load(path: *const c_char) -> c_int; - fn pma_close(epoch: u64, event: u64) -> c_int; - fn pma_malloc(size: size_t) -> *mut c_void; - fn pma_free(ptr: *mut c_void) -> c_int; - fn pma_sync(epoch: u64, event: u64) -> c_int; -} - -fn pma() -> io::Result<()> { - unsafe { - std::fs::remove_dir_all("/tmp/pma"); - eprintln!("\rpma_init"); - pma_init(CString::new("/tmp/pma").expect("init").as_ptr()); - eprintln!("\rpma_malloc 8"); - let eight = pma_malloc(8) as *mut u64; - *eight = 0xdeadbeef; - eprintln!("\rpma_close"); - assert!(0 == pma_close(10, 12)); - eprintln!("\rpma_load"); - pma_load(CString::new("/tmp/pma").expect("init").as_ptr()); - eprintln!("\rpma_sync 1 {}", pma_sync(13, 15)); - eprintln!("\rpma_malloc 20"); - let twenty = pma_malloc(8) as *mut u64; - eprintln!("\rpma_sync 2 {}", pma_sync(14, 16)); - eprintln!("\rpma_malloc 20"); - let twenty = pma_malloc(8) as *mut u64; - eprintln!("\rpma_sync 3 {}", pma_sync(15, 16)); - eprintln!("\rpma_malloc 20"); - let twenty = pma_malloc(8) as *mut u64; - eprintln!("\rpma_free 20"); - pma_free(twenty as *mut c_void); - eprintln!("\rpma_sync 4 {}", pma_sync(16, 15)); - eprintln!("\rpma_malloc 20"); - let twenty = pma_malloc(8) as *mut u64; - eprintln!("\rpma_sync 5 {}", pma_sync(17, 15)); - eprintln!("\rpma_malloc 20"); - let twenty = pma_malloc(8) as *mut u64; - eprintln!("\rpma_sync 6 {}", pma_sync(18, 15)); - eprintln!("\rpma_malloc 20"); - let twenty = pma_malloc(8) as *mut u64; - eprintln!("\rpma_malloc 20"); - let twenty = pma_malloc(8) as *mut u64; - *twenty = 0xcafebabe; - eprintln!("\rpma_free 20"); - pma_free(twenty as *mut c_void); - eprintln!("\rpma_close 20"); - pma_close(123, 124); - } - Ok(()) -} - fn main() -> io::Result<()> { let filename = env::args().nth(1).expect("Must provide input filename"); @@ -85,11 +30,7 @@ fn main() -> io::Result<()> { } if filename == "serf" { - return serf() - } - - if filename == "pma" { - return pma() + return serf(); } let output_filename = format!("{}.out", filename.clone()); diff --git a/rust/ares/src/pma.rs b/rust/ares/src/pma.rs new file mode 100644 index 0000000..7c0bbcc --- /dev/null +++ b/rust/ares/src/pma.rs @@ -0,0 +1,89 @@ +use libc::{c_char, c_int, c_void, size_t}; +use std::ffi::CString; +use std::path::Path; + +mod raw { + use super::*; + + #[link(name = "pma_malloc", kind = "static")] + extern "C" { + pub(super) fn pma_init(path: *const c_char) -> c_int; + pub(super) fn pma_load(path: *const c_char) -> c_int; + pub(super) fn pma_close(epoch: u64, event: u64) -> c_int; + pub(super) fn pma_malloc(size: size_t) -> *mut c_void; + pub(super) fn pma_free(ptr: *mut c_void) -> c_int; + pub(super) fn pma_sync(epoch: u64, event: u64) -> c_int; + } +} + +pub unsafe fn pma_init>(path: P) -> i32 { + let path = CString::new(path.as_ref().to_str().unwrap()).unwrap(); + raw::pma_init(path.as_ptr()) as i32 +} + +pub unsafe fn pma_load>(path: P) -> i32 { + let path = CString::new(path.as_ref().to_str().unwrap()).unwrap(); + raw::pma_load(path.as_ptr()) as i32 +} + +pub unsafe fn pma_close(epoch: u64, event: u64) -> i32 { + raw::pma_close(epoch, event) as i32 +} + +pub unsafe fn pma_malloc(size: usize) -> *mut c_void { + raw::pma_malloc(size as size_t) +} + +pub unsafe fn pma_free(ptr: *mut c_void) -> i32 { + raw::pma_free(ptr) as i32 +} + +pub unsafe fn pma_sync(epoch: u64, event: u64) -> i32 { + raw::pma_sync(epoch, event) as i32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_pma() { + let path = "/tmp/ares_pma_test"; + if let Err(err) = std::fs::remove_dir_all(path) { + if err.kind() != std::io::ErrorKind::NotFound { + panic!("failed to remove dir: {}", err); + } + } + + unsafe { + pma_init(path); + let eight = pma_malloc(8) as *mut u64; + *eight = 0xdeadbeef; + assert!(0 == pma_close(10, 12)); + pma_load(path); + assert_eq!(0, pma_sync(13, 15)); + let _ = pma_malloc(8) as *mut u64; + assert_eq!(0, pma_sync(14, 16)); + let _ = pma_malloc(8) as *mut u64; + assert_eq!(0, pma_sync(15, 16)); + let twenty = pma_malloc(8) as *mut u64; + pma_free(twenty as *mut c_void); + assert_eq!(0, pma_sync(16, 15)); + let _ = pma_malloc(8) as *mut u64; + assert_eq!(0, pma_sync(17, 15)); + let _ = pma_malloc(8) as *mut u64; + assert_eq!(0, pma_sync(18, 15)); + let _ = pma_malloc(8) as *mut u64; + let twenty = pma_malloc(8) as *mut u64; + *twenty = 0xcafebabe; + pma_free(twenty as *mut c_void); + pma_close(123, 124); + } + + if let Err(err) = std::fs::remove_dir_all(path) { + if err.kind() != std::io::ErrorKind::NotFound { + panic!("failed to remove dir: {}", err); + } + } + } +} diff --git a/rust/pma_malloc/src/malloc.c b/rust/pma_malloc/src/malloc.c index e785836..4b5a88b 100644 --- a/rust/pma_malloc/src/malloc.c +++ b/rust/pma_malloc/src/malloc.c @@ -428,8 +428,8 @@ int pma_init(const char *path) { DIR *dir; char *filepath; - void *meta_pages; - void *page_dir; + void *meta_pages = NULL;; + void *page_dir = NULL; uint64_t meta_bytes; int err; int err_line; @@ -691,8 +691,8 @@ init_error: err = errno; fprintf(stderr, "(L%d) Initialization error: %s\n", err_line, strerror(errno)); - munmap(meta_pages, meta_bytes); - munmap(page_dir, PMA_INIT_DIR_SIZE); + if (meta_pages) munmap(meta_pages, meta_bytes); + if (page_dir) munmap(page_dir, PMA_INIT_DIR_SIZE); if (snapshot_fd) close(snapshot_fd); if (page_dir_fd) close(page_dir_fd); free((void*)filepath); @@ -706,7 +706,7 @@ pma_load(const char *path) { Metadata *older_page; char *filepath; void *address; - void *meta_pages; + void *meta_pages = NULL; uint64_t index; uint64_t meta_bytes; int err; @@ -853,7 +853,7 @@ pma_load(const char *path) { _pma_state->free_pages = free_page; } else { - PageRunCache *page_run = (PageRunCache *)malloc(sizeof(SinglePageCache)); + PageRunCache *page_run = (PageRunCache *)malloc(sizeof(PageRunCache)); page_run->next = _pma_state->free_page_runs; page_run->page = INDEX_TO_PTR(index - count); @@ -939,7 +939,7 @@ load_error: err = errno; fprintf(stderr, "(L%d) Error loading from %s: %s\n", err_line, path, strerror(errno)); - munmap(meta_pages, meta_bytes); + if (meta_pages) munmap(meta_pages, meta_bytes); munmap(_pma_state->page_directory.entries, PMA_MAXIMUM_DIR_SIZE); munmap(_pma_state->metadata.arena_start, ((uint64_t)_pma_state->metadata.arena_end - (uint64_t)_pma_state->metadata.arena_start)); if (snapshot_fd) close(snapshot_fd); @@ -997,8 +997,6 @@ pma_malloc(size_t size) { void pma_free(void *address) { - uint64_t index; - // TODO: This is legal for POSIX free, but would this ever happen for pma_free? if (address == NULL) return; @@ -1016,8 +1014,6 @@ pma_free(void *address) { return; } - index = PTR_TO_INDEX(address); - _pma_free_bytes(address); } @@ -1210,7 +1206,7 @@ _pma_update_free_pages(uint8_t num_dirty_pages, DirtyPageEntry *dirty_pages) { if (dirty_pages[i].status != FREE) continue; if (dirty_pages[i].num_pages > 1) { - page_run = (PageRunCache *)malloc(sizeof(SinglePageCache)); + page_run = (PageRunCache *)malloc(sizeof(PageRunCache)); if (page_run == NULL) return -1; page_run->next = _pma_state->free_page_runs;