From: Junio C Hamano <gitster@pobox.com>
To: szager@chromium.org (Stefan Zager)
Cc: git@vger.kernel.org
Subject: Re: [PATCH] Enable index-pack threading in msysgit.
Date: Wed, 19 Mar 2014 15:23:33 -0700 [thread overview]
Message-ID: <xmqqha6t25ga.fsf@gitster.dls.corp.google.com> (raw)
In-Reply-To: <20140319213556.2FC3D4062B@wince.sfo.corp.google.com> (Stefan Zager's message of "Wed, 19 Mar 2014 14:35:56 -0700 (PDT)")
szager@chromium.org (Stefan Zager) writes:
> This adds a Windows implementation of pread. Note that it is NOT
> safe to intersperse calls to read() and pread() on a file
> descriptor. According to the ReadFile spec, using the 'overlapped'
> argument should not affect the implicit position pointer of the
> descriptor. Experiments have shown that this is, in fact, a lie.
>
> To accomodate that fact, this change also incorporates:
>
> http://article.gmane.org/gmane.comp.version-control.git/196042
>
> ... which gives each index-pack thread its own file descriptor.
>
> Signed-off-by: Stefan Zager <szager@chromium.org>
> ---
I'll queue it on 'pu' until I hear from Windows folks.
There were a few things I tweaked while queuing, tho.
- the indentation of the new comment inside struct thread_local
declaration looked strange;
- there was one new if () statement whose block was opened on the
next line, not on the same line as if () itself.
Thanks.
> builtin/index-pack.c | 30 ++++++++++++++++++++----------
> compat/mingw.c | 37 ++++++++++++++++++++++++++++++++++++-
> compat/mingw.h | 3 +++
> config.mak.uname | 1 -
> 4 files changed, 59 insertions(+), 12 deletions(-)
>
> diff --git a/builtin/index-pack.c b/builtin/index-pack.c
> index 2f37a38..63b8b0e 100644
> --- a/builtin/index-pack.c
> +++ b/builtin/index-pack.c
> @@ -40,17 +40,17 @@ struct base_data {
> int ofs_first, ofs_last;
> };
>
> -#if !defined(NO_PTHREADS) && defined(NO_THREAD_SAFE_PREAD)
> -/* pread() emulation is not thread-safe. Disable threading. */
> -#define NO_PTHREADS
> -#endif
> -
> struct thread_local {
> #ifndef NO_PTHREADS
> pthread_t thread;
> #endif
> struct base_data *base_cache;
> size_t base_cache_used;
> + /*
> + * To accomodate platforms that have pthreads, but don't have a
> + * thread-safe pread, give each thread its own file descriptor.
> + */
> + int pack_fd;
> };
>
> /*
> @@ -91,7 +91,8 @@ static off_t consumed_bytes;
> static unsigned deepest_delta;
> static git_SHA_CTX input_ctx;
> static uint32_t input_crc32;
> -static int input_fd, output_fd, pack_fd;
> +static const char *curr_pack;
> +static int input_fd, output_fd;
>
> #ifndef NO_PTHREADS
>
> @@ -134,6 +135,7 @@ static inline void unlock_mutex(pthread_mutex_t *mutex)
> */
> static void init_thread(void)
> {
> + int i;
> init_recursive_mutex(&read_mutex);
> pthread_mutex_init(&counter_mutex, NULL);
> pthread_mutex_init(&work_mutex, NULL);
> @@ -141,11 +143,17 @@ static void init_thread(void)
> pthread_mutex_init(&deepest_delta_mutex, NULL);
> pthread_key_create(&key, NULL);
> thread_data = xcalloc(nr_threads, sizeof(*thread_data));
> + for (i = 0; i < nr_threads; i++) {
> + thread_data[i].pack_fd = open(curr_pack, O_RDONLY);
> + if (thread_data[i].pack_fd == -1)
> + die_errno("unable to open %s", curr_pack);
> + }
> threads_active = 1;
> }
>
> static void cleanup_thread(void)
> {
> + int i;
> if (!threads_active)
> return;
> threads_active = 0;
> @@ -155,6 +163,8 @@ static void cleanup_thread(void)
> if (show_stat)
> pthread_mutex_destroy(&deepest_delta_mutex);
> pthread_key_delete(key);
> + for (i = 0; i < nr_threads; i++)
> + close(thread_data[i].pack_fd);
> free(thread_data);
> }
>
> @@ -288,13 +298,13 @@ static const char *open_pack_file(const char *pack_name)
> output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600);
> if (output_fd < 0)
> die_errno(_("unable to create '%s'"), pack_name);
> - pack_fd = output_fd;
> + nothread_data.pack_fd = output_fd;
> } else {
> input_fd = open(pack_name, O_RDONLY);
> if (input_fd < 0)
> die_errno(_("cannot open packfile '%s'"), pack_name);
> output_fd = -1;
> - pack_fd = input_fd;
> + nothread_data.pack_fd = input_fd;
> }
> git_SHA1_Init(&input_ctx);
> return pack_name;
> @@ -542,7 +552,7 @@ static void *unpack_data(struct object_entry *obj,
>
> do {
> ssize_t n = (len < 64*1024) ? len : 64*1024;
> - n = pread(pack_fd, inbuf, n, from);
> + n = pread(get_thread_data()->pack_fd, inbuf, n, from);
> if (n < 0)
> die_errno(_("cannot pread pack file"));
> if (!n)
> @@ -1490,7 +1500,7 @@ static void show_pack_info(int stat_only)
> int cmd_index_pack(int argc, const char **argv, const char *prefix)
> {
> int i, fix_thin_pack = 0, verify = 0, stat_only = 0;
> - const char *curr_pack, *curr_index;
> + const char *curr_index;
> const char *index_name = NULL, *pack_name = NULL;
> const char *keep_name = NULL, *keep_msg = NULL;
> char *index_name_buf = NULL, *keep_name_buf = NULL;
> diff --git a/compat/mingw.c b/compat/mingw.c
> index 383cafe..0efc570 100644
> --- a/compat/mingw.c
> +++ b/compat/mingw.c
> @@ -329,7 +329,42 @@ int mingw_mkdir(const char *path, int mode)
> return ret;
> }
>
> -int mingw_open (const char *filename, int oflags, ...)
> +
> +/*
> + * Warning: contrary to the specificiation, when ReadFile() is called
> + * with an 'overlapped' argument, it *will* modify the implict position
> + * pointer for the file descriptor. As a result, it is *not* safe to
> + * intersperse calls to read() and pread() on a single file descriptor.
> + */
> +ssize_t mingw_pread(int fd, void *buf, size_t count, off64_t offset)
> +{
> + HANDLE hand = (HANDLE)_get_osfhandle(fd);
> + if (hand == INVALID_HANDLE_VALUE) {
> + errno = EBADF;
> + return -1;
> + }
> +
> + LARGE_INTEGER offset_value;
> + offset_value.QuadPart = offset;
> +
> + DWORD bytes_read = 0;
> + OVERLAPPED overlapped = {0};
> + overlapped.Offset = offset_value.LowPart;
> + overlapped.OffsetHigh = offset_value.HighPart;
> + BOOL result = ReadFile(hand, buf, count, &bytes_read, &overlapped);
> +
> + ssize_t ret = bytes_read;
> +
> + if (!result && GetLastError() != ERROR_HANDLE_EOF)
> + {
> + errno = err_win_to_posix(GetLastError());
> + ret = -1;
> + }
> +
> + return ret;
> +}
> +
> +int mingw_open(const char *filename, int oflags, ...)
> {
> va_list args;
> unsigned mode;
> diff --git a/compat/mingw.h b/compat/mingw.h
> index 08b83fe..377ba50 100644
> --- a/compat/mingw.h
> +++ b/compat/mingw.h
> @@ -174,6 +174,9 @@ int mingw_unlink(const char *pathname);
> int mingw_rmdir(const char *path);
> #define rmdir mingw_rmdir
>
> +ssize_t mingw_pread(int fd, void *buf, size_t count, off64_t offset);
> +#define pread mingw_pread
> +
> int mingw_open (const char *filename, int oflags, ...);
> #define open mingw_open
>
> diff --git a/config.mak.uname b/config.mak.uname
> index e8acc39..b405524 100644
> --- a/config.mak.uname
> +++ b/config.mak.uname
> @@ -474,7 +474,6 @@ ifeq ($(uname_S),NONSTOP_KERNEL)
> endif
> ifneq (,$(findstring MINGW,$(uname_S)))
> pathsep = ;
> - NO_PREAD = YesPlease
> NEEDS_CRYPTO_WITH_SSL = YesPlease
> NO_LIBGEN_H = YesPlease
> NO_POLL = YesPlease
next prev parent reply other threads:[~2014-03-19 22:23 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-19 21:35 [PATCH] Enable index-pack threading in msysgit Stefan Zager
2014-03-19 22:23 ` Junio C Hamano [this message]
2014-03-20 1:25 ` Duy Nguyen
2014-03-21 18:40 ` Karsten Blees
2014-03-30 13:44 ` [BUG] 'pread' : macro redefinition Marat Radchenko
-- strict thread matches above, loose matches on Subject: below --
2014-03-19 0:46 [PATCH] Enable index-pack threading in msysgit szager
2014-03-19 7:30 ` Duy Nguyen
2014-03-19 7:50 ` Stefan Zager
2014-03-19 10:28 ` Duy Nguyen
2014-03-19 16:57 ` Stefan Zager
2014-03-19 19:15 ` Stefan Zager
2014-03-19 20:57 ` Junio C Hamano
2014-03-20 13:54 ` Karsten Blees
2014-03-20 16:08 ` Stefan Zager
2014-03-20 21:35 ` Karsten Blees
2014-03-20 21:56 ` Stefan Zager
2014-03-21 1:33 ` Duy Nguyen
2014-03-21 20:01 ` Karsten Blees
2014-03-21 1:51 ` Duy Nguyen
2014-03-21 5:21 ` Duy Nguyen
2014-03-21 5:35 ` Stefan Zager
2014-03-21 18:55 ` Karsten Blees
2014-03-26 8:35 ` Johannes Sixt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=xmqqha6t25ga.fsf@gitster.dls.corp.google.com \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
--cc=szager@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.