]> git.lizzy.rs Git - rust.git/commitdiff
implement and test posix_memalign
authorRalf Jung <post@ralfj.de>
Wed, 13 Feb 2019 16:47:47 +0000 (17:47 +0100)
committerRalf Jung <post@ralfj.de>
Wed, 13 Feb 2019 16:47:54 +0000 (17:47 +0100)
src/fn_call.rs
tests/run-pass/heap.rs

index a5708305a9762be726b83edb810a9b9fffd0b4e5..fa68f1d0d703ad2c01ab1a50da3796b1779718b5 100644 (file)
@@ -93,6 +93,32 @@ fn emulate_foreign_item(
                     this.write_scalar(Scalar::Ptr(ptr.with_default_tag()), dest)?;
                 }
             }
+            "posix_memalign" => {
+                let ret = this.deref_operand(args[0])?;
+                let align = this.read_scalar(args[1])?.to_usize(this)?;
+                let size = this.read_scalar(args[2])?.to_usize(this)?;
+                // align must be a power of 2, and also at least ptr-sized (wtf, POSIX)
+                if !align.is_power_of_two() {
+                    return err!(HeapAllocNonPowerOfTwoAlignment(align));
+                }
+                if align < this.pointer_size().bytes() {
+                    return err!(MachineError(format!(
+                        "posix_memalign: alignment must be at least the size of a pointer, but is {}",
+                        align,
+                    )));
+                }
+                if size == 0 {
+                    this.write_null(ret.into())?;
+                } else {
+                    let ptr = this.memory_mut().allocate(
+                        Size::from_bytes(size),
+                        Align::from_bytes(align).unwrap(),
+                        MiriMemoryKind::C.into()
+                    );
+                    this.write_scalar(Scalar::Ptr(ptr.with_default_tag()), ret.into())?;
+                }
+                this.write_null(dest)?;
+            }
 
             "free" => {
                 let ptr = this.read_scalar(args[0])?.not_undef()?;
index b533f916469881a96c23657ea33f4d65f6e2d218..8421dce9c21bf60dbc3a9c941e7d6d45defb759b 100644 (file)
@@ -1,4 +1,7 @@
 #![feature(box_syntax)]
+#![feature(allocator_api)]
+
+use std::alloc::{Global, Alloc, Layout, System};
 
 fn make_box() -> Box<(i16, i16)> {
     Box::new((1, 2))
@@ -27,8 +30,31 @@ fn allocate_reallocate() {
     assert_eq!(s.capacity(), 9);
 }
 
+fn check_overalign_requests<T: Alloc>(mut allocator: T) {
+    let size = 8;
+    let align = 16; // greater than size
+    let iterations = 1; // Miri is deterministic, no need to try many times
+    unsafe {
+        let pointers: Vec<_> = (0..iterations).map(|_| {
+            allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap()
+        }).collect();
+        for &ptr in &pointers {
+            assert_eq!((ptr.as_ptr() as usize) % align, 0,
+                       "Got a pointer less aligned than requested")
+        }
+
+        // Clean up
+        for &ptr in &pointers {
+            allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap())
+        }
+    }
+}
+
 fn main() {
     assert_eq!(*make_box(), (1, 2));
     assert_eq!(*make_box_syntax(), (1, 2));
     allocate_reallocate();
+
+    check_overalign_requests(System);
+    check_overalign_requests(Global);
 }