@@ -433,13 +433,27 @@ int _mi_prim_commit(void* start, size_t size, bool* is_zero) {
433
433
return err ;
434
434
}
435
435
436
+ int _mi_prim_reuse (void * start , size_t size ) {
437
+ #if defined(__APPLE__ ) && defined(MADV_FREE_REUSE )
438
+ return unix_madvise (start , size , MADV_FREE_REUSE );
439
+ #endif
440
+ return 0 ;
441
+ }
442
+
436
443
int _mi_prim_decommit (void * start , size_t size , bool * needs_recommit ) {
437
444
int err = 0 ;
438
- // decommit: use MADV_DONTNEED as it decreases rss immediately (unlike MADV_FREE)
439
- err = unix_madvise (start , size , MADV_DONTNEED );
440
445
#if !MI_DEBUG && MI_SECURE <=2
441
446
* needs_recommit = false;
447
+ #if defined(__APPLE__ ) && defined(MADV_FREE_REUSABLE )
448
+ // decommit on macOS: use MADV_FREE_REUSABLE as it does immediate rss accounting (issue #1097)
449
+ err = unix_madvise (start , size , MADV_FREE_REUSABLE );
450
+ #else
451
+ // decommit: use MADV_DONTNEED as it decreases rss immediately (unlike MADV_FREE)
452
+ err = unix_madvise (start , size , MADV_DONTNEED );
453
+ #endif
442
454
#else
455
+ // note: don't use MADV_FREE_REUSABLE as the range may contain protected areas
456
+ err = unix_madvise (start , size , MADV_DONTNEED );
443
457
* needs_recommit = true;
444
458
mprotect (start , size , PROT_NONE );
445
459
#endif
@@ -454,22 +468,29 @@ int _mi_prim_decommit(void* start, size_t size, bool* needs_recommit) {
454
468
}
455
469
456
470
int _mi_prim_reset (void * start , size_t size ) {
457
- // We try to use `MADV_FREE` as that is the fastest. A drawback though is that it
471
+ int err = 0 ;
472
+ #if defined(__APPLE__ ) && defined(MADV_FREE_REUSABLE )
473
+ // on macOS we try to use MADV_FREE_REUSABLE as it seems the fastest
474
+ err = unix_madvise (start , size , MADV_FREE_REUSABLE );
475
+ if (err == 0 ) return 0 ;
476
+ // fall through
477
+ #endif
478
+
479
+ #if defined(MADV_FREE )
480
+ // Otherwise, we try to use `MADV_FREE` as that is the fastest. A drawback though is that it
458
481
// will not reduce the `rss` stats in tools like `top` even though the memory is available
459
482
// to other processes. With the default `MIMALLOC_PURGE_DECOMMITS=1` we ensure that by
460
483
// default `MADV_DONTNEED` is used though.
461
- #if defined(MADV_FREE )
462
484
static _Atomic (size_t ) advice = MI_ATOMIC_VAR_INIT (MADV_FREE );
463
485
int oadvice = (int )mi_atomic_load_relaxed (& advice );
464
- int err ;
465
486
while ((err = unix_madvise (start , size , oadvice )) != 0 && errno == EAGAIN ) { errno = 0 ; };
466
487
if (err != 0 && errno == EINVAL && oadvice == MADV_FREE ) {
467
488
// if MADV_FREE is not supported, fall back to MADV_DONTNEED from now on
468
489
mi_atomic_store_release (& advice , (size_t )MADV_DONTNEED );
469
490
err = unix_madvise (start , size , MADV_DONTNEED );
470
491
}
471
492
#else
472
- int err = unix_madvise (start , size , MADV_DONTNEED );
493
+ err = unix_madvise (start , size , MADV_DONTNEED );
473
494
#endif
474
495
return err ;
475
496
}
0 commit comments