summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2018-10-18 12:47:26 -0400
committerRich Felker <dalias@aerifal.cx>2018-10-18 13:09:33 -0400
commit9dd19122565c70bc6e0fff35724c91a61209a629 (patch)
tree272f42ab2c781e3663063779ab4a2e338fdd147a
parent7eda27d025d6d52f855588590366c83d737eb727 (diff)
downloadmusl-9dd19122565c70bc6e0fff35724c91a61209a629.tar.gz
further optimize getc/putc when locking is needed
check whether the lock is free before loading the calling thread's tid. if so, just use a dummy tid value that cannot compare equal to any actual thread id (because it's one bit wider). this also avoids the need to save the tid and pass it to locking_getc or locking_putc, reducing register pressure. this change might slightly hurt the case where the caller already holds the lock, but it does not affect the single-threaded case, and may significantly improve the multi-threaded case, especially on archs where loading the thread pointer is disproportionately expensive like early mips and arm ISA levels. but even on i386 it helps, at least on some machines; I measured roughly a 10-15% improvement.
-rw-r--r--src/stdio/getc.h10
-rw-r--r--src/stdio/putc.h10
2 files changed, 10 insertions, 10 deletions
diff --git a/src/stdio/getc.h b/src/stdio/getc.h
index 0657ab6f..e24f9905 100644
--- a/src/stdio/getc.h
+++ b/src/stdio/getc.h
@@ -4,9 +4,9 @@
#ifdef __GNUC__
__attribute__((__noinline__))
#endif
-static int locking_getc(FILE *f, int tid)
+static int locking_getc(FILE *f)
{
- if (a_cas(&f->lock, 0, tid)) __lockfile(f);
+ if (a_cas(&f->lock, 0, MAYBE_WAITERS-1)) __lockfile(f);
int c = getc_unlocked(f);
if (a_swap(&f->lock, 0) & MAYBE_WAITERS)
__wake(&f->lock, 1, 1);
@@ -15,8 +15,8 @@ static int locking_getc(FILE *f, int tid)
static inline int do_getc(FILE *f)
{
- int tid, l = f->lock;
- if (l < 0 || (l & ~MAYBE_WAITERS) == (tid=__pthread_self()->tid))
+ int l = f->lock;
+ if (l < 0 || l && (l & ~MAYBE_WAITERS) == __pthread_self()->tid)
return getc_unlocked(f);
- return locking_getc(f, tid);
+ return locking_getc(f);
}
diff --git a/src/stdio/putc.h b/src/stdio/putc.h
index a37937e8..2014c4ec 100644
--- a/src/stdio/putc.h
+++ b/src/stdio/putc.h
@@ -4,9 +4,9 @@
#ifdef __GNUC__
__attribute__((__noinline__))
#endif
-static int locking_putc(int c, FILE *f, int tid)
+static int locking_putc(int c, FILE *f)
{
- if (a_cas(&f->lock, 0, tid)) __lockfile(f);
+ if (a_cas(&f->lock, 0, MAYBE_WAITERS-1)) __lockfile(f);
c = putc_unlocked(c, f);
if (a_swap(&f->lock, 0) & MAYBE_WAITERS)
__wake(&f->lock, 1, 1);
@@ -15,8 +15,8 @@ static int locking_putc(int c, FILE *f, int tid)
static inline int do_putc(int c, FILE *f)
{
- int tid, l = f->lock;
- if (l < 0 || (l & ~MAYBE_WAITERS) == (tid=__pthread_self()->tid))
+ int l = f->lock;
+ if (l < 0 || l && (l & ~MAYBE_WAITERS) == __pthread_self()->tid)
return putc_unlocked(c, f);
- return locking_putc(c, f, tid);
+ return locking_putc(c, f);
}