aboutsummaryrefslogtreecommitdiff
path: root/ports
diff options
context:
space:
mode:
authorMaxim Kuvyrkov <maxim@codesourcery.com>2012-08-15 16:44:30 -0700
committerMaxim Kuvyrkov <maxim@codesourcery.com>2012-08-15 16:44:30 -0700
commit309becf120640bb0fdd1a16e65996c23d0542590 (patch)
tree6adbada4d391a306dd2e4558626f759a7cadbed7 /ports
parentef4009734b84903615be28b38638c166e5455692 (diff)
downloadglibc-309becf120640bb0fdd1a16e65996c23d0542590.zip
glibc-309becf120640bb0fdd1a16e65996c23d0542590.tar.gz
glibc-309becf120640bb0fdd1a16e65996c23d0542590.tar.bz2
Optimize __libc_lock_lock and __libc_lock_trylock for MIPS.
Diffstat (limited to 'ports')
-rw-r--r--ports/ChangeLog.mips6
-rw-r--r--ports/sysdeps/unix/sysv/linux/mips/nptl/lowlevellock.h39
2 files changed, 43 insertions, 2 deletions
diff --git a/ports/ChangeLog.mips b/ports/ChangeLog.mips
index 5187772..f8c18b3 100644
--- a/ports/ChangeLog.mips
+++ b/ports/ChangeLog.mips
@@ -1,3 +1,9 @@
+2012-08-15 Tom de Vries <vries@codesourcery.com>
+ Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/mips/nptl/lowlevellock.h (__libc_lock_lock)
+ (__libc_lock_trylock): Define versions optimized for MIPS.
+
2012-08-15 Maxim Kuvyrkov <maxim@codesourcery.com>
* sysdeps/mips/nptl/pthread_spin_lock.S: Remove, use generic version.
diff --git a/ports/sysdeps/unix/sysv/linux/mips/nptl/lowlevellock.h b/ports/sysdeps/unix/sysv/linux/mips/nptl/lowlevellock.h
index 88b601e..d368ae1 100644
--- a/ports/sysdeps/unix/sysv/linux/mips/nptl/lowlevellock.h
+++ b/ports/sysdeps/unix/sysv/linux/mips/nptl/lowlevellock.h
@@ -1,5 +1,4 @@
-/* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008,
- 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2003-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -291,4 +290,40 @@ extern int __lll_timedwait_tid (int *, const struct timespec *)
__res; \
})
+/* Implement __libc_lock_lock using exchange_and_add, which expands into
+ a single instruction on XLP processors. We enable this for all MIPS
+ processors as atomic_exchange_and_add_acq and
+ atomic_compare_and_exchange_acq take the same time to execute.
+ This is a simplified expansion of ({ lll_lock (NAME, LLL_PRIVATE); 0; }).
+
+ Note: __lll_lock_wait_private() resets lock value to '2', which prevents
+ unbounded increase of the lock value and [with billions of threads]
+ overflow. */
+#define __libc_lock_lock(NAME) \
+ ({ \
+ int *__futex = &(NAME); \
+ if (__builtin_expect (atomic_exchange_and_add_acq (__futex, 1), 0)) \
+ __lll_lock_wait_private (__futex); \
+ 0; \
+ })
+
+#ifdef _MIPS_ARCH_XLP
+/* The generic version using a single atomic_compare_and_exchange_acq takes
+ less time for non-XLP processors, so we use below for XLP only. */
+# define __libc_lock_trylock(NAME) \
+ ({ \
+ int *__futex = &(NAME); \
+ int __result = atomic_exchange_and_add_acq (__futex, 1); \
+ /* If __result == 0, we succeeded in acquiring the lock. \
+ If __result == 1, we switched the lock to 'contended' state, which \
+ will cause a [possibly unnecessary] call to lll_futex_wait. This is \
+ unlikely, so we accept the possible inefficiency. \
+ If __result >= 2, we need to set the lock to 'contended' state to avoid \
+ unbounded increase from subsequent trylocks. */ \
+ if (__result >= 2) \
+ __result = atomic_exchange_acq (__futex, 2); \
+ __result; \
+ })
+#endif
+
#endif /* lowlevellock.h */