Add a simple mmap wrapper for cross-platform mmap usage Win32 has a variant of mmap that is harder to use than POSIX, but to run natively and efficiently on Win32 we need some form of it. gitfo_map_ro() provides a basic mmap function for use in locations where we need read-only random data access to large ranges of a file, such as a pack-*.idx. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
diff --git a/src/fileops.c b/src/fileops.c
index 16b9dc5..f494e47 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -1,5 +1,6 @@
#include "common.h"
#include "fileops.h"
+#include <sys/mman.h>
int gitfo_open(const char *path, int flags)
{
@@ -106,6 +107,20 @@ void gitfo_free_buf(gitfo_buf *obj)
obj->data = NULL;
}
+int gitfo_map_ro(gitfo_map *out, git_file fd, off_t begin, size_t len)
+{
+ out->data = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, begin);
+ if (out->data == (void*)-1)
+ return git_os_error();
+ out->len = len;
+ return GIT_SUCCESS;
+}
+
+void gitfo_free_map(gitfo_map *out)
+{
+ munmap(out->data, out->len);
+}
+
/* cached diskio */
struct gitfo_cache {
git_file fd;
diff --git a/src/fileops.h b/src/fileops.h
index 820e02c..22237f6 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -30,6 +30,10 @@ typedef struct { /* file io buffer */
size_t len; /* data length */
} gitfo_buf;
+typedef struct { /* memory mapped buffer */
+ void *data; /* data bytes */
+ size_t len; /* data length */
+} gitfo_map;
extern int gitfo_exists(const char *path);
extern int gitfo_open(const char *path, int flags);
@@ -44,6 +48,33 @@ extern int gitfo_read_file(gitfo_buf *obj, const char *path);
extern void gitfo_free_buf(gitfo_buf *obj);
/**
+ * Read-only map all or part of a file into memory.
+ * When possible this function should favor a virtual memory
+ * style mapping over some form of malloc()+read(), as the
+ * data access will be random and is not likely to touch the
+ * majority of the region requested.
+ *
+ * @param out buffer to populate with the mapping information.
+ * @param fd open descriptor to configure the mapping from.
+ * @param begin first byte to map, this should be page aligned.
+ * @param end number of bytes to map.
+ * @return
+ * - GIT_SUCCESS on success;
+ * - GIT_EOSERR on an unspecified OS related error.
+ */
+extern int gitfo_map_ro(
+ gitfo_map *out,
+ git_file fd,
+ off_t begin,
+ size_t len);
+
+/**
+ * Release the memory associated with a previous memory mapping.
+ * @param map the mapping description previously configured.
+ */
+extern void gitfo_free_map(gitfo_map *map);
+
+/**
* Walk each directory entry, except '.' and '..', calling fn(state).
*
* @param pathbuf buffer the function reads the initial directory