diff options
| author | Matt Brubeck <mbrubeck@limpet.net> | 2017-03-09 17:53:01 -0800 |
|---|---|---|
| committer | Matt Brubeck <mbrubeck@limpet.net> | 2017-04-15 09:01:56 -0700 |
| commit | 675475c4d3e3b1ebff5b761570f4a3f9a0ca23df (patch) | |
| tree | 49cfa5b4d6edca5205909e9b0729e9744507940c /src/liballoc | |
| parent | 5637ed756632ded9e458b82a23cc1dddbb57c51f (diff) | |
| download | rust-675475c4d3e3b1ebff5b761570f4a3f9a0ca23df.tar.gz rust-675475c4d3e3b1ebff5b761570f4a3f9a0ca23df.zip | |
Specialize Vec::from_elem<u8> to use calloc or memset
Fixes #38723.
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/heap.rs | 34 | ||||
| -rw-r--r-- | src/liballoc/raw_vec.rs | 17 |
2 files changed, 50 insertions, 1 deletions
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 51e6f2f8bd7..08a0b2a6d00 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -23,6 +23,7 @@ use core::intrinsics::{min_align_of_val, size_of_val}; extern "C" { #[allocator] fn __rust_allocate(size: usize, align: usize) -> *mut u8; + fn __rust_allocate_zeroed(size: usize, align: usize) -> *mut u8; fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize); fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8; fn __rust_reallocate_inplace(ptr: *mut u8, @@ -59,6 +60,20 @@ pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { __rust_allocate(size, align) } +/// Return a pointer to `size` bytes of memory aligned to `align` and +/// initialized to zeroes. +/// +/// On failure, return a null pointer. +/// +/// Behavior is undefined if the requested size is 0 or the alignment is not a +/// power of 2. The alignment must be no larger than the largest supported page +/// size on the platform. +#[inline] +pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 { + check_size_and_alignment(size, align); + __rust_allocate_zeroed(size, align) +} + /// Resize the allocation referenced by `ptr` to `size` bytes. /// /// On failure, return a null pointer and leave the original allocation intact. @@ -163,6 +178,25 @@ mod tests { use heap; #[test] + fn allocate_zeroed() { + unsafe { + let size = 1024; + let ptr = heap::allocate_zeroed(size, 1); + if ptr.is_null() { + ::oom() + } + + let end = ptr.offset(size as isize); + let mut i = ptr; + while i < end { + assert_eq!(*i, 0); + i = i.offset(1); + } + heap::deallocate(ptr, size, 1); + } + } + + #[test] fn basic_reallocate_inplace_noop() { unsafe { let size = 4000; diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 357a2724e00..6a53d3a9ca5 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -81,7 +81,18 @@ impl<T> RawVec<T> { /// # Aborts /// /// Aborts on OOM + #[inline] pub fn with_capacity(cap: usize) -> Self { + RawVec::allocate(cap, false) + } + + /// Like `with_capacity` but guarantees the buffer is zeroed. + #[inline] + pub fn with_capacity_zeroed(cap: usize) -> Self { + RawVec::allocate(cap, true) + } + + fn allocate(cap: usize, zeroed: bool) -> Self { unsafe { let elem_size = mem::size_of::<T>(); @@ -93,7 +104,11 @@ impl<T> RawVec<T> { heap::EMPTY as *mut u8 } else { let align = mem::align_of::<T>(); - let ptr = heap::allocate(alloc_size, align); + let ptr = if zeroed { + heap::allocate_zeroed(alloc_size, align) + } else { + heap::allocate(alloc_size, align) + }; if ptr.is_null() { oom() } |
