@@ -14,6 +14,7 @@ extern crate alloc;
14
14
use alloc:: alloc:: Layout ;
15
15
#[ cfg( feature = "alloc_ref" ) ]
16
16
use alloc:: alloc:: { AllocErr , AllocInit , AllocRef , MemoryBlock } ;
17
+ #[ cfg( feature = "use_spin" ) ]
17
18
use core:: alloc:: GlobalAlloc ;
18
19
use core:: mem;
19
20
#[ cfg( feature = "use_spin" ) ]
@@ -31,6 +32,7 @@ mod test;
31
32
pub struct Heap {
32
33
bottom : usize ,
33
34
size : usize ,
35
+ used : usize ,
34
36
holes : HoleList ,
35
37
}
36
38
@@ -40,6 +42,7 @@ impl Heap {
40
42
Heap {
41
43
bottom : 0 ,
42
44
size : 0 ,
45
+ used : 0 ,
43
46
holes : HoleList :: empty ( ) ,
44
47
}
45
48
}
@@ -53,6 +56,7 @@ impl Heap {
53
56
pub unsafe fn init ( & mut self , heap_bottom : usize , heap_size : usize ) {
54
57
self . bottom = heap_bottom;
55
58
self . size = heap_size;
59
+ self . used = 0 ;
56
60
self . holes = HoleList :: new ( heap_bottom, heap_size) ;
57
61
}
58
62
@@ -67,25 +71,37 @@ impl Heap {
67
71
Heap {
68
72
bottom : heap_bottom,
69
73
size : heap_size,
74
+ used : 0 ,
70
75
holes : HoleList :: new ( heap_bottom, heap_size) ,
71
76
}
72
77
}
73
78
}
74
79
75
- /// Allocates a chunk of the given size with the given alignment. Returns a pointer to the
76
- /// beginning of that chunk if it was successful. Else it returns `None`.
77
- /// This function scans the list of free memory blocks and uses the first block that is big
78
- /// enough. The runtime is in O(n) where n is the number of free blocks, but it should be
79
- /// reasonably fast for small allocations.
80
- pub fn allocate_first_fit ( & mut self , layout : Layout ) -> Result < NonNull < u8 > , ( ) > {
80
+ /// Align layout. Returns a layout with size increased to
81
+ /// fit at least `HoleList::min_size` and proper alignment of a `Hole`.
82
+ fn align_layout ( layout : Layout ) -> Layout {
81
83
let mut size = layout. size ( ) ;
82
84
if size < HoleList :: min_size ( ) {
83
85
size = HoleList :: min_size ( ) ;
84
86
}
85
87
let size = align_up ( size, mem:: align_of :: < Hole > ( ) ) ;
86
88
let layout = Layout :: from_size_align ( size, layout. align ( ) ) . unwrap ( ) ;
87
89
88
- self . holes . allocate_first_fit ( layout)
90
+ layout
91
+ }
92
+
93
+ /// Allocates a chunk of the given size with the given alignment. Returns a pointer to the
94
+ /// beginning of that chunk if it was successful. Else it returns `None`.
95
+ /// This function scans the list of free memory blocks and uses the first block that is big
96
+ /// enough. The runtime is in O(n) where n is the number of free blocks, but it should be
97
+ /// reasonably fast for small allocations.
98
+ pub fn allocate_first_fit ( & mut self , layout : Layout ) -> Result < NonNull < u8 > , ( ) > {
99
+ let aligned_layout = Self :: align_layout ( layout) ;
100
+ let res = self . holes . allocate_first_fit ( aligned_layout) ;
101
+ if res. is_ok ( ) {
102
+ self . used += aligned_layout. size ( ) ;
103
+ }
104
+ res
89
105
}
90
106
91
107
/// Frees the given allocation. `ptr` must be a pointer returned
@@ -96,14 +112,9 @@ impl Heap {
96
112
/// correct place. If the freed block is adjacent to another free block, the blocks are merged
97
113
/// again. This operation is in `O(n)` since the list needs to be sorted by address.
98
114
pub unsafe fn deallocate ( & mut self , ptr : NonNull < u8 > , layout : Layout ) {
99
- let mut size = layout. size ( ) ;
100
- if size < HoleList :: min_size ( ) {
101
- size = HoleList :: min_size ( ) ;
102
- }
103
- let size = align_up ( size, mem:: align_of :: < Hole > ( ) ) ;
104
- let layout = Layout :: from_size_align ( size, layout. align ( ) ) . unwrap ( ) ;
105
-
106
- self . holes . deallocate ( ptr, layout) ;
115
+ let aligned_layout = Self :: align_layout ( layout) ;
116
+ self . holes . deallocate ( ptr, aligned_layout) ;
117
+ self . used -= aligned_layout. size ( ) ;
107
118
}
108
119
109
120
/// Returns the bottom address of the heap.
@@ -121,6 +132,16 @@ impl Heap {
121
132
self . bottom + self . size
122
133
}
123
134
135
+ /// Returns the size of the used part of the heap
136
+ pub fn used ( & self ) -> usize {
137
+ self . used
138
+ }
139
+
140
+ /// Returns the size of the free part of the heap
141
+ pub fn free ( & self ) -> usize {
142
+ self . size - self . used
143
+ }
144
+
124
145
/// Extends the size of the heap by creating a new hole at the end
125
146
///
126
147
/// # Unsafety
@@ -182,6 +203,7 @@ impl LockedHeap {
182
203
LockedHeap ( Spinlock :: new ( Heap {
183
204
bottom : heap_bottom,
184
205
size : heap_size,
206
+ used : 0 ,
185
207
holes : HoleList :: new ( heap_bottom, heap_size) ,
186
208
} ) )
187
209
}
0 commit comments