Skip to content

Commit

Permalink
MinGW: implement mmap
Browse files Browse the repository at this point in the history
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 <janos.dev@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Janos Laube authored and Junio C Hamano committed Mar 19, 2009
1 parent 1c192f3 commit b130a72
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 4 deletions.
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,6 @@ ifneq (,$(findstring CYGWIN,$(uname_S)))
COMPAT_OBJS += compat/cygwin.o
endif
ifneq (,$(findstring MINGW,$(uname_S)))
NO_MMAP = YesPlease
NO_PREAD = YesPlease
NO_OPENSSL = YesPlease
NO_CURL = YesPlease
Expand All @@ -808,6 +807,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_POSIX_ONLY_PROGRAMS = YesPlease
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
NO_NSEC = YesPlease
USE_WIN32_MMAP = YesPlease
COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
Expand Down Expand Up @@ -985,6 +985,11 @@ endif
ifdef NO_MMAP
COMPAT_CFLAGS += -DNO_MMAP
COMPAT_OBJS += compat/mmap.o
else
ifdef USE_WIN32_MMAP
COMPAT_CFLAGS += -DUSE_WIN32_MMAP
COMPAT_OBJS += compat/win32mmap.o
endif
endif
ifdef NO_PREAD
COMPAT_CFLAGS += -DNO_PREAD
Expand Down
5 changes: 5 additions & 0 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);
int mingw_rename(const char*, const char*);
#define rename mingw_rename

#ifdef USE_WIN32_MMAP
int mingw_getpagesize(void);
#define getpagesize mingw_getpagesize
#endif

/* Use mingw_lstat() instead of lstat()/stat() and
* mingw_fstat() instead of fstat() on Windows.
*/
Expand Down
53 changes: 53 additions & 0 deletions compat/win32mmap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include "../git-compat-util.h"

/*
* Note that this doesn't return the actual pagesize, but
* the allocation granularity. If future Windows specific git code
* needs the real getpagesize function, we need to find another solution.
*/
int mingw_getpagesize(void)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
return si.dwAllocationGranularity;
}

void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
{
HANDLE hmap;
void *temp;
size_t len;
struct stat st;
uint64_t o = offset;
uint32_t l = o & 0xFFFFFFFF;
uint32_t h = (o >> 32) & 0xFFFFFFFF;

if (!fstat(fd, &st))
len = xsize_t(st.st_size);
else
die("mmap: could not determine filesize");

if ((length + offset) > len)
length = len - offset;

if (!(flags & MAP_PRIVATE))
die("Invalid usage of mmap when built with USE_WIN32_MMAP");

hmap = CreateFileMapping((HANDLE)_get_osfhandle(fd), 0, PAGE_WRITECOPY,
0, 0, 0);

if (!hmap)
return MAP_FAILED;

temp = MapViewOfFileEx(hmap, FILE_MAP_COPY, h, l, length, start);

if (!CloseHandle(hmap))
warning("unable to close file mapping handle\n");

return temp ? temp : MAP_FAILED;
}

int git_munmap(void *start, size_t length)
{
return !UnmapViewOfFile(start);
}
12 changes: 9 additions & 3 deletions git-compat-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ static inline const char *skip_prefix(const char *str, const char *prefix)
return strncmp(str, prefix, len) ? NULL : str + len;
}

#ifdef NO_MMAP
#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)

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

#else /* NO_MMAP || USE_WIN32_MMAP */

#include <sys/mman.h>

#endif /* NO_MMAP || USE_WIN32_MMAP */

#ifdef NO_MMAP

/* This value must be multiple of (pagesize * 2) */
#define DEFAULT_PACKED_GIT_WINDOW_SIZE (1 * 1024 * 1024)

#else /* NO_MMAP */

#include <sys/mman.h>

/* This value must be multiple of (pagesize * 2) */
#define DEFAULT_PACKED_GIT_WINDOW_SIZE \
(sizeof(void*) >= 8 \
Expand Down

0 comments on commit b130a72

Please sign in to comment.