mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-03 08:11:08 +00:00
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.
This commit is contained in:
parent
65af7e6142
commit
06f6ca9019
12
elf/Makefile
12
elf/Makefile
@ -71,7 +71,7 @@ distribute := rtld-Rules \
|
|||||||
tst-tlsmod1.c tst-tlsmod2.c tst-tlsmod3.c tst-tlsmod4.c \
|
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-tlsmod5.c tst-tlsmod6.c tst-tlsmod7.c tst-tlsmod8.c \
|
||||||
tst-tlsmod9.c tst-tlsmod10.c tst-tlsmod11.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 \
|
circlemod1.c circlemod1a.c circlemod2.c circlemod2a.c \
|
||||||
circlemod3.c circlemod3a.c nodlopenmod2.c \
|
circlemod3.c circlemod3a.c nodlopenmod2.c \
|
||||||
tls-macros.h \
|
tls-macros.h \
|
||||||
@ -150,7 +150,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
|||||||
neededtest3 neededtest4 unload2 lateglobal initfirst global \
|
neededtest3 neededtest4 unload2 lateglobal initfirst global \
|
||||||
restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
|
restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
|
||||||
circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \
|
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
|
# reldep9
|
||||||
test-srcs = tst-pathopt
|
test-srcs = tst-pathopt
|
||||||
tests-vis-yes = vismain
|
tests-vis-yes = vismain
|
||||||
@ -177,7 +177,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
|||||||
circlemod1 circlemod1a circlemod2 circlemod2a \
|
circlemod1 circlemod1a circlemod2 circlemod2a \
|
||||||
circlemod3 circlemod3a \
|
circlemod3 circlemod3a \
|
||||||
reldep8mod1 reldep8mod2 reldep8mod3 \
|
reldep8mod1 reldep8mod2 reldep8mod3 \
|
||||||
reldep9mod1 reldep9mod2 reldep9mod3
|
reldep9mod1 reldep9mod2 reldep9mod3 \
|
||||||
|
tst-alignmod
|
||||||
ifeq (yes,$(have-initfini-array))
|
ifeq (yes,$(have-initfini-array))
|
||||||
modules-names += tst-array2dep
|
modules-names += tst-array2dep
|
||||||
endif
|
endif
|
||||||
@ -648,6 +649,11 @@ $(objpfx)tst-tls13.out: $(objpfx)tst-tlsmod13a.so
|
|||||||
$(objpfx)tst-tls14: $(objpfx)tst-tlsmod14a.so $(libdl)
|
$(objpfx)tst-tls14: $(objpfx)tst-tlsmod14a.so $(libdl)
|
||||||
$(objpfx)tst-tls14.out:$(objpfx)tst-tlsmod14b.so
|
$(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
|
ifdef libdl
|
||||||
$(objpfx)tst-tls9-static: $(common-objpfx)dlfcn/libdl.a
|
$(objpfx)tst-tls9-static: $(common-objpfx)dlfcn/libdl.a
|
||||||
$(objpfx)tst-tls9-static.out: $(objpfx)tst-tlsmod5.so $(objpfx)tst-tlsmod6.so
|
$(objpfx)tst-tls9-static.out: $(objpfx)tst-tlsmod5.so $(objpfx)tst-tlsmod6.so
|
||||||
|
54
elf/tst-align.c
Normal file
54
elf/tst-align.c
Normal 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
53
elf/tst-alignmod.c
Normal 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;
|
||||||
|
}
|
@ -32,8 +32,6 @@ struct _IO_FILE_memstream
|
|||||||
|
|
||||||
static int _IO_mem_sync __P ((_IO_FILE* fp));
|
static int _IO_mem_sync __P ((_IO_FILE* fp));
|
||||||
static void _IO_mem_finish __P ((_IO_FILE* fp, int));
|
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 =
|
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)
|
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
|
/* 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
|
necessary. *BUFLOC and *SIZELOC are updated with the buffer's location
|
||||||
and the number of characters written on fflush or fclose. */
|
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);
|
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);
|
|
||||||
}
|
|
||||||
|
@ -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>
|
2003-09-17 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
* descr.h (manager_thread): Rename to...
|
* descr.h (manager_thread): Rename to...
|
||||||
|
@ -404,7 +404,11 @@ int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_TLS
|
||||||
if (attr->__stackaddr == NULL)
|
if (attr->__stackaddr == NULL)
|
||||||
|
#else
|
||||||
|
if (descr == &__pthread_initial_thread)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* Defined in ld.so. */
|
/* Defined in ld.so. */
|
||||||
extern void *__libc_stack_end;
|
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->__stacksize = rl.rlim_cur;
|
||||||
attr->__stackaddr = (void *) to;
|
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. */
|
/* We succeed and no need to look further. */
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -20,37 +20,60 @@
|
|||||||
#include <sysdep-cancel.h>
|
#include <sysdep-cancel.h>
|
||||||
#define _ERRNO_H 1
|
#define _ERRNO_H 1
|
||||||
#include <bits/errno.h>
|
#include <bits/errno.h>
|
||||||
|
#include <kernel-features.h>
|
||||||
|
|
||||||
/* Clone the calling process, but without copying the whole address
|
/* Clone the calling process, but without copying the whole address space.
|
||||||
pace.
|
|
||||||
The calling process is suspended until the new process exits or is
|
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
|
replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
|
||||||
rocess,
|
|
||||||
and the process ID of the new process to the old process. */
|
and the process ID of the new process to the old process. */
|
||||||
|
|
||||||
PSEUDO_PROLOGUE
|
PSEUDO_PROLOGUE
|
||||||
|
|
||||||
ENTRY (__vfork)
|
ENTRY (__vfork)
|
||||||
|
|
||||||
SINGLE_THREAD_P
|
|
||||||
bne HIDDEN_JUMPTARGET (__fork)
|
|
||||||
#ifdef __NR_vfork
|
#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
|
swi __NR_vfork
|
||||||
cmn a1, #4096
|
cmn a1, #4096
|
||||||
RETINSTR(movcc, pc, lr)
|
RETINSTR(movcc, pc, lr)
|
||||||
|
|
||||||
|
#ifndef __ASSUME_VFORK_SYSCALL
|
||||||
/* Check if vfork syscall is known at all. */
|
/* Check if vfork syscall is known at all. */
|
||||||
ldr a2, =-ENOSYS
|
cmn a1, #ENOSYS
|
||||||
teq a1, a2
|
|
||||||
bne PLTJMP(C_SYMBOL_NAME(__syscall_error))
|
bne PLTJMP(C_SYMBOL_NAME(__syscall_error))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ASSUME_VFORK_SYSCALL
|
||||||
/* If we don't have vfork, fork is close enough. */
|
/* If we don't have vfork, fork is close enough. */
|
||||||
swi __NR_fork
|
swi __NR_fork
|
||||||
cmn a1, #4096
|
cmn a1, #4096
|
||||||
RETINSTR(movcc, pc, lr)
|
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))
|
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)
|
PSEUDO_END (__vfork)
|
||||||
libc_hidden_def (__vfork)
|
libc_hidden_def (__vfork)
|
||||||
|
|
||||||
|
@ -89,6 +89,7 @@ CFLAGS-mkstemp64.c = -fexceptions
|
|||||||
CFLAGS-getsysstats.c = -fexceptions
|
CFLAGS-getsysstats.c = -fexceptions
|
||||||
CFLAGS-getusershell.c = -fexceptions
|
CFLAGS-getusershell.c = -fexceptions
|
||||||
CFLAGS-err.c = -fexceptions
|
CFLAGS-err.c = -fexceptions
|
||||||
|
CFLAGS-tst-tsearch.c = $(stack-align-test-flags)
|
||||||
|
|
||||||
include ../Rules
|
include ../Rules
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Test program for tsearch et al.
|
/* 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.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -25,6 +25,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <search.h>
|
#include <search.h>
|
||||||
|
#include <tst-stack-align.h>
|
||||||
|
|
||||||
#define SEED 0
|
#define SEED 0
|
||||||
#define BALANCED 1
|
#define BALANCED 1
|
||||||
@ -72,10 +73,14 @@ static int depths[SIZE];
|
|||||||
/* Maximum depth during a tree walk. */
|
/* Maximum depth during a tree walk. */
|
||||||
static int max_depth;
|
static int max_depth;
|
||||||
|
|
||||||
|
static int stack_align_check[2];
|
||||||
|
|
||||||
/* Compare two keys. */
|
/* Compare two keys. */
|
||||||
static int
|
static int
|
||||||
cmp_fn (const void *a, const void *b)
|
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;
|
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;
|
int key = **(int **) nodep;
|
||||||
|
|
||||||
|
if (!stack_align_check[1])
|
||||||
|
stack_align_check[1] = TEST_STACK_ALIGN () ? -1 : 1;
|
||||||
|
|
||||||
if (depth > max_depth)
|
if (depth > max_depth)
|
||||||
max_depth = depth;
|
max_depth = depth;
|
||||||
if (which == leaf || which == preorder)
|
if (which == leaf || which == preorder)
|
||||||
@ -329,5 +337,17 @@ main (int argc, char **argv)
|
|||||||
total_error |= error;
|
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;
|
return total_error;
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
NPTL 0.58 by Ulrich Drepper
|
NPTL 0.59 by Ulrich Drepper
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
2003-09-17 Jakub Jelinek <jakub@redhat.com>
|
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.
|
* sysdeps/i386/Makefile (CFLAGS-tst-align.c): Remove.
|
||||||
|
|
||||||
2003-09-15 Jakub Jelinek <jakub@redhat.com>
|
2003-09-15 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
@ -189,7 +189,7 @@ CFLAGS-pt-system.c = -fexceptions
|
|||||||
omit-deps = $(unix-syscalls:%=ptw-%)
|
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-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \
|
||||||
tst-mutex7 tst-mutex8 tst-mutex9 \
|
tst-mutex7 tst-mutex8 tst-mutex9 \
|
||||||
tst-spin1 tst-spin2 tst-spin3 \
|
tst-spin1 tst-spin2 tst-spin3 \
|
||||||
|
@ -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,
|
extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
|
||||||
int execute);
|
int execute);
|
||||||
|
|
||||||
|
#if defined NOT_IN_libc && defined IS_IN_libpthread
|
||||||
|
hidden_proto (pthread_getaffinity_np)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* pthreadP.h */
|
#endif /* pthreadP.h */
|
||||||
|
@ -114,6 +114,11 @@ pthread_getattr_np (thread_id, attr)
|
|||||||
iattr->stacksize = rl.rlim_cur;
|
iattr->stacksize = rl.rlim_cur;
|
||||||
iattr->stackaddr = (void *) to;
|
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. */
|
/* We succeed and no need to look further. */
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
@ -127,6 +132,23 @@ pthread_getattr_np (thread_id, attr)
|
|||||||
|
|
||||||
iattr->flags |= ATTR_FLAG_STACKADDR;
|
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);
|
lll_unlock (thread->lock);
|
||||||
|
|
||||||
pthread_cleanup_pop (0);
|
pthread_cleanup_pop (0);
|
||||||
|
@ -35,7 +35,10 @@ pthread_attr_getaffinity_np (attr, cpuset)
|
|||||||
assert (sizeof (*attr) >= sizeof (struct pthread_attr));
|
assert (sizeof (*attr) >= sizeof (struct pthread_attr));
|
||||||
iattr = (struct pthread_attr *) attr;
|
iattr = (struct pthread_attr *) attr;
|
||||||
|
|
||||||
|
if (iattr->cpuset)
|
||||||
memcpy (cpuset, iattr->cpuset, sizeof (cpu_set_t));
|
memcpy (cpuset, iattr->cpuset, sizeof (cpu_set_t));
|
||||||
|
else
|
||||||
|
memset (cpuset, -1, sizeof (cpu_set_t));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -41,3 +41,4 @@ pthread_getaffinity_np (th, cpuset)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
hidden_def (pthread_getaffinity_np)
|
||||||
|
414
nptl/tst-attr3.c
Normal file
414
nptl/tst-attr3.c
Normal 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"
|
@ -97,6 +97,7 @@ CFLAGS-atexit.c = -DHAVE_DOT_HIDDEN
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS-tst-bsearch.c = $(stack-align-test-flags)
|
CFLAGS-tst-bsearch.c = $(stack-align-test-flags)
|
||||||
|
CFLAGS-tst-qsort.c = $(stack-align-test-flags)
|
||||||
|
|
||||||
include ../Rules
|
include ../Rules
|
||||||
|
|
||||||
|
@ -1,17 +1,24 @@
|
|||||||
/* Test case by Paul Eggert <eggert@twinsun.com> */
|
/* Test case by Paul Eggert <eggert@twinsun.com> */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <tst-stack-align.h>
|
||||||
|
|
||||||
struct big { char c[4 * 1024]; };
|
struct big { char c[4 * 1024]; };
|
||||||
|
|
||||||
struct big *array;
|
struct big *array;
|
||||||
struct big *array_end;
|
struct big *array_end;
|
||||||
|
|
||||||
|
static int align_check;
|
||||||
|
|
||||||
int
|
int
|
||||||
compare (void const *a1, void const *b1)
|
compare (void const *a1, void const *b1)
|
||||||
{
|
{
|
||||||
struct big const *a = a1;
|
struct big const *a = a1;
|
||||||
struct big const *b = b1;
|
struct big const *b = b1;
|
||||||
|
|
||||||
|
if (!align_check)
|
||||||
|
align_check = TEST_STACK_ALIGN () ? -1 : 1;
|
||||||
|
|
||||||
if (! (array <= a && a < array_end
|
if (! (array <= a && a < array_end
|
||||||
&& array <= b && b < array_end))
|
&& array <= b && b < array_end))
|
||||||
{
|
{
|
||||||
@ -38,5 +45,11 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
qsort (array, array_members, sizeof *array, compare);
|
qsort (array, array_members, sizeof *array, compare);
|
||||||
|
|
||||||
|
if (align_check == -1)
|
||||||
|
{
|
||||||
|
puts ("stack not sufficiently aligned");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -123,22 +123,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
|||||||
return lazy;
|
return lazy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This code is used in dl-runtime.c to call the `fixup' function
|
#if defined(__THUMB_INTERWORK__)
|
||||||
and then redirect to the address it returns. */
|
#define BX(x) "bx\t" #x
|
||||||
// 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: "
|
|
||||||
#else
|
#else
|
||||||
#define CALL_ROUTINE(x) " bl " #x
|
#define BX(x) "mov\tpc, " #x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PROF
|
#ifndef PROF
|
||||||
@ -153,29 +141,29 @@ _dl_runtime_resolve:\n\
|
|||||||
@ ip contains &GOT[n+3] (pointer to function)\n\
|
@ ip contains &GOT[n+3] (pointer to function)\n\
|
||||||
@ lr points to &GOT[2]\n\
|
@ lr points to &GOT[2]\n\
|
||||||
\n\
|
\n\
|
||||||
@ save almost everything; lr is already on the stack\n\
|
@ stack arguments\n\
|
||||||
stmdb sp!,{r0-r3,sl,fp}\n\
|
stmdb sp!,{r0-r3}\n\
|
||||||
|
\n\
|
||||||
|
@ get pointer to linker struct\n\
|
||||||
|
ldr r0, [lr, #-4]\n\
|
||||||
\n\
|
\n\
|
||||||
@ prepare to call fixup()\n\
|
@ prepare to call fixup()\n\
|
||||||
@ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each\n\
|
@ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each\n\
|
||||||
sub r1, ip, lr\n\
|
sub r1, ip, lr\n\
|
||||||
sub r1, r1, #4\n\
|
sub r1, r1, #4\n\
|
||||||
add r1, r1, r1\n\
|
add r1, r1, r1\n\
|
||||||
\n\
|
|
||||||
@ get pointer to linker struct\n\
|
|
||||||
ldr r0, [lr, #-4]\n\
|
|
||||||
\n\
|
\n\
|
||||||
@ call fixup routine\n\
|
@ call fixup routine\n\
|
||||||
" CALL_ROUTINE(fixup) "\n\
|
bl fixup\n\
|
||||||
\n\
|
\n\
|
||||||
@ save the return\n\
|
@ save the return\n\
|
||||||
mov ip, r0\n\
|
mov ip, r0\n\
|
||||||
\n\
|
\n\
|
||||||
@ restore the stack\n\
|
@ get arguments and return address back\n\
|
||||||
ldmia sp!,{r0-r3,sl,fp,lr}\n\
|
ldmia sp!, {r0-r3,lr}\n\
|
||||||
\n\
|
\n\
|
||||||
@ jump to the newly found address\n\
|
@ jump to the newly found address\n\
|
||||||
mov pc, ip\n\
|
" BX(ip) "\n\
|
||||||
\n\
|
\n\
|
||||||
.size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
|
.size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
|
||||||
\n\
|
\n\
|
||||||
@ -183,29 +171,29 @@ _dl_runtime_resolve:\n\
|
|||||||
.type _dl_runtime_profile, #function\n\
|
.type _dl_runtime_profile, #function\n\
|
||||||
.align 2\n\
|
.align 2\n\
|
||||||
_dl_runtime_profile:\n\
|
_dl_runtime_profile:\n\
|
||||||
@ save almost everything; lr is already on the stack\n\
|
@ stack arguments\n\
|
||||||
stmdb sp!,{r0-r3,sl,fp}\n\
|
stmdb sp!, {r0-r3}\n\
|
||||||
|
\n\
|
||||||
|
@ get pointer to linker struct\n\
|
||||||
|
ldr r0, [lr, #-4]\n\
|
||||||
\n\
|
\n\
|
||||||
@ prepare to call fixup()\n\
|
@ prepare to call fixup()\n\
|
||||||
@ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each\n\
|
@ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each\n\
|
||||||
sub r1, ip, lr\n\
|
sub r1, ip, lr\n\
|
||||||
sub r1, r1, #4\n\
|
sub r1, r1, #4\n\
|
||||||
add r1, r1, r1\n\
|
add r1, r1, r1\n\
|
||||||
\n\
|
|
||||||
@ get pointer to linker struct\n\
|
|
||||||
ldr r0, [lr, #-4]\n\
|
|
||||||
\n\
|
\n\
|
||||||
@ call profiling fixup routine\n\
|
@ call profiling fixup routine\n\
|
||||||
" CALL_ROUTINE(profile_fixup) "\n\
|
bl profile_fixup\n\
|
||||||
\n\
|
\n\
|
||||||
@ save the return\n\
|
@ save the return\n\
|
||||||
mov ip, r0\n\
|
mov ip, r0\n\
|
||||||
\n\
|
\n\
|
||||||
@ restore the stack\n\
|
@ get arguments and return address back\n\
|
||||||
ldmia sp!,{r0-r3,sl,fp,lr}\n\
|
ldmia sp!, {r0-r3,lr}\n\
|
||||||
\n\
|
\n\
|
||||||
@ jump to the newly found address\n\
|
@ jump to the newly found address\n\
|
||||||
mov pc, ip\n\
|
" BX(ip) "\n\
|
||||||
\n\
|
\n\
|
||||||
.size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
|
.size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
|
||||||
.previous\n\
|
.previous\n\
|
||||||
@ -225,29 +213,29 @@ _dl_runtime_profile:\n\
|
|||||||
@ ip contains &GOT[n+3] (pointer to function)\n\
|
@ ip contains &GOT[n+3] (pointer to function)\n\
|
||||||
@ lr points to &GOT[2]\n\
|
@ lr points to &GOT[2]\n\
|
||||||
\n\
|
\n\
|
||||||
@ save almost everything; return add is already on the stack\n\
|
@ stack arguments\n\
|
||||||
stmdb sp!,{r0-r3,sl,fp}\n\
|
stmdb sp!, {r0-r3}\n\
|
||||||
|
\n\
|
||||||
|
@ get pointer to linker struct\n\
|
||||||
|
ldr r0, [lr, #-4]\n\
|
||||||
\n\
|
\n\
|
||||||
@ prepare to call fixup()\n\
|
@ prepare to call fixup()\n\
|
||||||
@ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each\n\
|
@ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each\n\
|
||||||
sub r1, ip, lr\n\
|
sub r1, ip, lr\n\
|
||||||
sub r1, r1, #4\n\
|
sub r1, r1, #4\n\
|
||||||
add r1, r1, r1\n\
|
add r1, r1, r1\n\
|
||||||
\n\
|
|
||||||
@ get pointer to linker struct\n\
|
|
||||||
ldr r0, [lr, #-4]\n\
|
|
||||||
\n\
|
\n\
|
||||||
@ call profiling fixup routine\n\
|
@ call profiling fixup routine\n\
|
||||||
" CALL_ROUTINE(fixup) "\n\
|
bl fixup\n\
|
||||||
\n\
|
\n\
|
||||||
@ save the return\n\
|
@ save the return\n\
|
||||||
mov ip, r0\n\
|
mov ip, r0\n\
|
||||||
\n\
|
\n\
|
||||||
@ restore the stack\n\
|
@ get arguments and return address back\n\
|
||||||
ldmia sp!,{r0-r3,sl,fp,lr}\n\
|
ldmia sp!, {r0-r3,lr}\n\
|
||||||
\n\
|
\n\
|
||||||
@ jump to the newly found address\n\
|
@ jump to the newly found address\n\
|
||||||
mov pc, ip\n\
|
" BX(ip) "\n\
|
||||||
\n\
|
\n\
|
||||||
.size _dl_runtime_profile, .-_dl_runtime_profile\n\
|
.size _dl_runtime_profile, .-_dl_runtime_profile\n\
|
||||||
.previous\n\
|
.previous\n\
|
||||||
|
@ -52,11 +52,20 @@
|
|||||||
ldm##cond base,reglist
|
ldm##cond base,reglist
|
||||||
#define RETINSTR(instr, regs...)\
|
#define RETINSTR(instr, regs...)\
|
||||||
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 */
|
#else /* APCS-26 */
|
||||||
#define LOADREGS(cond, base, reglist...)\
|
#define LOADREGS(cond, base, reglist...)\
|
||||||
ldm##cond base,reglist^
|
ldm##cond base,reglist^
|
||||||
#define RETINSTR(instr, regs...)\
|
#define RETINSTR(instr, regs...)\
|
||||||
instr##s regs
|
instr##s regs
|
||||||
|
#define DO_RET(_reg) \
|
||||||
|
movs pc, _reg
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Define an entry point visible from C. */
|
/* Define an entry point visible from C. */
|
||||||
|
@ -4,4 +4,4 @@ static-only-routines += hp-timing
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# So that we can test __m128's alignment
|
# So that we can test __m128's alignment
|
||||||
stack-align-test-flags += -msse -mpreferred-stack-boundary=4
|
stack-align-test-flags += -msse
|
||||||
|
@ -38,8 +38,7 @@ ENTRY (__vfork)
|
|||||||
b PLTJMP(C_SYMBOL_NAME(__syscall_error))
|
b PLTJMP(C_SYMBOL_NAME(__syscall_error))
|
||||||
# else
|
# else
|
||||||
/* Check if vfork syscall is known at all. */
|
/* Check if vfork syscall is known at all. */
|
||||||
ldr a2, =-ENOSYS
|
cmn a2, #ENOSYS
|
||||||
teq a1, a2
|
|
||||||
bne PLTJMP(C_SYMBOL_NAME(__syscall_error))
|
bne PLTJMP(C_SYMBOL_NAME(__syscall_error))
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
@ -50,6 +49,8 @@ ENTRY (__vfork)
|
|||||||
cmn a1, #4096
|
cmn a1, #4096
|
||||||
RETINSTR(movcc, pc, lr)
|
RETINSTR(movcc, pc, lr)
|
||||||
b PLTJMP(C_SYMBOL_NAME(__syscall_error))
|
b PLTJMP(C_SYMBOL_NAME(__syscall_error))
|
||||||
|
#elif !defined __NR_vfork
|
||||||
|
# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PSEUDO_END (__vfork)
|
PSEUDO_END (__vfork)
|
||||||
|
47
sysdeps/x86_64/tst-stack-align.h
Normal file
47
sysdeps/x86_64/tst-stack-align.h
Normal 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; \
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user