@@ -429,13 +429,27 @@ int _mi_prim_commit(void* start, size_t size, bool* is_zero) {
429429 return err ;
430430}
431431
432+ int _mi_prim_reuse (void * start , size_t size ) {
433+ #if defined(__APPLE__ ) && defined(MADV_FREE_REUSE )
434+ return unix_madvise (start , size , MADV_FREE_REUSE );
435+ #endif
436+ return 0 ;
437+ }
438+
432439int _mi_prim_decommit (void * start , size_t size , bool * needs_recommit ) {
433440 int err = 0 ;
434- // decommit: use MADV_DONTNEED as it decreases rss immediately (unlike MADV_FREE)
435- err = unix_madvise (start , size , MADV_DONTNEED );
436441 #if !MI_DEBUG && MI_SECURE <=2
437442 * needs_recommit = false;
443+ #if defined(__APPLE__ ) && defined(MADV_FREE_REUSABLE )
444+ // decommit on macOS: use MADV_FREE_REUSABLE as it does immediate rss accounting (issue #1097)
445+ err = unix_madvise (start , size , MADV_FREE_REUSABLE );
446+ #else
447+ // decommit: use MADV_DONTNEED as it decreases rss immediately (unlike MADV_FREE)
448+ err = unix_madvise (start , size , MADV_DONTNEED );
449+ #endif
438450 #else
451+ // note: don't use MADV_FREE_REUSABLE as the range may contain protected areas
452+ err = unix_madvise (start , size , MADV_DONTNEED );
439453 * needs_recommit = true;
440454 mprotect (start , size , PROT_NONE );
441455 #endif
@@ -450,22 +464,29 @@ int _mi_prim_decommit(void* start, size_t size, bool* needs_recommit) {
450464}
451465
452466int _mi_prim_reset (void * start , size_t size ) {
453- // We try to use `MADV_FREE` as that is the fastest. A drawback though is that it
467+ int err = 0 ;
468+ #if defined(__APPLE__ ) && defined(MADV_FREE_REUSABLE )
469+ // on macOS we try to use MADV_FREE_REUSABLE as it seems the fastest
470+ err = unix_madvise (start , size , MADV_FREE_REUSABLE );
471+ if (err == 0 ) return 0 ;
472+ // fall through
473+ #endif
474+
475+ #if defined(MADV_FREE )
476+ // Otherwise, we try to use `MADV_FREE` as that is the fastest. A drawback though is that it
454477 // will not reduce the `rss` stats in tools like `top` even though the memory is available
455478 // to other processes. With the default `MIMALLOC_PURGE_DECOMMITS=1` we ensure that by
456479 // default `MADV_DONTNEED` is used though.
457- #if defined(MADV_FREE )
458480 static _Atomic (size_t ) advice = MI_ATOMIC_VAR_INIT (MADV_FREE );
459481 int oadvice = (int )mi_atomic_load_relaxed (& advice );
460- int err ;
461482 while ((err = unix_madvise (start , size , oadvice )) != 0 && errno == EAGAIN ) { errno = 0 ; };
462483 if (err != 0 && errno == EINVAL && oadvice == MADV_FREE ) {
463484 // if MADV_FREE is not supported, fall back to MADV_DONTNEED from now on
464485 mi_atomic_store_release (& advice , (size_t )MADV_DONTNEED );
465486 err = unix_madvise (start , size , MADV_DONTNEED );
466487 }
467488 #else
468- int err = unix_madvise (start , size , MADV_DONTNEED );
489+ err = unix_madvise (start , size , MADV_DONTNEED );
469490 #endif
470491 return err ;
471492}
0 commit comments