@@ -7,9 +7,9 @@ use core::cmp;
77use core:: mem;
88use core:: ptr;
99
10- use sys ;
10+ use Allocator ;
1111
12- pub struct Dlmalloc {
12+ pub struct Dlmalloc < A > {
1313 smallmap : u32 ,
1414 treemap : u32 ,
1515 smallbins : [ * mut Chunk ; ( NSMALLBINS + 1 ) * 2 ] ,
@@ -24,31 +24,9 @@ pub struct Dlmalloc {
2424 trim_check : usize ,
2525 least_addr : * mut u8 ,
2626 release_checks : usize ,
27+ system_allocator : A ,
2728}
28-
29- unsafe impl Send for Dlmalloc { }
30-
31- pub const DLMALLOC_INIT : Dlmalloc = Dlmalloc {
32- smallmap : 0 ,
33- treemap : 0 ,
34- smallbins : [ 0 as * mut _ ; ( NSMALLBINS + 1 ) * 2 ] ,
35- treebins : [ 0 as * mut _ ; NTREEBINS ] ,
36- dvsize : 0 ,
37- topsize : 0 ,
38- dv : 0 as * mut _ ,
39- top : 0 as * mut _ ,
40- footprint : 0 ,
41- max_footprint : 0 ,
42- seg : Segment {
43- base : 0 as * mut _ ,
44- size : 0 ,
45- next : 0 as * mut _ ,
46- flags : 0 ,
47- } ,
48- trim_check : 0 ,
49- least_addr : 0 as * mut _ ,
50- release_checks : 0 ,
51- } ;
29+ unsafe impl < A : Send > Send for Dlmalloc < A > { }
5230
5331// TODO: document this
5432const NSMALLBINS : usize = 32 ;
@@ -108,7 +86,34 @@ fn leftshift_for_tree_index(x: u32) -> u32 {
10886 }
10987}
11088
111- impl Dlmalloc {
89+ impl < A > Dlmalloc < A > {
90+ pub const fn new ( system_allocator : A ) -> Dlmalloc < A > {
91+ Dlmalloc {
92+ smallmap : 0 ,
93+ treemap : 0 ,
94+ smallbins : [ 0 as * mut _ ; ( NSMALLBINS + 1 ) * 2 ] ,
95+ treebins : [ 0 as * mut _ ; NTREEBINS ] ,
96+ dvsize : 0 ,
97+ topsize : 0 ,
98+ dv : 0 as * mut _ ,
99+ top : 0 as * mut _ ,
100+ footprint : 0 ,
101+ max_footprint : 0 ,
102+ seg : Segment {
103+ base : 0 as * mut _ ,
104+ size : 0 ,
105+ next : 0 as * mut _ ,
106+ flags : 0 ,
107+ } ,
108+ trim_check : 0 ,
109+ least_addr : 0 as * mut _ ,
110+ release_checks : 0 ,
111+ system_allocator,
112+ }
113+ }
114+ }
115+
116+ impl < A : Allocator > Dlmalloc < A > {
112117 // TODO: can we get rid of this?
113118 pub fn malloc_alignment ( & self ) -> usize {
114119 mem:: size_of :: < usize > ( ) * 2
@@ -225,7 +230,7 @@ impl Dlmalloc {
225230 }
226231
227232 pub unsafe fn calloc_must_clear ( & self , ptr : * mut u8 ) -> bool {
228- !sys :: allocates_zeros ( ) || !Chunk :: mmapped ( Chunk :: from_mem ( ptr) )
233+ !self . system_allocator . allocates_zeros ( ) || !Chunk :: mmapped ( Chunk :: from_mem ( ptr) )
229234 }
230235
231236 pub unsafe fn malloc ( & mut self , size : usize ) -> * mut u8 {
@@ -344,6 +349,7 @@ impl Dlmalloc {
344349 self . sys_alloc ( nb)
345350 }
346351
352+ /// allocates system resources
347353 unsafe fn sys_alloc ( & mut self , size : usize ) -> * mut u8 {
348354 self . check_malloc_state ( ) ;
349355 // keep in sync with max_request
@@ -352,7 +358,7 @@ impl Dlmalloc {
352358 DEFAULT_GRANULARITY ,
353359 ) ;
354360
355- let ( tbase, tsize, flags) = sys :: alloc ( asize) ;
361+ let ( tbase, tsize, flags) = self . system_allocator . alloc ( asize) ;
356362 if tbase. is_null ( ) {
357363 return tbase;
358364 }
@@ -533,7 +539,7 @@ impl Dlmalloc {
533539 let oldmmsize = oldsize + offset + self . mmap_foot_pad ( ) ;
534540 let newmmsize =
535541 self . mmap_align ( nb + 6 * mem:: size_of :: < usize > ( ) + self . malloc_alignment ( ) - 1 ) ;
536- let ptr = sys :: remap (
542+ let ptr = self . system_allocator . remap (
537543 ( oldp as * mut u8 ) . offset ( -( offset as isize ) ) ,
538544 oldmmsize,
539545 newmmsize,
@@ -555,7 +561,7 @@ impl Dlmalloc {
555561 }
556562
557563 fn mmap_align ( & self , a : usize ) -> usize {
558- align_up ( a, sys :: page_size ( ) )
564+ align_up ( a, self . system_allocator . page_size ( ) )
559565 }
560566
561567 // Only call this with power-of-two alignment and alignment >
@@ -631,7 +637,10 @@ impl Dlmalloc {
631637 let prevsize = ( * p) . prev_foot ;
632638 if Chunk :: mmapped ( p) {
633639 psize += prevsize + self . mmap_foot_pad ( ) ;
634- if sys:: free ( ( p as * mut u8 ) . offset ( -( prevsize as isize ) ) , psize) {
640+ if self
641+ . system_allocator
642+ . free ( ( p as * mut u8 ) . offset ( -( prevsize as isize ) ) , psize)
643+ {
635644 self . footprint -= psize;
636645 }
637646 return ;
@@ -1161,7 +1170,10 @@ impl Dlmalloc {
11611170
11621171 if Chunk :: mmapped ( p) {
11631172 psize += prevsize + self . mmap_foot_pad ( ) ;
1164- if sys:: free ( ( p as * mut u8 ) . offset ( -( prevsize as isize ) ) , psize) {
1173+ if self
1174+ . system_allocator
1175+ . free ( ( p as * mut u8 ) . offset ( -( prevsize as isize ) ) , psize)
1176+ {
11651177 self . footprint -= psize;
11661178 }
11671179 return ;
@@ -1242,10 +1254,13 @@ impl Dlmalloc {
12421254 debug_assert ! ( !sp. is_null( ) ) ;
12431255
12441256 if !Segment :: is_extern ( sp) {
1245- if Segment :: can_release_part ( sp) {
1257+ if Segment :: can_release_part ( & self . system_allocator , sp) {
12461258 if ( * sp) . size >= extra && !self . has_segment_link ( sp) {
12471259 let newsize = ( * sp) . size - extra;
1248- if sys:: free_part ( ( * sp) . base , ( * sp) . size , newsize) {
1260+ if self
1261+ . system_allocator
1262+ . free_part ( ( * sp) . base , ( * sp) . size , newsize)
1263+ {
12491264 released = extra;
12501265 }
12511266 }
@@ -1295,7 +1310,7 @@ impl Dlmalloc {
12951310 let next = ( * sp) . next ;
12961311 nsegs += 1 ;
12971312
1298- if Segment :: can_release_part ( sp) && !Segment :: is_extern ( sp) {
1313+ if Segment :: can_release_part ( & self . system_allocator , sp) && !Segment :: is_extern ( sp) {
12991314 let p = self . align_as_chunk ( base) ;
13001315 let psize = Chunk :: size ( p) ;
13011316 // We can unmap if the first chunk holds the entire segment and
@@ -1311,7 +1326,7 @@ impl Dlmalloc {
13111326 } else {
13121327 self . unlink_large_chunk ( tp) ;
13131328 }
1314- if sys :: free ( base, size) {
1329+ if self . system_allocator . free ( base, size) {
13151330 released += size;
13161331 self . footprint -= size;
13171332 // unlink our obsolete record
@@ -1405,7 +1420,7 @@ impl Dlmalloc {
14051420 ) ;
14061421 debug_assert ! ( p as * mut u8 >= self . least_addr) ;
14071422 debug_assert ! ( !self . is_small( sz) ) ;
1408- debug_assert_eq ! ( align_up( len, sys :: page_size( ) ) , len) ;
1423+ debug_assert_eq ! ( align_up( len, self . system_allocator . page_size( ) ) , len) ;
14091424 debug_assert_eq ! ( ( * Chunk :: plus_offset( p, sz) ) . head, Chunk :: fencepost_head( ) ) ;
14101425 debug_assert_eq ! (
14111426 ( * Chunk :: plus_offset( p, sz + mem:: size_of:: <usize >( ) ) ) . head,
@@ -1746,8 +1761,8 @@ impl Segment {
17461761 ( * seg) . flags & EXTERN != 0
17471762 }
17481763
1749- unsafe fn can_release_part ( seg : * mut Segment ) -> bool {
1750- sys :: can_release_part ( ( * seg) . flags >> 1 )
1764+ unsafe fn can_release_part < A : Allocator > ( system_allocator : & A , seg : * mut Segment ) -> bool {
1765+ system_allocator . can_release_part ( ( * seg) . flags >> 1 )
17511766 }
17521767
17531768 unsafe fn sys_flags ( seg : * mut Segment ) -> u32 {
@@ -1766,10 +1781,11 @@ impl Segment {
17661781#[ cfg( test) ]
17671782mod tests {
17681783 use super :: * ;
1784+ use System ;
17691785
17701786 // Prime the allocator with some allocations such that there will be free
17711787 // chunks in the treemap
1772- unsafe fn setup_treemap ( a : & mut Dlmalloc ) {
1788+ unsafe fn setup_treemap < A : Allocator > ( a : & mut Dlmalloc < A > ) {
17731789 let large_request_size = NSMALLBINS * ( 1 << SMALLBIN_SHIFT ) ;
17741790 assert ! ( !a. is_small( large_request_size) ) ;
17751791 let large_request1 = a. malloc ( large_request_size) ;
@@ -1784,7 +1800,7 @@ mod tests {
17841800 // Test allocating, with a non-empty treemap, a specific size that used to
17851801 // trigger an integer overflow bug
17861802 fn treemap_alloc_overflow_minimal ( ) {
1787- let mut a = DLMALLOC_INIT ;
1803+ let mut a = Dlmalloc :: new ( System :: new ( ) ) ;
17881804 unsafe {
17891805 setup_treemap ( & mut a) ;
17901806 let min_idx31_size = ( 0xc000 << TREEBIN_SHIFT ) - a. chunk_overhead ( ) + 1 ;
@@ -1795,7 +1811,7 @@ mod tests {
17951811 #[ test]
17961812 // Test allocating the maximum request size with a non-empty treemap
17971813 fn treemap_alloc_max ( ) {
1798- let mut a = DLMALLOC_INIT ;
1814+ let mut a = Dlmalloc :: new ( System :: new ( ) ) ;
17991815 unsafe {
18001816 setup_treemap ( & mut a) ;
18011817 let max_request_size = a. max_request ( ) - 1 ;
0 commit comments