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: Florian Weimer <fweimer at redhat dot com>
- To: Szabolcs Nagy <szabolcs dot nagy at arm 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, 7 Jul 2017 14:38:23 +0200
- Subject: Re: [PATCH v2] Single threaded stdio optimization
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=fweimer at redhat dot com
- Dkim-filter: OpenDKIM Filter v2.11.0 mx1.redhat.com AB2CC61971
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com AB2CC61971
- References: <594AA0A4.7010600@arm.com>
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.
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.
Thanks,
Florian
#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;
}