]> git.lizzy.rs Git - rust.git/blob - src/liballoc_system/lib.rs
Auto merge of #32990 - tbu-:pr_more_defaults_cstr_path, r=alexcrichton
[rust.git] / src / liballoc_system / lib.rs
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.
4 //
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.
10
11 #![crate_name = "alloc_system"]
12 #![crate_type = "rlib"]
13 #![no_std]
14 #![allocator]
15 #![cfg_attr(not(stage0), deny(warnings))]
16 #![unstable(feature = "alloc_system",
17             reason = "this library is unlikely to be stabilized in its current \
18                       form or name",
19             issue = "27783")]
20 #![feature(allocator)]
21 #![feature(libc)]
22 #![feature(staged_api)]
23
24 extern crate libc;
25
26 // The minimum alignment guaranteed by the architecture. This value is used to
27 // add fast paths for low alignment values. In practice, the alignment is a
28 // constant at the call site and the branch will be optimized out.
29 #[cfg(all(any(target_arch = "x86",
30               target_arch = "arm",
31               target_arch = "mips",
32               target_arch = "powerpc",
33               target_arch = "powerpc64",
34               target_arch = "asmjs")))]
35 const MIN_ALIGN: usize = 8;
36 #[cfg(all(any(target_arch = "x86_64",
37               target_arch = "aarch64")))]
38 const MIN_ALIGN: usize = 16;
39
40 #[no_mangle]
41 pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
42     unsafe { imp::allocate(size, align) }
43 }
44
45 #[no_mangle]
46 pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
47     unsafe { imp::deallocate(ptr, old_size, align) }
48 }
49
50 #[no_mangle]
51 pub extern "C" fn __rust_reallocate(ptr: *mut u8,
52                                     old_size: usize,
53                                     size: usize,
54                                     align: usize)
55                                     -> *mut u8 {
56     unsafe { imp::reallocate(ptr, old_size, size, align) }
57 }
58
59 #[no_mangle]
60 pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8,
61                                             old_size: usize,
62                                             size: usize,
63                                             align: usize)
64                                             -> usize {
65     unsafe { imp::reallocate_inplace(ptr, old_size, size, align) }
66 }
67
68 #[no_mangle]
69 pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
70     imp::usable_size(size, align)
71 }
72
73 #[cfg(unix)]
74 mod imp {
75     use core::cmp;
76     use core::ptr;
77     use libc;
78     use MIN_ALIGN;
79
80     pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
81         if align <= MIN_ALIGN {
82             libc::malloc(size as libc::size_t) as *mut u8
83         } else {
84             let mut out = ptr::null_mut();
85             let ret = libc::posix_memalign(&mut out, align as libc::size_t, size as libc::size_t);
86             if ret != 0 {
87                 ptr::null_mut()
88             } else {
89                 out as *mut u8
90             }
91         }
92     }
93
94     pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
95         if align <= MIN_ALIGN {
96             libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
97         } else {
98             let new_ptr = allocate(size, align);
99             if !new_ptr.is_null() {
100                 ptr::copy(ptr, new_ptr, cmp::min(size, old_size));
101                 deallocate(ptr, old_size, align);
102             }
103             new_ptr
104         }
105     }
106
107     pub unsafe fn reallocate_inplace(_ptr: *mut u8,
108                                      old_size: usize,
109                                      _size: usize,
110                                      _align: usize)
111                                      -> usize {
112         old_size
113     }
114
115     pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) {
116         libc::free(ptr as *mut libc::c_void)
117     }
118
119     pub fn usable_size(size: usize, _align: usize) -> usize {
120         size
121     }
122 }
123
124 #[cfg(windows)]
125 #[allow(bad_style)]
126 mod imp {
127     use MIN_ALIGN;
128
129     type LPVOID = *mut u8;
130     type HANDLE = LPVOID;
131     type SIZE_T = usize;
132     type DWORD = u32;
133     type BOOL = i32;
134
135     extern "system" {
136         fn GetProcessHeap() -> HANDLE;
137         fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
138         fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
139         fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
140     }
141
142     #[repr(C)]
143     struct Header(*mut u8);
144
145     const HEAP_REALLOC_IN_PLACE_ONLY: DWORD = 0x00000010;
146
147     unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
148         &mut *(ptr as *mut Header).offset(-1)
149     }
150
151     unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
152         let aligned = ptr.offset((align - (ptr as usize & (align - 1))) as isize);
153         *get_header(aligned) = Header(ptr);
154         aligned
155     }
156
157     pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
158         if align <= MIN_ALIGN {
159             HeapAlloc(GetProcessHeap(), 0, size as SIZE_T) as *mut u8
160         } else {
161             let ptr = HeapAlloc(GetProcessHeap(), 0, (size + align) as SIZE_T) as *mut u8;
162             if ptr.is_null() {
163                 return ptr;
164             }
165             align_ptr(ptr, align)
166         }
167     }
168
169     pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize, align: usize) -> *mut u8 {
170         if align <= MIN_ALIGN {
171             HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, size as SIZE_T) as *mut u8
172         } else {
173             let header = get_header(ptr);
174             let new = HeapReAlloc(GetProcessHeap(),
175                                   0,
176                                   header.0 as LPVOID,
177                                   (size + align) as SIZE_T) as *mut u8;
178             if new.is_null() {
179                 return new;
180             }
181             align_ptr(new, align)
182         }
183     }
184
185     pub unsafe fn reallocate_inplace(ptr: *mut u8,
186                                      old_size: usize,
187                                      size: usize,
188                                      align: usize)
189                                      -> usize {
190         if align <= MIN_ALIGN {
191             let new = HeapReAlloc(GetProcessHeap(),
192                                   HEAP_REALLOC_IN_PLACE_ONLY,
193                                   ptr as LPVOID,
194                                   size as SIZE_T) as *mut u8;
195             if new.is_null() {
196                 old_size
197             } else {
198                 size
199             }
200         } else {
201             old_size
202         }
203     }
204
205     pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, align: usize) {
206         if align <= MIN_ALIGN {
207             let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID);
208             debug_assert!(err != 0);
209         } else {
210             let header = get_header(ptr);
211             let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID);
212             debug_assert!(err != 0);
213         }
214     }
215
216     pub fn usable_size(size: usize, _align: usize) -> usize {
217         size
218     }
219 }