diff --git a/configure b/configure index 715f06023..8b9e9cddc 100755 --- a/configure +++ b/configure @@ -2997,7 +2997,6 @@ fi print_config "timerfd_create" "$timerfd_create" ############################################################################# - if test "$wordsize" = "64" ; then output_sym "CONFIG_64BIT" elif test "$wordsize" = "32" ; then diff --git a/helpers.c b/helpers.c index ab9d706da..03311fb08 100644 --- a/helpers.c +++ b/helpers.c @@ -26,9 +26,19 @@ int sync_file_range(int fd, uint64_t offset, uint64_t nbytes, } #endif +#if defined (__APPLE__) +int posix_fadvise(int fd, off_t offset, off_t len, int advice) +{ + if (advice == POSIX_FADV_DONTNEED) + return discard_pages(fd, offset, len); + errno = EINVAL; + return -1; +} +#else #ifndef CONFIG_POSIX_FADVISE int posix_fadvise(int fd, off_t offset, off_t len, int advice) { return 0; } #endif +#endif /* defined (__APPLE__) */ diff --git a/os/os-mac.h b/os/os-mac.h index c9103c45a..1d52b75a0 100644 --- a/os/os-mac.h +++ b/os/os-mac.h @@ -14,6 +14,11 @@ #include #include +#include +#include +#include + + #include "../arch/arch.h" #include "../file.h" @@ -117,3 +122,60 @@ static inline bool os_cpu_has(cpu_features feature) } #endif + +#if defined (__APPLE__) +/* + * discard_pages should not be run within Rosetta. Native arm64 or x86 only. + */ + +#define MMAP_CHUNK_SIZE (1024 * 1024 * 1024) + +static inline int discard_pages(int fd, off_t offset, off_t size) +{ + caddr_t *addr; + uint64_t chunk_size = MMAP_CHUNK_SIZE; + + if (fsync(fd) < 0) { + int __err = errno; + fprintf(stderr, "Cannot fsync file\n"); + errno = __err; + return -1; + } + + /* + * mmap the file in 1GB chunks and msync(MS_INVALIDATE). + */ + while (size > 0) { + uint64_t mmap_size = MIN(chunk_size, size); + + addr = mmap((caddr_t)0, mmap_size, PROT_NONE, MAP_SHARED, fd, offset); + if (addr == MAP_FAILED) { + int __map_errno = errno; + fprintf(stderr, "Failed to mmap (%s), offset = %llu, size = %llu\n", + strerror(errno), offset, mmap_size); + errno = __map_errno; + return -1; + } + + if (msync(addr, mmap_size, MS_INVALIDATE)) { + int __msync_errno = errno; + fprintf(stderr, "msync failed to free cache pages.\n"); + errno = __msync_errno; + return -1; + } + + /* Destroy the above mappings used to invalidate cache - cleaning up */ + if (munmap(addr, mmap_size) < 0) { + int __munmap_errno = errno; + fprintf(stderr, "munmap failed, error = %d.\n", errno); + errno = __munmap_errno; + return -1; + } + + size -= mmap_size; + offset += mmap_size; + } + + return 0; +} +#endif /* defined (__APPLE__) */