@@ -35,12 +35,7 @@ impl MachineAlloc {
3535 /// allow this function to be `const`; it is updated to its real value on
3636 /// the first call to `alloc()` or `alloc_zeroed()`.
3737 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 }
4439 }
4540
4641 /// Expands the available memory pool by adding one page.
@@ -68,9 +63,7 @@ impl MachineAlloc {
6863 #[ inline]
6964 pub unsafe fn alloc ( layout : Layout ) -> * mut u8 {
7065 let mut alloc = ALLOCATOR . lock ( ) . unwrap ( ) ;
71- unsafe {
72- alloc. alloc_inner ( layout, false )
73- }
66+ unsafe { alloc. alloc_inner ( layout, false ) }
7467 }
7568
7669 /// Same as `alloc()`, but zeroes out data before allocating.
@@ -199,3 +192,90 @@ impl MachineAlloc {
199192 }
200193 }
201194}
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