@@ -35,12 +35,7 @@ impl MachineAlloc {
35
35
/// allow this function to be `const`; it is updated to its real value on
36
36
/// the first call to `alloc()` or `alloc_zeroed()`.
37
37
const fn empty ( ) -> Self {
38
- Self {
39
- pages : Vec :: new ( ) ,
40
- huge_allocs : Vec :: new ( ) ,
41
- allocated : Vec :: new ( ) ,
42
- page_size : 0 ,
43
- }
38
+ Self { pages : Vec :: new ( ) , huge_allocs : Vec :: new ( ) , allocated : Vec :: new ( ) , page_size : 0 }
44
39
}
45
40
46
41
/// Expands the available memory pool by adding one page.
@@ -68,9 +63,7 @@ impl MachineAlloc {
68
63
#[ inline]
69
64
pub unsafe fn alloc ( layout : Layout ) -> * mut u8 {
70
65
let mut alloc = ALLOCATOR . lock ( ) . unwrap ( ) ;
71
- unsafe {
72
- alloc. alloc_inner ( layout, false )
73
- }
66
+ unsafe { alloc. alloc_inner ( layout, false ) }
74
67
}
75
68
76
69
/// Same as `alloc()`, but zeroes out data before allocating.
@@ -199,3 +192,90 @@ impl MachineAlloc {
199
192
}
200
193
}
201
194
}
195
+
196
+ #[ cfg( test) ]
197
+ mod tests {
198
+ use super :: * ;
199
+
200
+ fn assert_zeroes ( ptr : * mut u8 , layout : Layout ) {
201
+ unsafe {
202
+ for ofs in 0 ..layout. size ( ) {
203
+ assert_eq ! ( 0 , ptr. offset( ofs as isize ) . read( ) ) ;
204
+ }
205
+ }
206
+ }
207
+
208
+ #[ test]
209
+ fn small_zeroes ( ) {
210
+ let layout = Layout :: from_size_align ( 256 , 32 ) . unwrap ( ) ;
211
+ let ptr = unsafe { MachineAlloc :: alloc_zeroed ( layout) } ;
212
+ assert_zeroes ( ptr, layout) ;
213
+ unsafe {
214
+ MachineAlloc :: dealloc ( ptr, layout) ;
215
+ }
216
+ }
217
+
218
+ #[ test]
219
+ fn big_zeroes ( ) {
220
+ let layout = Layout :: from_size_align ( 16 * 1024 , 128 ) . unwrap ( ) ;
221
+ let ptr = unsafe { MachineAlloc :: alloc_zeroed ( layout) } ;
222
+ assert_zeroes ( ptr, layout) ;
223
+ unsafe {
224
+ MachineAlloc :: dealloc ( ptr, layout) ;
225
+ }
226
+ }
227
+
228
+ #[ test]
229
+ fn repeated_allocs ( ) {
230
+ for sz in ( 1 ..=( 16 * 1024 ) ) . step_by ( 128 ) {
231
+ let layout = Layout :: from_size_align ( sz, 1 ) . unwrap ( ) ;
232
+ let ptr = unsafe { MachineAlloc :: alloc_zeroed ( layout) } ;
233
+ assert_zeroes ( ptr, layout) ;
234
+ unsafe {
235
+ ptr. write_bytes ( 255 , sz) ;
236
+ MachineAlloc :: dealloc ( ptr, layout) ;
237
+ }
238
+ }
239
+ }
240
+
241
+ #[ test]
242
+ fn no_overlaps ( ) {
243
+ // Some random sizes and aligns
244
+ let mut sizes = vec ! [ 32 ; 10 ] ;
245
+ sizes. append ( & mut vec ! [ 15 ; 4 ] ) ;
246
+ sizes. append ( & mut vec ! [ 256 ; 12 ] ) ;
247
+
248
+ let mut aligns = vec ! [ 16 ; 12 ] ;
249
+ aligns. append ( & mut vec ! [ 256 ; 2 ] ) ;
250
+ aligns. append ( & mut vec ! [ 64 ; 12 ] ) ;
251
+
252
+ assert_eq ! ( sizes. len( ) , aligns. len( ) ) ;
253
+ let layouts: Vec < _ > = std:: iter:: zip ( sizes, aligns)
254
+ . map ( |( sz, al) | Layout :: from_size_align ( sz, al) . unwrap ( ) )
255
+ . collect ( ) ;
256
+ let ptrs: Vec < _ > = layouts. iter ( ) . map ( |layout| unsafe { MachineAlloc :: alloc_zeroed ( * layout) } ) . collect ( ) ;
257
+
258
+ for ( & ptr, & layout) in std:: iter:: zip ( & ptrs, & layouts) {
259
+ // Make sure we don't allocate overlapping ranges
260
+ unsafe {
261
+ assert_zeroes ( ptr, layout) ;
262
+ ptr. write_bytes ( 255 , layout. size ( ) ) ;
263
+ MachineAlloc :: dealloc ( ptr, layout) ;
264
+ }
265
+ }
266
+ }
267
+
268
+ #[ test]
269
+ fn check_leaks ( ) {
270
+ // In case this test gets run on its own, make sure to generate some
271
+ // noise in the allocator.
272
+ no_overlaps ( ) ;
273
+
274
+ let alloc = ALLOCATOR . lock ( ) . unwrap ( ) ;
275
+ for pinfo in & alloc. allocated {
276
+ for eight_bytes in 0 ..pinfo. len ( ) {
277
+ assert_eq ! ( eight_bytes, 0 ) ;
278
+ }
279
+ }
280
+ }
281
+ }
0 commit comments