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.
This commit is contained in:
Ulrich Drepper 2003-09-17 18:23:49 +00:00
parent 65af7e6142
commit 06f6ca9019
24 changed files with 746 additions and 138 deletions

View File

@ -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

54
elf/tst-align.c Normal file
View File

@ -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"

53
elf/tst-alignmod.c Normal file
View File

@ -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;
}

View File

@ -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);
}

View File

@ -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...

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -1 +1 @@
NPTL 0.58 by Ulrich Drepper
NPTL 0.59 by Ulrich Drepper

View File

@ -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>

View File

@ -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 \

View File

@ -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 */

View File

@ -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);

View File

@ -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;
}

View File

@ -41,3 +41,4 @@ pthread_getaffinity_np (th, cpuset)
return 0;
}
hidden_def (pthread_getaffinity_np)

414
nptl/tst-attr3.c Normal file
View File

@ -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"

View File

@ -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

View File

@ -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;
}

View File

@ -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\

View File

@ -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. */

View File

@ -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

View File

@ -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)

View File

@ -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; \
})