This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH v2] Single threaded stdio optimization
- From: Szabolcs Nagy <szabolcs dot nagy at arm dot com>
- To: Florian Weimer <fweimer at redhat dot com>, GNU C Library <libc-alpha at sourceware dot org>
- Cc: nd at arm dot com, "triegel at redhat dot com" <triegel at redhat dot com>
- Date: Fri, 07 Jul 2017 14:38:02 +0100
- Subject: Re: [PATCH v2] Single threaded stdio optimization
- Authentication-results: sourceware.org; auth=none
- Authentication-results: redhat.com; dkim=none (message not signed) header.d=none;redhat.com; dmarc=none action=none header.from=arm.com;
- Nodisclaimer: True
- References: <594AA0A4.7010600@arm.com> <a48172d4-1d98-43e2-31c5-05042e12a082@redhat.com>
- Spamdiagnosticmetadata: NSPM
- Spamdiagnosticoutput: 1:99
On 07/07/17 13:38, Florian Weimer wrote:
> This patch breaks the attached test case. Not all stream objects are
> linked into the global list, so the locking upgrade doesn't happen for
> some of them.
>
i thought all files need to be flushed on exit
or on fflush(0), if glibc does not do that that's
observably non-conforming.
> The global list management is quite expensive because the list is
> single-linked, so we can't just add all stream objects when not yet
> running multi-threaded.
>
> I fear that this patch may have to be backed out again, until we can
> address these issues.
>
i can back it out, or try to create all the
problematic files with the optimization-disabling
flag set (in case that's simple.. will look into
it in a minute).
> Thanks,
> Florian
>
>
> memstream-thread.c
>
>
> #include <err.h>
> #include <errno.h>
> #include <pthread.h>
> #include <stdio.h>
>
> enum
> {
> thread_count = 2,
> byte_count = 1000000,
> };
>
> struct closure
> {
> FILE *fp;
> char b;
> };
>
> static void *
> thread_func (void *closure)
> {
> struct closure *args = closure;
>
> for (int i = 0; i < byte_count; ++i)
> fputc (args->b, args->fp);
>
> return NULL;
> }
>
> int
> main (void)
> {
> char *buffer = NULL;
> size_t buffer_length = 0;
> FILE *fp = open_memstream (&buffer, &buffer_length);
> if (fp == NULL)
> err (1, "open_memstream");
>
> pthread_t threads[thread_count];
> struct closure args[thread_count];
>
> for (int i = 0; i < thread_count; ++i)
> {
> args[i].fp = fp;
> args[i].b = 'A' + i;
> int ret = pthread_create (threads + i, NULL, thread_func, args + i);
> if (ret != 0)
> {
> errno = ret;
> err (1, "pthread_create");
> }
> }
>
> for (int i = 0; i < thread_count; ++i)
> {
> int ret = pthread_join (threads[i], NULL);
> if (ret != 0)
> {
> errno = ret;
> err (1, "pthread_join");
> }
> }
>
> fclose (fp);
>
> if (buffer_length != thread_count * byte_count)
> errx (1, "unexpected number of written bytes: %zu (should be %d)",
> buffer_length, thread_count * byte_count);
>
> size_t counts[thread_count] = { 0, };
> for (size_t i = 0; i < buffer_length; ++i)
> {
> if (buffer[i] < 'A' || buffer[i] >= 'A' + thread_count)
> errx (1, "written byte at %zu out of range: %d", i, buffer[i] & 0xFF);
> ++counts[buffer[i] - 'A'];
> }
> for (int i = 0; i < thread_count; ++i)
> if (counts[i] != byte_count)
> errx (1, "incorrect write count for thread %d: %zu (should be %d)",
> i, counts[i], byte_count);
>
> return 0;
> }
>