@@ -126,9 +126,9 @@ __pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
LIBC_PROBE (rdlock_entry, 1, rwlock);
if (ELIDE_LOCK (rwlock->__data.__rwelision,
- rwlock->__data.__lock == 0
- && rwlock->__data.__writer == 0
- && rwlock->__data.__nr_readers == 0))
+ rwlock->__data.__lock,
+ rwlock->__data.__writer,
+ rwlock->__data.__nr_readers))
return 0;
/* Make sure we are alone. */
@@ -33,9 +33,9 @@ __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
rwlock->__data.__shared == LLL_PRIVATE ? FUTEX_PRIVATE : FUTEX_SHARED;
if (ELIDE_TRYLOCK (rwlock->__data.__rwelision,
- rwlock->__data.__lock == 0
- && rwlock->__data.__nr_readers == 0
- && rwlock->__data.__writer, 0))
+ rwlock->__data.__lock,
+ rwlock->__data.__writer,
+ rwlock->__data.__nr_readers, 0))
return 0;
lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
@@ -28,9 +28,9 @@ __pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
int result = EBUSY;
if (ELIDE_TRYLOCK (rwlock->__data.__rwelision,
- rwlock->__data.__lock == 0
- && rwlock->__data.__nr_readers == 0
- && rwlock->__data.__writer, 1))
+ rwlock->__data.__lock,
+ rwlock->__data.__writer,
+ rwlock->__data.__nr_readers, 1))
return 0;
lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
@@ -35,8 +35,7 @@ __pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
LIBC_PROBE (rwlock_unlock, 1, rwlock);
- if (ELIDE_UNLOCK (rwlock->__data.__writer == 0
- && rwlock->__data.__nr_readers == 0))
+ if (ELIDE_UNLOCK (rwlock->__data.__writer, rwlock->__data.__nr_readers))
return 0;
lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
@@ -98,9 +98,9 @@ __pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
LIBC_PROBE (wrlock_entry, 1, rwlock);
if (ELIDE_LOCK (rwlock->__data.__rwelision,
- rwlock->__data.__lock == 0
- && rwlock->__data.__writer == 0
- && rwlock->__data.__nr_readers == 0))
+ rwlock->__data.__lock,
+ rwlock->__data.__writer,
+ rwlock->__data.__nr_readers))
return 0;
/* Make sure we are alone. */
@@ -15,11 +15,12 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+
#ifndef ELIDE_H
#define ELIDE_H 1
-#define ELIDE_LOCK(adapt_count, is_lock_free) 0
-#define ELIDE_TRYLOCK(adapt_count, is_lock_free, write) 0
-#define ELIDE_UNLOCK(is_lock_free) 0
+#define ELIDE_LOCK(adapt_count, lock, writer, readers) 0
+#define ELIDE_TRYLOCK(adapt_count, lock, writer, readers, write) 0
+#define ELIDE_UNLOCK(writer, readers) 0
#endif
@@ -27,7 +27,7 @@
ADAPT_COUNT is a pointer to per-lock state variable. */
static inline bool
-__elide_lock (uint8_t *adapt_count, int is_lock_free)
+__elide_lock (uint8_t *adapt_count, int *lock, int *writer, unsigned int *readers)
{
if (*adapt_count > 0)
{
@@ -39,7 +39,10 @@ __elide_lock (uint8_t *adapt_count, int is_lock_free)
{
if (__builtin_tbegin (0))
{
- if (is_lock_free)
+ /* The compiler barrier is required because some GCC version might
+ reorder the lock read before the transaction init builtin. */
+ asm volatile("" ::: "memory");
+ if ((*lock == 0) && (*writer == 0) && (*readers == 0))
return true;
/* Lock was busy. */
__builtin_tabort (_ABORT_LOCK_BUSY);
@@ -66,30 +69,31 @@ __elide_lock (uint8_t *adapt_count, int is_lock_free)
return false;
}
-# define ELIDE_LOCK(adapt_count, is_lock_free) \
- __elide_lock (&(adapt_count), is_lock_free)
+# define ELIDE_LOCK(adapt_count, lock, writer, readers) \
+ __elide_lock (&(adapt_count), &(lock), &(writer), &(readers))
static inline bool
-__elide_trylock (uint8_t *adapt_count, int is_lock_free, int write)
+__elide_trylock (uint8_t *adapt_count, int *lock, int *writer,
+ unsigned int *readers, int write)
{
if (__elision_aconf.try_tbegin > 0)
{
if (write)
__builtin_tabort (_ABORT_NESTED_TRYLOCK);
- return __elide_lock (adapt_count, is_lock_free);
+ return __elide_lock (adapt_count, lock, writer, readers);
}
return false;
}
-# define ELIDE_TRYLOCK(adapt_count, is_lock_free, write) \
- __elide_trylock (&(adapt_count), is_lock_free, write)
+# define ELIDE_TRYLOCK(adapt_count, lock, writer, readers, write) \
+ __elide_trylock (&(adapt_count), &(lock), &(writer), &(readers), write)
static inline bool
-__elide_unlock (int is_lock_free)
+__elide_unlock (int *writer, unsigned int *readers)
{
- if (is_lock_free)
+ if ((*writer == 0) && (*readers == 0))
{
__builtin_tend (0);
return true;
@@ -97,14 +101,14 @@ __elide_unlock (int is_lock_free)
return false;
}
-# define ELIDE_UNLOCK(is_lock_free) \
- __elide_unlock (is_lock_free)
+# define ELIDE_UNLOCK(writer, readers) \
+ __elide_unlock (&(writer), &(readers))
# else
-# define ELIDE_LOCK(adapt_count, is_lock_free) 0
-# define ELIDE_TRYLOCK(adapt_count, is_lock_free, write) 0
-# define ELIDE_UNLOCK(is_lock_free) 0
+# define ELIDE_LOCK(adapt_count, lock, writer, readers) 0
+# define ELIDE_TRYLOCK(adapt_count, lock, writer, readers, write) 0
+# define ELIDE_UNLOCK(writer, readers) 0
#endif /* ENABLE_LOCK_ELISION */