Re: Attempt to fix pread() threading issue on Cygwin and MinGW

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jun 26, 2012 at 9:00 PM, Ramsay Jones
<ramsay@xxxxxxxxxxxxxxxxxxx> wrote:
> Hi Johannes,
>
> I had an "fix pread() on MinGW" item low on my todo list. As we have
> seen recently, Cygwin has the same problem. So, I decided to try and
> fix it up last night, since I had an idea that I thought would work.
>
> Several years ago, I read somewhere (a Microsoft Press publication of
> some sort) that, even when using *synchonous* I/O, you could pass an
> OVERLAPPED structure to ReadFile() and have it use the file offset in
> that structure, rather than the implicit stream pointer.
>
> So, I modified my "hacked up test program" from the other day to try
> it out; the diff looks like:
>
> -- >8 --
> diff --git a/test-pread.c b/test-pread.c
> index 61280cb..8a2b2ff 100644
> --- a/test-pread.c
> +++ b/test-pread.c
> @@ -1,5 +1,6 @@
>  #include "git-compat-util.h"
>  #include "thread-utils.h"
> +#include <windows.h>
>
>  #define DATA_FILE "junk.data"
>  #define MAX_DATA 256 * 1024
> @@ -16,6 +17,31 @@ struct thread_data {
>
>  static struct thread_data t[NUM_THREADS+1];
>
> +ssize_t pread_(int fd, void *buf, size_t count, off_t offset)
> +{
> +       OVERLAPPED o = {0};
> +       HANDLE fh = (HANDLE)_get_osfhandle(fd);
> +       uint64_t off = offset;
> +       DWORD bytes;
> +       BOOL ret;
> +
> +       if (fh == INVALID_HANDLE_VALUE) {
> +               errno = EBADF;
> +               return -1;
> +       }
> +
> +       o.Offset = off & 0xffffffff;
> +       o.OffsetHigh = (off >> 32) & 0xffffffff;
> +
> +       ret = ReadFile(fh, buf, (DWORD)count, &bytes, &o);
> +       if (!ret) {
> +               errno = EIO;
> +               return -1;
> +       }
> +
> +       return (ssize_t)bytes;
> +}
> +
>  int create_data_file(void)
>  {
>        int i, fd = open(DATA_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0600);
> @@ -55,7 +81,7 @@ void *pread_thread(void *data)
>                ssize_t sz;
>                d->n = d->n * 1103515245 + 12345;
>                j = d->n % MAX_DATA;
> -               sz = pread(d->fd, &rd, sizeof(int), j * sizeof(int));
> +               sz = pread_(d->fd, &rd, sizeof(int), j * sizeof(int));
>                if (sz < 0 || rd != j)
>                        d->fails++;
>                d->cnt++;
>
> -- 8< --
>
> The result of running the updated program looks like:
>
>    ramsay $ gcc -I. -o test-pread test-pread.c
>    ramsay $ ./test-pread.exe
>     0: trials 524288, failed 262139
>     1: trials 500000, failed 0
>     2: trials 500000, failed 0
>     3: trials 500000, failed 0
>    ramsay $
>
> So, the results are a little disappointing. :(
>
> Although ReadFile() is indeed using the OVERLAPPED structure to specify
> the read position, it is still updating the implicit stream position.
>
> So, this implementation does not faithfully reproduce the full semantics
> of pread(), since it updates the stream position (affecting other I/O
> calls which rely on the implicit file position. eg read()).
>
> [Note: this was tested on Windows XP SP3. Maybe Vista/Win7/Win8 would
> behave differently?]
>
> This implementation should be sufficient to fix the immediate problem with
> the threaded index-pack, but I'm not sure it would be a good idea to
> provide an *almost* compliant pread().
>
> I've attached the full test program below, just for completeness.
>

We've been through this before:

http://thread.gmane.org/CABPQNSZ6VdyoLcVUUJ4z5A2A7KGP8qBZAkzdx8zAtAs2mZN25w@xxxxxxxxxxxxxx

My worries are the same as yours: An approach like this looks a bit
too much like pread, and might make someone else assume it works the
same.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]