summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-09-17 18:23:49 +0000
committerUlrich Drepper <drepper@redhat.com>2003-09-17 18:23:49 +0000
commit06f6ca9019897f5d1799c0ae8d7293ed249c0f97 (patch)
tree9a04e5058de47ce0898cf279205c8e58735efb96
parent65af7e61427ce9bbbc0e43b2ad44e5b4678a37fc (diff)
Update.
2003-09-17 Philip Blundell <philb@gnu.org> * sysdeps/unix/sysv/linux/arm/vfork.S: Branch to fork if libpthread is loaded. Elide backwards compatibility code when not required.
-rw-r--r--elf/Makefile12
-rw-r--r--elf/tst-align.c54
-rw-r--r--elf/tst-alignmod.c53
-rw-r--r--libio/memstream.c78
-rw-r--r--linuxthreads/ChangeLog6
-rw-r--r--linuxthreads/attr.c9
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S39
-rw-r--r--misc/Makefile1
-rw-r--r--misc/tst-tsearch.c22
-rw-r--r--nptl/Banner2
-rw-r--r--nptl/ChangeLog11
-rw-r--r--nptl/Makefile2
-rw-r--r--nptl/pthreadP.h4
-rw-r--r--nptl/pthread_getattr_np.c22
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c5
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c1
-rw-r--r--nptl/tst-attr3.c414
-rw-r--r--stdlib/Makefile1
-rw-r--r--stdlib/tst-qsort.c13
-rw-r--r--sysdeps/arm/dl-machine.h72
-rw-r--r--sysdeps/arm/sysdep.h9
-rw-r--r--sysdeps/i386/i686/Makefile2
-rw-r--r--sysdeps/unix/sysv/linux/arm/vfork.S5
-rw-r--r--sysdeps/x86_64/tst-stack-align.h47
24 files changed, 746 insertions, 138 deletions
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 <jakub@redhat.com>, 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 <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+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 <jakub@redhat.com>, 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 <stdio.h>
+#include <tst-stack-align.h>
+
+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 <philb@gnu.org>
+
+ * 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 <jakub@redhat.com>
* 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 <sysdep-cancel.h>
#define _ERRNO_H 1
#include <bits/errno.h>
+#include <kernel-features.h>
-/* 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 <stdlib.h>
#include <string.h>
#include <search.h>
+#include <tst-stack-align.h>
#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 <jakub@redhat.com>
+ * 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 <jakub@redhat.com>
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 <jakub@redhat.com>, 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 <errno.h>
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <stackinfo.h>
+
+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 <eggert@twinsun.com> */
#include <stdio.h>
#include <stdlib.h>
+#include <tst-stack-align.h>
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,8 +141,11 @@ _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\
@@ -162,20 +153,17 @@ _dl_runtime_resolve:\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,8 +171,11 @@ _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\
@@ -192,20 +183,17 @@ _dl_runtime_profile:\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,8 +213,11 @@ _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\
@@ -234,20 +225,17 @@ _dl_runtime_profile:\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 <stdio.h>
+#include <stdint.h>
+
+#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; \
+ })