Commit/Decommit memory. Usually commit is aligned liberal, while decommit is aligned conservative. (but not for the reset version where we want commit to be conservative as well)
| 925 | // Usually commit is aligned liberal, while decommit is aligned conservative. |
| 926 | // (but not for the reset version where we want commit to be conservative as well) |
| 927 | static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservative, bool* is_zero, mi_stats_t* stats) { |
| 928 | // page align in the range, commit liberally, decommit conservative |
| 929 | if (is_zero != NULL) { *is_zero = false; } |
| 930 | size_t csize; |
| 931 | void* start = mi_os_page_align_areax(conservative, addr, size, &csize); |
| 932 | if (csize == 0) return true; // || _mi_os_is_huge_reserved(addr)) |
| 933 | int err = 0; |
| 934 | if (commit) { |
| 935 | _mi_stat_increase(&stats->committed, size); // use size for precise commit vs. decommit |
| 936 | _mi_stat_counter_increase(&stats->commit_calls, 1); |
| 937 | } |
| 938 | else { |
| 939 | _mi_stat_decrease(&stats->committed, size); |
| 940 | } |
| 941 | |
| 942 | #if defined(_WIN32) |
| 943 | if (commit) { |
| 944 | // *is_zero = true; // note: if the memory was already committed, the call succeeds but the memory is not zero'd |
| 945 | void* p = VirtualAlloc(start, csize, MEM_COMMIT, PAGE_READWRITE); |
| 946 | err = (p == start ? 0 : GetLastError()); |
| 947 | } |
| 948 | else { |
| 949 | BOOL ok = VirtualFree(start, csize, MEM_DECOMMIT); |
| 950 | err = (ok ? 0 : GetLastError()); |
| 951 | } |
| 952 | #elif defined(__wasi__) |
| 953 | // WebAssembly guests can't control memory protection |
| 954 | #elif 0 && defined(MAP_FIXED) && !defined(__APPLE__) |
| 955 | // Linux: disabled for now as mmap fixed seems much more expensive than MADV_DONTNEED (and splits VMA's?) |
| 956 | if (commit) { |
| 957 | // commit: just change the protection |
| 958 | err = mprotect(start, csize, (PROT_READ | PROT_WRITE)); |
| 959 | if (err != 0) { err = errno; } |
| 960 | } |
| 961 | else { |
| 962 | // decommit: use mmap with MAP_FIXED to discard the existing memory (and reduce rss) |
| 963 | const int fd = mi_unix_mmap_fd(); |
| 964 | void* p = mmap(start, csize, PROT_NONE, (MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE), fd, 0); |
| 965 | if (p != start) { err = errno; } |
| 966 | } |
| 967 | #else |
| 968 | // Linux, macOSX and others. |
| 969 | if (commit) { |
| 970 | // commit: ensure we can access the area |
| 971 | err = mprotect(start, csize, (PROT_READ | PROT_WRITE)); |
| 972 | if (err != 0) { err = errno; } |
| 973 | } |
| 974 | else { |
| 975 | #if defined(MADV_DONTNEED) && MI_DEBUG == 0 && MI_SECURE == 0 |
| 976 | // decommit: use MADV_DONTNEED as it decreases rss immediately (unlike MADV_FREE) |
| 977 | // (on the other hand, MADV_FREE would be good enough.. it is just not reflected in the stats :-( ) |
| 978 | err = madvise(start, csize, MADV_DONTNEED); |
| 979 | #else |
| 980 | // decommit: just disable access (also used in debug and secure mode to trap on illegal access) |
| 981 | err = mprotect(start, csize, PROT_NONE); |
| 982 | if (err != 0) { err = errno; } |
| 983 | #endif |
| 984 | //#if defined(MADV_FREE_REUSE) |
no test coverage detected