Commit d8fcafb2ca384a9b5e89ea922c515145fb050e46

Carlos Martín Nieto 2016-03-16T19:05:11

Split the page size from the mmap alignment While often similar, these are not the same on Windows. We want to use the page size on Windows for the pools, but for mmap we need to use the allocation granularity as the alignment. On the other platforms these values remain the same.

diff --git a/src/indexer.c b/src/indexer.c
index 6266bc8..a3a8669 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -449,7 +449,7 @@ static void hash_partially(git_indexer *idx, const uint8_t *data, size_t size)
 static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t size)
 {
 	git_file fd = idx->pack->mwf.fd;
-	size_t page_size;
+	size_t mmap_alignment;
 	size_t page_offset;
 	git_off_t page_start;
 	unsigned char *map_data;
@@ -458,11 +458,11 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t
 
 	assert(data && size);
 
-	if ((error = git__page_size(&page_size)) < 0)
+	if ((error = git__mmap_alignment(&mmap_alignment)) < 0)
 		return error;
 
-	/* the offset needs to be at the beginning of the a page boundary */
-	page_offset = offset % page_size;
+	/* the offset needs to be at the mmap boundary for the platform */
+	page_offset = offset % mmap_alignment;
 	page_start = offset - page_offset;
 
 	if ((error = p_mmap(&map, page_offset + size, GIT_PROT_WRITE, GIT_MAP_SHARED, fd, page_start)) < 0)
diff --git a/src/posix.c b/src/posix.c
index c7201ba..b3f1a1c 100644
--- a/src/posix.c
+++ b/src/posix.c
@@ -224,6 +224,13 @@ int git__page_size(size_t *page_size)
 	return 0;
 }
 
+int git__mmap_alignment(size_t *alignment)
+{
+	/* dummy; here we don't need any alignment anyway */
+	*alignment = 4096;
+	return 0;
+}
+
 
 int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
 {
diff --git a/src/posix.h b/src/posix.h
index 8785a4c..f204751 100644
--- a/src/posix.h
+++ b/src/posix.h
@@ -109,6 +109,7 @@ extern int p_getcwd(char *buffer_out, size_t size);
 extern int p_rename(const char *from, const char *to);
 
 extern int git__page_size(size_t *page_size);
+extern int git__mmap_alignment(size_t *page_size);
 
 /**
  * Platform-dependent methods
diff --git a/src/unix/map.c b/src/unix/map.c
index 72abb34..c55ad1a 100644
--- a/src/unix/map.c
+++ b/src/unix/map.c
@@ -24,6 +24,11 @@ int git__page_size(size_t *page_size)
 	return 0;
 }
 
+int git__mmap_alignment(size_t *alignment)
+{
+  return git__page_size(alignment);
+}
+
 int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
 {
 	int mprot = PROT_READ;
diff --git a/src/win32/map.c b/src/win32/map.c
index a99c30f..03a3646 100644
--- a/src/win32/map.c
+++ b/src/win32/map.c
@@ -17,22 +17,41 @@ static DWORD get_page_size(void)
 
 	if (!page_size) {
 		GetSystemInfo(&sys);
-		page_size = sys.dwAllocationGranularity;
+		page_size = sys.dwPageSize;
 	}
 
 	return page_size;
 }
 
+static DWORD get_allocation_granularity(void)
+{
+	static DWORD granularity;
+	SYSTEM_INFO sys;
+
+	if (!granularity) {
+		GetSystemInfo(&sys);
+		granularity = sys.dwAllocationGranularity;
+	}
+
+	return granularity;
+}
+
 int git__page_size(size_t *page_size)
 {
 	*page_size = get_page_size();
 	return 0;
 }
 
+int git__mmap_alignment(size_t *page_size)
+{
+	*page_size = get_allocation_granularity();
+	return 0;
+}
+
 int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
 {
 	HANDLE fh = (HANDLE)_get_osfhandle(fd);
-	DWORD page_size = get_page_size();
+	DWORD alignment = get_allocation_granularity();
 	DWORD fmap_prot = 0;
 	DWORD view_prot = 0;
 	DWORD off_low = 0;
@@ -62,12 +81,12 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
 	if (prot & GIT_PROT_READ)
 		view_prot |= FILE_MAP_READ;
 
-	page_start = (offset / page_size) * page_size;
+	page_start = (offset / alignment) * alignment;
 	page_offset = offset - page_start;
 
-	if (page_offset != 0) { /* offset must be multiple of page size */
+	if (page_offset != 0) { /* offset must be multiple of the allocation granularity */
 		errno = EINVAL;
-		giterr_set(GITERR_OS, "Failed to mmap. Offset must be multiple of page size");
+		giterr_set(GITERR_OS, "Failed to mmap. Offset must be multiple of allocation granularity");
 		return -1;
 	}