From 009a69f0bcce04d3743c9b59246e6885dbd2b100 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 27 Jul 2009 06:55:04 -0700 Subject: [PATCH 1/7] No need for special strcmp for rtld. --- ChangeLog | 1 - sysdeps/x86_64/rtld-strcmp.S | 28 ---------------------------- 2 files changed, 29 deletions(-) delete mode 100644 sysdeps/x86_64/rtld-strcmp.S diff --git a/ChangeLog b/ChangeLog index 12ac487385..801ec189d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,7 +7,6 @@ * sysdeps/x86_64/rtld-memcmp.c: New file. * sysdeps/x86_64/rtld-rawmemchr.c: New file. * sysdeps/x86_64/rtld-strchr.S: New file. - * sysdeps/x86_64/rtld-strcmp.S: New file. * sysdeps/x86_64/rtld-strlen.S: New file. * sysdeps/x86_64/multiarch/rtld-rawmemchr.c: New file. * sysdeps/x86_64/multiarch/rtld-strlen.S: New file. diff --git a/sysdeps/x86_64/rtld-strcmp.S b/sysdeps/x86_64/rtld-strcmp.S deleted file mode 100644 index a25535c161..0000000000 --- a/sysdeps/x86_64/rtld-strcmp.S +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include "asm-syntax.h" -#include "bp-sym.h" -#include "bp-asm.h" - -#ifndef LABEL -#define LABEL(l) L(l) -#endif - - .text -ENTRY (BP_SYM (STRCMP)) -/* Simple version since we can't use SSE registers in ld.so. */ -L(oop): movb (%rdi), %al - cmpb (%rsi), %al - jne L(neq) - incq %rdi - incq %rsi - testb %al, %al - jnz L(oop) - - xorl %eax, %eax - ret - -L(neq): movl $1, %eax - movl $-1, %ecx - cmovbl %ecx, %eax - ret -END (BP_SYM (STRCMP)) From 09cd1f575476a48b262e4e45997bb56753f9d4f5 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 27 Jul 2009 07:25:57 -0700 Subject: [PATCH 2/7] Fix STB_GNU_UNIQUE handling for > 30 unique symbols. There were several issues when the initial 31 entries hashtab filled up. size * 3 <= tab->n_elements is always false, table can't have more elements than its size. I assume from libiberty/hashtab.c this meant to be check for 3/4 full. Even after fixing that, _dl_higher_prime_number (31) apparently returns 31, only _dl_higher_prime_number (32) returns 61. And, size variable wasn't updated during reallocation, which means during reallocation the insertion of the new entry was done into a wrong spot. All this lead to a hang in ld.so, because a search with n_elements 31 size 31 wouldn't ever terminate. --- ChangeLog | 6 ++++++ elf/dl-lookup.c | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 801ec189d0..8cc2e675c9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-07-27 Jakub Jelinek + + * elf/dl-lookup.c (do_lookup_x): Fix check for table more than + 3/4 full. Pass size + 1 rather than size to _dl_higher_prime_number. + Update size when reallocating. + 2009-07-26 Ulrich Drepper * sysdeps/x86_64/tst-xmmymm.sh: New file. Check whether any of the diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 18f728812e..1d68d67a35 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -377,10 +377,10 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, idx -= size; } - if (size * 3 <= tab->n_elements) + if (size * 3 <= tab->n_elements * 4) { /* Expand the table. */ - size_t newsize = _dl_higher_prime_number (size); + size_t newsize = _dl_higher_prime_number (size + 1); struct unique_sym *newentries = calloc (sizeof (struct unique_sym), newsize); if (newentries == NULL) @@ -398,6 +398,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, tab->free (entries); tab->size = newsize; + size = newsize; entries = tab->entries = newentries; tab->free = free; } From 2d0671cbbdade9013d6fd5153d01bd5e1d3f60cb Mon Sep 17 00:00:00 2001 From: Adam Tkac Date: Mon, 27 Jul 2009 07:33:48 -0700 Subject: [PATCH 3/7] Define and implement RES_USE_DNSSEC option in resolver. --- ChangeLog | 10 ++++++++++ resolv/res_debug.c | 2 ++ resolv/res_mkquery.c | 10 +++++++++- resolv/res_query.c | 8 ++++---- resolv/resolv.h | 1 + 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8cc2e675c9..e31b72ff65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-07-27 Ulrich Drepper + + * resolv/resolv.h (RES_USE_DNSSEC): Define. + * resolv/res_debug.c (p_option): Handle RES_USE_EDNS0 and + RES_USE_DNSSEC. + * resolv/res_mkquery.c (__res_nopt): Set flags for RES_USE_DNSSEC. + * resolv/res_query.c (__libc_res_nquery): Handle RES_USE_DNSSEC in + all the places we handled RES_USE_EDNS0 only before. + Patch by Adam Tkac . + 2009-07-27 Jakub Jelinek * elf/dl-lookup.c (do_lookup_x): Fix check for table more than diff --git a/resolv/res_debug.c b/resolv/res_debug.c index c38de640a5..f7996a71da 100644 --- a/resolv/res_debug.c +++ b/resolv/res_debug.c @@ -586,6 +586,8 @@ p_option(u_long option) { case RES_ROTATE: return "rotate"; case RES_NOCHECKNAME: return "no-check-names"; case RES_USEBSTRING: return "ip6-bytstring"; + case RES_USE_EDNS0: return "edns0"; + case RES_USE_DNSSEC: return "dnssec"; /* XXX nonreentrant */ default: sprintf(nbuf, "?0x%lx?", (u_long)option); return (nbuf); diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c index 2dda4c0f45..2bc2d2497f 100644 --- a/resolv/res_mkquery.c +++ b/resolv/res_mkquery.c @@ -247,7 +247,15 @@ __res_nopt(res_state statp, NS_PUT16(MIN(anslen, 0xffff), cp); /* CLASS = UDP payload size */ *cp++ = NOERROR; /* extended RCODE */ *cp++ = 0; /* EDNS version */ - /* XXX Once we support DNSSEC we change the flag value here. */ + + if (statp->options & RES_USE_DNSSEC) { +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_opt()... ENDS0 DNSSEC\n"); +#endif + flags |= NS_OPT_DNSSEC_OK; + } + NS_PUT16(flags, cp); NS_PUT16(0, cp); /* RDLEN */ hp->arcount = htons(ntohs(hp->arcount) + 1); diff --git a/resolv/res_query.c b/resolv/res_query.c index 9ffb3e3685..5ff352e2fc 100644 --- a/resolv/res_query.c +++ b/resolv/res_query.c @@ -147,7 +147,7 @@ __libc_res_nquery(res_state statp, if (n > 0) { if ((oflags & RES_F_EDNS0ERR) == 0 - && (statp->options & RES_USE_EDNS0) != 0) + && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) { n = __res_nopt(statp, n, query1, bufsize, anslen / 2); if (n < 0) @@ -169,7 +169,7 @@ __libc_res_nquery(res_state statp, NULL, query2, bufsize - nused); if (n > 0 && (oflags & RES_F_EDNS0ERR) == 0 - && (statp->options & RES_USE_EDNS0) != 0) + && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) n = __res_nopt(statp, n, query2, bufsize - nused - n, anslen / 2); nquery2 = n; @@ -184,7 +184,7 @@ __libc_res_nquery(res_state statp, if (n > 0 && (oflags & RES_F_EDNS0ERR) == 0 - && (statp->options & RES_USE_EDNS0) != 0) + && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) n = __res_nopt(statp, n, query1, bufsize, anslen); nquery1 = n; @@ -203,7 +203,7 @@ __libc_res_nquery(res_state statp, } if (__builtin_expect (n <= 0, 0)) { /* If the query choked with EDNS0, retry without EDNS0. */ - if ((statp->options & RES_USE_EDNS0) != 0 + if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0 && ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) { statp->_flags |= RES_F_EDNS0ERR; #ifdef DEBUG diff --git a/resolv/resolv.h b/resolv/resolv.h index 3ef714f458..e49c29d2fe 100644 --- a/resolv/resolv.h +++ b/resolv/resolv.h @@ -218,6 +218,7 @@ struct res_sym { #define RES_SNGLKUP 0x00200000 /* one outstanding request at a time */ #define RES_SNGLKUPREOP 0x00400000 /* -"-, but open new socket for each request */ +#define RES_USE_DNSSEC 0x00800000 /* use DNSSEC using OK bit in OPT */ #define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT) From 87cfd82a1fc269635c9b0dd37c47470b5465e775 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 27 Jul 2009 13:23:00 -0700 Subject: [PATCH 4/7] Break out _dl_scope_free into its own file. This reduces the coarse static callgraph that can be discovered by looking at the object files. --- elf/Makefile | 2 +- elf/dl-open.c | 35 ------------------------------ elf/dl-scope.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 36 deletions(-) create mode 100644 elf/dl-scope.c diff --git a/elf/Makefile b/elf/Makefile index 21d131ec92..3baad9621d 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -29,7 +29,7 @@ routines = $(dl-routines) dl-support dl-iteratephdr \ # profiled libraries. dl-routines = $(addprefix dl-,load cache lookup object reloc deps \ runtime error init fini debug misc \ - version profile conflict tls origin \ + version profile conflict tls origin scope \ execstack caller open close trampoline) all-dl-routines = $(dl-routines) $(sysdep-dl-routines) # But they are absent from the shared libc, because that code is in ld.so. diff --git a/elf/dl-open.c b/elf/dl-open.c index b8ebfe0e60..e920c7738c 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -165,41 +165,6 @@ add_to_global (struct link_map *new) return 0; } -int -_dl_scope_free (void *old) -{ - struct dl_scope_free_list *fsl; -#define DL_SCOPE_FREE_LIST_SIZE (sizeof (fsl->list) / sizeof (fsl->list[0])) - - if (RTLD_SINGLE_THREAD_P) - free (old); - else if ((fsl = GL(dl_scope_free_list)) == NULL) - { - GL(dl_scope_free_list) = fsl = malloc (sizeof (*fsl)); - if (fsl == NULL) - { - THREAD_GSCOPE_WAIT (); - free (old); - return 1; - } - else - { - fsl->list[0] = old; - fsl->count = 1; - } - } - else if (fsl->count < DL_SCOPE_FREE_LIST_SIZE) - fsl->list[fsl->count++] = old; - else - { - THREAD_GSCOPE_WAIT (); - while (fsl->count > 0) - free (fsl->list[--fsl->count]); - return 1; - } - return 0; -} - static void dl_open_worker (void *a) { diff --git a/elf/dl-scope.c b/elf/dl-scope.c new file mode 100644 index 0000000000..229177ed34 --- /dev/null +++ b/elf/dl-scope.c @@ -0,0 +1,58 @@ +/* Memory handling for the scope data structures. + Copyright (C) 2009 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +int +_dl_scope_free (void *old) +{ + struct dl_scope_free_list *fsl; +#define DL_SCOPE_FREE_LIST_SIZE (sizeof (fsl->list) / sizeof (fsl->list[0])) + + if (RTLD_SINGLE_THREAD_P) + free (old); + else if ((fsl = GL(dl_scope_free_list)) == NULL) + { + GL(dl_scope_free_list) = fsl = malloc (sizeof (*fsl)); + if (fsl == NULL) + { + THREAD_GSCOPE_WAIT (); + free (old); + return 1; + } + else + { + fsl->list[0] = old; + fsl->count = 1; + } + } + else if (fsl->count < DL_SCOPE_FREE_LIST_SIZE) + fsl->list[fsl->count++] = old; + else + { + THREAD_GSCOPE_WAIT (); + while (fsl->count > 0) + free (fsl->list[--fsl->count]); + return 1; + } + return 0; +} From e83c1a8a72b3ea3009e18ecb3fc0778e81655d3b Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 27 Jul 2009 13:40:27 -0700 Subject: [PATCH 5/7] Refine testing for xmm/ymm register use in x86-64 ld.so. The test now takes the callgraph into account. Only code called during runtime relocation is affected by the limitation. We now determine the affected object files as closely as possible from the outside. This allowed to remove some the specializations for some of the string functions as they are only used in other code paths. --- ChangeLog | 14 ++++ sysdeps/x86_64/Makefile | 1 + sysdeps/x86_64/multiarch/rtld-rawmemchr.c | 1 - sysdeps/x86_64/rtld-memchr.c | 1 - sysdeps/x86_64/rtld-rawmemchr.c | 1 - sysdeps/x86_64/tst-xmmymm.sh | 80 ++++++++++++++++++++--- 6 files changed, 86 insertions(+), 12 deletions(-) delete mode 100644 sysdeps/x86_64/multiarch/rtld-rawmemchr.c delete mode 100644 sysdeps/x86_64/rtld-memchr.c delete mode 100644 sysdeps/x86_64/rtld-rawmemchr.c diff --git a/ChangeLog b/ChangeLog index e31b72ff65..60b76547c1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ 2009-07-27 Ulrich Drepper + * sysdeps/x86_64/tst-xmmymm.sh: Refine testing. The script now + determines which files are used in runtime lookups and only checks + those for SSE use. + * sysdeps/x86_64/rtld-memchr.c: Removed. Not needed with refined + testing. + * sysdeps/x86_64/rtld-rawmemchr.c: Removed. + * sysdeps/x86_64/multiarch/rtld-rawmemchr.c: Removed + * sysdeps/x86_64/Makefile: Emit warning that tst-xmmymm.sh might + take a while. + + * elf/dl-open.c: Move _dl_scope_free to... + * elf/dl-scope.c: ...here. New file. + * elf/Makefile (dl-routines): Add scope. + * resolv/resolv.h (RES_USE_DNSSEC): Define. * resolv/res_debug.c (p_option): Handle RES_USE_EDNS0 and RES_USE_DNSSEC. diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile index 57cd88432a..e8d0285e26 100644 --- a/sysdeps/x86_64/Makefile +++ b/sysdeps/x86_64/Makefile @@ -22,6 +22,7 @@ sysdep-rtld-routines += tlsdesc dl-tlsdesc tests: $(objpfx)tst-xmmymm.out $(objpfx)tst-xmmymm.out: ../sysdeps/x86_64/tst-xmmymm.sh $(objpfx)ld.so + @echo "Checking ld.so for SSE register use. This will take a few seconds..." $(SHELL) -e $< $(objpfx) > $@ endif diff --git a/sysdeps/x86_64/multiarch/rtld-rawmemchr.c b/sysdeps/x86_64/multiarch/rtld-rawmemchr.c deleted file mode 100644 index 53a90675ab..0000000000 --- a/sysdeps/x86_64/multiarch/rtld-rawmemchr.c +++ /dev/null @@ -1 +0,0 @@ -#include "../rtld-rawmemchr.c" diff --git a/sysdeps/x86_64/rtld-memchr.c b/sysdeps/x86_64/rtld-memchr.c deleted file mode 100644 index f63fefbcec..0000000000 --- a/sysdeps/x86_64/rtld-memchr.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/sysdeps/x86_64/rtld-rawmemchr.c b/sysdeps/x86_64/rtld-rawmemchr.c deleted file mode 100644 index 2b9189393c..0000000000 --- a/sysdeps/x86_64/rtld-rawmemchr.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/sysdeps/x86_64/tst-xmmymm.sh b/sysdeps/x86_64/tst-xmmymm.sh index 0735276e6d..a576e7da0d 100755 --- a/sysdeps/x86_64/tst-xmmymm.sh +++ b/sysdeps/x86_64/tst-xmmymm.sh @@ -1,17 +1,79 @@ -#! /bin/sh +#! /bin/bash objpfx="$1" tmp=$(mktemp ${objpfx}tst-xmmymm.XXXXXX) trap 'rm -f "$tmp"' 1 2 3 15 -objdump -d "${objpfx}ld.so" | -awk 'BEGIN { last="" } /^[[:xdigit:]]* <[_[:alnum:]]*>:$/ { fct=substr($2, 2, length($2)-3) } /,%[xy]mm[[:digit:]]*$/ { if (last != fct) { print fct; last=fct} }' | -tee "$tmp" +# List of object files we have to test +rtldobjs=$(readelf -W -wi ${objpfx}dl-allobjs.os | + awk '/^ "$tmp" +declare -a objects +objects=($(cat "$tmp")) + +objs="dl-runtime.os" +tocheck="dl-runtime.os" + +while test -n "$objs"; do + this="$objs" + objs="" + + for f in $this; do + undef=$(nm -u "$objpfx"../*/"$f" | awk '{print $2}') + if test -n "$undef"; then + for s in $undef; do + for obj in ${objects[*]} "_GLOBAL_OFFSET_TABLE_"; do + if test "$obj" = "$s"; then + continue 2 + fi + done + for o in $rtldobjs; do + ro=$(echo "$objpfx"../*/"$o") + if nm -g --defined-only "$ro" | egrep -qs " $s\$"; then + if ! (echo "$tocheck $objs" | fgrep -qs "$o"); then + echo "$o needed for $s" + objs="$objs $o" + fi + break; + fi + done + done + fi + done + tocheck="$tocheck$objs" +done + +echo +echo +echo "object files needed: $tocheck" + +cp /dev/null "$tmp" +for f in $tocheck; do + objdump -d "$objpfx"../*/"$f" | + awk 'BEGIN { last="" } /^[[:xdigit:]]* <[_[:alnum:]]*>:$/ { fct=substr($2, 2, length($2)-3) } /,%[xy]mm[[:digit:]]*$/ { if (last != fct) { print fct; last=fct} }' | + while read fct; do + if test "$fct" != "_dl_runtime_profile"; then + echo "function $fct in $f modifies xmm/ymm" >> "$tmp" + result=1 + fi + done +done + +if test -s "$tmp"; then + echo + echo + cat "$tmp" + result=1 +else + result=0 +fi rm "$tmp" -exit $err +exit $result From 052757bfa652d86d7976df430a5272df1f560076 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 27 Jul 2009 13:43:01 -0700 Subject: [PATCH 6/7] Revert "Memory ordering in pthread_mutex_{,timed}lock." This reverts commit 7b7f43bed134db6a0da34282fffcbf0af10d4613. --- nptl/ChangeLog | 7 ------- nptl/pthread_mutex_lock.c | 12 ++++++------ nptl/pthread_mutex_timedlock.c | 12 ++++++------ 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 222112161a..cb9ec53cd1 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,10 +1,3 @@ -2009-07-26 Ulrich Drepper - - [BZ #10418] - * pthread_mutex_lock.c (pthread_mutex_lock): Use _rel instead of of - _acq variants of cmpxchg. - * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise. - 2009-07-23 Ulrich Drepper * sysdeps/x86_64/configure.in: New file. diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c index a0ff881faf..406e588fdb 100644 --- a/nptl/pthread_mutex_lock.c +++ b/nptl/pthread_mutex_lock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002-2007, 2008, 2009 Free Software Foundation, Inc. +/* Copyright (C) 2002-2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -160,7 +160,7 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) #endif newval - = atomic_compare_and_exchange_val_rel (&mutex->__data.__lock, + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, newval, oldval); if (newval != oldval) @@ -285,7 +285,7 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) #ifdef NO_INCR newval |= FUTEX_WAITERS; #endif - oldval = atomic_compare_and_exchange_val_rel (&mutex->__data.__lock, + oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, newval, 0); if (oldval != 0) @@ -420,7 +420,7 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) oldprio = ceiling; oldval - = atomic_compare_and_exchange_val_rel (&mutex->__data.__lock, + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, #ifdef NO_INCR ceilval | 2, #else @@ -434,7 +434,7 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) do { oldval - = atomic_compare_and_exchange_val_rel (&mutex->__data.__lock, + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, ceilval | 2, ceilval | 1); @@ -445,7 +445,7 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) lll_futex_wait (&mutex->__data.__lock, ceilval | 2, PTHREAD_MUTEX_PSHARED (mutex)); } - while (atomic_compare_and_exchange_val_rel (&mutex->__data.__lock, + while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, ceilval | 2, ceilval) != ceilval); } diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c index 2c6ff114da..8d0db79d58 100644 --- a/nptl/pthread_mutex_timedlock.c +++ b/nptl/pthread_mutex_timedlock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002-2007, 2008, 2009 Free Software Foundation, Inc. +/* Copyright (C) 2002-2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -126,7 +126,7 @@ pthread_mutex_timedlock (mutex, abstime) int newval = id | (oldval & FUTEX_WAITERS); newval - = atomic_compare_and_exchange_val_rel (&mutex->__data.__lock, + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, newval, oldval); if (newval != oldval) { @@ -246,7 +246,7 @@ pthread_mutex_timedlock (mutex, abstime) } } - oldval = atomic_compare_and_exchange_val_rel (&mutex->__data.__lock, + oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, id, 0); if (oldval != 0) @@ -404,7 +404,7 @@ pthread_mutex_timedlock (mutex, abstime) oldprio = ceiling; oldval - = atomic_compare_and_exchange_val_rel (&mutex->__data.__lock, + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, ceilval | 1, ceilval); if (oldval == ceilval) @@ -413,7 +413,7 @@ pthread_mutex_timedlock (mutex, abstime) do { oldval - = atomic_compare_and_exchange_val_rel (&mutex->__data.__lock, + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, ceilval | 2, ceilval | 1); @@ -456,7 +456,7 @@ pthread_mutex_timedlock (mutex, abstime) PTHREAD_MUTEX_PSHARED (mutex)); } } - while (atomic_compare_and_exchange_val_rel (&mutex->__data.__lock, + while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, ceilval | 2, ceilval) != ceilval); } From e73e694e38b7b222eec3ec5897eb507d88bb8928 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 27 Jul 2009 13:46:56 -0700 Subject: [PATCH 7/7] pthread_mutex_unlock needs to use _rel semantics for atomic ops. --- nptl/ChangeLog | 6 ++++++ nptl/pthread_mutex_unlock.c | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/nptl/ChangeLog b/nptl/ChangeLog index cb9ec53cd1..8dd93732b5 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,9 @@ +2009-07-27 Ulrich Drepper + + [BZ #10418] + * pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Use _rel + instead of of _acq variants of cmpxchg. + 2009-07-23 Ulrich Drepper * sysdeps/x86_64/configure.in: New file. diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c index 0028c5583f..fbe8274a55 100644 --- a/nptl/pthread_mutex_unlock.c +++ b/nptl/pthread_mutex_unlock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005-2007, 2008 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005-2008, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -213,7 +213,7 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) /* Unlock. */ if ((mutex->__data.__lock & FUTEX_WAITERS) != 0 - || atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock, 0, + || atomic_compare_and_exchange_bool_rel (&mutex->__data.__lock, 0, THREAD_GETMEM (THREAD_SELF, tid))) { @@ -263,7 +263,7 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) oldval = mutex->__data.__lock; newval = oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK; } - while (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock, + while (atomic_compare_and_exchange_bool_rel (&mutex->__data.__lock, newval, oldval)); if ((oldval & ~PTHREAD_MUTEX_PRIO_CEILING_MASK) > 1)