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} ;
1512use 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
6221fn 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}
0 commit comments