{"thread":{"id":"36236","subject":"[PATCH] Enable index-pack threading in msysgit.","startedAt":"2014-03-19T21:35:56Z","lastAt":"2014-03-30T13:44:21Z","messageCount":5,"participants":["Stefan Zager","Junio C Hamano","Duy Nguyen","Karsten Blees","Marat Radchenko"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"237122","messageId":"20140319213556.2FC3D4062B@wince.sfo.corp.google.com","threadId":"36236","inReplyTo":null,"subject":"[PATCH] Enable index-pack threading in msysgit.","fromName":"Stefan Zager","fromEmail":"szager@chromium.org","sentAt":"2014-03-19T21:35:56Z","receivedAt":"2014-03-19T21:35:56Z","isPatch":true,"sender":{"key":"szager@chromium.org","avatar":null},"body":"This 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\nSigned-off-by: Stefan Zager <szager@chromium.org>\n---\n builtin/index-pack.c | 30 ++++++++++++++++++++----------\n compat/mingw.c       | 37 ++++++++++++++++++++++++++++++++++++-\n compat/mingw.h       |  3 +++\n config.mak.uname     |  1 -\n 4 files changed, 59 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 2f37a38..63b8b0e 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -40,17 +40,17 @@ struct base_data {\n \tint ofs_first, ofs_last;\n };\n \n-#if !defined(NO_PTHREADS) && defined(NO_THREAD_SAFE_PREAD)\n-/* pread() emulation is not thread-safe. Disable threading. */\n-#define NO_PTHREADS\n-#endif\n-\n struct thread_local {\n #ifndef NO_PTHREADS\n \tpthread_t thread;\n #endif\n \tstruct base_data *base_cache;\n \tsize_t base_cache_used;\n+    /*\n+     * To accomodate platforms that have pthreads, but don't have a\n+     * thread-safe pread, give each thread its own file descriptor.\n+     */\n+\tint pack_fd;\n };\n \n /*\n@@ -91,7 +91,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 +135,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 +143,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 +163,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 +298,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 +552,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 +1500,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..0efc570 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -329,7 +329,42 @@ int mingw_mkdir(const char *path, int mode)\n \treturn ret;\n }\n \n-int mingw_open (const char *filename, int oflags, ...)\n+\n+/*\n+ * Warning: contrary to the specificiation, when ReadFile() is called\n+ * with an 'overlapped' argument, it *will* modify the implict position\n+ * pointer for the file descriptor.  As a result, it is *not* safe to\n+ * intersperse calls to read() and pread() on a single file descriptor.\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"},{"id":"237126","messageId":"xmqqha6t25ga.fsf@gitster.dls.corp.google.com","threadId":"36236","inReplyTo":"20140319213556.2FC3D4062B@wince.sfo.corp.google.com","subject":"Re: [PATCH] Enable index-pack threading in msysgit.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-19T22:23:33Z","receivedAt":"2014-03-19T22:23:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"szager@chromium.org (Stefan Zager) writes:\n\n> This adds a Windows implementation of pread.  Note that it is NOT\n> safe to intersperse calls to read() and pread() on a file\n> descriptor.  According to the ReadFile spec, using the 'overlapped'\n> argument should not affect the implicit position pointer of the\n> descriptor.  Experiments have shown that this is, in fact, a lie.\n>\n> To accomodate that fact, this change also incorporates:\n>\n> http://article.gmane.org/gmane.comp.version-control.git/196042\n>\n> ... which gives each index-pack thread its own file descriptor.\n>\n> Signed-off-by: Stefan Zager <szager@chromium.org>\n> ---\n\nI'll queue it on 'pu' until I hear from Windows folks.\nThere were a few things I tweaked while queuing, tho.\n\n - the indentation of the new comment inside struct thread_local\n   declaration looked strange;\n\n - there was one new if () statement whose block was opened on the\n   next line, not on the same line as if () itself.\n\nThanks.\n\n>  builtin/index-pack.c | 30 ++++++++++++++++++++----------\n>  compat/mingw.c       | 37 ++++++++++++++++++++++++++++++++++++-\n>  compat/mingw.h       |  3 +++\n>  config.mak.uname     |  1 -\n>  4 files changed, 59 insertions(+), 12 deletions(-)\n>\n> diff --git a/builtin/index-pack.c b/builtin/index-pack.c\n> index 2f37a38..63b8b0e 100644\n> --- a/builtin/index-pack.c\n> +++ b/builtin/index-pack.c\n> @@ -40,17 +40,17 @@ struct base_data {\n>  \tint ofs_first, ofs_last;\n>  };\n>  \n> -#if !defined(NO_PTHREADS) && defined(NO_THREAD_SAFE_PREAD)\n> -/* pread() emulation is not thread-safe. Disable threading. */\n> -#define NO_PTHREADS\n> -#endif\n> -\n>  struct thread_local {\n>  #ifndef NO_PTHREADS\n>  \tpthread_t thread;\n>  #endif\n>  \tstruct base_data *base_cache;\n>  \tsize_t base_cache_used;\n> +    /*\n> +     * To accomodate platforms that have pthreads, but don't have a\n> +     * thread-safe pread, give each thread its own file descriptor.\n> +     */\n> +\tint pack_fd;\n>  };\n>  \n>  /*\n> @@ -91,7 +91,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 +135,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 +143,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 +163,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 +298,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 +552,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 +1500,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;\n> diff --git a/compat/mingw.c b/compat/mingw.c\n> index 383cafe..0efc570 100644\n> --- a/compat/mingw.c\n> +++ b/compat/mingw.c\n> @@ -329,7 +329,42 @@ int mingw_mkdir(const char *path, int mode)\n>  \treturn ret;\n>  }\n>  \n> -int mingw_open (const char *filename, int oflags, ...)\n> +\n> +/*\n> + * Warning: contrary to the specificiation, when ReadFile() is called\n> + * with an 'overlapped' argument, it *will* modify the implict position\n> + * pointer for the file descriptor.  As a result, it is *not* safe to\n> + * intersperse calls to read() and pread() on a single file descriptor.\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;\n> diff --git a/compat/mingw.h b/compat/mingw.h\n> index 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>  \n> diff --git a/config.mak.uname b/config.mak.uname\n> index 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"},{"id":"237136","messageId":"CACsJy8D01gxeSoxgD9QkLgS85B=Af8aXytuqn6CBkF+_7WjZtQ@mail.gmail.com","threadId":"36236","inReplyTo":"20140319213556.2FC3D4062B@wince.sfo.corp.google.com","subject":"Re: [PATCH] Enable index-pack threading in msysgit.","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2014-03-20T01:25:40Z","receivedAt":"2014-03-20T01:25:40Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Mar 20, 2014 at 4:35 AM, Stefan Zager <szager@chromium.org> wrote:\n> This adds a Windows implementation of pread.  Note that it is NOT\n> safe to intersperse calls to read() and pread() on a file\n> descriptor.  According to the ReadFile spec, using the 'overlapped'\n> argument should not affect the implicit position pointer of the\n> descriptor.  Experiments have shown that this is, in fact, a lie.\n>\n> To accomodate that fact, this change also incorporates:\n>\n> http://article.gmane.org/gmane.comp.version-control.git/196042\n>\n> ... which gives each index-pack thread its own file descriptor.\n\nIf the problem is mixing read() and pread() then perhaps it's enough to do\n\noutput_fd = dup(output_fd);\n\nafter pack_fd is set in open_pack_file(), to make sure that\nfixup_pack_header_footer() has its own file handle. If that works, we\ndon't need one pack_fd per thread.\n\ncompat/mmap.c uses pread() and its bad interaction with read() could\nturn it into a nightmare. Fortunately Windows (except Cygwin) does not\nuse this implementation. Not sure if we should make a note about this.\n\nIt makes me wonder if sliding mmap window (like we do for pack access\nin sha1_file.c) would be better than pread(). index-pack used to do\nmmap() [1] in the past with poor performance but I don't think sliding\nwindow was mentioned.\n\n[1] http://thread.gmane.org/gmane.comp.version-control.git/34741/focus=34832\n\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>         pathsep = ;\n> -       NO_PREAD = YesPlease\n>         NEEDS_CRYPTO_WITH_SSL = YesPlease\n>         NO_LIBGEN_H = YesPlease\n>         NO_POLL = YesPlease\n\nWhat about the \"ifeq ($(uname_S),Windows)\" section? I think MSVC and\nMinGW builds share a lot of code.\n-- \nDuy\n"},{"id":"237342","messageId":"532C8793.8050202@gmail.com","threadId":"36236","inReplyTo":"CACsJy8D01gxeSoxgD9QkLgS85B=Af8aXytuqn6CBkF+_7WjZtQ@mail.gmail.com","subject":"Re: [PATCH] Enable index-pack threading in msysgit.","fromName":"Karsten Blees","fromEmail":"karsten.blees@gmail.com","sentAt":"2014-03-21T18:40:19Z","receivedAt":"2014-03-21T18:40:19Z","isPatch":true,"sender":{"key":"karsten.blees@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1111200?v=4"},"body":"Am 20.03.2014 02:25, schrieb Duy Nguyen:\n> On Thu, Mar 20, 2014 at 4:35 AM, Stefan Zager <szager@chromium.org> wrote:\n>> This adds a Windows implementation of pread.  Note that it is NOT\n>> safe to intersperse calls to read() and pread() on a file\n>> descriptor.  According to the ReadFile spec, using the 'overlapped'\n>> argument should not affect the implicit position pointer of the\n>> descriptor.  Experiments have shown that this is, in fact, a lie.\n>>\n>> To accomodate that fact, this change also incorporates:\n>>\n>> http://article.gmane.org/gmane.comp.version-control.git/196042\n>>\n>> ... which gives each index-pack thread its own file descriptor.\n> \n> If the problem is mixing read() and pread() then perhaps it's enough to do\n> \n> output_fd = dup(output_fd);\n> \n\nUnfortunately not, dup() / DuplicateHandle() just opens another handle to the same file object (i.e. sharing the same file position).\n"},{"id":"238081","messageId":"loom.20140330T154129-838@post.gmane.org","threadId":"36236","inReplyTo":"20140319213556.2FC3D4062B@wince.sfo.corp.google.com","subject":"[BUG] 'pread' : macro redefinition","fromName":"Marat Radchenko","fromEmail":"marat@slonopotamus.org","sentAt":"2014-03-30T13:44:21Z","receivedAt":"2014-03-30T13:44:21Z","isPatch":false,"sender":{"key":"marat@slonopotamus.org","avatar":"https://avatars.githubusercontent.com/u/92637?v=4"},"body":"Stefan Zager <szager <at> chromium.org> writes:\n\n> \n> This adds a Windows implementation of pread.\n> diff --git a/compat/mingw.h b/compat/mingw.h\n> index 08b83fe..377ba50 100644\n> --- a/compat/mingw.h\n> +++ b/compat/mingw.h\n> +ssize_t mingw_pread(int fd, void *buf, size_t count, off64_t offset);\n> +#define pread mingw_pread\n\nThis result in tons of following warnings in MSVC=1 build:\n\ngit-compat-util.h(401) : warning C4005: 'pread' : macro redefinition\nmingw.h(181) : see previous definition of 'pread'\n"}]}