/src/liballoc_system/lib.rs

https://gitlab.com/alx741/rust · Rust · 219 lines · 181 code · 26 blank · 12 comment · 22 complexity · 80932e504893d3cd3fbf0215f7125e1e MD5 · raw file

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