Skip to content

Commit f36546d

Browse files
author
Julian Orth
committed
---
yaml --- r: 157471 b: refs/heads/snap-stage3 c: 8adfd02 h: refs/heads/master i: 157469: fcc758f 157467: 90d7062 157463: 9362587 157455: 6e1e885 157439: f3eba8f v: v3
1 parent a897173 commit f36546d

38 files changed

+969
-880
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: 065caf34f5ff29e04605f95d9c5d511af219439a
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: f037452447f5f46deb26e1c483fe88fb51a19198
4+
refs/heads/snap-stage3: 8adfd02368343636fe83b68e35c3b8e2db0f0e02
55
refs/heads/try: 0ee4d8b0b112c608646fa75463ab4dc59132efd9
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/src/doc/guide.md

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3466,14 +3466,13 @@ for destroying that resource as well. Given that we're discussing pointers
34663466
right now, let's discuss this in the context of memory allocation, though
34673467
it applies to other resources as well.
34683468

3469-
When you allocate heap memory, you need a mechanism to free that memory. Many
3470-
languages use a garbage collector to handle deallocation. This is a valid,
3471-
time-tested strategy, but it's not without its drawbacks: it adds overhead, and
3472-
can lead to unpredictable pauses in execution. Because the programmer does not
3473-
have to think as much about deallocation, allocation becomes something
3474-
commonplace, leading to more memory usage. And if you need precise control
3475-
over when something is deallocated, leaving it up to your runtime can make this
3476-
difficult.
3469+
When you allocate heap memory, you need a mechanism to free that memory. Many
3470+
languages let the programmer control the allocation, and then use a garbage
3471+
collector to handle the deallocation. This is a valid, time-tested strategy,
3472+
but it's not without its drawbacks. Because the programmer does not have to
3473+
think as much about deallocation, allocation becomes something commonplace,
3474+
because it's easy. And if you need precise control over when something is
3475+
deallocated, leaving it up to your runtime can make this difficult.
34773476

34783477
Rust chooses a different path, and that path is called **ownership**. Any
34793478
binding that creates a resource is the **owner** of that resource.
@@ -3499,19 +3498,17 @@ memory. The length of time that the borrower is borrowing the pointer
34993498
from you is called a **lifetime**.
35003499

35013500
If two distinct bindings share a pointer, and the memory that pointer points to
3502-
is immutable, then there are no problems. But if it's mutable, the result of
3503-
changing it can vary unpredictably depending on who happens to access it first,
3504-
which is called a **race condition**. To avoid this, if someone wants to mutate
3505-
something that they've borrowed from you, you must not have lent out that
3506-
pointer to anyone else.
3501+
is immutable, then there are no problems. But if it's mutable, both pointers
3502+
can attempt to write to the memory at the same time, causing a **race
3503+
condition**. Therefore, if someone wants to mutate something that they've
3504+
borrowed from you, you must not have lent out that pointer to anyone else.
35073505

35083506
Rust has a sophisticated system called the **borrow checker** to make sure that
35093507
everyone plays by these rules. At compile time, it verifies that none of these
3510-
rules are broken. If our program compiles successfully, Rust can guarantee it
3511-
is free of data races and other memory errors, and there is no runtime overhead
3512-
for any of this. The borrow checker works only at compile time. If the borrow
3513-
checker did find a problem, it will report a **lifetime error**, and your
3514-
program will refuse to compile.
3508+
rules are broken. If there's no problem, our program compiles successfully, and
3509+
there is no runtime overhead for any of this. The borrow checker works only at
3510+
compile time. If the borrow checker did find a problem, it will report a
3511+
**lifetime error**, and your program will refuse to compile.
35153512

35163513
That's a lot to take in. It's also one of the _most_ important concepts in
35173514
all of Rust. Let's see this syntax in action:

branches/snap-stage3/src/liballoc/heap.rs

Lines changed: 40 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
2828
/// size on the platform.
2929
///
3030
/// The `old_size` and `align` parameters are the parameters that were used to
31-
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
32-
/// any value in range_inclusive(requested_size, usable_size).
31+
/// create the allocation referenced by `ptr`. The `old_size` parameter may also
32+
/// be the value returned by `usable_size` for the requested size.
3333
#[inline]
3434
pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
3535
imp::reallocate(ptr, old_size, size, align)
@@ -38,8 +38,8 @@ pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint)
3838
/// Extends or shrinks the allocation referenced by `ptr` to `size` bytes of
3939
/// memory in-place.
4040
///
41-
/// If the operation succeeds, it returns `usable_size(size, align)` and if it
42-
/// fails (or is a no-op) it returns `usable_size(old_size, align)`.
41+
/// Returns true if successful, otherwise false if the allocation was not
42+
/// altered.
4343
///
4444
/// Behavior is undefined if the requested size is 0 or the alignment is not a
4545
/// power of 2. The alignment must be no larger than the largest supported page
@@ -49,20 +49,20 @@ pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint)
4949
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
5050
/// any value in range_inclusive(requested_size, usable_size).
5151
#[inline]
52-
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> uint {
52+
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> bool {
5353
imp::reallocate_inplace(ptr, old_size, size, align)
5454
}
5555

5656
/// Deallocates the memory referenced by `ptr`.
5757
///
5858
/// The `ptr` parameter must not be null.
5959
///
60-
/// The `old_size` and `align` parameters are the parameters that were used to
61-
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
62-
/// any value in range_inclusive(requested_size, usable_size).
60+
/// The `size` and `align` parameters are the parameters that were used to
61+
/// create the allocation referenced by `ptr`. The `size` parameter may also be
62+
/// the value returned by `usable_size` for the requested size.
6363
#[inline]
64-
pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
65-
imp::deallocate(ptr, old_size, align)
64+
pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
65+
imp::deallocate(ptr, size, align)
6666
}
6767

6868
/// Returns the usable size of an allocation created with the specified the
@@ -102,8 +102,8 @@ unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
102102
#[cfg(not(test))]
103103
#[lang="exchange_free"]
104104
#[inline]
105-
unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
106-
deallocate(ptr, old_size, align);
105+
unsafe fn exchange_free(ptr: *mut u8, size: uint, align: uint) {
106+
deallocate(ptr, size, align);
107107
}
108108

109109
// The minimum alignment guaranteed by the architecture. This value is used to
@@ -112,10 +112,10 @@ unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
112112
#[cfg(any(target_arch = "arm",
113113
target_arch = "mips",
114114
target_arch = "mipsel"))]
115-
const MIN_ALIGN: uint = 8;
115+
static MIN_ALIGN: uint = 8;
116116
#[cfg(any(target_arch = "x86",
117117
target_arch = "x86_64"))]
118-
const MIN_ALIGN: uint = 16;
118+
static MIN_ALIGN: uint = 16;
119119

120120
#[cfg(jemalloc)]
121121
mod imp {
@@ -178,16 +178,22 @@ mod imp {
178178
}
179179

180180
#[inline]
181-
pub unsafe fn reallocate_inplace(ptr: *mut u8, _old_size: uint, size: uint,
182-
align: uint) -> uint {
181+
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
182+
align: uint) -> bool {
183183
let flags = align_to_flags(align);
184-
je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as uint
184+
let new_size = je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as uint;
185+
// checking for failure to shrink is tricky
186+
if size < old_size {
187+
usable_size(size, align) == new_size as uint
188+
} else {
189+
new_size >= size
190+
}
185191
}
186192

187193
#[inline]
188-
pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
194+
pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
189195
let flags = align_to_flags(align);
190-
je_sdallocx(ptr as *mut c_void, old_size as size_t, flags)
196+
je_sdallocx(ptr as *mut c_void, size as size_t, flags)
191197
}
192198

193199
#[inline]
@@ -207,8 +213,8 @@ mod imp {
207213
mod imp {
208214
use core::cmp;
209215
use core::ptr;
210-
use core::ptr::RawPtr;
211216
use libc;
217+
use libc_heap;
212218
use super::MIN_ALIGN;
213219

214220
extern {
@@ -220,11 +226,7 @@ mod imp {
220226
#[inline]
221227
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
222228
if align <= MIN_ALIGN {
223-
let ptr = libc::malloc(size as libc::size_t);
224-
if ptr.is_null() {
225-
::oom();
226-
}
227-
ptr as *mut u8
229+
libc_heap::malloc_raw(size)
228230
} else {
229231
let mut out = 0 as *mut libc::c_void;
230232
let ret = posix_memalign(&mut out,
@@ -240,11 +242,7 @@ mod imp {
240242
#[inline]
241243
pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
242244
if align <= MIN_ALIGN {
243-
let ptr = libc::realloc(ptr as *mut libc::c_void, size as libc::size_t);
244-
if ptr.is_null() {
245-
::oom();
246-
}
247-
ptr as *mut u8
245+
libc_heap::realloc_raw(ptr, size)
248246
} else {
249247
let new_ptr = allocate(size, align);
250248
ptr::copy_memory(new_ptr, ptr as *const u8, cmp::min(size, old_size));
@@ -254,13 +252,13 @@ mod imp {
254252
}
255253

256254
#[inline]
257-
pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint,
258-
_align: uint) -> uint {
259-
old_size
255+
pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, size: uint,
256+
_align: uint) -> bool {
257+
size == old_size
260258
}
261259

262260
#[inline]
263-
pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, _align: uint) {
261+
pub unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) {
264262
libc::free(ptr as *mut libc::c_void)
265263
}
266264

@@ -276,6 +274,7 @@ mod imp {
276274
mod imp {
277275
use libc::{c_void, size_t};
278276
use libc;
277+
use libc_heap;
279278
use core::ptr::RawPtr;
280279
use super::MIN_ALIGN;
281280

@@ -289,11 +288,7 @@ mod imp {
289288
#[inline]
290289
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
291290
if align <= MIN_ALIGN {
292-
let ptr = libc::malloc(size as size_t);
293-
if ptr.is_null() {
294-
::oom();
295-
}
296-
ptr as *mut u8
291+
libc_heap::malloc_raw(size)
297292
} else {
298293
let ptr = _aligned_malloc(size as size_t, align as size_t);
299294
if ptr.is_null() {
@@ -306,11 +301,7 @@ mod imp {
306301
#[inline]
307302
pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 {
308303
if align <= MIN_ALIGN {
309-
let ptr = libc::realloc(ptr as *mut c_void, size as size_t);
310-
if ptr.is_null() {
311-
::oom();
312-
}
313-
ptr as *mut u8
304+
libc_heap::realloc_raw(ptr, size)
314305
} else {
315306
let ptr = _aligned_realloc(ptr as *mut c_void, size as size_t,
316307
align as size_t);
@@ -322,13 +313,13 @@ mod imp {
322313
}
323314

324315
#[inline]
325-
pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, _size: uint,
326-
_align: uint) -> uint {
327-
old_size
316+
pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: uint, size: uint,
317+
_align: uint) -> bool {
318+
size == old_size
328319
}
329320

330321
#[inline]
331-
pub unsafe fn deallocate(ptr: *mut u8, _old_size: uint, align: uint) {
322+
pub unsafe fn deallocate(ptr: *mut u8, _size: uint, align: uint) {
332323
if align <= MIN_ALIGN {
333324
libc::free(ptr as *mut libc::c_void)
334325
} else {
@@ -357,7 +348,7 @@ mod test {
357348
let ptr = heap::allocate(size, 8);
358349
let ret = heap::reallocate_inplace(ptr, size, size, 8);
359350
heap::deallocate(ptr, size, 8);
360-
assert_eq!(ret, heap::usable_size(size, 8));
351+
assert!(ret);
361352
}
362353
}
363354

branches/snap-stage3/src/liballoc/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,11 @@
5454
//!
5555
//! ## Heap interfaces
5656
//!
57-
//! The [`heap`](heap/index.html) module defines the low-level interface to the
58-
//! default global allocator. It is not compatible with the libc allocator API.
57+
//! The [`heap`](heap/index.html) and [`libc_heap`](libc_heap/index.html)
58+
//! modules are the unsafe interfaces to the underlying allocation systems. The
59+
//! `heap` module is considered the default heap, and is not necessarily backed
60+
//! by libc malloc/free. The `libc_heap` module is defined to be wired up to
61+
//! the system malloc/free.
5962
6063
#![crate_name = "alloc"]
6164
#![experimental]
@@ -87,6 +90,7 @@ pub use boxed as owned;
8790
// Heaps provided for low-level allocation strategies
8891

8992
pub mod heap;
93+
pub mod libc_heap;
9094

9195
// Primitive types using the heaps above
9296

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2012-2014 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+
11+
12+
//! The global (exchange) heap.
13+
14+
use libc::{c_void, size_t, free, malloc, realloc};
15+
use core::ptr::{RawPtr, null_mut};
16+
17+
/// A wrapper around libc::malloc, aborting on out-of-memory.
18+
#[inline]
19+
pub unsafe fn malloc_raw(size: uint) -> *mut u8 {
20+
// `malloc(0)` may allocate, but it may also return a null pointer
21+
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html
22+
if size == 0 {
23+
null_mut()
24+
} else {
25+
let p = malloc(size as size_t);
26+
if p.is_null() {
27+
::oom();
28+
}
29+
p as *mut u8
30+
}
31+
}
32+
33+
/// A wrapper around libc::realloc, aborting on out-of-memory.
34+
#[inline]
35+
pub unsafe fn realloc_raw(ptr: *mut u8, size: uint) -> *mut u8 {
36+
// `realloc(ptr, 0)` may allocate, but it may also return a null pointer
37+
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/realloc.html
38+
if size == 0 {
39+
free(ptr as *mut c_void);
40+
null_mut()
41+
} else {
42+
let p = realloc(ptr as *mut c_void, size as size_t);
43+
if p.is_null() {
44+
::oom();
45+
}
46+
p as *mut u8
47+
}
48+
}

branches/snap-stage3/src/libcore/cell.rs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -191,17 +191,6 @@ impl<T:Copy> Cell<T> {
191191
*self.value.get() = value;
192192
}
193193
}
194-
195-
/// Get a reference to the underlying `UnsafeCell`.
196-
///
197-
/// This can be used to circumvent `Cell`'s safety checks.
198-
///
199-
/// This function is `unsafe` because `UnsafeCell`'s field is public.
200-
#[inline]
201-
#[experimental]
202-
pub unsafe fn as_unsafe_cell<'a>(&'a self) -> &'a UnsafeCell<T> {
203-
&self.value
204-
}
205194
}
206195

207196
#[unstable = "waiting for `Clone` trait to become stable"]
@@ -317,17 +306,6 @@ impl<T> RefCell<T> {
317306
None => fail!("RefCell<T> already borrowed")
318307
}
319308
}
320-
321-
/// Get a reference to the underlying `UnsafeCell`.
322-
///
323-
/// This can be used to circumvent `RefCell`'s safety checks.
324-
///
325-
/// This function is `unsafe` because `UnsafeCell`'s field is public.
326-
#[inline]
327-
#[experimental]
328-
pub unsafe fn as_unsafe_cell<'a>(&'a self) -> &'a UnsafeCell<T> {
329-
&self.value
330-
}
331309
}
332310

333311
#[unstable = "waiting for `Clone` to become stable"]

0 commit comments

Comments
 (0)