diff --git a/Makefile b/Makefile index f79c905bdcbf8f..058bc83753a573 100644 --- a/Makefile +++ b/Makefile @@ -1654,6 +1654,7 @@ ifeq ($(uname_S),Darwin) COMPAT_CFLAGS += -DAPPLE_COMMON_CRYPTO endif PTHREAD_LIBS = + COMPAT_OBJS += compat/osxmmap.o endif ifdef NO_LIBGEN_H diff --git a/compat/osxmmap.c b/compat/osxmmap.c new file mode 100644 index 00000000000000..5f9cf633caf485 --- /dev/null +++ b/compat/osxmmap.c @@ -0,0 +1,49 @@ +#include +#include "../git-compat-util.h" +/* We need original mmap/munmap here. */ +#undef mmap +#undef munmap + +/* + * OSX doesn't have any specific setting like Linux's vm.max_map_count, + * so COUNT_MAX can be any large number. We here set it to the default + * value of Linux's vm.max_map_count. + */ +#define COUNT_MAX (65530) + +struct munmap_queue { + void *start; + size_t length; +}; + +void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) +{ + /* + * We can simply discard munmap operations in the queue by + * restricting mmap arguments. + */ + if (start != NULL || flags != MAP_PRIVATE || prot != PROT_READ) + die("invalid usage of mmap"); + return mmap(start, length, prot, flags, fd, offset); +} + +int git_munmap(void *start, size_t length) +{ + static pthread_mutex_t mutex; + static struct munmap_queue *queue; + static int count; + int i; + + pthread_mutex_lock(&mutex); + if (!queue) + queue = xmalloc(COUNT_MAX * sizeof(struct munmap_queue)); + queue[count].start = start; + queue[count].length = length; + if (++count == COUNT_MAX) { + for (i = 0; i < COUNT_MAX; i++) + munmap(queue[i].start, queue[i].length); + count = 0; + } + pthread_mutex_unlock(&mutex); + return 0; +} diff --git a/compat/posix.h b/compat/posix.h index 067a00f33b83f3..3fa12182895241 100644 --- a/compat/posix.h +++ b/compat/posix.h @@ -278,6 +278,13 @@ int git_munmap(void *start, size_t length); #include +#if defined(__APPLE__) +#define mmap git_mmap +#define munmap git_munmap +void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); +int git_munmap(void *start, size_t length); +#endif + #endif /* NO_MMAP || USE_WIN32_MMAP */ #ifndef MAP_FAILED diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index edb0fc04ad7649..5c08f2fe5ceffa 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -271,6 +271,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") compat/strdup.c) set(NO_UNIX_SOCKETS 1) +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + list(APPEND compat_SOURCES + compat/osxmmap.c) + elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") add_compile_definitions(PROCFS_EXECUTABLE_PATH="/proc/self/exe" HAVE_DEV_TTY ) list(APPEND compat_SOURCES unix-socket.c unix-stream-server.c compat/linux/procinfo.c) diff --git a/meson.build b/meson.build index cee94244759904..b9b6e731b1c9c7 100644 --- a/meson.build +++ b/meson.build @@ -1275,6 +1275,8 @@ elif host_machine.system() == 'windows' else libgit_sources += 'compat/mingw.c' endif +elif host_machine.system() == 'darwin' + libgit_sources += 'compat/osxmmap.c' endif if host_machine.system() == 'linux'