{"thread":{"id":"36213","subject":"(unknown)","startedAt":"2014-03-19T00:45:49Z","lastAt":"2014-03-19T00:45:49Z","messageCount":1,"participants":["szager@chromium.org"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"237029","messageId":"5328e8bd.fNxY4x6POKCJfhV6%szager@chromium.org","threadId":"36213","inReplyTo":null,"subject":"(unknown)","fromName":"","fromEmail":"szager@chromium.org","sentAt":"2014-03-19T00:45:49Z","receivedAt":"2014-03-19T00:45:49Z","isPatch":false,"sender":{"key":"szager@chromium.org","avatar":null},"body":"Subject: [PATCH] Enable index-pack threading in msysgit.\n\nThis adds a Windows implementation of pread.  Note that it is NOT\nsafe to intersperse calls to read() and pread() on a file\ndescriptor.  According to the ReadFile spec, using the 'overlapped'\nargument should not affect the implicit position pointer of the\ndescriptor.  Experiments have shown that this is, in fact, a lie.\n\nTo accomodate that fact, this change also incorporates:\n\nhttp://article.gmane.org/gmane.comp.version-control.git/196042\n\n... which gives each index-pack thread its own file descriptor.\n---\n builtin/index-pack.c | 21 ++++++++++++++++-----\n compat/mingw.c       | 31 ++++++++++++++++++++++++++++++-\n compat/mingw.h       |  3 +++\n config.mak.uname     |  1 -\n 4 files changed, 49 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 2f37a38..c02dd4c 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -51,6 +51,7 @@ struct thread_local {\n #endif\n \tstruct base_data *base_cache;\n \tsize_t base_cache_used;\n+\tint pack_fd;\n };\n \n /*\n@@ -91,7 +92,8 @@ static off_t consumed_bytes;\n static unsigned deepest_delta;\n static git_SHA_CTX input_ctx;\n static uint32_t input_crc32;\n-static int input_fd, output_fd, pack_fd;\n+static const char *curr_pack;\n+static int input_fd, output_fd;\n \n #ifndef NO_PTHREADS\n \n@@ -134,6 +136,7 @@ static inline void unlock_mutex(pthread_mutex_t *mutex)\n  */\n static void init_thread(void)\n {\n+\tint i;\n \tinit_recursive_mutex(&read_mutex);\n \tpthread_mutex_init(&counter_mutex, NULL);\n \tpthread_mutex_init(&work_mutex, NULL);\n@@ -141,11 +144,17 @@ static void init_thread(void)\n \t\tpthread_mutex_init(&deepest_delta_mutex, NULL);\n \tpthread_key_create(&key, NULL);\n \tthread_data = xcalloc(nr_threads, sizeof(*thread_data));\n+\tfor (i = 0; i < nr_threads; i++) {\n+\t\tthread_data[i].pack_fd = open(curr_pack, O_RDONLY);\n+\t\tif (thread_data[i].pack_fd == -1)\n+\t\t\tdie_errno(\"unable to open %s\", curr_pack);\n+\t}\n \tthreads_active = 1;\n }\n \n static void cleanup_thread(void)\n {\n+\tint i;\n \tif (!threads_active)\n \t\treturn;\n \tthreads_active = 0;\n@@ -155,6 +164,8 @@ static void cleanup_thread(void)\n \tif (show_stat)\n \t\tpthread_mutex_destroy(&deepest_delta_mutex);\n \tpthread_key_delete(key);\n+\tfor (i = 0; i < nr_threads; i++)\n+\t\tclose(thread_data[i].pack_fd);\n \tfree(thread_data);\n }\n \n@@ -288,13 +299,13 @@ static const char *open_pack_file(const char *pack_name)\n \t\t\toutput_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600);\n \t\tif (output_fd < 0)\n \t\t\tdie_errno(_(\"unable to create '%s'\"), pack_name);\n-\t\tpack_fd = output_fd;\n+\t\tnothread_data.pack_fd = output_fd;\n \t} else {\n \t\tinput_fd = open(pack_name, O_RDONLY);\n \t\tif (input_fd < 0)\n \t\t\tdie_errno(_(\"cannot open packfile '%s'\"), pack_name);\n \t\toutput_fd = -1;\n-\t\tpack_fd = input_fd;\n+\t\tnothread_data.pack_fd = input_fd;\n \t}\n \tgit_SHA1_Init(&input_ctx);\n \treturn pack_name;\n@@ -542,7 +553,7 @@ static void *unpack_data(struct object_entry *obj,\n \n \tdo {\n \t\tssize_t n = (len < 64*1024) ? len : 64*1024;\n-\t\tn = pread(pack_fd, inbuf, n, from);\n+\t\tn = pread(get_thread_data()->pack_fd, inbuf, n, from);\n \t\tif (n < 0)\n \t\t\tdie_errno(_(\"cannot pread pack file\"));\n \t\tif (!n)\n@@ -1490,7 +1501,7 @@ static void show_pack_info(int stat_only)\n int cmd_index_pack(int argc, const char **argv, const char *prefix)\n {\n \tint i, fix_thin_pack = 0, verify = 0, stat_only = 0;\n-\tconst char *curr_pack, *curr_index;\n+\tconst char *curr_index;\n \tconst char *index_name = NULL, *pack_name = NULL;\n \tconst char *keep_name = NULL, *keep_msg = NULL;\n \tchar *index_name_buf = NULL, *keep_name_buf = NULL;\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 383cafe..6cc85d6 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -329,7 +329,36 @@ int mingw_mkdir(const char *path, int mode)\n \treturn ret;\n }\n \n-int mingw_open (const char *filename, int oflags, ...)\n+\n+ssize_t mingw_pread(int fd, void *buf, size_t count, off64_t offset)\n+{\n+\tHANDLE hand = (HANDLE)_get_osfhandle(fd);\n+\tif (hand == INVALID_HANDLE_VALUE) {\n+\t\terrno = EBADF;\n+\t\treturn -1;\n+\t}\n+\n+\tLARGE_INTEGER offset_value;\n+\toffset_value.QuadPart = offset;\n+\n+\tDWORD bytes_read = 0;\n+\tOVERLAPPED overlapped = {0};\n+\toverlapped.Offset = offset_value.LowPart;\n+\toverlapped.OffsetHigh = offset_value.HighPart;\n+\tBOOL result = ReadFile(hand, buf, count, &bytes_read, &overlapped);\n+\n+\tssize_t ret = bytes_read;\n+\n+\tif (!result && GetLastError() != ERROR_HANDLE_EOF)\n+\t{\n+\t\terrno = err_win_to_posix(GetLastError());\n+\t\tret = -1;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+int mingw_open(const char *filename, int oflags, ...)\n {\n \tva_list args;\n \tunsigned mode;\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 08b83fe..377ba50 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -174,6 +174,9 @@ int mingw_unlink(const char *pathname);\n int mingw_rmdir(const char *path);\n #define rmdir mingw_rmdir\n \n+ssize_t mingw_pread(int fd, void *buf, size_t count, off64_t offset);\n+#define pread mingw_pread\n+\n int mingw_open (const char *filename, int oflags, ...);\n #define open mingw_open\n \ndiff --git a/config.mak.uname b/config.mak.uname\nindex e8acc39..b405524 100644\n--- a/config.mak.uname\n+++ b/config.mak.uname\n@@ -474,7 +474,6 @@ ifeq ($(uname_S),NONSTOP_KERNEL)\n endif\n ifneq (,$(findstring MINGW,$(uname_S)))\n \tpathsep = ;\n-\tNO_PREAD = YesPlease\n \tNEEDS_CRYPTO_WITH_SSL = YesPlease\n \tNO_LIBGEN_H = YesPlease\n \tNO_POLL = YesPlease\n-- \n1.9.0.279.gdc9e3eb\n"}]}