1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 #[cfg(any(windows, unix, target_os = "redox"))]
15 mod realloc_fallback {
16 use core::alloc::{GlobalAlloc, Layout};
20 pub(crate) unsafe fn realloc_fallback(
26 // Docs for GlobalAlloc::realloc require this to be valid:
27 let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
28 let new_ptr = GlobalAlloc::alloc(self, new_layout);
29 if !new_ptr.is_null() {
30 let size = cmp::min(old_layout.size(), new_size);
31 ptr::copy_nonoverlapping(ptr, new_ptr, size);
32 GlobalAlloc::dealloc(self, ptr, old_layout);
38 #[cfg(any(unix, target_os = "redox"))]
40 use core::alloc::{GlobalAlloc, Layout};
41 use core::ffi::c_void;
45 fn posix_memalign(memptr: *mut *mut c_void, align: usize, size: usize) -> i32;
46 fn free(p: *mut c_void);
48 unsafe impl GlobalAlloc for System {
50 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
51 aligned_malloc(&layout)
54 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
55 let ptr = self.alloc(layout.clone());
57 ptr::write_bytes(ptr, 0, layout.size());
62 unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
63 free(ptr as *mut c_void)
66 unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
67 self.realloc_fallback(ptr, layout, new_size)
70 unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
71 let mut out = ptr::null_mut();
72 let ret = posix_memalign(&mut out, layout.align(), layout.size());
73 if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
77 #[allow(nonstandard_style)]
79 use core::alloc::{GlobalAlloc, Layout};
81 type LPVOID = *mut u8;
87 fn GetProcessHeap() -> HANDLE;
88 fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
89 fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
90 fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
91 fn GetLastError() -> DWORD;
94 struct Header(*mut u8);
95 const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
96 unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
97 &mut *(ptr as *mut Header).sub(1)
99 unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
100 let aligned = ptr.add(align - (ptr as usize & (align - 1)));
101 *get_header(aligned) = Header(ptr);
105 unsafe fn allocate_with_flags(layout: Layout, flags: DWORD) -> *mut u8 {
106 let size = layout.size() + layout.align();
107 let ptr = HeapAlloc(GetProcessHeap(), flags, size);
108 (if ptr.is_null() { ptr } else { align_ptr(ptr, layout.align()) }) as *mut u8
110 unsafe impl GlobalAlloc for System {
112 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
113 allocate_with_flags(layout, 0)
116 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
117 allocate_with_flags(layout, HEAP_ZERO_MEMORY)
120 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
121 let header = get_header(ptr);
122 let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID);
123 debug_assert!(err != 0, "Failed to free heap memory: {}", GetLastError());
126 unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
127 self.realloc_fallback(ptr, layout, new_size)