@@ -345,47 +345,94 @@ mod imp {
345
345
not( jemalloc) ,
346
346
windows) ) ]
347
347
mod imp {
348
- use libc:: { c_void, size_t} ;
349
- use libc;
348
+ use core:: mem:: size_of;
349
+ use libc:: { BOOL , DWORD , HANDLE , LPVOID , SIZE_T , INVALID_HANDLE_VALUE } ;
350
+ use libc:: { WriteFile } ;
350
351
use super :: MIN_ALIGN ;
351
352
352
- extern {
353
- fn _aligned_malloc ( size : size_t , align : size_t ) -> * mut c_void ;
354
- fn _aligned_realloc ( block : * mut c_void , size : size_t ,
355
- align : size_t ) -> * mut c_void ;
356
- fn _aligned_free ( ptr : * mut c_void ) ;
353
+ extern "system" {
354
+ fn GetProcessHeap ( ) -> HANDLE ;
355
+ fn GetStdHandle ( nStdHandle : DWORD ) -> HANDLE ;
356
+ fn HeapAlloc ( hHeap : HANDLE , dwFlags : DWORD , dwBytes : SIZE_T ) -> LPVOID ;
357
+ fn HeapReAlloc ( hHeap : HANDLE , dwFlags : DWORD , lpMem : LPVOID , dwBytes : SIZE_T ) -> LPVOID ;
358
+ fn HeapFree ( hHeap : HANDLE , dwFlags : DWORD , lpMem : LPVOID ) -> BOOL ;
359
+ fn HeapSummary ( hHeap : HANDLE , dwFlags : DWORD , lpSummary : LPHEAP_SUMMARY ) -> BOOL ;
360
+ }
361
+
362
+ #[ repr( C ) ] #[ allow( non_snake_case) ]
363
+ struct HEAP_SUMMARY {
364
+ cb : DWORD ,
365
+ cbAllocated : SIZE_T ,
366
+ cbCommitted : SIZE_T ,
367
+ cbReserved : SIZE_T ,
368
+ cbMaxReserve : SIZE_T ,
369
+ }
370
+ #[ allow( non_camel_case_types) ]
371
+ type LPHEAP_SUMMARY = * mut HEAP_SUMMARY ;
372
+
373
+ #[ repr( C ) ]
374
+ struct Header ( * mut u8 ) ;
375
+
376
+ const HEAP_REALLOC_IN_PLACE_ONLY : DWORD = 0x00000010 ;
377
+ const STD_OUTPUT_HANDLE : DWORD = -11i32 as u32 ;
378
+
379
+ #[ inline]
380
+ unsafe fn get_header < ' a > ( ptr : * mut u8 ) -> & ' a mut Header {
381
+ & mut * ( ptr as * mut Header ) . offset ( -1 )
382
+ }
383
+
384
+ #[ inline]
385
+ unsafe fn align_ptr ( ptr : * mut u8 , align : usize ) -> * mut u8 {
386
+ let aligned = ptr. offset ( ( align - ( ptr as usize & ( align - 1 ) ) ) as isize ) ;
387
+ * get_header ( aligned) = Header ( ptr) ;
388
+ aligned
357
389
}
358
390
359
391
#[ inline]
360
392
pub unsafe fn allocate ( size : usize , align : usize ) -> * mut u8 {
361
393
if align <= MIN_ALIGN {
362
- libc :: malloc ( size as size_t ) as * mut u8
394
+ HeapAlloc ( GetProcessHeap ( ) , 0 , size as SIZE_T ) as * mut u8
363
395
} else {
364
- _aligned_malloc ( size as size_t , align as size_t ) as * mut u8
396
+ let ptr = HeapAlloc ( GetProcessHeap ( ) , 0 , ( size + align) as SIZE_T ) as * mut u8 ;
397
+ if ptr. is_null ( ) { return ptr }
398
+ align_ptr ( ptr, align)
365
399
}
366
400
}
367
401
368
402
#[ inline]
369
403
pub unsafe fn reallocate ( ptr : * mut u8 , _old_size : usize , size : usize , align : usize ) -> * mut u8 {
370
404
if align <= MIN_ALIGN {
371
- libc :: realloc ( ptr as * mut c_void , size as size_t ) as * mut u8
405
+ HeapReAlloc ( GetProcessHeap ( ) , 0 , ptr as LPVOID , size as SIZE_T ) as * mut u8
372
406
} else {
373
- _aligned_realloc ( ptr as * mut c_void , size as size_t , align as size_t ) as * mut u8
407
+ let header = get_header ( ptr) ;
408
+ let new = HeapReAlloc ( GetProcessHeap ( ) , 0 , header. 0 as LPVOID ,
409
+ ( size + align) as SIZE_T ) as * mut u8 ;
410
+ if new. is_null ( ) { return new }
411
+ align_ptr ( new, align)
374
412
}
375
413
}
376
414
377
415
#[ inline]
378
- pub unsafe fn reallocate_inplace ( _ptr : * mut u8 , old_size : usize , _size : usize ,
379
- _align : usize ) -> usize {
380
- old_size
416
+ pub unsafe fn reallocate_inplace ( ptr : * mut u8 , old_size : usize , size : usize ,
417
+ align : usize ) -> usize {
418
+ if align <= MIN_ALIGN {
419
+ let new = HeapReAlloc ( GetProcessHeap ( ) , HEAP_REALLOC_IN_PLACE_ONLY , ptr as LPVOID ,
420
+ size as SIZE_T ) as * mut u8 ;
421
+ if new. is_null ( ) { old_size } else { size }
422
+ } else {
423
+ old_size
424
+ }
381
425
}
382
426
383
427
#[ inline]
384
428
pub unsafe fn deallocate ( ptr : * mut u8 , _old_size : usize , align : usize ) {
385
429
if align <= MIN_ALIGN {
386
- libc:: free ( ptr as * mut libc:: c_void )
430
+ let err = HeapFree ( GetProcessHeap ( ) , 0 , ptr as LPVOID ) ;
431
+ debug_assert ! ( err != 0 ) ;
387
432
} else {
388
- _aligned_free ( ptr as * mut c_void )
433
+ let header = get_header ( ptr) ;
434
+ let err = HeapFree ( GetProcessHeap ( ) , 0 , header. 0 as LPVOID ) ;
435
+ debug_assert ! ( err != 0 ) ;
389
436
}
390
437
}
391
438
@@ -394,7 +441,45 @@ mod imp {
394
441
size
395
442
}
396
443
397
- pub fn stats_print ( ) { }
444
+ pub fn stats_print ( ) {
445
+ use core:: fmt:: { Error , Result , Write } ;
446
+ use core:: ptr:: null_mut;
447
+ use core:: raw:: Repr ;
448
+ use core:: result:: Result :: { Ok , Err } ;
449
+ struct Console ( HANDLE ) ;
450
+ impl Write for Console {
451
+ fn write_str ( & mut self , s : & str ) -> Result {
452
+ let repr = s. repr ( ) ;
453
+ let mut written = 0 ;
454
+ let err = unsafe { WriteFile ( self . 0 , repr. data as LPVOID , repr. len as DWORD ,
455
+ & mut written, null_mut ( ) ) } ;
456
+ if written as usize != repr. len { return Err ( Error ) }
457
+ if err == 0 { return Err ( Error ) }
458
+ Ok ( ( ) )
459
+ }
460
+ }
461
+ let mut hs = HEAP_SUMMARY {
462
+ cb : size_of :: < HEAP_SUMMARY > ( ) as DWORD ,
463
+ cbAllocated : 0 ,
464
+ cbCommitted : 0 ,
465
+ cbReserved : 0 ,
466
+ cbMaxReserve : 0 ,
467
+ } ;
468
+ let err = unsafe { HeapSummary ( GetProcessHeap ( ) , 0 , & mut hs) } ;
469
+ assert ! ( err != 0 ) ;
470
+ let handle = unsafe { GetStdHandle ( STD_OUTPUT_HANDLE ) } ;
471
+ if handle. is_null ( ) || handle == INVALID_HANDLE_VALUE { panic ! ( "Failed to open stdout" ) }
472
+ let mut out = Console ( handle) ;
473
+ writeln ! ( & mut out, "Allocated: {}" , hs. cbAllocated) . unwrap ( ) ;
474
+ writeln ! ( & mut out, "Committed: {}" , hs. cbCommitted) . unwrap ( ) ;
475
+ writeln ! ( & mut out, "Reserved: {}" , hs. cbReserved) . unwrap ( ) ;
476
+ writeln ! ( & mut out, "MaxReserve: {}" , hs. cbMaxReserve) . unwrap ( ) ;
477
+ }
478
+
479
+ #[ test]
480
+ fn alignment_header_size ( ) {
481
+ assert ! ( size_of:: <Header >( ) <= MIN_ALIGN ) ;
482
+ }
398
483
}
399
484
400
485
#[ cfg( test) ]
0 commit comments