Skip to content

Commit b883d6a

Browse files
committed
simplify the exchange allocator
* stop using an atomic counter, this has a significant cost and valgrind will already catch these leaks * remove the extra layer of function calls * remove the assert of non-null in free, freeing null is well defined but throwing a failure from free will not be * stop initializing the `prev`/`next` pointers * abort on out-of-memory, failing won't necessarily work
1 parent 439b13f commit b883d6a

File tree

8 files changed

+44
-180
lines changed

8 files changed

+44
-180
lines changed

src/libstd/os.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
730730
#[cfg(windows)]
731731
unsafe fn get_list(p: &Path) -> ~[~str] {
732732
use libc::consts::os::extra::INVALID_HANDLE_VALUE;
733-
use libc::wcslen;
733+
use libc::{wcslen, free};
734734
use libc::funcs::extra::kernel32::{
735735
FindFirstFileW,
736736
FindNextFileW,
@@ -739,7 +739,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
739739
use os::win32::{
740740
as_utf16_p
741741
};
742-
use rt::global_heap::{malloc_raw, free_raw};
742+
use rt::global_heap::malloc_raw;
743743
#[nolink]
744744
extern {
745745
unsafe fn rust_list_dir_wfd_size() -> libc::size_t;
@@ -772,7 +772,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
772772
::cast::transmute(wfd_ptr));
773773
}
774774
FindClose(find_handle);
775-
free_raw(wfd_ptr);
775+
free(wfd_ptr)
776776
}
777777
strings
778778
}

src/libstd/rt/global_heap.rs

Lines changed: 41 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,21 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use sys::{size_of};
12-
use libc::{c_void, size_t, uintptr_t};
13-
use c_malloc = libc::malloc;
14-
use c_free = libc::free;
11+
use libc::{c_char, c_void, size_t, uintptr_t, free, malloc};
1512
use managed::raw::{BoxHeaderRepr, BoxRepr};
16-
use cast::transmute;
17-
use unstable::intrinsics::{atomic_xadd,atomic_xsub,TyDesc};
18-
use ptr::null;
13+
use unstable::intrinsics::TyDesc;
14+
use sys::size_of;
1915

20-
pub unsafe fn malloc(td: *TyDesc, size: uint) -> *c_void {
21-
assert!(td.is_not_null());
22-
23-
let total_size = get_box_size(size, (*td).align);
24-
let p = c_malloc(total_size as size_t);
25-
assert!(p.is_not_null());
26-
27-
let box: &mut BoxRepr = transmute(p);
28-
box.header.ref_count = -1; // Exchange values not ref counted
29-
box.header.type_desc = td;
30-
box.header.prev = null();
31-
box.header.next = null();
32-
33-
let exchange_count = &mut *exchange_count_ptr();
34-
atomic_xadd(exchange_count, 1);
35-
36-
return transmute(box);
37-
}
38-
/**
39-
Thin wrapper around libc::malloc, none of the box header
40-
stuff in exchange_alloc::malloc
41-
*/
42-
pub unsafe fn malloc_raw(size: uint) -> *c_void {
43-
let p = c_malloc(size as size_t);
44-
if p.is_null() {
45-
fail!("Failure in malloc_raw: result ptr is null");
46-
}
47-
p
48-
}
49-
50-
pub unsafe fn free(ptr: *c_void) {
51-
let exchange_count = &mut *exchange_count_ptr();
52-
atomic_xsub(exchange_count, 1);
53-
54-
assert!(ptr.is_not_null());
55-
c_free(ptr);
56-
}
57-
///Thin wrapper around libc::free, as with exchange_alloc::malloc_raw
58-
pub unsafe fn free_raw(ptr: *c_void) {
59-
c_free(ptr);
16+
extern {
17+
#[rust_stack]
18+
fn abort();
6019
}
6120

6221
fn get_box_size(body_size: uint, body_align: uint) -> uint {
6322
let header_size = size_of::<BoxHeaderRepr>();
6423
// FIXME (#2699): This alignment calculation is suspicious. Is it right?
6524
let total_size = align_to(header_size, body_align) + body_size;
66-
return total_size;
25+
total_size
6726
}
6827

6928
// Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power
@@ -73,11 +32,40 @@ fn align_to(size: uint, align: uint) -> uint {
7332
(size + align - 1) & !(align - 1)
7433
}
7534

76-
fn exchange_count_ptr() -> *mut int {
77-
// XXX: Need mutable globals
78-
unsafe { transmute(&rust_exchange_count) }
35+
/// A wrapper around libc::malloc, aborting on out-of-memory
36+
pub unsafe fn malloc_raw(size: uint) -> *c_void {
37+
let p = malloc(size as size_t);
38+
if p.is_null() {
39+
// we need a non-allocating way to print an error here
40+
abort();
41+
}
42+
p
7943
}
8044

81-
extern {
82-
static rust_exchange_count: uintptr_t;
45+
// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
46+
#[lang="exchange_malloc"]
47+
#[inline]
48+
pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
49+
let td = td as *TyDesc;
50+
let size = size as uint;
51+
52+
assert!(td.is_not_null());
53+
54+
let total_size = get_box_size(size, (*td).align);
55+
let p = malloc_raw(total_size as uint);
56+
57+
let box: *mut BoxRepr = p as *mut BoxRepr;
58+
(*box).header.ref_count = -1; // Exchange values not ref counted
59+
(*box).header.type_desc = td;
60+
61+
box as *c_char
62+
}
63+
64+
// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
65+
// inside a landing pad may corrupt the state of the exception handler.
66+
#[cfg(not(test))]
67+
#[lang="exchange_free"]
68+
#[inline]
69+
pub unsafe fn exchange_free(ptr: *c_char) {
70+
free(ptr as *c_void);
8371
}

src/libstd/unstable/exchange_alloc.rs

Lines changed: 0 additions & 83 deletions
This file was deleted.

src/libstd/unstable/lang.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use rt::task::Task;
2222
use rt::local::Local;
2323
use option::{Option, Some, None};
2424
use io;
25-
use rt::global_heap;
2625

2726
#[allow(non_camel_case_types)]
2827
pub type rust_task = c_void;
@@ -150,13 +149,6 @@ unsafe fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) {
150149
}
151150
}
152151

153-
// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
154-
#[lang="exchange_malloc"]
155-
#[inline]
156-
pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
157-
transmute(global_heap::malloc(transmute(td), transmute(size)))
158-
}
159-
160152
/// Because this code is so perf. sensitive, use a static constant so that
161153
/// debug printouts are compiled out most of the time.
162154
static ENABLE_DEBUG: bool = false;
@@ -228,15 +220,6 @@ impl DebugPrints for io::fd_t {
228220
}
229221
}
230222

231-
// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
232-
// inside a landing pad may corrupt the state of the exception handler. If a
233-
// problem occurs, call exit instead.
234-
#[lang="exchange_free"]
235-
#[inline]
236-
pub unsafe fn exchange_free(ptr: *c_char) {
237-
global_heap::free(transmute(ptr))
238-
}
239-
240223
#[lang="malloc"]
241224
pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
242225
match context() {

src/rt/rust_exchange_alloc.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,10 @@
1515
#include <string.h>
1616
#include <stdio.h>
1717

18-
extern uintptr_t rust_exchange_count;
19-
uintptr_t rust_exchange_count = 0;
20-
2118
void *
2219
rust_exchange_alloc::malloc(size_t size) {
2320
void *value = ::malloc(size);
2421
assert(value);
25-
26-
sync::increment(rust_exchange_count);
27-
2822
return value;
2923
}
3024

@@ -37,15 +31,5 @@ rust_exchange_alloc::realloc(void *ptr, size_t size) {
3731

3832
void
3933
rust_exchange_alloc::free(void *ptr) {
40-
sync::decrement(rust_exchange_count);
4134
::free(ptr);
4235
}
43-
44-
void
45-
rust_check_exchange_count_on_exit() {
46-
if (rust_exchange_count != 0) {
47-
printf("exchange heap not empty on exit\n");
48-
printf("%d dangling allocations\n", (int)rust_exchange_count);
49-
abort();
50-
}
51-
}

src/rt/rust_exchange_alloc.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,4 @@ class rust_exchange_alloc {
2121
void free(void *mem);
2222
};
2323

24-
extern "C" uintptr_t *
25-
rust_get_exchange_count_ptr();
26-
27-
void
28-
rust_check_exchange_count_on_exit();
29-
3024
#endif

src/rt/rust_kernel.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ rust_kernel::run() {
211211
assert(osmain_driver != NULL);
212212
osmain_driver->start_main_loop();
213213
sched_reaper.join();
214-
rust_check_exchange_count_on_exit();
215214
return rval;
216215
}
217216

src/rt/rustrt.def.in

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@ rust_register_exit_function
196196
rust_get_global_data_ptr
197197
rust_inc_kernel_live_count
198198
rust_dec_kernel_live_count
199-
rust_exchange_count
200199
rust_get_rt_tls_key
201200
swap_registers
202201
rust_readdir

0 commit comments

Comments
 (0)