From 609cf61467154868c88b1ede078322fb4b48a528 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 18 Oct 2006 19:26:30 +0000 Subject: [BZ #3313] 2006-10-17 Jakub Jelinek * sunrpc/xdr_mem.c (xdrmem_setpos): Don't compare addresses as signed longs, check for x_base + pos overflow. * sunrpc/Makefile (tests): Add tst-xdrmem2. * sunrpc/tst-xdrmem2.c: New test. 2006-10-18 Ulrich Drepper * elf/dl-lookup.c (_dl_lookup_symbol_x): Add warning to _dl_lookup_symbol_x code. 2006-10-17 Jakub Jelinek * elf/dl-runtime.c: Include sysdep-cancel.h. (_dl_fixup, _dl_profile_fixup): Use __rtld_mrlock_* and scoperec->nusers only if !SINGLE_THREAD_P. Use atomic_* instead of catomic_* macros. * elf/dl-sym.c: Include sysdep-cancel.h. (do_sym): Use __rtld_mrlock_* and scoperec->nusers only if !SINGLE_THREAD_P. Use atomic_* instead of catomic_* macros. * elf/dl-close.c: Include sysdep-cancel.h. (_dl_close): Use __rtld_mrlock_* and scoperec->nusers only if !SINGLE_THREAD_P. Use atomic_* instead of catomic_* macros. * elf/dl-open.c: Include sysdep-cancel.h. (dl_open_worker): Use __rtld_mrlock_* and scoperec->nusers only if !SINGLE_THREAD_P. Use atomic_* instead of catomic_* macros. 2006-10-17 Jakub Jelinek [BZ #3313] * malloc/malloc.c (malloc_consolidate): Set maxfb to address of last fastbin rather than end of fastbin array. 2006-10-18 Ulrich Drepper * sysdeps/i386/i486/bits/atomic.h (catomic_decrement): Use correct body macro. * sysdeps/x86_64/bits/atomic.h (__arch_c_compare_and_exchange_val_64_acq): Add missing casts. (catomic_decrement): Use correct body macro. 2006-10-17 Jakub Jelinek * include/atomic.h: Add a unique prefix to all local variables in macros. * csu/tst-atomic.c (do_test): Test also catomic_* macros. * include/link.h: Include . Define struct --- ChangeLog | 50 ++++- csu/tst-atomic.c | 113 ++++++++++- elf/dl-close.c | 24 ++- elf/dl-lookup.c | 6 +- elf/dl-open.c | 10 +- elf/dl-runtime.c | 17 +- elf/dl-sym.c | 7 +- include/atomic.h | 286 +++++++++++++-------------- malloc/malloc.c | 2 +- nptl/ChangeLog | 6 + nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h | 18 +- sunrpc/Makefile | 4 +- sunrpc/tst-xdrmem2.c | 114 +++++++++++ sunrpc/xdr_mem.c | 10 +- sysdeps/i386/i486/bits/atomic.h | 2 +- sysdeps/x86_64/bits/atomic.h | 15 +- 16 files changed, 491 insertions(+), 193 deletions(-) create mode 100644 sunrpc/tst-xdrmem2.c diff --git a/ChangeLog b/ChangeLog index 3c9628c131..c36631cd1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,51 @@ +2006-10-17 Jakub Jelinek + + * sunrpc/xdr_mem.c (xdrmem_setpos): Don't compare addresses + as signed longs, check for x_base + pos overflow. + * sunrpc/Makefile (tests): Add tst-xdrmem2. + * sunrpc/tst-xdrmem2.c: New test. + +2006-10-18 Ulrich Drepper + + * elf/dl-lookup.c (_dl_lookup_symbol_x): Add warning to + _dl_lookup_symbol_x code. + +2006-10-17 Jakub Jelinek + + * elf/dl-runtime.c: Include sysdep-cancel.h. + (_dl_fixup, _dl_profile_fixup): Use __rtld_mrlock_* and + scoperec->nusers only if !SINGLE_THREAD_P. Use atomic_* + instead of catomic_* macros. + * elf/dl-sym.c: Include sysdep-cancel.h. + (do_sym): Use __rtld_mrlock_* and scoperec->nusers only + if !SINGLE_THREAD_P. Use atomic_* instead of catomic_* macros. + * elf/dl-close.c: Include sysdep-cancel.h. + (_dl_close): Use __rtld_mrlock_* and scoperec->nusers only + if !SINGLE_THREAD_P. Use atomic_* instead of catomic_* macros. + * elf/dl-open.c: Include sysdep-cancel.h. + (dl_open_worker): Use __rtld_mrlock_* and scoperec->nusers only + if !SINGLE_THREAD_P. Use atomic_* instead of catomic_* macros. + +2006-10-17 Jakub Jelinek + + [BZ #3313] + * malloc/malloc.c (malloc_consolidate): Set maxfb to address of last + fastbin rather than end of fastbin array. + +2006-10-18 Ulrich Drepper + + * sysdeps/i386/i486/bits/atomic.h (catomic_decrement): Use correct + body macro. + * sysdeps/x86_64/bits/atomic.h + (__arch_c_compare_and_exchange_val_64_acq): Add missing casts. + (catomic_decrement): Use correct body macro. + +2006-10-17 Jakub Jelinek + + * include/atomic.h: Add a unique prefix to all local variables + in macros. + * csu/tst-atomic.c (do_test): Test also catomic_* macros. + 2006-10-16 Ulrich Drepper [BZ #3369] @@ -108,7 +156,7 @@ * elf/dl-load.c: Likewise. * elf/dl-object.c: Likewise. * elf/rtld.c: Likewise. - * include/link.h: Inlcude . Define struct + * include/link.h: Include . Define struct r_scoperec. Replace r_scope with pointer to r_scoperec structure. Add l_scoperec_lock. * sysdeps/generic/ldsodefs.h: Include . diff --git a/csu/tst-atomic.c b/csu/tst-atomic.c index 7a2e3d0865..7c0b022b78 100644 --- a/csu/tst-atomic.c +++ b/csu/tst-atomic.c @@ -1,5 +1,5 @@ /* Tests for atomic.h macros. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2003. @@ -379,6 +379,117 @@ do_test (void) } #endif +#ifdef catomic_compare_and_exchange_val_acq + mem = 24; + if (catomic_compare_and_exchange_val_acq (&mem, 35, 24) != 24 + || mem != 35) + { + puts ("catomic_compare_and_exchange_val_acq test 1 failed"); + ret = 1; + } + + mem = 12; + if (catomic_compare_and_exchange_val_acq (&mem, 10, 15) != 12 + || mem != 12) + { + puts ("catomic_compare_and_exchange_val_acq test 2 failed"); + ret = 1; + } + + mem = -15; + if (catomic_compare_and_exchange_val_acq (&mem, -56, -15) != -15 + || mem != -56) + { + puts ("catomic_compare_and_exchange_val_acq test 3 failed"); + ret = 1; + } + + mem = -1; + if (catomic_compare_and_exchange_val_acq (&mem, 17, 0) != -1 + || mem != -1) + { + puts ("catomic_compare_and_exchange_val_acq test 4 failed"); + ret = 1; + } +#endif + + mem = 24; + if (catomic_compare_and_exchange_bool_acq (&mem, 35, 24) + || mem != 35) + { + puts ("catomic_compare_and_exchange_bool_acq test 1 failed"); + ret = 1; + } + + mem = 12; + if (! catomic_compare_and_exchange_bool_acq (&mem, 10, 15) + || mem != 12) + { + puts ("catomic_compare_and_exchange_bool_acq test 2 failed"); + ret = 1; + } + + mem = -15; + if (catomic_compare_and_exchange_bool_acq (&mem, -56, -15) + || mem != -56) + { + puts ("catomic_compare_and_exchange_bool_acq test 3 failed"); + ret = 1; + } + + mem = -1; + if (! catomic_compare_and_exchange_bool_acq (&mem, 17, 0) + || mem != -1) + { + puts ("catomic_compare_and_exchange_bool_acq test 4 failed"); + ret = 1; + } + + mem = 2; + if (catomic_exchange_and_add (&mem, 11) != 2 + || mem != 13) + { + puts ("catomic_exchange_and_add test failed"); + ret = 1; + } + + mem = -21; + catomic_add (&mem, 22); + if (mem != 1) + { + puts ("catomic_add test failed"); + ret = 1; + } + + mem = -1; + catomic_increment (&mem); + if (mem != 0) + { + puts ("catomic_increment test failed"); + ret = 1; + } + + mem = 2; + if (catomic_increment_val (&mem) != 3) + { + puts ("catomic_increment_val test failed"); + ret = 1; + } + + mem = 17; + catomic_decrement (&mem); + if (mem != 16) + { + puts ("catomic_decrement test failed"); + ret = 1; + } + + if (catomic_decrement_val (&mem) != 15) + { + puts ("catomic_decrement_val test failed"); + ret = 1; + } + return ret; } diff --git a/elf/dl-close.c b/elf/dl-close.c index 84e57e09d0..bfcceea4bc 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -30,6 +30,7 @@ #include #include #include +#include /* Type of the constructor functions. */ @@ -419,16 +420,21 @@ _dl_close (void *_map) struct r_scoperec *old = imap->l_scoperec; - __rtld_mrlock_change (imap->l_scoperec_lock); - imap->l_scoperec = newp; - __rtld_mrlock_done (imap->l_scoperec_lock); - - if (catomic_increment_val (&old->nusers) != 1) + if (SINGLE_THREAD_P) + imap->l_scoperec = newp; + else { - old->remove_after_use = true; - old->notify = true; - if (catomic_decrement_val (&old->nusers) != 0) - __rtld_waitzero (old->nusers); + __rtld_mrlock_change (imap->l_scoperec_lock); + imap->l_scoperec = newp; + __rtld_mrlock_done (imap->l_scoperec_lock); + + if (atomic_increment_val (&old->nusers) != 1) + { + old->remove_after_use = true; + old->notify = true; + if (atomic_decrement_val (&old->nusers) != 0) + __rtld_waitzero (old->nusers); + } } /* No user anymore, we can free it now. */ diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 7cfcc620a7..72381698db 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -207,7 +207,11 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map, /* Search loaded objects' symbol tables for a definition of the symbol - UNDEF_NAME, perhaps with a requested version for the symbol. */ + UNDEF_NAME, perhaps with a requested version for the symbol. + + We must never have calls to the audit functions inside this function + or in any function which gets called. If this would happen the audit + code might create a thread which can throw off all the scope locking. */ lookup_t internal_function _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, diff --git a/elf/dl-open.c b/elf/dl-open.c index 35712b5ac0..85b9637305 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -423,15 +424,20 @@ dl_open_worker (void *a) if (old == &imap->l_scoperec_mem) imap->l_scoperec = newp; + else if (SINGLE_THREAD_P) + { + imap->l_scoperec = newp; + free (old); + } else { __rtld_mrlock_change (imap->l_scoperec_lock); imap->l_scoperec = newp; __rtld_mrlock_done (imap->l_scoperec_lock); - catomic_increment (&old->nusers); + atomic_increment (&old->nusers); old->remove_after_use = true; - if (catomic_decrement_val (&old->nusers) == 0) + if (atomic_decrement_val (&old->nusers) == 0) /* No user, we can free it here and now. */ free (old); } diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c index 05fd974bf5..8bf5b89eb6 100644 --- a/elf/dl-runtime.c +++ b/elf/dl-runtime.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "dynamic-link.h" #if (!defined ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \ @@ -93,11 +94,11 @@ _dl_fixup ( } struct r_scoperec *scoperec = l->l_scoperec; - if (l->l_type == lt_loaded) + if (l->l_type == lt_loaded && !SINGLE_THREAD_P) { __rtld_mrlock_lock (l->l_scoperec_lock); scoperec = l->l_scoperec; - catomic_increment (&scoperec->nusers); + atomic_increment (&scoperec->nusers); __rtld_mrlock_unlock (l->l_scoperec_lock); } @@ -106,8 +107,8 @@ _dl_fixup ( ELF_RTYPE_CLASS_PLT, DL_LOOKUP_ADD_DEPENDENCY, NULL); - if (l->l_type == lt_loaded - && catomic_decrement_val (&scoperec->nusers) == 0 + if (l->l_type == lt_loaded && !SINGLE_THREAD_P + && atomic_decrement_val (&scoperec->nusers) == 0 && __builtin_expect (scoperec->remove_after_use, 0)) { if (scoperec->notify) @@ -195,11 +196,11 @@ _dl_profile_fixup ( } struct r_scoperec *scoperec = l->l_scoperec; - if (l->l_type == lt_loaded) + if (l->l_type == lt_loaded && !SINGLE_THREAD_P) { __rtld_mrlock_lock (l->l_scoperec_lock); scoperec = l->l_scoperec; - catomic_increment (&scoperec->nusers); + atomic_increment (&scoperec->nusers); __rtld_mrlock_unlock (l->l_scoperec_lock); } @@ -208,8 +209,8 @@ _dl_profile_fixup ( ELF_RTYPE_CLASS_PLT, DL_LOOKUP_ADD_DEPENDENCY, NULL); - if (l->l_type == lt_loaded - && catomic_decrement_val (&scoperec->nusers) == 0 + if (l->l_type == lt_loaded && !SINGLE_THREAD_P + && atomic_decrement_val (&scoperec->nusers) == 0 && __builtin_expect (scoperec->remove_after_use, 0)) { if (scoperec->notify) diff --git a/elf/dl-sym.c b/elf/dl-sym.c index 43933466b4..34d75a1a67 100644 --- a/elf/dl-sym.c +++ b/elf/dl-sym.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef USE_TLS # include #endif @@ -115,7 +116,7 @@ do_sym (void *handle, const char *name, void *who, the initial binary. And then the more complex part where the object is dynamically loaded and the scope array can change. */ - if (match->l_type != lt_loaded) + if (match->l_type != lt_loaded || SINGLE_THREAD_P) result = GLRO(dl_lookup_symbol_x) (name, match, &ref, match->l_scoperec->scope, vers, 0, flags | DL_LOOKUP_ADD_DEPENDENCY, @@ -124,7 +125,7 @@ do_sym (void *handle, const char *name, void *who, { __rtld_mrlock_lock (match->l_scoperec_lock); struct r_scoperec *scoperec = match->l_scoperec; - catomic_increment (&scoperec->nusers); + atomic_increment (&scoperec->nusers); __rtld_mrlock_unlock (match->l_scoperec_lock); struct call_dl_lookup_args args; @@ -141,7 +142,7 @@ do_sym (void *handle, const char *name, void *who, int err = GLRO(dl_catch_error) (&objname, &errstring, &malloced, call_dl_lookup, &args); - if (catomic_decrement_val (&scoperec->nusers) == 0 + if (atomic_decrement_val (&scoperec->nusers) == 0 && __builtin_expect (scoperec->remove_after_use, 0)) { if (scoperec->notify) diff --git a/include/atomic.h b/include/atomic.h index 340c6e6bfb..ec1e9899f1 100644 --- a/include/atomic.h +++ b/include/atomic.h @@ -39,7 +39,12 @@ Architectures must provide a few lowlevel macros (the compare and exchange definitions). All others are optional. They should only be provided if the architecture has specific - support for the operation. */ + support for the operation. + + As macros are usually heavily nested and often use local + variables to make sure side-effects are evaluated properly, use for + macro local variables a per-macro unique prefix. This file uses + __atgN_ prefix where N is different in each macro. */ #include @@ -50,33 +55,33 @@ and following args. */ #define __atomic_val_bysize(pre, post, mem, ...) \ ({ \ - __typeof (*mem) __result; \ + __typeof (*mem) __atg1_result; \ if (sizeof (*mem) == 1) \ - __result = pre##_8_##post (mem, __VA_ARGS__); \ + __atg1_result = pre##_8_##post (mem, __VA_ARGS__); \ else if (sizeof (*mem) == 2) \ - __result = pre##_16_##post (mem, __VA_ARGS__); \ + __atg1_result = pre##_16_##post (mem, __VA_ARGS__); \ else if (sizeof (*mem) == 4) \ - __result = pre##_32_##post (mem, __VA_ARGS__); \ + __atg1_result = pre##_32_##post (mem, __VA_ARGS__); \ else if (sizeof (*mem) == 8) \ - __result = pre##_64_##post (mem, __VA_ARGS__); \ + __atg1_result = pre##_64_##post (mem, __VA_ARGS__); \ else \ abort (); \ - __result; \ + __atg1_result; \ }) #define __atomic_bool_bysize(pre, post, mem, ...) \ ({ \ - int __result; \ + int __atg2_result; \ if (sizeof (*mem) == 1) \ - __result = pre##_8_##post (mem, __VA_ARGS__); \ + __atg2_result = pre##_8_##post (mem, __VA_ARGS__); \ else if (sizeof (*mem) == 2) \ - __result = pre##_16_##post (mem, __VA_ARGS__); \ + __atg2_result = pre##_16_##post (mem, __VA_ARGS__); \ else if (sizeof (*mem) == 4) \ - __result = pre##_32_##post (mem, __VA_ARGS__); \ + __atg2_result = pre##_32_##post (mem, __VA_ARGS__); \ else if (sizeof (*mem) == 8) \ - __result = pre##_64_##post (mem, __VA_ARGS__); \ + __atg2_result = pre##_64_##post (mem, __VA_ARGS__); \ else \ abort (); \ - __result; \ + __atg2_result; \ }) @@ -124,8 +129,9 @@ # define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ ({ /* Cannot use __oldval here, because macros later in this file might \ call this macro with __oldval argument. */ \ - __typeof (oldval) __old = (oldval); \ - atomic_compare_and_exchange_val_acq (mem, newval, __old) != __old; \ + __typeof (oldval) __atg3_old = (oldval); \ + atomic_compare_and_exchange_val_acq (mem, newval, __atg3_old) \ + != __atg3_old; \ }) # endif #endif @@ -140,8 +146,9 @@ # define catomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ ({ /* Cannot use __oldval here, because macros later in this file might \ call this macro with __oldval argument. */ \ - __typeof (oldval) __old = (oldval); \ - catomic_compare_and_exchange_val_acq (mem, newval, __old) != __old; \ + __typeof (oldval) __atg4_old = (oldval); \ + catomic_compare_and_exchange_val_acq (mem, newval, __atg4_old) \ + != __atg4_old; \ }) # endif #endif @@ -162,18 +169,17 @@ /* Store NEWVALUE in *MEM and return the old value. */ #ifndef atomic_exchange_acq # define atomic_exchange_acq(mem, newvalue) \ - ({ __typeof (*(mem)) __oldval; \ - __typeof (mem) __memp = (mem); \ - __typeof (*(mem)) __value = (newvalue); \ + ({ __typeof (*(mem)) __atg5_oldval; \ + __typeof (mem) __atg5_memp = (mem); \ + __typeof (*(mem)) __atg5_value = (newvalue); \ \ do \ - __oldval = *__memp; \ - while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ - __value, \ - __oldval),\ - 0)); \ + __atg5_oldval = *__atg5_memp; \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg5_memp, __atg5_value, \ + __atg5_oldval), 0)); \ \ - __oldval; }) + __atg5_oldval; }) #endif #ifndef atomic_exchange_rel @@ -184,54 +190,53 @@ /* Add VALUE to *MEM and return the old value of *MEM. */ #ifndef atomic_exchange_and_add # define atomic_exchange_and_add(mem, value) \ - ({ __typeof (*(mem)) __oldval; \ - __typeof (mem) __memp = (mem); \ - __typeof (*(mem)) __value = (value); \ + ({ __typeof (*(mem)) __atg6_oldval; \ + __typeof (mem) __atg6_memp = (mem); \ + __typeof (*(mem)) __atg6_value = (value); \ \ do \ - __oldval = *__memp; \ - while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ - __oldval \ - + __value,\ - __oldval),\ - 0)); \ + __atg6_oldval = *__atg6_memp; \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg6_memp, \ + __atg6_oldval \ + + __atg6_value, \ + __atg6_oldval), 0)); \ \ - __oldval; }) + __atg6_oldval; }) #endif #ifndef catomic_exchange_and_add # define catomic_exchange_and_add(mem, value) \ - ({ __typeof (*(mem)) __oldv; \ - __typeof (mem) __memp = (mem); \ - __typeof (*(mem)) __value = (value); \ + ({ __typeof (*(mem)) __atg7_oldv; \ + __typeof (mem) __atg7_memp = (mem); \ + __typeof (*(mem)) __atg7_value = (value); \ \ do \ - __oldv = *__memp; \ - while (__builtin_expect (catomic_compare_and_exchange_bool_acq (__memp, \ - __oldv \ - + __value,\ - __oldv), \ - 0)); \ + __atg7_oldv = *__atg7_memp; \ + while (__builtin_expect \ + (catomic_compare_and_exchange_bool_acq (__atg7_memp, \ + __atg7_oldv \ + + __atg7_value, \ + __atg7_oldv), 0)); \ \ - __oldv; }) + __atg7_oldv; }) #endif #ifndef atomic_max # define atomic_max(mem, value) \ do { \ - __typeof (*(mem)) __oldval; \ - __typeof (mem) __memp = (mem); \ - __typeof (*(mem)) __value = (value); \ + __typeof (*(mem)) __atg8_oldval; \ + __typeof (mem) __atg8_memp = (mem); \ + __typeof (*(mem)) __atg8_value = (value); \ do { \ - __oldval = *__memp; \ - if (__oldval >= __value) \ + __atg8_oldval = *__atg8_memp; \ + if (__atg8_oldval >= __atg8_value) \ break; \ - } while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ - __value, \ - __oldval),\ - 0)); \ + } while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg8_memp, __atg8_value,\ + __atg8_oldval), 0)); \ } while (0) #endif @@ -239,17 +244,17 @@ #ifndef catomic_max # define catomic_max(mem, value) \ do { \ - __typeof (*(mem)) __oldv; \ - __typeof (mem) __memp = (mem); \ - __typeof (*(mem)) __value = (value); \ + __typeof (*(mem)) __atg9_oldv; \ + __typeof (mem) __atg9_memp = (mem); \ + __typeof (*(mem)) __atg9_value = (value); \ do { \ - __oldv = *__memp; \ - if (__oldv >= __value) \ + __atg9_oldv = *__atg9_memp; \ + if (__atg9_oldv >= __atg9_value) \ break; \ - } while (__builtin_expect (catomic_compare_and_exchange_bool_acq (__memp, \ - __value,\ - __oldv),\ - 0)); \ + } while (__builtin_expect \ + (catomic_compare_and_exchange_bool_acq (__atg9_memp, \ + __atg9_value, \ + __atg9_oldv), 0)); \ } while (0) #endif @@ -257,17 +262,17 @@ #ifndef atomic_min # define atomic_min(mem, value) \ do { \ - __typeof (*(mem)) __oldval; \ - __typeof (mem) __memp = (mem); \ - __typeof (*(mem)) __value = (value); \ + __typeof (*(mem)) __atg10_oldval; \ + __typeof (mem) __atg10_memp = (mem); \ + __typeof (*(mem)) __atg10_value = (value); \ do { \ - __oldval = *__memp; \ - if (__oldval <= __value) \ + __atg10_oldval = *__atg10_memp; \ + if (__atg10_oldval <= __atg10_value) \ break; \ - } while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ - __value, \ - __oldval),\ - 0)); \ + } while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg10_memp, \ + __atg10_value, \ + __atg10_oldval), 0)); \ } while (0) #endif @@ -340,35 +345,34 @@ /* Decrement *MEM if it is > 0, and return the old value. */ #ifndef atomic_decrement_if_positive # define atomic_decrement_if_positive(mem) \ - ({ __typeof (*(mem)) __oldval; \ - __typeof (mem) __memp = (mem); \ + ({ __typeof (*(mem)) __atg11_oldval; \ + __typeof (mem) __atg11_memp = (mem); \ \ do \ { \ - __oldval = *__memp; \ - if (__builtin_expect (__oldval <= 0, 0)) \ + __atg11_oldval = *__atg11_memp; \ + if (__builtin_expect (__atg11_oldval <= 0, 0)) \ break; \ } \ - while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ - __oldval \ - - 1, \ - __oldval),\ - 0));\ - __oldval; }) + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg11_memp, \ + __atg11_oldval - 1, \ + __atg11_oldval), 0)); \ + __atg11_oldval; }) #endif #ifndef atomic_add_negative # define atomic_add_negative(mem, value) \ - ({ __typeof (value) __aan_value = (value); \ - atomic_exchange_and_add (mem, __aan_value) < -__aan_value; }) + ({ __typeof (value) __atg12_value = (value); \ + atomic_exchange_and_add (mem, __atg12_value) < -__atg12_value; }) #endif #ifndef atomic_add_zero # define atomic_add_zero(mem, value) \ - ({ __typeof (value) __aaz_value = (value); \ - atomic_exchange_and_add (mem, __aaz_value) == -__aaz_value; }) + ({ __typeof (value) __atg13_value = (value); \ + atomic_exchange_and_add (mem, __atg13_value) == -__atg13_value; }) #endif @@ -380,108 +384,102 @@ #ifndef atomic_bit_test_set # define atomic_bit_test_set(mem, bit) \ - ({ __typeof (*(mem)) __oldval; \ - __typeof (mem) __memp = (mem); \ - __typeof (*(mem)) __mask = ((__typeof (*(mem))) 1 << (bit)); \ + ({ __typeof (*(mem)) __atg14_old; \ + __typeof (mem) __atg14_memp = (mem); \ + __typeof (*(mem)) __atg14_mask = ((__typeof (*(mem))) 1 << (bit)); \ \ do \ - __oldval = (*__memp); \ - while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ - __oldval \ - | __mask, \ - __oldval),\ - 0)); \ + __atg14_old = (*__atg14_memp); \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg14_memp, \ + __atg14_old | __atg14_mask,\ + __atg14_old), 0)); \ \ - __oldval & __mask; }) + __atg14_old & __atg14_mask; }) #endif /* Atomically *mem &= mask. */ #ifndef atomic_and # define atomic_and(mem, mask) \ do { \ - __typeof (*(mem)) __oldval; \ - __typeof (mem) __memp = (mem); \ - __typeof (*(mem)) __mask = (mask); \ + __typeof (*(mem)) __atg15_old; \ + __typeof (mem) __atg15_memp = (mem); \ + __typeof (*(mem)) __atg15_mask = (mask); \ \ do \ - __oldval = (*__memp); \ - while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ - __oldval \ - & __mask, \ - __oldval), \ - 0)); \ + __atg15_old = (*__atg15_memp); \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg15_memp, \ + __atg15_old & __atg15_mask, \ + __atg15_old), 0)); \ } while (0) #endif /* Atomically *mem &= mask and return the old value of *mem. */ #ifndef atomic_and_val # define atomic_and_val(mem, mask) \ - ({ __typeof (*(mem)) __oldval; \ - __typeof (mem) __memp = (mem); \ - __typeof (*(mem)) __mask = (mask); \ + ({ __typeof (*(mem)) __atg16_old; \ + __typeof (mem) __atg16_memp = (mem); \ + __typeof (*(mem)) __atg16_mask = (mask); \ \ do \ - __oldval = (*__memp); \ - while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ - __oldval \ - & __mask, \ - __oldval),\ - 0)); \ + __atg16_old = (*__atg16_memp); \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg16_memp, \ + __atg16_old & __atg16_mask,\ + __atg16_old), 0)); \ \ - __oldval; }) + __atg16_old; }) #endif /* Atomically *mem |= mask and return the old value of *mem. */ #ifndef atomic_or # define atomic_or(mem, mask) \ do { \ - __typeof (*(mem)) __oldval; \ - __typeof (mem) __memp = (mem); \ - __typeof (*(mem)) __mask = (mask); \ + __typeof (*(mem)) __atg17_old; \ + __typeof (mem) __atg17_memp = (mem); \ + __typeof (*(mem)) __atg17_mask = (mask); \ \ do \ - __oldval = (*__memp); \ - while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ - __oldval \ - | __mask, \ - __oldval), \ - 0)); \ + __atg17_old = (*__atg17_memp); \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg17_memp, \ + __atg17_old | __atg17_mask, \ + __atg17_old), 0)); \ } while (0) #endif #ifndef catomic_or # define catomic_or(mem, mask) \ do { \ - __typeof (*(mem)) __oldval; \ - __typeof (mem) __memp = (mem); \ - __typeof (*(mem)) __mask = (mask); \ + __typeof (*(mem)) __atg18_old; \ + __typeof (mem) __atg18_memp = (mem); \ + __typeof (*(mem)) __atg18_mask = (mask); \ \ do \ - __oldval = (*__memp); \ - while (__builtin_expect (catomic_compare_and_exchange_bool_acq (__memp, \ - __oldval \ - | __mask, \ - __oldval),\ - 0)); \ + __atg18_old = (*__atg18_memp); \ + while (__builtin_expect \ + (catomic_compare_and_exchange_bool_acq (__atg18_memp, \ + __atg18_old | __atg18_mask,\ + __atg18_old), 0)); \ } while (0) #endif /* Atomically *mem |= mask and return the old value of *mem. */ #ifndef atomic_or_val # define atomic_or_val(mem, mask) \ - ({ __typeof (*(mem)) __oldval; \ - __typeof (mem) __memp = (mem); \ - __typeof (*(mem)) __mask = (mask); \ + ({ __typeof (*(mem)) __atg19_old; \ + __typeof (mem) __atg19_memp = (mem); \ + __typeof (*(mem)) __atg19_mask = (mask); \ \ do \ - __oldval = (*__memp); \ - while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ - __oldval \ - | __mask, \ - __oldval),\ - 0)); \ + __atg19_old = (*__atg19_memp); \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg19_memp, \ + __atg19_old | __atg19_mask,\ + __atg19_old), 0)); \ \ - __oldval; }) + __atg19_old; }) #endif #ifndef atomic_full_barrier diff --git a/malloc/malloc.c b/malloc/malloc.c index 38ceb1e909..4cbce0455b 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -4699,7 +4699,7 @@ static void malloc_consolidate(av) mstate av; search all bins all the time. */ maxfb = &(av->fastbins[fastbin_index(get_max_fast ())]); #else - maxfb = &(av->fastbins[NFASTBINS]); + maxfb = &(av->fastbins[NFASTBINS - 1]); #endif fb = &(av->fastbins[0]); do { diff --git a/nptl/ChangeLog b/nptl/ChangeLog index a1e64928ae..43933219e8 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,9 @@ +2006-10-17 Jakub Jelinek + + * sysdeps/unix/sysv/linux/rtld-lowlevel.h (__rtld_mrlock_lock, + __rtld_mrlock_unlock, __rtld_mrlock_change, __rtld_mrlock_done): Use + atomic_* instead of catomic_* macros. + 2006-10-12 Ulrich Drepper [BZ #3285] diff --git a/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h b/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h index b16fd2165d..7152dd20aa 100644 --- a/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h +++ b/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h @@ -62,9 +62,9 @@ typedef int __rtld_mrlock_t; { \ int newval = ((oldval & __RTLD_MRLOCK_RBITS) \ + __RTLD_MRLOCK_INC); \ - int ret = catomic_compare_and_exchange_val_acq (&(lock), \ - newval, \ - oldval); \ + int ret = atomic_compare_and_exchange_val_acq (&(lock), \ + newval, \ + oldval); \ if (__builtin_expect (ret == oldval, 1)) \ goto out; \ } \ @@ -72,7 +72,7 @@ typedef int __rtld_mrlock_t; } \ if ((oldval & __RTLD_MRLOCK_RWAIT) == 0) \ { \ - catomic_or (&(lock), __RTLD_MRLOCK_RWAIT); \ + atomic_or (&(lock), __RTLD_MRLOCK_RWAIT); \ oldval |= __RTLD_MRLOCK_RWAIT; \ } \ lll_futex_wait (lock, oldval); \ @@ -83,7 +83,7 @@ typedef int __rtld_mrlock_t; #define __rtld_mrlock_unlock(lock) \ do { \ - int oldval = catomic_exchange_and_add (&(lock), -__RTLD_MRLOCK_INC); \ + int oldval = atomic_exchange_and_add (&(lock), -__RTLD_MRLOCK_INC); \ if (__builtin_expect ((oldval \ & (__RTLD_MRLOCK_RBITS | __RTLD_MRLOCK_WWAIT)) \ == (__RTLD_MRLOCK_INC | __RTLD_MRLOCK_WWAIT), 0)) \ @@ -103,11 +103,11 @@ typedef int __rtld_mrlock_t; for (int tries = 0; tries < __RTLD_MRLOCK_TRIES; ++tries) \ { \ oldval = lock; \ - while (__builtin_expect ((oldval & __RTLD_MRLOCK_RBITS) == 0, 1))\ + while (__builtin_expect ((oldval & __RTLD_MRLOCK_RBITS) == 0, 1)) \ { \ int newval = ((oldval & __RTLD_MRLOCK_RWAIT) \ + __RTLD_MRLOCK_WRITER); \ - int ret = catomic_compare_and_exchange_val_acq (&(lock), \ + int ret = atomic_compare_and_exchange_val_acq (&(lock), \ newval, \ oldval); \ if (__builtin_expect (ret == oldval, 1)) \ @@ -115,7 +115,7 @@ typedef int __rtld_mrlock_t; } \ atomic_delay (); \ } \ - catomic_or (&(lock), __RTLD_MRLOCK_WWAIT); \ + atomic_or (&(lock), __RTLD_MRLOCK_WWAIT); \ oldval |= __RTLD_MRLOCK_WWAIT; \ lll_futex_wait (lock, oldval); \ } \ @@ -125,7 +125,7 @@ typedef int __rtld_mrlock_t; #define __rtld_mrlock_done(lock) \ do { \ - int oldval = catomic_exchange_and_add (&(lock), -__RTLD_MRLOCK_WRITER); \ + int oldval = atomic_exchange_and_add (&(lock), -__RTLD_MRLOCK_WRITER); \ if (__builtin_expect ((oldval & __RTLD_MRLOCK_RWAIT) != 0, 0)) \ lll_futex_wake (&(lock), 0x7fffffff); \ } while (0) diff --git a/sunrpc/Makefile b/sunrpc/Makefile index bc826affdd..30f74dc135 100644 --- a/sunrpc/Makefile +++ b/sunrpc/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1994-2004, 2005 Free Software Foundation, Inc. +# Copyright (C) 1994-2004, 2005, 2006 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 @@ -85,7 +85,7 @@ all: # Make this the default target; it will be defined in Rules. include ../Makeconfig -tests = tst-xdrmem +tests = tst-xdrmem tst-xdrmem2 xtests := tst-getmyaddr ifeq ($(have-thread-library),yes) diff --git a/sunrpc/tst-xdrmem2.c b/sunrpc/tst-xdrmem2.c new file mode 100644 index 0000000000..eed8ccc072 --- /dev/null +++ b/sunrpc/tst-xdrmem2.c @@ -0,0 +1,114 @@ +/* Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2006. + + 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 +#include +#include +#include + +static int +do_test (void) +{ + XDR xdrs; + void *buf; + size_t ps = sysconf (_SC_PAGESIZE); + uintptr_t half = -1; + int v_int; + u_short v_u_short; + + half = (half >> 1) & ~(uintptr_t) (ps - 1); + buf = mmap ((void *) half, 2 * ps, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (buf == MAP_FAILED || buf != (void *) half) + { + puts ("Couldn't mmap 2 pages in the middle of address space"); + return 0; + } + + xdrmem_create (&xdrs, (char *) buf, 2 * ps, XDR_ENCODE); + +#define T(type, val) \ + v_##type = val; \ + if (! xdr_##type (&xdrs, &v_##type)) \ + { \ + puts ("encoding of " #type \ + " " #val " failed"); \ + return 1; \ + } + + T(int, 127) + + u_int pos = xdr_getpos (&xdrs); + + T(u_short, 31) + + if (! xdr_setpos (&xdrs, pos)) + { + puts ("xdr_setpos during encoding failed"); + return 1; + } + + T(u_short, 36) + +#undef T + + xdr_destroy (&xdrs); + + xdrmem_create (&xdrs, (char *) buf, 2 * ps, XDR_DECODE); + +#define T(type, val) \ + v_##type = 0x15; \ + if (! xdr_##type (&xdrs, &v_##type)) \ + { \ + puts ("decoding of " #type \ + " " #val " failed"); \ + return 1; \ + } \ + if (v_##type != val) \ + { \ + puts ("decoded value differs, " \ + "type " #type " " #val); \ + return 1; \ + } + + T(int, 127) + + pos = xdr_getpos (&xdrs); + + T(u_short, 36) + + if (! xdr_setpos (&xdrs, pos)) + { + puts ("xdr_setpos during encoding failed"); + return 1; + } + + T(u_short, 36) + +#undef T + + xdr_destroy (&xdrs); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sunrpc/xdr_mem.c b/sunrpc/xdr_mem.c index e3167de040..7b1261bbae 100644 --- a/sunrpc/xdr_mem.c +++ b/sunrpc/xdr_mem.c @@ -177,13 +177,15 @@ xdrmem_setpos (xdrs, pos) { caddr_t newaddr = xdrs->x_base + pos; caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; + size_t handy = lastaddr - newaddr; - if ((long) newaddr > (long) lastaddr - || (UINT_MAX < LONG_MAX - && (long) UINT_MAX < (long) lastaddr - (long) newaddr)) + if (newaddr > lastaddr + || newaddr < xdrs->x_base + || handy != (u_int) handy) return FALSE; + xdrs->x_private = newaddr; - xdrs->x_handy = (long) lastaddr - (long) newaddr; + xdrs->x_handy = (u_int) handy; return TRUE; } diff --git a/sysdeps/i386/i486/bits/atomic.h b/sysdeps/i386/i486/bits/atomic.h index 218656b2fb..a27734c37e 100644 --- a/sysdeps/i386/i486/bits/atomic.h +++ b/sysdeps/i386/i486/bits/atomic.h @@ -425,7 +425,7 @@ typedef uintmax_t uatomic_max_t; "cmpl $0, %%gs:%P2\n\tje 0f\n\tlock\n0:\t" #define catomic_decrement(mem) \ - __arch_increment_body (__arch_decrement_cprefix, __arch_c, mem) + __arch_decrement_body (__arch_decrement_cprefix, __arch_c, mem) #define atomic_decrement_and_test(mem) \ diff --git a/sysdeps/x86_64/bits/atomic.h b/sysdeps/x86_64/bits/atomic.h index e1981e94d6..65d6b02008 100644 --- a/sysdeps/x86_64/bits/atomic.h +++ b/sysdeps/x86_64/bits/atomic.h @@ -81,8 +81,8 @@ typedef uintmax_t uatomic_max_t; ({ __typeof (*mem) ret; \ __asm __volatile (LOCK_PREFIX "cmpxchgq %q2, %1" \ : "=a" (ret), "=m" (*mem) \ - : "r" ((long) (newval)), "m" (*mem), \ - "0" ((long) (oldval))); \ + : "r" ((long int) (newval)), "m" (*mem), \ + "0" ((long int) (oldval))); \ ret; }) @@ -121,12 +121,13 @@ typedef uintmax_t uatomic_max_t; #define __arch_c_compare_and_exchange_val_64_acq(mem, newval, oldval) \ ({ __typeof (*mem) ret; \ - __asm __volatile ("cmpl $0, %%fs:%P5\n\t" \ - "je 0f\n\t" \ - "lock\n" \ + __asm __volatile ("cmpl $0, %%fs:%P5\n\t" \ + "je 0f\n\t" \ + "lock\n" \ "0:\tcmpxchgq %q2, %1" \ : "=a" (ret), "=m" (*mem) \ - : "q" (newval), "m" (*mem), "0" (oldval), \ + : "q" ((long int) (newval)), "m" (*mem), \ + "0" ((long int)oldval), \ "i" (offsetof (tcbhead_t, multiple_threads))); \ ret; }) @@ -351,7 +352,7 @@ typedef uintmax_t uatomic_max_t; "cmpl $0, %%fs:%P2\n\tje 0f\n\tlock\n0:\t" #define catomic_decrement(mem) \ - __arch_increment_body (__arch_decrement_cprefix, mem) + __arch_decrement_body (__arch_decrement_cprefix, mem) #define atomic_decrement_and_test(mem) \ -- cgit 1.4.1