From 2c0b891afe29dd28d0e6d75e0da8681db7fd100d Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 24 Mar 2004 06:36:06 +0000 Subject: [PATCH] Update. * sysdeps/unix/sysv/linux/smp.h: New file. * sysdeps/unix/sysv/linux/sh/smp.h: New file. * init.c: Define __is_smp. (__pthread_initialize_minimal_internal): Call is_smp_system to initialize __is_smp. * pthreadP.h: Declare __is_smp. Define MAX_ADAPTIVE_COUNT is necessary. * pthread_mutex_init.c: Add comment regarding __spins field. * pthread_mutex_lock.c: Implement adaptive mutex type. * pthread_mutex_timedlock.c: Likewise. * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Likewise. * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_mutex_t): Add __spins field. * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Define lll_mutex_cond_trylock. * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. Define BUSY_WAIT_NOP. * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. * tst-mutex5.c: Add support for testing adaptive mutexes. * tst-mutex7.c: Likewise. * tst-mutex5a.c: New file. * tst-mutex7a.c: New file. * Makefile (tests): Add tst-mutex5a and tst-mutex7a. --- nptl/Banner | 2 +- nptl/ChangeLog | 37 ++++++++++++++ nptl/Makefile | 2 +- nptl/init.c | 7 +++ nptl/pthreadP.h | 9 ++++ nptl/pthread_mutex_init.c | 3 +- nptl/pthread_mutex_lock.c | 34 ++++++++++++- nptl/pthread_mutex_timedlock.c | 31 +++++++++++- .../unix/sysv/linux/alpha/bits/pthreadtypes.h | 3 +- .../unix/sysv/linux/alpha/lowlevellock.h | 10 +++- .../unix/sysv/linux/i386/bits/pthreadtypes.h | 3 +- .../unix/sysv/linux/i386/lowlevellock.h | 14 ++++++ .../unix/sysv/linux/ia64/bits/pthreadtypes.h | 3 +- .../unix/sysv/linux/ia64/lowlevellock.h | 10 +++- .../sysv/linux/powerpc/bits/pthreadtypes.h | 3 +- .../unix/sysv/linux/powerpc/lowlevellock.h | 17 ++++++- .../unix/sysv/linux/pthread_mutex_cond_lock.c | 1 + .../unix/sysv/linux/s390/bits/pthreadtypes.h | 3 +- .../unix/sysv/linux/s390/lowlevellock.h | 16 +++++- .../unix/sysv/linux/sh/bits/pthreadtypes.h | 3 +- .../sysdeps/unix/sysv/linux/sh/lowlevellock.h | 25 +++++++++- nptl/sysdeps/unix/sysv/linux/sh/smp.h | 24 +++++++++ nptl/sysdeps/unix/sysv/linux/smp.h | 50 +++++++++++++++++++ .../unix/sysv/linux/sparc/bits/pthreadtypes.h | 3 +- .../unix/sysv/linux/sparc/lowlevellock.h | 12 ++++- .../sysv/linux/x86_64/bits/pthreadtypes.h | 3 +- .../unix/sysv/linux/x86_64/lowlevellock.h | 25 ++++++++-- nptl/tst-mutex5.c | 28 ++++++++++- nptl/tst-mutex5a.c | 2 + nptl/tst-mutex7.c | 7 ++- nptl/tst-mutex7a.c | 2 + 31 files changed, 364 insertions(+), 28 deletions(-) create mode 100644 nptl/sysdeps/unix/sysv/linux/sh/smp.h create mode 100644 nptl/sysdeps/unix/sysv/linux/smp.h create mode 100644 nptl/tst-mutex5a.c create mode 100644 nptl/tst-mutex7a.c diff --git a/nptl/Banner b/nptl/Banner index 5f10f81731..53444807bb 100644 --- a/nptl/Banner +++ b/nptl/Banner @@ -1 +1 @@ -NPTL 0.60 by Ulrich Drepper +NPTL 0.61 by Ulrich Drepper diff --git a/nptl/ChangeLog b/nptl/ChangeLog index a10c6c12ec..05906737e7 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,5 +1,42 @@ 2004-03-23 Ulrich Drepper + * sysdeps/unix/sysv/linux/smp.h: New file. + * sysdeps/unix/sysv/linux/sh/smp.h: New file. + * init.c: Define __is_smp. + (__pthread_initialize_minimal_internal): Call is_smp_system to + initialize __is_smp. + * pthreadP.h: Declare __is_smp. + Define MAX_ADAPTIVE_COUNT is necessary. + * pthread_mutex_init.c: Add comment regarding __spins field. + * pthread_mutex_lock.c: Implement adaptive mutex type. + * pthread_mutex_timedlock.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_mutex_t): + Add __spins field. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Define + lll_mutex_cond_trylock. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + Define BUSY_WAIT_NOP. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + + * tst-mutex5.c: Add support for testing adaptive mutexes. + * tst-mutex7.c: Likewise. + * tst-mutex5a.c: New file. + * tst-mutex7a.c: New file. + * Makefile (tests): Add tst-mutex5a and tst-mutex7a. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S (__lll_mutex_timedlock_wait): Preserve r8 and r9 since the vgettimeofday call miht destroy the content. diff --git a/nptl/Makefile b/nptl/Makefile index 114d4a3ad8..c3bc89cb43 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -190,7 +190,7 @@ omit-deps = $(unix-syscalls:%=ptw-%) tests = tst-attr1 tst-attr2 tst-attr3 \ tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \ - tst-mutex7 tst-mutex8 tst-mutex9 \ + tst-mutex7 tst-mutex8 tst-mutex9 tst-mutex5a tst-mutex7a \ tst-spin1 tst-spin2 tst-spin3 \ tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ diff --git a/nptl/init.c b/nptl/init.c index f46e0bb531..47bb0a6f72 100644 --- a/nptl/init.c +++ b/nptl/init.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifndef __NR_set_tid_address @@ -61,6 +62,9 @@ size_t __default_stacksize attribute_hidden; size_t __static_tls_size; size_t __static_tls_align_m1; +/* Flag whether the machine is SMP or not. */ +int __is_smp attribute_hidden; + /* Version of the library, used in libthread_db to detect mismatches. */ static const char nptl_version[] __attribute_used__ = VERSION; @@ -301,6 +305,9 @@ __pthread_initialize_minimal_internal (void) #endif __libc_pthread_init (&__fork_generation, __reclaim_stacks, ptr_pthread_functions); + + /* Determine whether the machine is SMP or not. */ + __is_smp = is_smp_system (); } strong_alias (__pthread_initialize_minimal_internal, __pthread_initialize_minimal) diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index 560457908a..ba9529f01b 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -45,6 +45,12 @@ #endif +/* Adaptive mutex definitions. */ +#ifndef MAX_ADAPTIVE_COUNT +# define MAX_ADAPTIVE_COUNT 100 +#endif + + /* Internal variables. */ @@ -55,6 +61,9 @@ extern size_t __default_stacksize attribute_hidden; extern size_t __static_tls_size attribute_hidden; extern size_t __static_tls_align_m1 attribute_hidden; +/* Flag whether the machine is SMP or not. */ +extern int __is_smp attribute_hidden; + /* Thread descriptor handling. */ extern list_t __stack_user; hidden_proto (__stack_user) diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c index a95f97ad4f..074941daf3 100644 --- a/nptl/pthread_mutex_init.c +++ b/nptl/pthread_mutex_init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -50,6 +50,7 @@ __pthread_mutex_init (mutex, mutexattr) // mutex->__count = 0; already done by memset // mutex->__owner = 0; already done by memset // mutex->__nusers = 0; already done by memset + // mutex->__spins = 0; already done by memset return 0; } diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c index ac770c5c00..ee39f20820 100644 --- a/nptl/pthread_mutex_lock.c +++ b/nptl/pthread_mutex_lock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -25,6 +25,7 @@ #ifndef LLL_MUTEX_LOCK # define LLL_MUTEX_LOCK(mutex) lll_mutex_lock (mutex) +# define LLL_MUTEX_TRYLOCK(mutex) lll_mutex_trylock (mutex) #endif @@ -32,6 +33,8 @@ int __pthread_mutex_lock (mutex) pthread_mutex_t *mutex; { + assert (sizeof (mutex->__size) >= sizeof (mutex->__data)); + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP)) @@ -68,10 +71,37 @@ __pthread_mutex_lock (mutex) default: /* Correct code cannot set any other type. */ case PTHREAD_MUTEX_TIMED_NP: - case PTHREAD_MUTEX_ADAPTIVE_NP: + simple: /* Normal mutex. */ LLL_MUTEX_LOCK (mutex->__data.__lock); break; + + case PTHREAD_MUTEX_ADAPTIVE_NP: + if (! __is_smp) + goto simple; + + if (LLL_MUTEX_TRYLOCK (mutex->__data.__lock) != 0) + { + int cnt = 0; + int max_cnt = MIN (MAX_ADAPTIVE_COUNT, + mutex->__data.__spins * 2 + 10); + do + { + if (cnt++ >= max_cnt) + { + LLL_MUTEX_LOCK (mutex->__data.__lock); + break; + } + +#ifdef BUSY_WAIT_NOP + BUSY_WAIT_NOP; +#endif + } + while (LLL_MUTEX_TRYLOCK (mutex->__data.__lock) != 0); + + mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8; + } + break; } /* Record the ownership. */ diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c index 8efc422042..1cd2c7e606 100644 --- a/nptl/pthread_mutex_timedlock.c +++ b/nptl/pthread_mutex_timedlock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -73,10 +73,37 @@ pthread_mutex_timedlock (mutex, abstime) default: /* Correct code cannot set any other type. */ case PTHREAD_MUTEX_TIMED_NP: - case PTHREAD_MUTEX_ADAPTIVE_NP: + simple: /* Normal mutex. */ result = lll_mutex_timedlock (mutex->__data.__lock, abstime); break; + + case PTHREAD_MUTEX_ADAPTIVE_NP: + if (! __is_smp) + goto simple; + + if (lll_mutex_trylock (mutex->__data.__lock) != 0) + { + int cnt = 0; + int max_cnt = MIN (MAX_ADAPTIVE_COUNT, + mutex->__data.__spins * 2 + 10); + do + { + if (cnt++ >= max_cnt) + { + result = lll_mutex_timedlock (mutex->__data.__lock, abstime); + break; + } + +#ifdef BUSY_WAIT_NOP + BUSY_WAIT_NOP; +#endif + } + while (lll_mutex_trylock (mutex->__data.__lock) != 0); + + mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8; + } + break; } if (result == 0) diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h index 2d8a00b93f..0fed5cc918 100644 --- a/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h @@ -1,5 +1,5 @@ /* Machine-specific pthread type layouts. Alpha version. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2004 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 @@ -56,6 +56,7 @@ typedef union /* KIND must stay at this position in the structure to maintain binary compatibility. */ int __kind; + int __spins; } __data; char __size[__SIZEOF_PTHREAD_MUTEX_T]; long int __align; diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h index 9d125e0d6d..a7079a8490 100644 --- a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004 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 @@ -80,6 +80,14 @@ __lll_mutex_trylock(int *futex) #define lll_mutex_trylock(lock) __lll_mutex_trylock (&(lock)) +static inline int __attribute__((always_inline)) +__lll_mutex_cond_trylock(int *futex) +{ + return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0; +} +#define lll_mutex_cond_trylock(lock) __lll_mutex_cond_trylock (&(lock)) + + extern void __lll_lock_wait (int *futex) attribute_hidden; static inline void __attribute__((always_inline)) diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h index fc0a54c036..f998138d7e 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 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 @@ -56,6 +56,7 @@ typedef union binary compatibility. */ int __kind; unsigned int __nusers; + int __spins; } __data; char __size[__SIZEOF_PTHREAD_MUTEX_T]; long int __align; diff --git a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h index a9823d8d4b..b86f11c9b4 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -40,6 +40,7 @@ /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) #define LLL_MUTEX_LOCK_INITIALIZER_LOCKED (1) +#define LLL_MUTEX_LOCK_INITIALIZER_WAITERS (2) #ifdef PIC @@ -60,6 +61,9 @@ # define LLL_ENTER_KERNEL "int $0x80\n\t" #endif +/* Delay in spinlock loop. */ +#define BUSY_WAIT_NOP asm ("rep; nop") + #define lll_futex_wait(futex, val) \ do { \ @@ -117,6 +121,16 @@ extern int __lll_mutex_unlock_wake (int *__futex) ret; }) +#define lll_mutex_cond_trylock(futex) \ + ({ int ret; \ + __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (futex) \ + : "r" (LLL_MUTEX_LOCK_INITIALIZER_WAITERS), \ + "m" (futex), "0" (LLL_MUTEX_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + + #define lll_mutex_lock(futex) \ (void) ({ int ignore1, ignore2; \ __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h index 6cd6c05705..e4c15d1e20 100644 --- a/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2003. @@ -56,6 +56,7 @@ typedef union /* KIND must stay at this position in the structure to maintain binary compatibility. */ int __kind; + int __spins; } __data; char __size[__SIZEOF_PTHREAD_MUTEX_T]; long int __align; diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h index e462776c02..6ed21fdc14 100644 --- a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2003. @@ -31,6 +31,9 @@ #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +/* Delay in spinlock loop. */ +#define BUSY_WAIT_NOP asm ("hint @pause") + /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) @@ -62,6 +65,11 @@ #define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex)) +#define __lll_mutex_cond_trylock(futex) \ + (atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0) +#define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex)) + + extern void __lll_lock_wait (int *futex) attribute_hidden; diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h index 2d98a80e36..d6d94cda24 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h @@ -1,5 +1,5 @@ /* Machine-specific pthread type layouts. PowerPC version. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Paul Mackerras , 2003. @@ -76,6 +76,7 @@ typedef union #if __WORDSIZE != 64 unsigned int __nusers; #endif + int __spins; } __data; char __size[__SIZEOF_PTHREAD_MUTEX_T]; long int __align; diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h index a715879dbd..e9f895d6e8 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Paul Mackerras , 2003. @@ -100,6 +100,21 @@ #define lll_mutex_trylock(lock) __lll_trylock (&(lock)) +/* Set *futex to 2 if it is 0, atomically. Returns the old value */ +#define lll_mutex_cond_trylock(futex) \ + ({ int __val; \ + __asm __volatile ("1: lwarx %0,0,%2\n" \ + " cmpwi 0,%0,0\n" \ + " bne 2f\n" \ + " stwcx. %3,0,%2\n" \ + " bne- 1b\n" \ + "2: " __lll_acq_instr \ + : "=&r" (__val), "=m" (*futex) \ + : "r" (futex), "r" (2), "1" (*futex) \ + : "cr0", "memory"); \ + __val; \ + }) + extern void __lll_lock_wait (int *futex) attribute_hidden; diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c b/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c index d253c72ea4..990db87416 100644 --- a/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c +++ b/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c @@ -1,6 +1,7 @@ #include #define LLL_MUTEX_LOCK(mutex) lll_mutex_cond_lock(mutex) +#define LLL_MUTEX_TRYLOCK(mutex) lll_mutex_cond_trylock(mutex) #define __pthread_mutex_lock __pthread_mutex_cond_lock #define NO_INCR diff --git a/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h index 022ba4982b..e2606aff8e 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Martin Schwidefsky , 2003. @@ -75,6 +75,7 @@ typedef union #if __WORDSIZE != 64 unsigned int __nusers; #endif + int __spins; } __data; char __size[__SIZEOF_PTHREAD_MUTEX_T]; long int __align; diff --git a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h index 5751206dd9..8b460eb98f 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Martin Schwidefsky , 2003. @@ -127,6 +127,20 @@ __lll_mutex_trylock (int *futex) #define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex)) +static inline int +__attribute__ ((always_inline)) +__lll_mutex_cond_trylock (int *futex) +{ + unsigned int old; + + __asm __volatile ("cs %0,%3,%1" + : "=d" (old), "=Q" (*futex) + : "0" (0), "d" (2), "m" (*futex) : "cc" ); + return old != 0; +} +#define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex)) + + extern void __lll_lock_wait (int *futex) attribute_hidden; static inline void diff --git a/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h index 3cd84864f4..7d05908778 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -57,6 +57,7 @@ typedef union binary compatibility. */ int __kind; unsigned int __nusers; + int __spins; } __data; char __size[__SIZEOF_PTHREAD_MUTEX_T]; long int __align; diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h index 37842263b6..00ff1b20fb 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004 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 @@ -31,6 +31,7 @@ /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) #define LLL_MUTEX_LOCK_INITIALIZER_LOCKED (1) +#define LLL_MUTEX_LOCK_INITIALIZER_WAITERS (2) extern int __lll_mutex_lock_wait (int val, int *__futex) attribute_hidden; extern int __lll_mutex_timedlock_wait (int val, int *__futex, @@ -61,6 +62,28 @@ extern int __lll_mutex_unlock_wake (int *__futex) attribute_hidden; : "r0", "r1", "r2", "t", "memory"); \ __result; }) +#define lll_mutex_cond_trylock(futex) \ + ({ unsigned char __result; \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%1,r2\n\ + cmp/eq r2,%3\n\ + bf 1f\n\ + mov.l %2,@%1\n\ + 1: mov r1,r15\n\ + mov #-1,%0\n\ + negc %0,%0"\ + : "=r" (__result) \ + : "r" (&(futex)), \ + "r" (LLL_MUTEX_LOCK_INITIALIZER_WAITERS), \ + "r" (LLL_MUTEX_LOCK_INITIALIZER) \ + : "r0", "r1", "r2", "t", "memory"); \ + __result; }) + #define lll_mutex_lock(futex) \ (void) ({ int __result, val, *__futex = &(futex); \ __asm __volatile ("\ diff --git a/nptl/sysdeps/unix/sysv/linux/sh/smp.h b/nptl/sysdeps/unix/sysv/linux/sh/smp.h new file mode 100644 index 0000000000..2c0cbe99ac --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/smp.h @@ -0,0 +1,24 @@ +/* Determine whether the host has multiple processors. SH version. + Copyright (C) 2002 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 + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +static inline int +is_smp_system (void) +{ + return 0; +} diff --git a/nptl/sysdeps/unix/sysv/linux/smp.h b/nptl/sysdeps/unix/sysv/linux/smp.h new file mode 100644 index 0000000000..718fab683b --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/smp.h @@ -0,0 +1,50 @@ +/* Determine whether the host has multiple processors. Linux version. + Copyright (C) 1996, 2002, 2004 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 + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +/* Test whether the machine has more than one processor. This is not the + best test but good enough. More complicated tests would require `malloc' + which is not available at that time. */ +static inline int +is_smp_system (void) +{ + static const int sysctl_args[] = { CTL_KERN, KERN_VERSION }; + char buf[512]; + size_t reslen = sizeof (buf); + + /* Try reading the number using `sysctl' first. */ + if (__sysctl ((int *) sysctl_args, + sizeof (sysctl_args) / sizeof (sysctl_args[0]), + buf, &reslen, NULL, 0) < 0) + { + /* This was not successful. Now try reading the /proc filesystem. */ + int fd = __open ("/proc/sys/kernel/version", O_RDONLY); + if (__builtin_expect (fd, 0) == -1 + || (reslen = __read (fd, buf, sizeof (buf))) <= 0) + /* This also didn't work. We give up and say it's a UP machine. */ + buf[0] = '\0'; + + __close (fd); + } + + return strstr (buf, "SMP") != NULL; +} diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h index b947439e34..d123fd059f 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h @@ -1,5 +1,5 @@ /* Machine-specific pthread type layouts. SPARC version. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2003. @@ -76,6 +76,7 @@ typedef union #if __WORDSIZE != 64 unsigned int __nusers; #endif + int __spins; } __data; char __size[__SIZEOF_PTHREAD_MUTEX_T]; long int __align; diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h index 76ec431a6c..05bc5a2974 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2003. @@ -86,6 +86,14 @@ __lll_mutex_trylock (int *futex) } #define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex)) +static inline int +__attribute__ ((always_inline)) +__lll_mutex_cond_trylock (int *futex) +{ + return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0; +} +#define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex)) + extern void __lll_lock_wait (int *futex) attribute_hidden; @@ -124,7 +132,7 @@ __lll_mutex_timedlock (int *futex, const struct timespec *abstime) { int val = atomic_compare_and_exchange_val_acq (futex, 1, 0); int result = 0; - + if (__builtin_expect (val != 0, 0)) result = __lll_timedlock_wait (futex, abstime); return result; diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h index 3f151d04ed..1b4820eb0c 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -56,6 +56,7 @@ typedef union /* KIND must stay at this position in the structure to maintain binary compatibility. */ int __kind; + int __spins; } __data; char __size[__SIZEOF_PTHREAD_MUTEX_T]; long int __align; diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h index 156d1f7c64..ca8d568038 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -40,6 +40,10 @@ /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) #define LLL_MUTEX_LOCK_INITIALIZER_LOCKED (1) +#define LLL_MUTEX_LOCK_INITIALIZER_WAITERS (2) + +/* Delay in spinlock loop. */ +#define BUSY_WAIT_NOP asm ("rep; nop") #define lll_futex_wait(futex, val) \ @@ -77,9 +81,14 @@ extern int __lll_mutex_timedlock_wait (int *__futex, int __val, extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden; +/* NB: in the lll_mutex_trylock macro we simply return the value in %eax + after the cmpxchg instruction. In case the operation succeded this + value is zero. In case the operation failed, the cmpxchg instruction + has loaded the current value of the memory work which is guaranteed + to be nonzero. */ #define lll_mutex_trylock(futex) \ - ({ unsigned char ret; \ - __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1; setne %0" \ + ({ int ret; \ + __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \ : "=a" (ret), "=m" (futex) \ : "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), "m" (futex),\ "0" (LLL_MUTEX_LOCK_INITIALIZER) \ @@ -87,6 +96,16 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden; ret; }) +#define lll_mutex_cond_trylock(futex) \ + ({ int ret; \ + __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (futex) \ + : "r" (LLL_MUTEX_LOCK_INITIALIZER_WAITERS), \ + "m" (futex), "0" (LLL_MUTEX_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + + #define lll_mutex_lock(futex) \ (void) ({ int ignore1, ignore2, ignore3; \ __asm __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t" \ diff --git a/nptl/tst-mutex5.c b/nptl/tst-mutex5.c index a615012507..eb35b78d36 100644 --- a/nptl/tst-mutex5.c +++ b/nptl/tst-mutex5.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -25,6 +25,11 @@ #include +#ifndef TYPE +# define TYPE PTHREAD_MUTEX_NORMAL +#endif + + static int do_test (void) { @@ -33,13 +38,32 @@ do_test (void) struct timeval tv; struct timeval tv2; int err; + pthread_mutexattr_t a; + + if (pthread_mutexattr_init (&a) != 0) + { + puts ("mutexattr_init failed"); + return 1; + } + + if (pthread_mutexattr_settype (&a, TYPE) != 0) + { + puts ("mutexattr_settype failed"); + return 1; + } - if (pthread_mutex_init (&m, NULL) != 0) + if (pthread_mutex_init (&m, &a) != 0) { puts ("mutex_init failed"); return 1; } + if (pthread_mutexattr_destroy (&a) != 0) + { + puts ("mutexattr_destroy failed"); + return 1; + } + if (pthread_mutex_lock (&m) != 0) { puts ("mutex_lock failed"); diff --git a/nptl/tst-mutex5a.c b/nptl/tst-mutex5a.c new file mode 100644 index 0000000000..f91eec0d7d --- /dev/null +++ b/nptl/tst-mutex5a.c @@ -0,0 +1,2 @@ +#define TYPE PTHREAD_MUTEX_ADAPTIVE_NP +#include "tst-mutex5.c" diff --git a/nptl/tst-mutex7.c b/nptl/tst-mutex7.c index 183fd10f82..a9b9f318cb 100644 --- a/nptl/tst-mutex7.c +++ b/nptl/tst-mutex7.c @@ -22,7 +22,12 @@ #include -static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +#ifndef INIT +# define INIT PTHREAD_MUTEX_INITIALIZER +#endif + + +static pthread_mutex_t lock = INIT; #define ROUNDS 1000 diff --git a/nptl/tst-mutex7a.c b/nptl/tst-mutex7a.c new file mode 100644 index 0000000000..f08799ae79 --- /dev/null +++ b/nptl/tst-mutex7a.c @@ -0,0 +1,2 @@ +#define INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +#include "tst-mutex7.c"