Introduce get_process_heap
and fix atomic ordering.
This commit is contained in:
parent
4cce9e3db2
commit
c86e0985f9
1 changed files with 22 additions and 13 deletions
|
@ -89,10 +89,10 @@ extern "system" {
|
||||||
static HEAP: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
|
static HEAP: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
|
||||||
|
|
||||||
// Get a handle to the default heap of the current process, or null if the operation fails.
|
// Get a handle to the default heap of the current process, or null if the operation fails.
|
||||||
// SAFETY: If this operation is successful, `HEAP` will be successfully initialized and contain
|
// If this operation is successful, `HEAP` will be successfully initialized and contain
|
||||||
// a non-null handle returned by `GetProcessHeap`.
|
// a non-null handle returned by `GetProcessHeap`.
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn init_or_get_process_heap() -> c::HANDLE {
|
fn init_or_get_process_heap() -> c::HANDLE {
|
||||||
let heap = HEAP.load(Ordering::Relaxed);
|
let heap = HEAP.load(Ordering::Relaxed);
|
||||||
if heap.is_null() {
|
if heap.is_null() {
|
||||||
// `HEAP` has not yet been successfully initialized
|
// `HEAP` has not yet been successfully initialized
|
||||||
|
@ -100,7 +100,7 @@ unsafe fn init_or_get_process_heap() -> c::HANDLE {
|
||||||
if !heap.is_null() {
|
if !heap.is_null() {
|
||||||
// SAFETY: No locking is needed because within the same process,
|
// SAFETY: No locking is needed because within the same process,
|
||||||
// successful calls to `GetProcessHeap` will always return the same value, even on different threads.
|
// successful calls to `GetProcessHeap` will always return the same value, even on different threads.
|
||||||
HEAP.store(heap, Ordering::Relaxed);
|
HEAP.store(heap, Ordering::Release);
|
||||||
|
|
||||||
// SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap`
|
// SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap`
|
||||||
heap
|
heap
|
||||||
|
@ -114,16 +114,25 @@ unsafe fn init_or_get_process_heap() -> c::HANDLE {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get a non-null handle to the default heap of the current process.
|
||||||
|
// SAFETY: `HEAP` must have been successfully initialized.
|
||||||
|
#[inline]
|
||||||
|
unsafe fn get_process_heap() -> c::HANDLE {
|
||||||
|
HEAP.load(Ordering::Acquire)
|
||||||
|
}
|
||||||
|
|
||||||
// Header containing a pointer to the start of an allocated block.
|
// Header containing a pointer to the start of an allocated block.
|
||||||
// SAFETY: Size and alignment must be <= `MIN_ALIGN`.
|
// SAFETY: Size and alignment must be <= `MIN_ALIGN`.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct Header(*mut u8);
|
struct Header(*mut u8);
|
||||||
|
|
||||||
// Allocate a block of optionally zeroed memory for a given `layout`.
|
// Allocate a block of optionally zeroed memory for a given `layout`.
|
||||||
// SAFETY: Returns a pointer satisfying the guarantees of `System` about allocated pointers.
|
// SAFETY: Returns a pointer satisfying the guarantees of `System` about allocated pointers,
|
||||||
|
// or null if the operation fails. If this returns non-null `HEAP` will have been successfully
|
||||||
|
// initialized.
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 {
|
unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 {
|
||||||
let heap = unsafe { init_or_get_process_heap() };
|
let heap = init_or_get_process_heap();
|
||||||
if heap.is_null() {
|
if heap.is_null() {
|
||||||
// Allocation has failed, could not get the current process heap.
|
// Allocation has failed, could not get the current process heap.
|
||||||
return ptr::null_mut();
|
return ptr::null_mut();
|
||||||
|
@ -209,11 +218,11 @@ unsafe impl GlobalAlloc for System {
|
||||||
};
|
};
|
||||||
|
|
||||||
// SAFETY: because `ptr` has been successfully allocated with this allocator,
|
// SAFETY: because `ptr` has been successfully allocated with this allocator,
|
||||||
// `HEAP` must have been successfully initialized and contain a non-null handle
|
// `HEAP` must have been successfully initialized.
|
||||||
// returned by `GetProcessHeap`.
|
let heap = unsafe { get_process_heap() };
|
||||||
let heap = HEAP.load(Ordering::Relaxed);
|
|
||||||
|
|
||||||
// SAFETY: `block` is a pointer to the start of an allocated block.
|
// SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`,
|
||||||
|
// `block` is a pointer to the start of an allocated block.
|
||||||
unsafe {
|
unsafe {
|
||||||
let err = HeapFree(heap, 0, block as c::LPVOID);
|
let err = HeapFree(heap, 0, block as c::LPVOID);
|
||||||
debug_assert!(err != 0, "Failed to free heap memory: {}", c::GetLastError());
|
debug_assert!(err != 0, "Failed to free heap memory: {}", c::GetLastError());
|
||||||
|
@ -224,11 +233,11 @@ unsafe impl GlobalAlloc for System {
|
||||||
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||||
if layout.align() <= MIN_ALIGN {
|
if layout.align() <= MIN_ALIGN {
|
||||||
// SAFETY: because `ptr` has been successfully allocated with this allocator,
|
// SAFETY: because `ptr` has been successfully allocated with this allocator,
|
||||||
// `HEAP` must have been successfully initialized and contain a non-null handle
|
// `HEAP` must have been successfully initialized.
|
||||||
// returned by `GetProcessHeap`.
|
let heap = unsafe { get_process_heap() };
|
||||||
let heap = HEAP.load(Ordering::Relaxed);
|
|
||||||
|
|
||||||
// SAFETY: `ptr` is a pointer to the start of an allocated block.
|
// SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`,
|
||||||
|
// `ptr` is a pointer to the start of an allocated block.
|
||||||
// The returned pointer points to the start of an allocated block.
|
// The returned pointer points to the start of an allocated block.
|
||||||
unsafe { HeapReAlloc(heap, 0, ptr as c::LPVOID, new_size) as *mut u8 }
|
unsafe { HeapReAlloc(heap, 0, ptr as c::LPVOID, new_size) as *mut u8 }
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue