From 06f6ca9019897f5d1799c0ae8d7293ed249c0f97 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 17 Sep 2003 18:23:49 +0000 Subject: [PATCH] Update. 2003-09-17 Philip Blundell * sysdeps/unix/sysv/linux/arm/vfork.S: Branch to fork if libpthread is loaded. Elide backwards compatibility code when not required. --- elf/Makefile | 12 +- elf/tst-align.c | 54 +++ elf/tst-alignmod.c | 53 +++ libio/memstream.c | 78 ---- linuxthreads/ChangeLog | 6 + linuxthreads/attr.c | 9 + .../sysdeps/unix/sysv/linux/arm/vfork.S | 39 +- misc/Makefile | 1 + misc/tst-tsearch.c | 22 +- nptl/Banner | 2 +- nptl/ChangeLog | 11 + nptl/Makefile | 2 +- nptl/pthreadP.h | 4 + nptl/pthread_getattr_np.c | 22 + .../sysv/linux/pthread_attr_getaffinity.c | 5 +- .../unix/sysv/linux/pthread_getaffinity.c | 1 + nptl/tst-attr3.c | 414 ++++++++++++++++++ stdlib/Makefile | 1 + stdlib/tst-qsort.c | 13 + sysdeps/arm/dl-machine.h | 72 ++- sysdeps/arm/sysdep.h | 9 + sysdeps/i386/i686/Makefile | 2 +- sysdeps/unix/sysv/linux/arm/vfork.S | 5 +- sysdeps/x86_64/tst-stack-align.h | 47 ++ 24 files changed, 746 insertions(+), 138 deletions(-) create mode 100644 elf/tst-align.c create mode 100644 elf/tst-alignmod.c create mode 100644 nptl/tst-attr3.c create mode 100644 sysdeps/x86_64/tst-stack-align.h diff --git a/elf/Makefile b/elf/Makefile index 734b7854e8..c292cfa283 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -71,7 +71,7 @@ distribute := rtld-Rules \ tst-tlsmod1.c tst-tlsmod2.c tst-tlsmod3.c tst-tlsmod4.c \ tst-tlsmod5.c tst-tlsmod6.c tst-tlsmod7.c tst-tlsmod8.c \ tst-tlsmod9.c tst-tlsmod10.c tst-tlsmod11.c \ - tst-tlsmod12.c tst-tls10.h \ + tst-tlsmod12.c tst-tls10.h tst-alignmod.c \ circlemod1.c circlemod1a.c circlemod2.c circlemod2a.c \ circlemod3.c circlemod3a.c nodlopenmod2.c \ tls-macros.h \ @@ -150,7 +150,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ neededtest3 neededtest4 unload2 lateglobal initfirst global \ restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \ circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \ - tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 + tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align # reldep9 test-srcs = tst-pathopt tests-vis-yes = vismain @@ -177,7 +177,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ circlemod1 circlemod1a circlemod2 circlemod2a \ circlemod3 circlemod3a \ reldep8mod1 reldep8mod2 reldep8mod3 \ - reldep9mod1 reldep9mod2 reldep9mod3 + reldep9mod1 reldep9mod2 reldep9mod3 \ + tst-alignmod ifeq (yes,$(have-initfini-array)) modules-names += tst-array2dep endif @@ -648,6 +649,11 @@ $(objpfx)tst-tls13.out: $(objpfx)tst-tlsmod13a.so $(objpfx)tst-tls14: $(objpfx)tst-tlsmod14a.so $(libdl) $(objpfx)tst-tls14.out:$(objpfx)tst-tlsmod14b.so +CFLAGS-tst-align.c = $(stack-align-test-flags) +CFLAGS-tst-alignmod.c = $(stack-align-test-flags) +$(objpfx)tst-align: $(libdl) +$(objpfx)tst-align.out: $(objpfx)tst-alignmod.so + ifdef libdl $(objpfx)tst-tls9-static: $(common-objpfx)dlfcn/libdl.a $(objpfx)tst-tls9-static.out: $(objpfx)tst-tlsmod5.so $(objpfx)tst-tlsmod6.so diff --git a/elf/tst-align.c b/elf/tst-align.c new file mode 100644 index 0000000000..e4d77763cd --- /dev/null +++ b/elf/tst-align.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + 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 + +static int +do_test (void) +{ + static const char modname[] = "tst-alignmod.so"; + int result = 0; + void (*fp) (int *); + void *h; + + h = dlopen (modname, RTLD_LAZY); + if (h == NULL) + { + printf ("cannot open '%s': %s\n", modname, dlerror ()); + exit (1); + } + + fp = dlsym (h, "in_dso"); + if (fp == NULL) + { + printf ("cannot get symbol 'in_dso': %s\n", dlerror ()); + exit (1); + } + + fp (&result); + + dlclose (h); + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/elf/tst-alignmod.c b/elf/tst-alignmod.c new file mode 100644 index 0000000000..d1305c1a6c --- /dev/null +++ b/elf/tst-alignmod.c @@ -0,0 +1,53 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + 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 + +static int res, *resp; + +static void __attribute__((constructor)) +con (void) +{ + res = TEST_STACK_ALIGN () ? -1 : 1; +} + +void +in_dso (int *result) +{ + if (!res) + { + puts ("constructor has not been run"); + *result = 1; + } + else if (res != 1) + { + puts ("constructor has been run without sufficient alignment"); + *result = 1; + } + + resp = result; +} + +static void __attribute__((destructor)) +des (void) +{ + if (TEST_STACK_ALIGN ()) + *resp = 1; +} diff --git a/libio/memstream.c b/libio/memstream.c index 68645fa829..d09b8ab920 100644 --- a/libio/memstream.c +++ b/libio/memstream.c @@ -32,8 +32,6 @@ struct _IO_FILE_memstream static int _IO_mem_sync __P ((_IO_FILE* fp)); static void _IO_mem_finish __P ((_IO_FILE* fp, int)); -static int _IO_wmem_sync __P ((_IO_FILE* fp)); -static void _IO_wmem_finish __P ((_IO_FILE* fp, int)); static struct _IO_jump_t _IO_mem_jumps = @@ -60,30 +58,6 @@ static struct _IO_jump_t _IO_mem_jumps = JUMP_INIT(imbue, _IO_default_imbue) }; -static struct _IO_jump_t _IO_wmem_jumps = -{ - JUMP_INIT_DUMMY, - JUMP_INIT (finish, (_IO_finish_t) _IO_wmem_finish), - JUMP_INIT (overflow, (_IO_overflow_t) _IO_wstr_overflow), - JUMP_INIT (underflow, (_IO_underflow_t) _IO_wstr_underflow), - JUMP_INIT (uflow, (_IO_underflow_t) INTUSE(_IO_wdefault_uflow)), - JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail), - JUMP_INIT (xsputn, (_IO_xsputn_t) INTUSE(_IO_wdefault_xsputn)), - JUMP_INIT (xsgetn, (_IO_xsgetn_t) INTUSE(_IO_wdefault_xsgetn)), - JUMP_INIT (seekoff, _IO_wstr_seekoff), - JUMP_INIT (seekpos, _IO_default_seekpos), - JUMP_INIT (setbuf, _IO_default_setbuf), - JUMP_INIT (sync, (_IO_sync_t) _IO_wmem_sync), - JUMP_INIT (doallocate, INTUSE(_IO_wdefault_doallocate)), - JUMP_INIT (read, _IO_default_read), - JUMP_INIT (write, _IO_default_write), - JUMP_INIT (seek, _IO_default_seek), - JUMP_INIT (close, _IO_default_close), - JUMP_INIT (stat, _IO_default_stat), - JUMP_INIT(showmanyc, _IO_default_showmanyc), - JUMP_INIT(imbue, _IO_default_imbue) -}; - /* Open a stream that writes into a malloc'd buffer that is expanded as necessary. *BUFLOC and *SIZELOC are updated with the buffer's location and the number of characters written on fflush or fclose. */ @@ -172,55 +146,3 @@ _IO_mem_finish (fp, dummy) INTUSE(_IO_default_finish) (fp, 0); } - - -static int -_IO_wmem_sync (fp) - _IO_FILE* fp; -{ - struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp; - int res; - - res = _IO_default_sync (fp); - if (res < 0) - return res; - - if (fp->_wide_data->_IO_write_ptr == fp->_wide_data->_IO_write_end) - { - _IO_wstr_overflow (fp, L'\0'); - --fp->_wide_data->_IO_write_ptr; - } - else - *fp->_wide_data->_IO_write_ptr = '\0'; - - *mp->bufloc = (char *) fp->_wide_data->_IO_write_base; - *mp->sizeloc = (fp->_wide_data->_IO_write_ptr - - fp->_wide_data->_IO_write_base); - - return 0; -} - - -static void -_IO_wmem_finish (fp, dummy) - _IO_FILE* fp; - int dummy; -{ - struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp; - - *mp->bufloc = (char *) realloc (fp->_wide_data->_IO_write_base, - (fp->_wide_data->_IO_write_ptr - - fp->_wide_data->_IO_write_base + 1) - * sizeof (wchar_t)); - if (*mp->bufloc != NULL) - { - ((wchar_t *) (*mp->bufloc))[fp->_wide_data->_IO_write_ptr - - fp->_wide_data->_IO_write_base] = '\0'; - *mp->sizeloc = (fp->_wide_data->_IO_write_ptr - - fp->_wide_data->_IO_write_base); - } - - fp->_wide_data->_IO_buf_base = NULL; - - INTUSE(_IO_default_finish) (fp, 0); -} diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index cd5eb8e61f..5a86b94232 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,9 @@ +2003-09-17 Philip Blundell + + * sysdeps/unix/sysv/linux/arm/vfork.S: Branch to fork if + libpthread is loaded. Elide backwards compatibility code when not + required. + 2003-09-17 Jakub Jelinek * descr.h (manager_thread): Rename to... diff --git a/linuxthreads/attr.c b/linuxthreads/attr.c index a66eb72c27..687334ffdb 100644 --- a/linuxthreads/attr.c +++ b/linuxthreads/attr.c @@ -404,7 +404,11 @@ int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr) # endif #endif +#ifdef USE_TLS if (attr->__stackaddr == NULL) +#else + if (descr == &__pthread_initial_thread) +#endif { /* Defined in ld.so. */ extern void *__libc_stack_end; @@ -448,6 +452,11 @@ int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr) attr->__stacksize = rl.rlim_cur; attr->__stackaddr = (void *) to; + /* The limit might be too high. This is a bogus + situation but try to avoid making it worse. */ + if ((size_t) attr->__stacksize > (size_t) attr->__stackaddr) + attr->__stacksize = (size_t) attr->__stackaddr; + /* We succeed and no need to look further. */ ret = 0; break; diff --git a/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S index 8d3338afd0..23687342d1 100644 --- a/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S +++ b/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S @@ -20,37 +20,60 @@ #include #define _ERRNO_H 1 #include +#include -/* Clone the calling process, but without copying the whole address -pace. +/* Clone the calling process, but without copying the whole address space. The calling process is suspended until the new process exits or is - replaced by a call to `execve'. Return -1 for errors, 0 to the new -rocess, + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, and the process ID of the new process to the old process. */ PSEUDO_PROLOGUE ENTRY (__vfork) - SINGLE_THREAD_P - bne HIDDEN_JUMPTARGET (__fork) #ifdef __NR_vfork + +#ifdef SHARED + ldr ip, 1f + ldr r0, 2f +3: add ip, pc, ip + ldr r0, [ip, r0] +#else + ldr r0, 1f +#endif + movs r0, r0 + bne HIDDEN_JUMPTARGET (__fork) + swi __NR_vfork cmn a1, #4096 RETINSTR(movcc, pc, lr) +#ifndef __ASSUME_VFORK_SYSCALL /* Check if vfork syscall is known at all. */ - ldr a2, =-ENOSYS - teq a1, a2 + cmn a1, #ENOSYS bne PLTJMP(C_SYMBOL_NAME(__syscall_error)) #endif +#endif + +#ifndef __ASSUME_VFORK_SYSCALL /* If we don't have vfork, fork is close enough. */ swi __NR_fork cmn a1, #4096 RETINSTR(movcc, pc, lr) +#elif !defined __NR_vfork +# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined" +#endif b PLTJMP(C_SYMBOL_NAME(__syscall_error)) +#ifdef SHARED +1: .word _GLOBAL_OFFSET_TABLE_ - 3b - 8 +2: .word __libc_pthread_functions(GOTOFF) +#else + .weak pthread_create +1: .word pthread_create +#endif + PSEUDO_END (__vfork) libc_hidden_def (__vfork) diff --git a/misc/Makefile b/misc/Makefile index e74070113d..ad57434f26 100644 --- a/misc/Makefile +++ b/misc/Makefile @@ -89,6 +89,7 @@ CFLAGS-mkstemp64.c = -fexceptions CFLAGS-getsysstats.c = -fexceptions CFLAGS-getusershell.c = -fexceptions CFLAGS-err.c = -fexceptions +CFLAGS-tst-tsearch.c = $(stack-align-test-flags) include ../Rules diff --git a/misc/tst-tsearch.c b/misc/tst-tsearch.c index 722b6d7907..66f76ac884 100644 --- a/misc/tst-tsearch.c +++ b/misc/tst-tsearch.c @@ -1,5 +1,5 @@ /* Test program for tsearch et al. - Copyright (C) 1997, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1997, 2000, 2001, 2003 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 @@ -25,6 +25,7 @@ #include #include #include +#include #define SEED 0 #define BALANCED 1 @@ -72,10 +73,14 @@ static int depths[SIZE]; /* Maximum depth during a tree walk. */ static int max_depth; +static int stack_align_check[2]; + /* Compare two keys. */ static int cmp_fn (const void *a, const void *b) { + if (!stack_align_check[0]) + stack_align_check[0] = TEST_STACK_ALIGN () ? -1 : 1; return *(const int *) a - *(const int *) b; } @@ -103,6 +108,9 @@ walk_action (const void *nodep, const VISIT which, const int depth) { int key = **(int **) nodep; + if (!stack_align_check[1]) + stack_align_check[1] = TEST_STACK_ALIGN () ? -1 : 1; + if (depth > max_depth) max_depth = depth; if (which == leaf || which == preorder) @@ -329,5 +337,17 @@ main (int argc, char **argv) total_error |= error; } + for (i = 0; i < 2; ++i) + if (stack_align_check[i] == 0) + { + printf ("stack alignment check %d not run\n", i); + total_error |= 1; + } + else if (stack_align_check[i] != 1) + { + printf ("stack insufficiently aligned in check %d\n", i); + total_error |= 1; + } + return total_error; } diff --git a/nptl/Banner b/nptl/Banner index cc4ac696ef..5d6a6d0445 100644 --- a/nptl/Banner +++ b/nptl/Banner @@ -1 +1 @@ -NPTL 0.58 by Ulrich Drepper +NPTL 0.59 by Ulrich Drepper diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 1edbb9842b..e7341f1394 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,5 +1,16 @@ 2003-09-17 Jakub Jelinek + * sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c + (pthread_attr_getaffinity_np): Don't segfault if iattr->cpuset is + NULL. + * pthread_getattr_np.c: Set cpuset using pthread_getaffinity_np. + * pthreadP.h (pthread_getaffinity_np): Add hidden_proto. + * sysdeps/unix/sysv/linux/pthread_getaffinity.c + (pthread_getaffinity_np): Add hidden_def. + + * Makefile (tests): Add tst-attr3. + * tst-attr3.c: New test. + * sysdeps/i386/Makefile (CFLAGS-tst-align.c): Remove. 2003-09-15 Jakub Jelinek diff --git a/nptl/Makefile b/nptl/Makefile index 7876331e52..ba568dffba 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -189,7 +189,7 @@ CFLAGS-pt-system.c = -fexceptions omit-deps = $(unix-syscalls:%=ptw-%) -tests = tst-attr1 tst-attr2 \ +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-spin1 tst-spin2 tst-spin3 \ diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index 99b344489a..1981fc4aeb 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -424,4 +424,8 @@ extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, int execute); +#if defined NOT_IN_libc && defined IS_IN_libpthread +hidden_proto (pthread_getaffinity_np) +#endif + #endif /* pthreadP.h */ diff --git a/nptl/pthread_getattr_np.c b/nptl/pthread_getattr_np.c index dfacd887c9..9cc948f4c6 100644 --- a/nptl/pthread_getattr_np.c +++ b/nptl/pthread_getattr_np.c @@ -114,6 +114,11 @@ pthread_getattr_np (thread_id, attr) iattr->stacksize = rl.rlim_cur; iattr->stackaddr = (void *) to; + /* The limit might be too high. This is a bogus + situation but try to avoid making it worse. */ + if ((size_t) iattr->stacksize > (size_t) iattr->stackaddr) + iattr->stacksize = (size_t) iattr->stackaddr; + /* We succeed and no need to look further. */ ret = 0; break; @@ -127,6 +132,23 @@ pthread_getattr_np (thread_id, attr) iattr->flags |= ATTR_FLAG_STACKADDR; + if (ret == 0) + { + iattr->cpuset = (cpu_set_t *) malloc (sizeof (cpu_set_t)); + if (iattr->cpuset == NULL) + ret = ENOMEM; + else + { + ret = pthread_getaffinity_np (thread_id, iattr->cpuset); + if (ret == ENOSYS) + { + free (iattr->cpuset); + iattr->cpuset = NULL; + ret = 0; + } + } + } + lll_unlock (thread->lock); pthread_cleanup_pop (0); diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c b/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c index e6c795b8b4..8a3f31d078 100644 --- a/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c +++ b/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c @@ -35,7 +35,10 @@ pthread_attr_getaffinity_np (attr, cpuset) assert (sizeof (*attr) >= sizeof (struct pthread_attr)); iattr = (struct pthread_attr *) attr; - memcpy (cpuset, iattr->cpuset, sizeof (cpu_set_t)); + if (iattr->cpuset) + memcpy (cpuset, iattr->cpuset, sizeof (cpu_set_t)); + else + memset (cpuset, -1, sizeof (cpu_set_t)); return 0; } diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c b/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c index 70553d7e5f..41849ddadf 100644 --- a/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c +++ b/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c @@ -41,3 +41,4 @@ pthread_getaffinity_np (th, cpuset) return 0; } +hidden_def (pthread_getaffinity_np) diff --git a/nptl/tst-attr3.c b/nptl/tst-attr3.c new file mode 100644 index 0000000000..f6a5c46466 --- /dev/null +++ b/nptl/tst-attr3.c @@ -0,0 +1,414 @@ +/* pthread_getattr_np test. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + 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 +#include + +#include + +static void * +tf (void *arg) +{ + pthread_attr_t a, *ap, a2; + int err; + void *result = NULL; + + if (arg == NULL) + { + ap = &a2; + err = pthread_attr_init (ap); + if (err) + { + error (0, err, "pthread_attr_init failed"); + return tf; + } + } + else + ap = (pthread_attr_t *) arg; + + err = pthread_getattr_np (pthread_self (), &a); + if (err) + { + error (0, err, "pthread_getattr_np failed"); + result = tf; + } + + int detachstate1, detachstate2; + err = pthread_attr_getdetachstate (&a, &detachstate1); + if (err) + { + error (0, err, "pthread_attr_getdetachstate failed"); + result = tf; + } + else + { + err = pthread_attr_getdetachstate (ap, &detachstate2); + if (err) + { + error (0, err, "pthread_attr_getdetachstate failed"); + result = tf; + } + else if (detachstate1 != detachstate2) + { + error (0, 0, "detachstate differs %d != %d", + detachstate1, detachstate2); + result = tf; + } + } + + void *stackaddr; + size_t stacksize; + err = pthread_attr_getstack (&a, &stackaddr, &stacksize); + if (err) + { + error (0, err, "pthread_attr_getstack failed"); + result = tf; + } + else if ((void *) &a < stackaddr + || (void *) &a >= stackaddr + stacksize) + { + error (0, 0, "pthread_attr_getstack returned range does not cover thread's stack"); + result = tf; + } + + size_t guardsize1, guardsize2; + err = pthread_attr_getguardsize (&a, &guardsize1); + if (err) + { + error (0, err, "pthread_attr_getguardsize failed"); + result = tf; + } + else + { + err = pthread_attr_getguardsize (ap, &guardsize2); + if (err) + { + error (0, err, "pthread_attr_getguardsize failed"); + result = tf; + } + else if (guardsize1 != guardsize2) + { + error (0, 0, "guardsize differs %zd != %zd", + guardsize1, guardsize2); + result = tf; + } + } + + int scope1, scope2; + err = pthread_attr_getscope (&a, &scope1); + if (err) + { + error (0, err, "pthread_attr_getscope failed"); + result = tf; + } + else + { + err = pthread_attr_getscope (ap, &scope2); + if (err) + { + error (0, err, "pthread_attr_getscope failed"); + result = tf; + } + else if (scope1 != scope2) + { + error (0, 0, "scope differs %d != %d", + scope1, scope2); + result = tf; + } + } + + int inheritsched1, inheritsched2; + err = pthread_attr_getinheritsched (&a, &inheritsched1); + if (err) + { + error (0, err, "pthread_attr_getinheritsched failed"); + result = tf; + } + else + { + err = pthread_attr_getinheritsched (ap, &inheritsched2); + if (err) + { + error (0, err, "pthread_attr_getinheritsched failed"); + result = tf; + } + else if (inheritsched1 != inheritsched2) + { + error (0, 0, "inheritsched differs %d != %d", + inheritsched1, inheritsched2); + result = tf; + } + } + + cpu_set_t c1, c2; + err = pthread_getaffinity_np (pthread_self (), &c1); + if (err == 0) + { + err = pthread_attr_getaffinity_np (&a, &c2); + if (err) + { + error (0, err, "pthread_attr_getaffinity_np failed"); + result = tf; + } + else if (memcmp (&c1, &c2, sizeof (c1))) + { + error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np"); + result = tf; + } + } + + err = pthread_attr_destroy (&a); + if (err) + { + error (0, err, "pthread_attr_destroy failed"); + result = tf; + } + + if (ap == &a2) + { + err = pthread_attr_destroy (ap); + if (err) + { + error (0, err, "pthread_attr_destroy failed"); + result = tf; + } + } + + return result; +} + + +static int +do_test (void) +{ + int result = 0; + pthread_attr_t a; + cpu_set_t c1, c2; + + int err = pthread_attr_init (&a); + if (err) + { + error (0, err, "pthread_attr_init failed"); + result = 1; + } + + err = pthread_attr_getaffinity_np (&a, &c1); + if (err && err != ENOSYS) + { + error (0, err, "pthread_attr_getaffinity_np failed"); + result = 1; + } + + err = pthread_attr_destroy (&a); + if (err) + { + error (0, err, "pthread_attr_destroy failed"); + result = 1; + } + + err = pthread_getattr_np (pthread_self (), &a); + if (err) + { + error (0, err, "pthread_getattr_np failed"); + result = 1; + } + + int detachstate; + err = pthread_attr_getdetachstate (&a, &detachstate); + if (err) + { + error (0, err, "pthread_attr_getdetachstate failed"); + result = 1; + } + else if (detachstate != PTHREAD_CREATE_JOINABLE) + { + error (0, 0, "initial thread not joinable"); + result = 1; + } + + void *stackaddr; + size_t stacksize; + err = pthread_attr_getstack (&a, &stackaddr, &stacksize); + if (err) + { + error (0, err, "pthread_attr_getstack failed"); + result = 1; + } + else if ((void *) &a < stackaddr + || (void *) &a >= stackaddr + stacksize) + { + error (0, 0, "pthread_attr_getstack returned range does not cover main's stack"); + result = 1; + } + + size_t guardsize; + err = pthread_attr_getguardsize (&a, &guardsize); + if (err) + { + error (0, err, "pthread_attr_getguardsize failed"); + result = 1; + } + else if (guardsize != 0) + { + error (0, 0, "pthread_attr_getguardsize returned %zd != 0", + guardsize); + result = 1; + } + + int scope; + err = pthread_attr_getscope (&a, &scope); + if (err) + { + error (0, err, "pthread_attr_getscope failed"); + result = 1; + } + else if (scope != PTHREAD_SCOPE_SYSTEM) + { + error (0, 0, "pthread_attr_getscope returned %d != PTHREAD_SCOPE_SYSTEM", + scope); + result = 1; + } + + int inheritsched; + err = pthread_attr_getinheritsched (&a, &inheritsched); + if (err) + { + error (0, err, "pthread_attr_getinheritsched failed"); + result = 1; + } + else if (inheritsched != PTHREAD_INHERIT_SCHED) + { + error (0, 0, "pthread_attr_getinheritsched returned %d != PTHREAD_INHERIT_SCHED", + inheritsched); + result = 1; + } + + err = pthread_getaffinity_np (pthread_self (), &c1); + if (err == 0) + { + err = pthread_attr_getaffinity_np (&a, &c2); + if (err) + { + error (0, err, "pthread_attr_getaffinity_np failed"); + result = 1; + } + else if (memcmp (&c1, &c2, sizeof (c1))) + { + error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np"); + result = 1; + } + } + + err = pthread_attr_destroy (&a); + if (err) + { + error (0, err, "pthread_attr_destroy failed"); + result = 1; + } + + pthread_t th; + err = pthread_create (&th, NULL, tf, NULL); + if (err) + { + error (0, err, "pthread_create #1 failed"); + result = 1; + } + else + { + void *ret; + err = pthread_join (th, &ret); + if (err) + { + error (0, err, "pthread_join #1 failed"); + result = 1; + } + else if (ret != NULL) + result = 1; + } + + err = pthread_attr_init (&a); + if (err) + { + error (0, err, "pthread_attr_init failed"); + result = 1; + } + + err = pthread_create (&th, &a, tf, &a); + if (err) + { + error (0, err, "pthread_create #2 failed"); + result = 1; + } + else + { + void *ret; + err = pthread_join (th, &ret); + if (err) + { + error (0, err, "pthread_join #2 failed"); + result = 1; + } + else if (ret != NULL) + result = 1; + } + + err = pthread_attr_setguardsize (&a, 16 * sysconf (_SC_PAGESIZE)); + if (err) + { + error (0, err, "pthread_attr_setguardsize failed"); + result = 1; + } + + err = pthread_create (&th, &a, tf, &a); + if (err) + { + error (0, err, "pthread_create #3 failed"); + result = 1; + } + else + { + void *ret; + err = pthread_join (th, &ret); + if (err) + { + error (0, err, "pthread_join #3 failed"); + result = 1; + } + else if (ret != NULL) + result = 1; + } + + err = pthread_attr_destroy (&a); + if (err) + { + error (0, err, "pthread_attr_destroy failed"); + result = 1; + } + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdlib/Makefile b/stdlib/Makefile index f882a554ef..72633d8290 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -97,6 +97,7 @@ CFLAGS-atexit.c = -DHAVE_DOT_HIDDEN endif CFLAGS-tst-bsearch.c = $(stack-align-test-flags) +CFLAGS-tst-qsort.c = $(stack-align-test-flags) include ../Rules diff --git a/stdlib/tst-qsort.c b/stdlib/tst-qsort.c index f39667b17c..2b26e74d0b 100644 --- a/stdlib/tst-qsort.c +++ b/stdlib/tst-qsort.c @@ -1,17 +1,24 @@ /* Test case by Paul Eggert */ #include #include +#include struct big { char c[4 * 1024]; }; struct big *array; struct big *array_end; +static int align_check; + int compare (void const *a1, void const *b1) { struct big const *a = a1; struct big const *b = b1; + + if (!align_check) + align_check = TEST_STACK_ALIGN () ? -1 : 1; + if (! (array <= a && a < array_end && array <= b && b < array_end)) { @@ -38,5 +45,11 @@ main (int argc, char **argv) qsort (array, array_members, sizeof *array, compare); + if (align_check == -1) + { + puts ("stack not sufficiently aligned"); + exit (EXIT_FAILURE); + } + return 0; } diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h index 9c11f0b28c..15de939a3c 100644 --- a/sysdeps/arm/dl-machine.h +++ b/sysdeps/arm/dl-machine.h @@ -123,22 +123,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) return lazy; } -/* This code is used in dl-runtime.c to call the `fixup' function - and then redirect to the address it returns. */ - // macro for handling PIC situation.... -#ifdef PIC -#define CALL_ROUTINE(x) "\ - ldr sl,0f\n\ - add sl, pc, sl\n\ -1: ldr r2, 2f\n\ - mov lr, pc\n\ - add pc, sl, r2\n\ - b 3f\n\ -0: .word _GLOBAL_OFFSET_TABLE_ - 1b - 4\n\ -2: .word " #x "(GOTOFF)\n\ -3: " +#if defined(__THUMB_INTERWORK__) +#define BX(x) "bx\t" #x #else -#define CALL_ROUTINE(x) " bl " #x +#define BX(x) "mov\tpc, " #x #endif #ifndef PROF @@ -153,29 +141,29 @@ _dl_runtime_resolve:\n\ @ ip contains &GOT[n+3] (pointer to function)\n\ @ lr points to &GOT[2]\n\ \n\ - @ save almost everything; lr is already on the stack\n\ - stmdb sp!,{r0-r3,sl,fp}\n\ + @ stack arguments\n\ + stmdb sp!,{r0-r3}\n\ +\n\ + @ get pointer to linker struct\n\ + ldr r0, [lr, #-4]\n\ \n\ @ prepare to call fixup()\n\ @ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each\n\ sub r1, ip, lr\n\ sub r1, r1, #4\n\ add r1, r1, r1\n\ -\n\ - @ get pointer to linker struct\n\ - ldr r0, [lr, #-4]\n\ \n\ @ call fixup routine\n\ - " CALL_ROUTINE(fixup) "\n\ + bl fixup\n\ \n\ @ save the return\n\ mov ip, r0\n\ \n\ - @ restore the stack\n\ - ldmia sp!,{r0-r3,sl,fp,lr}\n\ + @ get arguments and return address back\n\ + ldmia sp!, {r0-r3,lr}\n\ \n\ @ jump to the newly found address\n\ - mov pc, ip\n\ + " BX(ip) "\n\ \n\ .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\ \n\ @@ -183,29 +171,29 @@ _dl_runtime_resolve:\n\ .type _dl_runtime_profile, #function\n\ .align 2\n\ _dl_runtime_profile:\n\ - @ save almost everything; lr is already on the stack\n\ - stmdb sp!,{r0-r3,sl,fp}\n\ + @ stack arguments\n\ + stmdb sp!, {r0-r3}\n\ +\n\ + @ get pointer to linker struct\n\ + ldr r0, [lr, #-4]\n\ \n\ @ prepare to call fixup()\n\ @ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each\n\ sub r1, ip, lr\n\ sub r1, r1, #4\n\ add r1, r1, r1\n\ -\n\ - @ get pointer to linker struct\n\ - ldr r0, [lr, #-4]\n\ \n\ @ call profiling fixup routine\n\ - " CALL_ROUTINE(profile_fixup) "\n\ + bl profile_fixup\n\ \n\ @ save the return\n\ mov ip, r0\n\ \n\ - @ restore the stack\n\ - ldmia sp!,{r0-r3,sl,fp,lr}\n\ + @ get arguments and return address back\n\ + ldmia sp!, {r0-r3,lr}\n\ \n\ @ jump to the newly found address\n\ - mov pc, ip\n\ + " BX(ip) "\n\ \n\ .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\ .previous\n\ @@ -225,29 +213,29 @@ _dl_runtime_profile:\n\ @ ip contains &GOT[n+3] (pointer to function)\n\ @ lr points to &GOT[2]\n\ \n\ - @ save almost everything; return add is already on the stack\n\ - stmdb sp!,{r0-r3,sl,fp}\n\ + @ stack arguments\n\ + stmdb sp!, {r0-r3}\n\ +\n\ + @ get pointer to linker struct\n\ + ldr r0, [lr, #-4]\n\ \n\ @ prepare to call fixup()\n\ @ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each\n\ sub r1, ip, lr\n\ sub r1, r1, #4\n\ add r1, r1, r1\n\ -\n\ - @ get pointer to linker struct\n\ - ldr r0, [lr, #-4]\n\ \n\ @ call profiling fixup routine\n\ - " CALL_ROUTINE(fixup) "\n\ + bl fixup\n\ \n\ @ save the return\n\ mov ip, r0\n\ \n\ - @ restore the stack\n\ - ldmia sp!,{r0-r3,sl,fp,lr}\n\ + @ get arguments and return address back\n\ + ldmia sp!, {r0-r3,lr}\n\ \n\ @ jump to the newly found address\n\ - mov pc, ip\n\ + " BX(ip) "\n\ \n\ .size _dl_runtime_profile, .-_dl_runtime_profile\n\ .previous\n\ diff --git a/sysdeps/arm/sysdep.h b/sysdeps/arm/sysdep.h index 4bc7d827b8..cb3f105afe 100644 --- a/sysdeps/arm/sysdep.h +++ b/sysdeps/arm/sysdep.h @@ -52,11 +52,20 @@ ldm##cond base,reglist #define RETINSTR(instr, regs...)\ instr regs +#ifdef __THUMB_INTERWORK__ +#define DO_RET(_reg) \ + bx _reg +#else +#define DO_RET(_reg) \ + mov pc, _reg +#endif #else /* APCS-26 */ #define LOADREGS(cond, base, reglist...)\ ldm##cond base,reglist^ #define RETINSTR(instr, regs...)\ instr##s regs +#define DO_RET(_reg) \ + movs pc, _reg #endif /* Define an entry point visible from C. */ diff --git a/sysdeps/i386/i686/Makefile b/sysdeps/i386/i686/Makefile index e9ac505e78..bfc0fc93f3 100644 --- a/sysdeps/i386/i686/Makefile +++ b/sysdeps/i386/i686/Makefile @@ -4,4 +4,4 @@ static-only-routines += hp-timing endif # So that we can test __m128's alignment -stack-align-test-flags += -msse -mpreferred-stack-boundary=4 +stack-align-test-flags += -msse diff --git a/sysdeps/unix/sysv/linux/arm/vfork.S b/sysdeps/unix/sysv/linux/arm/vfork.S index 0630c7ff06..bba1a548ba 100644 --- a/sysdeps/unix/sysv/linux/arm/vfork.S +++ b/sysdeps/unix/sysv/linux/arm/vfork.S @@ -38,8 +38,7 @@ ENTRY (__vfork) b PLTJMP(C_SYMBOL_NAME(__syscall_error)) # else /* Check if vfork syscall is known at all. */ - ldr a2, =-ENOSYS - teq a1, a2 + cmn a2, #ENOSYS bne PLTJMP(C_SYMBOL_NAME(__syscall_error)) # endif #endif @@ -50,6 +49,8 @@ ENTRY (__vfork) cmn a1, #4096 RETINSTR(movcc, pc, lr) b PLTJMP(C_SYMBOL_NAME(__syscall_error)) +#elif !defined __NR_vfork +# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined" #endif PSEUDO_END (__vfork) diff --git a/sysdeps/x86_64/tst-stack-align.h b/sysdeps/x86_64/tst-stack-align.h new file mode 100644 index 0000000000..a89f092c5c --- /dev/null +++ b/sysdeps/x86_64/tst-stack-align.h @@ -0,0 +1,47 @@ +/* Copyright (C) 2003 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 + +#define TEST_STACK_ALIGN() \ + ({ \ + /* AMD64 ABI mandates 16byte aligned stack. \ + Unfortunately, current GCC doesn't support __int128 or __float128 \ + types, so use aligned attribute instead. */ \ + struct _S \ + { \ + int _i __attribute__((aligned (16))); \ + int _pad[3]; \ + } _s = { ._i = 18 }; \ + double _d = 12.0; \ + long double _ld = 15.0; \ + int _ret = 0; \ + printf ("__int128: %d %p %zu\n", _s._i, &_s, __alignof (_s)); \ + if ((((uintptr_t) &_s) & (__alignof (_s) - 1)) != 0) \ + _ret = 1; \ + \ + printf ("double: %g %p %zu\n", _d, &_d, __alignof (double)); \ + if ((((uintptr_t) &_d) & (__alignof (double) - 1)) != 0) \ + _ret = 1; \ + \ + printf ("ldouble: %Lg %p %zu\n", _ld, &_ld, __alignof (long double)); \ + if ((((uintptr_t) &_ld) & (__alignof (long double) - 1)) != 0) \ + _ret = 1; \ + _ret; \ + })