Skip to content

Commit b130a72

Browse files
sothisgitster
authored andcommitted
MinGW: implement mmap
Add USE_WIN32_MMAP which triggers the use of windows' native file memory mapping functionality in git_mmap()/git_munmap() functions. As git functions currently use mmap with MAP_PRIVATE set only, this implementation supports only that mode for now. On Windows, offsets for memory mapped files need to match the allocation granularity. Take this into account when calculating the packed git- windowsize and file offsets. At the moment, the only function which makes use of offsets in conjunction with mmap is use_pack() in sha1-file.c. Git fast-import's code path tries to map a portion of the temporary packfile that exceeds the current filesize, i.e. offset+length is greater than the filesize. The NO_MMAP code worked with that since pread() just reads the file content until EOF and returns gracefully, while MapViewOfFile() aborts the mapping and returns 'Access Denied'. Working around that by determining the filesize and adjusting the length parameter. Signed-off-by: Janos Laube <[email protected]> Signed-off-by: Johannes Sixt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1c192f3 commit b130a72

File tree

4 files changed

+73
-4
lines changed

4 files changed

+73
-4
lines changed

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,6 @@ ifneq (,$(findstring CYGWIN,$(uname_S)))
784784
COMPAT_OBJS += compat/cygwin.o
785785
endif
786786
ifneq (,$(findstring MINGW,$(uname_S)))
787-
NO_MMAP = YesPlease
788787
NO_PREAD = YesPlease
789788
NO_OPENSSL = YesPlease
790789
NO_CURL = YesPlease
@@ -808,6 +807,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
808807
NO_POSIX_ONLY_PROGRAMS = YesPlease
809808
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
810809
NO_NSEC = YesPlease
810+
USE_WIN32_MMAP = YesPlease
811811
COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
812812
COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
813813
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
@@ -985,6 +985,11 @@ endif
985985
ifdef NO_MMAP
986986
COMPAT_CFLAGS += -DNO_MMAP
987987
COMPAT_OBJS += compat/mmap.o
988+
else
989+
ifdef USE_WIN32_MMAP
990+
COMPAT_CFLAGS += -DUSE_WIN32_MMAP
991+
COMPAT_OBJS += compat/win32mmap.o
992+
endif
988993
endif
989994
ifdef NO_PREAD
990995
COMPAT_CFLAGS += -DNO_PREAD

compat/mingw.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);
159159
int mingw_rename(const char*, const char*);
160160
#define rename mingw_rename
161161

162+
#ifdef USE_WIN32_MMAP
163+
int mingw_getpagesize(void);
164+
#define getpagesize mingw_getpagesize
165+
#endif
166+
162167
/* Use mingw_lstat() instead of lstat()/stat() and
163168
* mingw_fstat() instead of fstat() on Windows.
164169
*/

compat/win32mmap.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include "../git-compat-util.h"
2+
3+
/*
4+
* Note that this doesn't return the actual pagesize, but
5+
* the allocation granularity. If future Windows specific git code
6+
* needs the real getpagesize function, we need to find another solution.
7+
*/
8+
int mingw_getpagesize(void)
9+
{
10+
SYSTEM_INFO si;
11+
GetSystemInfo(&si);
12+
return si.dwAllocationGranularity;
13+
}
14+
15+
void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
16+
{
17+
HANDLE hmap;
18+
void *temp;
19+
size_t len;
20+
struct stat st;
21+
uint64_t o = offset;
22+
uint32_t l = o & 0xFFFFFFFF;
23+
uint32_t h = (o >> 32) & 0xFFFFFFFF;
24+
25+
if (!fstat(fd, &st))
26+
len = xsize_t(st.st_size);
27+
else
28+
die("mmap: could not determine filesize");
29+
30+
if ((length + offset) > len)
31+
length = len - offset;
32+
33+
if (!(flags & MAP_PRIVATE))
34+
die("Invalid usage of mmap when built with USE_WIN32_MMAP");
35+
36+
hmap = CreateFileMapping((HANDLE)_get_osfhandle(fd), 0, PAGE_WRITECOPY,
37+
0, 0, 0);
38+
39+
if (!hmap)
40+
return MAP_FAILED;
41+
42+
temp = MapViewOfFileEx(hmap, FILE_MAP_COPY, h, l, length, start);
43+
44+
if (!CloseHandle(hmap))
45+
warning("unable to close file mapping handle\n");
46+
47+
return temp ? temp : MAP_FAILED;
48+
}
49+
50+
int git_munmap(void *start, size_t length)
51+
{
52+
return !UnmapViewOfFile(start);
53+
}

git-compat-util.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ static inline const char *skip_prefix(const char *str, const char *prefix)
166166
return strncmp(str, prefix, len) ? NULL : str + len;
167167
}
168168

169-
#ifdef NO_MMAP
169+
#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
170170

171171
#ifndef PROT_READ
172172
#define PROT_READ 1
@@ -180,13 +180,19 @@ static inline const char *skip_prefix(const char *str, const char *prefix)
180180
extern void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
181181
extern int git_munmap(void *start, size_t length);
182182

183+
#else /* NO_MMAP || USE_WIN32_MMAP */
184+
185+
#include <sys/mman.h>
186+
187+
#endif /* NO_MMAP || USE_WIN32_MMAP */
188+
189+
#ifdef NO_MMAP
190+
183191
/* This value must be multiple of (pagesize * 2) */
184192
#define DEFAULT_PACKED_GIT_WINDOW_SIZE (1 * 1024 * 1024)
185193

186194
#else /* NO_MMAP */
187195

188-
#include <sys/mman.h>
189-
190196
/* This value must be multiple of (pagesize * 2) */
191197
#define DEFAULT_PACKED_GIT_WINDOW_SIZE \
192198
(sizeof(void*) >= 8 \

0 commit comments

Comments
 (0)