diff options
Diffstat (limited to 'libpthread/nptl/sysdeps/i386')
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/Makefile | 27 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/Makefile.arch | 53 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/dl-tls.h | 60 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S | 47 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S | 20 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/i686/Makefile | 32 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S | 21 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/i686/tls.h | 36 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h | 32 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/pthread_spin_init.c | 20 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/pthread_spin_lock.c | 49 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S | 32 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/pthreaddef.h | 48 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/tcb-offsets.sym | 17 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/i386/tls.h | 480 | 
15 files changed, 974 insertions, 0 deletions
| diff --git a/libpthread/nptl/sysdeps/i386/Makefile b/libpthread/nptl/sysdeps/i386/Makefile new file mode 100644 index 000000000..2f0d88f30 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/Makefile @@ -0,0 +1,27 @@ +# Copyright (C) 2002, 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. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif + +ifeq ($(subdir),nptl) +CFLAGS-pthread_create.c += -mpreferred-stack-boundary=4 +CFLAGS-tst-align.c += -mpreferred-stack-boundary=4 +CFLAGS-tst-align2.c += -mpreferred-stack-boundary=4 +endif diff --git a/libpthread/nptl/sysdeps/i386/Makefile.arch b/libpthread/nptl/sysdeps/i386/Makefile.arch new file mode 100644 index 000000000..e047b1428 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/Makefile.arch @@ -0,0 +1,53 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_CSRC = pthread_spin_lock.c +libpthread_SSRC = i486/pthread_spin_trylock.S + +CFLAGS-pthread_spin_lock.c += -D_GNU_SOURCE + +CFLAGS-i386 = $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +PTHREAD_ARCH_DIR := $(top_srcdir)libpthread/nptl/sysdeps/i386 +PTHREAD_ARCH_OUT := $(top_builddir)libpthread/nptl/sysdeps/i386 +PTHREAD_ARCH_OBJ := $(patsubst %.S,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_SSRC)) +PTHREAD_ARCH_OBJ += $(patsubst %.c,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(PTHREAD_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(PTHREAD_ARCH_OBJ) +endif +libpthread-so-y += $(PTHREAD_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y += $(PTHREAD_ARCH_OBJ) + +objclean-y += nptl_arch_clean +headers_clean-y += nptl_arch_headers_clean + +# +# Create 'tcb-offsets.h' header file. +# +CFLAGS-tcb-offsets.c = -S + +$(PTHREAD_ARCH_OUT)/tcb-offsets.c: $(PTHREAD_ARCH_DIR)/tcb-offsets.sym +	$(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_ARCH_OUT)/tcb-offsets.s: $(PTHREAD_ARCH_OUT)/tcb-offsets.c +	$(compile.c) + +$(PTHREAD_ARCH_OUT)/tcb-offsets.h: $(PTHREAD_ARCH_OUT)/tcb-offsets.s +	@sed -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(PTHREAD_ARCH_OUT)/tcb-offsets.h + +nptl_arch_headers_clean: +	$(do_rm) $(addprefix $(PTHREAD_ARCH_OUT)/tcb-offsets., c s h) + +nptl_arch_clean: +	$(do_rm) $(addprefix $(PTHREAD_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/i386/dl-tls.h b/libpthread/nptl/sysdeps/i386/dl-tls.h new file mode 100644 index 000000000..a1707197c --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/dl-tls.h @@ -0,0 +1,60 @@ +/* Thread-local storage handling in the ELF dynamic linker.  i386 version. +   Copyright (C) 2002, 2004 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.  */ + + +/* Type used for the representation of TLS information in the GOT.  */ +typedef struct +{ +  unsigned long int ti_module; +  unsigned long int ti_offset; +} tls_index; + + +#ifdef SHARED +/* This is the prototype for the GNU version.  */ +extern void *___tls_get_addr (tls_index *ti) +     __attribute__ ((__regparm__ (1))); +extern void *___tls_get_addr_internal (tls_index *ti) +     __attribute__ ((__regparm__ (1))) attribute_hidden; + +# ifdef IS_IN_rtld +/* The special thing about the x86 TLS ABI is that we have two +   variants of the __tls_get_addr function with different calling +   conventions.  The GNU version, which we are mostly concerned here, +   takes the parameter in a register.  The name is changed by adding +   an additional underscore at the beginning.  The Sun version uses +   the normal calling convention.  */ +void * +__tls_get_addr (tls_index *ti) +{ +  return ___tls_get_addr_internal (ti); +} + + +/* Prepare using the definition of __tls_get_addr in the generic +   version of this file.  */ +# define __tls_get_addr __attribute__ ((__regparm__ (1))) ___tls_get_addr +strong_alias (___tls_get_addr, ___tls_get_addr_internal) +#else + +/* Users should get the better interface.  */ +# define __tls_get_addr ___tls_get_addr + +# endif +#endif diff --git a/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S new file mode 100644 index 000000000..e30072c3d --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S @@ -0,0 +1,47 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   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 <pthread-errnos.h> + + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +	.globl	pthread_spin_trylock +	.type	pthread_spin_trylock,@function +	.align	16 +pthread_spin_trylock: +	movl	4(%esp), %edx +	movl	$1, %eax +	xorl	%ecx, %ecx +	LOCK +	cmpxchgl %ecx, (%edx) +	movl	$EBUSY, %eax +#ifdef HAVE_CMOV +	cmovel	%ecx, %eax +#else +	jne	0f +	movl	%ecx, %eax +0: +#endif +	ret +	.size	pthread_spin_trylock,.-pthread_spin_trylock diff --git a/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S new file mode 100644 index 000000000..ffe3d456b --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   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 "../i486/pthread_spin_trylock.S" diff --git a/libpthread/nptl/sysdeps/i386/i686/Makefile b/libpthread/nptl/sysdeps/i386/i686/Makefile new file mode 100644 index 000000000..137c0a2f0 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i686/Makefile @@ -0,0 +1,32 @@ +# Copyright (C) 2003 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +# 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. + +ifeq ($(subdir),nptl) +# It turns out that stack coloring is in general not good on P4s.  Some +# applications will benefit.  We will probably have a configuration option +# at some point.  Enabling coloring can be done with +# +#   -DCOLORING_INCREMENT=128 +# +# What is useful is to avoid the 64k aliasing problem which reliably +# happens if all stacks use sizes which are a multiple of 64k.  Tell +# the stack allocator to disturb this by allocation one more page if +# necessary. +CFLAGS-pthread_create.c += -DMULTI_PAGE_ALIASING=65536 +endif diff --git a/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S new file mode 100644 index 000000000..a5d861f92 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S @@ -0,0 +1,21 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   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.  */ + +#define HAVE_CMOV	1 +#include "../i486/pthread_spin_trylock.S" diff --git a/libpthread/nptl/sysdeps/i386/i686/tls.h b/libpthread/nptl/sysdeps/i386/i686/tls.h new file mode 100644 index 000000000..4025ed8d2 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i686/tls.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   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.  */ + +#ifndef _TLS_H + +/* Additional definitions for <tls.h> on i686 and up.  */ + + +/* Macros to load from and store into segment registers.  We can use +   the 32-bit instructions.  */ +#define TLS_GET_GS() \ +  ({ int __seg; __asm ("movl %%gs, %0" : "=q" (__seg)); __seg; }) +#define TLS_SET_GS(val) \ +  __asm ("movl %0, %%gs" :: "q" (val)) + + +/* Get the full set of definitions.  */ +#include "../tls.h" + +#endif	/* tls.h */ diff --git a/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h new file mode 100644 index 000000000..b9528f363 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2003, 2004 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 <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ +  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ +  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj)) + +/* We use the normal lobngjmp for unwinding.  */ +extern __typeof(longjmp) __libc_longjmp attribute_noreturn; +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/i386/pthread_spin_init.c b/libpthread/nptl/sysdeps/i386/pthread_spin_init.c new file mode 100644 index 000000000..0a47981aa --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/pthread_spin_init.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   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.  */ + +/* Not needed.  pthread_spin_init is an alias for pthread_spin_unlock.  */ diff --git a/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c b/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c new file mode 100644 index 000000000..34cd525dc --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002,2003,2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   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 "pthreadP.h" + +#ifndef LOCK_PREFIX +# ifdef UP +#  define LOCK_PREFIX	/* nothing */ +# else +#  define LOCK_PREFIX	"lock;" +# endif +#endif + + +int +pthread_spin_lock ( +     pthread_spinlock_t *lock) +{ +  __asm__ ("\n" +       "1:\t" LOCK_PREFIX "decl %0\n\t" +       "jne 2f\n\t" +       ".subsection 1\n\t" +       ".align 16\n" +       "2:\trep; nop\n\t" +       "cmpl $0, %0\n\t" +       "jg 1b\n\t" +       "jmp 2b\n\t" +       ".previous" +       : "=m" (*lock) +       : "m" (*lock)); + +  return 0; +} diff --git a/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S b/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S new file mode 100644 index 000000000..d94f1e7b8 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   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.  */ + +	.globl	pthread_spin_unlock +	.type	pthread_spin_unlock,@function +	.align	16 +pthread_spin_unlock: +	movl	4(%esp), %eax +	movl	$1, (%eax) +	xorl	%eax, %eax +	ret +	.size	pthread_spin_unlock,.-pthread_spin_unlock + +	/* The implementation of pthread_spin_init is identical.  */ +	.globl	pthread_spin_init +pthread_spin_init = pthread_spin_unlock diff --git a/libpthread/nptl/sysdeps/i386/pthreaddef.h b/libpthread/nptl/sysdeps/i386/pthreaddef.h new file mode 100644 index 000000000..81456a4fc --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/pthreaddef.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   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.  */ + +/* Default stack size.  */ +#define ARCH_STACK_DEFAULT_SIZE	(2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning.  SSE requires 16 +   bytes.  */ +#define STACK_ALIGN		16 + +/* Minimal stack size after allocating thread descriptor and guard size.  */ +#define MINIMAL_REST_STACK	2048 + +/* Alignment requirement for TCB.  */ +#define TCB_ALIGNMENT		16 + + +/* Location of current stack frame.  */ +#define CURRENT_STACK_FRAME	__builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here.  */ + +/* While there is no such syscall.  */ +#define __exit_thread_inline(val) \ +  while (1) {								      \ +    if (__builtin_constant_p (val) && (val) == 0)			      \ +      __asm__ volatile ("xorl %%ebx, %%ebx; int $0x80" :: "a" (__NR_exit));	      \ +    else								      \ +      __asm__ volatile ("movl %1, %%ebx; int $0x80"				      \ +		    :: "a" (__NR_exit), "r" (val));			      \ +  } diff --git a/libpthread/nptl/sysdeps/i386/tcb-offsets.sym b/libpthread/nptl/sysdeps/i386/tcb-offsets.sym new file mode 100644 index 000000000..69f9deb36 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/tcb-offsets.sym @@ -0,0 +1,17 @@ +#include <sysdep.h> +#include <tls.h> + +RESULT			offsetof (struct pthread, result) +TID			offsetof (struct pthread, tid) +PID			offsetof (struct pthread, pid) +CANCELHANDLING		offsetof (struct pthread, cancelhandling) +CLEANUP_JMP_BUF		offsetof (struct pthread, cleanup_jmp_buf) +MULTIPLE_THREADS_OFFSET	offsetof (tcbhead_t, multiple_threads) +SYSINFO_OFFSET		offsetof (tcbhead_t, sysinfo) +CLEANUP			offsetof (struct pthread, cleanup) +CLEANUP_PREV		offsetof (struct _pthread_cleanup_buffer, __prev) +MUTEX_FUTEX		offsetof (pthread_mutex_t, __data.__lock) +POINTER_GUARD		offsetof (tcbhead_t, pointer_guard) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX		offsetof (tcbhead_t, private_futex) +#endif diff --git a/libpthread/nptl/sysdeps/i386/tls.h b/libpthread/nptl/sysdeps/i386/tls.h new file mode 100644 index 000000000..5f27d8fec --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/tls.h @@ -0,0 +1,480 @@ +/* Definition for thread-local data handling.  nptl/i386 version. +   Copyright (C) 2002-2007, 2009 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.  */ + +#ifndef _TLS_H +#define _TLS_H	1 + +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> +# include <stdlib.h> +# include <list.h> +# include <sysdep.h> +# include <bits/kernel-features.h> + + +/* Type for the dtv.  */ +typedef union dtv +{ +  size_t counter; +  struct +  { +    void *val; +    bool is_static; +  } pointer; +} dtv_t; + + +typedef struct +{ +  void *tcb;		/* Pointer to the TCB.  Not necessarily the +			   thread descriptor used by libpthread.  */ +  dtv_t *dtv; +  void *self;		/* Pointer to the thread descriptor.  */ +  int multiple_threads; +  uintptr_t sysinfo; +  uintptr_t stack_guard; +  uintptr_t pointer_guard; +  int gscope_flag; +#ifndef __ASSUME_PRIVATE_FUTEX +  int private_futex; +#else +  int __unused1; +#endif +  /* Reservation of some values for the TM ABI.  */ +  void *__private_tm[5]; +} tcbhead_t; + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif + + +/* We require TLS support in the tools.  */ +#define HAVE_TLS_SUPPORT +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 + +/* Signal that TLS support is available.  */ +#define USE_TLS        1 + + +/* Alignment requirement for the stack.  For IA-32 this is governed by +   the SSE memory functions.  */ +#define STACK_ALIGN	16 + +#ifndef __ASSEMBLER__ +/* Get system call information.  */ +# include <sysdep.h> + +/* The old way: using LDT.  */ + +/* Structure passed to `modify_ldt', 'set_thread_area', and 'clone' calls.  */ +struct user_desc +{ +  unsigned int entry_number; +  unsigned long int base_addr; +  unsigned int limit; +  unsigned int seg_32bit:1; +  unsigned int contents:2; +  unsigned int read_exec_only:1; +  unsigned int limit_in_pages:1; +  unsigned int seg_not_present:1; +  unsigned int useable:1; +  unsigned int empty:25; +}; + +/* Initializing bit fields is slow.  We speed it up by using a union.  */ +union user_desc_init +{ +  struct user_desc desc; +  unsigned int vals[4]; +}; + + +/* Get the thread descriptor definition.  */ +# include <descr.h> + +/* This is the size of the initial TCB.  Can't be just sizeof (tcbhead_t), +   because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole +   struct pthread even when not linked with -lpthread.  */ +# define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the initial TCB.  */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB.  */ +# define TLS_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB.  */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TCB can have any size and the memory following the address the +   thread pointer points to is unspecified.  Allocate the TCB there.  */ +# define TLS_TCB_AT_TP	1 + + +/* Install the dtv pointer.  The pointer passed is to the element with +   index -1 which contain the length.  */ +# define INSTALL_DTV(descr, dtvp) \ +  ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread.  */ +# define INSTALL_NEW_DTV(dtvp) \ +  ({ struct pthread *__pd;						      \ +     THREAD_SETMEM (__pd, header.dtv, (dtvp)); }) + +/* Return dtv of given thread descriptor.  */ +# define GET_DTV(descr) \ +  (((tcbhead_t *) (descr))->dtv) + +#define THREAD_SELF_SYSINFO	THREAD_GETMEM (THREAD_SELF, header.sysinfo) +#define THREAD_SYSINFO(pd)	((pd)->header.sysinfo) + +/* Macros to load from and store into segment registers.  */ +# ifndef TLS_GET_GS +#  define TLS_GET_GS() \ +  ({ int __seg; __asm__ ("movw %%gs, %w0" : "=q" (__seg)); __seg & 0xffff; }) +# endif +# ifndef TLS_SET_GS +#  define TLS_SET_GS(val) \ +  __asm__ ("movw %w0, %%gs" :: "q" (val)) +# endif + + +# ifndef __NR_set_thread_area +#  define __NR_set_thread_area 243 +# endif +# ifndef TLS_FLAG_WRITABLE +#  define TLS_FLAG_WRITABLE		0x00000001 +# endif + +// XXX Enable for the real world. +#if 0 +# ifndef __ASSUME_SET_THREAD_AREA +#  error "we need set_thread_area" +# endif +#endif + +# ifdef __PIC__ +#  define TLS_EBX_ARG "r" +#  define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t" +# else +#  define TLS_EBX_ARG "b" +#  define TLS_LOAD_EBX +# endif + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ +  _head->sysinfo = GLRO(dl_sysinfo) +#else +# define INIT_SYSINFO +#endif + +#ifndef LOCK_PREFIX +# ifdef UP +#  define LOCK_PREFIX  /* nothing */ +# else +#  define LOCK_PREFIX "lock;" +# endif +#endif + +/* Code to initially initialize the thread pointer.  This might need +   special attention since 'errno' is not yet available and if the +   operation can cause a failure 'errno' must not be touched.  */ +# define TLS_INIT_TP(thrdescr, secondcall) \ +  ({ void *_thrdescr = (thrdescr);					      \ +     tcbhead_t *_head = _thrdescr;					      \ +     union user_desc_init _segdescr;					      \ +     int _result;							      \ +									      \ +     _head->tcb = _thrdescr;						      \ +     /* For now the thread descriptor is at the same address.  */	      \ +     _head->self = _thrdescr;						      \ +     /* New syscall handling support.  */				      \ +     INIT_SYSINFO;							      \ +									      \ +     /* The 'entry_number' field.  Let the kernel pick a value.  */	      \ +     if (secondcall)							      \ +       _segdescr.vals[0] = TLS_GET_GS () >> 3;				      \ +     else								      \ +       _segdescr.vals[0] = -1;						      \ +     /* The 'base_addr' field.  Pointer to the TCB.  */			      \ +     _segdescr.vals[1] = (unsigned long int) _thrdescr;			      \ +     /* The 'limit' field.  We use 4GB which is 0xfffff pages.  */	      \ +     _segdescr.vals[2] = 0xfffff;					      \ +     /* Collapsed value of the bitfield:				      \ +	  .seg_32bit = 1						      \ +	  .contents = 0							      \ +	  .read_exec_only = 0						      \ +	  .limit_in_pages = 1						      \ +	  .seg_not_present = 0						      \ +	  .useable = 1 */						      \ +     _segdescr.vals[3] = 0x51;						      \ +									      \ +     /* Install the TLS.  */						      \ +     __asm__ volatile (TLS_LOAD_EBX						  \ +		   "int $0x80\n\t"					      \ +		   TLS_LOAD_EBX						      \ +		   : "=a" (_result), "=m" (_segdescr.desc.entry_number)	      \ +		   : "0" (__NR_set_thread_area),			      \ +		     TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc));    \ +									      \ +     if (_result == 0)							      \ +       /* We know the index in the GDT, now load the segment register.	      \ +	  The use of the GDT is described by the value 3 in the lower	      \ +	  three bits of the segment descriptor value.			      \ +									      \ +	  Note that we have to do this even if the numeric value of	      \ +	  the descriptor does not change.  Loading the segment register	      \ +	  causes the segment information from the GDT to be loaded	      \ +	  which is necessary since we have changed it.   */		      \ +       TLS_SET_GS (_segdescr.desc.entry_number * 8 + 3);		      \ +									      \ +     _result == 0 ? NULL						      \ +     : "set_thread_area failed when setting up thread-local storage\n"; }) + + +/* Return the address of the dtv for the current thread.  */ +# define THREAD_DTV() \ +  ({ struct pthread *__pd;						      \ +     THREAD_GETMEM (__pd, header.dtv); }) + + +/* Return the thread descriptor for the current thread. + +   The contained asm must *not* be marked volatile since otherwise +   assignments like +        pthread_descr self = thread_self(); +   do not get optimized away.  */ +# define THREAD_SELF \ +  ({ struct pthread *__self;						      \ +     __asm__ ("movl %%gs:%c1,%0" : "=r" (__self)				    \ +	  : "i" (offsetof (struct pthread, header.self)));		      \ +     __self;}) + +/* Magic for libthread_db to know how to do THREAD_SELF.  */ +# define DB_THREAD_SELF \ +  REGISTER_THREAD_AREA (32, offsetof (struct user_regs_struct, xgs), 3) \ +  REGISTER_THREAD_AREA (64, 26 * 8, 3) /* x86-64's user_regs_struct->gs */ + + +/* Read member of the thread descriptor directly.  */ +# define THREAD_GETMEM(descr, member) \ +  ({ __typeof (descr->member) __value;					      \ +     if (sizeof (__value) == 1)						      \ +       __asm__ volatile ("movb %%gs:%P2,%b0"				    \ +		     : "=q" (__value)					      \ +		     : "0" (0), "i" (offsetof (struct pthread, member)));     \ +     else if (sizeof (__value) == 4)					      \ +       __asm__ volatile ("movl %%gs:%P1,%0"					    \ +		     : "=r" (__value)					      \ +		     : "i" (offsetof (struct pthread, member)));	      \ +     else								      \ +       {								      \ +	 if (sizeof (__value) != 8)					      \ +	   /* There should not be any value with a size other than 1,	      \ +	      4 or 8.  */						      \ +	   abort ();							      \ +									      \ +	 __asm__ volatile ("movl %%gs:%P1,%%eax\n\t"			      \ +		       "movl %%gs:%P2,%%edx"				      \ +		       : "=A" (__value)					      \ +		       : "i" (offsetof (struct pthread, member)),	      \ +			 "i" (offsetof (struct pthread, member) + 4));	      \ +       }								      \ +     __value; }) + + +/* Same as THREAD_GETMEM, but the member offset can be non-constant.  */ +# define THREAD_GETMEM_NC(descr, member, idx) \ +  ({ __typeof (descr->member[0]) __value;				      \ +     if (sizeof (__value) == 1)						      \ +       __asm__ volatile ("movb %%gs:%P2(%3),%b0"				      \ +		     : "=q" (__value)					      \ +		     : "0" (0), "i" (offsetof (struct pthread, member[0])),   \ +		     "r" (idx));					      \ +     else if (sizeof (__value) == 4)					      \ +       __asm__ volatile ("movl %%gs:%P1(,%2,4),%0"				      \ +		     : "=r" (__value)					      \ +		     : "i" (offsetof (struct pthread, member[0])),	      \ +		       "r" (idx));					      \ +     else								      \ +       {								      \ +	 if (sizeof (__value) != 8)					      \ +	   /* There should not be any value with a size other than 1,	      \ +	      4 or 8.  */						      \ +	   abort ();							      \ +									      \ +	 __asm__ volatile  ("movl %%gs:%P1(,%2,8),%%eax\n\t"		      \ +			"movl %%gs:4+%P1(,%2,8),%%edx"			      \ +			: "=&A" (__value)				      \ +			: "i" (offsetof (struct pthread, member[0])),	      \ +			  "r" (idx));					      \ +       }								      \ +     __value; }) + + +/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */ +# define THREAD_SETMEM(descr, member, value) \ +  ({ if (sizeof (descr->member) == 1)					      \ +       __asm__ volatile ("movb %b0,%%gs:%P1" :				      \ +		     : "iq" (value),					      \ +		       "i" (offsetof (struct pthread, member)));	      \ +     else if (sizeof (descr->member) == 4)				      \ +       __asm__ volatile ("movl %0,%%gs:%P1" :				      \ +		     : "ir" (value),					      \ +		       "i" (offsetof (struct pthread, member)));	      \ +     else								      \ +       {								      \ +	 if (sizeof (descr->member) != 8)				      \ +	   /* There should not be any value with a size other than 1,	      \ +	      4 or 8.  */						      \ +	   abort ();							      \ +									      \ +	 __asm__ volatile ("movl %%eax,%%gs:%P1\n\t"			      \ +		       "movl %%edx,%%gs:%P2" :				      \ +		       : "A" (value),					      \ +			 "i" (offsetof (struct pthread, member)),	      \ +			 "i" (offsetof (struct pthread, member) + 4));	      \ +       }}) + + +/* Set member of the thread descriptor directly.  */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ +  ({ if (sizeof (descr->member[0]) == 1)				      \ +       __asm__ volatile ("movb %b0,%%gs:%P1(%2)" :				      \ +		     : "iq" (value),					      \ +		       "i" (offsetof (struct pthread, member)),		      \ +		       "r" (idx));					      \ +     else if (sizeof (descr->member[0]) == 4)				      \ +       __asm__ volatile ("movl %0,%%gs:%P1(,%2,4)" :			      \ +		     : "ir" (value),					      \ +		       "i" (offsetof (struct pthread, member)),		      \ +		       "r" (idx));					      \ +     else								      \ +       {								      \ +	 if (sizeof (descr->member[0]) != 8)				      \ +	   /* There should not be any value with a size other than 1,	      \ +	      4 or 8.  */						      \ +	   abort ();							      \ +									      \ +	 __asm__ volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t"			      \ +		       "movl %%edx,%%gs:4+%P1(,%2,8)" :			      \ +		       : "A" (value),					      \ +			 "i" (offsetof (struct pthread, member)),	      \ +			 "r" (idx));					      \ +       }}) + + +/* Atomic compare and exchange on TLS, returning old value.  */ +#define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \ +  ({ __typeof (descr->member) __ret;					      \ +     __typeof (oldval) __old = (oldval);				      \ +     if (sizeof (descr->member) == 4)					      \ +       __asm__ volatile (LOCK_PREFIX "cmpxchgl %2, %%gs:%P3"		      \ +		     : "=a" (__ret)					      \ +		     : "0" (__old), "r" (newval),			      \ +		       "i" (offsetof (struct pthread, member)));	      \ +     else								      \ +       /* Not necessary for other sizes in the moment.  */		      \ +       abort ();							      \ +     __ret; }) + + +/* Atomic logical and.  */ +#define THREAD_ATOMIC_AND(descr, member, val) \ +  (void) ({ if (sizeof ((descr)->member) == 4)				      \ +	      __asm__ volatile (LOCK_PREFIX "andl %1, %%gs:%P0"		      \ +			    :: "i" (offsetof (struct pthread, member)),	      \ +			       "ir" (val));				      \ +	    else							      \ +	      /* Not necessary for other sizes in the moment.  */	      \ +	      abort (); }) + + +/* Atomic set bit.  */ +#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ +  (void) ({ if (sizeof ((descr)->member) == 4)				      \ +	      __asm__ volatile (LOCK_PREFIX "orl %1, %%gs:%P0"		      \ +			    :: "i" (offsetof (struct pthread, member)),	      \ +			       "ir" (1 << (bit)));			      \ +	    else							      \ +	      /* Not necessary for other sizes in the moment.  */	      \ +	      abort (); }) + + +/* Call the user-provided thread function.  */ +#define CALL_THREAD_FCT(descr) \ +  ({ void *__res;							      \ +     int __ignore1, __ignore2;						      \ +     __asm__ volatile ("pushl %%eax\n\t"					      \ +		   "pushl %%eax\n\t"					      \ +		   "pushl %%eax\n\t"					      \ +		   "pushl %%gs:%P4\n\t"					      \ +		   "call *%%gs:%P3\n\t"					      \ +		   "addl $16, %%esp"					      \ +		   : "=a" (__res), "=c" (__ignore1), "=d" (__ignore2)	      \ +		   : "i" (offsetof (struct pthread, start_routine)),	      \ +		     "i" (offsetof (struct pthread, arg)));		      \ +     __res; }) + + +/* Set the stack guard field in TCB head.  */ +#define THREAD_SET_STACK_GUARD(value) \ +  THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +#define THREAD_COPY_STACK_GUARD(descr) \ +  ((descr)->header.stack_guard						      \ +   = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + + +/* Set the pointer guard field in the TCB head.  */ +#define THREAD_SET_POINTER_GUARD(value) \ +  THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value) +#define THREAD_COPY_POINTER_GUARD(descr) \ +  ((descr)->header.pointer_guard					      \ +   = THREAD_GETMEM (THREAD_SELF, header.pointer_guard)) + + +/* Get and set the global scope generation counter in the TCB head.  */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED   1 +#define THREAD_GSCOPE_FLAG_WAIT   2 +#define THREAD_GSCOPE_RESET_FLAG() \ +  do									      \ +    { int __res;							      \ +      __asm__ volatile ("xchgl %0, %%gs:%P1"				      \ +		    : "=r" (__res)					      \ +		    : "i" (offsetof (struct pthread, header.gscope_flag)),    \ +		      "0" (THREAD_GSCOPE_FLAG_UNUSED));			      \ +      if (__res == THREAD_GSCOPE_FLAG_WAIT)				      \ +	lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE);    \ +    }									      \ +  while (0) +#define THREAD_GSCOPE_SET_FLAG() \ +  THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED) +#define THREAD_GSCOPE_WAIT() \ +  GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ + +#endif	/* tls.h */ | 
