Skip to content

Rollup of 7 pull requests #83790

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Apr 2, 2021
Merged
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7c89cc4
Add SharedResource abstraction and use it in write_shared
jyn514 Mar 25, 2021
f77ebd4
Add unstable option to only emit shared/crate-specific files
jyn514 Mar 25, 2021
0dbed61
Rework `std::sys::windows::alloc`
CDirkx Mar 12, 2021
b01bf0e
Apply suggestions from code review
CDirkx Mar 22, 2021
4cce9e3
Cache `GetProcessHeap`
CDirkx Mar 26, 2021
fa89c0f
add testcase for double-drop during Vec in-place collection
the8472 Mar 29, 2021
421f5d2
fix double-drop in in-place collect specialization
the8472 Mar 29, 2021
f2e52ff
2229: Produce a rustfix migration suggestion
arora-aman Mar 29, 2021
8f77356
give full path of constraint in suggest_constraining_type_param
0xPoe Mar 30, 2021
e78fac5
Handle the case of partially captured drop type
arora-aman Mar 31, 2021
d4f3f91
Enforce that Toolchain files are static and Crate files are dynamic
jyn514 Mar 31, 2021
1086d9b
Rename CrateSpecific -> InvocationSpecific
jyn514 Mar 31, 2021
413938d
Fix `--external-css` to be invocation-specific and note main.js shoul…
jyn514 Mar 31, 2021
18af989
Update lint message
arora-aman Apr 1, 2021
da86348
Update test cases
arora-aman Apr 1, 2021
a721957
Don't introduce a block if a block exists
arora-aman Apr 2, 2021
1b9620d
Make the diagnostic message more readable
arora-aman Apr 2, 2021
ca14abb
Fix stack overflow detection on FreeBSD 11.1+
asomers Mar 27, 2021
fad5388
Simplify coverage tests
richkadel Apr 1, 2021
c86e098
Introduce `get_process_heap` and fix atomic ordering.
CDirkx Apr 2, 2021
db1d003
Remove `debug_assert`
CDirkx Apr 2, 2021
48ebad5
Rollup merge of #83065 - CDirkx:win-alloc, r=dtolnay
Dylan-DPC Apr 2, 2021
31f5320
Rollup merge of #83478 - jyn514:fine-grained-files, r=Mark-Simulacrum
Dylan-DPC Apr 2, 2021
542f441
Rollup merge of #83629 - the8472:fix-inplace-panic-on-drop, r=m-ou-se
Dylan-DPC Apr 2, 2021
6cb74ad
Rollup merge of #83673 - hi-rustin:rustin-patch-suggestion, r=estebank
Dylan-DPC Apr 2, 2021
7009117
Rollup merge of #83755 - richkadel:cov-test-simplify, r=tmandry
Dylan-DPC Apr 2, 2021
eed73c6
Rollup merge of #83757 - sexxi-goose:migrations_out, r=nikomatsakis
Dylan-DPC Apr 2, 2021
cb7133f
Rollup merge of #83771 - asomers:stack_overflow_freebsd, r=dtolnay
Dylan-DPC Apr 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Cache GetProcessHeap
  • Loading branch information
CDirkx committed Mar 26, 2021
commit 4cce9e3db2d8a93fe72994e0a39e15e69cdbc7c2
70 changes: 54 additions & 16 deletions library/std/src/sys/windows/alloc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#![deny(unsafe_op_in_unsafe_fn)]

use crate::alloc::{GlobalAlloc, Layout, System};
use crate::ffi::c_void;
use crate::ptr;
use crate::sync::atomic::{AtomicPtr, Ordering};
use crate::sys::c;
use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN};

Expand All @@ -17,6 +19,9 @@ const HEAP_ZERO_MEMORY: c::DWORD = 0x00000008;
extern "system" {
// Get a handle to the default heap of the current process, or null if the operation fails.
//
// SAFETY: Successful calls to this function within the same process are assumed to
// always return the same handle, which remains valid for the entire lifetime of the process.
//
// See https://docs.microsoft.com/windows/win32/api/heapapi/nf-heapapi-getprocessheap
fn GetProcessHeap() -> c::HANDLE;

Expand Down Expand Up @@ -66,29 +71,59 @@ extern "system" {
// Returns a nonzero value if the operation is successful, and zero if the operation fails.
//
// SAFETY:
// - `hHeap` must be a non-null handle returned by `GetProcessHeap`.
// - `dwFlags` must be set to zero.
// - `lpMem` must be a pointer to an allocated block returned by `HeapAlloc` or `HeapReAlloc`,
// that has not already been freed.
// If the block was successfully freed, pointers pointing to the freed memory, such as `lpMem`,
// must not be dereferenced ever again.
//
// Note that both `hHeap` is allowed to be any value, and `lpMem` is allowed to be null,
// both of which will not cause the operation to fail.
// Note that `lpMem` is allowed to be null, which will not cause the operation to fail.
//
// See https://docs.microsoft.com/windows/win32/api/heapapi/nf-heapapi-heapfree
fn HeapFree(hHeap: c::HANDLE, dwFlags: c::DWORD, lpMem: c::LPVOID) -> c::BOOL;
}

// Cached handle to the default heap of the current process.
// Either a non-null handle returned by `GetProcessHeap`, or null when not yet initialized or `GetProcessHeap` failed.
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.
// SAFETY: If this operation is successful, `HEAP` will be successfully initialized and contain
// a non-null handle returned by `GetProcessHeap`.
#[inline]
unsafe fn init_or_get_process_heap() -> c::HANDLE {
let heap = HEAP.load(Ordering::Relaxed);
if heap.is_null() {
// `HEAP` has not yet been successfully initialized
let heap = unsafe { GetProcessHeap() };
if !heap.is_null() {
// SAFETY: No locking is needed because within the same process,
// successful calls to `GetProcessHeap` will always return the same value, even on different threads.
HEAP.store(heap, Ordering::Relaxed);

// SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap`
heap
} else {
// Could not get the current process heap.
ptr::null_mut()
}
} else {
// SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap`
heap
}
}

// 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)]
struct Header(*mut u8);

// Allocates a block of optionally zeroed memory for a given `layout`.
// Returns a pointer satisfying the guarantees of `System` about allocated pointers.
// Allocate a block of optionally zeroed memory for a given `layout`.
// SAFETY: Returns a pointer satisfying the guarantees of `System` about allocated pointers.
#[inline]
unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 {
let heap = unsafe { GetProcessHeap() };
let heap = unsafe { init_or_get_process_heap() };
if heap.is_null() {
// Allocation has failed, could not get the current process heap.
return ptr::null_mut();
Expand Down Expand Up @@ -147,14 +182,14 @@ unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 {
unsafe impl GlobalAlloc for System {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
// SAFETY: pointers returned by `allocate` satisfy the guarantees of `System`
// SAFETY: Pointers returned by `allocate` satisfy the guarantees of `System`
let zeroed = false;
unsafe { allocate(layout, zeroed) }
}

#[inline]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
// SAFETY: pointers returned by `allocate` satisfy the guarantees of `System`
// SAFETY: Pointers returned by `allocate` satisfy the guarantees of `System`
let zeroed = true;
unsafe { allocate(layout, zeroed) }
}
Expand All @@ -173,24 +208,27 @@ unsafe impl GlobalAlloc for System {
}
};

// SAFETY: because `ptr` has been successfully allocated with this allocator,
// `HEAP` must have been successfully initialized and contain a non-null handle
// returned by `GetProcessHeap`.
let heap = HEAP.load(Ordering::Relaxed);

// SAFETY: `block` is a pointer to the start of an allocated block.
unsafe {
let err = HeapFree(GetProcessHeap(), 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());
}
}

#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
if layout.align() <= MIN_ALIGN {
let heap = unsafe { GetProcessHeap() };
if heap.is_null() {
// Reallocation has failed, could not get the current process heap.
return ptr::null_mut();
}
// SAFETY: because `ptr` has been successfully allocated with this allocator,
// `HEAP` must have been successfully initialized and contain a non-null handle
// returned by `GetProcessHeap`.
let heap = HEAP.load(Ordering::Relaxed);

// SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`,
// `ptr` is a pointer to the start of an allocated block.
// SAFETY: `ptr` is a pointer 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 }
} else {
Expand Down