Skip to content

Commit 7c13f64

Browse files
committed
Move OOM handling to liballoc and remove the oom lang item
This removes the need for `no_std` programs to define that lang item themselves: Fixes #51540
1 parent 68dfaed commit 7c13f64

File tree

5 files changed

+98
-66
lines changed

5 files changed

+98
-66
lines changed

src/liballoc/alloc.rs

+84-5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
use core::intrinsics::{min_align_of_val, size_of_val};
1616
use core::ptr::{NonNull, Unique};
1717
use core::usize;
18+
#[cfg(target_has_atomic = "ptr")] use core::{mem, ptr};
19+
#[cfg(target_has_atomic = "ptr")] use core::sync::atomic::{AtomicPtr, Ordering};
1820

1921
#[stable(feature = "alloc_module", since = "1.28.0")]
2022
#[doc(inline)]
@@ -191,12 +193,89 @@ pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
191193
#[stable(feature = "global_alloc", since = "1.28.0")]
192194
#[rustc_allocator_nounwind]
193195
pub fn handle_alloc_error(layout: Layout) -> ! {
194-
#[allow(improper_ctypes)]
195-
extern "Rust" {
196-
#[lang = "oom"]
197-
fn oom_impl(layout: Layout) -> !;
196+
#[cfg(target_has_atomic = "ptr")]
197+
{
198+
let hook = HOOK.load(Ordering::SeqCst);
199+
let hook: fn(Layout) = if hook.is_null() {
200+
default_alloc_error_hook
201+
} else {
202+
unsafe { mem::transmute(hook) }
203+
};
204+
hook(layout);
205+
}
206+
#[cfg(not(target_has_atomic = "ptr"))]
207+
{
208+
default_alloc_error_hook(layout)
209+
}
210+
211+
unsafe {
212+
#[cfg(not(stage0))]
213+
{
214+
#[allow(improper_ctypes)]
215+
extern "Rust" {
216+
// This function is generated by the compiler
217+
// and calls __rust_abort_internal in src/libstd/alloc.rs
218+
// if the `std` crate is linked.
219+
fn __rust_maybe_abort_internal();
220+
}
221+
__rust_maybe_abort_internal();
222+
}
223+
// The above does nothing and returns when `std` is not linked.
224+
// In that case we abort "naively" here:
225+
::core::intrinsics::abort()
226+
}
227+
}
228+
229+
fn default_alloc_error_hook(layout: Layout) {
230+
#[cfg(stage0)]
231+
let _ = layout;
232+
#[cfg(not(stage0))]
233+
unsafe {
234+
#[allow(improper_ctypes)]
235+
extern "Rust" {
236+
// This function is generated by the compiler
237+
// and calls __rust_default_alloc_error_hook in src/libstd/alloc.rs
238+
// if the `std` crate is linked.
239+
fn __rust_maybe_default_alloc_error_hook(size: usize, align: usize);
240+
}
241+
__rust_maybe_default_alloc_error_hook(layout.size(), layout.align())
242+
}
243+
}
244+
245+
#[cfg(target_has_atomic = "ptr")]
246+
static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
247+
248+
/// Registers a custom allocation error hook, replacing any that was previously registered.
249+
///
250+
/// The allocation error hook is invoked when an infallible memory allocation fails, before
251+
/// the runtime aborts. The default hook prints a message to standard error,
252+
/// but this behavior can be customized with the [`set_alloc_error_hook`] and
253+
/// [`take_alloc_error_hook`] functions.
254+
///
255+
/// The hook is provided with a `Layout` struct which contains information
256+
/// about the allocation that failed.
257+
///
258+
/// The allocation error hook is a global resource.
259+
#[unstable(feature = "alloc_error_hook", issue = "51245")]
260+
#[cfg(target_has_atomic = "ptr")]
261+
pub fn set_alloc_error_hook(hook: fn(Layout)) {
262+
HOOK.store(hook as *mut (), Ordering::SeqCst);
263+
}
264+
265+
/// Unregisters the current allocation error hook, returning it.
266+
///
267+
/// *See also the function [`set_alloc_error_hook`].*
268+
///
269+
/// If no custom hook is registered, the default hook will be returned.
270+
#[unstable(feature = "alloc_error_hook", issue = "51245")]
271+
#[cfg(target_has_atomic = "ptr")]
272+
pub fn take_alloc_error_hook() -> fn(Layout) {
273+
let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
274+
if hook.is_null() {
275+
default_alloc_error_hook
276+
} else {
277+
unsafe { mem::transmute(hook) }
198278
}
199-
unsafe { oom_impl(layout) }
200279
}
201280

202281
#[cfg(test)]

src/librustc/middle/lang_items.rs

-1
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,6 @@ language_item_table! {
307307
ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
308308
BoxFreeFnLangItem, "box_free", box_free_fn;
309309
DropInPlaceFnLangItem, "drop_in_place", drop_in_place_fn;
310-
OomLangItem, "oom", oom;
311310

312311
StartFnLangItem, "start", start_fn;
313312

src/librustc/middle/weak_lang_items.rs

-1
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,4 @@ weak_lang_items! {
151151
panic_impl, PanicImplLangItem, rust_begin_unwind;
152152
eh_personality, EhPersonalityLangItem, rust_eh_personality;
153153
eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume;
154-
oom, OomLangItem, rust_oom;
155154
}

src/libstd/alloc.rs

+14-56
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,6 @@
7474
7575
#![stable(feature = "alloc_module", since = "1.28.0")]
7676

77-
use core::sync::atomic::{AtomicPtr, Ordering};
78-
use core::{mem, ptr};
79-
use sys_common::util::dumb_print;
80-
8177
#[stable(feature = "alloc_module", since = "1.28.0")]
8278
#[doc(inline)]
8379
pub use alloc_crate::alloc::*;
@@ -86,64 +82,14 @@ pub use alloc_crate::alloc::*;
8682
#[doc(inline)]
8783
pub use alloc_system::System;
8884

89-
static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
90-
91-
/// Registers a custom allocation error hook, replacing any that was previously registered.
92-
///
93-
/// The allocation error hook is invoked when an infallible memory allocation fails, before
94-
/// the runtime aborts. The default hook prints a message to standard error,
95-
/// but this behavior can be customized with the [`set_alloc_error_hook`] and
96-
/// [`take_alloc_error_hook`] functions.
97-
///
98-
/// The hook is provided with a `Layout` struct which contains information
99-
/// about the allocation that failed.
100-
///
101-
/// The allocation error hook is a global resource.
102-
#[unstable(feature = "alloc_error_hook", issue = "51245")]
103-
pub fn set_alloc_error_hook(hook: fn(Layout)) {
104-
HOOK.store(hook as *mut (), Ordering::SeqCst);
105-
}
106-
107-
/// Unregisters the current allocation error hook, returning it.
108-
///
109-
/// *See also the function [`set_alloc_error_hook`].*
110-
///
111-
/// If no custom hook is registered, the default hook will be returned.
112-
#[unstable(feature = "alloc_error_hook", issue = "51245")]
113-
pub fn take_alloc_error_hook() -> fn(Layout) {
114-
let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
115-
if hook.is_null() {
116-
default_alloc_error_hook
117-
} else {
118-
unsafe { mem::transmute(hook) }
119-
}
120-
}
121-
122-
fn default_alloc_error_hook(layout: Layout) {
123-
dumb_print(format_args!("memory allocation of {} bytes failed", layout.size()));
124-
}
125-
126-
#[cfg(not(test))]
127-
#[doc(hidden)]
128-
#[lang = "oom"]
129-
#[unstable(feature = "alloc_internals", issue = "0")]
130-
pub extern fn rust_oom(layout: Layout) -> ! {
131-
let hook = HOOK.load(Ordering::SeqCst);
132-
let hook: fn(Layout) = if hook.is_null() {
133-
default_alloc_error_hook
134-
} else {
135-
unsafe { mem::transmute(hook) }
136-
};
137-
hook(layout);
138-
unsafe { ::sys::abort_internal(); }
139-
}
140-
14185
#[cfg(not(test))]
14286
#[doc(hidden)]
14387
#[allow(unused_attributes)]
14488
#[unstable(feature = "alloc_internals", issue = "0")]
14589
pub mod __default_lib_allocator {
14690
use super::{System, Layout, GlobalAlloc};
91+
use sys_common::util::dumb_print;
92+
14793
// for symbol names src/librustc/middle/allocator.rs
14894
// for signatures src/librustc_allocator/lib.rs
14995

@@ -181,4 +127,16 @@ pub mod __default_lib_allocator {
181127
let layout = Layout::from_size_align_unchecked(size, align);
182128
System.alloc_zeroed(layout)
183129
}
130+
131+
#[no_mangle]
132+
#[rustc_std_internal_symbol]
133+
pub extern fn __rust_default_alloc_error_hook(size: usize, _align: usize) {
134+
dumb_print(format_args!("memory allocation of {} bytes failed", size));
135+
}
136+
137+
#[no_mangle]
138+
#[rustc_std_internal_symbol]
139+
pub unsafe extern fn __rust_abort_internal() {
140+
::sys::abort_internal()
141+
}
184142
}

src/test/ui/missing-allocator.rs

-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,4 @@ fn panic(_: &core::panic::PanicInfo) -> ! {
2020
loop {}
2121
}
2222

23-
#[lang = "oom"]
24-
fn oom() {}
25-
2623
extern crate alloc;

0 commit comments

Comments
 (0)