/src/liballoc_system/lib.rs

https://gitlab.com/0072016/0072016-rusty · Rust · 218 lines · 180 code · 26 blank · 12 comment · 21 complexity · d9c173dd6948d18304a32c12473bb69b 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 = "mipsel",
  30. target_arch = "powerpc",
  31. target_arch = "powerpc64",
  32. target_arch = "powerpc64le")))]
  33. const MIN_ALIGN: usize = 8;
  34. #[cfg(all(any(target_arch = "x86_64",
  35. target_arch = "aarch64")))]
  36. const MIN_ALIGN: usize = 16;
  37. #[no_mangle]
  38. pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
  39. unsafe { imp::allocate(size, align) }
  40. }
  41. #[no_mangle]
  42. pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
  43. unsafe { imp::deallocate(ptr, old_size, align) }
  44. }
  45. #[no_mangle]
  46. pub extern "C" fn __rust_reallocate(ptr: *mut u8,
  47. old_size: usize,
  48. size: usize,
  49. align: usize)
  50. -> *mut u8 {
  51. unsafe { imp::reallocate(ptr, old_size, size, align) }
  52. }
  53. #[no_mangle]
  54. pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8,
  55. old_size: usize,
  56. size: usize,
  57. align: usize)
  58. -> usize {
  59. unsafe { imp::reallocate_inplace(ptr, old_size, size, align) }
  60. }
  61. #[no_mangle]
  62. pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
  63. imp::usable_size(size, align)
  64. }
  65. #[cfg(unix)]
  66. mod imp {
  67. use core::cmp;
  68. use core::ptr;
  69. use libc;
  70. use MIN_ALIGN;
  71. pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
  72. if align <= MIN_ALIGN {
  73. libc::malloc(size as libc::size_t) as *mut u8
  74. } else {
  75. let mut out = ptr::null_mut();
  76. let ret = libc::posix_memalign(&mut out, align as libc::size_t, size as libc::size_t);
  77. if ret != 0 {
  78. ptr::null_mut()
  79. } else {
  80. out as *mut u8
  81. }
  82. }
  83. }
  84. pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
  85. if align <= MIN_ALIGN {
  86. libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
  87. } else {
  88. let new_ptr = allocate(size, align);
  89. ptr::copy(ptr, new_ptr, cmp::min(size, old_size));
  90. deallocate(ptr, old_size, align);
  91. new_ptr
  92. }
  93. }
  94. pub unsafe fn reallocate_inplace(_ptr: *mut u8,
  95. old_size: usize,
  96. _size: usize,
  97. _align: usize)
  98. -> usize {
  99. old_size
  100. }
  101. pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) {
  102. libc::free(ptr as *mut libc::c_void)
  103. }
  104. pub fn usable_size(size: usize, _align: usize) -> usize {
  105. size
  106. }
  107. }
  108. #[cfg(windows)]
  109. #[allow(bad_style)]
  110. mod imp {
  111. use MIN_ALIGN;
  112. type LPVOID = *mut u8;
  113. type HANDLE = LPVOID;
  114. type SIZE_T = usize;
  115. type DWORD = u32;
  116. type BOOL = i32;
  117. extern "system" {
  118. fn GetProcessHeap() -> HANDLE;
  119. fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
  120. fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
  121. fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
  122. }
  123. #[repr(C)]
  124. struct Header(*mut u8);
  125. const HEAP_REALLOC_IN_PLACE_ONLY: DWORD = 0x00000010;
  126. unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
  127. &mut *(ptr as *mut Header).offset(-1)
  128. }
  129. unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
  130. let aligned = ptr.offset((align - (ptr as usize & (align - 1))) as isize);
  131. *get_header(aligned) = Header(ptr);
  132. aligned
  133. }
  134. pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
  135. if align <= MIN_ALIGN {
  136. HeapAlloc(GetProcessHeap(), 0, size as SIZE_T) as *mut u8
  137. } else {
  138. let ptr = HeapAlloc(GetProcessHeap(), 0, (size + align) as SIZE_T) as *mut u8;
  139. if ptr.is_null() {
  140. return ptr;
  141. }
  142. align_ptr(ptr, align)
  143. }
  144. }
  145. pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize, align: usize) -> *mut u8 {
  146. if align <= MIN_ALIGN {
  147. HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, size as SIZE_T) as *mut u8
  148. } else {
  149. let header = get_header(ptr);
  150. let new = HeapReAlloc(GetProcessHeap(),
  151. 0,
  152. header.0 as LPVOID,
  153. (size + align) as SIZE_T) as *mut u8;
  154. if new.is_null() {
  155. return new;
  156. }
  157. align_ptr(new, align)
  158. }
  159. }
  160. pub unsafe fn reallocate_inplace(ptr: *mut u8,
  161. old_size: usize,
  162. size: usize,
  163. align: usize)
  164. -> usize {
  165. if align <= MIN_ALIGN {
  166. let new = HeapReAlloc(GetProcessHeap(),
  167. HEAP_REALLOC_IN_PLACE_ONLY,
  168. ptr as LPVOID,
  169. size as SIZE_T) as *mut u8;
  170. if new.is_null() {
  171. old_size
  172. } else {
  173. size
  174. }
  175. } else {
  176. old_size
  177. }
  178. }
  179. pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, align: usize) {
  180. if align <= MIN_ALIGN {
  181. let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID);
  182. debug_assert!(err != 0);
  183. } else {
  184. let header = get_header(ptr);
  185. let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID);
  186. debug_assert!(err != 0);
  187. }
  188. }
  189. pub fn usable_size(size: usize, _align: usize) -> usize {
  190. size
  191. }
  192. }