diff options
Diffstat (limited to 'libpthread/nptl/sysdeps/unix')
347 files changed, 27007 insertions, 0 deletions
diff --git a/libpthread/nptl/sysdeps/unix/sh/sysdep.h b/libpthread/nptl/sysdeps/unix/sh/sysdep.h new file mode 100644 index 000000000..bf1ac0fd4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sh/sysdep.h @@ -0,0 +1,29 @@ +/* Copyright (C) 1999, 2000 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 <sysdeps/unix/sysdep.h> +#include <sysdeps/sh/sysdep.h> + +#ifdef __ASSEMBLER__ + +#define ret	rts ; nop + +/* The sh move insn is s, d.  */ +#define MOVE(x,y)	mov x , y + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysdep.h b/libpthread/nptl/sysdeps/unix/sysdep.h new file mode 100644 index 000000000..0e7c9da5a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysdep.h @@ -0,0 +1,63 @@ +/* Copyright (C) 1991, 92, 93, 96, 98, 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 <sysdeps/generic/sysdep.h> + +#include <sys/syscall.h> +#define	HAVE_SYSCALLS + +/* Note that using a `PASTE' macro loses.  */ +#ifdef	__STDC__ +#define	SYSCALL__(name, args)	PSEUDO (__##name, name, args) +#else +#define	SYSCALL__(name, args)	PSEUDO (__/**/name, name, args) +#endif +#define	SYSCALL(name, args)	PSEUDO (name, name, args) + +/* Machine-dependent sysdep.h files are expected to define the macro +   PSEUDO (function_name, syscall_name) to emit assembly code to define the +   C-callable function FUNCTION_NAME to do system call SYSCALL_NAME. +   r0 and r1 are the system call outputs.  MOVE(x, y) should be defined as +   an instruction such that "MOVE(r1, r0)" works.  ret should be defined +   as the return instruction.  */ + +#ifndef SYS_ify +#ifdef __STDC__ +#define SYS_ify(syscall_name) SYS_##syscall_name +#else +#define SYS_ify(syscall_name) SYS_/**/syscall_name +#endif +#endif + +/* Terminate a system call named SYM.  This is used on some platforms +   to generate correct debugging information.  */ +#ifndef PSEUDO_END +#define PSEUDO_END(sym) +#endif +#ifndef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(sym)	PSEUDO_END(sym) +#endif +#ifndef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(sym)	PSEUDO_END(sym) +#endif + +/* Wrappers around system calls should normally inline the system call code. +   But sometimes it is not possible or implemented and we use this code.  */ +#ifndef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) __syscall_##name (args) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile new file mode 100644 index 000000000..34d647527 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile @@ -0,0 +1,13 @@ +# 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. +# + +top_srcdir=../../../../../../ +top_builddir=../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.in b/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.in new file mode 100644 index 000000000..186fefbea --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.in @@ -0,0 +1,208 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_CSRC = pthread_attr_getaffinity.c			\ +		  pthread_attr_setaffinity.c pthread_getaffinity.c	\ +		  pthread_getcpuclockid.c pthread_kill.c		\ +		  pthread_mutex_cond_lock.c pthread_setaffinity.c	\ +		  pthread_yield.c sem_post.c sem_timedwait.c		\ +		  sem_trywait.c sem_wait.c pt-fork.c			\ +		  sigtimedwait.c sigwaitinfo.c sigwait.c pt-sleep.c + +libpthread_SSRC = #ptw-close.S ptw-open.S ptw-waitid.S ptw-waidpid.S ptw-write.S + +libc_CSRC = libc_pthread_init.c libc_multiple_threads.c			\ +	    register-atfork.c unregister-atfork.c getpid.c		\ +	    raise.c sleep.c jmp-unwind.c + +# These provide both a cancellable and a not cancellable implementation +libc_SSRC = close.S open.S write.S read.S + +ifneq ($(TARGET_ARCH),arm) +libc_SSRC += waitpid.S +endif + +librt_CSRC := mq_notify.c timer_create.c timer_delete.c			 \ +	      timer_getoverr.c timer_gettime.c timer_routines.c		 \ +	      timer_settime.c + + +ifeq ($(TARGET_ARCH),alpha) +libpthread_CSRC += lowlevellock.c +libc_CSRC += libc-lowlevellock.c +librt_CSRC := mq_notify.c +endif + +ifeq ($(TARGET_ARCH),mips) +libpthread_CSRC += lowlevellock.c +libc_CSRC += libc-lowlevellock.c +endif + +ifeq ($(TARGET_ARCH),powerpc) +libpthread_CSRC += lowlevellock.c +libc_CSRC += libc-lowlevellock.c +librt_CSRC := mq_notify.c +endif + +ifeq ($(TARGET_ARCH),sparc) +libpthread_CSRC += __syscall_error.c +librt_CSRC := mq_notify.c __syscall_error.c +endif + +ifeq ($(TARGET_ARCH),sh) +SH_PTHREAD_SPECIFIC := sem_post.c sem_wait.c sem_timedwait.c sem_trywait.c +libpthread_CSRC := $(filter-out $(SH_PTHREAD_SPECIFIC),$(libpthread_CSRC)) +endif + +ifeq ($(TARGET_ARCH),i386) +X86_PTHREAD_SPECIFIC := sem_post.c sem_wait.c sem_timedwait.c sem_trywait.c +libpthread_CSRC := $(filter-out $(X86_PTHREAD_SPECIFIC),$(libpthread_CSRC)) +endif + +ifeq ($(TARGET_ARCH),x86_64) +X86_PTHREAD_SPECIFIC := sem_post.c sem_wait.c sem_timedwait.c sem_trywait.c +libpthread_CSRC := $(filter-out $(X86_PTHREAD_SPECIFIC),$(libpthread_CSRC)) +librt_CSRC := mq_notify.c +endif + +CFLAGS-pthread_getcpuclockid.c = -I$(top_srcdir)librt +CFLAGS-pt-pread_pwrite.c = -I$(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH) \ +			    -I$(top_srcdir)libc/sysdeps/linux/common +CFLAGS-mq_notify.c = -I$(top_srcdir)librt -DIS_IN_librt=1 +CFLAGS-timer_create.c = -I$(top_srcdir)librt -DIS_IN_librt=1 +CFLAGS-timer_delete.c = -I$(top_srcdir)librt -DIS_IN_librt=1 +CFLAGS-timer_getoverr.c = -I$(top_srcdir)librt -DIS_IN_librt=1 +CFLAGS-timer_gettime.c = -I$(top_srcdir)librt -DIS_IN_librt=1 +CFLAGS-timer_routines.c = -I$(top_srcdir)librt -DIS_IN_librt=1 +CFLAGS-timer_settime.c = -I$(top_srcdir)librt -DIS_IN_librt=1 + +CFLAGS-linux = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +CFLAGS-OMIT-libc_pthread_init.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-libc_multiple_threads.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-register-atfork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-unregister-atfork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-getpid.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-raise.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-sleep.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-libc-lowlevellock.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +CFLAGS-OMIT-close.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-open.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-read.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-write.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-waitpid.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +CFLAGS-OMIT-mq_notify.c = -DIS_IN_libpthread=1 +CFLAGS-OMIT-timer_create.c = -DIS_IN_libpthread=1 +CFLAGS-OMIT-timer_delete.c = -DIS_IN_libpthread=1 +CFLAGS-OMIT-timer_getoverr.c = -DIS_IN_libpthread=1 +CFLAGS-OMIT-timer_gettime.c = -DIS_IN_libpthread=1 +CFLAGS-OMIT-timer_routines.c = -DIS_IN_libpthread=1 +CFLAGS-OMIT-timer_settime.c = -DIS_IN_libpthread=1 + +PTHREAD_LINUX_DIR := $(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux +PTHREAD_LINUX_OUT := $(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux + +PTHREAD_LINUX_OBJ := $(patsubst %.c,$(PTHREAD_LINUX_OUT)/%.o,$(libpthread_CSRC)) +PTHREAD_LINUX_OBJ += $(patsubst %.S,$(PTHREAD_LINUX_OUT)/%.o,$(libpthread_SSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(PTHREAD_LINUX_OBJ:.o=.os) +else +libpthread-a-y += $(PTHREAD_LINUX_OBJ) +endif +libpthread-so-y += $(PTHREAD_LINUX_OBJ:.o=.oS) +libpthread-so-y += $(PTHREAD_LINUX_OUT)/pt-raise.oS +libpthread-nomulti-y += $(PTHREAD_LINUX_OBJ) + +ASFLAGS-open.S = -D_LIBC_REENTRANT +ASFLAGS-close.S = -D_LIBC_REENTRANT +ASFLAGS-read.S = -D_LIBC_REENTRANT +ASFLAGS-write.S = -D_LIBC_REENTRANT +ASFLAGS-waitpid.S = -D_LIBC_REENTRANT + +LIBC_LINUX_OBJ := $(patsubst %.c,$(PTHREAD_LINUX_OUT)/%.o,$(libc_CSRC)) +LIBC_LINUX_OBJ += $(patsubst %.S,$(PTHREAD_LINUX_OUT)/%.o,$(libc_SSRC)) + +libc-static-y += $(LIBC_LINUX_OBJ) +libc-shared-y += $(LIBC_LINUX_OBJ:.o=.oS) +libc-nomulti-y += $(LIBC_LINUX_OBJ) + +LIBRT_LINUX_OBJ := $(patsubst %.c,$(PTHREAD_LINUX_OUT)/%.o,$(librt_CSRC)) + +librt-a-y += $(LIBRT_LINUX_OBJ) +librt-so-y += $(LIBRT_LINUX_OBJ:.o=.oS) + +objclean-y += nptl_linux_clean +headers_clean-y += nptl_linux_headers_clean + +# +# Create header files. +# +CFLAGS-lowlevelbarrier.c = -S +CFLAGS-lowlevelcond.c = -S +CFLAGS-lowlevelrwlock.c = -S +CFLAGS-unwindbuf.c = -S + +$(PTHREAD_LINUX_OUT)/lowlevelbarrier.c: $(PTHREAD_LINUX_DIR)/lowlevelbarrier.sym +	$(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_LINUX_OUT)/lowlevelcond.c: $(PTHREAD_LINUX_DIR)/lowlevelcond.sym +	$(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_LINUX_OUT)/lowlevelrwlock.c: $(PTHREAD_LINUX_DIR)/lowlevelrwlock.sym +	$(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_LINUX_OUT)/unwindbuf.c: $(PTHREAD_LINUX_DIR)/unwindbuf.sym +	$(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_LINUX_OUT)/lowlevelbarrier.s: $(PTHREAD_LINUX_OUT)/lowlevelbarrier.c +	$(compile.c) + +$(PTHREAD_LINUX_OUT)/lowlevelcond.s: $(PTHREAD_LINUX_OUT)/lowlevelcond.c +	$(compile.c) + +$(PTHREAD_LINUX_OUT)/lowlevelrwlock.s: $(PTHREAD_LINUX_OUT)/lowlevelrwlock.c +	$(compile.c) + +$(PTHREAD_LINUX_OUT)/unwindbuf.s: $(PTHREAD_LINUX_OUT)/unwindbuf.c +	$(compile.c) + +$(PTHREAD_LINUX_OUT)/lowlevelbarrier.h: $(PTHREAD_LINUX_OUT)/lowlevelbarrier.s +	$(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +$(PTHREAD_LINUX_OUT)/lowlevelcond.h: $(PTHREAD_LINUX_OUT)/lowlevelcond.s +	$(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +$(PTHREAD_LINUX_OUT)/lowlevelrwlock.h: $(PTHREAD_LINUX_OUT)/lowlevelrwlock.s +	$(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +$(PTHREAD_LINUX_OUT)/unwindbuf.h: $(PTHREAD_LINUX_OUT)/unwindbuf.s +	$(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +nptl_linux_headers: $(PTHREAD_LINUX_OUT)/lowlevelbarrier.h \ +					$(PTHREAD_LINUX_OUT)/lowlevelcond.h \ +					$(PTHREAD_LINUX_OUT)/lowlevelrwlock.h \ +					$(PTHREAD_LINUX_OUT)/unwindbuf.h + +HEADERS_BITS_PTHREAD     := $(notdir $(wildcard $(PTHREAD_LINUX_DIR)/bits/*.h)) +ALL_HEADERS_BITS_PTHREAD := $(addprefix include/bits/,$(HEADERS_BITS_PTHREAD)) + +$(ALL_HEADERS_BITS_PTHREAD): +	$(do_ln) ../../$(PTHREAD_LINUX_DIR)/bits/$(@F) $(top_builddir)$@ + +nptl_linux_headers_clean: +	$(do_rm) $(addprefix $(PTHREAD_LINUX_OUT)/lowlevelbarrier., c h s) \ +	$(addprefix $(PTHREAD_LINUX_OUT)/lowlevelcond., c h s) \ +	$(addprefix $(PTHREAD_LINUX_OUT)/lowlevelrwlock., c h s) \ +	$(addprefix $(PTHREAD_LINUX_OUT)/unwindbuf., c h s) + + +nptl_linux_clean: +	$(do_rm) $(addprefix $(PTHREAD_LINUX_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c b/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c new file mode 100644 index 000000000..5e109a83b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <errno.h> +#include <features.h> + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno.  */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ +	__set_errno(err_no); +	return -1; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/accept.S b/libpthread/nptl/sysdeps/unix/sysv/linux/accept.S new file mode 100644 index 000000000..529763d80 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/accept.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_accept +#error Missing definition of NR_accept needed for cancellation. +#endif +PSEUDO (__libc_accept, accept, 3) +ret +PSEUDO_END(__libc_accept) +libc_hidden_def (__libc_accept) +weak_alias (__libc_accept, __accept) +libc_hidden_weak (__accept) +weak_alias (__libc_accept, accept) +libc_hidden_weak (accept) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile new file mode 100644 index 000000000..8c8084079 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile @@ -0,0 +1,2 @@ +# pull in __syscall_error routine, __sigprocmask, __syscall_rt_sigaction +libpthread-routines += ptw-sysdep ptw-sigprocmask ptw-rt_sigaction diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Versions b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Versions new file mode 100644 index 000000000..437c4da28 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Versions @@ -0,0 +1,13 @@ +libpthread { +  GLIBC_2.3.3 { +    # Changed PTHREAD_STACK_MIN. +    pthread_attr_setstack; pthread_attr_setstacksize; +  } +} +librt { +  GLIBC_2.3.3 { +    # Changed timer_t. +    timer_create; timer_delete; timer_getoverrun; timer_gettime; +    timer_settime; +  } +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h new file mode 100644 index 000000000..e0718780c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h @@ -0,0 +1,89 @@ +/* Minimum guaranteed maximum values for system limits.  Linux/Alpha version. +   Copyright (C) 1993-1998,2000,2002,2003,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 Library General Public License as +   published by the Free Software Foundation; either version 2 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 +   Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public +   License along with the GNU C Library; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol +   and defines LINK_MAX although filesystems have different maxima.  A +   similar thing is true for OPEN_MAX: the limit can be changed at +   runtime and therefore the macro must not be defined.  Remove this +   after including the header if necessary.  */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information.  */ +#include <linux/limits.h> + +/* Have to remove NR_OPEN?  */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX?  */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX?  */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process.  */ +#define _POSIX_THREAD_KEYS_MAX	128 +/* This is the value this implementation supports.  */ +#define PTHREAD_KEYS_MAX	1024 + +/* Controlling the iterations of destructors for thread-specific data.  */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS	4 +/* Number of iterations this implementation does.  */ +#define PTHREAD_DESTRUCTOR_ITERATIONS	_POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process.  */ +#define _POSIX_THREAD_THREADS_MAX	64 +/* We have no predefined limit on the number of threads.  */ +#undef PTHREAD_THREADS_MAX + +/* Maximum amount by which a process can descrease its asynchronous I/O +   priority level.  */ +#define AIO_PRIO_DELTA_MAX	20 + +/* Minimum size for a thread.  We are free to choose a reasonable value.  */ +#define PTHREAD_STACK_MIN	24576 + +/* Maximum number of timer expiration overruns.  */ +#define DELAYTIMER_MAX	2147483647 + +/* Maximum tty name length.  */ +#define TTY_NAME_MAX		32 + +/* Maximum login name length.  This is arbitrary.  */ +#define LOGIN_NAME_MAX		256 + +/* Maximum host name length.  */ +#define HOST_NAME_MAX		64 + +/* Maximum message queue priority level.  */ +#define MQ_PRIO_MAX		32768 diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h new file mode 100644 index 000000000..0f3bf838e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h @@ -0,0 +1,168 @@ +/* Machine-specific pthread type layouts.  Alpha version. +   Copyright (C) 2003, 2004, 2005 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 _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H	1 + +#define __SIZEOF_PTHREAD_ATTR_T		56 +#define __SIZEOF_PTHREAD_MUTEX_T	40 +#define __SIZEOF_PTHREAD_MUTEXATTR_T	4 +#define __SIZEOF_PTHREAD_COND_T		48 +#define __SIZEOF_PTHREAD_CONDATTR_T	4 +#define __SIZEOF_PTHREAD_RWLOCK_T	56 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T	8 +#define __SIZEOF_PTHREAD_BARRIER_T	32 +#define __SIZEOF_PTHREAD_BARRIERATTR_T	4 + + +/* Thread identifiers.  The structure of the attribute type is +   deliberately not exposed.  */ +typedef unsigned long int pthread_t; + + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_ATTR_T]; +  long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_list +{ +  struct __pthread_internal_list *__prev; +  struct __pthread_internal_list *__next; +} __pthread_list_t; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is deliberately not exposed.  */ +typedef union +{ +  struct __pthread_mutex_s +  { +    int __lock; +    unsigned int __count; +    int __owner; +    unsigned int __nusers; +    /* KIND must stay at this position in the structure to maintain +       binary compatibility.  */ +    int __kind; +    int __spins; +    __pthread_list_t __list; +#define __PTHREAD_MUTEX_HAVE_PREV       1 +  } __data; +  char __size[__SIZEOF_PTHREAD_MUTEX_T]; +  long int __align; +} pthread_mutex_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; +  int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling.  The structure of +   the attribute type is deliberately not exposed.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __futex; +    __extension__ unsigned long long int __total_seq; +    __extension__ unsigned long long int __wakeup_seq; +    __extension__ unsigned long long int __woken_seq; +    void *__mutex; +    unsigned int __nwaiters; +    unsigned int __broadcast_seq; +  } __data; +  char __size[__SIZEOF_PTHREAD_COND_T]; +  __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_CONDATTR_T]; +  int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling.  The +   structure of the attribute type is deliberately not exposed.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    int __writer; +    int __pad1; +    unsigned long int __pad2; +    unsigned long int __pad3; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +  } __data; +  char __size[__SIZEOF_PTHREAD_RWLOCK_T]; +  long int __align; +} pthread_rwlock_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; +  long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type.  */ +typedef volatile int pthread_spinlock_t; + +/* POSIX barriers data type.  The structure of the type is +   deliberately not exposed.  */ +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIER_T]; +  long int __align; +} pthread_barrier_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; +  int __align; +} pthread_barrierattr_t; +#endif + + +#endif	/* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h new file mode 100644 index 000000000..6dadfda20 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h @@ -0,0 +1,37 @@ +/* Machine-specific POSIX semaphore type layouts.  Alpha version. +   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.  */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +# define __SIZEOF_SEM_T	32 + +/* Value returned if `sem_open' failed.  */ +#define SEM_FAILED      ((sem_t *) 0) + +/* Maximum value the semaphore can have.  */ +#define SEM_VALUE_MAX   (2147483647) + + +typedef union +{ +  char __size[__SIZEOF_SEM_T]; +  long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S new file mode 100644 index 000000000..eea1cbeed --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/linux/alpha/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c new file mode 100644 index 000000000..6a51e73da --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c @@ -0,0 +1,23 @@ +/* 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.  */ + +/* Value passed to 'clone' for initialization of the thread register.  */ +#define TLS_VALUE (pd + 1) + +/* Get the real implementation.	 */ +#include <nptl/sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c new file mode 100644 index 000000000..ca85fc008 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c @@ -0,0 +1,30 @@ +/* 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 <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + + +#define ARCH_FORK()							\ +  INLINE_SYSCALL (clone, 5,						\ +		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,	\ +		  NULL, NULL, &THREAD_SELF->tid, NULL) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h new file mode 100644 index 000000000..fd4a7ca4b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h @@ -0,0 +1,217 @@ +/* Copyright (C) 2003, 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 Libr	\ary; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H	1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> +#include <sysdep.h> + + +#define __NR_futex		394 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 +#define FUTEX_CMP_REQUEUE	4 + +/* Initializer for compatibility lock.	*/ +#define LLL_MUTEX_LOCK_INITIALIZER (0) + +#define lll_futex_wait(futexp, val) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAIT, (val), 0);		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret;		      \ +  }) + +#define lll_futex_timed_wait(futexp, val, timespec) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAIT, (val), (timespec));	      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret;		      \ +  }) + +#define lll_futex_wake(futexp, nr) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAKE, (nr), 0);		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret;		      \ +  }) + +/* Returns non-zero if error happened, zero if success.  */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 6,				      \ +			      (futexp), FUTEX_CMP_REQUEUE, (nr_wake),	      \ +			      (nr_move), (mutex), (val));		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \ +  }) + + +static inline int __attribute__((always_inline)) +__lll_mutex_trylock(int *futex) +{ +  return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0; +} +#define lll_mutex_trylock(lock)	__lll_mutex_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_mutex_cond_trylock(int *futex) +{ +  return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0; +} +#define lll_mutex_cond_trylock(lock)	__lll_mutex_cond_trylock (&(lock)) + + +extern void __lll_lock_wait (int *futex) attribute_hidden; + +static inline void __attribute__((always_inline)) +__lll_mutex_lock(int *futex) +{ +  if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) +    __lll_lock_wait (futex); +} +#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex)) + + +static inline void __attribute__ ((always_inline)) +__lll_mutex_cond_lock (int *futex) +{ +  if (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0) +    __lll_lock_wait (futex); +} +#define lll_mutex_cond_lock(futex) __lll_mutex_cond_lock (&(futex)) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *) +	attribute_hidden; + +static inline int __attribute__ ((always_inline)) +__lll_mutex_timedlock (int *futex, const struct timespec *abstime) +{ +  int result = 0; +  if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) +    result = __lll_timedlock_wait (futex, abstime); +  return result; +} +#define lll_mutex_timedlock(futex, abstime) \ +  __lll_mutex_timedlock (&(futex), abstime) + + +static inline void __attribute__ ((always_inline)) +__lll_mutex_unlock (int *futex) +{ +  int val = atomic_exchange_rel (futex, 0); +  if (__builtin_expect (val > 1, 0)) +    lll_futex_wake (futex, 1); +} +#define lll_mutex_unlock(futex) __lll_mutex_unlock(&(futex)) + + +static inline void __attribute__ ((always_inline)) +__lll_mutex_unlock_force (int *futex) +{ +  (void) atomic_exchange_rel (futex, 0); +  lll_futex_wake (futex, 1); +} +#define lll_mutex_unlock_force(futex) __lll_mutex_unlock_force(&(futex)) + + +#define lll_mutex_islocked(futex) \ +  (futex != 0) + + +/* Our internal lock implementation is identical to the binary-compatible +   mutex implementation. */ + +/* Type for lock object.  */ +typedef int lll_lock_t; + +/* Initializers for lock.  */ +#define LLL_LOCK_INITIALIZER		(0) +#define LLL_LOCK_INITIALIZER_LOCKED	(1) + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + +/* The states of a lock are: +    0  -  untaken +    1  -  taken by one user +   >1  -  taken by more users */ + +#define lll_trylock(lock)	lll_mutex_trylock (lock) +#define lll_lock(lock)		lll_mutex_lock (lock) +#define lll_unlock(lock)	lll_mutex_unlock (lock) +#define lll_islocked(lock)	lll_mutex_islocked (lock) + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex +   wakeup when the clone terminates.  The memory location contains the +   thread ID while the clone is running and is reset to zero +   afterwards.	*/ +#define lll_wait_tid(tid) \ +  do {					\ +    __typeof (tid) __tid;		\ +    while ((__tid = (tid)) != 0)	\ +      lll_futex_wait (&(tid), __tid);	\ +  } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) +     attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ +  ({							\ +    int __res = 0;					\ +    if ((tid) != 0)					\ +      __res = __lll_timedwait_tid (&(tid), (abstime));	\ +    __res;						\ +  }) + + +/* Conditional variable handling.  */ + +extern void __lll_cond_wait (pthread_cond_t *cond) +     attribute_hidden; +extern int __lll_cond_timedwait (pthread_cond_t *cond, +				 const struct timespec *abstime) +     attribute_hidden; +extern void __lll_cond_wake (pthread_cond_t *cond) +     attribute_hidden; +extern void __lll_cond_broadcast (pthread_cond_t *cond) +     attribute_hidden; + +#define lll_cond_wait(cond) \ +  __lll_cond_wait (cond) +#define lll_cond_timedwait(cond, abstime) \ +  __lll_cond_timedwait (cond, abstime) +#define lll_cond_wake(cond) \ +  __lll_cond_wake (cond) +#define lll_cond_broadcast(cond) \ +  __lll_cond_broadcast (cond) + +#endif	/* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S new file mode 100644 index 000000000..ec5d175be --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S @@ -0,0 +1,43 @@ +/* Copyright (C) 2003, 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.  */ + +#include <sysdep.h> +#include <tcb-offsets.h> + +#undef PSEUDO_PREPARE_ARGS +#define PSEUDO_PREPARE_ARGS						\ +	/* Load the current cached pid value across the vfork.  */	\ +	rduniq;								\ +	ldl	a2, PID_OFFSET(v0);					\ +	mov	v0, a1;							\ +	/* Write back its negation, to indicate that the pid value is	\ +	   uninitialized in the the child, and in the window between	\ +	   here and the point at which we restore the value.  */	\ +	negl	a2, t0;							\ +	stl	t0, PID_OFFSET(v0); + +PSEUDO (__vfork, vfork, 0) + +	/* If we're back in the parent, restore the saved pid.  */ +	beq	v0, 1f +	stl	a2, PID_OFFSET(a1) +1:	ret + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c new file mode 100644 index 000000000..79a3c47ae --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c @@ -0,0 +1,96 @@ +/* Copyright (C) 2003, 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.  */ + +#include "pthreadP.h" +#include <lowlevellock.h> + + +unsigned long int __fork_generation attribute_hidden; + +static void +clear_once_control (void *arg) +{ +  pthread_once_t *once_control = (pthread_once_t *) arg; + +  *once_control = 0; +  lll_futex_wake (once_control, INT_MAX); +} + +int +__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ +  for (;;) +    { +      int oldval; +      int newval; +      int tmp; + +      /* Pseudo code: +	 newval = __fork_generation | 1; +	 oldval = *once_control; +	 if ((oldval & 2) == 0) +	   *once_control = newval; +	 Do this atomically. +      */ +      newval = __fork_generation | 1; +      __asm __volatile ( +		"1:	ldl_l	%0, %2\n" +		"	and	%0, 2, %1\n" +		"	bne	%1, 2f\n" +		"	mov	%3, %1\n" +		"	stl_c	%1, %2\n" +		"	beq	%1, 1b\n" +		"2:	mb" +		: "=&r" (oldval), "=&r" (tmp), "=m" (*once_control) +		: "r" (newval), "m" (*once_control)); + +      /* Check if the initializer has already been done.  */ +      if ((oldval & 2) != 0) +	return 0; + +      /* Check if another thread already runs the initializer.	*/ +      if ((oldval & 1) == 0) +	break; + +      /* Check whether the initializer execution was interrupted by a fork.  */ +      if (oldval != newval) +	break; + +      /* Same generation, some other thread was faster. Wait.  */ +      lll_futex_wait (once_control, oldval); +    } + +  /* This thread is the first here.  Do the initialization. +     Register a cleanup handler so that in case the thread gets +     interrupted the initialization can be restarted.  */ +  pthread_cleanup_push (clear_once_control, once_control); + +  init_routine (); + +  pthread_cleanup_pop (0); + +  /* Add one to *once_control to take the bottom 2 bits from 01 to 10.  */ +  atomic_increment (once_control); + +  /* Wake up all other threads.  */ +  lll_futex_wake (once_control, INT_MAX); + +  return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c new file mode 100644 index 000000000..27fd817e6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c @@ -0,0 +1,5 @@ +/* ??? This is an ass-backwards way to do this.  We should simply define +   the acquire/release semantics of atomic_exchange_and_add.  And even if +   we don't do this, we should be using atomic_full_barrier or otherwise.  */ +#define __lll_rel_instr  "mb" +#include "../sem_post.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h new file mode 100644 index 000000000..f3f7718e3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h @@ -0,0 +1,169 @@ +/* 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 <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <nptl/pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifdef PROF +#  define PSEUDO_PROF				\ +	.set noat;				\ +	lda	AT, _mcount;			\ +	jsr	AT, (AT), _mcount;		\ +	.set at +# else +#  define PSEUDO_PROF +# endif + +/* ??? Assumes that nothing comes between PSEUDO and PSEUDO_END +   besides "ret".  */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args)			\ +	.globl name;						\ +	.align 4;						\ +	.type name, @function;					\ +	.usepv name, std;					\ +	cfi_startproc;						\ +__LABEL(name)							\ +	ldgp	gp, 0(pv);					\ +	PSEUDO_PROF;						\ +	PSEUDO_PREPARE_ARGS					\ +	SINGLE_THREAD_P(t0);					\ +	bne	t0, $pseudo_cancel;				\ +	lda	v0, SYS_ify(syscall_name);			\ +	call_pal PAL_callsys;					\ +	bne	a3, SYSCALL_ERROR_LABEL;			\ +__LABEL($pseudo_ret)						\ +	.subsection 2;						\ +__LABEL($pseudo_cancel)						\ +	subq	sp, 64, sp;					\ +	cfi_def_cfa_offset(64);					\ +	stq	ra, 0(sp);					\ +	cfi_offset(ra, -64);					\ +	SAVE_ARGS_##args;					\ +	CENABLE;						\ +	LOAD_ARGS_##args;					\ +	/* Save the CENABLE return value in RA.  That register	\ +	   is preserved across syscall and the real return 	\ +	   address is saved on the stack.  */			\ +	mov	v0, ra;						\ +	lda	v0, SYS_ify(syscall_name);			\ +	call_pal PAL_callsys;					\ +	stq	v0, 8(sp);					\ +	mov	ra, a0;						\ +	bne	a3, $multi_error;				\ +	CDISABLE;						\ +	ldq	ra, 0(sp);					\ +	ldq	v0, 8(sp);					\ +	addq	sp, 64, sp;					\ +	cfi_remember_state;					\ +	cfi_restore(ra);					\ +	cfi_def_cfa_offset(0);					\ +	ret;							\ +	cfi_restore_state;					\ +__LABEL($multi_error)						\ +	CDISABLE;						\ +	ldq	ra, 0(sp);					\ +	ldq	v0, 8(sp);					\ +	addq	sp, 64, sp;					\ +	cfi_restore(ra);					\ +	cfi_def_cfa_offset(0);					\ +__LABEL($syscall_error)						\ +	SYSCALL_ERROR_HANDLER;					\ +	.previous + +# undef PSEUDO_END +# define PSEUDO_END(sym)					\ +	.subsection 2;						\ +	cfi_endproc;						\ +	.size sym, .-sym + +# define SAVE_ARGS_0	/* Nothing.  */ +# define SAVE_ARGS_1	SAVE_ARGS_0; stq a0, 8(sp) +# define SAVE_ARGS_2	SAVE_ARGS_1; stq a1, 16(sp) +# define SAVE_ARGS_3	SAVE_ARGS_2; stq a2, 24(sp) +# define SAVE_ARGS_4	SAVE_ARGS_3; stq a3, 32(sp) +# define SAVE_ARGS_5	SAVE_ARGS_4; stq a4, 40(sp) +# define SAVE_ARGS_6	SAVE_ARGS_5; stq a5, 48(sp) + +# define LOAD_ARGS_0	/* Nothing.  */ +# define LOAD_ARGS_1	LOAD_ARGS_0; ldq a0, 8(sp) +# define LOAD_ARGS_2	LOAD_ARGS_1; ldq a1, 16(sp) +# define LOAD_ARGS_3	LOAD_ARGS_2; ldq a2, 24(sp) +# define LOAD_ARGS_4	LOAD_ARGS_3; ldq a3, 32(sp) +# define LOAD_ARGS_5	LOAD_ARGS_4; ldq a4, 40(sp) +# define LOAD_ARGS_6	LOAD_ARGS_5; ldq a5, 48(sp) + +# ifdef IS_IN_libpthread +#  define __local_enable_asynccancel	__pthread_enable_asynccancel +#  define __local_disable_asynccancel	__pthread_disable_asynccancel +#  define __local_multiple_threads	__pthread_multiple_threads +# elif !defined NOT_IN_libc +#  define __local_enable_asynccancel	__libc_enable_asynccancel +#  define __local_disable_asynccancel	__libc_disable_asynccancel +#  define __local_multiple_threads	__libc_multiple_threads +# elif defined IS_IN_librt +#  define __local_enable_asynccancel	__librt_enable_asynccancel +#  define __local_disable_asynccancel	__librt_disable_asynccancel +# else +#  error Unsupported library +# endif + +# ifdef PIC +#  define CENABLE	bsr ra, __local_enable_asynccancel !samegp +#  define CDISABLE	bsr ra, __local_disable_asynccancel !samegp +# else +#  define CENABLE	jsr ra, __local_enable_asynccancel; ldgp ra, 0(gp) +#  define CDISABLE	jsr ra, __local_disable_asynccancel; ldgp ra, 0(gp) +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +#  ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +#   define SINGLE_THREAD_P \ +	__builtin_expect (__local_multiple_threads == 0, 1) +#  elif defined(PIC) +#   define SINGLE_THREAD_P(reg)  ldl reg, __local_multiple_threads(gp) !gprel +#  else +#   define SINGLE_THREAD_P(reg)					\ +	ldah	reg, __local_multiple_threads(gp) !gprelhigh;	\ +	ldl	reg, __local_multiple_threads(reg) !gprellow +#  endif +# else +#  ifndef __ASSEMBLER__ +#   define SINGLE_THREAD_P \ +	__builtin_expect (THREAD_GETMEM (THREAD_SELF, \ +				   header.multiple_threads) == 0, 1) +#  else +#   define SINGLE_THREAD_P(reg)					\ +	call_pal PAL_rduniq;					\ +	ldl reg, MULTIPLE_THREADS_OFFSET($0) +#  endif +# endif + +#else + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c new file mode 100644 index 000000000..172223af3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c @@ -0,0 +1 @@ +#include "../x86_64/timer_create.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c new file mode 100644 index 000000000..537516e0a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c @@ -0,0 +1 @@ +#include "../x86_64/timer_delete.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c new file mode 100644 index 000000000..3f21a73c9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c @@ -0,0 +1 @@ +#include "../x86_64/timer_getoverr.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c new file mode 100644 index 000000000..a50143adc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_gettime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c new file mode 100644 index 000000000..37baeffac --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_settime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S new file mode 100644 index 000000000..f0c39982c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S @@ -0,0 +1,46 @@ +/* Copyright (C) 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.  */ + +#include <sysdep.h> +#include <tcb-offsets.h> + +#undef PSEUDO_PREPARE_ARGS +#define PSEUDO_PREPARE_ARGS						\ +	/* Load the current cached pid value across the vfork.  */	\ +	rduniq;								\ +	ldl	a2, PID_OFFSET(v0);					\ +	mov	v0, a1;							\ +	/* If the cached value is initialized (nonzero), then write	\ +	   back its negation, or INT_MIN, to indicate that the pid	\ +	   value is uninitialized in the the child, and in the window	\ +	   between here and the point at which we restore the value.  */ \ +	ldah	t0, -0x8000;						\ +	negl	a2, t1;							\ +	cmovne	a2, t1, t0;						\ +	stl	t0, PID_OFFSET(v0); + +PSEUDO (__vfork, vfork, 0) + +	/* If we're back in the parent, restore the saved pid.  */ +	beq	v0, 1f +	stl	a2, PID_OFFSET(a1) +1:	ret + +PSEUDO_END (__vfork) +hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile @@ -0,0 +1,13 @@ +# 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. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch new file mode 100644 index 000000000..2256d6b2e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch @@ -0,0 +1,56 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_SSRC = pt-vfork.S +libpthread_CSRC = pthread_once.c lowlevellock.c \ +                  pt-__syscall_rt_sigaction.c pt-__syscall_error.c + +libc_a_CSRC = fork.c +libc_a_SSRC = clone.S vfork.S + +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif +CFLAGS-pthread_once.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-lowlevellock.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -marm +# We always compile it in arm mode because of SAVE_PID macro +# This macro should be alternatively implemented in THUMB +# assembly. +ASFLAGS-vfork.S = -marm + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/arm +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/arm + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) +LINUX_ARCH_OBJ+=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJ) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) +LIBC_LINUX_ARCH_OBJ+=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libc_a_SSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=pthread_linux_arch_objclean + +pthread_linux_arch_objclean: +	$(RM) $(LINUX_ARCH_OUT)/*.{o,os,oS} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h new file mode 100644 index 000000000..49a935a52 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h @@ -0,0 +1,136 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <stdint.h> +#include <sysdep.h> + + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +void __arm_link_error (void); + +#ifdef __thumb__ + +/* Note that to allow efficient implementation the arguemtns are reversed +   relative to atomic_exchange_acq.  */ +int __thumb_swpb (int newvalue, void *mem) +  attribute_hidden; +unsigned int __thumb_swp (unsigned int newvalue, void *mem) +  attribute_hidden; +unsigned int __thumb_cmpxchg (unsigned int oldval, unsigned int newval, void *mem) +  attribute_hidden; + +#define atomic_exchange_acq(mem, newvalue)				      \ +  ({ __typeof (*mem) result;						      \ +     if (sizeof (*mem) == 1)						      \ +       result = __thumb_swpb (newvalue, mem);				      \ +     else if (sizeof (*mem) == 4)					      \ +       result = __thumb_swp (newvalue, mem);				      \ +     else								      \ +       {								      \ +	 result = 0;							      \ +	 abort ();							      \ +       }								      \ +     result; }) + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ +  ({ __arm_link_error (); oldval; }) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ +  ({ __arm_link_error (); oldval; }) + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ +  ((__typeof (oldval)) __thumb_cmpxchg (oldval, newval, mem)) + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ +  ({ __arm_link_error (); oldval; }) + +#else +/* ARM mode.  */ + +#define atomic_exchange_acq(mem, newvalue)				      \ +  ({ __typeof (*mem) _xchg_result;					      \ +     if (sizeof (*mem) == 1)						      \ +       __asm__ __volatile__ ("swpb %0, %1, [%2]"			      \ +			     : "=&r,&r" (_xchg_result)			      \ +			     : "r,0" (newvalue), "r,r" (mem) : "memory");     \ +     else if (sizeof (*mem) == 4)					      \ +       __asm__ __volatile__ ("swp %0, %1, [%2]"				      \ +			     : "=&r,&r" (_xchg_result)			      \ +			     : "r,0" (newvalue), "r,r" (mem) : "memory");     \ +     else								      \ +       {								      \ +	 _xchg_result = 0;						      \ +	 abort ();							      \ +       }								      \ +     _xchg_result; }) + +/* Atomic compare and exchange.  This sequence relies on the kernel to +   provide a compare and exchange operation which is atomic on the +   current architecture, either via cleverness on pre-ARMv6 or via +   ldrex / strex on ARMv6.  */ + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ +  ({ __arm_link_error (); oldval; }) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ +  ({ __arm_link_error (); oldval; }) + +/* It doesn't matter what register is used for a_oldval2, but we must +   specify one to work around GCC PR rtl-optimization/21223.  Otherwise +   it may cause a_oldval or a_tmp to be moved to a different register.  */ + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ +  ({ register __typeof (oldval) a_oldval asm ("r0");			      \ +     register __typeof (oldval) a_newval asm ("r1") = (newval);		      \ +     register __typeof (mem) a_ptr asm ("r2") = (mem);			      \ +     register __typeof (oldval) a_tmp asm ("r3");			      \ +     register __typeof (oldval) a_oldval2 asm ("r4") = (oldval);	      \ +     __asm__ __volatile__						      \ +	     ("0:\tldr\t%1,[%3]\n\t"					      \ +	      "cmp\t%1, %4\n\t"						      \ +	      "bne\t1f\n\t"						      \ +	      "mov\t%0, %4\n\t"						      \ +	      "mov\t%1, #0xffff0fff\n\t"				      \ +	      "mov\tlr, pc\n\t"						      \ +	      "add\tpc, %1, #(0xffff0fc0 - 0xffff0fff)\n\t"		      \ +	      "bcc\t0b\n\t"						      \ +	      "mov\t%1, %4\n\t"						      \ +	      "1:"							      \ +	      : "=&r" (a_oldval), "=&r" (a_tmp)				      \ +	      : "r" (a_newval), "r" (a_ptr), "r" (a_oldval2)		      \ +	      : "ip", "lr", "cc", "memory");				      \ +     a_tmp; }) + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ +  ({ __arm_link_error (); oldval; }) + +#endif /* __thumb__ */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h new file mode 100644 index 000000000..ea8d6a2f0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h @@ -0,0 +1,167 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 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 _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H	1 + +#define __SIZEOF_PTHREAD_ATTR_T 36 +#define __SIZEOF_PTHREAD_MUTEX_T 24 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_COND_COMPAT_T 12 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 32 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 20 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + + +/* Thread identifiers.  The structure of the attribute type is not +   exposed on purpose.  */ +typedef unsigned long int pthread_t; + + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_ATTR_T]; +  long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_slist +{ +  struct __pthread_internal_slist *__next; +} __pthread_slist_t; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is not exposed on purpose.  */ +typedef union +{ +  struct __pthread_mutex_s +  { +    int __lock; +    unsigned int __count; +    int __owner; +    /* KIND must stay at this position in the structure to maintain +       binary compatibility.  */ +    int __kind; +    unsigned int __nusers; +    __extension__ union +    { +      int __spins; +      __pthread_slist_t __list; +    }; +  } __data; +  char __size[__SIZEOF_PTHREAD_MUTEX_T]; +  long int __align; +} pthread_mutex_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; +  long int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling.  The structure of +   the attribute type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __futex; +    __extension__ unsigned long long int __total_seq; +    __extension__ unsigned long long int __wakeup_seq; +    __extension__ unsigned long long int __woken_seq; +    void *__mutex; +    unsigned int __nwaiters; +    unsigned int __broadcast_seq; +  } __data; +  char __size[__SIZEOF_PTHREAD_COND_T]; +  __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_CONDATTR_T]; +  long int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling.  The +   structure of the attribute type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +    int __writer; +  } __data; +  char __size[__SIZEOF_PTHREAD_RWLOCK_T]; +  long int __align; +} pthread_rwlock_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; +  long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type.  */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type.  The structure of the type is +   deliberately not exposed.  */ +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIER_T]; +  long int __align; +} pthread_barrier_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; +  int __align; +} pthread_barrierattr_t; +#endif + + +#endif	/* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h new file mode 100644 index 000000000..3fc647d31 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2002, 2005 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 _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + + +#define __SIZEOF_SEM_T	16 + + +/* Value returned if `sem_open' failed.  */ +#define SEM_FAILED      ((sem_t *) 0) + +/* Maximum value the semaphore can have.  */ +#define SEM_VALUE_MAX   ((int) ((~0u) >> 1)) + + +typedef union +{ +  char __size[__SIZEOF_SEM_T]; +  long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/clone.S new file mode 100644 index 000000000..23227eb24 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/clone.S @@ -0,0 +1,3 @@ +#define RESET_PID +#include <tcb-offsets.h> +#include "../../../../../../../libc/sysdeps/linux/arm/clone.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/createthread.c new file mode 100644 index 000000000..2d4355980 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/createthread.c @@ -0,0 +1,23 @@ +/* Copyright (C) 2005 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.  */ + +/* Value passed to 'clone' for initialization of the thread register.  */ +#define TLS_VALUE (pd + 1) + +/* Get the real implementation.	 */ +#include <sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/fork.c new file mode 100644 index 000000000..1c8f4c43a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/fork.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Phil Blundell <pb@nexus.co.uk>, 2005 + +   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 <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + + +#define ARCH_FORK()							\ +  INLINE_SYSCALL (clone, 5,						\ +		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,	\ +		  NULL, NULL, NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c new file mode 100644 index 000000000..74be18855 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c @@ -0,0 +1,118 @@ +/* low level locking for pthread library.  Generic futex-using version. +   Copyright (C) 2003, 2005 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <sys/time.h> + +int +__lll_timedlock_wait (int *futex, const struct timespec *abstime) +{ +  struct timespec rt; + +  /* Reject invalid timeouts.  */ +  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) +    return EINVAL; + +  /* Upgrade the lock.  */ +  if (atomic_exchange_acq (futex, 2) == 0) +    return 0; + +  do +    { +      struct timeval tv; + +      /* Get the current time.  */ +      (void) gettimeofday (&tv, NULL); + +      /* Compute relative timeout.  */ +      rt.tv_sec = abstime->tv_sec - tv.tv_sec; +      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; +      if (rt.tv_nsec < 0) +	{ +	  rt.tv_nsec += 1000000000; +	  --rt.tv_sec; +	} + +      /* Already timed out?  */ +      if (rt.tv_sec < 0) +	return ETIMEDOUT; + +      lll_futex_timed_wait (futex, 2, &rt); +    } +  while (atomic_exchange_acq (futex, 2) != 0); + +  return 0; +} + + +/* These don't get included in libc.so  */ +#ifdef IS_IN_libpthread +int +lll_unlock_wake_cb (int *futex) +{ +  int val = atomic_exchange_rel (futex, 0); + +  if (__builtin_expect (val > 1, 0)) +    lll_futex_wake (futex, 1); + +  return 0; +} + + +int +__lll_timedwait_tid (int *tidp, const struct timespec *abstime) +{ +  int tid; + +  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) +    return EINVAL; + +  /* Repeat until thread terminated.  */ +  while ((tid = *tidp) != 0) +    { +      struct timeval tv; +      struct timespec rt; + +      /* Get the current time.  */ +      (void) gettimeofday (&tv, NULL); + +      /* Compute relative timeout.  */ +      rt.tv_sec = abstime->tv_sec - tv.tv_sec; +      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; +      if (rt.tv_nsec < 0) +	{ +	  rt.tv_nsec += 1000000000; +	  --rt.tv_sec; +	} + +      /* Already timed out?  */ +      if (rt.tv_sec < 0) +	return ETIMEDOUT; + +      /* Wait until thread terminates.  */ +      if (lll_futex_timed_wait (tidp, tid, &rt) == -ETIMEDOUT) +	return ETIMEDOUT; +    } + +  return 0; +} + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.h new file mode 100644 index 000000000..79f3ddeca --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.h @@ -0,0 +1,339 @@ +/* Copyright (C) 2005, 2006 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 Libr	\ary; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H	1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> +#include <sysdep.h> + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 +#define FUTEX_CMP_REQUEUE	4 +#define FUTEX_WAKE_OP		5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE	((4 << 24) | 1) + +/* Initializer for compatibility lock.	*/ +#define LLL_MUTEX_LOCK_INITIALIZER (0) + +#define lll_futex_wait(futexp, val) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAIT, (val), 0);		      \ +    __ret;								      \ +  }) + +#define lll_futex_timed_wait(futexp, val, timespec) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAIT, (val), (timespec));	      \ +    __ret;								      \ +  }) + +#define lll_futex_wake(futexp, nr) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAKE, (nr), 0);		      \ +    __ret;								      \ +  }) + +#define lll_robust_mutex_dead(futexv) \ +  do									      \ +    {									      \ +      int *__futexp = &(futexv);					      \ +      atomic_or (__futexp, FUTEX_OWNER_DIED);				      \ +      lll_futex_wake (__futexp, 1);					      \ +    }									      \ +  while (0) + +/* Returns non-zero if error happened, zero if success.  */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 6,				      \ +			      (futexp), FUTEX_CMP_REQUEUE, (nr_wake),	      \ +			      (nr_move), (mutex), (val));		      \ +    __ret;								      \ +  }) + + +/* Returns non-zero if error happened, zero if success.  */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 6,				      \ +			      (futexp), FUTEX_WAKE_OP, (nr_wake),	      \ +			      (nr_wake2), (futexp2),			      \ +			      FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);		      \ +    __ret;								      \ +  }) + + +static inline int __attribute__((always_inline)) +__lll_mutex_trylock (int *futex) +{ +  int flag = 1, old; +#ifdef __thumb__ +  old = atomic_exchange_acq (futex, flag); +  if (old < 1) +    flag = 0; +  else if (old > 1) +    flag = atomic_exchange_acq (futex, old); +#else +  __asm__ __volatile__ ( +    "\tswp	%[old], %[flag], [%[futex]]	@ try to take the lock\n" +    "\tcmp	%[old], #1			@ check old lock value\n" +    "\tmovlo	%[flag], #0			@ if we got it, return 0\n" +    "\tswphi	%[flag], %[old], [%[futex]]	@ if it was contested,\n" +    "						@ restore the contested flag,\n" +    "						@ and check whether that won." +    : [futex] "+&r" (futex), [flag] "+&r" (flag), [old] "=&r" (old) +    : : "memory" ); +#endif + +  return flag; +} +#define lll_mutex_trylock(lock)	__lll_mutex_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_mutex_cond_trylock (int *futex) +{ +  int flag = 2, old; +#ifdef __thumb__ +  old = atomic_exchange_acq (futex, flag); +  if (old < 1) +    flag = 0; +  else if (old > 1) +    flag = atomic_exchange_acq (futex, old); +#else +  __asm__ __volatile__ ( +    "\tswp	%[old], %[flag], [%[futex]]	@ try to take the lock\n" +    "\tcmp	%[old], #1			@ check old lock value\n" +    "\tmovlo	%[flag], #0			@ if we got it, return 0\n" +    "\tswphi	%[flag], %[old], [%[futex]]	@ if it was contested,\n" +    "						@ restore the contested flag,\n" +    "						@ and check whether that won." +    : [futex] "+&r" (futex), [flag] "+&r" (flag), [old] "=&r" (old) +    : : "memory" ); +#endif + +  return flag; +} +#define lll_mutex_cond_trylock(lock)	__lll_mutex_cond_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_robust_mutex_trylock(int *futex, int id) +{ +  return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0; +} +#define lll_robust_mutex_trylock(lock, id) \ +  __lll_robust_mutex_trylock (&(lock), id) + +extern int __lll_robust_lock_wait (int *futex) attribute_hidden; + +static inline void __attribute__((always_inline)) +__lll_mutex_lock (int *futex) +{ +  int val = atomic_exchange_acq (futex, 1); + +  if (__builtin_expect (val != 0, 0)) +    { +      while (atomic_exchange_acq (futex, 2) != 0) +	lll_futex_wait (futex, 2); +    } +} +#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex)) + + +static inline int __attribute__ ((always_inline)) +__lll_robust_mutex_lock (int *futex, int id) +{ +  int result = 0; +  if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) +    result = __lll_robust_lock_wait (futex); +  return result; +} +#define lll_robust_mutex_lock(futex, id) \ +  __lll_robust_mutex_lock (&(futex), id) + + +static inline void __attribute__ ((always_inline)) +__lll_mutex_cond_lock (int *futex) +{ +  int val = atomic_exchange_acq (futex, 2); + +  if (__builtin_expect (val != 0, 0)) +    { +      while (atomic_exchange_acq (futex, 2) != 0) +	lll_futex_wait (futex, 2); +    } +} +#define lll_mutex_cond_lock(futex) __lll_mutex_cond_lock (&(futex)) + + +#define lll_robust_mutex_cond_lock(futex, id) \ +  __lll_robust_mutex_lock (&(futex), (id) | FUTEX_WAITERS) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *) +	attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *) +	attribute_hidden; + +static inline int __attribute__ ((always_inline)) +__lll_mutex_timedlock (int *futex, const struct timespec *abstime) +{ +  int result = 0; +  int val = atomic_exchange_acq (futex, 1); + +  if (__builtin_expect (val != 0, 0)) +    result = __lll_timedlock_wait (futex, abstime); +  return result; +} +#define lll_mutex_timedlock(futex, abstime) \ +  __lll_mutex_timedlock (&(futex), abstime) + + +static inline int __attribute__ ((always_inline)) +__lll_robust_mutex_timedlock (int *futex, const struct timespec *abstime, +			      int id) +{ +  int result = 0; +  if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) +    result = __lll_robust_timedlock_wait (futex, abstime); +  return result; +} +#define lll_robust_mutex_timedlock(futex, abstime, id) \ +  __lll_robust_mutex_timedlock (&(futex), abstime, id) + + +static inline void __attribute__ ((always_inline)) +__lll_mutex_unlock (int *futex) +{ +  int val = atomic_exchange_rel (futex, 0); +  if (__builtin_expect (val > 1, 0)) +    lll_futex_wake (futex, 1); +} +#define lll_mutex_unlock(futex) __lll_mutex_unlock(&(futex)) + + +static inline void __attribute__ ((always_inline)) +__lll_robust_mutex_unlock (int *futex, int mask) +{ +  int val = atomic_exchange_rel (futex, 0); +  if (__builtin_expect (val & mask, 0)) +    lll_futex_wake (futex, 1); +} +#define lll_robust_mutex_unlock(futex) \ +  __lll_robust_mutex_unlock(&(futex), FUTEX_WAITERS) + + +static inline void __attribute__ ((always_inline)) +__lll_mutex_unlock_force (int *futex) +{ +  (void) atomic_exchange_rel (futex, 0); +  lll_futex_wake (futex, 1); +} +#define lll_mutex_unlock_force(futex) __lll_mutex_unlock_force(&(futex)) + + +#define lll_mutex_islocked(futex) \ +  (futex != 0) + + +/* Our internal lock implementation is identical to the binary-compatible +   mutex implementation. */ + +/* Type for lock object.  */ +typedef int lll_lock_t; + +/* Initializers for lock.  */ +#define LLL_LOCK_INITIALIZER		(0) +#define LLL_LOCK_INITIALIZER_LOCKED	(1) + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + +/* The states of a lock are: +    0  -  untaken +    1  -  taken by one user +   >1  -  taken by more users */ + +#define lll_trylock(lock)	lll_mutex_trylock (lock) +#define lll_lock(lock)		lll_mutex_lock (lock) +#define lll_unlock(lock)	lll_mutex_unlock (lock) +#define lll_islocked(lock)	lll_mutex_islocked (lock) + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex +   wakeup when the clone terminates.  The memory location contains the +   thread ID while the clone is running and is reset to zero +   afterwards.	*/ +#define lll_wait_tid(tid) \ +  do {					\ +    __typeof (tid) __tid;		\ +    while ((__tid = (tid)) != 0)	\ +      lll_futex_wait (&(tid), __tid);	\ +  } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) +     attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ +  ({							\ +    int __res = 0;					\ +    if ((tid) != 0)					\ +      __res = __lll_timedwait_tid (&(tid), (abstime));	\ +    __res;						\ +  }) + + +/* Conditional variable handling.  */ + +extern void __lll_cond_wait (pthread_cond_t *cond) +     attribute_hidden; +extern int __lll_cond_timedwait (pthread_cond_t *cond, +				 const struct timespec *abstime) +     attribute_hidden; +extern void __lll_cond_wake (pthread_cond_t *cond) +     attribute_hidden; +extern void __lll_cond_broadcast (pthread_cond_t *cond) +     attribute_hidden; + +#define lll_cond_wait(cond) \ +  __lll_cond_wait (cond) +#define lll_cond_timedwait(cond, abstime) \ +  __lll_cond_timedwait (cond, abstime) +#define lll_cond_wake(cond) \ +  __lll_cond_wake (cond) +#define lll_cond_broadcast(cond) \ +  __lll_cond_broadcast (cond) + +#endif	/* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/nptl-aeabi_unwind_cpp_pr1.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/nptl-aeabi_unwind_cpp_pr1.c new file mode 100644 index 000000000..7b8352243 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/nptl-aeabi_unwind_cpp_pr1.c @@ -0,0 +1 @@ +#include <aeabi_unwind_cpp_pr1.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_error.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_error.c new file mode 100644 index 000000000..5a48a9b2e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_error.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/arm/__syscall_error.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_rt_sigaction.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_rt_sigaction.c new file mode 100644 index 000000000..50137c84a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_rt_sigaction.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/common/__syscall_rt_sigaction.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-gettimeofday.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-gettimeofday.c new file mode 100644 index 000000000..08710f1c8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-gettimeofday.c @@ -0,0 +1,5 @@ +#include <sys/syscall.h> +#include <sys/time.h> + +int gettimeofday (struct timeval *, struct timezone *) attribute_hidden; +_syscall2(int, gettimeofday, struct timeval *, tv, struct timezone *, tz); diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-vfork.S new file mode 100644 index 000000000..9764e9ee2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-vfork.S @@ -0,0 +1,38 @@ +/* Copyright (C) 2005 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 <tcb-offsets.h> + +/* Save the PID value.  */ +#define SAVE_PID \ +	str	lr, [sp, #-4]!;		/* Save LR.  */			\ +	mov	r0, #0xffff0fff;	/* Point to the high page.  */	\ +	mov	lr, pc;			/* Save our return address.  */	\ +	sub	pc, r0, #31;		/* Jump to the TLS entry.  */	\ +	ldr	lr, [sp], #4;		/* Restore LR.  */		\ +	mov	r2, r0;			/* Save the TLS addr in r2.  */	\ +	ldr	r3, [r2, #PID_OFFSET];	/* Load the saved PID.  */	\ +	rsb	r0, r3, #0;		/* Negate it.  */		\ +	str	r0, [r2, #PID_OFFSET]	/* Store the temporary PID.  */ + +/* Restore the old PID value in the parent.  */ +#define RESTORE_PID \ +	cmp	r0, #0;			/* If we are the parent... */	\ +	strne	r3, [r2, #PID_OFFSET]	/* ... restore the saved PID.  */ + +#INCLUDE <../../../../../../../LIBC/SYSDEPS/LINUX/ARM/VFORK.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pthread_once.c new file mode 100644 index 000000000..c8925810c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pthread_once.c @@ -0,0 +1,99 @@ +/* Copyright (C) 2004, 2005 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 "pthreadP.h" +#include <lowlevellock.h> + +unsigned long int __fork_generation attribute_hidden; + +static void +clear_once_control (void *arg) +{ +  pthread_once_t *once_control = (pthread_once_t *) arg; + +  *once_control = 0; +  lll_futex_wake (once_control, INT_MAX); +} + +int +__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ +  for (;;) +    { +      int oldval; +      int newval; + +      /* Pseudo code: +	 newval = __fork_generation | 1; +	 oldval = *once_control; +	 if ((oldval & 2) == 0) +	   *once_control = newval; +	 Do this atomically. +      */ +      do +	{ +	  newval = __fork_generation | 1; +	  oldval = *once_control; +	  if (oldval & 2) +	    break; +	} while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval); + +      /* Check if the initializer has already been done.  */ +      if ((oldval & 2) != 0) +	return 0; + +      /* Check if another thread already runs the initializer.	*/ +      if ((oldval & 1) == 0) +	break; + +      /* Check whether the initializer execution was interrupted by a fork.  */ +      if (oldval != newval) +	break; + +      /* Same generation, some other thread was faster. Wait.  */ +      lll_futex_wait (once_control, oldval); +    } + +  /* This thread is the first here.  Do the initialization. +     Register a cleanup handler so that in case the thread gets +     interrupted the initialization can be restarted.  */ +  pthread_cleanup_push (clear_once_control, once_control); + +  init_routine (); + +  pthread_cleanup_pop (0); + +  /* Say that the initialisation is done.  */ +  *once_control = __fork_generation | 2; + +  /* Wake up all other threads.  */ +  lll_futex_wake (once_control, INT_MAX); + +  return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) + +#if defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__PIC__) +/* When statically linked, if pthread_create is used, this file +   will be brought in.  The exception handling code in GCC assumes +   that if pthread_create is available, so are these.  */ +const void *include_pthread_getspecific attribute_hidden = pthread_getspecific; +const void *include_pthread_setspecific attribute_hidden = pthread_setspecific; +const void *include_pthread_key_create attribute_hidden = pthread_key_create; +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h new file mode 100644 index 000000000..350d9af50 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h @@ -0,0 +1,153 @@ +/* Copyright (C) 2003, 2004, 2005 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 <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +/* NOTE: We do mark syscalls with unwind annotations, for the benefit of +   cancellation; but they're really only accurate at the point of the +   syscall.  The ARM unwind directives are not rich enough without adding +   a custom personality function.  */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args)				\ +  .section ".text";							\ +    PSEUDO_PROLOGUE;							\ +  .type __##syscall_name##_nocancel,%function;				\ +  .globl __##syscall_name##_nocancel;					\ +  __##syscall_name##_nocancel:						\ +    DO_CALL (syscall_name, args);					\ +    PSEUDO_RET;								\ +  .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	\ +  ENTRY (name);								\ +    SINGLE_THREAD_P;							\ +    DOARGS_##args;							\ +    bne .Lpseudo_cancel;						\ +    DO_CALL (syscall_name, 0);						\ +    UNDOARGS_##args;							\ +    cmn r0, $4096;							\ +    PSEUDO_RET;								\ +  .Lpseudo_cancel:							\ +    .fnstart;								\ +    DOCARGS_##args;	/* save syscall args etc. around CENABLE.  */	\ +    CENABLE;								\ +    mov ip, r0;		/* put mask in safe place.  */			\ +    UNDOCARGS_##args;	/* restore syscall args.  */			\ +    ldr r7, =SYS_ify (syscall_name);					\ +    swi 0x0;		/* do the call.  */				\ +    .fnend;		/* Past here we can't easily unwind.  */	\ +    mov r7, r0;		/* save syscall return value.  */		\ +    mov r0, ip;		/* get mask back.  */				\ +    CDISABLE;								\ +    mov r0, r7;		/* retrieve return value.  */			\ +    RESTORE_LR_##args;							\ +    UNDOARGS_##args;							\ +    cmn r0, $4096; + +/* DOARGS pushes four bytes on the stack for five arguments, eight bytes for +   six arguments, and nothing for fewer.  In order to preserve doubleword +   alignment, sometimes we must save an extra register.  */ + +# define RESTART_UNWIND .fnend; .fnstart; .save {r7, lr} + +# define DOCARGS_0	stmfd sp!, {r7, lr}; .save {r7, lr} +# define UNDOCARGS_0 +# define RESTORE_LR_0	ldmfd sp!, {r7, lr}; + +# define DOCARGS_1	stmfd sp!, {r0, r1, r7, lr}; .save {r7, lr}; .pad #8 +# define UNDOCARGS_1	ldr r0, [sp], #8; RESTART_UNWIND +# define RESTORE_LR_1	RESTORE_LR_0 + +# define DOCARGS_2	stmfd sp!, {r0, r1, r7, lr}; .save {r7, lr}; .pad #8 +# define UNDOCARGS_2	ldmfd sp!, {r0, r1}; RESTART_UNWIND +# define RESTORE_LR_2	RESTORE_LR_0 + +# define DOCARGS_3	stmfd sp!, {r0, r1, r2, r3, r7, lr}; .save {r7, lr}; .pad #16 +# define UNDOCARGS_3	ldmfd sp!, {r0, r1, r2, r3}; RESTART_UNWIND +# define RESTORE_LR_3	RESTORE_LR_0 + +# define DOCARGS_4	stmfd sp!, {r0, r1, r2, r3, r7, lr}; .save {r7, lr}; .pad #16 +# define UNDOCARGS_4	ldmfd sp!, {r0, r1, r2, r3}; RESTART_UNWIND +# define RESTORE_LR_4	RESTORE_LR_0 + +# define DOCARGS_5	.save {r4}; stmfd sp!, {r0, r1, r2, r3, r4, r7, lr}; .save {r7, lr}; .pad #20 +# define UNDOCARGS_5	ldmfd sp!, {r0, r1, r2, r3}; .fnend; .fnstart; .save {r4}; .save {r7, lr}; .pad #4 +# define RESTORE_LR_5	ldmfd sp!, {r4, r7, lr} + +# define DOCARGS_6	.save {r4, r5}; stmfd sp!, {r0, r1, r2, r3, r7, lr}; .save {r7, lr}; .pad #20 +# define UNDOCARGS_6	ldmfd sp!, {r0, r1, r2, r3}; .fnend; .fnstart; .save {r4, r5}; .save {r7, lr} +# define RESTORE_LR_6	RESTORE_LR_0 + +# ifdef IS_IN_libpthread +#  define CENABLE	bl PLTJMP(__pthread_enable_asynccancel) +#  define CDISABLE	bl PLTJMP(__pthread_disable_asynccancel) +#  define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +#  define CENABLE	bl PLTJMP(__libc_enable_asynccancel) +#  define CDISABLE	bl PLTJMP(__libc_disable_asynccancel) +#  define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_librt +#  define CENABLE	bl PLTJMP(__librt_enable_asynccancel) +#  define CDISABLE	bl PLTJMP(__librt_disable_asynccancel) +# else +#  error Unsupported library +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +#  ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +#   define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +#  else +#   define SINGLE_THREAD_P						\ +  ldr ip, 1b;								\ +2:									\ +  ldr ip, [pc, ip];							\ +  teq ip, #0; +#   define PSEUDO_PROLOGUE						\ +  1:  .word __local_multiple_threads - 2f - 8; +#  endif +# else +/*  There is no __local_multiple_threads for librt, so use the TCB.  */ +#  ifndef __ASSEMBLER__ +#   define SINGLE_THREAD_P						\ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				\ +				   header.multiple_threads) == 0, 1) +#  else +#   define PSEUDO_PROLOGUE +#   define SINGLE_THREAD_P						\ +  stmfd	sp!, {r0, lr};							\ +  bl	__aeabi_read_tp;						\ +  ldr	ip, [r0, #MULTIPLE_THREADS_OFFSET];				\ +  ldmfd	sp!, {r0, lr};							\ +  teq	ip, #0 +#   define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P +#  endif +# endif + +#elif !defined __ASSEMBLER__ + +/* For rtld, et cetera.  */ +# define SINGLE_THREAD_P 1 +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep.h new file mode 100644 index 000000000..23c2bfc8c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep.h @@ -0,0 +1,334 @@ +/* Copyright (C) 1992, 93, 1995-2000, 2002, 2003, 2005, 2006 +   Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995. +   ARM changes by Philip Blundell, <pjb27@cam.ac.uk>, May 1997. + +   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 _LINUX_ARM_SYSDEP_H +#define _LINUX_ARM_SYSDEP_H 1 + +#include <sys/syscall.h> + +/* There is some commonality.  */ +#include <sysdeps/arm/sysdep.h> + +/* For Linux we can use the system call table in the header file +	/usr/include/asm/unistd.h +   of the kernel.  But these symbols do not follow the SYS_* syntax +   so we have to redefine the `SYS_ify' macro here.  */ +#undef SYS_ify +#define SWI_BASE  (0x900000) +#define SYS_ify(syscall_name)	(__NR_##syscall_name) + + +#ifdef __ASSEMBLER__ + +/* Linux uses a negative return value to indicate syscall errors, +   unlike most Unices, which use the condition codes' carry flag. + +   Since version 2.1 the return value of a system call might be +   negative even if the call succeeded.  E.g., the `lseek' system call +   might return a large offset.  Therefore we must not anymore test +   for < 0, but test for a real error by making sure the value in R0 +   is a real error number.  Linus said he will make sure the no syscall +   returns a value in -1 .. -4095 as a valid result so we can safely +   test with -4095.  */ + +#undef	PSEUDO +#define	PSEUDO(name, syscall_name, args)				      \ +  .text;								      \ +  ENTRY (name);								      \ +    DO_CALL (syscall_name, args);					      \ +    cmn r0, $4096; + +#define PSEUDO_RET							      \ +    RETINSTR(cc, lr);							      \ +    b PLTJMP(SYSCALL_ERROR) +#undef ret +#define ret PSEUDO_RET + +#undef	PSEUDO_END +#define	PSEUDO_END(name)						      \ +  SYSCALL_ERROR_HANDLER							      \ +  END (name) + +#undef	PSEUDO_NOERRNO +#define	PSEUDO_NOERRNO(name, syscall_name, args)			      \ +  .text;								      \ +  ENTRY (name);								      \ +    DO_CALL (syscall_name, args); + +#define PSEUDO_RET_NOERRNO						      \ +    DO_RET (lr); + +#undef ret_NOERRNO +#define ret_NOERRNO PSEUDO_RET_NOERRNO + +#undef	PSEUDO_END_NOERRNO +#define	PSEUDO_END_NOERRNO(name)					      \ +  END (name) + +/* The function has to return the error code.  */ +#undef	PSEUDO_ERRVAL +#define	PSEUDO_ERRVAL(name, syscall_name, args) \ +  .text;								      \ +  ENTRY (name)								      \ +    DO_CALL (syscall_name, args);					      \ +    rsb r0, r0, #0 + +#undef	PSEUDO_END_ERRVAL +#define	PSEUDO_END_ERRVAL(name) \ +  END (name) + +#define ret_ERRVAL PSEUDO_RET_NOERRNO + +#if NOT_IN_libc +# define SYSCALL_ERROR __local_syscall_error +# ifdef RTLD_PRIVATE_ERRNO +#  define SYSCALL_ERROR_HANDLER					\ +__local_syscall_error:						\ +       ldr     r1, 1f;						\ +       rsb     r0, r0, #0;					\ +0:     str     r0, [pc, r1];					\ +       mvn     r0, #0;						\ +       DO_RET(lr);						\ +1:     .word C_SYMBOL_NAME(rtld_errno) - 0b - 8; +# else +#  define SYSCALL_ERROR_HANDLER					\ +__local_syscall_error:						\ +	str	lr, [sp, #-4]!;					\ +	str	r0, [sp, #-4]!;					\ +	bl	PLTJMP(C_SYMBOL_NAME(__errno_location)); 	\ +	ldr	r1, [sp], #4;					\ +	rsb	r1, r1, #0;					\ +	str	r1, [r0];					\ +	mvn	r0, #0;						\ +	ldr	pc, [sp], #4; +# endif +#else +# define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.S is used.  */ +# define SYSCALL_ERROR __syscall_error +#endif + +/* Linux takes system call args in registers: +	syscall number	in the SWI instruction +	arg 1		r0 +	arg 2		r1 +	arg 3		r2 +	arg 4		r3 +	arg 5		r4	(this is different from the APCS convention) +	arg 6		r5 +	arg 7		r6 + +   The compiler is going to form a call by coming here, through PSEUDO, with +   arguments +	syscall number	in the DO_CALL macro +	arg 1		r0 +	arg 2		r1 +	arg 3		r2 +	arg 4		r3 +	arg 5		[sp] +	arg 6		[sp+4] +	arg 7		[sp+8] + +   We need to shuffle values between R4..R6 and the stack so that the +   caller's v1..v3 and stack frame are not corrupted, and the kernel +   sees the right arguments. + +*/ + +#undef	DO_CALL +#if defined(__ARM_EABI__) +#define DO_CALL(syscall_name, args)		\ +    DOARGS_##args				\ +    mov ip, r7;					\ +    ldr r7, =SYS_ify (syscall_name);		\ +    swi 0x0;					\ +    mov r7, ip;					\ +    UNDOARGS_##args +#else +#define DO_CALL(syscall_name, args)		\ +    DOARGS_##args				\ +    swi SYS_ify (syscall_name); 		\ +    UNDOARGS_##args +#endif + +#define DOARGS_0 /* nothing */ +#define DOARGS_1 /* nothing */ +#define DOARGS_2 /* nothing */ +#define DOARGS_3 /* nothing */ +#define DOARGS_4 /* nothing */ +#define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $4]; +#define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmia ip, {r4, r5}; +#define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmia ip, {r4, r5, r6}; + +#define UNDOARGS_0 /* nothing */ +#define UNDOARGS_1 /* nothing */ +#define UNDOARGS_2 /* nothing */ +#define UNDOARGS_3 /* nothing */ +#define UNDOARGS_4 /* nothing */ +#define UNDOARGS_5 ldr r4, [sp], $4; +#define UNDOARGS_6 ldmfd sp!, {r4, r5}; +#define UNDOARGS_7 ldmfd sp!, {r4, r5, r6}; + +#else /* not __ASSEMBLER__ */ + +/* Define a macro which expands into the inline wrapper code for a system +   call.  */ +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...)				\ +  ({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args);	\ +     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))	\ +       {								\ +	 __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, ));		\ +	 _sys_result = (unsigned int) -1;				\ +       }								\ +     (int) _sys_result; }) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) do { } while (0) + +#undef INTERNAL_SYSCALL_RAW +#if defined(__thumb__) +/* Hide the use of r7 from the compiler, this would be a lot + * easier but for the fact that the syscalls can exceed 255. + * For the moment the LOAD_ARG_7 is sacrificed. + * We can't use push/pop inside the asm because that breaks + * unwinding (ie. thread cancellation). + */ +#define INTERNAL_SYSCALL_RAW(name, err, nr, args...)		\ +  ({ unsigned int _sys_result;                                  \ +    {                                                           \ +      int _sys_buf[2];						\ +      register int _a1 __asm__ ("a1");                          \ +      register int *_v3 __asm__ ("v3") = _sys_buf;		\ +      LOAD_ARGS_##nr (args)                                     \ +      *_v3 = (int) (name);					\ +      __asm__ __volatile__ ("str	r7, [v3, #4]\n"		\ +                    "\tldr      r7, [v3]\n"                     \ +                    "\tswi      0       @ syscall " #name "\n"  \ +                    "\tldr      r7, [v3, #4]"                   \ +                   : "=r" (_a1)                                 \ +                    : "r" (_v3) ASM_ARGS_##nr                   \ +                    : "memory");                                \ +      _sys_result = _a1;                                        \ +    }                                                           \ +    (int) _sys_result; }) +#elif defined(__ARM_EABI__) +#define INTERNAL_SYSCALL_RAW(name, err, nr, args...)		\ +  ({unsigned int _sys_result;					\ +     {								\ +       register int _a1 __asm__ ("r0"), _nr __asm__ ("r7");	\ +       LOAD_ARGS_##nr (args)					\ +       _nr = name;						\ +       __asm__ __volatile__ ("swi	0x0 @ syscall " #name	\ +		     : "=r" (_a1)				\ +		     : "r" (_nr) ASM_ARGS_##nr			\ +		     : "memory");				\ +       _sys_result = _a1;					\ +     }								\ +     (int) _sys_result; }) +#else /* !defined(__ARM_EABI__) */ +#define INTERNAL_SYSCALL_RAW(name, err, nr, args...)		\ +  ({ unsigned int _sys_result;					\ +     {								\ +       register int _a1 __asm__ ("a1");				\ +       LOAD_ARGS_##nr (args)					\ +       __asm__ __volatile__ ("swi	%1 @ syscall " #name	\ +		     : "=r" (_a1)				\ +		     : "i" (name) ASM_ARGS_##nr			\ +		     : "memory");				\ +       _sys_result = _a1;					\ +     }								\ +     (int) _sys_result; }) +#endif + +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...)		\ +	INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args) + +#undef INTERNAL_SYSCALL_ARM +#define INTERNAL_SYSCALL_ARM(name, err, nr, args...)		\ +	INTERNAL_SYSCALL_RAW(__ARM_NR_##name, err, nr, args) + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ +  ((unsigned int) (val) >= 0xfffff001u) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, err)	(-(val)) + +#define LOAD_ARGS_0() +#define ASM_ARGS_0 +#define LOAD_ARGS_1(a1)				\ +  _a1 = (int) (a1);				\ +  LOAD_ARGS_0 () +#define ASM_ARGS_1	ASM_ARGS_0, "r" (_a1) +#define LOAD_ARGS_2(a1, a2)			\ +  register int _a2 __asm__ ("a2") = (int) (a2);	\ +  LOAD_ARGS_1 (a1) +#define ASM_ARGS_2	ASM_ARGS_1, "r" (_a2) +#define LOAD_ARGS_3(a1, a2, a3)			\ +  register int _a3 __asm__ ("a3") = (int) (a3);	\ +  LOAD_ARGS_2 (a1, a2) +#define ASM_ARGS_3	ASM_ARGS_2, "r" (_a3) +#define LOAD_ARGS_4(a1, a2, a3, a4)		\ +  register int _a4 __asm__ ("a4") = (int) (a4);	\ +  LOAD_ARGS_3 (a1, a2, a3) +#define ASM_ARGS_4	ASM_ARGS_3, "r" (_a4) +#define LOAD_ARGS_5(a1, a2, a3, a4, a5)		\ +  register int _v1 __asm__ ("v1") = (int) (a5);	\ +  LOAD_ARGS_4 (a1, a2, a3, a4) +#define ASM_ARGS_5	ASM_ARGS_4, "r" (_v1) +#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)	\ +  register int _v2 __asm__ ("v2") = (int) (a6);	\ +  LOAD_ARGS_5 (a1, a2, a3, a4, a5) +#define ASM_ARGS_6	ASM_ARGS_5, "r" (_v2) +#define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7)	\ +  register int _v3 __asm__ ("v3") = (int) (a7);	\ +  LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6) +#define ASM_ARGS_7	ASM_ARGS_6, "r" (_v3) + +#if defined(__ARM_EABI__) +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...)		\ +	INTERNAL_SYSCALL_RAW(number, err, nr, args) +#else +/* We can't implement non-constant syscalls directly since the syscall +   number is normally encoded in the instruction.  So use SYS_syscall.  */ +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...)		\ +	INTERNAL_SYSCALL_NCS_##nr (number, err, args) + +#define INTERNAL_SYSCALL_NCS_0(number, err, args...)		\ +	INTERNAL_SYSCALL (syscall, err, 1, number, args) +#define INTERNAL_SYSCALL_NCS_1(number, err, args...)		\ +	INTERNAL_SYSCALL (syscall, err, 2, number, args) +#define INTERNAL_SYSCALL_NCS_2(number, err, args...)		\ +	INTERNAL_SYSCALL (syscall, err, 3, number, args) +#define INTERNAL_SYSCALL_NCS_3(number, err, args...)		\ +	INTERNAL_SYSCALL (syscall, err, 4, number, args) +#define INTERNAL_SYSCALL_NCS_4(number, err, args...)		\ +	INTERNAL_SYSCALL (syscall, err, 5, number, args) +#define INTERNAL_SYSCALL_NCS_5(number, err, args...)		\ +	INTERNAL_SYSCALL (syscall, err, 6, number, args) +#endif + +#endif	/* __ASSEMBLER__ */ + +#endif /* linux/arm/sysdep.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c new file mode 100644 index 000000000..206202809 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c @@ -0,0 +1,129 @@ +/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>. + +   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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <dlfcn.h> +#include <string.h> +#include <unwind.h> +#include <unistd.h> +#include <pthreadP.h> + +#define __libc_dlopen(x)	dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) +#define __libc_dlsym		dlsym + +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) +  (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *); +static _Unwind_Reason_Code (*libgcc_s_forcedunwind) +  (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); +static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *); + +void +pthread_cancel_init (void) +{ +  void *resume, *personality, *forcedunwind, *getcfa; +  void *handle; + +  if (__builtin_expect (libgcc_s_getcfa != NULL, 1)) +    return; + +  handle = __libc_dlopen ("libgcc_s.so.1"); + +  if (handle == NULL +      || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL +      || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL +      || (forcedunwind = __libc_dlsym (handle, "_Unwind_ForcedUnwind")) +	 == NULL +      || (getcfa = __libc_dlsym (handle, "_Unwind_GetCFA")) == NULL +#ifdef ARCH_CANCEL_INIT +      || ARCH_CANCEL_INIT (handle) +#endif +      ) +    { +# define STR_N_LEN(str) str, strlen (str) +      INTERNAL_SYSCALL_DECL (err); +      INTERNAL_SYSCALL (write, err, 3, STDERR_FILENO, +			STR_N_LEN ("libgcc_s.so.1 must be installed for pthread_cancel to work\n")); +      abort (); +    } + +  libgcc_s_resume = resume; +  libgcc_s_personality = personality; +  libgcc_s_forcedunwind = forcedunwind; +  libgcc_s_getcfa = getcfa; +} + +/* It's vitally important that _Unwind_Resume not have a stack frame; the +   ARM unwinder relies on register state at entrance.  So we write this in +   assembly.  */ + +asm ( +#ifdef __thumb__ +"	.code 32" +#endif +"	.globl	_Unwind_Resume\n" +"	.type	_Unwind_Resume, %function\n" +"_Unwind_Resume:\n" +"	stmfd	sp!, {r4, r5, r6, lr}\n" +"	ldr	r4, 1f\n" +"	ldr	r5, 2f\n" +"3:	add	r4, pc, r4\n" +"	ldr	r3, [r4, r5]\n" +"	mov	r6, r0\n" +"	cmp	r3, #0\n" +"	beq	4f\n" +"5:	mov	r0, r6\n" +"	ldmfd	sp!, {r4, r5, r6, lr}\n" +"	bx	r3\n" +"4:	bl	pthread_cancel_init\n" +"	ldr	r3, [r4, r5]\n" +"	b	5b\n" +"1:	.word	_GLOBAL_OFFSET_TABLE_ - 3b - 8\n" +"2:	.word	libgcc_s_resume(GOTOFF)\n" +"	.size	_Unwind_Resume, .-_Unwind_Resume\n" +#ifdef __thumb__ +"	.code 16" +#endif +); + +_Unwind_Reason_Code +__gcc_personality_v0 (_Unwind_State state, +		      struct _Unwind_Exception *ue_header, +		      struct _Unwind_Context *context) +{ +  if (__builtin_expect (libgcc_s_personality == NULL, 0)) +    pthread_cancel_init (); +  return libgcc_s_personality (state, ue_header, context); +} + +_Unwind_Reason_Code +_Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop, +		      void *stop_argument) +{ +  if (__builtin_expect (libgcc_s_forcedunwind == NULL, 0)) +    pthread_cancel_init (); +  return libgcc_s_forcedunwind (exc, stop, stop_argument); +} + +_Unwind_Word +_Unwind_GetCFA (struct _Unwind_Context *context) +{ +  if (__builtin_expect (libgcc_s_getcfa == NULL, 0)) +    pthread_cancel_init (); +  return libgcc_s_getcfa (context); +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c new file mode 100644 index 000000000..99b15746a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c @@ -0,0 +1,95 @@ +/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>. + +   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; see the file COPYING.LIB.  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> +#include <unwind.h> + +#define __libc_dlopen(x)	dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) +#define __libc_dlsym		dlsym + +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) +  (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *); + +static void init (void) __attribute_used__; + +static void +init (void) +{ +  void *resume, *personality; +  void *handle; + +  handle = __libc_dlopen ("libgcc_s.so.1"); + +  if (handle == NULL +      || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL +      || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL) { +    fprintf(stderr, "libgcc_s.so.1 must be installed for pthread_cancel to work\n"); +    abort (); +  } + +  libgcc_s_resume = resume; +  libgcc_s_personality = personality; +} + +/* It's vitally important that _Unwind_Resume not have a stack frame; the +   ARM unwinder relies on register state at entrance.  So we write this in +   assembly.  */ + +__asm__ ( +#ifdef __thumb__ +"       .code 32\n" +#endif +"	.globl	_Unwind_Resume\n" +"	.type	_Unwind_Resume, %function\n" +"_Unwind_Resume:\n" +"	stmfd	sp!, {r4, r5, r6, lr}\n" +"	ldr	r4, 1f\n" +"	ldr	r5, 2f\n" +"3:	add	r4, pc, r4\n" +"	ldr	r3, [r4, r5]\n" +"	mov	r6, r0\n" +"	cmp	r3, #0\n" +"	beq	4f\n" +"5:	mov	r0, r6\n" +"	ldmfd	sp!, {r4, r5, r6, lr}\n" +"	bx	r3\n" +"4:	bl	init\n" +"	ldr	r3, [r4, r5]\n" +"	b	5b\n" +"1:	.word	_GLOBAL_OFFSET_TABLE_ - 3b - 8\n" +"2:	.word	libgcc_s_resume(GOTOFF)\n" +"	.size	_Unwind_Resume, .-_Unwind_Resume\n" +#ifdef __thumb__ +"       .code 16\n" +#endif + +); + +_Unwind_Reason_Code +__gcc_personality_v0 (_Unwind_State state, +		      struct _Unwind_Exception *ue_header, +		      struct _Unwind_Context *context) +{ +  if (__builtin_expect (libgcc_s_personality == NULL, 0)) +    init (); +  return libgcc_s_personality (state, ue_header, context); +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind.h new file mode 100644 index 000000000..d625fb288 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind.h @@ -0,0 +1,274 @@ +/* Header file for the ARM EABI unwinder +   Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc. +   Contributed by Paul Brook + +   This file is free software; you can redistribute it and/or modify it +   under the terms of the GNU General Public License as published by the +   Free Software Foundation; either version 2, or (at your option) any +   later version. + +   In addition to the permissions in the GNU General Public License, the +   Free Software Foundation gives you unlimited permission to link the +   compiled version of this file into combinations with other programs, +   and to distribute those combinations without any restriction coming +   from the use of this file.  (The General Public License restrictions +   do apply in other respects; for example, they cover modification of +   the file, and distribution when not linked into a combine +   executable.) + +   This file 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 +   General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program; see the file COPYING.  If not, write to +   the Free Software Foundation, 51 Franklin Street, Fifth Floor, +   Boston, MA 02110-1301, USA.  */ + +/* Language-independent unwinder header public defines.  This contains both +   ABI defined objects, and GNU support routines.  */ + +#ifndef UNWIND_ARM_H +#define UNWIND_ARM_H + +#define __ARM_EABI_UNWINDER__ 1 + +#ifdef __cplusplus +extern "C" { +#endif +  typedef unsigned _Unwind_Word __attribute__((__mode__(__word__))); +  typedef signed _Unwind_Sword __attribute__((__mode__(__word__))); +  typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); +  typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__))); +  typedef _Unwind_Word _uw; +  typedef unsigned _uw64 __attribute__((mode(__DI__))); +  typedef unsigned _uw16 __attribute__((mode(__HI__))); +  typedef unsigned _uw8 __attribute__((mode(__QI__))); + +  typedef enum +    { +      _URC_OK = 0,       /* operation completed successfully */ +      _URC_FOREIGN_EXCEPTION_CAUGHT = 1, +      _URC_END_OF_STACK = 5, +      _URC_HANDLER_FOUND = 6, +      _URC_INSTALL_CONTEXT = 7, +      _URC_CONTINUE_UNWIND = 8, +      _URC_FAILURE = 9   /* unspecified failure of some kind */ +    } +  _Unwind_Reason_Code; + +  typedef enum +    { +      _US_VIRTUAL_UNWIND_FRAME = 0, +      _US_UNWIND_FRAME_STARTING = 1, +      _US_UNWIND_FRAME_RESUME = 2, +      _US_ACTION_MASK = 3, +      _US_FORCE_UNWIND = 8, +      _US_END_OF_STACK = 16 +    } +  _Unwind_State; + +  /* Provided only for for compatibility with existing code.  */ +  typedef int _Unwind_Action; +#define _UA_SEARCH_PHASE	1 +#define _UA_CLEANUP_PHASE	2 +#define _UA_HANDLER_FRAME	4 +#define _UA_FORCE_UNWIND	8 +#define _UA_END_OF_STACK	16 +#define _URC_NO_REASON 	_URC_OK + +  typedef struct _Unwind_Control_Block _Unwind_Control_Block; +  typedef struct _Unwind_Context _Unwind_Context; +  typedef _uw _Unwind_EHT_Header; + + +  /* UCB: */ + +  struct _Unwind_Control_Block +    { +#ifdef _LIBC +      /* For the benefit of code which assumes this is a scalar.  All +	 glibc ever does is clear it.  */ +      _uw64 exception_class; +#else +      char exception_class[8]; +#endif +      void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *); +      /* Unwinder cache, private fields for the unwinder's use */ +      struct +	{ +	  _uw reserved1;  /* Forced unwind stop fn, 0 if not forced */ +	  _uw reserved2;  /* Personality routine address */ +	  _uw reserved3;  /* Saved callsite address */ +	  _uw reserved4;  /* Forced unwind stop arg */ +	  _uw reserved5; +	} +      unwinder_cache; +      /* Propagation barrier cache (valid after phase 1): */ +      struct +	{ +	  _uw sp; +	  _uw bitpattern[5]; +	} +      barrier_cache; +      /* Cleanup cache (preserved over cleanup): */ +      struct +	{ +	  _uw bitpattern[4]; +	} +      cleanup_cache; +      /* Pr cache (for pr's benefit): */ +      struct +	{ +	  _uw fnstart;			/* function start address */ +	  _Unwind_EHT_Header *ehtp;	/* pointer to EHT entry header word */ +	  _uw additional;		/* additional data */ +	  _uw reserved1; +	} +      pr_cache; +      long long int :0;	/* Force alignment to 8-byte boundary */ +    }; + +  /* Virtual Register Set*/ + +  typedef enum +    { +      _UVRSC_CORE = 0,      /* integer register */ +      _UVRSC_VFP = 1,       /* vfp */ +      _UVRSC_FPA = 2,       /* fpa */ +      _UVRSC_WMMXD = 3,     /* Intel WMMX data register */ +      _UVRSC_WMMXC = 4      /* Intel WMMX control register */ +    } +  _Unwind_VRS_RegClass; + +  typedef enum +    { +      _UVRSD_UINT32 = 0, +      _UVRSD_VFPX = 1, +      _UVRSD_FPAX = 2, +      _UVRSD_UINT64 = 3, +      _UVRSD_FLOAT = 4, +      _UVRSD_DOUBLE = 5 +    } +  _Unwind_VRS_DataRepresentation; + +  typedef enum +    { +      _UVRSR_OK = 0, +      _UVRSR_NOT_IMPLEMENTED = 1, +      _UVRSR_FAILED = 2 +    } +  _Unwind_VRS_Result; + +  /* Frame unwinding state.  */ +  typedef struct +    { +      /* The current word (bytes packed msb first).  */ +      _uw data; +      /* Pointer to the next word of data.  */ +      _uw *next; +      /* The number of bytes left in this word.  */ +      _uw8 bytes_left; +      /* The number of words pointed to by ptr.  */ +      _uw8 words_left; +    } +  __gnu_unwind_state; + +  typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State, +      _Unwind_Control_Block *, _Unwind_Context *); + +  _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass, +                                     _uw, _Unwind_VRS_DataRepresentation, +                                     void *); + +  _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass, +                                     _uw, _Unwind_VRS_DataRepresentation, +                                     void *); + +  _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass, +                                     _uw, _Unwind_VRS_DataRepresentation); + + +  /* Support functions for the PR.  */ +#define _Unwind_Exception _Unwind_Control_Block +  typedef char _Unwind_Exception_Class[8]; + +  void * _Unwind_GetLanguageSpecificData (_Unwind_Context *); +  _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *); + +  /* These two should never be used.  */ +  _Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *); +  _Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *); + +  /* Interface functions: */ +  _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp); +  void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp); +  _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp); + +  typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) +       (int, _Unwind_Action, _Unwind_Exception_Class, +	_Unwind_Control_Block *, struct _Unwind_Context *, void *); +  _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *, +					    _Unwind_Stop_Fn, void *); +  _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *); +  void _Unwind_Complete(_Unwind_Control_Block *ucbp); +  void _Unwind_DeleteException (_Unwind_Exception *); + +  _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *, +					  _Unwind_Context *); +  _Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *, +					    __gnu_unwind_state *); + +  /* Decode an R_ARM_TARGET2 relocation.  */ +  static inline _Unwind_Word +  _Unwind_decode_target2 (_Unwind_Word ptr) +    { +      _Unwind_Word tmp; + +      tmp = *(_Unwind_Word *) ptr; +      /* Zero values are always NULL.  */ +      if (!tmp) +	return 0; + +#if defined(linux) || defined(__NetBSD__) +      /* Pc-relative indirect.  */ +      tmp += ptr; +      tmp = *(_Unwind_Word *) tmp; +#elif defined(__symbian__) +      /* Absolute pointer.  Nothing more to do.  */ +#else +      /* Pc-relative pointer.  */ +      tmp += ptr; +#endif +      return tmp; +    } + +  static inline _Unwind_Word +  _Unwind_GetGR (_Unwind_Context *context, int regno) +    { +      _uw val; +      _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val); +      return val; +    } + +  /* Return the address of the instruction, not the actual IP value.  */ +#define _Unwind_GetIP(context) \ +  (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1) + +  static inline void +  _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val) +    { +      _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val); +    } + +  /* The dwarf unwinder doesn't understand arm/thumb state.  We assume the +     landing pad uses the same instruction set as the call site.  */ +#define _Unwind_SetIP(context, val) \ +  _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1)) + +#ifdef __cplusplus +}   /* extern "C" */ +#endif + +#endif /* defined UNWIND_ARM_H */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/vfork.S new file mode 100644 index 000000000..935a4e904 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/vfork.S @@ -0,0 +1,39 @@ +/* Copyright (C) 2005 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 <tcb-offsets.h> + +/* Save the PID value.  */ +#define SAVE_PID \ +	str	lr, [sp, #-4]!;		/* Save LR.  */			\ +	mov	r0, #0xffff0fff;	/* Point to the high page.  */	\ +	mov	lr, pc;			/* Save our return address.  */	\ +	sub	pc, r0, #31;		/* Jump to the TLS entry.  */	\ +	ldr	lr, [sp], #4;		/* Restore LR.  */		\ +	mov	r2, r0;			/* Save the TLS addr in r2.  */	\ +	ldr	r3, [r2, #PID_OFFSET];	/* Load the saved PID.  */	\ +	rsbs	r0, r3, #0;		/* Negate it.  */		\ +	moveq	r0, #0x80000000;	/* Use 0x80000000 if it was 0.  */ \ +	str	r0, [r2, #PID_OFFSET]	/* Store the temporary PID.  */ + +/* Restore the old PID value in the parent.  */ +#define RESTORE_PID \ +	cmp	r0, #0;			/* If we are the parent... */	\ +	strne	r3, [r2, #PID_OFFSET]	/* ... restore the saved PID.  */ + +#include "../../../../../../../libc/sysdeps/linux/arm/vfork.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h b/libpthread/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h new file mode 100644 index 000000000..b639ba44a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h @@ -0,0 +1,89 @@ +/* Minimum guaranteed maximum values for system limits.  Linux version. +   Copyright (C) 1993-1998,2000,2002,2003,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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol +   and defines LINK_MAX although filesystems have different maxima.  A +   similar thing is true for OPEN_MAX: the limit can be changed at +   runtime and therefore the macro must not be defined.  Remove this +   after including the header if necessary.  */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information.  */ +#include <linux/limits.h> + +/* Have to remove NR_OPEN?  */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX?  */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX?  */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process.  */ +#define _POSIX_THREAD_KEYS_MAX	128 +/* This is the value this implementation supports.  */ +#define PTHREAD_KEYS_MAX	1024 + +/* Controlling the iterations of destructors for thread-specific data.  */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS	4 +/* Number of iterations this implementation does.  */ +#define PTHREAD_DESTRUCTOR_ITERATIONS	_POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process.  */ +#define _POSIX_THREAD_THREADS_MAX	64 +/* We have no predefined limit on the number of threads.  */ +#undef PTHREAD_THREADS_MAX + +/* Maximum amount by which a process can descrease its asynchronous I/O +   priority level.  */ +#define AIO_PRIO_DELTA_MAX	20 + +/* Minimum size for a thread.  We are free to choose a reasonable value.  */ +#define PTHREAD_STACK_MIN	16384 + +/* Maximum number of timer expiration overruns.  */ +#define DELAYTIMER_MAX	2147483647 + +/* Maximum tty name length.  */ +#define TTY_NAME_MAX		32 + +/* Maximum login name length.  This is arbitrary.  */ +#define LOGIN_NAME_MAX		256 + +/* Maximum host name length.  */ +#define HOST_NAME_MAX		64 + +/* Maximum message queue priority level.  */ +#define MQ_PRIO_MAX		32768 diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h new file mode 100644 index 000000000..92c2d3282 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h @@ -0,0 +1,178 @@ +/* Define POSIX options for Linux. +   Copyright (C) 1996-2001, 2002, 2003, 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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#ifndef	_POSIX_OPT_H +#define	_POSIX_OPT_H	1 + +/* Job control is supported.  */ +#define	_POSIX_JOB_CONTROL	1 + +/* Processes have a saved set-user-ID and a saved set-group-ID.  */ +#define	_POSIX_SAVED_IDS	1 + +/* Priority scheduling is supported.  */ +#define	_POSIX_PRIORITY_SCHEDULING	200112L + +/* Synchronizing file data is supported.  */ +#define	_POSIX_SYNCHRONIZED_IO	200112L + +/* The fsync function is present.  */ +#define	_POSIX_FSYNC	200112L + +/* Mapping of files to memory is supported.  */ +#define	_POSIX_MAPPED_FILES	200112L + +/* Locking of all memory is supported.  */ +#define	_POSIX_MEMLOCK	200112L + +/* Locking of ranges of memory is supported.  */ +#define	_POSIX_MEMLOCK_RANGE	200112L + +/* Setting of memory protections is supported.  */ +#define	_POSIX_MEMORY_PROTECTION	200112L + +/* Only root can change owner of file.  */ +#define	_POSIX_CHOWN_RESTRICTED	1 + +/* `c_cc' member of 'struct termios' structure can be disabled by +   using the value _POSIX_VDISABLE.  */ +#define	_POSIX_VDISABLE	'\0' + +/* Filenames are not silently truncated.  */ +#define	_POSIX_NO_TRUNC	1 + +/* X/Open realtime support is available.  */ +#define _XOPEN_REALTIME	1 + +/* XPG4.2 shared memory is supported.  */ +#define	_XOPEN_SHM	1 + +/* Tell we have POSIX threads.  */ +#define _POSIX_THREADS	200112L + +/* We have the reentrant functions described in POSIX.  */ +#define _POSIX_REENTRANT_FUNCTIONS      1 +#define _POSIX_THREAD_SAFE_FUNCTIONS	200112L + +/* We provide priority scheduling for threads.  */ +#define _POSIX_THREAD_PRIORITY_SCHEDULING	200112L + +/* We support user-defined stack sizes.  */ +#define _POSIX_THREAD_ATTR_STACKSIZE	200112L + +/* We support user-defined stacks.  */ +#define _POSIX_THREAD_ATTR_STACKADDR	200112L + +/* We support POSIX.1b semaphores.  */ +#define _POSIX_SEMAPHORES	200112L + +/* Real-time signals are supported.  */ +#define _POSIX_REALTIME_SIGNALS	200112L + +/* We support asynchronous I/O.  */ +#define _POSIX_ASYNCHRONOUS_IO	200112L +#define _POSIX_ASYNC_IO		1 +/* Alternative name for Unix98.  */ +#define _LFS_ASYNCHRONOUS_IO	1 +/* Support for prioritization is also available.  */ +#define _POSIX_PRIORITIZED_IO	200112L + +/* The LFS support in asynchronous I/O is also available.  */ +#define _LFS64_ASYNCHRONOUS_IO	1 + +/* The rest of the LFS is also available.  */ +#define _LFS_LARGEFILE		1 +#define _LFS64_LARGEFILE	1 +#define _LFS64_STDIO		1 + +/* POSIX shared memory objects are implemented.  */ +#define _POSIX_SHARED_MEMORY_OBJECTS	200112L + +/* CPU-time clocks support needs to be checked at runtime.  */ +#define _POSIX_CPUTIME	0 + +/* Clock support in threads must be also checked at runtime.  */ +#define _POSIX_THREAD_CPUTIME	0 + +/* GNU libc provides regular expression handling.  */ +#define _POSIX_REGEXP	1 + +/* Reader/Writer locks are available.  */ +#define _POSIX_READER_WRITER_LOCKS	200112L + +/* We have a POSIX shell.  */ +#define _POSIX_SHELL	1 + +/* We support the Timeouts option.  */ +#define _POSIX_TIMEOUTS	200112L + +/* We support spinlocks.  */ +#define _POSIX_SPIN_LOCKS	200112L + +/* The `spawn' function family is supported.  */ +#define _POSIX_SPAWN	200112L + +/* We have POSIX timers.  */ +#define _POSIX_TIMERS	200112L + +/* The barrier functions are available.  */ +#define _POSIX_BARRIERS	200112L + +/* POSIX message queues are available.  */ +#define	_POSIX_MESSAGE_PASSING	200112L + +/* Thread process-shared synchronization is supported.  */ +#define _POSIX_THREAD_PROCESS_SHARED	200112L + +/* The monotonic clock might be available.  */ +#define _POSIX_MONOTONIC_CLOCK	0 + +/* The clock selection interfaces are available.  */ +#define _POSIX_CLOCK_SELECTION	200112L + +/* Advisory information interfaces are available.  */ +#define _POSIX_ADVISORY_INFO	200112L + +/* IPv6 support is available.  */ +#define _POSIX_IPV6	200112L + +/* Raw socket support is available.  */ +#define _POSIX_RAW_SOCKETS	200112L + +/* We have at least one terminal.  */ +#define _POSIX2_CHAR_TERM	200112L + +/* Neither process nor thread sporadic server interfaces is available.  */ +#define _POSIX_SPORADIC_SERVER	-1 +#define _POSIX_THREAD_SPORADIC_SERVER	-1 + +/* trace.h is not available.  */ +#define _POSIX_TRACE	-1 +#define _POSIX_TRACE_EVENT_FILTER	-1 +#define _POSIX_TRACE_INHERIT	-1 +#define _POSIX_TRACE_LOG	-1 + +/* Typed memory objects are not available.  */ +#define _POSIX_TYPED_MEMORY_OBJECTS	-1 + +/* No support for priority inheritance or protection so far.  */ +#define _POSIX_THREAD_PRIO_INHERIT	-1 +#define _POSIX_THREAD_PRIO_PROTECT	-1 + +#endif /* posix_opt.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/close.S b/libpthread/nptl/sysdeps/unix/sysv/linux/close.S new file mode 100644 index 000000000..cf50a1eae --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/close.S @@ -0,0 +1,21 @@ +#include <sysdep-cancel.h> + +/* +extern int __close_nocancel (int) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + + +PSEUDO (__libc_close, close, 1) +ret +PSEUDO_END(__libc_close) + +libc_hidden_def (__close_nocancel) +libc_hidden_def (__libc_close) +weak_alias (__libc_close, __close) +libc_hidden_weak (__close) +weak_alias (__libc_close, close) +libc_hidden_weak (close) + + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/connect.S b/libpthread/nptl/sysdeps/unix/sysv/linux/connect.S new file mode 100644 index 000000000..441843fa0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/connect.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_connect +#error Missing definition of NR_connect needed for cancellation. +#endif +PSEUDO (__libc_connect, connect, 3) +ret +PSEUDO_END(__libc_connect) +libc_hidden_def (__libc_connect) +weak_alias (__libc_connect, __connect) +libc_hidden_weak (__connect) +weak_alias (__libc_connect, connect) +libc_hidden_weak (connect) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/creat.S b/libpthread/nptl/sysdeps/unix/sysv/linux/creat.S new file mode 100644 index 000000000..cd0e1b879 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/creat.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_creat, creat, 2) +ret +PSEUDO_END(__libc_creat) +libc_hidden_def (__libc_creat) +weak_alias (__libc_creat, creat) +libc_hidden_weak (creat) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/createthread.c new file mode 100644 index 000000000..9149efe58 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/createthread.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>. + +   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.  */ + +/* Value passed to 'clone' for initialization of the thread register.  */ +#define TLS_VALUE pd + +/* Get the real implementation.	 */ +#include <sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/exit-thread.S b/libpthread/nptl/sysdeps/unix/sysv/linux/exit-thread.S new file mode 100644 index 000000000..bb996fecf --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/exit-thread.S @@ -0,0 +1,23 @@ +/* Copyright (C) 1991,92,97,99,2002 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 <sysdep.h> + +PSEUDO (__exit_thread, exit, 1) +	/* Shouldn't get here.  */ +PSEUDO_END(__exit_thread) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c new file mode 100644 index 000000000..a84b5c237 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c @@ -0,0 +1,220 @@ +/* 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 <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sysdep.h> +#include <tls.h> +#include "fork.h" +#include <hp-timing.h> +#include <ldsodefs.h> +#include <atomic.h> +#include <errno.h> + +unsigned long int *__fork_generation_pointer; + + + +/* The single linked list of all currently registered for handlers.  */ +struct fork_handler *__fork_handlers; + + +static void +fresetlockfiles (void) +{ +  FILE *fp; +#ifdef __USE_STDIO_FUTEXES__ +  for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) +    STDIO_INIT_MUTEX(fp->__lock); +#else +  pthread_mutexattr_t attr; + +  pthread_mutexattr_init(&attr); +  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); + +  for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) +    pthread_mutex_init(&fp->__lock, &attr); + +  pthread_mutexattr_destroy(&attr); +#endif +} + +extern __typeof(fork) __libc_fork; +pid_t __libc_fork (void) +{ +  pid_t pid; +  struct used_handler +  { +    struct fork_handler *handler; +    struct used_handler *next; +  } *allp = NULL; + +  /* Run all the registered preparation handlers.  In reverse order. +     While doing this we build up a list of all the entries.  */ +  struct fork_handler *runp; +  while ((runp = __fork_handlers) != NULL) +    { +      unsigned int oldval = runp->refcntr; + +      if (oldval == 0) +	/* This means some other thread removed the list just after +	   the pointer has been loaded.  Try again.  Either the list +	   is empty or we can retry it.  */ +	continue; + +      /* Bump the reference counter.  */ +      if (atomic_compare_and_exchange_bool_acq (&__fork_handlers->refcntr, +						oldval + 1, oldval)) +	/* The value changed, try again.  */ +	continue; + +      /* We bumped the reference counter for the first entry in the +	 list.  That means that none of the following entries will +	 just go away.  The unloading code works in the order of the +	 list. + +         While executing the registered handlers we are building a +         list of all the entries so that we can go backward later on.  */ +      while (1) +	{ +	  /* Execute the handler if there is one.  */ +	  if (runp->prepare_handler != NULL) +	    runp->prepare_handler (); + +	  /* Create a new element for the list.  */ +	  struct used_handler *newp +	    = (struct used_handler *) alloca (sizeof (*newp)); +	  newp->handler = runp; +	  newp->next = allp; +	  allp = newp; + +	  /* Advance to the next handler.  */ +	  runp = runp->next; +	  if (runp == NULL) +	    break; + +	  /* Bump the reference counter for the next entry.  */ +	  atomic_increment (&runp->refcntr); +	} + +      /* We are done.  */ +      break; +    } + +  __UCLIBC_IO_MUTEX_LOCK_CANCEL_UNSAFE(_stdio_openlist_add_lock); + +#ifndef NDEBUG +  pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid); +#endif + +  /* We need to prevent the getpid() code to update the PID field so +     that, if a signal arrives in the child very early and the signal +     handler uses getpid(), the value returned is correct.  */ +  pid_t parentpid = THREAD_GETMEM (THREAD_SELF, pid); +  THREAD_SETMEM (THREAD_SELF, pid, -parentpid); + +#ifdef ARCH_FORK +  pid = ARCH_FORK (); +#else +# error "ARCH_FORK must be defined so that the CLONE_SETTID flag is used" +  pid = INLINE_SYSCALL (fork, 0); +#endif + + +  if (pid == 0) +    { +      struct pthread *self = THREAD_SELF; + +      assert (THREAD_GETMEM (self, tid) != ppid); + +      if (__fork_generation_pointer != NULL) +	*__fork_generation_pointer += 4; + +      /* Adjust the PID field for the new process.  */ +      THREAD_SETMEM (self, pid, THREAD_GETMEM (self, tid)); + +#if HP_TIMING_AVAIL +      /* The CPU clock of the thread and process have to be set to zero.  */ +      hp_timing_t now; +      HP_TIMING_NOW (now); +      THREAD_SETMEM (self, cpuclock_offset, now); +      GL(dl_cpuclock_offset) = now; +#endif + +      /* Reset the file list.  These are recursive mutexes.  */ +      fresetlockfiles (); + +      /* Reset locks in the I/O code.  */ +      STDIO_INIT_MUTEX(_stdio_openlist_add_lock); + +      /* Run the handlers registered for the child.  */ +      while (allp != NULL) +	{ +	  if (allp->handler->child_handler != NULL) +	    allp->handler->child_handler (); + +	  /* Note that we do not have to wake any possible waiter. +	     This is the only thread in the new process.  */ +	  --allp->handler->refcntr; + +	  /* XXX We could at this point look through the object pool +	     and mark all objects not on the __fork_handlers list as +	     unused.  This is necessary in case the fork() happened +	     while another thread called dlclose() and that call had +	     to create a new list.  */ + +	  allp = allp->next; +	} + +      /* Initialize the fork lock.  */ +      __fork_lock = (lll_lock_t) LLL_LOCK_INITIALIZER; +    } +  else +    { +      assert (THREAD_GETMEM (THREAD_SELF, tid) == ppid); + +      /* Restore the PID value.  */ +      THREAD_SETMEM (THREAD_SELF, pid, parentpid); + +      /* We execute this even if the 'fork' call failed.  */ +      __UCLIBC_IO_MUTEX_UNLOCK_CANCEL_UNSAFE(_stdio_openlist_add_lock); + +      /* Run the handlers registered for the parent.  */ +      while (allp != NULL) +	{ +	  if (allp->handler->parent_handler != NULL) +	    allp->handler->parent_handler (); + +	  if (atomic_decrement_and_test (&allp->handler->refcntr) +	      && allp->handler->need_signal) +	    lll_futex_wake (allp->handler->refcntr, 1); + +	  allp = allp->next; +	} +    } + +  return pid; +} +weak_alias(__libc_fork,__fork) +libc_hidden_proto(fork) +weak_alias(__libc_fork,fork) +libc_hidden_weak(fork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/fork.h b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.h new file mode 100644 index 000000000..bcdf6217c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.h @@ -0,0 +1,56 @@ +/* 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 <lowlevellock.h> + +/* The fork generation counter, defined in libpthread.  */ +extern unsigned long int __fork_generation attribute_hidden; + +/* Pointer to the fork generation counter in the thread library.  */ +extern unsigned long int *__fork_generation_pointer attribute_hidden; + +/* Lock to protect allocation and deallocation of fork handlers.  */ +extern lll_lock_t __fork_lock attribute_hidden; + +/* Elements of the fork handler lists.  */ +struct fork_handler +{ +  struct fork_handler *next; +  void (*prepare_handler) (void); +  void (*parent_handler) (void); +  void (*child_handler) (void); +  void *dso_handle; +  unsigned int refcntr; +  int need_signal; +}; + +/* The single linked list of all currently registered for handlers.  */ +extern struct fork_handler *__fork_handlers; + + +/* Function to call to unregister fork handlers.  */ +extern void __unregister_atfork (void *dso_handle) attribute_hidden; +#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle) + + +/* C library side function to register new fork handlers.  */ +extern int __register_atfork (void (*__prepare) (void), +			      void (*__parent) (void), +			      void (*__child) (void), +			      void *dso_handle); diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/getpid.c b/libpthread/nptl/sysdeps/unix/sysv/linux/getpid.c new file mode 100644 index 000000000..9a4f51c9d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/getpid.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 <unistd.h> +#include <tls.h> +#include <sysdep.h> + + +extern __typeof(getpid) __getpid; +#ifndef NOT_IN_libc +static __always_inline pid_t really_getpid (pid_t oldval); + +static __always_inline pid_t really_getpid (pid_t oldval) +{ +  if (__builtin_expect (oldval == 0, 1)) +    { +      pid_t selftid = THREAD_GETMEM (THREAD_SELF, tid); +      if (__builtin_expect (selftid != 0, 1)) +	return selftid; +    } + +  INTERNAL_SYSCALL_DECL (err); +  pid_t result = INTERNAL_SYSCALL (getpid, err, 0); + +  /* We do not set the PID field in the TID here since we might be +     called from a signal handler while the thread executes fork.  */ +  if (oldval == 0) +    THREAD_SETMEM (THREAD_SELF, tid, result); +  return result; +} +#endif + +pid_t __getpid (void) +{ +#ifdef NOT_IN_libc +  INTERNAL_SYSCALL_DECL (err); +  pid_t result = INTERNAL_SYSCALL (getpid, err, 0); +#else +  pid_t result = THREAD_GETMEM (THREAD_SELF, pid); +  if (__builtin_expect (result <= 0, 0)) +    result = really_getpid (result); +#endif +  return result; +} +libc_hidden_proto(getpid) +weak_alias(__getpid, getpid) +libc_hidden_weak(getpid) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile @@ -0,0 +1,13 @@ +# 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. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile.arch new file mode 100644 index 000000000..740ee7fcb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile.arch @@ -0,0 +1,74 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/i386 +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/i386 + + +libpthread_SSRC = pt-vfork.S clone.S pthread_spin_unlock.S pthread_once.S +libpthread_CSRC = pthread_spin_init.c pt-__syscall_error.c + +libc_a_CSRC = fork.c +libc_a_SSRC = clone.S vfork.S + +libpthread_SSRC += i486/lowlevellock.S i486/pthread_barrier_wait.S i486/pthread_cond_signal.S i486/pthread_cond_broadcast.S \ +		   i486/sem_post.S i486/sem_timedwait.S \ +		   i486/sem_trywait.S i486/sem_wait.S i486/pthread_rwlock_rdlock.S i486/pthread_rwlock_wrlock.S \ +		   i486/pthread_rwlock_timedrdlock.S i486/pthread_rwlock_timedwrlock.S i486/pthread_rwlock_unlock.S +#i486/pthread_cond_timedwait.S i486/pthread_cond_wait.S + +libc_a_SSRC += i486/libc-lowlevellock.S + + +CFLAGS-OMIT-fork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-lowlevellock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_once.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_spin_unlock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD + + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT +ASFLAGS-libc-lowlevellock.S = -D_LIBC_REENTRANT + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +#Needed to use the correct SYSCALL_ERROR_HANDLER +ASFLAGS-clone.S += -DUSE___THREAD +ASFLAGS-vfork.S += -DUSE___THREAD +endif + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) +LINUX_ARCH_OBJ+=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJS) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) +LIBC_LINUX_ARCH_OBJ+=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libc_a_SSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=nptl_linux_arch_clean + +nptl_linux_arch_clean: +	$(do_rm) $(addprefix $(LINUX_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h new file mode 100644 index 000000000..0ec6e5534 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h @@ -0,0 +1,170 @@ +/* Copyright (C) 2002, 2003, 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.  */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H	1 + +#define __SIZEOF_PTHREAD_ATTR_T 36 +#define __SIZEOF_PTHREAD_MUTEX_T 24 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_COND_COMPAT_T 12 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 32 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 20 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + + +/* Thread identifiers.  The structure of the attribute type is not +   exposed on purpose.  */ +typedef unsigned long int pthread_t; + + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_ATTR_T]; +  long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_slist +{ +  struct __pthread_internal_slist *__next; +} __pthread_slist_t; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is not exposed on purpose.  */ +typedef union +{ +  struct __pthread_mutex_s +  { +    int __lock; +    unsigned int __count; +    int __owner; +    /* KIND must stay at this position in the structure to maintain +       binary compatibility.  */ +    int __kind; +    unsigned int __nusers; +    __extension__ union +    { +      int __spins; +      __pthread_slist_t __list; +    }; +  } __data; +  char __size[__SIZEOF_PTHREAD_MUTEX_T]; +  long int __align; +} pthread_mutex_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; +  long int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling.  The structure of +   the attribute type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __futex; +    __extension__ unsigned long long int __total_seq; +    __extension__ unsigned long long int __wakeup_seq; +    __extension__ unsigned long long int __woken_seq; +    void *__mutex; +    unsigned int __nwaiters; +    unsigned int __broadcast_seq; +  } __data; +  char __size[__SIZEOF_PTHREAD_COND_T]; +  __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_CONDATTR_T]; +  long int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling.  The +   structure of the attribute type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +    int __writer; +  } __data; +  char __size[__SIZEOF_PTHREAD_RWLOCK_T]; +  long int __align; +} pthread_rwlock_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; +  long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type.  */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type.  The structure of the type is +   deliberately not exposed.  */ +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIER_T]; +  long int __align; +} pthread_barrier_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; +  int __align; +} pthread_barrierattr_t; +#endif + + +/* Extra attributes for the cleanup functions.  */ +#define __cleanup_fct_attribute __attribute ((regparm (1))) + +#endif	/* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h new file mode 100644 index 000000000..e6c5d845c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h @@ -0,0 +1,39 @@ +/* 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 _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + + +#define __SIZEOF_SEM_T	16 + + +/* Value returned if `sem_open' failed.  */ +#define SEM_FAILED      ((sem_t *) 0) + +/* Maximum value the semaphore can have.  */ +#define SEM_VALUE_MAX   (2147483647) + + +typedef union +{ +  char __size[__SIZEOF_SEM_T]; +  long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/clone.S new file mode 100644 index 000000000..9c7c46467 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <libc/sysdeps/linux/i386/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/createthread.c new file mode 100644 index 000000000..35719be96 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/createthread.c @@ -0,0 +1,49 @@ +/* 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.  */ + +/* The "thread register" gets initialized from a segment descriptor. +   Initialize such a descriptor first.  */ +#define PREPARE_CREATE \ +  union user_desc_init desc;						      \ +									      \ +  /* Describe the thread-local storage segment.  */			      \ +									      \ +  /* The 'entry_number' field.  The first three bits of the segment	      \ +     register value select the GDT, ignore them.  We get the index	      \ +     from the value of the %gs register in the current thread.  */	      \ +  desc.vals[0] = TLS_GET_GS () >> 3;					      \ +  /* The 'base_addr' field.  Pointer to the TCB.  */			      \ +  desc.vals[1] = (unsigned long int) pd;				      \ +  /* The 'limit' field.  We use 4GB which is 0xfffff pages.  */		      \ +  desc.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 */							      \ +  desc.vals[3] = 0x51 + +/* Value passed to 'clone' for initialization of the thread register.  */ +#define TLS_VALUE &desc.desc + + +/* Get the real implementation.  */ +#include <sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/fork.c new file mode 100644 index 000000000..b874538b3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/fork.c @@ -0,0 +1,31 @@ +/* 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 <sched.h> +#include <signal.h> +#include <stdio.h> +#include <sysdep.h> +#include <tls.h> + +#define ARCH_FORK() \ +  INLINE_SYSCALL (clone, 5,						      \ +		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,     \ +		  NULL, NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S new file mode 100644 index 000000000..223b11108 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S @@ -0,0 +1,30 @@ +/* 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.  */ + +/* In libc.so we do not unconditionally use the lock prefix.  Only if +   the application is using threads.  */ +#ifndef UP +# define LOCK \ +	cmpl	$0, %gs:MULTIPLE_THREADS_OFFSET; 			      \ +	je,pt	0f;							      \ +	lock;								      \ +0: +#endif + +#include "lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S new file mode 100644 index 000000000..955e119ab --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S @@ -0,0 +1,283 @@ +/* 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 <sysdep.h> +#include <pthread-errnos.h> + +	.text + +#ifndef LOCK +# ifdef UP +#  define LOCK +# else +#  define LOCK lock +# endif +#endif + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.globl	__lll_mutex_lock_wait +	.type	__lll_mutex_lock_wait,@function +	.hidden	__lll_mutex_lock_wait +	.align	16 +__lll_mutex_lock_wait: +	pushl	%edx +	pushl	%ebx +	pushl	%esi + +	movl	$2, %edx +	movl	%ecx, %ebx +	xorl	%esi, %esi	/* No timeout.  */ +	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */ + +	cmpl	%edx, %eax	/* NB:	 %edx == 2 */ +	jne 2f + +1:	movl	$SYS_futex, %eax +	ENTER_KERNEL + +2:	movl	%edx, %eax +	xchgl	%eax, (%ebx)	/* NB:	 lock is implied */ + +	testl	%eax, %eax +	jnz,pn	1b + +	popl	%esi +	popl	%ebx +	popl	%edx +	ret +	.size	__lll_mutex_lock_wait,.-__lll_mutex_lock_wait + + +#ifdef NOT_IN_libc +	.globl	__lll_mutex_timedlock_wait +	.type	__lll_mutex_timedlock_wait,@function +	.hidden	__lll_mutex_timedlock_wait +	.align	16 +__lll_mutex_timedlock_wait: +	/* Check for a valid timeout value.  */ +	cmpl	$1000000000, 4(%edx) +	jae	3f + +	pushl	%edi +	pushl	%esi +	pushl	%ebx +	pushl	%ebp + +	/* Stack frame for the timespec and timeval structs.  */ +	subl	$8, %esp + +	movl	%ecx, %ebp +	movl	%edx, %edi + +1: +	/* Get current time.  */ +	movl	%esp, %ebx +	xorl	%ecx, %ecx +	movl	$SYS_gettimeofday, %eax +	ENTER_KERNEL + +	/* Compute relative timeout.  */ +	movl	4(%esp), %eax +	movl	$1000, %edx +	mul	%edx		/* Milli seconds to nano seconds.  */ +	movl	(%edi), %ecx +	movl	4(%edi), %edx +	subl	(%esp), %ecx +	subl	%eax, %edx +	jns	4f +	addl	$1000000000, %edx +	subl	$1, %ecx +4:	testl	%ecx, %ecx +	js	5f		/* Time is already up.  */ + +	/* Store relative timeout.  */ +	movl	%ecx, (%esp) +	movl	%edx, 4(%esp) + +	movl	%ebp, %ebx + +	movl	$1, %eax +	movl	$2, %edx +	LOCK +	cmpxchgl %edx, (%ebx) + +	testl	%eax, %eax +	je	8f + +	/* Futex call.  */ +	movl	%esp, %esi +	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */ +	movl	$SYS_futex, %eax +	ENTER_KERNEL +	movl	%eax, %ecx + +8:				/* NB: %edx == 2 */ +	xorl	%eax, %eax +	LOCK +	cmpxchgl %edx, (%ebx) + +	jnz	7f + +6:	addl	$8, %esp +	popl	%ebp +	popl	%ebx +	popl	%esi +	popl	%edi +	ret + +	/* Check whether the time expired.  */ +7:	cmpl	$-ETIMEDOUT, %ecx +	je	5f + +	/* Make sure the current holder knows we are going to sleep.  */ +	movl	%edx, %eax +	xchgl	%eax, (%ebx) +	testl	%eax, %eax +	jz	6b +	jmp	1b + +3:	movl	$EINVAL, %eax +	ret + +5:	movl	$ETIMEDOUT, %eax +	jmp	6b +	.size	__lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait +#endif + + +#ifdef NOT_IN_libc +	.globl	lll_unlock_wake_cb +	.type	lll_unlock_wake_cb,@function +	.hidden	lll_unlock_wake_cb +	.align	16 +lll_unlock_wake_cb: +	pushl	%ebx +	pushl	%ecx +	pushl	%edx + +	movl	20(%esp), %ebx +	LOCK +	subl	$1, (%ebx) +	je	1f + +	movl	$FUTEX_WAKE, %ecx +	movl	$1, %edx	/* Wake one thread.  */ +	movl	$SYS_futex, %eax +	movl	$0, (%ebx) +	ENTER_KERNEL + +1:	popl	%edx +	popl	%ecx +	popl	%ebx +	ret +	.size	lll_unlock_wake_cb,.-lll_unlock_wake_cb +#endif + + +	.globl	__lll_mutex_unlock_wake +	.type	__lll_mutex_unlock_wake,@function +	.hidden	__lll_mutex_unlock_wake +	.align	16 +__lll_mutex_unlock_wake: +	pushl	%ebx +	pushl	%ecx +	pushl	%edx + +	movl	%eax, %ebx +	movl	$0, (%eax) +	movl	$FUTEX_WAKE, %ecx +	movl	$1, %edx	/* Wake one thread.  */ +	movl	$SYS_futex, %eax +	ENTER_KERNEL + +	popl	%edx +	popl	%ecx +	popl	%ebx +	ret +	.size	__lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake + + +#ifdef NOT_IN_libc +	.globl	__lll_timedwait_tid +	.type	__lll_timedwait_tid,@function +	.hidden	__lll_timedwait_tid +	.align	16 +__lll_timedwait_tid: +	pushl	%edi +	pushl	%esi +	pushl	%ebx +	pushl	%ebp + +	movl	%eax, %ebp +	movl	%edx, %edi +	subl	$8, %esp + +	/* Get current time.  */ +2:	movl	%esp, %ebx +	xorl	%ecx, %ecx +	movl	$SYS_gettimeofday, %eax +	ENTER_KERNEL + +	/* Compute relative timeout.  */ +	movl	4(%esp), %eax +	movl	$1000, %edx +	mul	%edx		/* Milli seconds to nano seconds.  */ +	movl	(%edi), %ecx +	movl	4(%edi), %edx +	subl	(%esp), %ecx +	subl	%eax, %edx +	jns	5f +	addl	$1000000000, %edx +	subl	$1, %ecx +5:	testl	%ecx, %ecx +	js	6f		/* Time is already up.  */ + +	movl	%ecx, (%esp)	/* Store relative timeout.  */ +	movl	%edx, 4(%esp) + +	movl	(%ebp), %edx +	testl	%edx, %edx +	jz	4f + +	movl	%esp, %esi +	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */ +	movl	%ebp, %ebx +	movl	$SYS_futex, %eax +	ENTER_KERNEL + +	cmpl	$0, (%ebx) +	jne	1f +4:	xorl	%eax, %eax + +3:	addl	$8, %esp +	popl	%ebp +	popl	%ebx +	popl	%esi +	popl	%edi +	ret + +1:	cmpl	$-ETIMEDOUT, %eax +	jne	2b +6:	movl	$ETIMEDOUT, %eax +	jmp	3b +	.size	__lll_timedwait_tid,.-__lll_timedwait_tid +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S new file mode 100644 index 000000000..2af9e38cd --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S @@ -0,0 +1,162 @@ +/* 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 <sysdep.h> +#include <lowlevelbarrier.h> + +#define FUTEX_WAIT	0 +#define FUTEX_WAKE	1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	pthread_barrier_wait +	.type	pthread_barrier_wait,@function +	.align	16 +pthread_barrier_wait: +	pushl	%ebx + +	movl	8(%esp), %ebx + +	/* Get the mutex.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +	cmpxchgl %edx, MUTEX(%ebx) +	jnz	1f + +	/* One less waiter.  If this was the last one needed wake +	   everybody.  */ +2:	subl	$1, LEFT(%ebx) +	je	3f + +	/* There are more threads to come.  */ +	pushl	%esi + +#if CURR_EVENT == 0 +	movl	(%ebx), %edx +#else +	movl	CURR_EVENT(%ebx), %edx +#endif + +	/* Release the mutex.  */ +	LOCK +	subl	$1, MUTEX(%ebx) +	jne	6f + +	/* Wait for the remaining threads.  The call will return immediately +	   if the CURR_EVENT memory has meanwhile been changed.  */ +7:	xorl	%ecx, %ecx		/* movl $FUTEX_WAIT, %ecx */ +	xorl	%esi, %esi +8:	movl	$SYS_futex, %eax +	ENTER_KERNEL + +	/* Don't return on spurious wakeups.  The syscall does not change +	   any register except %eax so there is no need to reload any of +	   them.  */ +#if CURR_EVENT == 0 +	cmpl	%edx, (%ebx) +#else +	cmpl	%edx, CURR_EVENT(%ebx) +#endif +	je,pn	8b + +	/* Increment LEFT.  If this brings the count back to the +	   initial count unlock the object.  */ +	movl	$1, %edx +	movl	INIT_COUNT(%ebx), %ecx +	LOCK +	xaddl	%edx, LEFT(%ebx) +	subl	$1, %ecx +	cmpl	%ecx, %edx +	jne,pt	10f + +	/* Release the mutex.  We cannot release the lock before +	   waking the waiting threads since otherwise a new thread might +	   arrive and gets waken up, too.  */ +	LOCK +	subl	$1, MUTEX(%ebx) +	jne	9f + +	/* Note: %esi is still zero.  */ +10:	movl	%esi, %eax		/* != PTHREAD_BARRIER_SERIAL_THREAD */ + +	popl	%esi +	popl	%ebx +	ret + +	/* The necessary number of threads arrived.  */ +3: +#if CURR_EVENT == 0 +	addl	$1, (%ebx) +#else +	addl	$1, CURR_EVENT(%ebx) +#endif + +	/* Wake up all waiters.  The count is a signed number in the kernel +	   so 0x7fffffff is the highest value.  */ +	movl	$0x7fffffff, %edx +	movl	$FUTEX_WAKE, %ecx +	movl	$SYS_futex, %eax +	ENTER_KERNEL + +	/* Increment LEFT.  If this brings the count back to the +	   initial count unlock the object.  */ +	movl	$1, %edx +	movl	INIT_COUNT(%ebx), %ecx +	LOCK +	xaddl	%edx, LEFT(%ebx) +	subl	$1, %ecx +	cmpl	%ecx, %edx +	jne,pt	5f + +	/* Release the mutex.  We cannot release the lock before +	   waking the waiting threads since otherwise a new thread might +	   arrive and gets waken up, too.  */ +	LOCK +	subl	$1, MUTEX(%ebx) +	jne	4f + +5:	orl	$-1, %eax		/* == PTHREAD_BARRIER_SERIAL_THREAD */ + +	popl	%ebx +	ret + +1:	leal	MUTEX(%ebx), %ecx +	call	__lll_mutex_lock_wait +	jmp	2b + +4:	leal	MUTEX(%ebx), %eax +	call	__lll_mutex_unlock_wake +	jmp	5b + +6:	leal	MUTEX(%ebx), %eax +	call	__lll_mutex_unlock_wake +	jmp	7b + +9:	leal	MUTEX(%ebx), %eax +	call	__lll_mutex_unlock_wake +	jmp	10b +	.size	pthread_barrier_wait,.-pthread_barrier_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S new file mode 100644 index 000000000..6e8ffe6f6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S @@ -0,0 +1,161 @@ +/* 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 <sysdep.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 +#define FUTEX_CMP_REQUEUE	4 + +#define EINVAL			22 + + +	.text + +	/* int pthread_cond_broadcast (pthread_cond_t *cond) */ +	.globl	__pthread_cond_broadcast +	.type	__pthread_cond_broadcast, @function +	.align	16 +__pthread_cond_broadcast: + +	pushl	%ebx +	pushl	%esi +	pushl	%edi +	pushl	%ebp + +	movl	20(%esp), %ebx + +	/* Get internal lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %edx, (%ebx) +#else +	cmpxchgl %edx, cond_lock(%ebx) +#endif +	jnz	1f + +2:	addl	$cond_futex, %ebx +	movl	total_seq+4-cond_futex(%ebx), %eax +	movl	total_seq-cond_futex(%ebx), %ebp +	cmpl	wakeup_seq+4-cond_futex(%ebx), %eax +	ja	3f +	jb	4f +	cmpl	wakeup_seq-cond_futex(%ebx), %ebp +	jna	4f + +	/* Cause all currently waiting threads to recognize they are +	   woken up.  */ +3:	movl	%ebp, wakeup_seq-cond_futex(%ebx) +	movl	%eax, wakeup_seq-cond_futex+4(%ebx) +	movl	%ebp, woken_seq-cond_futex(%ebx) +	movl	%eax, woken_seq-cond_futex+4(%ebx) +	addl	%ebp, %ebp +	addl	$1, broadcast_seq-cond_futex(%ebx) +	movl	%ebp, (%ebx) + +	/* Get the address of the mutex used.  */ +	movl	dep_mutex-cond_futex(%ebx), %edi + +	/* Unlock.  */ +	LOCK +	subl	$1, cond_lock-cond_futex(%ebx) +	jne	7f + +	/* Don't use requeue for pshared condvars.  */ +8:	cmpl	$-1, %edi +	je	9f + +	/* Wake up all threads.  */ +	movl	$FUTEX_CMP_REQUEUE, %ecx +	movl	$SYS_futex, %eax +	movl	$0x7fffffff, %esi +	movl	$1, %edx +	/* Get the address of the futex involved.  */ +# if MUTEX_FUTEX != 0 +	addl	$MUTEX_FUTEX, %edi +# endif +/* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter. +	ENTER_KERNEL  */ +	int	$0x80 + +	/* For any kind of error, which mainly is EAGAIN, we try again +	   with WAKE.  The general test also covers running on old +	   kernels.  */ +	cmpl	$0xfffff001, %eax +	jae	9f + +10:	xorl	%eax, %eax +	popl	%ebp +	popl	%edi +	popl	%esi +	popl	%ebx +	ret + +	.align	16 +	/* Unlock.  */ +4:	LOCK +	subl	$1, cond_lock-cond_futex(%ebx) +	jne	5f + +6:	xorl	%eax, %eax +	popl	%ebp +	popl	%edi +	popl	%esi +	popl	%ebx +	ret + +	/* Initial locking failed.  */ +1: +#if cond_lock == 0 +	movl	%ebx, %ecx +#else +	leal	cond_lock(%ebx), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	2b + +	/* Unlock in loop requires waekup.  */ +5:	leal	cond_lock-cond_futex(%ebx), %eax +	call	__lll_mutex_unlock_wake +	jmp	6b + +	/* Unlock in loop requires waekup.  */ +7:	leal	cond_lock-cond_futex(%ebx), %eax +	call	__lll_mutex_unlock_wake +	jmp	8b + +9:	/* The futex requeue functionality is not available.  */ +	movl	$0x7fffffff, %edx +	movl	$FUTEX_WAKE, %ecx +	movl	$SYS_futex, %eax +	ENTER_KERNEL +	jmp	10b +	.size	__pthread_cond_broadcast, .-__pthread_cond_broadcast +weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S new file mode 100644 index 000000000..ec8217987 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S @@ -0,0 +1,111 @@ +/* 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 <sysdep.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 + +#define EINVAL			22 + + +	.text + +	/* int pthread_cond_signal (pthread_cond_t *cond) */ +	.globl	__pthread_cond_signal +	.type	__pthread_cond_signal, @function +	.align	16 +__pthread_cond_signal: + +	pushl	%ebx +	pushl	%edi + +	movl	12(%esp), %edi + +	/* Get internal lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %edx, (%edi) +#else +	cmpxchgl %edx, cond_lock(%edi) +#endif +	jnz	1f + +2:	leal	cond_futex(%edi), %ebx +	movl	total_seq+4(%edi), %eax +	movl	total_seq(%edi), %ecx +	cmpl	wakeup_seq+4(%edi), %eax +#if cond_lock != 0 +	/* Must use leal to preserve the flags.  */ +	leal	cond_lock(%edi), %edi +#endif +	ja	3f +	jb	4f +	cmpl	wakeup_seq-cond_futex(%ebx), %ecx +	jbe	4f + +	/* Bump the wakeup number.  */ +3:	addl	$1, wakeup_seq-cond_futex(%ebx) +	adcl	$0, wakeup_seq-cond_futex+4(%ebx) +	addl	$1, (%ebx) + +	/* Wake up one thread.  */ +	movl	$FUTEX_WAKE, %ecx +	movl	$SYS_futex, %eax +	movl	$1, %edx +	ENTER_KERNEL + +	/* Unlock.  Note that at this point %edi always points to +	   cond_lock.  */ +4:	LOCK +	subl	$1, (%edi) +	jne	5f + +6:	xorl	%eax, %eax +	popl	%edi +	popl	%ebx +	ret + +	/* Initial locking failed.  */ +1: +#if cond_lock == 0 +	movl	%edi, %ecx +#else +	leal	cond_lock(%edi), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	2b + +	/* Unlock in loop requires wakeup.  */ +5:	movl	%edi, %eax +	call	__lll_mutex_unlock_wake +	jmp	6b +	.size	__pthread_cond_signal, .-__pthread_cond_signal +weak_alias(__pthread_cond_signal, pthread_cond_signal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S new file mode 100644 index 000000000..b8f0d2e4b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S @@ -0,0 +1,465 @@ +/* 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 <sysdep.h> +#include <lowlevelcond.h> +#include <pthread-errnos.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, +			       const struct timespec *abstime)  */ +	.globl	__pthread_cond_timedwait +	.type	__pthread_cond_timedwait, @function +	.align	16 +__pthread_cond_timedwait: +.LSTARTCODE: +	pushl	%ebp +.Lpush_ebp: +	pushl	%edi +.Lpush_edi: +	pushl	%esi +.Lpush_esi: +	pushl	%ebx +.Lpush_ebx: + +	movl	20(%esp), %ebx +	movl	28(%esp), %ebp + +	cmpl	$1000000000, 4(%ebp) +	movl	$EINVAL, %eax +	jae	18f + +	/* Get internal lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %edx, (%ebx) +#else +	cmpxchgl %edx, cond_lock(%ebx) +#endif +	jnz	1f + +	/* Store the reference to the mutex.  If there is already a +	   different value in there this is a bad user bug.  */ +2:	cmpl	$-1, dep_mutex(%ebx) +	movl	24(%esp), %eax +	je	17f +	movl	%eax, dep_mutex(%ebx) + +	/* Unlock the mutex.  */ +17:	xorl	%edx, %edx +	call	__pthread_mutex_unlock_usercnt + +	testl	%eax, %eax +	jne	16f + +	addl	$1, total_seq(%ebx) +	adcl	$0, total_seq+4(%ebx) +	addl	$1, cond_futex(%ebx) +	addl	$(1 << clock_bits), cond_nwaiters(%ebx) + +#define FRAME_SIZE 24 +	subl	$FRAME_SIZE, %esp +.Lsubl: + +	/* Get and store current wakeup_seq value.  */ +	movl	wakeup_seq(%ebx), %edi +	movl	wakeup_seq+4(%ebx), %edx +	movl	broadcast_seq(%ebx), %eax +	movl	%edi, 12(%esp) +	movl	%edx, 16(%esp) +	movl	%eax, 20(%esp) + +	/* Get the current time.  */ +8:	movl	%ebx, %edx +#ifdef __NR_clock_gettime +	/* Get the clock number.  */ +	movl	cond_nwaiters(%ebx), %ebx +	andl	$((1 << clock_bits) - 1), %ebx +	/* Only clocks 0 and 1 are allowed so far.  Both are handled in the +	   kernel.  */ +	leal	4(%esp), %ecx +	movl	$__NR_clock_gettime, %eax +	ENTER_KERNEL +# ifndef __ASSUME_POSIX_TIMERS +	cmpl	$-ENOSYS, %eax +	je	19f +# endif +	movl	%edx, %ebx + +	/* Compute relative timeout.  */ +	movl	(%ebp), %ecx +	movl	4(%ebp), %edx +	subl	4(%esp), %ecx +	subl	8(%esp), %edx +#else +	/* Get the current time.  */ +	leal	4(%esp), %ebx +	xorl	%ecx, %ecx +	movl	$SYS_gettimeofday, %eax +	ENTER_KERNEL +	movl	%edx, %ebx + +	/* Compute relative timeout.  */ +	movl	8(%esp), %eax +	movl	$1000, %edx +	mul	%edx		/* Milli seconds to nano seconds.  */ +	movl	(%ebp), %ecx +	movl	4(%ebp), %edx +	subl	4(%esp), %ecx +	subl	%eax, %edx +#endif +	jns	12f +	addl	$1000000000, %edx +	subl	$1, %ecx +12:	testl	%ecx, %ecx +	movl	$-ETIMEDOUT, %esi +	js	6f + +	/* Store relative timeout.  */ +21:	movl	%ecx, 4(%esp) +	movl	%edx, 8(%esp) + +	movl	cond_futex(%ebx), %edi + +	/* Unlock.  */ +	LOCK +#if cond_lock == 0 +	subl	$1, (%ebx) +#else +	subl	$1, cond_lock(%ebx) +#endif +	jne	3f + +.LcleanupSTART: +4:	call	__pthread_enable_asynccancel +	movl	%eax, (%esp) + +	leal	4(%esp), %esi +	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */ +	movl	%edi, %edx +	addl	$cond_futex, %ebx +.Ladd_cond_futex: +	movl	$SYS_futex, %eax +	ENTER_KERNEL +	subl	$cond_futex, %ebx +.Lsub_cond_futex: +	movl	%eax, %esi + +	movl	(%esp), %eax +	call	__pthread_disable_asynccancel +.LcleanupEND: + +	/* Lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %edx, (%ebx) +#else +	cmpxchgl %edx, cond_lock(%ebx) +#endif +	jnz	5f + +6:	movl	broadcast_seq(%ebx), %eax +	cmpl	20(%esp), %eax +	jne	23f + +	movl	woken_seq(%ebx), %eax +	movl	woken_seq+4(%ebx), %ecx + +	movl	wakeup_seq(%ebx), %edi +	movl	wakeup_seq+4(%ebx), %edx + +	cmpl	16(%esp), %edx +	jne	7f +	cmpl	12(%esp), %edi +	je	15f + +7:	cmpl	%ecx, %edx +	jne	9f +	cmp	%eax, %edi +	jne	9f + +15:	cmpl	$-ETIMEDOUT, %esi +	jne	8b + +	addl	$1, wakeup_seq(%ebx) +	adcl	$0, wakeup_seq+4(%ebx) +	addl	$1, cond_futex(%ebx) +	movl	$ETIMEDOUT, %esi +	jmp	14f + +23:	xorl	%esi, %esi +	jmp	24f + +9:	xorl	%esi, %esi +14:	addl	$1, woken_seq(%ebx) +	adcl	$0, woken_seq+4(%ebx) + +24:	subl	$(1 << clock_bits), cond_nwaiters(%ebx) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	movl	total_seq(%ebx), %eax +	andl	total_seq+4(%ebx), %eax +	cmpl	$0xffffffff, %eax +	jne	25f +	movl	cond_nwaiters(%ebx), %eax +	andl	$~((1 << clock_bits) - 1), %eax +	jne	25f + +	addl	$cond_nwaiters, %ebx +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %ecx +	movl	$1, %edx +	ENTER_KERNEL +	subl	$cond_nwaiters, %ebx + +25:	LOCK +#if cond_lock == 0 +	subl	$1, (%ebx) +#else +	subl	$1, cond_lock(%ebx) +#endif +	jne	10f + +	/* Remove cancellation handler.  */ +11:	movl	24+FRAME_SIZE(%esp), %eax +	call	__pthread_mutex_cond_lock +	addl	$FRAME_SIZE, %esp +.Laddl: + +	/* We return the result of the mutex_lock operation if it failed.  */ +	testl	%eax, %eax +#ifdef HAVE_CMOV +	cmovel	%esi, %eax +#else +	jne	22f +	movl	%esi, %eax +22: +#endif + +18:	popl	%ebx +.Lpop_ebx: +	popl	%esi +.Lpop_esi: +	popl	%edi +.Lpop_edi: +	popl	%ebp +.Lpop_ebp: + +	ret + +	/* Initial locking failed.  */ +1: +.LSbl1: +#if cond_lock == 0 +	movl	%ebx, %ecx +#else +	leal	cond_lock(%ebx), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	2b + +	/* Unlock in loop requires wakeup.  */ +3: +.LSbl2: +#if cond_lock == 0 +	movl	%ebx, %eax +#else +	leal	cond_lock(%ebx), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	4b + +	/* Locking in loop failed.  */ +5: +#if cond_lock == 0 +	movl	%ebx, %ecx +#else +	leal	cond_lock(%ebx), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	6b + +	/* Unlock after loop requires wakeup.  */ +10: +#if cond_lock == 0 +	movl	%ebx, %eax +#else +	leal	cond_lock(%ebx), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	11b + +	/* The initial unlocking of the mutex failed.  */ +16: +.LSbl3: +	LOCK +#if cond_lock == 0 +	subl	$1, (%ebx) +#else +	subl	$1, cond_lock(%ebx) +#endif +	jne	18b + +	movl	%eax, %esi +#if cond_lock == 0 +	movl	%ebx, %eax +#else +	leal	cond_lock(%ebx), %eax +#endif +	call	__lll_mutex_unlock_wake + +	movl	%esi, %eax +	jmp	18b + +#if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS +	/* clock_gettime not available.  */ +.LSbl4: +19:	leal	4(%esp), %ebx +	xorl	%ecx, %ecx +	movl	$SYS_gettimeofday, %eax +	ENTER_KERNEL +	movl	%edx, %ebx + +	/* Compute relative timeout.  */ +	movl	8(%esp), %eax +	movl	$1000, %edx +	mul	%edx		/* Milli seconds to nano seconds.  */ +	movl	(%ebp), %ecx +	movl	4(%ebp), %edx +	subl	4(%esp), %ecx +	subl	%eax, %edx +	jns	20f +	addl	$1000000000, %edx +	subl	$1, %ecx +20:	testl	%ecx, %ecx +	movl	$-ETIMEDOUT, %esi +	js	6b +	jmp	21b +#endif +	.size	__pthread_cond_timedwait, .-__pthread_cond_timedwait +weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait) + + +	.type	__condvar_tw_cleanup2, @function +__condvar_tw_cleanup2: +	subl	$cond_futex, %ebx +.LSbl5: +	.size	__condvar_tw_cleanup2, .-__condvar_tw_cleanup2 +	.type	__condvar_tw_cleanup, @function +__condvar_tw_cleanup: +	movl	%eax, %esi + +	/* Get internal lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %edx, (%ebx) +#else +	cmpxchgl %edx, cond_lock(%ebx) +#endif +	jz	1f + +#if cond_lock == 0 +	movl	%ebx, %ecx +#else +	leal	cond_lock(%ebx), %ecx +#endif +	call	__lll_mutex_lock_wait + +1:	movl	broadcast_seq(%ebx), %eax +	cmpl	20(%esp), %eax +	jne	3f + +	addl	$1, wakeup_seq(%ebx) +	adcl	$0, wakeup_seq+4(%ebx) + +	addl	$1, cond_futex(%ebx) + +	addl	$1, woken_seq(%ebx) +	adcl	$0, woken_seq+4(%ebx) + +3:	subl	$(1 << clock_bits), cond_nwaiters(%ebx) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	xorl	%edi, %edi +	movl	total_seq(%ebx), %eax +	andl	total_seq+4(%ebx), %eax +	cmpl	$0xffffffff, %eax +	jne	4f +	movl	cond_nwaiters(%ebx), %eax +	andl	$~((1 << clock_bits) - 1), %eax +	jne	4f + +	addl	$cond_nwaiters, %ebx +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %ecx +	movl	$1, %edx +	ENTER_KERNEL +	subl	$cond_nwaiters, %ebx +	movl	$1, %edi + +4:	LOCK +#if cond_lock == 0 +	subl	$1, (%ebx) +#else +	subl	$1, cond_lock(%ebx) +#endif +	je	2f + +#if cond_lock == 0 +	movl	%ebx, %eax +#else +	leal	cond_lock(%ebx), %eax +#endif +	call	__lll_mutex_unlock_wake + +	/* Wake up all waiters to make sure no signal gets lost.  */ +2:	testl	%edi, %edi +	jnz	5f +	addl	$cond_futex, %ebx +	movl	$FUTEX_WAKE, %ecx +	movl	$SYS_futex, %eax +	movl	$0x7fffffff, %edx +	ENTER_KERNEL + +5:	movl	24+FRAME_SIZE(%esp), %eax +	call	__pthread_mutex_cond_lock + +	movl	%esi, (%esp) +.LcallUR: +	call	_Unwind_Resume +	hlt +.LENDCODE: +	.size	__condvar_tw_cleanup, .-__condvar_tw_cleanup diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S new file mode 100644 index 000000000..377a7340f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S @@ -0,0 +1,357 @@ +/* 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 <sysdep.h> +#include <lowlevelcond.h> +#include <tcb-offsets.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */ +	.globl	__pthread_cond_wait +	.type	__pthread_cond_wait, @function +	.align	16 +__pthread_cond_wait: +.LSTARTCODE: + +	pushl	%edi +.Lpush_edi: +	pushl	%esi +.Lpush_esi: +	pushl	%ebx +.Lpush_ebx: + +	xorl	%esi, %esi +	movl	16(%esp), %ebx + +	/* Get internal lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %edx, (%ebx) +#else +	cmpxchgl %edx, cond_lock(%ebx) +#endif +	jnz	1f + +	/* Store the reference to the mutex.  If there is already a +	   different value in there this is a bad user bug.  */ +2:	cmpl	$-1, dep_mutex(%ebx) +	movl	20(%esp), %eax +	je	15f +	movl	%eax, dep_mutex(%ebx) + +	/* Unlock the mutex.  */ +15:	xorl	%edx, %edx +	call	__pthread_mutex_unlock_usercnt + +	testl	%eax, %eax +	jne	12f + +	addl	$1, total_seq(%ebx) +	adcl	$0, total_seq+4(%ebx) +	addl	$1, cond_futex(%ebx) +	addl	$(1 << clock_bits), cond_nwaiters(%ebx) + +#define FRAME_SIZE 16 +	subl	$FRAME_SIZE, %esp +.Lsubl: + +	/* Get and store current wakeup_seq value.  */ +	movl	wakeup_seq(%ebx), %edi +	movl	wakeup_seq+4(%ebx), %edx +	movl	broadcast_seq(%ebx), %eax +	movl	%edi, 4(%esp) +	movl	%edx, 8(%esp) +	movl	%eax, 12(%esp) + +8:	movl	cond_futex(%ebx), %edi + +	/* Unlock.  */ +	LOCK +#if cond_lock == 0 +	subl	$1, (%ebx) +#else +	subl	$1, cond_lock(%ebx) +#endif +	jne	3f + +.LcleanupSTART: +4:	call	__pthread_enable_asynccancel +	movl	%eax, (%esp) + +	movl	%esi, %ecx	/* movl $FUTEX_WAIT, %ecx */ +	movl	%edi, %edx +	addl	$cond_futex, %ebx +.Ladd_cond_futex: +	movl	$SYS_futex, %eax +	ENTER_KERNEL +	subl	$cond_futex, %ebx +.Lsub_cond_futex: + +	movl	(%esp), %eax +	call	__pthread_disable_asynccancel +.LcleanupEND: + +	/* Lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %edx, (%ebx) +#else +	cmpxchgl %edx, cond_lock(%ebx) +#endif +	jnz	5f + +6:	movl	broadcast_seq(%ebx), %eax +	cmpl	12(%esp), %eax +	jne	16f + +	movl	woken_seq(%ebx), %eax +	movl	woken_seq+4(%ebx), %ecx + +	movl	wakeup_seq(%ebx), %edi +	movl	wakeup_seq+4(%ebx), %edx + +	cmpl	8(%esp), %edx +	jne	7f +	cmpl	4(%esp), %edi +	je	8b + +7:	cmpl	%ecx, %edx +	jne	9f +	cmp	%eax, %edi +	je	8b + +9:	addl	$1, woken_seq(%ebx) +	adcl	$0, woken_seq+4(%ebx) + +	/* Unlock */ +16:	subl	$(1 << clock_bits), cond_nwaiters(%ebx) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	movl	total_seq(%ebx), %eax +	andl	total_seq+4(%ebx), %eax +	cmpl	$0xffffffff, %eax +	jne	17f +	movl	cond_nwaiters(%ebx), %eax +	andl	$~((1 << clock_bits) - 1), %eax +	jne	17f + +	addl	$cond_nwaiters, %ebx +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %ecx +	movl	$1, %edx +	ENTER_KERNEL +	subl	$cond_nwaiters, %ebx + +17:	LOCK +#if cond_lock == 0 +	subl	$1, (%ebx) +#else +	subl	$1, cond_lock(%ebx) +#endif +	jne	10f + +11:	movl	20+FRAME_SIZE(%esp), %eax +	call	__pthread_mutex_cond_lock +	addl	$FRAME_SIZE, %esp +.Laddl: + +14:	popl	%ebx +.Lpop_ebx: +	popl	%esi +.Lpop_esi: +	popl	%edi +.Lpop_edi: + +	/* We return the result of the mutex_lock operation.  */ +	ret + +	/* Initial locking failed.  */ +1: +.LSbl1: +#if cond_lock == 0 +	movl	%ebx, %ecx +#else +	leal	cond_lock(%ebx), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	2b + +	/* Unlock in loop requires waekup.  */ +3: +.LSbl2: +#if cond_lock == 0 +	movl	%ebx, %eax +#else +	leal	cond_lock(%ebx), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	4b + +	/* Locking in loop failed.  */ +5: +#if cond_lock == 0 +	movl	%ebx, %ecx +#else +	leal	cond_lock(%ebx), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	6b + +	/* Unlock after loop requires wakeup.  */ +10: +#if cond_lock == 0 +	movl	%ebx, %eax +#else +	leal	cond_lock(%ebx), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	11b + +	/* The initial unlocking of the mutex failed.  */ +12: +.LSbl3: +	LOCK +#if cond_lock == 0 +	subl	$1, (%ebx) +#else +	subl	$1, cond_lock(%ebx) +#endif +	jne	14b + +	movl	%eax, %esi +#if cond_lock == 0 +	movl	%ebx, %eax +#else +	leal	cond_lock(%ebx), %eax +#endif +	call	__lll_mutex_unlock_wake + +	movl	%esi, %eax +	jmp	14b +	.size	__pthread_cond_wait, .-__pthread_cond_wait +weak_alias(__pthread_cond_wait, pthread_cond_wait) + + +	.type	__condvar_w_cleanup2, @function +__condvar_w_cleanup2: +	subl	$cond_futex, %ebx +	.size	__condvar_w_cleanup2, .-__condvar_w_cleanup2 +.LSbl4: +	.type	__condvar_w_cleanup, @function +__condvar_w_cleanup: +	movl	%eax, %esi + +	/* Get internal lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %edx, (%ebx) +#else +	cmpxchgl %edx, cond_lock(%ebx) +#endif +	jz	1f + +#if cond_lock == 0 +	movl	%ebx, %ecx +#else +	leal	cond_lock(%ebx), %ecx +#endif +	call	__lll_mutex_lock_wait + +1:	movl	broadcast_seq(%ebx), %eax +	cmpl	12(%esp), %eax +	jne	3f + +	addl	$1, wakeup_seq(%ebx) +	adcl	$0, wakeup_seq+4(%ebx) + +	addl	$1, cond_futex(%ebx) + +	addl	$1, woken_seq(%ebx) +	adcl	$0, woken_seq+4(%ebx) + +3:	subl	$(1 << clock_bits), cond_nwaiters(%ebx) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	xorl	%edi, %edi +	movl	total_seq(%ebx), %eax +	andl	total_seq+4(%ebx), %eax +	cmpl	$0xffffffff, %eax +	jne	4f +	movl	cond_nwaiters(%ebx), %eax +	andl	$~((1 << clock_bits) - 1), %eax +	jne	4f + +	addl	$cond_nwaiters, %ebx +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %ecx +	movl	$1, %edx +	ENTER_KERNEL +	subl	$cond_nwaiters, %ebx +	movl	$1, %edi + +4:	LOCK +#if cond_lock == 0 +	subl	$1, (%ebx) +#else +	subl	$1, cond_lock(%ebx) +#endif +	je	2f + +#if cond_lock == 0 +	movl	%ebx, %eax +#else +	leal	cond_lock(%ebx), %eax +#endif +	call	__lll_mutex_unlock_wake + +	/* Wake up all waiters to make sure no signal gets lost.  */ +2:	testl	%edi, %edi +	jnz	5f +	addl	$cond_futex, %ebx +	movl	$FUTEX_WAKE, %ecx +	movl	$SYS_futex, %eax +	movl	$0x7fffffff, %edx +	ENTER_KERNEL + +5:	movl	20+FRAME_SIZE(%esp), %eax +	call	__pthread_mutex_cond_lock + +	movl	%esi, (%esp) +.LcallUR: +	call	_Unwind_Resume +	hlt +.LENDCODE: +	.size	__condvar_w_cleanup, .-__condvar_w_cleanup diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S new file mode 100644 index 000000000..aec79f07e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S @@ -0,0 +1,175 @@ +/* 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> + + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	__pthread_rwlock_rdlock +	.type	__pthread_rwlock_rdlock,@function +	.align	16 +__pthread_rwlock_rdlock: +	pushl	%esi +	pushl	%ebx + +	xorl	%esi, %esi +	movl	12(%esp), %ebx + +	/* Get the lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %edx, (%ebx) +#else +	cmpxchgl %edx, MUTEX(%ebx) +#endif +	jnz	1f + +2:	movl	WRITER(%ebx), %eax +	testl	%eax, %eax +	jne	14f +	cmpl	$0, WRITERS_QUEUED(%ebx) +	je	5f +	cmpl	$0, FLAGS(%ebx) +	je	5f + +3:	addl	$1, READERS_QUEUED(%ebx) +	je	4f + +	movl	READERS_WAKEUP(%ebx), %edx + +	LOCK +#if MUTEX == 0 +	subl	$1, (%ebx) +#else +	subl	$1, MUTEX(%ebx) +#endif +	jne	10f + +11:	addl	$READERS_WAKEUP, %ebx +	movl	%esi, %ecx	/* movl $FUTEX_WAIT, %ecx */ +	movl	$SYS_futex, %eax +	ENTER_KERNEL + +	subl	$READERS_WAKEUP, %ebx + +	/* Reget the lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %edx, (%ebx) +#else +	cmpxchgl %edx, MUTEX(%ebx) +#endif +	jnz	12f + +13:	subl	$1, READERS_QUEUED(%ebx) +	jmp	2b + +5:	xorl	%ecx, %ecx +	addl	$1, NR_READERS(%ebx) +	je	8f +9:	LOCK +#if MUTEX == 0 +	subl	$1, (%ebx) +#else +	subl	$1, MUTEX(%ebx) +#endif +	jne	6f +7: + +	movl	%ecx, %eax +	popl	%ebx +	popl	%esi +	ret + +1: +#if MUTEX == 0 +	movl	%ebx, %ecx +#else +	leal	MUTEX(%ebx), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	2b + +14:	cmpl	%gs:TID, %eax +	jne	3b +	/* Deadlock detected.  */ +	movl	$EDEADLK, %ecx +	jmp	9b + +6: +#if MUTEX == 0 +	movl	%ebx, %eax +#else +	leal	MUTEX(%ebx), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	7b + +	/* Overflow.  */ +8:	subl	$1, NR_READERS(%ebx) +	movl	$EAGAIN, %ecx +	jmp	9b + +	/* Overflow.  */ +4:	subl	$1, READERS_QUEUED(%ebx) +	movl	$EAGAIN, %ecx +	jmp	9b + +10: +#if MUTEX == 0 +	movl	%ebx, %eax +#else +	leal	MUTEX(%ebx), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	11b + +12: +#if MUTEX == 0 +	movl	%ebx, %ecx +#else +	leal	MUTEX(%ebx), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	13b +	.size	__pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock + +	.globl	pthread_rwlock_rdlock +pthread_rwlock_rdlock = __pthread_rwlock_rdlock + +	.globl	__pthread_rwlock_rdlock_internal +__pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S new file mode 100644 index 000000000..3717d7ef5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S @@ -0,0 +1,214 @@ +/* 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> + + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	pthread_rwlock_timedrdlock +	.type	pthread_rwlock_timedrdlock,@function +	.align	16 +pthread_rwlock_timedrdlock: +	pushl	%esi +	pushl	%edi +	pushl	%ebx +	pushl	%ebp +	subl	$8, %esp + +	movl	28(%esp), %ebp +	movl	32(%esp), %edi + +	/* Get the lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %edx, (%ebp) +#else +	cmpxchgl %edx, MUTEX(%ebp) +#endif +	jnz	1f + +2:	movl	WRITER(%ebp), %eax +	testl	%eax, %eax +	jne	14f +	cmpl	$0, WRITERS_QUEUED(%ebp) +	je	5f +	cmpl	$0, FLAGS(%ebp) +	je	5f + +	/* Check the value of the timeout parameter.  */ +3:	cmpl	$1000000000, 4(%edi) +	jae	19f + +	addl	$1, READERS_QUEUED(%ebp) +	je	4f + +	movl	READERS_WAKEUP(%ebp), %esi + +	LOCK +#if MUTEX == 0 +	subl	$1, (%ebp) +#else +	subl	$1, MUTEX(%ebp) +#endif +	jne	10f + +	/* Get current time.  */ +11:	movl	%esp, %ebx +	xorl	%ecx, %ecx +	movl	$SYS_gettimeofday, %eax +	ENTER_KERNEL + +	/* Compute relative timeout.  */ +	movl	4(%esp), %eax +	movl	$1000, %edx +	mul	%edx		/* Milli seconds to nano seconds.  */ +	movl	(%edi), %ecx +	movl	4(%edi), %edx +	subl	(%esp), %ecx +	subl	%eax, %edx +	jns	15f +	addl	$1000000000, %edx +	subl	$1, %ecx +15:	testl	%ecx, %ecx +	js	16f		/* Time is already up.  */ + +	/* Futex call.  */ +	movl	%ecx, (%esp)	/* Store relative timeout.  */ +	movl	%edx, 4(%esp) +	movl	%esi, %edx +	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */ +	movl	%esp, %esi +	leal	READERS_WAKEUP(%ebp), %ebx +	movl	$SYS_futex, %eax +	ENTER_KERNEL +	movl	%eax, %ecx +17: + +	/* Reget the lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %edx, (%ebp) +#else +	cmpxchgl %edx, MUTEX(%ebp) +#endif +	jnz	12f + +13:	subl	$1, READERS_QUEUED(%ebp) +	cmpl	$-ETIMEDOUT, %ecx +	jne	2b + +18:	movl	$ETIMEDOUT, %ecx +	jmp	9f + + +5:	xorl	%ecx, %ecx +	addl	$1, NR_READERS(%ebp) +	je	8f +9:	LOCK +#if MUTEX == 0 +	subl	$1, (%ebp) +#else +	subl	$1, MUTEX(%ebp) +#endif +	jne	6f + +7:	movl	%ecx, %eax + +	addl	$8, %esp +	popl	%ebp +	popl	%ebx +	popl	%edi +	popl	%esi +	ret + +1: +#if MUTEX == 0 +	movl	%ebp, %ecx +#else +	leal	MUTEX(%ebp), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	2b + +14:	cmpl	%gs:TID, %eax +	jne	3b +	movl	$EDEADLK, %ecx +	jmp	9b + +6: +#if MUTEX == 0 +	movl	%ebp, %eax +#else +	leal	MUTEX(%ebp), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	7b + +	/* Overflow.  */ +8:	subl	$1, NR_READERS(%ebp) +	movl	$EAGAIN, %ecx +	jmp	9b + +	/* Overflow.  */ +4:	subl	$1, READERS_QUEUED(%ebp) +	movl	$EAGAIN, %ecx +	jmp	9b + +10: +#if MUTEX == 0 +	movl	%ebp, %eax +#else +	leal	MUTEX(%ebp), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	11b + +12: +#if MUTEX == 0 +	movl	%ebp, %ecx +#else +	leal	MUTEX(%ebp), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	13b + +16:	movl	$-ETIMEDOUT, %ecx +	jmp	17b + +19:	movl	$EINVAL, %ecx +	jmp	9b +	.size	pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S new file mode 100644 index 000000000..09c9e30ca --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S @@ -0,0 +1,207 @@ +/* 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> + + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	pthread_rwlock_timedwrlock +	.type	pthread_rwlock_timedwrlock,@function +	.align	16 +pthread_rwlock_timedwrlock: +	pushl	%esi +	pushl	%edi +	pushl	%ebx +	pushl	%ebp +	subl	$8, %esp + +	movl	28(%esp), %ebp +	movl	32(%esp), %edi + +	/* Get the lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %edx, (%ebp) +#else +	cmpxchgl %edx, MUTEX(%ebp) +#endif +	jnz	1f + +2:	movl	WRITER(%ebp), %eax +	testl	%eax, %eax +	jne	14f +	cmpl	$0, NR_READERS(%ebp) +	je	5f + +	/* Check the value of the timeout parameter.  */ +3:	cmpl	$1000000000, 4(%edi) +	jae	19f + +	addl	$1, WRITERS_QUEUED(%ebp) +	je	4f + +	movl	WRITERS_WAKEUP(%ebp), %esi + +	LOCK +#if MUTEX == 0 +	subl	$1, (%ebp) +#else +	subl	$1, MUTEX(%ebp) +#endif +	jne	10f + +	/* Get current time.  */ +11:	movl	%esp, %ebx +	xorl	%ecx, %ecx +	movl	$SYS_gettimeofday, %eax +	ENTER_KERNEL + +	/* Compute relative timeout.  */ +	movl	4(%esp), %eax +	movl	$1000, %edx +	mul	%edx		/* Milli seconds to nano seconds.  */ +	movl	(%edi), %ecx +	movl	4(%edi), %edx +	subl	(%esp), %ecx +	subl	%eax, %edx +	jns	15f +	addl	$1000000000, %edx +	subl	$1, %ecx +15:	testl	%ecx, %ecx +	js	16f		/* Time is already up.  */ + +	/* Futex call.  */ +	movl	%ecx, (%esp)	/* Store relative timeout.  */ +	movl	%edx, 4(%esp) +	movl	%esi, %edx +	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */ +	movl	%esp, %esi +	leal	WRITERS_WAKEUP(%ebp), %ebx +	movl	$SYS_futex, %eax +	ENTER_KERNEL +	movl	%eax, %ecx +17: + +	/* Reget the lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %edx, (%ebp) +#else +	cmpxchgl %edx, MUTEX(%ebp) +#endif +	jnz	12f + +13:	subl	$1, WRITERS_QUEUED(%ebp) +	cmpl	$-ETIMEDOUT, %ecx +	jne	2b + +18:	movl	$ETIMEDOUT, %ecx +	jmp	9f + + +5:	xorl	%ecx, %ecx +	movl	%gs:TID, %eax +	movl	%eax, WRITER(%ebp) +9:	LOCK +#if MUTEX == 0 +	subl	$1, (%ebp) +#else +	subl	$1, MUTEX(%ebp) +#endif +	jne	6f + +7:	movl	%ecx, %eax + +	addl	$8, %esp +	popl	%ebp +	popl	%ebx +	popl	%edi +	popl	%esi +	ret + +1: +#if MUTEX == 0 +	movl	%ebp, %ecx +#else +	leal	MUTEX(%ebp), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	2b + +14:	cmpl	%gs:TID, %eax +	jne	3b +20:	movl	$EDEADLK, %ecx +	jmp	9b + +6: +#if MUTEX == 0 +	movl	%ebp, %eax +#else +	leal	MUTEX(%ebp), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	7b + +	/* Overflow.  */ +4:	subl	$1, WRITERS_QUEUED(%ebp) +	movl	$EAGAIN, %ecx +	jmp	9b + +10: +#if MUTEX == 0 +	movl	%ebp, %eax +#else +	leal	MUTEX(%ebp), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	11b + +12: +#if MUTEX == 0 +	movl	%ebp, %ecx +#else +	leal	MUTEX(%ebp), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	13b + +16:	movl	$-ETIMEDOUT, %ecx +	jmp	17b + +19:	movl	$EINVAL, %ecx +	jmp	9b +	.size	pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S new file mode 100644 index 000000000..597c82fa8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S @@ -0,0 +1,140 @@ +/* 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 <sysdep.h> +#include <lowlevelrwlock.h> + + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	__pthread_rwlock_unlock +	.type	__pthread_rwlock_unlock,@function +	.align	16 +__pthread_rwlock_unlock: +	pushl	%ebx +	pushl	%edi + +	movl	12(%esp), %edi + +	/* Get the lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %edx, (%edi) +#else +	cmpxchgl %edx, MUTEX(%edi) +#endif +	jnz	1f + +2:	cmpl	$0, WRITER(%edi) +	jne	5f +	subl	$1, NR_READERS(%edi) +	jnz	6f + +5:	movl	$0, WRITER(%edi) + +	movl	$1, %ecx +	leal	WRITERS_WAKEUP(%edi), %ebx +	movl	%ecx, %edx +	cmpl	$0, WRITERS_QUEUED(%edi) +	jne	0f + +	/* If also no readers waiting nothing to do.  */ +	cmpl	$0, READERS_QUEUED(%edi) +	je	6f + +	movl	$0x7fffffff, %edx +	leal	READERS_WAKEUP(%edi), %ebx + +0:	addl	$1, (%ebx) +	LOCK +#if MUTEX == 0 +	subl	$1, (%edi) +#else +	subl	$1, MUTEX(%edi) +#endif +	jne	7f + +8:	movl	$SYS_futex, %eax +	ENTER_KERNEL + +	xorl	%eax, %eax +	popl	%edi +	popl	%ebx +	ret + +	.align	16 +6:	LOCK +#if MUTEX == 0 +	subl	$1, (%edi) +#else +	subl	$1, MUTEX(%edi) +#endif +	jne	3f + +4:	xorl	%eax, %eax +	popl	%edi +	popl	%ebx +	ret + +1: +#if MUTEX == 0 +	movl	%edi, %ecx +#else +	leal	MUTEX(%edx), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	2b + +3: +#if MUTEX == 0 +	movl	%edi, %eax +#else +	leal	MUTEX(%edx), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	4b + +7: +#if MUTEX == 0 +	movl	%edi, %eax +#else +	leal	MUTEX(%edx), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	8b + +	.size	__pthread_rwlock_unlock,.-__pthread_rwlock_unlock + +	.globl	pthread_rwlock_unlock +pthread_rwlock_unlock = __pthread_rwlock_unlock + +	.globl	__pthread_rwlock_unlock_internal +__pthread_rwlock_unlock_internal = __pthread_rwlock_unlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S new file mode 100644 index 000000000..bb384a267 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S @@ -0,0 +1,165 @@ +/* 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	__pthread_rwlock_wrlock +	.type	__pthread_rwlock_wrlock,@function +	.align	16 +__pthread_rwlock_wrlock: +	pushl	%esi +	pushl	%ebx + +	xorl	%esi, %esi +	movl	12(%esp), %ebx + +	/* Get the lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %edx, (%ebx) +#else +	cmpxchgl %edx, MUTEX(%ebx) +#endif +	jnz	1f + +2:	movl	WRITER(%ebx), %eax +	testl	%eax, %eax +	jne	14f +	cmpl	$0, NR_READERS(%ebx) +	je	5f + +3:	addl	$1, WRITERS_QUEUED(%ebx) +	je	4f + +	movl	WRITERS_WAKEUP(%ebx), %edx + +	LOCK +#if MUTEX == 0 +	subl	$1, (%ebx) +#else +	subl	$1, MUTEX(%ebx) +#endif +	jne	10f + +11:	addl	$WRITERS_WAKEUP, %ebx +	movl	%esi, %ecx	/* movl $FUTEX_WAIT, %ecx */ +	movl	$SYS_futex, %eax +	ENTER_KERNEL + +	subl	$WRITERS_WAKEUP, %ebx + +	/* Reget the lock.  */ +	movl	$1, %edx +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %edx, (%ebx) +#else +	cmpxchgl %edx, MUTEX(%ebx) +#endif +	jnz	12f + +13:	subl	$1, WRITERS_QUEUED(%ebx) +	jmp	2b + +5:	xorl	%ecx, %ecx +	movl	%gs:TID, %eax +	movl	%eax, WRITER(%ebx) +9:	LOCK +#if MUTEX == 0 +	subl	$1, (%ebx) +#else +	subl	$1, MUTEX(%ebx) +#endif +	jne	6f +7: + +	movl	%ecx, %eax +	popl	%ebx +	popl	%esi +	ret + +1: +#if MUTEX == 0 +	movl	%ebx, %ecx +#else +	leal	MUTEX(%ebx), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	2b + +14:	cmpl	%gs:TID	, %eax +	jne	3b +	movl	$EDEADLK, %ecx +	jmp	9b + +6: +#if MUTEX == 0 +	movl	%ebx, %eax +#else +	leal	MUTEX(%ebx), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	7b + +4:	subl	$1, WRITERS_QUEUED(%ebx) +	movl	$EAGAIN, %ecx +	jmp	9b + +10: +#if MUTEX == 0 +	movl	%ebx, %eax +#else +	leal	MUTEX(%ebx), %eax +#endif +	call	__lll_mutex_unlock_wake +	jmp	11b + +12: +#if MUTEX == 0 +	movl	%ebx, %ecx +#else +	leal	MUTEX(%ebx), %ecx +#endif +	call	__lll_mutex_lock_wait +	jmp	13b +	.size	__pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock + +	.globl	pthread_rwlock_wrlock +pthread_rwlock_wrlock = __pthread_rwlock_wrlock + +	.globl	__pthread_rwlock_wrlock_internal +__pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S new file mode 100644 index 000000000..de057c8b0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S @@ -0,0 +1,96 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <pthread-errnos.h> +#include <tls.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define FUTEX_WAKE		1 + + +	.text + +	.globl	__new_sem_post +	.type	__new_sem_post,@function +	.align	16 +__new_sem_post: +	pushl	%ebx + +	movl	8(%esp), %ebx +	movl	$1, %edx +	LOCK +	xaddl	%edx, (%ebx) + +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %ecx +	addl	$1, %edx +	ENTER_KERNEL + +	testl	%eax, %eax +	js	1f + +	xorl	%eax, %eax +	popl	%ebx +	ret + +1: +#ifdef PIC +	call	__x86.get_pc_thunk.bx +#else +	movl	$4f, %ebx +4: +#endif +	addl	$_GLOBAL_OFFSET_TABLE_, %ebx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS +	movl	errno@gotntpoff(%ebx), %edx +	addl	%gs:0, %edx +	movl	$EINVAL, (%edx) +# else +	movl	errno@gotntpoff(%ebx), %edx +	movl	$EINVAL, %gs:(%edx) +# endif +#else +	call	__errno_location@plt +	movl	$EINVAL, (%eax) +#endif + +	orl	$-1, %eax +	popl	%ebx +	ret +	.size	__new_sem_post,.-__new_sem_post +weak_alias(__new_sem_post, sem_post) + + +#ifdef PIC +	.section .gnu.linkonce.t.__x86.get_pc_thunk.bx,"ax",@progbits +	.globl	__x86.get_pc_thunk.bx +	.hidden	__x86.get_pc_thunk.bx +	.type	__x86.get_pc_thunk.bx,@function +__x86.get_pc_thunk.bx: +	movl (%esp), %ebx; +	ret +	.size	__x86.get_pc_thunk.bx,.-__x86.get_pc_thunk.bx +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S new file mode 100644 index 000000000..278b42ab3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S @@ -0,0 +1,193 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define FUTEX_WAKE		1 + + +	.text + +	.globl	sem_timedwait +	.type	sem_timedwait,@function +	.align	16 +	cfi_startproc +sem_timedwait: +	/* First check for cancellation.  */ +	movl	%gs:CANCELHANDLING, %eax +	andl	$0xfffffff9, %eax +	cmpl	$8, %eax +	je	10f + +	movl	4(%esp), %ecx + +	movl	(%ecx), %eax +2:	testl	%eax, %eax +	je,pn	1f + +	leal	-1(%eax), %edx +	LOCK +	cmpxchgl %edx, (%ecx) +	jne,pn	2b + +	xorl	%eax, %eax +	ret + +	/* Check whether the timeout value is valid.  */ +1:	pushl	%esi +	cfi_adjust_cfa_offset(4) +	pushl	%edi +	cfi_adjust_cfa_offset(4) +	pushl	%ebx +	cfi_adjust_cfa_offset(4) +	subl	$12, %esp +	cfi_adjust_cfa_offset(12) + +	movl	32(%esp), %edi +	cfi_offset(7, -12)		/* %edi */ + +	/* Check for invalid nanosecond field.  */ +	cmpl	$1000000000, 4(%edi) +	movl	$EINVAL, %esi +	cfi_offset(6, -8)		/* %esi */ +	jae	6f + +	cfi_offset(3, -16)		/* %ebx */ +7:	call	__pthread_enable_asynccancel +	movl	%eax, 8(%esp) + +	xorl	%ecx, %ecx +	movl	%esp, %ebx +	movl	%ecx, %edx +	movl	$SYS_gettimeofday, %eax +	ENTER_KERNEL + +	/* Compute relative timeout.  */ +	movl	4(%esp), %eax +	movl	$1000, %edx +	mul	%edx		/* Milli seconds to nano seconds.  */ +	movl	(%edi), %ecx +	movl	4(%edi), %edx +	subl	(%esp), %ecx +	subl	%eax, %edx +	jns	5f +	addl	$1000000000, %edx +	subl	$1, %ecx +5:	testl	%ecx, %ecx +	movl	$ETIMEDOUT, %esi +	js	6f		/* Time is already up.  */ + +	movl	%ecx, (%esp)	/* Store relative timeout.  */ +	movl	%edx, 4(%esp) +	movl	28(%esp), %ebx +	xorl	%ecx, %ecx +	movl	%esp, %esi +	movl	$SYS_futex, %eax +	xorl	%edx, %edx +	ENTER_KERNEL +	movl	%eax, %esi + +	movl	8(%esp), %eax +	call	__pthread_disable_asynccancel + +	testl	%esi, %esi +	je,pt	9f +	cmpl	$-EWOULDBLOCK, %esi +	jne	3f + +9:	movl	(%ebx), %eax +8:	testl	%eax, %eax +	je	7b + +	leal	-1(%eax), %ecx +	LOCK +	cmpxchgl %ecx, (%ebx) +	jne,pn	8b + +	addl	$12, %esp +	cfi_adjust_cfa_offset(-12) +	xorl	%eax, %eax +	popl	%ebx +	cfi_adjust_cfa_offset(-4) +	cfi_restore(3) +	popl	%edi +	cfi_adjust_cfa_offset(-4) +	cfi_restore(7) +	popl	%esi +	cfi_adjust_cfa_offset(-4) +	cfi_restore(6) +	ret + +	cfi_adjust_cfa_offset(24) +	cfi_offset(6, -8)		/* %esi */ +	cfi_offset(7, -12)	 	/* %edi */ +	cfi_offset(3, -16)		/* %ebx */ +3:	negl	%esi +6: +#ifdef PIC +	call	__x86.get_pc_thunk.bx +#else +	movl	$4f, %ebx +4: +#endif +	addl	$_GLOBAL_OFFSET_TABLE_, %ebx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS +	movl	errno@gotntpoff(%ebx), %edx +	addl	%gs:0, %edx +	movl	%esi, (%edx) +# else +	movl	errno@gotntpoff(%ebx), %edx +	movl	%esi, %gs:(%edx) +# endif +#else +	call	__errno_location@plt +	movl	%esi, (%eax) +#endif + +	addl	$12, %esp +	cfi_adjust_cfa_offset(-12) +	orl	$-1, %eax +	popl	%ebx +	cfi_adjust_cfa_offset(-4) +	cfi_restore(3) +	popl	%edi +	cfi_adjust_cfa_offset(-4) +	cfi_restore(7) +	popl	%esi +	cfi_adjust_cfa_offset(-4) +	cfi_restore(6) +	ret + +10:	/* Canceled.  */ +	movl	$0xffffffff, %gs:RESULT +	LOCK +	orl	$0x10, %gs:CANCELHANDLING +	movl	%gs:CLEANUP_JMP_BUF, %eax +	jmp	HIDDEN_JUMPTARGET (__pthread_unwind) +	cfi_endproc +	.size	sem_timedwait,.-sem_timedwait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S new file mode 100644 index 000000000..16c41b748 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S @@ -0,0 +1,85 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <pthread-errnos.h> +#include <tls.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +	.text + +	.globl	__new_sem_trywait +	.type	__new_sem_trywait,@function +	.align	16 +__new_sem_trywait: +	movl	4(%esp), %ecx + +	movl	(%ecx), %eax +2:	testl	%eax, %eax +	jz	1f + +	leal	-1(%eax), %edx +	LOCK +	cmpxchgl %edx, (%ecx) +	jne,pn	2b +	xorl	%eax, %eax +	ret + +1: +#ifdef PIC +	call	__x86.get_pc_thunk.cx +#else +	movl	$3f, %ecx +3: +#endif +	addl	$_GLOBAL_OFFSET_TABLE_, %ecx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS +	movl	errno@gotntpoff(%ecx), %edx +	addl	%gs:0, %edx +	movl	$EAGAIN, (%edx) +# else +	movl	errno@gotntpoff(%ecx), %edx +	movl	$EAGAIN, %gs:(%edx) +# endif +#else +	call	__errno_location@plt +	movl	$EAGAIN, (%eax) +#endif +	orl	$-1, %eax +	ret +	.size	__new_sem_trywait,.-__new_sem_trywait +weak_alias(__new_sem_trywait, sem_trywait) + + +#ifdef PIC +	.section .gnu.linkonce.t.__x86.get_pc_thunk.cx,"ax",@progbits +	.globl	__x86.get_pc_thunk.cx +	.hidden	__x86.get_pc_thunk.cx +	.type	__x86.get_pc_thunk.cx,@function +__x86.get_pc_thunk.cx: +	movl (%esp), %ecx; +	ret +	.size	__x86.get_pc_thunk.cx,.-__x86.get_pc_thunk.cx +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S new file mode 100644 index 000000000..053630617 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S @@ -0,0 +1,134 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include <tls.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define FUTEX_WAKE		1 + + +	.text + +	.globl	__new_sem_wait +	.type	__new_sem_wait,@function +	.align	16 +	cfi_startproc +__new_sem_wait: +	/* First check for cancellation.  */ +	movl	%gs:CANCELHANDLING, %eax +	andl	$0xfffffff9, %eax +	cmpl	$8, %eax +	je	5f + +	pushl	%ebx +	cfi_adjust_cfa_offset(4) +	pushl	%esi +	cfi_adjust_cfa_offset(4) +	subl	$4, %esp +	cfi_adjust_cfa_offset(4) + +	movl	16(%esp), %ebx +	cfi_offset(3, -8)		/* %ebx */ + +	cfi_offset(6, -12)		/* %esi */ +3:	movl	(%ebx), %eax +2:	testl	%eax, %eax +	je,pn	1f + +	leal	-1(%eax), %edx +	LOCK +	cmpxchgl %edx, (%ebx) +	jne,pn	2b +	xorl	%eax, %eax + +	movl	4(%esp), %esi +	cfi_restore(6) +	movl	8(%esp), %ebx +	cfi_restore(3) +	addl	$12, %esp +	cfi_adjust_cfa_offset(-12) +	ret + +	cfi_adjust_cfa_offset(8) +	cfi_offset(3, -8)		/* %ebx */ +	cfi_offset(6, -12)		/* %esi */ +1:	call	__pthread_enable_asynccancel +	movl	%eax, (%esp) + +	xorl	%esi, %esi +	movl	$SYS_futex, %eax +	movl	%esi, %ecx +	movl	%esi, %edx +	ENTER_KERNEL +	movl	%eax, %esi + +	movl	(%esp), %eax +	call	__pthread_disable_asynccancel + +	testl	%esi, %esi +	je	3b +	cmpl	$-EWOULDBLOCK, %esi +	je	3b +	negl	%esi +#ifdef PIC +	call	__x86.get_pc_thunk.bx +#else +	movl	$4f, %ebx +4: +#endif +	addl	$_GLOBAL_OFFSET_TABLE_, %ebx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS +	movl	errno@gotntpoff(%ebx), %edx +	addl	%gs:0, %edx +	movl	%esi, (%edx) +# else +	movl	errno@gotntpoff(%ebx), %edx +	movl	%esi, %gs:(%edx) +# endif +#else +	call	__errno_location@plt +	movl	%esi, (%eax) +#endif +	orl	$-1, %eax +	movl	4(%esp), %esi +	cfi_restore(6) +	movl	8(%esp), %ebx +	cfi_restore(3) +	addl	$12, %esp +	cfi_adjust_cfa_offset(-12) +	ret + +5:	/* Canceled.  */ +	movl	$0xffffffff, %gs:RESULT +	LOCK +	orl	$0x10, %gs:CANCELHANDLING +	movl	%gs:CLEANUP_JMP_BUF, %eax +	jmp	HIDDEN_JUMPTARGET (__pthread_unwind) +	cfi_endproc +	.size	__new_sem_wait,.-__new_sem_wait +weak_alias(__new_sem_wait, sem_wait) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S new file mode 100644 index 000000000..f567c1d6d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S @@ -0,0 +1 @@ +#include "../i486/libc-lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S new file mode 100644 index 000000000..e60dea89e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.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/lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S new file mode 100644 index 000000000..6d20b9a95 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.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_barrier_wait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S new file mode 100644 index 000000000..5e1024eab --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_cond_broadcast.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S new file mode 100644 index 000000000..da4e8cbab --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_cond_signal.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S new file mode 100644 index 000000000..c0131555b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_cond_timedwait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S new file mode 100644 index 000000000..9b57fbaca --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_cond_wait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S new file mode 100644 index 000000000..da2bc4704 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_rwlock_rdlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S new file mode 100644 index 000000000..0f2ec168b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_rwlock_timedrdlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S new file mode 100644 index 000000000..26501590a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_rwlock_timedwrlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S new file mode 100644 index 000000000..5515e4895 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_rwlock_unlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S new file mode 100644 index 000000000..04ac275f6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_rwlock_wrlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_post.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_post.S new file mode 100644 index 000000000..7317e1582 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_post.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/sem_post.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S new file mode 100644 index 000000000..f34539d56 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/sem_timedwait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S new file mode 100644 index 000000000..64145c2e3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/sem_trywait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S new file mode 100644 index 000000000..b3d462125 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/sem_wait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S new file mode 100644 index 000000000..f567c1d6d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S @@ -0,0 +1 @@ +#include "../i486/libc-lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S new file mode 100644 index 000000000..e60dea89e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.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/lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S new file mode 100644 index 000000000..6d20b9a95 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.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_barrier_wait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S new file mode 100644 index 000000000..5e1024eab --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_cond_broadcast.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S new file mode 100644 index 000000000..da4e8cbab --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_cond_signal.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S new file mode 100644 index 000000000..07d481f37 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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.  */ + +#define HAVE_CMOV 1 +#include "../i486/pthread_cond_timedwait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S new file mode 100644 index 000000000..9b57fbaca --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_cond_wait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S new file mode 100644 index 000000000..da2bc4704 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_rwlock_rdlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S new file mode 100644 index 000000000..0f2ec168b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_rwlock_timedrdlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S new file mode 100644 index 000000000..26501590a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_rwlock_timedwrlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S new file mode 100644 index 000000000..0894f0546 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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.  */ + +#define HAVE_CMOV	1 +#include "../i486/pthread_rwlock_unlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S new file mode 100644 index 000000000..04ac275f6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/pthread_rwlock_wrlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_post.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_post.S new file mode 100644 index 000000000..7317e1582 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_post.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/sem_post.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S new file mode 100644 index 000000000..f34539d56 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/sem_timedwait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S new file mode 100644 index 000000000..64145c2e3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/sem_trywait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S new file mode 100644 index 000000000..b3d462125 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 "../i486/sem_wait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h new file mode 100644 index 000000000..1033ebc2d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -0,0 +1,365 @@ +/* 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.  */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H	1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> +#include <sysdep.h> + +/* We have a separate internal lock implementation which is not tied +   to binary compatibility.  */ + +/* Type for lock object.  */ +typedef int lll_lock_t; + +/* Initializers for lock.  */ +#define LLL_LOCK_INITIALIZER		(0) +#define LLL_LOCK_INITIALIZER_LOCKED	(1) + +#include <tls.h> + +#ifndef LOCK_INSTR +# define LOCK_INSTR "lock;" +#endif + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +/* Initializer for compatibility lock.  */ +#define LLL_MUTEX_LOCK_INITIALIZER		(0) +#define LLL_MUTEX_LOCK_INITIALIZER_LOCKED	(1) +#define LLL_MUTEX_LOCK_INITIALIZER_WAITERS	(2) + + +#ifdef PIC +# define LLL_EBX_LOAD	"xchgl %2, %%ebx\n" +# define LLL_EBX_REG	"D" +#else +# define LLL_EBX_LOAD +# define LLL_EBX_REG	"b" +#endif + +#define LLL_ENTER_KERNEL	"int $0x80\n\t" + +/* Delay in spinlock loop.  */ +#define BUSY_WAIT_NOP          __asm__ ("rep; nop") + +#define lll_futex_wait(futex, val) \ +  lll_futex_timed_wait (futex, val, NULL) + +#define lll_futex_timed_wait(futex, val, timeout) \ +  ({									      \ +    int __ret;							      \ +    register __typeof (val) _val __asm__ ("edx") = (val);		      \ +    __asm__ __volatile (LLL_EBX_LOAD					      \ +		      LLL_ENTER_KERNEL					      \ +		      LLL_EBX_LOAD					      \ +		      : "=a" (__ret)					      \ +		      : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (timeout),  \ +			"c" (FUTEX_WAIT), "d" (_val),			      \ +			"i" (offsetof (tcbhead_t, sysinfo)));		      \ +   __ret; }) + + +#define lll_futex_wake(futex, nr) \ +  ({									      \ +    int __ret;							      \ +    register __typeof (nr) _nr __asm__ ("edx") = (nr);			      \ +    __asm__ __volatile (LLL_EBX_LOAD					      \ +		      LLL_ENTER_KERNEL					      \ +		      LLL_EBX_LOAD					      \ +		      : "=a" (__ret)					      \ +		      : "0" (SYS_futex), LLL_EBX_REG (futex),		      \ +			"c" (FUTEX_WAKE), "d" (_nr),			      \ +			"i" (0) /* phony, to align next arg's number */,      \ +			"i" (offsetof (tcbhead_t, sysinfo)));		      \ +   __ret; }) + + +/* Does not preserve %eax and %ecx.  */ +extern int __lll_mutex_lock_wait (int val, int *__futex) +     __attribute ((regparm (2))) attribute_hidden; +/* Does not preserve %eax, %ecx, and %edx.  */ +extern int __lll_mutex_timedlock_wait (int val, int *__futex, +				       const struct timespec *abstime) +     __attribute ((regparm (3))) attribute_hidden; +/* Preserves all registers but %eax.  */ +extern int __lll_mutex_unlock_wake (int *__futex) +     __attribute ((regparm (1))) attribute_hidden; + + +/* NB: in the lll_mutex_trylock macro we simply return the value in %eax +   after the cmpxchg instruction.  In case the operation succeded this +   value is zero.  In case the operation failed, the cmpxchg instruction +   has loaded the current value of the memory work which is guaranteed +   to be nonzero.  */ +#define lll_mutex_trylock(futex) \ +  ({ int ret;								      \ +     __asm__ __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \ +		       : "=a" (ret), "=m" (futex)			      \ +		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), "m" (futex),\ +			 "0" (LLL_MUTEX_LOCK_INITIALIZER)		      \ +		       : "memory");					      \ +     ret; }) + + +#define lll_mutex_cond_trylock(futex) \ +  ({ int ret;								      \ +     __asm__ __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \ +		       : "=a" (ret), "=m" (futex)			      \ +		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_WAITERS),	      \ +			  "m" (futex), "0" (LLL_MUTEX_LOCK_INITIALIZER)	      \ +		       : "memory");					      \ +     ret; }) + + +#define lll_mutex_lock(futex) \ +  (void) ({ int ignore1, ignore2;					      \ +	    __asm__ __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t"	      \ +			      "jnz _L_mutex_lock_%=\n\t"		      \ +			      ".subsection 1\n\t"			      \ +			      ".type _L_mutex_lock_%=,@function\n"	      \ +			      "_L_mutex_lock_%=:\n\t"			      \ +			      "leal %2, %%ecx\n\t"			      \ +			      "call __lll_mutex_lock_wait\n\t"		      \ +			      "jmp 1f\n\t"				      \ +			      ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n"   \ +			      ".previous\n"				      \ +			      "1:"					      \ +			      : "=a" (ignore1), "=c" (ignore2), "=m" (futex)  \ +			      : "0" (0), "1" (1), "m" (futex)		      \ +			      : "memory"); }) + + +/* Special version of lll_mutex_lock which causes the unlock function to +   always wakeup waiters.  */ +#define lll_mutex_cond_lock(futex) \ +  (void) ({ int ignore1, ignore2;					      \ +	    __asm__ __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t"	      \ +			      "jnz _L_mutex_cond_lock_%=\n\t"		      \ +			      ".subsection 1\n\t"			      \ +			      ".type _L_mutex_cond_lock_%=,@function\n"	      \ +			      "_L_mutex_cond_lock_%=:\n\t"		      \ +			      "leal %2, %%ecx\n\t"			      \ +			      "call __lll_mutex_lock_wait\n\t"		      \ +			      "jmp 1f\n\t"				      \ +			      ".size _L_mutex_cond_lock_%=,.-_L_mutex_cond_lock_%=\n"   \ +			      ".previous\n"				      \ +			      "1:"					      \ +			      : "=a" (ignore1), "=c" (ignore2), "=m" (futex)  \ +			      : "0" (0), "1" (2), "m" (futex)		      \ +			      : "memory"); }) + + +#define lll_mutex_timedlock(futex, timeout) \ +  ({ int _result, ignore1, ignore2;					      \ +     __asm__ __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t"		      \ +		       "jnz _L_mutex_timedlock_%=\n\t"			      \ +		       ".subsection 1\n\t"				      \ +		       ".type _L_mutex_timedlock_%=,@function\n"	      \ +		       "_L_mutex_timedlock_%=:\n\t"			      \ +		       "leal %3, %%ecx\n\t"				      \ +		       "movl %7, %%edx\n\t"				      \ +		       "call __lll_mutex_timedlock_wait\n\t"		      \ +		       "jmp 1f\n\t"					      \ +		       ".size _L_mutex_timedlock_%=,.-_L_mutex_timedlock_%=\n"\ +		       ".previous\n"					      \ +		       "1:"						      \ +		       : "=a" (_result), "=c" (ignore1), "=&d" (ignore2),      \ +			 "=m" (futex)					      \ +		       : "0" (0), "1" (1), "m" (futex), "m" (timeout)	      \ +		       : "memory");					      \ +     _result; }) + + +#define lll_mutex_unlock(futex) \ +  (void) ({ int ignore;							      \ +            __asm__ __volatile (LOCK_INSTR "subl $1,%0\n\t"		      \ +			      "jne _L_mutex_unlock_%=\n\t"		      \ +			      ".subsection 1\n\t"			      \ +			      ".type _L_mutex_unlock_%=,@function\n"	      \ +			      "_L_mutex_unlock_%=:\n\t"			      \ +			      "leal %0, %%eax\n\t"			      \ +			      "call __lll_mutex_unlock_wake\n\t"	      \ +			      "jmp 1f\n\t"				      \ +			      ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \ +			      ".previous\n"				      \ +			      "1:"					      \ +			      : "=m" (futex), "=&a" (ignore)		      \ +			      : "m" (futex)				      \ +			      : "memory"); }) + + +#define lll_mutex_islocked(futex) \ +  (futex != 0) + + +extern int __lll_lock_wait (int val, int *__futex) +     __attribute ((regparm (2))) attribute_hidden; +extern int __lll_unlock_wake (int *__futex) +     __attribute ((regparm (1))) attribute_hidden; +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + + +/* The states of a lock are: +    0  -  untaken +    1  -  taken by one user +    2  -  taken by more users */ + + +#if defined NOT_IN_libc +# define lll_trylock(futex) lll_mutex_trylock (futex) +# define lll_lock(futex) lll_mutex_lock (futex) +# define lll_unlock(futex) lll_mutex_unlock (futex) +#else +/* Special versions of the macros for use in libc itself.  They avoid +   the lock prefix when the thread library is not used. */ + + + +# define lll_trylock(futex) \ +  ({ unsigned char ret;							      \ +     __asm__ __volatile ("cmpl $0, %%gs:%P5\n\t"			      \ +		       "je,pt 0f\n\t"					      \ +		       "lock\n"						      \ +		       "0:\tcmpxchgl %2, %1; setne %0"			      \ +		       : "=a" (ret), "=m" (futex)			      \ +		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), "m" (futex),\ +			 "0" (LLL_MUTEX_LOCK_INITIALIZER),		      \ +		         "i" (offsetof (tcbhead_t, multiple_threads))	      \ +		       : "memory");					      \ +     ret; }) + + +# define lll_lock(futex) \ +  (void) ({ int ignore1, ignore2;					      \ +	    __asm__ __volatile ("cmpl $0, %%gs:%P6\n\t"			      \ +			      "je,pt 0f\n\t"				      \ +			      "lock\n"					      \ +			      "0:\tcmpxchgl %1, %2\n\t"			      \ +			      "jnz _L_mutex_lock_%=\n\t"		      \ +			      ".subsection 1\n\t"			      \ +			      ".type _L_mutex_lock_%=,@function\n"	      \ +			      "_L_mutex_lock_%=:\n\t"			      \ +			      "leal %2, %%ecx\n\t"			      \ +			      "call __lll_mutex_lock_wait\n\t"		      \ +			      "jmp 1f\n\t"				      \ +			      ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n"   \ +			      ".previous\n"				      \ +			      "1:"					      \ +			      : "=a" (ignore1), "=c" (ignore2), "=m" (futex)  \ +			      : "0" (0), "1" (1), "m" (futex),		      \ +		                "i" (offsetof (tcbhead_t, multiple_threads))  \ +			      : "memory"); }) + + +# define lll_unlock(futex) \ +  (void) ({ int ignore;							      \ +            __asm__ __volatile ("cmpl $0, %%gs:%P3\n\t"			      \ +			      "je,pt 0f\n\t"				      \ +			      "lock\n"					      \ +			      "0:\tsubl $1,%0\n\t"		      \ +			      "jne _L_mutex_unlock_%=\n\t"		      \ +			      ".subsection 1\n\t"			      \ +			      ".type _L_mutex_unlock_%=,@function\n"	      \ +			      "_L_mutex_unlock_%=:\n\t"			      \ +			      "leal %0, %%eax\n\t"			      \ +			      "call __lll_mutex_unlock_wake\n\t"	      \ +			      "jmp 1f\n\t"				      \ +			      ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \ +			      ".previous\n"				      \ +			      "1:"					      \ +			      : "=m" (futex), "=&a" (ignore)		      \ +			      : "m" (futex),				      \ +				"i" (offsetof (tcbhead_t, multiple_threads))  \ +			      : "memory"); }) +#endif + + +#define lll_islocked(futex) \ +  (futex != LLL_LOCK_INITIALIZER) + + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex +   wakeup when the clone terminates.  The memory location contains the +   thread ID while the clone is running and is reset to zero +   afterwards. + +   The macro parameter must not have any side effect.  */ +#define lll_wait_tid(tid) \ +  ({									      \ +    int __ret;								      \ +    register __typeof (tid) _tid __asm__ ("edx") = (tid);		      \ +    if (_tid != 0)							      \ +      __asm__ __volatile (LLL_EBX_LOAD					      \ +			"1:\tmovl %1, %%eax\n\t"			      \ +			LLL_ENTER_KERNEL				      \ +			"cmpl $0, (%%ebx)\n\t"				      \ +			"jne,pn 1b\n\t"					      \ +			LLL_EBX_LOAD					      \ +			: "=&a" (__ret)				              \ +			: "i" (SYS_futex), LLL_EBX_REG (&tid), "S" (0),	      \ +			  "c" (FUTEX_WAIT), "d" (_tid),			      \ +			  "i" (offsetof (tcbhead_t, sysinfo)));		      \ +   __ret; }) + +extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) +     __attribute__ ((regparm (2))) attribute_hidden; +#define lll_timedwait_tid(tid, abstime) \ +  ({									      \ +    int __result = 0;							      \ +    if (tid != 0)							      \ +      {									      \ +	if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)	      \ +	  __result = EINVAL;						      \ +	else								      \ +	  __result = __lll_timedwait_tid (&tid, abstime);		      \ +      }									      \ +    __result; }) + + +/* Conditional variable handling.  */ + +extern void __lll_cond_wait (pthread_cond_t *cond) +     __attribute ((regparm (1))) attribute_hidden; +extern int __lll_cond_timedwait (pthread_cond_t *cond, +				 const struct timespec *abstime) +     __attribute ((regparm (2))) attribute_hidden; +extern void __lll_cond_wake (pthread_cond_t *cond) +     __attribute ((regparm (1))) attribute_hidden; +extern void __lll_cond_broadcast (pthread_cond_t *cond) +     __attribute ((regparm (1))) attribute_hidden; + + +#define lll_cond_wait(cond) \ +  __lll_cond_wait (cond) +#define lll_cond_timedwait(cond, abstime) \ +  __lll_cond_timedwait (cond, abstime) +#define lll_cond_wake(cond) \ +  __lll_cond_wake (cond) +#define lll_cond_broadcast(cond) \ +  __lll_cond_broadcast (cond) + + +#endif	/* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h new file mode 100644 index 000000000..5bdba3f51 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h @@ -0,0 +1,82 @@ +/* Uncancelable versions of cancelable interfaces.  Linux/NPTL version. +   Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 <sysdep.h> + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt +extern int __open_nocancel (const char *, int, ...) attribute_hidden; +extern int __close_nocancel (int) attribute_hidden; +extern int __read_nocancel (int, void *, size_t) attribute_hidden; +extern int __write_nocancel (int, const void *, size_t) attribute_hidden; +extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden; + +libc_hidden_proto(__open_nocancel) +libc_hidden_proto(__close_nocancel) +libc_hidden_proto(__read_nocancel) +libc_hidden_proto(__write_nocancel) +libc_hidden_proto(__waitpid_nocancel) + +#else +#define __open_nocancel(name, ...) open (name, __VA_ARGS__) +#define __close_nocancel(fd) close (fd) +#define __read_nocancel(fd, buf, len) read (fd, buf, len) +#define __write_nocancel(fd, buf, len) write (fd, buf, len) +#define __waitpid_nocancel(pid, stat_loc, options) \ +  waitpid (pid, stat_loc, options) +#endif + +/* Uncancelable open.  */ +#define open_not_cancel(name, flags, mode) \ +   __open_nocancel (name, flags, mode) +#define open_not_cancel_2(name, flags) \ +   __open_nocancel (name, flags) + +/* Uncancelable close.  */ +#define close_not_cancel(fd) \ +  __close_nocancel (fd) +#define close_not_cancel_no_status(fd) \ +  (void) ({ INTERNAL_SYSCALL_DECL (err);				      \ +	    INTERNAL_SYSCALL (close, err, 1, (fd)); }) + +/* Uncancelable read.  */ +#define read_not_cancel(fd, buf, n) \ +  __read_nocancel (fd, buf, n) + +/* Uncancelable write.  */ +#define write_not_cancel(fd, buf, n) \ +  __write_nocancel (fd, buf, n) + +/* Uncancelable writev.  */ +#define writev_not_cancel_no_status(fd, iov, n) \ +  (void) ({ INTERNAL_SYSCALL_DECL (err);				      \ +	    INTERNAL_SYSCALL (writev, err, 3, (fd), (iov), (n)); }) + +/* Uncancelable fcntl.  */ +#define fcntl_not_cancel(fd, cmd, val) \ +  __fcntl_nocancel (fd, cmd, val) + +/* Uncancelable waitpid.  */ +#ifdef __NR_waitpid +# define waitpid_not_cancel(pid, stat_loc, options) \ +  __waitpid_nocancel (pid, stat_loc, options) +#else +# define waitpid_not_cancel(pid, stat_loc, options) \ +  INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-__syscall_error.c b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-__syscall_error.c new file mode 100644 index 000000000..620640ad6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-__syscall_error.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/i386/__syscall_error.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S new file mode 100644 index 000000000..939538927 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S @@ -0,0 +1,36 @@ +/* Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Andreas Schwab <schwab@gnu.org>. + +   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 <tcb-offsets.h> + +/* Save the PID value.  */ +#define SAVE_PID \ +	movl	%gs:PID, %edx; 						      \ +	movl	%edx, %eax;						      \ +	negl	%eax;							      \ +	movl	%eax, %gs:PID + +/* Restore the old PID value in the parent.  */ +#define RESTORE_PID \ +	testl	%eax, %eax;						      \ +	je	1f;							      \ +	movl	%edx, %gs:PID;						      \ +1: + +#include <../../../../../../../libc/sysdeps/linux/i386/vfork.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S new file mode 100644 index 000000000..afdb1c5f9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S @@ -0,0 +1,181 @@ +/* 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 <unwindbuf.h> +#include <sysdep.h> + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + +#define FUTEX_WAKE	1 + +	.comm	__fork_generation, 4, 4 + +	.text + + +	.globl	__pthread_once +	.type	__pthread_once,@function +	.align	16 +	cfi_startproc +__pthread_once: +	movl	4(%esp), %ecx +	testl	$2, (%ecx) +	jz	1f +	xorl	%eax, %eax +	ret + +1:	pushl	%ebx +	cfi_adjust_cfa_offset (4) +	cfi_rel_offset (3, 0) +	pushl	%esi +	cfi_adjust_cfa_offset (4) +	cfi_rel_offset (6, 0) +	movl	%ecx, %ebx +	xorl	%esi, %esi + +	/* Not yet initialized or initialization in progress. +	   Get the fork generation counter now.  */ +6:	movl	(%ebx), %eax +#ifdef PIC +	call	__x86.get_pc_thunk.cx +	addl	$_GLOBAL_OFFSET_TABLE_, %ecx +#endif + +5:	movl	%eax, %edx + +	testl	$2, %eax +	jnz	4f + +	andl	$3, %edx +#ifdef PIC +	orl	__fork_generation@GOTOFF(%ecx), %edx +#else +	orl	__fork_generation, %edx +#endif +	orl	$1, %edx + +	LOCK +	cmpxchgl %edx, (%ebx) +	jnz	5b + +	/* Check whether another thread already runs the initializer.  */ +	testl	$1, %eax +	jz	3f	/* No -> do it.  */ + +	/* Check whether the initializer execution was interrupted +	   by a fork.  */ +	xorl	%edx, %eax +	testl	$0xfffffffc, %eax +	jnz	3f	/* Different for generation -> run initializer.  */ + +	/* Somebody else got here first.  Wait.  */ +	movl	%esi, %ecx		/* movl $FUTEX_WAIT, %ecx */ +	movl	$SYS_futex, %eax +	ENTER_KERNEL +	jmp	6b + +3:	/* Call the initializer function after setting up the +	   cancellation handler.  Note that it is not possible here +	   to use the unwind-based cleanup handling.  This would require +	   that the user-provided function and all the code it calls +	   is compiled with exceptions.  Unfortunately this cannot be +	   guaranteed.  */ +	subl	$UNWINDBUFSIZE+8, %esp +	cfi_adjust_cfa_offset (UNWINDBUFSIZE+8) +	movl	%ecx, %ebx		/* PIC register value.  */ + +	leal	8+UWJMPBUF(%esp), %eax +	movl	$0, 4(%esp) +	movl	%eax, (%esp) +	call	__sigsetjmp@PLT +	testl	%eax, %eax +	jne	7f + +	leal	8(%esp), %eax +	call	HIDDEN_JUMPTARGET(__pthread_register_cancel) + +	/* Call the user-provided initialization function.  */ +	call	*24+UNWINDBUFSIZE(%esp) + +	/* Pop the cleanup handler.  */ +	leal	8(%esp), %eax +	call	HIDDEN_JUMPTARGET(__pthread_unregister_cancel) +	addl	$UNWINDBUFSIZE+8, %esp +	cfi_adjust_cfa_offset (-UNWINDBUFSIZE-8) + +	/* Sucessful run of the initializer.  Signal that we are done.  */ +	movl	12(%esp), %ebx +	LOCK +	addl	$1, (%ebx) + +	/* Wake up all other threads.  */ +	movl	$0x7fffffff, %edx +	movl	$FUTEX_WAKE, %ecx +	movl	$SYS_futex, %eax +	ENTER_KERNEL + +4:	popl	%esi +	cfi_adjust_cfa_offset (-4) +	cfi_restore (6) +	popl	%ebx +	cfi_adjust_cfa_offset (-4) +	cfi_restore (3) +	xorl	%eax, %eax +	ret + +7:	/* __sigsetjmp returned for the second time.  */ +	movl	20+UNWINDBUFSIZE(%esp), %ebx +	cfi_adjust_cfa_offset (UNWINDBUFSIZE+16) +	cfi_offset (3, -8) +	cfi_offset (6, -12) +	movl	$0, (%ebx) + +	movl	$0x7fffffff, %edx +	movl	$FUTEX_WAKE, %ecx +	movl	$SYS_futex, %eax +	ENTER_KERNEL + +	leal	8(%esp), %eax +	call	HIDDEN_JUMPTARGET (__pthread_unwind_next) +	/* NOTREACHED */ +	hlt +	cfi_endproc +	.size	__pthread_once,.-__pthread_once + +	.globl	__pthread_once_internal +__pthread_once_internal = __pthread_once + +	.globl	pthread_once +pthread_once = __pthread_once + + +#ifdef PIC +	.section .gnu.linkonce.t.__x86.get_pc_thunk.cx,"ax",@progbits +	.globl	__x86.get_pc_thunk.cx +	.hidden	__x86.get_pc_thunk.cx +	.type	__x86.get_pc_thunk.cx,@function +__x86.get_pc_thunk.cx: +	movl (%esp), %ecx; +	ret +	.size	__x86.get_pc_thunk.cx,.-__x86.get_pc_thunk.cx +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_init.c b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_init.c new file mode 100644 index 000000000..d36e5373d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_init.c @@ -0,0 +1 @@ +#include <sysdeps/i386/pthread_spin_init.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_unlock.S new file mode 100644 index 000000000..8bae0fd31 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_unlock.S @@ -0,0 +1 @@ +#include <sysdeps/i386/pthread_spin_unlock.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/smp.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/smp.h new file mode 100644 index 000000000..2c0cbe99a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/smp.h @@ -0,0 +1,24 @@ +/* Determine whether the host has multiple processors.  SH version. +   Copyright (C) 2002 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 Library General Public License as +   published by the Free Software Foundation; either version 2 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 +   Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public +   License along with the GNU C Library; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +static inline int +is_smp_system (void) +{ +  return 0; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h new file mode 100644 index 000000000..f32c5bd20 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h @@ -0,0 +1,139 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@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 <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args)				      \ +  .text;								      \ +  ENTRY (name)								      \ +    cmpl $0, %gs:MULTIPLE_THREADS_OFFSET;				      \ +    jne L(pseudo_cancel);						      \ +  .type __##syscall_name##_nocancel,@function;				      \ +  .globl __##syscall_name##_nocancel;					      \ +  __##syscall_name##_nocancel:						      \ +    DO_CALL (syscall_name, args);					      \ +    cmpl $-4095, %eax;							      \ +    jae SYSCALL_ERROR_LABEL;						      \ +    ret;								      \ +  .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \ +  L(pseudo_cancel):							      \ +    CENABLE								      \ +    SAVE_OLDTYPE_##args							      \ +    PUSHCARGS_##args							      \ +    DOCARGS_##args							      \ +    movl $SYS_ify (syscall_name), %eax;					      \ +    ENTER_KERNEL;							      \ +    POPCARGS_##args;							      \ +    POPSTATE_##args							      \ +    cmpl $-4095, %eax;							      \ +    jae SYSCALL_ERROR_LABEL;						      \ +  L(pseudo_end): + +# define SAVE_OLDTYPE_0	movl %eax, %ecx; +# define SAVE_OLDTYPE_1	SAVE_OLDTYPE_0 +# define SAVE_OLDTYPE_2	pushl %eax; cfi_adjust_cfa_offset (4); +# define SAVE_OLDTYPE_3	SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_4	SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_5	SAVE_OLDTYPE_2 + +# define PUSHCARGS_0	/* No arguments to push.  */ +# define DOCARGS_0	/* No arguments to frob.  */ +# define POPCARGS_0	/* No arguments to pop.  */ +# define _PUSHCARGS_0	/* No arguments to push.  */ +# define _POPCARGS_0	/* No arguments to pop.  */ + +# define PUSHCARGS_1	movl %ebx, %edx; cfi_register (ebx, edx); PUSHCARGS_0 +# define DOCARGS_1	_DOARGS_1 (4) +# define POPCARGS_1	POPCARGS_0; movl %edx, %ebx; cfi_restore (ebx); +# define _PUSHCARGS_1	pushl %ebx; cfi_adjust_cfa_offset (4); \ +			cfi_rel_offset (ebx, 0); _PUSHCARGS_0 +# define _POPCARGS_1	_POPCARGS_0; popl %ebx; \ +			cfi_adjust_cfa_offset (-4); cfi_restore (ebx); + +# define PUSHCARGS_2	PUSHCARGS_1 +# define DOCARGS_2	_DOARGS_2 (12) +# define POPCARGS_2	POPCARGS_1 +# define _PUSHCARGS_2	_PUSHCARGS_1 +# define _POPCARGS_2	_POPCARGS_1 + +# define PUSHCARGS_3	_PUSHCARGS_2 +# define DOCARGS_3	_DOARGS_3 (20) +# define POPCARGS_3	_POPCARGS_3 +# define _PUSHCARGS_3	_PUSHCARGS_2 +# define _POPCARGS_3	_POPCARGS_2 + +# define PUSHCARGS_4	_PUSHCARGS_4 +# define DOCARGS_4	_DOARGS_4 (28) +# define POPCARGS_4	_POPCARGS_4 +# define _PUSHCARGS_4	pushl %esi; cfi_adjust_cfa_offset (4); \ +			cfi_rel_offset (esi, 0); _PUSHCARGS_3 +# define _POPCARGS_4	_POPCARGS_3; popl %esi; \ +			cfi_adjust_cfa_offset (-4); cfi_restore (esi); + +# define PUSHCARGS_5	_PUSHCARGS_5 +# define DOCARGS_5	_DOARGS_5 (36) +# define POPCARGS_5	_POPCARGS_5 +# define _PUSHCARGS_5	pushl %edi; cfi_adjust_cfa_offset (4); \ +			cfi_rel_offset (edi, 0); _PUSHCARGS_4 +# define _POPCARGS_5	_POPCARGS_4; popl %edi; \ +			cfi_adjust_cfa_offset (-4); cfi_restore (edi); + +# ifdef IS_IN_libpthread +#  define CENABLE	call __pthread_enable_asynccancel; +#  define CDISABLE	call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +#  define CENABLE	call __libc_enable_asynccancel; +#  define CDISABLE	call __libc_disable_asynccancel +# elif defined IS_IN_librt +#  define CENABLE	call __librt_enable_asynccancel; +#  define CDISABLE	call __librt_disable_asynccancel +# else +#  error Unsupported library +# endif +# define POPSTATE_0 \ + pushl %eax; cfi_adjust_cfa_offset (4); movl %ecx, %eax; \ + CDISABLE; popl %eax; cfi_adjust_cfa_offset (-4); +# define POPSTATE_1	POPSTATE_0 +# define POPSTATE_2	xchgl (%esp), %eax; CDISABLE; popl %eax; \ +			cfi_adjust_cfa_offset (-4); +# define POPSTATE_3	POPSTATE_2 +# define POPSTATE_4	POPSTATE_3 +# define POPSTATE_5	POPSTATE_4 + +# ifndef __ASSEMBLER__ +#  define SINGLE_THREAD_P \ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ +				   header.multiple_threads) == 0, 1) +# else +#  define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep.h new file mode 100644 index 000000000..f9343cc93 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep.h @@ -0,0 +1,336 @@ +/* Copyright (C) 1992,1993,1995-2000,2002-2006,2007 +	Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper, <drepper@gnu.org>, August 1995. + +   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 _LINUX_I386_SYSDEP_H +#define _LINUX_I386_SYSDEP_H 1 + +#include <sys/syscall.h> +#include <sysdeps/i386/sysdep.h> + +#ifndef offsetof +# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +/* For Linux we can use the system call table in the header file +	/usr/include/asm/unistd.h +   of the kernel.  But these symbols do not follow the SYS_* syntax +   so we have to redefine the `SYS_ify' macro here.  */ +#undef SYS_ify +#define SYS_ify(syscall_name)	__NR_##syscall_name + +#if defined USE_DL_SYSINFO \ +    && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define I386_USE_SYSENTER	1 +#else +# undef I386_USE_SYSENTER +#endif + +#ifdef __ASSEMBLER__ + +/* Linux uses a negative return value to indicate syscall errors, +   unlike most Unices, which use the condition codes' carry flag. + +   Since version 2.1 the return value of a system call might be +   negative even if the call succeeded.  E.g., the `lseek' system call +   might return a large offset.  Therefore we must not anymore test +   for < 0, but test for a real error by making sure the value in %eax +   is a real error number.  Linus said he will make sure the no syscall +   returns a value in -1 .. -4095 as a valid result so we can savely +   test with -4095.  */ + +/* We don't want the label for the error handle to be global when we define +   it here.  */ +#ifdef PIC +# define SYSCALL_ERROR_LABEL 0f +#else +# define SYSCALL_ERROR_LABEL syscall_error +#endif + +#undef	PSEUDO +#define	PSEUDO(name, syscall_name, args)				      \ +  .text;								      \ +  ENTRY (name)								      \ +    DO_CALL (syscall_name, args);					      \ +    cmpl $-4095, %eax;							      \ +    jae SYSCALL_ERROR_LABEL;						      \ +  L(pseudo_end): + +#undef	PSEUDO_END +#define	PSEUDO_END(name)						      \ +  SYSCALL_ERROR_HANDLER							      \ +  END (name) + +#undef	PSEUDO_NOERRNO +#define	PSEUDO_NOERRNO(name, syscall_name, args)			      \ +  .text;								      \ +  ENTRY (name)								      \ +    DO_CALL (syscall_name, args) + +#undef	PSEUDO_END_NOERRNO +#define	PSEUDO_END_NOERRNO(name)					      \ +  END (name) + +#define ret_NOERRNO ret + +/* The function has to return the error code.  */ +#undef	PSEUDO_ERRVAL +#define	PSEUDO_ERRVAL(name, syscall_name, args) \ +  .text;								      \ +  ENTRY (name)								      \ +    DO_CALL (syscall_name, args);					      \ +    negl %eax + +#undef	PSEUDO_END_ERRVAL +#define	PSEUDO_END_ERRVAL(name) \ +  END (name) + +#define ret_ERRVAL ret + +#ifndef PIC +# define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.S is used.  */ +#else + +# ifdef RTLD_PRIVATE_ERRNO +#  define SYSCALL_ERROR_HANDLER						      \ +0:SETUP_PIC_REG(cx);							      \ +  addl $_GLOBAL_OFFSET_TABLE_, %ecx;					      \ +  xorl %edx, %edx;							      \ +  subl %eax, %edx;							      \ +  movl %edx, rtld_errno@GOTOFF(%ecx);					      \ +  orl $-1, %eax;							      \ +  jmp L(pseudo_end); + +# elif defined _LIBC_REENTRANT + +#  if USE___THREAD +#   ifndef NOT_IN_libc +#    define SYSCALL_ERROR_ERRNO __libc_errno +#   else +#    define SYSCALL_ERROR_ERRNO errno +#   endif +#   define SYSCALL_ERROR_HANDLER					      \ +0:SETUP_PIC_REG (cx);							      \ +  addl $_GLOBAL_OFFSET_TABLE_, %ecx;					      \ +  movl SYSCALL_ERROR_ERRNO@GOTNTPOFF(%ecx), %ecx;			      \ +  xorl %edx, %edx;							      \ +  subl %eax, %edx;							      \ +  SYSCALL_ERROR_HANDLER_TLS_STORE (%edx, %ecx);				      \ +  orl $-1, %eax;							      \ +  jmp L(pseudo_end); +#   ifndef NO_TLS_DIRECT_SEG_REFS +#    define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff)		      \ +  movl src, %gs:(destoff) +#   else +#    define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff)		      \ +  addl %gs:0, destoff;							      \ +  movl src, (destoff) +#   endif +#  else +#   define SYSCALL_ERROR_HANDLER					      \ +0:pushl %ebx;								      \ +  cfi_adjust_cfa_offset (4);						      \ +  cfi_rel_offset (ebx, 0);						      \ +  SETUP_PIC_REG (bx);							      \ +  addl $_GLOBAL_OFFSET_TABLE_, %ebx;					      \ +  xorl %edx, %edx;							      \ +  subl %eax, %edx;							      \ +  pushl %edx;								      \ +  cfi_adjust_cfa_offset (4);						      \ +  call __errno_location@PLT;					              \ +  popl %ecx;								      \ +  cfi_adjust_cfa_offset (-4);						      \ +  popl %ebx;								      \ +  cfi_adjust_cfa_offset (-4);						      \ +  cfi_restore (ebx);							      \ +  movl %ecx, (%eax);							      \ +  orl $-1, %eax;							      \ +  jmp L(pseudo_end); +/* A quick note: it is assumed that the call to `__errno_location' does +   not modify the stack!  */ +#  endif +# else +/* Store (- %eax) into errno through the GOT.  */ +#  define SYSCALL_ERROR_HANDLER						      \ +0:SETUP_PIC_REG(cx);							      \ +  addl $_GLOBAL_OFFSET_TABLE_, %ecx;					      \ +  xorl %edx, %edx;							      \ +  subl %eax, %edx;							      \ +  movl errno@GOT(%ecx), %ecx;						      \ +  movl %edx, (%ecx);							      \ +  orl $-1, %eax;							      \ +  jmp L(pseudo_end); +# endif	/* _LIBC_REENTRANT */ +#endif	/* PIC */ + + +/* The original calling convention for system calls on Linux/i386 is +   to use int $0x80.  */ +#ifdef I386_USE_SYSENTER +# ifdef SHARED +#  define ENTER_KERNEL call *%gs:SYSINFO_OFFSET +# else +#  define ENTER_KERNEL call *_dl_sysinfo +# endif +#else +# define ENTER_KERNEL int $0x80 +#endif + +/* Linux takes system call arguments in registers: + +	syscall number	%eax	     call-clobbered +	arg 1		%ebx	     call-saved +	arg 2		%ecx	     call-clobbered +	arg 3		%edx	     call-clobbered +	arg 4		%esi	     call-saved +	arg 5		%edi	     call-saved +	arg 6		%ebp	     call-saved + +   The stack layout upon entering the function is: + +	24(%esp)	Arg# 6 +	20(%esp)	Arg# 5 +	16(%esp)	Arg# 4 +	12(%esp)	Arg# 3 +	 8(%esp)	Arg# 2 +	 4(%esp)	Arg# 1 +	  (%esp)	Return address + +   (Of course a function with say 3 arguments does not have entries for +   arguments 4, 5, and 6.) + +   The following code tries hard to be optimal.  A general assumption +   (which is true according to the data books I have) is that + +	2 * xchg	is more expensive than	pushl + movl + popl + +   Beside this a neat trick is used.  The calling conventions for Linux +   tell that among the registers used for parameters %ecx and %edx need +   not be saved.  Beside this we may clobber this registers even when +   they are not used for parameter passing. + +   As a result one can see below that we save the content of the %ebx +   register in the %edx register when we have less than 3 arguments +   (2 * movl is less expensive than pushl + popl). + +   Second unlike for the other registers we don't save the content of +   %ecx and %edx when we have more than 1 and 2 registers resp. + +   The code below might look a bit long but we have to take care for +   the pipelined processors (i586).  Here the `pushl' and `popl' +   instructions are marked as NP (not pairable) but the exception is +   two consecutive of these instruction.  This gives no penalty on +   other processors though.  */ + +#undef	DO_CALL +#define DO_CALL(syscall_name, args)			      		      \ +    PUSHARGS_##args							      \ +    DOARGS_##args							      \ +    movl $SYS_ify (syscall_name), %eax;					      \ +    ENTER_KERNEL							      \ +    POPARGS_##args + +#define PUSHARGS_0	/* No arguments to push.  */ +#define	DOARGS_0	/* No arguments to frob.  */ +#define	POPARGS_0	/* No arguments to pop.  */ +#define	_PUSHARGS_0	/* No arguments to push.  */ +#define _DOARGS_0(n)	/* No arguments to frob.  */ +#define	_POPARGS_0	/* No arguments to pop.  */ + +#define PUSHARGS_1	movl %ebx, %edx; L(SAVEBX1): PUSHARGS_0 +#define	DOARGS_1	_DOARGS_1 (4) +#define	POPARGS_1	POPARGS_0; movl %edx, %ebx; L(RESTBX1): +#define	_PUSHARGS_1	pushl %ebx; cfi_adjust_cfa_offset (4); \ +			cfi_rel_offset (ebx, 0); L(PUSHBX1): _PUSHARGS_0 +#define _DOARGS_1(n)	movl n(%esp), %ebx; _DOARGS_0(n-4) +#define	_POPARGS_1	_POPARGS_0; popl %ebx; cfi_adjust_cfa_offset (-4); \ +			cfi_restore (ebx); L(POPBX1): + +#define PUSHARGS_2	PUSHARGS_1 +#define	DOARGS_2	_DOARGS_2 (8) +#define	POPARGS_2	POPARGS_1 +#define _PUSHARGS_2	_PUSHARGS_1 +#define	_DOARGS_2(n)	movl n(%esp), %ecx; _DOARGS_1 (n-4) +#define	_POPARGS_2	_POPARGS_1 + +#define PUSHARGS_3	_PUSHARGS_2 +#define DOARGS_3	_DOARGS_3 (16) +#define POPARGS_3	_POPARGS_3 +#define _PUSHARGS_3	_PUSHARGS_2 +#define _DOARGS_3(n)	movl n(%esp), %edx; _DOARGS_2 (n-4) +#define _POPARGS_3	_POPARGS_2 + +#define PUSHARGS_4	_PUSHARGS_4 +#define DOARGS_4	_DOARGS_4 (24) +#define POPARGS_4	_POPARGS_4 +#define _PUSHARGS_4	pushl %esi; cfi_adjust_cfa_offset (4); \ +			cfi_rel_offset (esi, 0); L(PUSHSI1): _PUSHARGS_3 +#define _DOARGS_4(n)	movl n(%esp), %esi; _DOARGS_3 (n-4) +#define _POPARGS_4	_POPARGS_3; popl %esi; cfi_adjust_cfa_offset (-4); \ +			cfi_restore (esi); L(POPSI1): + +#define PUSHARGS_5	_PUSHARGS_5 +#define DOARGS_5	_DOARGS_5 (32) +#define POPARGS_5	_POPARGS_5 +#define _PUSHARGS_5	pushl %edi; cfi_adjust_cfa_offset (4); \ +			cfi_rel_offset (edi, 0); L(PUSHDI1): _PUSHARGS_4 +#define _DOARGS_5(n)	movl n(%esp), %edi; _DOARGS_4 (n-4) +#define _POPARGS_5	_POPARGS_4; popl %edi; cfi_adjust_cfa_offset (-4); \ +			cfi_restore (edi); L(POPDI1): + +#define PUSHARGS_6	_PUSHARGS_6 +#define DOARGS_6	_DOARGS_6 (40) +#define POPARGS_6	_POPARGS_6 +#define _PUSHARGS_6	pushl %ebp; cfi_adjust_cfa_offset (4); \ +			cfi_rel_offset (ebp, 0); L(PUSHBP1): _PUSHARGS_5 +#define _DOARGS_6(n)	movl n(%esp), %ebp; _DOARGS_5 (n-4) +#define _POPARGS_6	_POPARGS_5; popl %ebp; cfi_adjust_cfa_offset (-4); \ +			cfi_restore (ebp); L(POPBP1): + +#endif	/* __ASSEMBLER__ */ + + +/* Pointer mangling support.  */ +#if defined NOT_IN_libc && defined IS_IN_rtld +/* We cannot use the thread descriptor because in ld.so we use setjmp +   earlier than the descriptor is initialized.  Using a global variable +   is too complicated here since we have no PC-relative addressing mode.  */ +#else +# ifdef __ASSEMBLER__ +#  define PTR_MANGLE(reg)	xorl %gs:POINTER_GUARD, reg;		      \ +				roll $9, reg +#  define PTR_DEMANGLE(reg)	rorl $9, reg;				      \ +				xorl %gs:POINTER_GUARD, reg +# else +#  define PTR_MANGLE(var)	asm ("xorl %%gs:%c2, %0\n"		      \ +				     "roll $9, %0"			      \ +				     : "=r" (var)			      \ +				     : "0" (var),			      \ +				       "i" (offsetof (tcbhead_t,	      \ +						      pointer_guard))) +#  define PTR_DEMANGLE(var)	asm ("rorl $9, %0\n"			      \ +				     "xorl %%gs:%c2, %0"		      \ +				     : "=r" (var)			      \ +				     : "0" (var),			      \ +				       "i" (offsetof (tcbhead_t,	      \ +						      pointer_guard))) +# endif +#endif + +#endif /* linux/i386/sysdep.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/vfork.S new file mode 100644 index 000000000..dc7fb2ec4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/vfork.S @@ -0,0 +1,38 @@ +/* Copyright (C) 1999, 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.  */ + +#include <tcb-offsets.h> + +/* Save the PID value.  */ +#define SAVE_PID \ +	movl	%gs:PID, %edx; 						      \ +	movl	%edx, %eax;						      \ +	negl	%eax;							      \ +	jne	1f;							      \ +	movl	$0x80000000, %eax;					      \ +1:	movl	%eax, %gs:PID + +/* Restore the old PID value in the parent.  */ +#define RESTORE_PID \ +	testl	%eax, %eax;						      \ +	je	1f;							      \ +	movl	%edx, %gs:PID;						      \ +1: + + +#include <libc/sysdeps/linux/i386/vfork.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h new file mode 100644 index 000000000..07ee9d7dd --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h @@ -0,0 +1,153 @@ +/* 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.  */ + +#ifndef _INTERNALTYPES_H +#define _INTERNALTYPES_H	1 + +#include <stdint.h> +#include <sched.h> + + +struct pthread_attr +{ +  /* Scheduler parameters and priority.  */ +  struct sched_param schedparam; +  int schedpolicy; +  /* Various flags like detachstate, scope, etc.  */ +  int flags; +  /* Size of guard area.  */ +  size_t guardsize; +  /* Stack handling.  */ +  void *stackaddr; +  size_t stacksize; +  /* Affinity map.  */ +  cpu_set_t *cpuset; +  size_t cpusetsize; +}; + +#define ATTR_FLAG_DETACHSTATE		0x0001 +#define ATTR_FLAG_NOTINHERITSCHED	0x0002 +#define ATTR_FLAG_SCOPEPROCESS		0x0004 +#define ATTR_FLAG_STACKADDR		0x0008 +#define ATTR_FLAG_OLDATTR		0x0010 +#define ATTR_FLAG_SCHED_SET		0x0020 +#define ATTR_FLAG_POLICY_SET		0x0040 + + +/* Mutex attribute data structure.  */ +struct pthread_mutexattr +{ +  /* Identifier for the kind of mutex. + +     Bit 31 is set if the mutex is to be shared between processes. + +     Bit 0 to 30 contain one of the PTHREAD_MUTEX_ values to identify +     the type of the mutex.  */ +  int mutexkind; +}; + + +/* Conditional variable attribute data structure.  */ +struct pthread_condattr +{ +  /* Combination of values: + +     Bit 0  : flag whether coditional variable will be shareable between +	      processes. + +     Bit 1-7: clock ID.  */ +  int value; +}; + + +/* The __NWAITERS field is used as a counter and to house the number +   of bits which represent the clock.  COND_CLOCK_BITS is the number +   of bits reserved for the clock.  */ +#define COND_CLOCK_BITS	1 + + +/* Read-write lock variable attribute data structure.  */ +struct pthread_rwlockattr +{ +  int lockkind; +  int pshared; +}; + + +/* Barrier data structure.  */ +struct pthread_barrier +{ +  unsigned int curr_event; +  int lock; +  unsigned int left; +  unsigned int init_count; +}; + + +/* Barrier variable attribute data structure.  */ +struct pthread_barrierattr +{ +  int pshared; +}; + + +/* Thread-local data handling.  */ +struct pthread_key_struct +{ +  /* Sequence numbers.  Even numbers indicated vacant entries.  Note +     that zero is even.  We use uintptr_t to not require padding on +     32- and 64-bit machines.  On 64-bit machines it helps to avoid +     wrapping, too.  */ +  uintptr_t seq; + +  /* Destructor for the data.  */ +  void (*destr) (void *); +}; + +/* Check whether an entry is unused.  */ +#define KEY_UNUSED(p) (((p) & 1) == 0) +/* Check whether a key is usable.  We cannot reuse an allocated key if +   the sequence counter would overflow after the next destroy call. +   This would mean that we potentially free memory for a key with the +   same sequence.  This is *very* unlikely to happen, A program would +   have to create and destroy a key 2^31 times (on 32-bit platforms, +   on 64-bit platforms that would be 2^63).  If it should happen we +   simply don't use this specific key anymore.  */ +#define KEY_USABLE(p) (((uintptr_t) (p)) < ((uintptr_t) ((p) + 2))) + + +/* Handling of read-write lock data.  */ +// XXX For now there is only one flag.  Maybe more in future. +#define RWLOCK_RECURSIVE(rwlock) ((rwlock)->__data.__flags != 0) + + +/* Semaphore variable structure.  */ +struct sem +{ +  unsigned int count; +}; + + +/* Compatibility type for old conditional variable interfaces.  */ +typedef struct +{ +  pthread_cond_t *cond; +} pthread_cond_2_0_t; + +#endif	/* internaltypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c b/libpthread/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c new file mode 100644 index 000000000..c435eff30 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c @@ -0,0 +1,39 @@ +/* Clean up stack frames unwound by longjmp.  Linux version. +   Copyright (C) 1995, 1997, 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.  */ + +#include <setjmp.h> +#include <stddef.h> +#include <pthreadP.h> + +extern void __pthread_cleanup_upto (__jmp_buf env, char *targetframe); +#pragma weak __pthread_cleanup_upto + + +void +_longjmp_unwind (jmp_buf env, int val) +{ +#ifdef SHARED +# define fptr __libc_pthread_functions.ptr___pthread_cleanup_upto +#else +# define fptr __pthread_cleanup_upto +#endif + +  if (fptr != NULL) +    fptr (env->__jmpbuf, CURRENT_STACK_FRAME); +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h b/libpthread/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h new file mode 100644 index 000000000..9be630268 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h @@ -0,0 +1 @@ +#include <../../../../../../librt/kernel-posix-timers.h> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c new file mode 100644 index 000000000..b19282281 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.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.  */ + +/* No difference to lowlevellock.c, except we lose a couple of functions.  */ +#include "lowlevellock.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c b/libpthread/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c new file mode 100644 index 000000000..a96f17490 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c @@ -0,0 +1,26 @@ +/* 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 <pthreadP.h> + +#ifndef NOT_IN_libc +# ifndef TLS_MULTIPLE_THREADS_IN_TCB +int __libc_multiple_threads attribute_hidden; +# endif +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c new file mode 100644 index 000000000..4ad252800 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c @@ -0,0 +1,59 @@ +/* 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 <unistd.h> +#include <list.h> +#include "fork.h" +#include <tls.h> +#include <string.h> +#include <pthreadP.h> +#include <bits/libc-lock.h> + +libc_hidden_proto(memcpy) + +#ifdef TLS_MULTIPLE_THREADS_IN_TCB +void +#else +extern int __libc_multiple_threads attribute_hidden; + +int * +#endif +__libc_pthread_init ( +     unsigned long int *ptr, +     void (*reclaim) (void), +     const struct pthread_functions *functions) +{ +  /* Remember the pointer to the generation counter in libpthread.  */ +  __fork_generation_pointer = ptr; + +  /* Called by a child after fork.  */ +  __register_atfork (NULL, NULL, reclaim, NULL); + +#ifdef SHARED +  /* We copy the content of the variable pointed to by the FUNCTIONS +     parameter to one in libc.so since this means access to the array +     can be done with one memory access instead of two.  */ +  memcpy (&__libc_pthread_functions, functions, +	  sizeof (__libc_pthread_functions)); +#endif + +#ifndef TLS_MULTIPLE_THREADS_IN_TCB +  return &__libc_multiple_threads; +#endif +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym new file mode 100644 index 000000000..36e28eb2a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym @@ -0,0 +1,11 @@ +#include <stddef.h> +#include <sched.h> +#include <bits/pthreadtypes.h> +#include "internaltypes.h" + +-- + +CURR_EVENT		offsetof (struct pthread_barrier, curr_event) +MUTEX			offsetof (struct pthread_barrier, lock) +LEFT			offsetof (struct pthread_barrier, left) +INIT_COUNT		offsetof (struct pthread_barrier, init_count) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym new file mode 100644 index 000000000..c5e797806 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym @@ -0,0 +1,16 @@ +#include <stddef.h> +#include <sched.h> +#include <bits/pthreadtypes.h> +#include <internaltypes.h> + +-- + +cond_lock	offsetof (pthread_cond_t, __data.__lock) +cond_futex	offsetof (pthread_cond_t, __data.__futex) +cond_nwaiters	offsetof (pthread_cond_t, __data.__nwaiters) +total_seq	offsetof (pthread_cond_t, __data.__total_seq) +wakeup_seq	offsetof (pthread_cond_t, __data.__wakeup_seq) +woken_seq	offsetof (pthread_cond_t, __data.__woken_seq) +dep_mutex	offsetof (pthread_cond_t, __data.__mutex) +broadcast_seq	offsetof (pthread_cond_t, __data.__broadcast_seq) +clock_bits	COND_CLOCK_BITS diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c new file mode 100644 index 000000000..f93891431 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c @@ -0,0 +1,131 @@ +/* low level locking for pthread library.  Generic futex-using version. +   Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.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 <sysdep.h> +#include <lowlevellock.h> +#include <sys/time.h> + + +void +__lll_lock_wait (int *futex) +{ +  do +    { +      int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1); +      if (oldval != 0) +	lll_futex_wait (futex, 2); +    } +  while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); +} + + +int +__lll_timedlock_wait (int *futex, const struct timespec *abstime) +{ +  /* Reject invalid timeouts.  */ +  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) +    return EINVAL; + +  do +    { +      struct timeval tv; +      struct timespec rt; + +      /* Get the current time.  */ +      (void) gettimeofday (&tv, NULL); + +      /* Compute relative timeout.  */ +      rt.tv_sec = abstime->tv_sec - tv.tv_sec; +      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; +      if (rt.tv_nsec < 0) +	{ +	  rt.tv_nsec += 1000000000; +	  --rt.tv_sec; +	} + +      /* Already timed out?  */ +      if (rt.tv_sec < 0) +	return ETIMEDOUT; + +      /* Wait.  */ +      int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1); +      if (oldval != 0) +	lll_futex_timed_wait (futex, 2, &rt); +    } +  while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); + +  return 0; +} + + +/* These don't get included in libc.so  */ +#ifdef IS_IN_libpthread +int +lll_unlock_wake_cb (int *futex) +{ +  int val = atomic_exchange_rel (futex, 0); + +  if (__builtin_expect (val > 1, 0)) +    lll_futex_wake (futex, 1); + +  return 0; +} + + +int +__lll_timedwait_tid (int *tidp, const struct timespec *abstime) +{ +  int tid; + +  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) +    return EINVAL; + +  /* Repeat until thread terminated.  */ +  while ((tid = *tidp) != 0) +    { +      struct timeval tv; +      struct timespec rt; + +      /* Get the current time.  */ +      (void) gettimeofday (&tv, NULL); + +      /* Compute relative timeout.  */ +      rt.tv_sec = abstime->tv_sec - tv.tv_sec; +      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; +      if (rt.tv_nsec < 0) +	{ +	  rt.tv_nsec += 1000000000; +	  --rt.tv_sec; +	} + +      /* Already timed out?  */ +      if (rt.tv_sec < 0) +	return ETIMEDOUT; + +      /* Wait until thread terminates.  */ +      if (lll_futex_timed_wait (tidp, tid, &rt) == -ETIMEDOUT) +	return ETIMEDOUT; +    } + +  return 0; +} + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym new file mode 100644 index 000000000..e82c878d3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym @@ -0,0 +1,14 @@ +#include <stddef.h> +#include <stdio.h> +#include <bits/pthreadtypes.h> + +-- + +MUTEX		offsetof (pthread_rwlock_t, __data.__lock) +NR_READERS	offsetof (pthread_rwlock_t, __data.__nr_readers) +READERS_WAKEUP	offsetof (pthread_rwlock_t, __data.__readers_wakeup) +WRITERS_WAKEUP	offsetof (pthread_rwlock_t, __data.__writer_wakeup) +READERS_QUEUED	offsetof (pthread_rwlock_t, __data.__nr_readers_queued) +WRITERS_QUEUED	offsetof (pthread_rwlock_t, __data.__nr_writers_queued) +FLAGS		offsetof (pthread_rwlock_t, __data.__flags) +WRITER		offsetof (pthread_rwlock_t, __data.__writer) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lseek.S b/libpthread/nptl/sysdeps/unix/sysv/linux/lseek.S new file mode 100644 index 000000000..70a920ba1 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lseek.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_lseek, lseek, 3) +ret +PSEUDO_END (__libc_lseek) +libc_hidden_def (__libc_lseek) +weak_alias (__libc_lseek, lseek) +libc_hidden_weak (lseek) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile @@ -0,0 +1,13 @@ +# 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. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch new file mode 100644 index 000000000..a7de215e2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch @@ -0,0 +1,49 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_SSRC = pt-vfork.S +libpthread_CSRC = pthread_once.c pt-__syscall_rt_sigaction.c + +libc_a_CSRC = fork.c + +CFLAGS-OMIT-fork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif +CFLAGS-pthread_once.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/mips +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/mips + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) +LINUX_ARCH_OBJ+=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJS) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=pthread_linux_arch_objclean + +pthread_linux_arch_objclean: +	$(RM) $(LINUX_ARCH_OUT)/*.{o,os,oS} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h new file mode 100644 index 000000000..f112b8a39 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h @@ -0,0 +1,215 @@ +/* Machine-specific pthread type layouts.  MIPS version. +   Copyright (C) 2005 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 _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H	1 + +#include <sgidefs.h> + +#if _MIPS_SIM == _ABI64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers.  The structure of the attribute type is +   deliberately not exposed.  */ +typedef unsigned long int pthread_t; + + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_ATTR_T]; +  long int __align; +} pthread_attr_t; + +#if _MIPS_SIM == _ABI64 +typedef struct __pthread_internal_list +{ +  struct __pthread_internal_list *__prev; +  struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ +  struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + +/* Data structures for mutex handling.  The structure of the attribute +   type is deliberately not exposed.  */ +typedef union +{ +  struct __pthread_mutex_s +  { +    int __lock; +    unsigned int __count; +    int __owner; +#if _MIPS_SIM == _ABI64 +    unsigned int __nusers; +#endif +    /* KIND must stay at this position in the structure to maintain +       binary compatibility.  */ +    int __kind; +#if _MIPS_SIM == _ABI64 +    int __spins; +    __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV      1 +#else +    unsigned int __nusers; +    __extension__ union +    { +      int __spins; +      __pthread_slist_t __list; +    }; +#endif +  } __data; +  char __size[__SIZEOF_PTHREAD_MUTEX_T]; +  long int __align; +} pthread_mutex_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; +  int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling.  The structure of +   the attribute type is deliberately not exposed.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __futex; +    __extension__ unsigned long long int __total_seq; +    __extension__ unsigned long long int __wakeup_seq; +    __extension__ unsigned long long int __woken_seq; +    void *__mutex; +    unsigned int __nwaiters; +    unsigned int __broadcast_seq; +  } __data; +  char __size[__SIZEOF_PTHREAD_COND_T]; +  __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_CONDATTR_T]; +  int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling.  The +   structure of the attribute type is deliberately not exposed.  */ +typedef union +{ +# if _MIPS_SIM == _ABI64 +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    int __writer; +    int __pad1; +    unsigned long int __pad2; +    unsigned long int __pad3; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +  } __data; +# else +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +    int __writer; +  } __data; +# endif +  char __size[__SIZEOF_PTHREAD_RWLOCK_T]; +  long int __align; +} pthread_rwlock_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; +  long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type.  */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type.  The structure of the type is +   deliberately not exposed.  */ +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIER_T]; +  long int __align; +} pthread_barrier_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; +  int __align; +} pthread_barrierattr_t; +#endif + + +#endif	/* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/semaphore.h new file mode 100644 index 000000000..c4440f9e9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/semaphore.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2002, 2005 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 _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +#if _MIPS_SIM == _ABI64 +# define __SIZEOF_SEM_T	32 +#else +# define __SIZEOF_SEM_T	16 +#endif + +/* Value returned if `sem_open' failed.  */ +#define SEM_FAILED      ((sem_t *) 0) + +/* Maximum value the semaphore can have.  */ +#define SEM_VALUE_MAX   (2147483647) + + +typedef union +{ +  char __size[__SIZEOF_SEM_T]; +  long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/createthread.c new file mode 100644 index 000000000..d8a7c5539 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/createthread.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2005 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.  */ + +/* Value passed to 'clone' for initialization of the thread register.  */ +#define TLS_VALUE ((void *) (pd) \ +		   + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +/* Get the real implementation.	 */ +#include <sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/fork.c new file mode 100644 index 000000000..06b7e1c69 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/fork.c @@ -0,0 +1 @@ +#include "../i386/fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/lowlevellock.h new file mode 100644 index 000000000..7edb28794 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/lowlevellock.h @@ -0,0 +1,216 @@ +/* Copyright (C) 2003, 2004, 2005 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 _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H	1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> +#include <sysdep.h> + + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 +#define FUTEX_CMP_REQUEUE	4 + +/* Initializer for compatibility lock.	*/ +#define LLL_MUTEX_LOCK_INITIALIZER (0) + +#define lll_futex_wait(futexp, val) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAIT, (val), 0);		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret;		      \ +  }) + +#define lll_futex_timed_wait(futexp, val, timespec) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAIT, (val), (timespec));	      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret;		      \ +  }) + +#define lll_futex_wake(futexp, nr) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAKE, (nr), 0);		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret;		      \ +  }) + +/* Returns non-zero if error happened, zero if success.  */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 6,				      \ +			      (futexp), FUTEX_CMP_REQUEUE, (nr_wake),	      \ +			      (nr_move), (mutex), (val));		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \ +  }) + + +static inline int __attribute__((always_inline)) +__lll_mutex_trylock(int *futex) +{ +  return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0; +} +#define lll_mutex_trylock(lock)	__lll_mutex_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_mutex_cond_trylock(int *futex) +{ +  return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0; +} +#define lll_mutex_cond_trylock(lock)	__lll_mutex_cond_trylock (&(lock)) + + +extern void __lll_lock_wait (int *futex) attribute_hidden; + +static inline void __attribute__((always_inline)) +__lll_mutex_lock(int *futex) +{ +  if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) +    __lll_lock_wait (futex); +} +#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex)) + + +static inline void __attribute__ ((always_inline)) +__lll_mutex_cond_lock (int *futex) +{ +  if (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0) +    __lll_lock_wait (futex); +} +#define lll_mutex_cond_lock(futex) __lll_mutex_cond_lock (&(futex)) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *) +	attribute_hidden; + +static inline int __attribute__ ((always_inline)) +__lll_mutex_timedlock (int *futex, const struct timespec *abstime) +{ +  int result = 0; +  if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) +    result = __lll_timedlock_wait (futex, abstime); +  return result; +} +#define lll_mutex_timedlock(futex, abstime) \ +  __lll_mutex_timedlock (&(futex), abstime) + + +static inline void __attribute__ ((always_inline)) +__lll_mutex_unlock (int *futex) +{ +  int val = atomic_exchange_rel (futex, 0); +  if (__builtin_expect (val > 1, 0)) +    lll_futex_wake (futex, 1); +} +#define lll_mutex_unlock(futex) __lll_mutex_unlock(&(futex)) + + +static inline void __attribute__ ((always_inline)) +__lll_mutex_unlock_force (int *futex) +{ +  (void) atomic_exchange_rel (futex, 0); +  lll_futex_wake (futex, 1); +} +#define lll_mutex_unlock_force(futex) __lll_mutex_unlock_force(&(futex)) + + +#define lll_mutex_islocked(futex) \ +  (futex != 0) + + +/* Our internal lock implementation is identical to the binary-compatible +   mutex implementation. */ + +/* Type for lock object.  */ +typedef int lll_lock_t; + +/* Initializers for lock.  */ +#define LLL_LOCK_INITIALIZER		(0) +#define LLL_LOCK_INITIALIZER_LOCKED	(1) + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + +/* The states of a lock are: +    0  -  untaken +    1  -  taken by one user +   >1  -  taken by more users */ + +#define lll_trylock(lock)	lll_mutex_trylock (lock) +#define lll_lock(lock)		lll_mutex_lock (lock) +#define lll_unlock(lock)	lll_mutex_unlock (lock) +#define lll_islocked(lock)	lll_mutex_islocked (lock) + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex +   wakeup when the clone terminates.  The memory location contains the +   thread ID while the clone is running and is reset to zero +   afterwards.	*/ +#define lll_wait_tid(tid) \ +  do {					\ +    __typeof (tid) __tid;		\ +    while ((__tid = (tid)) != 0)	\ +      lll_futex_wait (&(tid), __tid);	\ +  } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) +     attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ +  ({							\ +    int __res = 0;					\ +    if ((tid) != 0)					\ +      __res = __lll_timedwait_tid (&(tid), (abstime));	\ +    __res;						\ +  }) + + +/* Conditional variable handling.  */ + +extern void __lll_cond_wait (pthread_cond_t *cond) +     attribute_hidden; +extern int __lll_cond_timedwait (pthread_cond_t *cond, +				 const struct timespec *abstime) +     attribute_hidden; +extern void __lll_cond_wake (pthread_cond_t *cond) +     attribute_hidden; +extern void __lll_cond_broadcast (pthread_cond_t *cond) +     attribute_hidden; + +#define lll_cond_wait(cond) \ +  __lll_cond_wait (cond) +#define lll_cond_timedwait(cond, abstime) \ +  __lll_cond_timedwait (cond, abstime) +#define lll_cond_wake(cond) \ +  __lll_cond_wake (cond) +#define lll_cond_broadcast(cond) \ +  __lll_cond_broadcast (cond) + +#endif	/* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-__syscall_rt_sigaction.c b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-__syscall_rt_sigaction.c new file mode 100644 index 000000000..50137c84a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-__syscall_rt_sigaction.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/common/__syscall_rt_sigaction.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-clone.S new file mode 100644 index 000000000..add405523 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <../../../../../../../libc/sysdeps/linux/mips/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S new file mode 100644 index 000000000..c02ffca93 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S @@ -0,0 +1,38 @@ +/* Copyright (C) 2005 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 <features.h> +#include <tls.h> + +/* Save the PID value.  */ +#define SAVE_PID \ +	READ_THREAD_POINTER(v1);	/* Get the thread pointer.  */	\ +	lw	a2, PID_OFFSET(v1);	/* Load the saved PID.  */	\ +	subu	a2, $0, a2;		/* Negate it.  */		\ +	sw	a2, PID_OFFSET(v1);	/* Store the temporary PID.  */ + +/* Restore the old PID value in the parent.  */ +#define RESTORE_PID \ +	beqz	v0, 1f;			/* If we are the parent... */	\ +	READ_THREAD_POINTER(v1);	/* Get the thread pointer.  */	\ +	lw	a2, PID_OFFSET(v1);	/* Load the saved PID.  */	\ +	subu	a2, $0, a2;		/* Re-negate it.  */		\ +	sw	a2, PID_OFFSET(v1);	/* Restore the PID.  */		\ +1: + +#include <../../../../../../../libc/sysdeps/linux/mips/vfork.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pthread_once.c new file mode 100644 index 000000000..649b752f5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pthread_once.c @@ -0,0 +1,94 @@ +/* Copyright (C) 2003, 2004, 2005 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 "pthreadP.h" +#include <lowlevellock.h> + + +unsigned long int __fork_generation attribute_hidden; + + +static void +clear_once_control (void *arg) +{ +  pthread_once_t *once_control = (pthread_once_t *) arg; + +  *once_control = 0; +  lll_futex_wake (once_control, INT_MAX); +} + + +int +__pthread_once (once_control, init_routine) +     pthread_once_t *once_control; +     void (*init_routine) (void); +{ +  while (1) +    { +      int oldval, val, newval; + +      val = *once_control; +      do +	{ +	  /* Check if the initialized has already been done.  */ +	  if ((val & 2) != 0) +	    return 0; + +	  oldval = val; +	  newval = (oldval & 3) | __fork_generation | 1; +	  val = atomic_compare_and_exchange_val_acq (once_control, newval, +						     oldval); +	} +      while (__builtin_expect (val != oldval, 0)); + +      /* Check if another thread already runs the initializer.	*/ +      if ((oldval & 1) != 0) +	{ +	  /* Check whether the initializer execution was interrupted +	     by a fork.	 */ +	  if (((oldval ^ newval) & -4) == 0) +	    { +	      /* Same generation, some other thread was faster. Wait.  */ +	      lll_futex_wait (once_control, newval); +	      continue; +	    } +	} + +      /* This thread is the first here.  Do the initialization. +	 Register a cleanup handler so that in case the thread gets +	 interrupted the initialization can be restarted.  */ +      pthread_cleanup_push (clear_once_control, once_control); + +      init_routine (); + +      pthread_cleanup_pop (0); + + +      /* Add one to *once_control.  */ +      atomic_increment (once_control); + +      /* Wake up all other threads.  */ +      lll_futex_wake (once_control, INT_MAX); +      break; +    } + +  return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h new file mode 100644 index 000000000..5fee89235 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h @@ -0,0 +1,169 @@ +/* Copyright (C) 2003, 2004, 2005 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 <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +#ifdef __PIC__ +# undef PSEUDO +# define PSEUDO(name, syscall_name, args)				      \ +      .align 2;								      \ +  L(pseudo_start):							      \ +      cfi_startproc;							      \ +  99: la t9,__syscall_error;						      \ +      jr t9;								      \ +  .type __##syscall_name##_nocancel, @function;				      \ +  .globl __##syscall_name##_nocancel;					      \ +  __##syscall_name##_nocancel:						      \ +    .set noreorder;							      \ +    .cpload t9;								      \ +    li v0, SYS_ify(syscall_name);					      \ +    syscall;								      \ +    .set reorder;							      \ +    bne a3, zero, SYSCALL_ERROR_LABEL;			       		      \ +    ret;								      \ +  .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \ +  ENTRY (name)								      \ +    .set noreorder;							      \ +    .cpload t9;								      \ +    .set reorder;							      \ +    SINGLE_THREAD_P(v1);						      \ +    bne zero, v1, L(pseudo_cancel);					      \ +    .set noreorder;							      \ +    li v0, SYS_ify(syscall_name);					      \ +    syscall;								      \ +    .set reorder;							      \ +    bne a3, zero, SYSCALL_ERROR_LABEL;			       		      \ +    ret;								      \ +  L(pseudo_cancel):							      \ +    SAVESTK_##args;						              \ +    sw ra, 28(sp);							      \ +    cfi_rel_offset (ra, 28);						      \ +    sw gp, 32(sp);							      \ +    cfi_rel_offset (gp, 32);						      \ +    PUSHARGS_##args;			/* save syscall args */	      	      \ +    CENABLE;								      \ +    lw gp, 32(sp);							      \ +    sw v0, 44(sp);			/* save mask */			      \ +    POPARGS_##args;			/* restore syscall args */	      \ +    .set noreorder;							      \ +    li v0, SYS_ify (syscall_name);				      	      \ +    syscall;								      \ +    .set reorder;							      \ +    sw v0, 36(sp);			/* save syscall result */             \ +    sw a3, 40(sp);			/* save syscall error flag */	      \ +    lw a0, 44(sp);			/* pass mask as arg1 */		      \ +    CDISABLE;								      \ +    lw gp, 32(sp);							      \ +    lw v0, 36(sp);			/* restore syscall result */          \ +    lw a3, 40(sp);			/* restore syscall error flag */      \ +    lw ra, 28(sp);			/* restore return address */	      \ +    .set noreorder;							      \ +    bne a3, zero, SYSCALL_ERROR_LABEL;					      \ +     RESTORESTK;						              \ +  L(pseudo_end):							      \ +    .set reorder; + +# undef PSEUDO_END +# define PSEUDO_END(sym) cfi_endproc; .end sym; .size sym,.-sym + +#endif + +# define PUSHARGS_0	/* nothing to do */ +# define PUSHARGS_1	PUSHARGS_0 sw a0, 0(sp); cfi_rel_offset (a0, 0); +# define PUSHARGS_2	PUSHARGS_1 sw a1, 4(sp); cfi_rel_offset (a1, 4); +# define PUSHARGS_3	PUSHARGS_2 sw a2, 8(sp); cfi_rel_offset (a2, 8); +# define PUSHARGS_4	PUSHARGS_3 sw a3, 12(sp); cfi_rel_offset (a3, 12); +# define PUSHARGS_5	PUSHARGS_4 /* handled by SAVESTK_## */ +# define PUSHARGS_6	PUSHARGS_5 +# define PUSHARGS_7	PUSHARGS_6 + +# define POPARGS_0	/* nothing to do */ +# define POPARGS_1	POPARGS_0 lw a0, 0(sp); +# define POPARGS_2	POPARGS_1 lw a1, 4(sp); +# define POPARGS_3	POPARGS_2 lw a2, 8(sp); +# define POPARGS_4	POPARGS_3 lw a3, 12(sp); +# define POPARGS_5	POPARGS_4 /* args already in new stackframe */ +# define POPARGS_6	POPARGS_5 +# define POPARGS_7	POPARGS_6 + + +# define STKSPACE	48 +# define SAVESTK_0 	subu sp, STKSPACE; cfi_adjust_cfa_offset(STKSPACE) +# define SAVESTK_1      SAVESTK_0 +# define SAVESTK_2      SAVESTK_1 +# define SAVESTK_3      SAVESTK_2 +# define SAVESTK_4      SAVESTK_3 +# define SAVESTK_5      lw t0, 16(sp);		\ +			SAVESTK_0;		\ +			sw t0, 16(sp) + +# define SAVESTK_6      lw t0, 16(sp);		\ +			lw t1, 20(sp);		\ +			SAVESTK_0;		\ +			sw t0, 16(sp);		\ +			sw t1, 20(sp) + +# define SAVESTK_7      lw t0, 16(sp);		\ +			lw t1, 20(sp);		\ +			lw t2, 24(sp);		\ +			SAVESTK_0;		\ +			sw t0, 16(sp);		\ +			sw t1, 20(sp);		\ +			sw t2, 24(sp) + +# define RESTORESTK 	addu sp, STKSPACE; cfi_adjust_cfa_offset(-STKSPACE) + + +/* We use jalr rather than jal.  This means that the assembler will not +   automatically restore $gp (in case libc has multiple GOTs) so we must +   do it manually - which we have to do anyway since we don't use .cprestore. +   It also shuts up the assembler warning about not using .cprestore.  */ +# ifdef IS_IN_libpthread +#  define CENABLE	la t9, __pthread_enable_asynccancel; jalr t9; +#  define CDISABLE	la t9, __pthread_disable_asynccancel; jalr t9; +# elif defined IS_IN_librt +#  define CENABLE	la t9, __librt_enable_asynccancel; jalr t9; +#  define CDISABLE	la t9, __librt_disable_asynccancel; jalr t9; +# else +#  define CENABLE	la t9, __libc_enable_asynccancel; jalr t9; +#  define CDISABLE	la t9, __libc_disable_asynccancel; jalr t9; +# endif + +# ifndef __ASSEMBLER__ +#  define SINGLE_THREAD_P						\ +	__builtin_expect (THREAD_GETMEM (THREAD_SELF,			\ +					 header.multiple_threads)	\ +			  == 0, 1) +# else +#  define SINGLE_THREAD_P(reg)						\ +	READ_THREAD_POINTER(reg);					\ +	lw reg, MULTIPLE_THREADS_OFFSET(reg) +#endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P 1 +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep.h new file mode 100644 index 000000000..bfaab1f3a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep.h @@ -0,0 +1,302 @@ +/* Copyright (C) 2000, 2002, 2003, 2004, 2005 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 _LINUX_MIPS_MIPS32_SYSDEP_H +#define _LINUX_MIPS_MIPS32_SYSDEP_H 1 + +#include <sys/syscall.h> + +/* There is some commonality.  */ +#include <sysdeps/mips/sysdep.h> + +/* For Linux we can use the system call table in the header file +	/usr/include/asm/unistd.h +   of the kernel.  But these symbols do not follow the SYS_* syntax +   so we have to redefine the `SYS_ify' macro here.  */ +#undef SYS_ify +#ifdef __STDC__ +# define SYS_ify(syscall_name)	__NR_##syscall_name +#else +# define SYS_ify(syscall_name)	__NR_/**/syscall_name +#endif + +#ifdef __ASSEMBLER__ + +/* We don't want the label for the error handler to be visible in the symbol +   table when we define it here.  */ +#ifdef __PIC__ +# define SYSCALL_ERROR_LABEL 99b +#endif + +#else   /* ! __ASSEMBLER__ */ + +/* Define a macro which expands into the inline wrapper code for a system +   call.  */ +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...)                               \ +  ({ INTERNAL_SYSCALL_DECL(err);					\ +     long result_var = INTERNAL_SYSCALL (name, err, nr, args);		\ +     if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) )			\ +       {								\ +	 __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err));	\ +	 result_var = -1L;						\ +       }								\ +     result_var; }) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) long err + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err)   ((long) (err)) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, err)     (val) + +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ +	internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t",	\ +			      "i" (SYS_ify (name)), err, args) + +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ +	internal_syscall##nr (= number, , "r" (__v0), err, args) +#undef internal_syscall0 +#define internal_syscall0(ncs_init, cs_init, input, err, dummy...)	\ +({									\ +	long _sys_result;						\ +									\ +	{								\ +	register long __v0 __asm__("$2") ncs_init;			\ +	register long __a3 __asm__("$7");				\ +	__asm__ volatile (						\ +	".set\tnoreorder\n\t"						\ +	cs_init								\ +	"syscall\n\t"							\ +	".set reorder"							\ +	: "=r" (__v0), "=r" (__a3)					\ +	: input								\ +	: __SYSCALL_CLOBBERS);						\ +	err = __a3;							\ +	_sys_result = __v0;						\ +	}								\ +	_sys_result;							\ +}) + +#undef internal_syscall1 +#define internal_syscall1(ncs_init, cs_init, input, err, arg1)		\ +({									\ +	long _sys_result;						\ +									\ +	{								\ +	register long __v0 __asm__("$2") ncs_init;			\ +	register long __a0 __asm__("$4") = (long) arg1;			\ +	register long __a3 __asm__("$7");				\ +	__asm__ volatile (						\ +	".set\tnoreorder\n\t"						\ +	cs_init								\ +	"syscall\n\t"							\ +	".set reorder"							\ +	: "=r" (__v0), "=r" (__a3)					\ +	: input, "r" (__a0)						\ +	: __SYSCALL_CLOBBERS);						\ +	err = __a3;							\ +	_sys_result = __v0;						\ +	}								\ +	_sys_result;							\ +}) + +#undef internal_syscall2 +#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2)	\ +({									\ +	long _sys_result;						\ +									\ +	{								\ +	register long __v0 __asm__("$2") ncs_init;			\ +	register long __a0 __asm__("$4") = (long) arg1;			\ +	register long __a1 __asm__("$5") = (long) arg2;			\ +	register long __a3 __asm__("$7");				\ +	__asm__ volatile (						\ +	".set\tnoreorder\n\t"						\ +	cs_init								\ +	"syscall\n\t"							\ +	".set\treorder"							\ +	: "=r" (__v0), "=r" (__a3)					\ +	: input, "r" (__a0), "r" (__a1)					\ +	: __SYSCALL_CLOBBERS);						\ +	err = __a3;							\ +	_sys_result = __v0;						\ +	}								\ +	_sys_result;							\ +}) + +#undef internal_syscall3 +#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\ +({									\ +	long _sys_result;						\ +									\ +	{								\ +	register long __v0 __asm__("$2") ncs_init;			\ +	register long __a0 __asm__("$4") = (long) arg1;			\ +	register long __a1 __asm__("$5") = (long) arg2;			\ +	register long __a2 __asm__("$6") = (long) arg3;			\ +	register long __a3 __asm__("$7");				\ +	__asm__ volatile (						\ +	".set\tnoreorder\n\t"						\ +	cs_init								\ +	"syscall\n\t"							\ +	".set\treorder"							\ +	: "=r" (__v0), "=r" (__a3)					\ +	: input, "r" (__a0), "r" (__a1), "r" (__a2)			\ +	: __SYSCALL_CLOBBERS);						\ +	err = __a3;							\ +	_sys_result = __v0;						\ +	}								\ +	_sys_result;							\ +}) + +#undef internal_syscall4 +#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\ +({									\ +	long _sys_result;						\ +									\ +	{								\ +	register long __v0 __asm__("$2") ncs_init;			\ +	register long __a0 __asm__("$4") = (long) arg1;			\ +	register long __a1 __asm__("$5") = (long) arg2;			\ +	register long __a2 __asm__("$6") = (long) arg3;			\ +	register long __a3 __asm__("$7") = (long) arg4;			\ +	__asm__ volatile (						\ +	".set\tnoreorder\n\t"						\ +	cs_init								\ +	"syscall\n\t"							\ +	".set\treorder"							\ +	: "=r" (__v0), "+r" (__a3)					\ +	: input, "r" (__a0), "r" (__a1), "r" (__a2)			\ +	: __SYSCALL_CLOBBERS);						\ +	err = __a3;							\ +	_sys_result = __v0;						\ +	}								\ +	_sys_result;							\ +}) + +/* We need to use a frame pointer for the functions in which we +   adjust $sp around the syscall, or debug information and unwind +   information will be $sp relative and thus wrong during the syscall.  As +   of GCC 3.4.3, this is sufficient.  */ +#define FORCE_FRAME_POINTER alloca (4) + +#undef internal_syscall5 +#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\ +({									\ +	long _sys_result;						\ +									\ +	FORCE_FRAME_POINTER;						\ +	{								\ +	register long __v0 __asm__("$2") ncs_init;			\ +	register long __a0 __asm__("$4") = (long) arg1;			\ +	register long __a1 __asm__("$5") = (long) arg2;			\ +	register long __a2 __asm__("$6") = (long) arg3;			\ +	register long __a3 __asm__("$7") = (long) arg4;			\ +	__asm__ volatile (						\ +	".set\tnoreorder\n\t"						\ +	"subu\t$29, 32\n\t"						\ +	"sw\t%6, 16($29)\n\t"						\ +	cs_init								\ +	"syscall\n\t"							\ +	"addiu\t$29, 32\n\t"						\ +	".set\treorder"							\ +	: "=r" (__v0), "+r" (__a3)					\ +	: input, "r" (__a0), "r" (__a1), "r" (__a2),			\ +	  "r" ((long)arg5)						\ +	: __SYSCALL_CLOBBERS);						\ +	err = __a3;							\ +	_sys_result = __v0;						\ +	}								\ +	_sys_result;							\ +}) + +#undef internal_syscall6 +#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\ +({									\ +	long _sys_result;						\ +									\ +	FORCE_FRAME_POINTER;						\ +	{								\ +	register long __v0 __asm__("$2") ncs_init;			\ +	register long __a0 __asm__("$4") = (long) arg1;			\ +	register long __a1 __asm__("$5") = (long) arg2;			\ +	register long __a2 __asm__("$6") = (long) arg3;			\ +	register long __a3 __asm__("$7") = (long) arg4;			\ +	__asm__ volatile (						\ +	".set\tnoreorder\n\t"						\ +	"subu\t$29, 32\n\t"						\ +	"sw\t%6, 16($29)\n\t"						\ +	"sw\t%7, 20($29)\n\t"						\ +	cs_init								\ +	"syscall\n\t"							\ +	"addiu\t$29, 32\n\t"						\ +	".set\treorder"							\ +	: "=r" (__v0), "+r" (__a3)					\ +	: input, "r" (__a0), "r" (__a1), "r" (__a2),			\ +	  "r" ((long)arg5), "r" ((long)arg6)				\ +	: __SYSCALL_CLOBBERS);						\ +	err = __a3;							\ +	_sys_result = __v0;						\ +	}								\ +	_sys_result;							\ +}) + +#undef internal_syscall7 +#define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\ +({									\ +	long _sys_result;						\ +									\ +	FORCE_FRAME_POINTER;						\ +	{								\ +	register long __v0 __asm__("$2") ncs_init;			\ +	register long __a0 __asm__("$4") = (long) arg1;			\ +	register long __a1 __asm__("$5") = (long) arg2;			\ +	register long __a2 __asm__("$6") = (long) arg3;			\ +	register long __a3 __asm__("$7") = (long) arg4;			\ +	__asm__ volatile (						\ +	".set\tnoreorder\n\t"						\ +	"subu\t$29, 32\n\t"						\ +	"sw\t%6, 16($29)\n\t"						\ +	"sw\t%7, 20($29)\n\t"						\ +	"sw\t%8, 24($29)\n\t"						\ +	cs_init								\ +	"syscall\n\t"							\ +	"addiu\t$29, 32\n\t"						\ +	".set\treorder"							\ +	: "=r" (__v0), "+r" (__a3)					\ +	: input, "r" (__a0), "r" (__a1), "r" (__a2),			\ +	  "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7)		\ +	: __SYSCALL_CLOBBERS);						\ +	err = __a3;							\ +	_sys_result = __v0;						\ +	}								\ +	_sys_result;							\ +}) + +#undef __SYSCALL_CLOBBERS +#define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \ +	"$14", "$15", "$24", "$25", "memory" + +#endif /* __ASSEMBLER__ */ + +#endif /* sysdeps/unix/sysv/linux/mips/sysdep.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mq_notify.c b/libpthread/nptl/sysdeps/unix/sysv/linux/mq_notify.c new file mode 100644 index 000000000..9d16fee56 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mq_notify.c @@ -0,0 +1,285 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contribute by Ulrich Drepper <drepper@redhat.com>, 2004. + +   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 <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> +#include <pthread.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <sysdep.h> +#include <unistd.h> +#include <sys/socket.h> +#include <not-cancel.h> + + +#ifdef __NR_mq_notify + +/* Defined in the kernel headers: */ +#define NOTIFY_COOKIE_LEN	32	/* Length of the cookie used.  */ +#define NOTIFY_WOKENUP		1	/* Code for notifcation.  */ +#define NOTIFY_REMOVED		2	/* Code for closed message queue +					   of de-notifcation.  */ + + +/* Data structure for the queued notification requests.  */ +union notify_data +{ +  struct +  { +    void (*fct) (union sigval);	/* The function to run.  */ +    union sigval param;		/* The parameter to pass.  */ +    pthread_attr_t *attr;	/* Attributes to create the thread with.  */ +    /* NB: on 64-bit machines the struct as a size of 24 bytes.  Which means +       byte 31 can still be used for returning the status.  */ +  }; +  char raw[NOTIFY_COOKIE_LEN]; +}; + + +/* Keep track of the initialization.  */ +static pthread_once_t once = PTHREAD_ONCE_INIT; + + +/* The netlink socket.  */ +static int netlink_socket = -1; + + +/* Barrier used to make sure data passed to the new thread is not +   resused by the parent.  */ +static pthread_barrier_t notify_barrier; + + +/* Modify the signal mask.  We move this into a separate function so +   that the stack space needed for sigset_t is not deducted from what +   the thread can use.  */ +static int +__attribute__ ((noinline)) +change_sigmask (int how, sigset_t *oss) +{ +  sigset_t ss; +  sigfillset (&ss); +  return pthread_sigmask (how, &ss, oss); +} + + +/* The function used for the notification.  */ +static void * +notification_function (void *arg) +{ +  /* Copy the function and parameter so that the parent thread can go +     on with its life.  */ +  volatile union notify_data *data = (volatile union notify_data *) arg; +  void (*fct) (union sigval) = data->fct; +  union sigval param = data->param; + +  /* Let the parent go.  */ +  (void) pthread_barrier_wait (¬ify_barrier); + +  /* Make the thread detached.  */ +  (void) pthread_detach (pthread_self ()); + +  /* The parent thread has all signals blocked.  This is probably a +     bit surprising for this thread.  So we unblock all of them.  */ +  (void) change_sigmask (SIG_UNBLOCK, NULL); + +  /* Now run the user code.  */ +  fct (param); + +  /* And we are done.  */ +  return NULL; +} + + +/* Helper thread.  */ +static void * +helper_thread (void *arg) +{ +  while (1) +    { +      union notify_data data; + +      ssize_t n = recv (netlink_socket, &data, sizeof (data), +			MSG_NOSIGNAL | MSG_WAITALL); +      if (n < NOTIFY_COOKIE_LEN) +	continue; + +      if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_WOKENUP) +	{ +	  /* Just create the thread as instructed.  There is no way to +	     report a problem with creating a thread.  */ +	  pthread_t th; +	  if (__builtin_expect (pthread_create (&th, data.attr, +						notification_function, &data) +				== 0, 0)) +	    /* Since we passed a pointer to DATA to the new thread we have +	       to wait until it is done with it.  */ +	    (void) pthread_barrier_wait (¬ify_barrier); +	} +      else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) +	/* The only state we keep is the copy of the thread attributes.  */ +	free (data.attr); +    } +  return NULL; +} + + +static void +reset_once (void) +{ +  once = PTHREAD_ONCE_INIT; +} + + +static void +init_mq_netlink (void) +{ +  /* This code might be called a second time after fork().  The file +     descriptor is inherited from the parent.  */ +  if (netlink_socket == -1) +    { +      /* Just a normal netlink socket, not bound.  */ +      netlink_socket = socket (AF_NETLINK, SOCK_RAW, 0); +      /* No need to do more if we have no socket.  */ +      if (netlink_socket == -1) +	return; + +      /* Make sure the descriptor is closed on exec.  */ +      if (fcntl (netlink_socket, F_SETFD, FD_CLOEXEC) != 0) +	goto errout; +    } + +  int err = 1; + +  /* Initialize the barrier.  */ +  if (__builtin_expect (pthread_barrier_init (¬ify_barrier, NULL, 2) == 0, +			0)) +    { +      /* Create the helper thread.  */ +      pthread_attr_t attr; +      (void) pthread_attr_init (&attr); +      (void) pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); +      /* We do not need much stack space, the bare minimum will be enough.  */ +      (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + +      /* Temporarily block all signals so that the newly created +	 thread inherits the mask.  */ +      sigset_t oss; +      int have_no_oss = change_sigmask (SIG_BLOCK, &oss); + +      pthread_t th; +      err = pthread_create (&th, &attr, helper_thread, NULL); + +      /* Reset the signal mask.  */ +      if (!have_no_oss) +	pthread_sigmask (SIG_SETMASK, &oss, NULL); + +      (void) pthread_attr_destroy (&attr); + +      if (err == 0) +	{ +	  static int added_atfork; + +	  if (added_atfork == 0 +	      && pthread_atfork (NULL, NULL, reset_once) != 0) +	    { +	      /* The child thread will call recv() which is a +		 cancellation point.  */ +	      (void) pthread_cancel (th); +	      err = 1; +	    } +	  else +	    added_atfork = 1; +	} +    } + +  if (err != 0) +    { +    errout: +      close_not_cancel_no_status (netlink_socket); +      netlink_socket = -1; +    } +} + + +/* Register notification upon message arrival to an empty message queue +   MQDES.  */ +int +mq_notify (mqd_t mqdes, const struct sigevent *notification) +{ +  /* Make sure the type is correctly defined.  */ +  assert (sizeof (union notify_data) == NOTIFY_COOKIE_LEN); + +  /* Special treatment needed for SIGEV_THREAD.  */ +  if (notification == NULL || notification->sigev_notify != SIGEV_THREAD) +    return INLINE_SYSCALL (mq_notify, 2, mqdes, notification); + +  /* The kernel cannot directly start threads.  This will have to be +     done at userlevel.  Since we cannot start threads from signal +     handlers we have to create a dedicated thread which waits for +     notifications for arriving messages and creates threads in +     response.  */ + +  /* Initialize only once.  */ +  pthread_once (&once, init_mq_netlink); + +  /* If we cannot create the netlink socket we cannot provide +     SIGEV_THREAD support.  */ +  if (__builtin_expect (netlink_socket == -1, 0)) +    { +      __set_errno (ENOSYS); +      return -1; +    } + +  /* Create the cookie.  It will hold almost all the state.  */ +  union notify_data data; +  memset (&data, '\0', sizeof (data)); +  data.fct = notification->sigev_notify_function; +  data.param = notification->sigev_value; + +  if (notification->sigev_notify_attributes != NULL) +    { +      /* The thread attribute has to be allocated separately.  */ +      data.attr = (pthread_attr_t *) malloc (sizeof (pthread_attr_t)); +      if (data.attr == NULL) +	return -1; + +      memcpy (data.attr, notification->sigev_notify_attributes, +	      sizeof (pthread_attr_t)); +    } + +  /* Construct the new request.  */ +  struct sigevent se; +  se.sigev_notify = SIGEV_THREAD; +  se.sigev_signo = netlink_socket; +  se.sigev_value.sival_ptr = &data; + +  /* Tell the kernel.  */ +  int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); + +  /* If it failed, free the allocated memory.  */ +  if (__builtin_expect (retval != 0, 0)) +    free (data.attr); + +  return retval; +} + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/msync.S b/libpthread/nptl/sysdeps/unix/sysv/linux/msync.S new file mode 100644 index 000000000..074a0d717 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/msync.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_msync, msync, 3) +ret +PSEUDO_END(__libc_msync) +libc_hidden_def (__libc_msync) +weak_alias (__libc_msync, msync) +libc_hidden_weak (msync) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.S b/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.S new file mode 100644 index 000000000..71efe32f9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.S @@ -0,0 +1,9 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_nanosleep, nanosleep, 3) +ret +PSEUDO_END (__libc_nanosleep) +libc_hidden_def (__libc_nanosleep) +weak_alias (__libc_nanosleep, __nanosleep) +libc_hidden_weak (__nanosleep) +weak_alias (__libc_nanosleep, nanosleep) +libc_hidden_weak (nanosleep) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/not-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/not-cancel.h new file mode 100644 index 000000000..9418417b4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/not-cancel.h @@ -0,0 +1,60 @@ +/* Uncancelable versions of cancelable interfaces.  Linux version. +   Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 <sysdep.h> + +/* Uncancelable open.  */ +#define open_not_cancel(name, flags, mode) \ +   INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode)) +#define open_not_cancel_2(name, flags) \ +   INLINE_SYSCALL (open, 2, (const char *) (name), (flags)) + +/* Uncancelable close.  */ +#define close_not_cancel(fd) \ +  INLINE_SYSCALL (close, 1, fd) +#define close_not_cancel_no_status(fd) \ +  (void) ({ INTERNAL_SYSCALL_DECL (err);				      \ +	    INTERNAL_SYSCALL (close, err, 1, (fd)); }) + +/* Uncancelable read.  */ +#define read_not_cancel(fd, buf, n) \ +  INLINE_SYSCALL (read, 3, (fd), (buf), (n)) + +/* Uncancelable write.  */ +#define write_not_cancel(fd, buf, n) \ +  INLINE_SYSCALL (write, 3, (fd), (buf), (n)) + +/* Uncancelable writev.  */ +#define writev_not_cancel_no_status(fd, iov, n) \ +  (void) ({ INTERNAL_SYSCALL_DECL (err);				      \ +	    INTERNAL_SYSCALL (writev, err, 3, (fd), (iov), (n)); }) + +/* Uncancelable fcntl.  */ +#define fcntl_not_cancel(fd, cmd, val) \ +  __fcntl_nocancel (fd, cmd, val) + +/* Uncancelable waitpid.  */ +#ifdef __NR_waitpid +# define waitpid_not_cancel(pid, stat_loc, options) \ +  INLINE_SYSCALL (waitpid, 3, pid, stat_loc, options) +#else +# define waitpid_not_cancel(pid, stat_loc, options) \ +  INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/open.S b/libpthread/nptl/sysdeps/unix/sysv/linux/open.S new file mode 100644 index 000000000..486686a22 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/open.S @@ -0,0 +1,21 @@ +#include <sysdep-cancel.h> + +/* +extern int __open_nocancel (const char *, int, ...) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +PSEUDO (__libc_open, open, 3) +ret +PSEUDO_END(__libc_open) + +libc_hidden_def (__open_nocancel) +libc_hidden_def (__libc_open) +weak_alias (__libc_open, __open) +libc_hidden_weak (__open) +weak_alias (__libc_open, open) +libc_hidden_weak (open) + + + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pause.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pause.S new file mode 100644 index 000000000..3841018a8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pause.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_pause, pause, 0) +ret +PSEUDO_END (__libc_pause) +libc_hidden_def (__libc_pause) +weak_alias (__libc_pause, pause) +libc_hidden_weak (pause) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile new file mode 100644 index 000000000..e98c9bd86 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile @@ -0,0 +1,2 @@ +# pull in __syscall_error routine +libpthread-routines += sysdep diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Versions b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Versions new file mode 100644 index 000000000..997784798 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Versions @@ -0,0 +1,5 @@ +libpthread { +  GLIBC_2.3.4 { +    longjmp; siglongjmp; +  } +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h new file mode 100644 index 000000000..c94ed0c38 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h @@ -0,0 +1,216 @@ +/* Machine-specific pthread type layouts.  PowerPC version. +   Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.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.  */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H	1 + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers.  The structure of the attribute type is +   deliberately not exposed.  */ +typedef unsigned long int pthread_t; + + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_ATTR_T]; +  long int __align; +} pthread_attr_t; + +#if __WORDSIZE == 64 +typedef struct __pthread_internal_list +{ +  struct __pthread_internal_list *__prev; +  struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ +  struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + +/* Data structures for mutex handling.  The structure of the attribute +   type is deliberately not exposed.  */ +typedef union +{ +  struct __pthread_mutex_s +  { +    int __lock; +    unsigned int __count; +    int __owner; +#if __WORDSIZE == 64 +    unsigned int __nusers; +#endif +    /* KIND must stay at this position in the structure to maintain +       binary compatibility.  */ +    int __kind; +#if __WORDSIZE == 64 +    int __spins; +    __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV      1 +#else +    unsigned int __nusers; +    __extension__ union +    { +      int __spins; +      __pthread_slist_t __list; +    }; +#endif +  } __data; +  char __size[__SIZEOF_PTHREAD_MUTEX_T]; +  long int __align; +} pthread_mutex_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; +  int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling.  The structure of +   the attribute type is deliberately not exposed.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __futex; +    __extension__ unsigned long long int __total_seq; +    __extension__ unsigned long long int __wakeup_seq; +    __extension__ unsigned long long int __woken_seq; +    void *__mutex; +    unsigned int __nwaiters; +    unsigned int __broadcast_seq; +  } __data; +  char __size[__SIZEOF_PTHREAD_COND_T]; +  __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_CONDATTR_T]; +  int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling.  The +   structure of the attribute type is deliberately not exposed.  */ +typedef union +{ +# if __WORDSIZE == 64 +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    int __writer; +    int __pad1; +    unsigned long int __pad2; +    unsigned long int __pad3; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +  } __data; +# else +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +    int __writer; +  } __data; +# endif +  char __size[__SIZEOF_PTHREAD_RWLOCK_T]; +  long int __align; +} pthread_rwlock_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; +  long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type.  */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type.  The structure of the type is +   deliberately not exposed.  */ +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIER_T]; +  long int __align; +} pthread_barrier_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; +  int __align; +} pthread_barrierattr_t; +#endif + + +#endif	/* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h new file mode 100644 index 000000000..8123b418b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h @@ -0,0 +1,44 @@ +/* Machine-specific POSIX semaphore type layouts.  PowerPC version. +   Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.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.  */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_SEM_T	32 +#else +# define __SIZEOF_SEM_T	16 +#endif + +/* Value returned if `sem_open' failed.  */ +#define SEM_FAILED      ((sem_t *) 0) + +/* Maximum value the semaphore can have.  */ +#define SEM_VALUE_MAX   (2147483647) + + +typedef union +{ +  char __size[__SIZEOF_SEM_T]; +  long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c new file mode 100644 index 000000000..e811ad74e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.com>. + +   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.  */ + +/* Value passed to 'clone' for initialization of the thread register.  */ +#define TLS_VALUE ((void *) (pd) \ +		   + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +/* Get the real implementation.	 */ +#include <nptl/sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c new file mode 100644 index 000000000..06b7e1c69 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c @@ -0,0 +1 @@ +#include "../i386/fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h new file mode 100644 index 000000000..1f2f481d6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h @@ -0,0 +1,241 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.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.  */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H	1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> + + +#ifndef __NR_futex +# define __NR_futex		221 +#endif +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 +#define FUTEX_CMP_REQUEUE	4 + +/* Initializer for compatibility lock.	*/ +#define LLL_MUTEX_LOCK_INITIALIZER (0) + +#define lll_futex_wait(futexp, val) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +									      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAIT, (val), 0);		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret;		      \ +  }) + +#define lll_futex_timed_wait(futexp, val, timespec) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +									      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAIT, (val), (timespec));	      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret;		      \ +  }) + +#define lll_futex_wake(futexp, nr) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +									      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAKE, (nr), 0);		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret;		      \ +  }) + +/* Returns non-zero if error happened, zero if success.  */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +									      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 6,				      \ +			      (futexp), FUTEX_CMP_REQUEUE, (nr_wake),	      \ +			      (nr_move), (mutex), (val));		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \ +  }) + +#ifdef UP +# define __lll_acq_instr	"" +# define __lll_rel_instr	"" +#else +# define __lll_acq_instr	"isync" +# define __lll_rel_instr	"sync" +#endif + +/* Set *futex to 1 if it is 0, atomically.  Returns the old value */ +#define __lll_trylock(futex) \ +  ({ int __val;								      \ +     __asm __volatile ("1:	lwarx	%0,0,%2\n"			      \ +		       "	cmpwi	0,%0,0\n"			      \ +		       "	bne	2f\n"				      \ +		       "	stwcx.	%3,0,%2\n"			      \ +		       "	bne-	1b\n"				      \ +		       "2:	" __lll_acq_instr			      \ +		       : "=&r" (__val), "=m" (*futex)			      \ +		       : "r" (futex), "r" (1), "m" (*futex)		      \ +		       : "cr0", "memory");				      \ +     __val;								      \ +  }) + +#define lll_mutex_trylock(lock)	__lll_trylock (&(lock)) + +/* Set *futex to 2 if it is 0, atomically.  Returns the old value */ +#define __lll_cond_trylock(futex) \ +  ({ int __val;								      \ +     __asm __volatile ("1:	lwarx	%0,0,%2\n"			      \ +		       "	cmpwi	0,%0,0\n"			      \ +		       "	bne	2f\n"				      \ +		       "	stwcx.	%3,0,%2\n"			      \ +		       "	bne-	1b\n"				      \ +		       "2:	" __lll_acq_instr			      \ +		       : "=&r" (__val), "=m" (*futex)			      \ +		       : "r" (futex), "r" (2), "m" (*futex)		      \ +		       : "cr0", "memory");				      \ +     __val;								      \ +  }) +#define lll_mutex_cond_trylock(lock)	__lll_cond_trylock (&(lock)) + + +extern void __lll_lock_wait (int *futex) attribute_hidden; + +#define lll_mutex_lock(lock) \ +  (void) ({								      \ +    int *__futex = &(lock);						      \ +    if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, 1, 0),\ +			  0) != 0)					      \ +      __lll_lock_wait (__futex);					      \ +  }) + +#define lll_mutex_cond_lock(lock) \ +  (void) ({								      \ +    int *__futex = &(lock);						      \ +    if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, 2, 0),\ +			  0) != 0)					      \ +      __lll_lock_wait (__futex);					      \ +  }) + +extern int __lll_timedlock_wait +  (int *futex, const struct timespec *) attribute_hidden; + +#define lll_mutex_timedlock(lock, abstime) \ +  ({									      \ +    int *__futex = &(lock);						      \ +    int __val = 0;							      \ +    if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, 1, 0),\ +			  0) != 0)					      \ +      __val = __lll_timedlock_wait (__futex, abstime);			      \ +    __val;								      \ +  }) + +#define lll_mutex_unlock(lock) \ +  ((void) ({								      \ +    int *__futex = &(lock);						      \ +    int __val = atomic_exchange_rel (__futex, 0);			      \ +    if (__builtin_expect (__val > 1, 0))				      \ +      lll_futex_wake (__futex, 1);					      \ +  })) + +#define lll_mutex_unlock_force(lock) \ +  ((void) ({								      \ +    int *__futex = &(lock);						      \ +    *__futex = 0;							      \ +    __asm __volatile (__lll_rel_instr ::: "memory");			      \ +    lll_futex_wake (__futex, 1);					      \ +  })) + +#define lll_mutex_islocked(futex) \ +  (futex != 0) + + +/* Our internal lock implementation is identical to the binary-compatible +   mutex implementation. */ + +/* Type for lock object.  */ +typedef int lll_lock_t; + +/* Initializers for lock.  */ +#define LLL_LOCK_INITIALIZER		(0) +#define LLL_LOCK_INITIALIZER_LOCKED	(1) + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + +/* The states of a lock are: +    0  -  untaken +    1  -  taken by one user +   >1  -  taken by more users */ + +#define lll_trylock(lock)	lll_mutex_trylock (lock) +#define lll_lock(lock)		lll_mutex_lock (lock) +#define lll_unlock(lock)	lll_mutex_unlock (lock) +#define lll_islocked(lock)	lll_mutex_islocked (lock) + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex +   wakeup when the clone terminates.  The memory location contains the +   thread ID while the clone is running and is reset to zero +   afterwards.	*/ +#define lll_wait_tid(tid) \ +  do {									      \ +    __typeof (tid) __tid;						      \ +    while ((__tid = (tid)) != 0)					      \ +      lll_futex_wait (&(tid), __tid);					      \ +  } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) +     attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ +  ({									      \ +    int __res = 0;							      \ +    if ((tid) != 0)							      \ +      __res = __lll_timedwait_tid (&(tid), (abstime));			      \ +    __res;								      \ +  }) + + +/* Conditional variable handling.  */ + +extern void __lll_cond_wait (pthread_cond_t *cond) +     attribute_hidden; +extern int __lll_cond_timedwait (pthread_cond_t *cond, +				 const struct timespec *abstime) +     attribute_hidden; +extern void __lll_cond_wake (pthread_cond_t *cond) +     attribute_hidden; +extern void __lll_cond_broadcast (pthread_cond_t *cond) +     attribute_hidden; + +#define lll_cond_wait(cond) \ +  __lll_cond_wait (cond) +#define lll_cond_timedwait(cond, abstime) \ +  __lll_cond_timedwait (cond, abstime) +#define lll_cond_wake(cond) \ +  __lll_cond_wake (cond) +#define lll_cond_broadcast(cond) \ +  __lll_cond_broadcast (cond) + +#endif	/* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/not-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/not-cancel.h new file mode 100644 index 000000000..acf1a617e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/not-cancel.h @@ -0,0 +1 @@ +#include "../i386/not-cancel.h" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S new file mode 100644 index 000000000..e19579e84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S @@ -0,0 +1,3 @@ +#define RESET_PID +#include <tcb-offsets.h> +#include <sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S new file mode 100644 index 000000000..61651fd97 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + +   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 <sysdep.h> +#define _ERRNO_H	1 +#include <bits/errno.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + +/* 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 process, +   and the process ID of the new process to the old process.  */ + +ENTRY (__vfork) +	lwz	0,PID(2) +	neg	0,0 +	stw	0,PID(2) + +	DO_CALL (SYS_ify (vfork)) + +	cmpwi	1,3,0 +	beqlr-	1 + +	lwz	0,PID(2) +	neg	0,0 +	stw	0,PID(2) + +	PSEUDO_RET + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h new file mode 100644 index 000000000..84acf3843 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h @@ -0,0 +1,132 @@ +/* Cancellable system call stubs.  Linux/PowerPC version. +   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.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 <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <nptl/pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args)				\ +  .section ".text";							\ +  ENTRY (name)								\ +    cfi_startproc;							\ +    SINGLE_THREAD_P;							\ +    bne- .Lpseudo_cancel;						\ +  .type __##syscall_name##_nocancel,@function;				\ +  .globl __##syscall_name##_nocancel;					\ +  __##syscall_name##_nocancel:						\ +    DO_CALL (SYS_ify (syscall_name));					\ +    PSEUDO_RET;								\ +  .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	\ +  .Lpseudo_cancel:							\ +    stwu 1,-48(1);							\ +    cfi_adjust_cfa_offset (48);						\ +    mflr 9;								\ +    stw 9,52(1);							\ +    cfi_offset (lr, 4);							\ +    CGOTSETUP;								\ +    DOCARGS_##args;	/* save syscall args around CENABLE.  */	\ +    CENABLE;								\ +    stw 3,16(1);	/* store CENABLE return value (MASK).  */	\ +    UNDOCARGS_##args;	/* restore syscall args.  */			\ +    DO_CALL (SYS_ify (syscall_name));					\ +    mfcr 0;		/* save CR/R3 around CDISABLE.  */		\ +    stw 3,8(1);								\ +    stw 0,12(1);							\ +    lwz 3,16(1);	/* pass MASK to CDISABLE.  */			\ +    CDISABLE;								\ +    lwz 4,52(1);							\ +    lwz 0,12(1);	/* restore CR/R3. */				\ +    lwz 3,8(1);								\ +    CGOTRESTORE;							\ +    mtlr 4;								\ +    mtcr 0;								\ +    addi 1,1,48;							\ +    cfi_endproc; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1	stw 3,20(1); DOCARGS_0 +# define UNDOCARGS_1	lwz 3,20(1); UNDOCARGS_0 + +# define DOCARGS_2	stw 4,24(1); DOCARGS_1 +# define UNDOCARGS_2	lwz 4,24(1); UNDOCARGS_1 + +# define DOCARGS_3	stw 5,28(1); DOCARGS_2 +# define UNDOCARGS_3	lwz 5,28(1); UNDOCARGS_2 + +# define DOCARGS_4	stw 6,32(1); DOCARGS_3 +# define UNDOCARGS_4	lwz 6,32(1); UNDOCARGS_3 + +# define DOCARGS_5	stw 7,36(1); DOCARGS_4 +# define UNDOCARGS_5	lwz 7,36(1); UNDOCARGS_4 + +# define DOCARGS_6	stw 8,40(1); DOCARGS_5 +# define UNDOCARGS_6	lwz 8,40(1); UNDOCARGS_5 + +# define CGOTSETUP +# define CGOTRESTORE + +# ifdef IS_IN_libpthread +#  define CENABLE	bl __pthread_enable_asynccancel@local +#  define CDISABLE	bl __pthread_disable_asynccancel@local +# elif !defined NOT_IN_libc +#  define CENABLE	bl __libc_enable_asynccancel@local +#  define CDISABLE	bl __libc_disable_asynccancel@local +# elif defined IS_IN_librt +#  define CENABLE	bl JUMPTARGET(__librt_enable_asynccancel) +#  define CDISABLE	bl JUMPTARGET(__librt_disable_asynccancel) +#  if defined HAVE_AS_REL16 && defined PIC +#   undef CGOTSETUP +#   define CGOTSETUP							\ +    bcl 20,31,1f;							\ + 1: stw 30,44(1);							\ +    mflr 30;								\ +    addis 30,30,_GLOBAL_OFFSET_TABLE-1b@ha;				\ +    addi 30,30,_GLOBAL_OFFSET_TABLE-1b@l +#   undef CGOTRESTORE +#   define CGOTRESTORE							\ +    lwz 30,44(1) +#  endif +# else +#  error Unsupported library +# endif + +# ifndef __ASSEMBLER__ +#  define SINGLE_THREAD_P						\ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				\ +				   header.multiple_threads) == 0, 1) +# else +#  define SINGLE_THREAD_P						\ +  lwz 10,MULTIPLE_THREADS_OFFSET(2);					\ +  cmpwi 10,0 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S new file mode 100644 index 000000000..b7e2cf6e7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S @@ -0,0 +1,57 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + +   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 <sysdep.h> +#define _ERRNO_H	1 +#include <bits/errno.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + +/* 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 process, +   and the process ID of the new process to the old process.  */ + +ENTRY (__vfork) +	lwz	0,PID(2) +	cmpwi	0,0,0 +	neg	0,0 +	bne-	0,1f +	lis	0,0x8000 +1:	stw	0,PID(2) + +	DO_CALL (SYS_ify (vfork)) + +	cmpwi	1,3,0 +	beqlr-	1 + +	lwz	0,PID(2) +	/* Cannot use clrlwi. here, because cr0 needs to be preserved +	   until PSEUDO_RET.  */ +	clrlwi	4,0,1 +	cmpwi	1,4,0 +	beq-	1,1f +	neg	4,0 +1:	stw	4,PID(2) + +	PSEUDO_RET + +PSEUDO_END (__vfork) +hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions new file mode 100644 index 000000000..3b111ddb5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions @@ -0,0 +1,7 @@ +librt { +  GLIBC_2.3.3 { +    # Changed timer_t. +    timer_create; timer_delete; timer_getoverrun; timer_gettime; +    timer_settime; +  } +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S new file mode 100644 index 000000000..f87adf473 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S @@ -0,0 +1,3 @@ +#define RESET_PID +#include <tcb-offsets.h> +#include <sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S new file mode 100644 index 000000000..e5b7b535c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + +   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 <sysdep.h> +#define _ERRNO_H	1 +#include <bits/errno.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + +/* 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 process, +   and the process ID of the new process to the old process.  */ + +ENTRY (__vfork) +	lwz	0,PID(13) +	neg	0,0 +	stw	0,PID(13) + +	DO_CALL (SYS_ify (vfork)) + +	cmpwi	1,3,0 +	beqlr-	1 + +	lwz	0,PID(13) +	neg	0,0 +	stw	0,PID(13) + +	PSEUDO_RET + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h new file mode 100644 index 000000000..226aaafdc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h @@ -0,0 +1,121 @@ +/* Cancellable system call stubs.  Linux/PowerPC64 version. +   Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.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 <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <nptl/pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +#  define DASHDASHPFX(str) .__##str +# else +#  define DASHDASHPFX(str) __##str +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args)				\ +  .section ".text";							\ +  ENTRY (name)								\ +    cfi_startproc;							\ +    SINGLE_THREAD_P;							\ +    bne- .Lpseudo_cancel;						\ +  .type DASHDASHPFX(syscall_name##_nocancel),@function;			\ +  .globl DASHDASHPFX(syscall_name##_nocancel);				\ +  DASHDASHPFX(syscall_name##_nocancel):					\ +    DO_CALL (SYS_ify (syscall_name));					\ +    PSEUDO_RET;								\ +  .size DASHDASHPFX(syscall_name##_nocancel),.-DASHDASHPFX(syscall_name##_nocancel);	\ +  .Lpseudo_cancel:							\ +    stdu 1,-128(1);							\ +    cfi_adjust_cfa_offset (128);					\ +    mflr 9;								\ +    std  9,128+16(1);							\ +    cfi_offset (lr, 16);						\ +    DOCARGS_##args;	/* save syscall args around CENABLE.  */	\ +    CENABLE;								\ +    std  3,72(1);	/* store CENABLE return value (MASK).  */	\ +    UNDOCARGS_##args;	/* restore syscall args.  */			\ +    DO_CALL (SYS_ify (syscall_name));					\ +    mfcr 0;		/* save CR/R3 around CDISABLE.  */		\ +    std  3,64(1);							\ +    std  0,8(1);							\ +    ld   3,72(1);	/* pass MASK to CDISABLE.  */			\ +    CDISABLE;								\ +    ld   9,128+16(1);							\ +    ld   0,8(1);	/* restore CR/R3. */				\ +    ld   3,64(1);							\ +    mtlr 9;								\ +    mtcr 0;								\ +    addi 1,1,128;							\ +    cfi_endproc; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1	std 3,80(1); DOCARGS_0 +# define UNDOCARGS_1	ld 3,80(1); UNDOCARGS_0 + +# define DOCARGS_2	std 4,88(1); DOCARGS_1 +# define UNDOCARGS_2	ld 4,88(1); UNDOCARGS_1 + +# define DOCARGS_3	std 5,96(1); DOCARGS_2 +# define UNDOCARGS_3	ld 5,96(1); UNDOCARGS_2 + +# define DOCARGS_4	std 6,104(1); DOCARGS_3 +# define UNDOCARGS_4	ld 6,104(1); UNDOCARGS_3 + +# define DOCARGS_5	std 7,112(1); DOCARGS_4 +# define UNDOCARGS_5	ld 7,112(1); UNDOCARGS_4 + +# define DOCARGS_6	std 8,120(1); DOCARGS_5 +# define UNDOCARGS_6	ld 8,120(1); UNDOCARGS_5 + +# ifdef IS_IN_libpthread +#  define CENABLE	bl JUMPTARGET(__pthread_enable_asynccancel) +#  define CDISABLE	bl JUMPTARGET(__pthread_disable_asynccancel) +# elif !defined NOT_IN_libc +#  define CENABLE	bl JUMPTARGET(__libc_enable_asynccancel) +#  define CDISABLE	bl JUMPTARGET(__libc_disable_asynccancel) +# elif defined IS_IN_librt +#  define CENABLE	bl JUMPTARGET(__librt_enable_asynccancel) +#  define CDISABLE	bl JUMPTARGET(__librt_disable_asynccancel) +# else +#  error Unsupported library +# endif + +# ifndef __ASSEMBLER__ +#  define SINGLE_THREAD_P						\ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				\ +				   header.multiple_threads) == 0, 1) +# else +#   define SINGLE_THREAD_P						\ +  lwz   10,MULTIPLE_THREADS_OFFSET(13);				\ +  cmpwi 10,0 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c new file mode 100644 index 000000000..172223af3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c @@ -0,0 +1 @@ +#include "../x86_64/timer_create.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c new file mode 100644 index 000000000..537516e0a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c @@ -0,0 +1 @@ +#include "../x86_64/timer_delete.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c new file mode 100644 index 000000000..3f21a73c9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c @@ -0,0 +1 @@ +#include "../x86_64/timer_getoverr.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c new file mode 100644 index 000000000..a50143adc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_gettime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c new file mode 100644 index 000000000..37baeffac --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_settime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S new file mode 100644 index 000000000..018132136 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S @@ -0,0 +1,55 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + +   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 <sysdep.h> +#define _ERRNO_H	1 +#include <bits/errno.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + +/* 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 process, +   and the process ID of the new process to the old process.  */ + +ENTRY (__vfork) +	lwz	0,PID(13) +	cmpwi	0,0,0 +	neg	0,0 +	bne-	0,1f +	lis	0,0x8000 +1:	stw	0,PID(13) + +	DO_CALL (SYS_ify (vfork)) + +	cmpwi	1,3,0 +	beqlr-	1 + +	lwz	0,PID(13) +	clrlwi	4,0,1 +	cmpwi	1,4,0 +	beq-	1,1f +	neg	4,0 +1:	stw	4,PID(13) + +	PSEUDO_RET + +PSEUDO_END (__vfork) +hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c new file mode 100644 index 000000000..b6d6b3d55 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c @@ -0,0 +1,37 @@ +/* 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 <setjmp.h> +#include <stdlib.h> +#include <bits/wordsize.h> +#include "pthreadP.h" + +void +__vmx_longjmp (jmp_buf env, int val) +{ +  __libc_longjmp (env, val); +} + +void +__vmx_siglongjmp (jmp_buf env, int val) +{ +  __libc_siglongjmp (env, val); +} +weak_alias(__vmx_longjmp, longjmp) +weak_alias(__vmx_siglongjmp, siglongjmp) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c new file mode 100644 index 000000000..e1afff8a3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.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 "pthreadP.h" +#include <lowlevellock.h> + + +unsigned long int __fork_generation attribute_hidden; + + +static void +clear_once_control (void *arg) +{ +  pthread_once_t *once_control = (pthread_once_t *) arg; + +  *once_control = 0; +  lll_futex_wake (once_control, INT_MAX); +} + + +int +__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ +  for (;;) +    { +      int oldval; +      int newval; +      int tmp; + +      /* Pseudo code: +	 newval = __fork_generation | 1; +	 oldval = *once_control; +	 if ((oldval & 2) == 0) +	   *once_control = newval; +	 Do this atomically. +      */ +      newval = __fork_generation | 1; +      __asm __volatile ("1:	lwarx	%0,0,%3\n" +			"	andi.	%1,%0,2\n" +			"	bne	2f\n" +			"	stwcx.	%4,0,%3\n" +			"	bne	1b\n" +			"2:	isync" +			: "=&r" (oldval), "=&r" (tmp), "=m" (*once_control) +			: "r" (once_control), "r" (newval), "m" (*once_control) +			: "cr0"); + +      /* Check if the initializer has already been done.  */ +      if ((oldval & 2) != 0) +	return 0; + +      /* Check if another thread already runs the initializer.	*/ +      if ((oldval & 1) == 0) +	break; + +      /* Check whether the initializer execution was interrupted by a fork.  */ +      if (oldval != newval) +	break; + +      /* Same generation, some other thread was faster. Wait.  */ +      lll_futex_wait (once_control, oldval); +    } + + +  /* This thread is the first here.  Do the initialization. +     Register a cleanup handler so that in case the thread gets +     interrupted the initialization can be restarted.  */ +  pthread_cleanup_push (clear_once_control, once_control); + +  init_routine (); + +  pthread_cleanup_pop (0); + + +  /* Add one to *once_control to take the bottom 2 bits from 01 to 10.  */ +  atomic_increment (once_control); + +  /* Wake up all other threads.  */ +  lll_futex_wake (once_control, INT_MAX); + +  return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c new file mode 100644 index 000000000..06b3bd0ab --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c @@ -0,0 +1,42 @@ +/* sem_post -- post to a POSIX semaphore.  Powerpc version. +   Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.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 <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + +int +__new_sem_post (sem_t *sem) +{ +  int *futex = (int *) sem; + +  __asm __volatile (__lll_rel_instr ::: "memory"); +  int nr = atomic_increment_val (futex); +  int err = lll_futex_wake (futex, nr); +  if (__builtin_expect (err, 0) < 0) +    { +      __set_errno (-err); +      return -1; +    } +  return 0; +} +weak_alias(__new_sem_post, sem_post) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-accept.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-accept.S new file mode 100644 index 000000000..24062101d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-accept.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_accept +#error Missing definition of NR_accept needed for cancellation. +#endif +PSEUDO (__libc_accept, accept, 3) +ret +PSEUDO_END(__libc_accept) +libpthread_hidden_def (__libc_accept) +weak_alias (__libc_accept, __accept) +libpthread_hidden_weak (__accept) +weak_alias (__libc_accept, accept) +libpthread_hidden_weak (accept) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-close.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-close.S new file mode 100644 index 000000000..ab32ca598 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-close.S @@ -0,0 +1,9 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_close, close, 1) +ret +PSEUDO_END (__libc_close) +libpthread_hidden_def (__libc_close) +weak_alias (__libc_close, __close) +libpthread_hidden_weak (__close) +weak_alias (__libc_close, close) +libpthread_hidden_weak (close) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-connect.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-connect.S new file mode 100644 index 000000000..b5124f8ec --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-connect.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_connect +#error Missing definition of NR_connect needed for cancellation. +#endif +PSEUDO (__libc_connect, connect, 3) +ret +PSEUDO_END(__libc_connect) +libpthread_hidden_def (__libc_connect) +weak_alias (__libc_connect, __connect) +libpthread_hidden_weak (__connect) +weak_alias (__libc_connect, connect) +libpthread_hidden_weak (connect) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fcntl.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fcntl.c new file mode 100644 index 000000000..0a8fd3cc2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fcntl.c @@ -0,0 +1 @@ +#include <../../../../../../libc/sysdeps/linux/common/__syscall_fcntl.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c new file mode 100644 index 000000000..3e1b70f86 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c @@ -0,0 +1,29 @@ +/* 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 <unistd.h> + +extern int __libc_fork (void); + +pid_t +__fork (void) +{ +  return __libc_fork (); +} +strong_alias (__fork, fork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fsync.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fsync.c new file mode 100644 index 000000000..6ec4821c7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fsync.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include <../../../../../../libc/sysdeps/linux/common/fsync.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-llseek.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-llseek.c new file mode 100644 index 000000000..1d0d57870 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-llseek.c @@ -0,0 +1,3 @@ +#include <pthreadP.h> +#define libc_hidden libpthread_hidden +#include <../../../../../../libc/sysdeps/linux/common/llseek.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-lseek.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-lseek.S new file mode 100644 index 000000000..4db71722a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-lseek.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_lseek, lseek, 3) +ret +PSEUDO_END (__libc_lseek) +libpthread_hidden_def (__libc_lseek) +weak_alias (__libc_lseek, lseek) +libpthread_hidden_weak (lseek) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgrcv.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgrcv.c new file mode 100644 index 000000000..3bb9d53df --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgrcv.c @@ -0,0 +1,2 @@ +#define L_msgrcv +#include <../../../../../../libc/misc/sysvipc/msgq.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgsnd.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgsnd.c new file mode 100644 index 000000000..1566f65f4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgsnd.c @@ -0,0 +1,2 @@ +#define L_msgsnd +#include <../../../../../../libc/misc/sysvipc/msgq.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msync.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msync.S new file mode 100644 index 000000000..640270ad9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msync.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_msync, msync, 3) +ret +PSEUDO_END(__libc_msync) +libpthread_hidden_def (__libc_msync) +weak_alias (__libc_msync, msync) +libpthread_hidden_weak (msync) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-nanosleep.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-nanosleep.S new file mode 100644 index 000000000..08d8f0150 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-nanosleep.S @@ -0,0 +1,9 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_nanosleep, nanosleep, 3) +ret +PSEUDO_END (__libc_nanosleep) +libpthread_hidden_def (__libc_nanosleep) +weak_alias (__libc_nanosleep, __nanosleep) +libpthread_hidden_weak (__nanosleep) +weak_alias (__libc_nanosleep, nanosleep) +libpthread_hidden_weak (nanosleep) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open.S new file mode 100644 index 000000000..39ed92cc7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open.S @@ -0,0 +1,9 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_open, open, 3) +ret +PSEUDO_END (__libc_open) +libpthread_hidden_def (__libc_open) +weak_alias (__libc_open, __open) +libpthread_hidden_weak (__open) +weak_alias (__libc_open, open) +libpthread_hidden_weak (open) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open64.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open64.c new file mode 100644 index 000000000..2029539a7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open64.c @@ -0,0 +1 @@ +#include <../../../../../../libc/sysdeps/linux/common/open64.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pause.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pause.S new file mode 100644 index 000000000..c6cb57180 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pause.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_pause, pause, 0) +ret +PSEUDO_END (__libc_pause) +libpthread_hidden_def (__libc_pause) +weak_alias (__libc_pause, pause) +libpthread_hidden_weak (pause) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pread_pwrite.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pread_pwrite.c new file mode 100644 index 000000000..f32c0a670 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pread_pwrite.c @@ -0,0 +1 @@ +#include "pread_write.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-raise.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-raise.c new file mode 100644 index 000000000..7bee29784 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-raise.c @@ -0,0 +1,53 @@ +/* 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 <errno.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> +#include <bits/kernel-features.h> + +extern __typeof(raise) __raise; +int __raise (int sig) +{ +#if __ASSUME_TGKILL || defined __NR_tgkill +  /* raise is an async-safe function.  It could be called while the +     fork function temporarily invalidated the PID field.  Adjust for +     that.  */ +  pid_t pid = THREAD_GETMEM (THREAD_SELF, pid); +  if (__builtin_expect (pid < 0, 0)) +    pid = -pid; +#endif + +#if __ASSUME_TGKILL +  return INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid), +			 sig); +#else +# ifdef __NR_tgkill +  int res = INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid), +			    sig); +  if (res != -1 || errno != ENOSYS) +    return res; +# endif +  return INLINE_SYSCALL (tkill, 2, THREAD_GETMEM (THREAD_SELF, tid), sig); +#endif +} +libc_hidden_proto(raise) +weak_alias(__raise, raise) +libc_hidden_weak(raise) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-read.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-read.S new file mode 100644 index 000000000..623ba27a8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-read.S @@ -0,0 +1,9 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_read, read, 3) +ret +PSEUDO_END (__libc_read) +libpthread_hidden_def (__libc_read) +weak_alias (__libc_read, __read) +libpthread_hidden_weak (__read) +weak_alias (__libc_read, read) +libpthread_hidden_weak (read) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recv.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recv.S new file mode 100644 index 000000000..6d2e3c2d6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recv.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_recv +#error Missing definition of NR_recv needed for cancellation. +#endif +PSEUDO (__libc_recv, recv, 4) +ret +PSEUDO_END(__libc_recv) +libpthread_hidden_def (__libc_recv) +weak_alias (__libc_recv, __recv) +libpthread_hidden_weak (__recv) +weak_alias (__libc_recv, recv) +libpthread_hidden_weak (recv) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvfrom.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvfrom.S new file mode 100644 index 000000000..96aeeaa3d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvfrom.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_recvfrom +#error Missing definition of NR_recvfrom needed for cancellation. +#endif +PSEUDO (__libc_recvfrom, recvfrom, 6) +ret +PSEUDO_END(__libc_recvfrom) +libpthread_hidden_def (__libc_recvfrom) +weak_alias (__libc_recvfrom, __recvfrom) +libpthread_hidden_weak (__recvfrom) +weak_alias (__libc_recvfrom, recvfrom) +libpthread_hidden_weak (recvfrom) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvmsg.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvmsg.S new file mode 100644 index 000000000..f7161e47c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvmsg.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_recvmsg +#error Missing definition of NR_recvmsg needed for cancellation. +#endif +PSEUDO (__libc_recvmsg, recvmsg, 3) +ret +PSEUDO_END(__libc_recvmsg) +libpthread_hidden_def (__libc_recvmsg) +weak_alias (__libc_recvmsg, __recvmsg) +libpthread_hidden_weak (__recvmsg) +weak_alias (__libc_recvmsg, recvmsg) +libpthread_hidden_weak (recvmsg) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-send.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-send.S new file mode 100644 index 000000000..76bed39ec --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-send.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_send +#error Missing definition of NR_send needed for cancellation. +#endif +PSEUDO (__libc_send, send, 4) +ret +PSEUDO_END (__libc_send) +libpthread_hidden_def (__libc_send) +weak_alias (__libc_send, __send) +libpthread_hidden_weak (__send) +weak_alias (__libc_send, send) +libpthread_hidden_weak (send) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendmsg.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendmsg.S new file mode 100644 index 000000000..d17096eae --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendmsg.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_sendmsg +#error Missing definition of NR_sendmsg needed for cancellation. +#endif +PSEUDO (__libc_sendmsg, sendmsg, 3) +ret +PSEUDO_END(__libc_sendmsg) +libpthread_hidden_def (__libc_sendmsg) +weak_alias (__libc_sendmsg, __sendmsg) +libpthread_hidden_weak (__sendmsg) +weak_alias (__libc_sendmsg, sendmsg) +libpthread_hidden_weak (sendmsg) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendto.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendto.S new file mode 100644 index 000000000..d07a71f8a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendto.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_sendto +#error Missing definition of NR_sendto needed for cancellation. +#endif +PSEUDO (__libc_sendto, sendto, 6) +ret +PSEUDO_END(__libc_sendto) +libpthread_hidden_def (__libc_sendto) +weak_alias (__libc_sendto, __sendto) +libpthread_hidden_weak (__sendto) +weak_alias (__libc_sendto, sendto) +libpthread_hidden_weak (sendto) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sigwait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sigwait.c new file mode 100644 index 000000000..bde0a9292 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sigwait.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include "../../../../../../libc/signal/sigwait.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sleep.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sleep.c new file mode 100644 index 000000000..9e948adce --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sleep.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include <../../../../../../libc/unistd/sleep.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-tcdrain.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-tcdrain.c new file mode 100644 index 000000000..07c1f8233 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-tcdrain.c @@ -0,0 +1 @@ +#include <../../../../../../libc/termios/tcdrain.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-wait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-wait.c new file mode 100644 index 000000000..a05c3eb49 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-wait.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include <../../../../../../libc/sysdeps/linux/common/wait.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-waitpid.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-waitpid.c new file mode 100644 index 000000000..8461c3ff2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-waitpid.c @@ -0,0 +1 @@ +#include <../../../../../../libc/sysdeps/linux/common/waitpid.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-write.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-write.S new file mode 100644 index 000000000..6bc666779 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-write.S @@ -0,0 +1,9 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_write, write, 3) +ret +PSEUDO_END (__libc_write) +libpthread_hidden_def (__libc_write) +weak_alias (__libc_write, __write) +libpthread_hidden_weak (__write) +weak_alias (__libc_write, write) +libpthread_hidden_weak (write) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c new file mode 100644 index 000000000..5a3d418a9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 <assert.h> +#include <errno.h> +#include <pthreadP.h> +#include <string.h> +#include <sysdep.h> +#include <sys/types.h> + + +int +__pthread_attr_getaffinity_new (const pthread_attr_t *attr, size_t cpusetsize, +				cpu_set_t *cpuset) +{ +  const struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (const struct pthread_attr *) attr; + +  if (iattr->cpuset != NULL) +    { +      /* Check whether there are any bits set beyond the limits +	 the user requested.  */ +      size_t cnt; +      for (cnt = cpusetsize; cnt < iattr->cpusetsize; ++cnt) +	if (((char *) iattr->cpuset)[cnt] != 0) +	  return EINVAL; + +      void *p = mempcpy (cpuset, iattr->cpuset, iattr->cpusetsize); +      if (cpusetsize > iattr->cpusetsize) +	memset (p, '\0', cpusetsize - iattr->cpusetsize); +    } +  else +    /* We have no information.  */ +    memset (cpuset, -1, cpusetsize); + +  return 0; +} +weak_alias(__pthread_attr_getaffinity_new, pthread_attr_getaffinity_np) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c new file mode 100644 index 000000000..e3414999c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c @@ -0,0 +1,82 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <pthreadP.h> + + +/* Defined in pthread_setaffinity.c.  */ +extern size_t __kernel_cpumask_size; +extern int __determine_cpumask_size (pid_t tid); + + +int +__pthread_attr_setaffinity_new (pthread_attr_t *attr, size_t cpusetsize, +				const cpu_set_t *cpuset) +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  if (cpuset == NULL || cpusetsize == 0) +    { +      free (iattr->cpuset); +      iattr->cpuset = NULL; +      iattr->cpusetsize = 0; +    } +  else +    { +      if (__kernel_cpumask_size == 0) +	{ +	  int res = __determine_cpumask_size (THREAD_SELF->tid); +	  if (res != 0) +	    /* Some serious problem.  */ +	    return res; +	} + +      /* Check whether the new bitmask has any bit set beyond the +	 last one the kernel accepts.  */ +      size_t cnt; +      for (cnt = __kernel_cpumask_size; cnt < cpusetsize; ++cnt) +	if (((char *) cpuset)[cnt] != '\0') +	  /* Found a nonzero byte.  This means the user request cannot be +	     fulfilled.  */ +	  return EINVAL; + +      if (iattr->cpusetsize != cpusetsize) +	{ +	  void *newp = (cpu_set_t *) realloc (iattr->cpuset, cpusetsize); +	  if (newp == NULL) +	    return ENOMEM; + +	  iattr->cpuset = newp; +	  iattr->cpusetsize = cpusetsize; +	} + +      memcpy (iattr->cpuset, cpuset, cpusetsize); +    } + +  return 0; +} +weak_alias(__pthread_attr_setaffinity_new, pthread_attr_setaffinity_np) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c new file mode 100644 index 000000000..3ca9d7d94 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 <limits.h> +#include <pthreadP.h> +#include <string.h> +#include <sysdep.h> +#include <sys/param.h> +#include <sys/types.h> + + +int +__pthread_getaffinity_new (pthread_t th, size_t cpusetsize, cpu_set_t *cpuset) +{ +  const struct pthread *pd = (const struct pthread *) th; + +  INTERNAL_SYSCALL_DECL (err); +  int res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, pd->tid, +			      MIN (INT_MAX, cpusetsize), cpuset); +  if (INTERNAL_SYSCALL_ERROR_P (res, err)) +    return INTERNAL_SYSCALL_ERRNO (res, err); + +  /* Clean the rest of the memory the kernel didn't do.  */ +  memset ((char *) cpuset + res, '\0', cpusetsize - res); + +  return 0; +} +strong_alias(__pthread_getaffinity_new, __pthread_getaffinity_np) +strong_alias(__pthread_getaffinity_new, pthread_getaffinity_np) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c new file mode 100644 index 000000000..155d3645f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c @@ -0,0 +1,111 @@ +/* pthread_getcpuclockid -- Get POSIX clockid_t for a pthread_t.  Linux version +   Copyright (C) 2000,2001,2002,2003,2004,2005 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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <errno.h> +#include <pthreadP.h> +#include <sys/time.h> +#include <tls.h> +#include <bits/kernel-features.h> +#include <kernel-posix-cpu-timers.h> + + +#if !(__ASSUME_POSIX_CPU_TIMERS > 0) +int __libc_missing_posix_cpu_timers attribute_hidden; +#endif +#if !(__ASSUME_POSIX_TIMERS > 0) +int __libc_missing_posix_timers attribute_hidden; +#endif + +int +pthread_getcpuclockid ( +     pthread_t threadid, +     clockid_t *clockid) +{ +  struct pthread *pd = (struct pthread *) threadid; + +  /* Make sure the descriptor is valid.  */ +  if (INVALID_TD_P (pd)) +    /* Not a valid thread handle.  */ +    return ESRCH; + +#ifdef __NR_clock_getres +  /* The clockid_t value is a simple computation from the TID. +     But we do a clock_getres call to validate it if we aren't +     yet sure we have the kernel support.  */ + +  const clockid_t tidclock = MAKE_THREAD_CPUCLOCK (pd->tid, CPUCLOCK_SCHED); + +# if !(__ASSUME_POSIX_CPU_TIMERS > 0) +#  if !(__ASSUME_POSIX_TIMERS > 0) +  if (__libc_missing_posix_timers && !__libc_missing_posix_cpu_timers) +    __libc_missing_posix_cpu_timers = 1; +#  endif +  if (!__libc_missing_posix_cpu_timers) +    { +      INTERNAL_SYSCALL_DECL (err); +      int r = INTERNAL_SYSCALL (clock_getres, err, 2, tidclock, NULL); +      if (!INTERNAL_SYSCALL_ERROR_P (r, err)) +# endif +	{ +	  *clockid = tidclock; +	  return 0; +	} + +# if !(__ASSUME_POSIX_CPU_TIMERS > 0) +#  if !(__ASSUME_POSIX_TIMERS > 0) +      if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS) +	{ +	  /* The kernel doesn't support these calls at all.  */ +	  __libc_missing_posix_timers = 1; +	  __libc_missing_posix_cpu_timers = 1; +	} +      else +#  endif +	if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL) +	  { +	    /* The kernel doesn't support these clocks at all.  */ +	    __libc_missing_posix_cpu_timers = 1; +	  } +      else +	return INTERNAL_SYSCALL_ERRNO (r, err); +    } +# endif +#endif + +#ifdef CLOCK_THREAD_CPUTIME_ID +  /* We need to store the thread ID in the CLOCKID variable together +     with a number identifying the clock.  We reserve the low 3 bits +     for the clock ID and the rest for the thread ID.  This is +     problematic if the thread ID is too large.  But 29 bits should be +     fine. + +     If some day more clock IDs are needed the ID part can be +     enlarged.  The IDs are entirely internal.  */ +  if (pd->tid >= 1 << (8 * sizeof (*clockid) - CLOCK_IDFIELD_SIZE)) +    return ERANGE; + +  /* Store the number.  */ +  *clockid = CLOCK_THREAD_CPUTIME_ID | (pd->tid << CLOCK_IDFIELD_SIZE); + +  return 0; +#else +  /* We don't have a timer for that.  */ +  return ENOENT; +#endif +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_kill.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_kill.c new file mode 100644 index 000000000..8d887e020 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_kill.c @@ -0,0 +1,70 @@ +/* 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 <errno.h> +#include <signal.h> +#include <pthreadP.h> +#include <tls.h> +#include <sysdep.h> +#include <bits/kernel-features.h> + + +int +__pthread_kill ( +     pthread_t threadid, +     int signo) +{ +  struct pthread *pd = (struct pthread *) threadid; + +  /* Make sure the descriptor is valid.  */ +  if (INVALID_TD_P (pd)) +    /* Not a valid thread handle.  */ +    return ESRCH; + +  /* Disallow sending the signal we use for cancellation, timers, for +     for the setxid implementation.  */ +  if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID) +    return EINVAL; + +  /* We have a special syscall to do the work.  */ +  INTERNAL_SYSCALL_DECL (err); + +  /* One comment: The PID field in the TCB can temporarily be changed +     (in fork).  But this must not affect this code here.  Since this +     function would have to be called while the thread is executing +     fork, it would have to happen in a signal handler.  But this is +     no allowed, pthread_kill is not guaranteed to be async-safe.  */ +  int val; +#if __ASSUME_TGKILL +  val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), +			  pd->tid, signo); +#else +# ifdef __NR_tgkill +  val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), +			  pd->tid, signo); +  if (INTERNAL_SYSCALL_ERROR_P (val, err) +      && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) +# endif +    val = INTERNAL_SYSCALL (tkill, err, 2, pd->tid, signo); +#endif + +  return (INTERNAL_SYSCALL_ERROR_P (val, err) +	  ? INTERNAL_SYSCALL_ERRNO (val, err) : 0); +} +strong_alias (__pthread_kill, pthread_kill) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c new file mode 100644 index 000000000..047c64322 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c @@ -0,0 +1,8 @@ +#include <pthreadP.h> + +#define LLL_MUTEX_LOCK(mutex) lll_mutex_cond_lock(mutex) +#define LLL_MUTEX_TRYLOCK(mutex) lll_mutex_cond_trylock(mutex) +#define __pthread_mutex_lock __pthread_mutex_cond_lock +#define NO_INCR + +#include <pthread_mutex_lock.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c new file mode 100644 index 000000000..fa7b48904 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c @@ -0,0 +1,86 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 <alloca.h> +#include <errno.h> +#include <pthreadP.h> +#include <sysdep.h> +#include <sys/types.h> + + +size_t __kernel_cpumask_size; + + +/* Determine the current affinity.  As a side affect we learn +   about the size of the cpumask_t in the kernel.  */ +int +__determine_cpumask_size (pid_t tid) +{ +  INTERNAL_SYSCALL_DECL (err); +  int res; + +  size_t psize = 128; +  void *p = alloca (psize); + +  while (res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, tid, psize, p), +	 INTERNAL_SYSCALL_ERROR_P (res, err) +	 && INTERNAL_SYSCALL_ERRNO (res, err) == EINVAL) +    p = extend_alloca (p, psize, 2 * psize); + +  if (res == 0 || INTERNAL_SYSCALL_ERROR_P (res, err)) +    return INTERNAL_SYSCALL_ERRNO (res, err); + +  __kernel_cpumask_size = res; + +  return 0; +} + + +int +__pthread_setaffinity_new (pthread_t th, size_t cpusetsize, +			   const cpu_set_t *cpuset) +{ +  const struct pthread *pd = (const struct pthread *) th; + +  INTERNAL_SYSCALL_DECL (err); +  int res; + +  if (__builtin_expect (__kernel_cpumask_size == 0, 0)) +    { +      res = __determine_cpumask_size (pd->tid); +      if (res != 0) +	return res; +    } + +  /* We now know the size of the kernel cpumask_t.  Make sure the user +     does not request to set a bit beyond that.  */ +  size_t cnt; +  for (cnt = __kernel_cpumask_size; cnt < cpusetsize; ++cnt) +    if (((char *) cpuset)[cnt] != '\0') +      /* Found a nonzero byte.  This means the user request cannot be +	 fulfilled.  */ +      return EINVAL; + +  res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, cpusetsize, +			  cpuset); +  return (INTERNAL_SYSCALL_ERROR_P (res, err) +	  ? INTERNAL_SYSCALL_ERRNO (res, err) +	  : 0); +} +weak_alias(__pthread_setaffinity_new, pthread_setaffinity_np) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_yield.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_yield.c new file mode 100644 index 000000000..5aecffcf0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_yield.c @@ -0,0 +1,30 @@ +/* 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 <pthread.h> +#include <sched.h> + + +/* With the 1-on-1 model we implement this function is equivalent to +   the 'sched_yield' function.  */ +int +pthread_yield (void) +{ +  return sched_yield (); +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/raise.c b/libpthread/nptl/sysdeps/unix/sysv/linux/raise.c new file mode 100644 index 000000000..de794e4ab --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/raise.c @@ -0,0 +1,75 @@ +/* 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 <errno.h> +#include <limits.h> +#include <signal.h> +#include <sysdep.h> +#include <pthreadP.h> +#include <bits/kernel-features.h> + + +extern __typeof(raise) __raise; +int __raise (int sig) +{ +  struct pthread *pd = THREAD_SELF; +#if __ASSUME_TGKILL || defined __NR_tgkill +  pid_t pid = THREAD_GETMEM (pd, pid); +#endif +  pid_t selftid = THREAD_GETMEM (pd, tid); +  if (selftid == 0) +    { +      /* This system call is not supposed to fail.  */ +#ifdef INTERNAL_SYSCALL +      INTERNAL_SYSCALL_DECL (err); +      selftid = INTERNAL_SYSCALL (gettid, err, 0); +#else +      selftid = INLINE_SYSCALL (gettid, 0); +#endif +      THREAD_SETMEM (pd, tid, selftid); + +#if __ASSUME_TGKILL || defined __NR_tgkill +      /* We do not set the PID field in the TID here since we might be +	 called from a signal handler while the thread executes fork.  */ +      pid = selftid; +#endif +    } +#if __ASSUME_TGKILL || defined __NR_tgkill +  else +    /* raise is an async-safe function.  It could be called while the +       fork/vfork function temporarily invalidated the PID field.  Adjust for +       that.  */ +    if (__builtin_expect (pid <= 0, 0)) +      pid = (pid & INT_MAX) == 0 ? selftid : -pid; +#endif + +#if __ASSUME_TGKILL +  return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); +#else +# ifdef __NR_tgkill +  int res = INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); +  if (res != -1 || errno != ENOSYS) +    return res; +# endif +  return INLINE_SYSCALL (tkill, 2, selftid, sig); +#endif +} +libc_hidden_proto(raise) +weak_alias(__raise, raise) +libc_hidden_weak(raise) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/read.S b/libpthread/nptl/sysdeps/unix/sysv/linux/read.S new file mode 100644 index 000000000..d3adfa84c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/read.S @@ -0,0 +1,19 @@ +#include <sysdep-cancel.h> + +/* +extern int __read_nocancel (int, void *, size_t) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +PSEUDO (__libc_read, read, 3) +ret +PSEUDO_END(__libc_read) + +libc_hidden_def (__read_nocancel) +libc_hidden_def (__libc_read) +weak_alias (__libc_read, __read) +libc_hidden_weak (__read) +weak_alias (__libc_read, read) +libc_hidden_weak (read) + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/recv.S b/libpthread/nptl/sysdeps/unix/sysv/linux/recv.S new file mode 100644 index 000000000..95fa6516e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/recv.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_recv +#error Missing definition of NR_recv needed for cancellation. +#endif +PSEUDO (__libc_recv, recv, 4) +ret +PSEUDO_END(__libc_recv) +libc_hidden_def (__libc_recv) +weak_alias (__libc_recv, __recv) +libc_hidden_weak (__recv) +weak_alias (__libc_recv, recv) +libc_hidden_weak (recv) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/recvfrom.S b/libpthread/nptl/sysdeps/unix/sysv/linux/recvfrom.S new file mode 100644 index 000000000..d9cc1e9b4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/recvfrom.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_recvfrom +#error Missing definition of NR_recvfrom needed for cancellation. +#endif +PSEUDO (__libc_recvfrom, recvfrom, 6) +ret +PSEUDO_END(__libc_recvfrom) +libc_hidden_def (__libc_recvfrom) +weak_alias (__libc_recvfrom, __recvfrom) +libc_hidden_weak (__recvfrom) +weak_alias (__libc_recvfrom, recvfrom) +libc_hidden_weak (recvfrom) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/recvmsg.S b/libpthread/nptl/sysdeps/unix/sysv/linux/recvmsg.S new file mode 100644 index 000000000..c761b907c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/recvmsg.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_recvmsg +#error Missing definition of NR_recvmsg needed for cancellation. +#endif +PSEUDO (__libc_recvmsg, recvmsg, 3) +ret +PSEUDO_END(__libc_recvmsg) +libc_hidden_def (__libc_recvmsg) +weak_alias (__libc_recvmsg, __recvmsg) +libc_hidden_weak (__recvmsg) +weak_alias (__libc_recvmsg, recvmsg) +libc_hidden_weak (recvmsg) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/register-atfork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/register-atfork.c new file mode 100644 index 000000000..f6c3de4bc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/register-atfork.c @@ -0,0 +1,108 @@ +/* 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 <errno.h> +#include <stdlib.h> +#include <string.h> +#include "fork.h" + + +/* Lock to protect allocation and deallocation of fork handlers.  */ +lll_lock_t __fork_lock = LLL_LOCK_INITIALIZER; + + +/* Number of pre-allocated handler entries.  */ +#define NHANDLER 48 + +/* Memory pool for fork handler structures.  */ +static struct fork_handler_pool +{ +  struct fork_handler_pool *next; +  struct fork_handler mem[NHANDLER]; +} fork_handler_pool; + + +static struct fork_handler * +fork_handler_alloc (void) +{ +  struct fork_handler_pool *runp = &fork_handler_pool; +  struct fork_handler *result = NULL; +  unsigned int i; + +  do +    { +      /* Search for an empty entry.  */ +      for (i = 0; i < NHANDLER; ++i) +	if (runp->mem[i].refcntr == 0) +	  goto found; +    } +  while ((runp = runp->next) != NULL); + +  /* We have to allocate a new entry.  */ +  runp = (struct fork_handler_pool *) calloc (1, sizeof (*runp)); +  if (runp != NULL) +    { +      /* Enqueue the new memory pool into the list.  */ +      runp->next = fork_handler_pool.next; +      fork_handler_pool.next = runp; + +      /* We use the last entry on the page.  This means when we start +	 searching from the front the next time we will find the first +	 entry unused.  */ +      i = NHANDLER - 1; + +    found: +      result = &runp->mem[i]; +      result->refcntr = 1; +      result->need_signal = 0; +    } + +  return result; +} + + +int +__register_atfork ( +     void (*prepare) (void), +     void (*parent) (void), +     void (*child) (void), +     void *dso_handle) +{ +  /* Get the lock to not conflict with other allocations.  */ +  lll_lock (__fork_lock); + +  struct fork_handler *newp = fork_handler_alloc (); + +  if (newp != NULL) +    { +      /* Initialize the new record.  */ +      newp->prepare_handler = prepare; +      newp->parent_handler = parent; +      newp->child_handler = child; +      newp->dso_handle = dso_handle; + +      newp->next = __fork_handlers; +      __fork_handlers = newp; +    } + +  /* Release the lock.  */ +  lll_unlock (__fork_lock); + +  return newp == NULL ? ENOMEM : 0; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_post.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_post.c new file mode 100644 index 000000000..7f0b67918 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_post.c @@ -0,0 +1,41 @@ +/* sem_post -- post to a POSIX semaphore.  Generic futex-using version. +   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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + +int +__new_sem_post (sem_t *sem) +{ +  int *futex = (int *) sem; + +  int nr = atomic_increment_val (futex); +  int err = lll_futex_wake (futex, nr); +  if (__builtin_expect (err, 0) < 0) +    { +      __set_errno (-err); +      return -1; +    } +  return 0; +} +weak_alias(__new_sem_post, sem_post) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c new file mode 100644 index 000000000..79b11948c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c @@ -0,0 +1,97 @@ +/* sem_timedwait -- wait on a semaphore.  Generic futex-using version. +   Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.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 <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> +#include <pthreadP.h> + + +int +sem_timedwait (sem_t *sem, const struct timespec *abstime) +{ +  /* First check for cancellation.  */ +  CANCELLATION_P (THREAD_SELF); + +  int *futex = (int *) sem; +  int val; +  int err; + +  if (*futex > 0) +    { +      val = atomic_decrement_if_positive (futex); +      if (val > 0) +	return 0; +    } + +  err = -EINVAL; +  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) +    goto error_return; + +  do +    { +      struct timeval tv; +      struct timespec rt; +      int sec, nsec; + +      /* Get the current time.  */ +      gettimeofday (&tv, NULL); + +      /* Compute relative timeout.  */ +      sec = abstime->tv_sec - tv.tv_sec; +      nsec = abstime->tv_nsec - tv.tv_usec * 1000; +      if (nsec < 0) +	{ +	  nsec += 1000000000; +	  --sec; +	} + +      /* Already timed out?  */ +      err = -ETIMEDOUT; +      if (sec < 0) +	goto error_return; + +      /* Do wait.  */ +      rt.tv_sec = sec; +      rt.tv_nsec = nsec; + +      /* Enable asynchronous cancellation.  Required by the standard.  */ +      int oldtype = __pthread_enable_asynccancel (); + +      err = lll_futex_timed_wait (futex, 0, &rt); + +      /* Disable asynchronous cancellation.  */ +      __pthread_disable_asynccancel (oldtype); + +      if (err != 0 && err != -EWOULDBLOCK) +	goto error_return; + +      val = atomic_decrement_if_positive (futex); +    } +  while (val <= 0); + +  return 0; + + error_return: +  __set_errno (-err); +  return -1; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_trywait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_trywait.c new file mode 100644 index 000000000..3cf1d9a8a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_trywait.c @@ -0,0 +1,44 @@ +/* sem_trywait -- wait on a semaphore.  Generic futex-using version. +   Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.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 <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + + +int +__new_sem_trywait (sem_t *sem) +{ +  int *futex = (int *) sem; +  int val; + +  if (*futex > 0) +    { +      val = atomic_decrement_if_positive (futex); +      if (val > 0) +	return 0; +    } + +  __set_errno (EAGAIN); +  return -1; +} +weak_alias(__new_sem_trywait, sem_trywait) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c new file mode 100644 index 000000000..416d8634b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c @@ -0,0 +1,56 @@ +/* sem_wait -- wait on a semaphore.  Generic futex-using version. +   Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.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 <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> +#include <pthreadP.h> + + +int +__new_sem_wait (sem_t *sem) +{ +  /* First check for cancellation.  */ +  CANCELLATION_P (THREAD_SELF); + +  int *futex = (int *) sem; +  int err; + +  do +    { +      if (atomic_decrement_if_positive (futex) > 0) +	return 0; + +      /* Enable asynchronous cancellation.  Required by the standard.  */ +      int oldtype = __pthread_enable_asynccancel (); + +      err = lll_futex_wait (futex, 0); + +      /* Disable asynchronous cancellation.  */ +      __pthread_disable_asynccancel (oldtype); +    } +  while (err == 0 || err == -EWOULDBLOCK); + +  __set_errno (-err); +  return -1; +} +weak_alias(__new_sem_wait, sem_wait) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/send.S b/libpthread/nptl/sysdeps/unix/sysv/linux/send.S new file mode 100644 index 000000000..eb744c712 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/send.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_send +#error Missing definition of NR_send needed for cancellation. +#endif +PSEUDO (__libc_send, send, 4) +ret +PSEUDO_END (__libc_send) +libc_hidden_def (__libc_send) +weak_alias (__libc_send, __send) +libc_hidden_weak (__send) +weak_alias (__libc_send, send) +libc_hidden_weak (send) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sendmsg.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sendmsg.S new file mode 100644 index 000000000..4c41e01c1 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sendmsg.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_sendmsg +#error Missing definition of NR_sendmsg needed for cancellation. +#endif +PSEUDO (__libc_sendmsg, sendmsg, 3) +ret +PSEUDO_END(__libc_sendmsg) +libc_hidden_def (__libc_sendmsg) +weak_alias (__libc_sendmsg, __sendmsg) +libc_hidden_weak (__sendmsg) +weak_alias (__libc_sendmsg, sendmsg) +libc_hidden_weak (sendmsg) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sendto.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sendto.S new file mode 100644 index 000000000..7cb5278e9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sendto.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_sendto +#error Missing definition of NR_sendto needed for cancellation. +#endif +PSEUDO (__libc_sendto, sendto, 6) +ret +PSEUDO_END(__libc_sendto) +libc_hidden_def (__libc_sendto) +weak_alias (__libc_sendto, __sendto) +libc_hidden_weak (__sendto) +weak_alias (__libc_sendto, sendto) +libc_hidden_weak (sendto) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile @@ -0,0 +1,13 @@ +# 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. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch new file mode 100644 index 000000000..9bd7569c9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch @@ -0,0 +1,84 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_SSRC = pt-vfork.S pthread_once.S pthread_rwlock_wrlock.S \ +			pthread_rwlock_rdlock.S pthread_rwlock_unlock.S \ +			lowlevellock.S pthread_barrier_wait.S pthread_cond_broadcast.S \ +			pthread_cond_signal.S \ +			pthread_rwlock_timedwrlock.S pthread_rwlock_timedrdlock.S \ +			sem_post.S sem_timedwait.S sem_trywait.S sem_wait.S + +libc_a_CSRC = fork.c +libc_a_SSRC = libc-lowlevellock.S clone.S vfork.S + +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_once.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_wrlock.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_rdlock.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_unlock.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_unlock.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-pthread_barrier_wait.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_cond_broadcast.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_cond_signal.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_cond_wait.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_cond_timedwait.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-pthread_rwlock_timedwrlock.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_timedrdlock.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-sem_post.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-sem_timedwait.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-sem_trywait.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-sem_wait.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-libc-lowlevellock.S = -D_LIBC_REENTRANT  -DUSE___THREAD + +ASFLAGS-lowlevellock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +#Needed to use the correct SYSCALL_ERROR_HANDLER +ASFLAGS-clone.S += -DUSE___THREAD +ASFLAGS-vfork.S += -DUSE___THREAD +endif + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/sh +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/sh + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJS) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) +LIBC_LINUX_ARCH_OBJ+=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libc_a_SSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=nptl_linux_arch_clean + +nptl_linux_arch_clean: +	$(do_rm) $(addprefix $(LINUX_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h new file mode 100644 index 000000000..969686dd5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h @@ -0,0 +1,168 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 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 _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H	1 + +#define __SIZEOF_PTHREAD_ATTR_T 36 +#define __SIZEOF_PTHREAD_MUTEX_T 24 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_COND_COMPAT_T 12 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 32 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 20 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + + +/* Thread identifiers.  The structure of the attribute type is not +   exposed on purpose.  */ +typedef unsigned long int pthread_t; + + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_ATTR_T]; +  long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_slist +{ +  struct __pthread_internal_slist *__next; +} __pthread_slist_t; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is not exposed on purpose.  */ +typedef union +{ +  struct __pthread_mutex_s +  { +    int __lock; +    unsigned int __count; +    int __owner; +    /* KIND must stay at this position in the structure to maintain +       binary compatibility.  */ +    int __kind; +    unsigned int __nusers; +    __extension__ union +    { +      int __spins; +      __pthread_slist_t __list; +    }; +  } __data; +  char __size[__SIZEOF_PTHREAD_MUTEX_T]; +  long int __align; +} pthread_mutex_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; +  long int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling.  The structure of +   the attribute type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __futex; +    __extension__ unsigned long long int __total_seq; +    __extension__ unsigned long long int __wakeup_seq; +    __extension__ unsigned long long int __woken_seq; +    void *__mutex; +    unsigned int __nwaiters; +    unsigned int __broadcast_seq; +  } __data; +  char __size[__SIZEOF_PTHREAD_COND_T]; +  __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_CONDATTR_T]; +  long int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling.  The +   structure of the attribute type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +    pthread_t __writer; +  } __data; +  char __size[__SIZEOF_PTHREAD_RWLOCK_T]; +  long int __align; +} pthread_rwlock_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; +  long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type.  */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type.  The structure of the type is +   deliberately not exposed.  */ +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIER_T]; +  long int __align; +} pthread_barrier_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; +  int __align; +} pthread_barrierattr_t; +#endif + + +#endif	/* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h new file mode 100644 index 000000000..e6c5d845c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h @@ -0,0 +1,39 @@ +/* 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 _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + + +#define __SIZEOF_SEM_T	16 + + +/* Value returned if `sem_open' failed.  */ +#define SEM_FAILED      ((sem_t *) 0) + +/* Maximum value the semaphore can have.  */ +#define SEM_VALUE_MAX   (2147483647) + + +typedef union +{ +  char __size[__SIZEOF_SEM_T]; +  long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S new file mode 100644 index 000000000..918d57926 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <libc/sysdeps/linux/sh/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c new file mode 100644 index 000000000..e17c0174b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c @@ -0,0 +1,24 @@ +/* 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.  */ + +/* Value passed to 'clone' for initialization of the thread register.  */ +#define TLS_VALUE (pd + 1) + + +/* Get the real implementation.  */ +#include <sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c new file mode 100644 index 000000000..dcedd2625 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c @@ -0,0 +1,31 @@ +/* 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 <sched.h> +#include <signal.h> +#include <stdio.h> +#include <sysdep.h> +#include <tls.h> + +/* TLS pointer argument is passed as the 5-th argument.  */ +#define ARCH_FORK() \ +  INLINE_SYSCALL (clone, 5,						      \ +		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,     \ +		  NULL, &THREAD_SELF->tid, NULL) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S new file mode 100644 index 000000000..94a24b46e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S @@ -0,0 +1,19 @@ +/* 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 "lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h new file mode 100644 index 000000000..062ce2871 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h @@ -0,0 +1,81 @@ +/* Copyright (C) 2003, 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.  */ + +#ifdef __ASSEMBLER__ + +#define _IMP1 #1 +#define _IMM1 #-1 +#define _IMM4 #-4 +#define _IMM6 #-6 +#define _IMM8 #-8 + +#define	INC(mem, reg) \ +	.align	2; \ +	mova	99f, r0; \ +	mov	r15, r1; \ +	mov	_IMM6, r15; \ +98:	mov.l	mem, reg; \ +	add	_IMP1, reg; \ +	mov.l	reg, mem; \ +99:	mov	r1, r15 + +#define	DEC(mem, reg) \ +	.align	2; \ +	mova	99f, r0; \ +	mov	r15, r1; \ +	mov	_IMM6, r15; \ +98:	mov.l	mem, reg; \ +	add	_IMM1, reg; \ +	mov.l	reg, mem; \ +99:	mov	r1, r15 + +#define	XADD(reg, mem, new, old) \ +	.align	2; \ +	mova	99f, r0; \ +	nop; \ +	mov	r15, r1; \ +	mov	_IMM4, r15; \ +98:	mov.l	mem, old; \ +	mov	old, new; \ +	add	reg, new; \ +	mov.l	new, mem; \ +99:	mov	r1, r15 + +#define	XCHG(reg, mem, old) \ +	.align	2; \ +	mova	99f, r0; \ +	nop; \ +	mov	r15, r1; \ +	mov	_IMM4, r15; \ +98:	mov.l	mem, old; \ +	mov.l	reg, mem; \ +99:	mov	r1, r15 + +#define	CMPXCHG(reg, mem, new, old) \ +	.align	2; \ +	mova	99f, r0; \ +	nop; \ +	mov	r15, r1; \ +	mov	_IMM8, r15; \ +98:	mov.l	mem, old; \ +	cmp/eq	old, reg; \ +	bf	99f; \ +	mov.l	new, mem; \ +99:	mov	r1, r15 + +#endif  /* __ASSEMBLER__ */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S new file mode 100644 index 000000000..a5c916bb7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S @@ -0,0 +1,296 @@ +/* Copyright (C) 2003, 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.  */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include "lowlevel-atomic.h" + +	.text + +#define SYS_gettimeofday	__NR_gettimeofday + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.globl	__lll_mutex_lock_wait +	.type	__lll_mutex_lock_wait,@function +	.hidden	__lll_mutex_lock_wait +	.align	5 +	/* void __lll_mutex_lock_wait (int val, int *__futex) */ +__lll_mutex_lock_wait: +	mov	#2, r6 +	cmp/eq	r4, r6 +	mov	r5, r4 +	mov	#0, r7		/* No timeout.  */ +	mov	#FUTEX_WAIT, r5 + +	bf	2f + +1: +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +2: +	XCHG (r6, @r4, r2) +	tst	r2, r2 +	bf	1b + +	rts +	 nop +	.size	__lll_mutex_lock_wait,.-__lll_mutex_lock_wait + + +#ifdef NOT_IN_libc +	.globl	__lll_mutex_timedlock_wait +	.type	__lll_mutex_timedlock_wait,@function +	.hidden	__lll_mutex_timedlock_wait +	.align	5 +	/* int __lll_mutex_timedlock_wait (int val, int *__futex, +				       const struct timespec *abstime) */ +__lll_mutex_timedlock_wait: +	/* Check for a valid timeout value.  */ +	mov.l	@(4,r6), r1 +	mov.l	.L1g, r0 +	cmp/hs	r0, r1 +	bt	3f + +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	mov	r6, r9 +	mov	r5, r8 + +	/* Stack frame for the timespec and timeval structs.  */ +	add	#-8, r15 + +1: +	/* Get current time.  */ +	mov	r15, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	/* Compute relative timeout.  */ +	mov.l	@(4,r15), r0 +	mov.w	.L1k, r1 +	dmulu.l	r0, r1		/* Micro seconds to nano seconds.  */ +	mov.l	@r9, r2 +	mov.l	@(4,r9), r3 +	mov.l	@r15, r0 +	sts	macl, r1 +	sub	r0, r2 +	clrt +	subc	r1, r3 +	bf	4f +	mov.l	.L1g, r1 +	add	r1, r3 +	add	#-1, r2 +4: +	cmp/pz	r2 +	bf	5f		/* Time is already up.  */ + +	mov.l	r2, @r15	/* Store relative timeout.  */ +	mov.l	r3, @(4,r15) + +	mov	#1, r3 +	mov	#2, r6 +	CMPXCHG (r3, @r8, r6, r2) +	tst	r2, r2 +	bt	8f + +	mov	r8, r4 +	mov	#FUTEX_WAIT, r5 +	mov	r15, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov	r0, r4 + +8: +	mov	#0, r3 +	CMPXCHG (r3, @r8, r6, r2) +	bf/s	7f +	mov	#0, r0 + +6: +	add	#8, r15 +	mov.l	@r15+, r8 +	rts +	mov.l	@r15+, r9 +7: +	/* Check whether the time expired.  */ +	mov	#-ETIMEDOUT, r1 +	cmp/eq	r5, r1 +	bt	5f + +	/* Make sure the current holder knows we are going to sleep.  */ +	XCHG (r2, @r8, r3) +	tst	r3, r3 +	bt/s	6b +	mov	#0, r0 +	bra	1b +	nop +3: +	rts +	mov	#EINVAL, r0 +5: +	bra	6b +	mov	#ETIMEDOUT, r0 + +.L1k: +	.word	1000 +	.align	2 +.L1g: +	.long	1000000000 + +	.size	__lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait +#endif + + +#ifdef NOT_IN_libc +	.globl	lll_unlock_wake_cb +	.type	lll_unlock_wake_cb,@function +	.hidden	lll_unlock_wake_cb +	.align	5 +lll_unlock_wake_cb: +	DEC	(@r4, r2) +	tst	r2, r2 +	bt	1f + +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6		/* Wake one thread.  */ +	mov	#0, r7 +	mov.l	r7, @r4		/* Stores 0.  */ +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +1: +	rts +	nop +	.size	lll_unlock_wake_cb,.-lll_unlock_wake_cb +#endif + + +	.globl	__lll_mutex_unlock_wake +	.type	__lll_mutex_unlock_wake,@function +	.hidden	__lll_mutex_unlock_wake +	.align	5 +	/* void __lll_mutex_unlock_wake(int *__futex) */ +__lll_mutex_unlock_wake: +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6		/* Wake one thread.  */ +	mov	#0, r7 +	mov.l	r7, @r4		/* Stores 0.  */ +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	rts +	nop +	.size	__lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake + + +#ifdef NOT_IN_libc +	.globl	__lll_timedwait_tid +	.type	__lll_timedwait_tid,@function +	.hidden	__lll_timedwait_tid +	.align	5 +__lll_timedwait_tid: +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	mov	r4, r8 +	mov	r5, r9 + +	/* Stack frame for the timespec and timeval structs.  */ +	add	#-8, r15 + +2: +	/* Get current time.  */ +	mov	r15, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	/* Compute relative timeout.  */ +	mov.l	@(4,r15), r0 +	mov.w	.L1k2, r1 +	dmulu.l	r0, r1		/* Micro seconds to nano seconds.  */ +	mov.l	@r9, r2 +	mov.l	@(4,r9), r3 +	mov.l	@r15, r0 +	sts	macl, r1 +	sub	r0, r2 +	clrt +	subc	r1, r3 +	bf	5f +	mov.l	.L1g2, r1 +	add	r1, r3 +	add	#-1, r2 +5: +	cmp/pz	r2 +	bf	6f		/* Time is already up.  */ + +	mov.l	r2, @r15	/* Store relative timeout.  */ +	mov.l	r3, @(4,r15) + +	mov.l	@r8, r2 +	tst	r2, r2 +	bt	4f + +	mov	r8, r4 +	mov	#FUTEX_WAIT, r5 +	mov	r2, r6 +	mov	r15, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	mov.l	@r8, r2 +	tst	r2, r2 +	bf	1f +4: +	mov	#0, r0 +3: +	add	#8, r15 +	mov.l	@r15+, r8 +	rts +	mov.l	@r15+, r9 +1: +	/* Check whether the time expired.  */ +	mov	#-ETIMEDOUT, r1 +	cmp/eq	r0, r1 +	bf	2b +6: +	bra	3b +	mov	#ETIMEDOUT, r0 + +.L1k2: +	.word	1000 +	.align	2 +.L1g2: +	.long	1000000000 +	.size	__lll_timedwait_tid,.-__lll_timedwait_tid +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h new file mode 100644 index 000000000..45339f5e0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h @@ -0,0 +1,294 @@ +/* Copyright (C) 2003, 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.  */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H	1 + +#include <syscall.h> +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +/* Initializer for compatibility lock.  */ +#define LLL_MUTEX_LOCK_INITIALIZER		(0) +#define LLL_MUTEX_LOCK_INITIALIZER_LOCKED	(1) +#define LLL_MUTEX_LOCK_INITIALIZER_WAITERS	(2) + +extern int __lll_mutex_lock_wait (int val, int *__futex) attribute_hidden; +extern int __lll_mutex_timedlock_wait (int val, int *__futex, +				       const struct timespec *abstime) +     attribute_hidden; +extern int __lll_mutex_unlock_wake (int *__futex) attribute_hidden; + + +#define lll_mutex_trylock(futex) \ +  ({ unsigned char __result; \ +     __asm __volatile ("\ +	.align 2\n\ +	mova 1f,r0\n\ +	nop\n\ +	mov r15,r1\n\ +	mov #-8,r15\n\ +     0: mov.l @%1,r2\n\ +	cmp/eq r2,%3\n\ +	bf 1f\n\ +	mov.l %2,@%1\n\ +     1: mov r1,r15\n\ +	mov #-1,%0\n\ +	negc %0,%0"\ +	: "=r" (__result) \ +	: "r" (&(futex)), \ +	  "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), \ +	  "r" (LLL_MUTEX_LOCK_INITIALIZER) \ +	: "r0", "r1", "r2", "t", "memory"); \ +     __result; }) + +#define lll_mutex_cond_trylock(futex) \ +  ({ unsigned char __result; \ +     __asm __volatile ("\ +	.align 2\n\ +	mova 1f,r0\n\ +	nop\n\ +	mov r15,r1\n\ +	mov #-8,r15\n\ +     0: mov.l @%1,r2\n\ +	cmp/eq r2,%3\n\ +	bf 1f\n\ +	mov.l %2,@%1\n\ +     1: mov r1,r15\n\ +	mov #-1,%0\n\ +	negc %0,%0"\ +	: "=r" (__result) \ +	: "r" (&(futex)), \ +	  "r" (LLL_MUTEX_LOCK_INITIALIZER_WAITERS), \ +	  "r" (LLL_MUTEX_LOCK_INITIALIZER) \ +	: "r0", "r1", "r2", "t", "memory"); \ +     __result; }) + +#define lll_mutex_lock(futex) \ +  (void) ({ int __result, *__futex = &(futex); \ +	    __asm __volatile ("\ +		.align 2\n\ +		mova 1f,r0\n\ +		nop\n\ +		mov r15,r1\n\ +		mov #-8,r15\n\ +	     0: mov.l @%2,%0\n\ +		tst %0,%0\n\ +		bf 1f\n\ +		mov.l %1,@%2\n\ +	     1: mov r1,r15"\ +		: "=&r" (__result) : "r" (1), "r" (__futex) \ +		: "r0", "r1", "t", "memory"); \ +	    if (__result) \ +	      __lll_mutex_lock_wait (__result, __futex); }) + +/* Special version of lll_mutex_lock which causes the unlock function to +   always wakeup waiters.  */ +#define lll_mutex_cond_lock(futex) \ +  (void) ({ int __result, *__futex = &(futex); \ +	    __asm __volatile ("\ +		.align 2\n\ +		mova 1f,r0\n\ +		nop\n\ +		mov r15,r1\n\ +		mov #-8,r15\n\ +	     0: mov.l @%2,%0\n\ +		tst %0,%0\n\ +		bf 1f\n\ +		mov.l %1,@%2\n\ +	     1: mov r1,r15"\ +		: "=&r" (__result) : "r" (2), "r" (__futex) \ +		: "r0", "r1", "t", "memory"); \ +	    if (__result) \ +	      __lll_mutex_lock_wait (__result, __futex); }) + +#define lll_mutex_timedlock(futex, timeout) \ +  ({ int __result, *__futex = &(futex); \ +     __asm __volatile ("\ +	.align 2\n\ +	mova 1f,r0\n\ +	nop\n\ +	mov r15,r1\n\ +	mov #-8,r15\n\ +     0: mov.l @%2,%0\n\ +	tst %0,%0\n\ +	bf 1f\n\ +	mov.l %1,@%2\n\ +     1: mov r1,r15"\ +	: "=&r" (__result) : "r" (1), "r" (__futex) \ +	: "r0", "r1", "t", "memory"); \ +    if (__result) \ +      __result = __lll_mutex_timedlock_wait (__result, __futex, timeout); \ +    __result; }) + +#define lll_mutex_unlock(futex) \ +  (void) ({ int __result, *__futex = &(futex); \ +	    __asm __volatile ("\ +		.align 2\n\ +		mova 1f,r0\n\ +		mov r15,r1\n\ +		mov #-6,r15\n\ +	     0: mov.l @%1,%0\n\ +		add #-1,%0\n\ +		mov.l %0,@%1\n\ +	     1: mov r1,r15"\ +		: "=&r" (__result) : "r" (__futex) \ +		: "r0", "r1", "memory"); \ +	    if (__result) \ +	      __lll_mutex_unlock_wake (__futex); }) + +#define lll_mutex_islocked(futex) \ +  (futex != 0) + + +/* We have a separate internal lock implementation which is not tied +   to binary compatibility.  */ + +/* Type for lock object.  */ +typedef int lll_lock_t; + +/* Initializers for lock.  */ +#define LLL_LOCK_INITIALIZER		(0) +#define LLL_LOCK_INITIALIZER_LOCKED	(1) + + +# ifdef NEED_SYSCALL_INST_PAD +#  define SYSCALL_WITH_INST_PAD "\ +	trapa #0x14; or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0" +# else +#  define SYSCALL_WITH_INST_PAD "\ +	trapa #0x14" +# endif + +#define lll_futex_wait(futex, val) \ +  do {									      \ +    int __ignore;							      \ +    register unsigned long __r3 __asm ("r3") = SYS_futex;			      \ +    register unsigned long __r4 __asm ("r4") = (unsigned long) (futex);	      \ +    register unsigned long __r5 __asm ("r5") = FUTEX_WAIT;		      \ +    register unsigned long __r6 __asm ("r6") = (unsigned long) (val);	      \ +    register unsigned long __r7 __asm ("r7") = 0;				      \ +    __asm __volatile (SYSCALL_WITH_INST_PAD				      \ +		      : "=z" (__ignore)					      \ +		      : "r" (__r3), "r" (__r4), "r" (__r5),		      \ +			"r" (__r6), "r" (__r7)				      \ +		      : "memory", "t");					      \ +  } while (0) + +#define lll_futex_timed_wait(futex, val, timeout) \ +  ({									      \ +    int __status;							      \ +    register unsigned long __r3 __asm ("r3") = SYS_futex;			      \ +    register unsigned long __r4 __asm ("r4") = (unsigned long) (futex);	      \ +    register unsigned long __r5 __asm ("r5") = FUTEX_WAIT;		      \ +    register unsigned long __r6 __asm ("r6") = (unsigned long) (val);	      \ +    register unsigned long __r7 __asm ("r7") = (timeout);			      \ +    __asm __volatile (SYSCALL_WITH_INST_PAD				      \ +		      : "=z" (__status)					      \ +		      : "r" (__r3), "r" (__r4), "r" (__r5),		      \ +			"r" (__r6), "r" (__r7)				      \ +		      : "memory", "t");					      \ +    __status;								      \ +  }) + + +#define lll_futex_wake(futex, nr) \ +  do {									      \ +    int __ignore;							      \ +    register unsigned long __r3 __asm ("r3") = SYS_futex;			      \ +    register unsigned long __r4 __asm ("r4") = (unsigned long) (futex);	      \ +    register unsigned long __r5 __asm ("r5") = FUTEX_WAKE;		      \ +    register unsigned long __r6 __asm ("r6") = (unsigned long) (nr);	      \ +    register unsigned long __r7 __asm ("r7") = 0;				      \ +    __asm __volatile (SYSCALL_WITH_INST_PAD				      \ +		      : "=z" (__ignore)					      \ +		      : "r" (__r3), "r" (__r4), "r" (__r5),		      \ +			"r" (__r6), "r" (__r7)				      \ +		      : "memory", "t");					      \ +  } while (0) + + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + + +/* The states of a lock are: +    0  -  untaken +    1  -  taken by one user +    2  -  taken by more users */ + +#define lll_trylock(futex) lll_mutex_trylock (futex) +#define lll_lock(futex) lll_mutex_lock (futex) +#define lll_unlock(futex) lll_mutex_unlock (futex) + +#define lll_islocked(futex) \ +  (futex != LLL_LOCK_INITIALIZER) + + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex +   wakeup when the clone terminates.  The memory location contains the +   thread ID while the clone is running and is reset to zero +   afterwards.  */ + +extern int __lll_wait_tid (int *tid) attribute_hidden; +#define lll_wait_tid(tid) \ +  do {									      \ +    __typeof (tid) *__tid = &(tid);					      \ +    while (*__tid != 0)							      \ +      lll_futex_wait (__tid, *__tid);					      \ +  } while (0) + +extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) +     attribute_hidden; +#define lll_timedwait_tid(tid, abstime) \ +  ({									      \ +    int __result = 0;							      \ +    if (tid != 0)							      \ +      {									      \ +	if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)	      \ +	  __result = EINVAL;						      \ +	else								      \ +	  __result = __lll_timedwait_tid (&tid, abstime);		      \ +      }									      \ +    __result; }) + + +/* Conditional variable handling.  */ + +extern void __lll_cond_wait (pthread_cond_t *cond) attribute_hidden; +extern int __lll_cond_timedwait (pthread_cond_t *cond, +				 const struct timespec *abstime) +     attribute_hidden; +extern void __lll_cond_wake (pthread_cond_t *cond) attribute_hidden; +extern void __lll_cond_broadcast (pthread_cond_t *cond) attribute_hidden; + + +#define lll_cond_wait(cond) \ +  __lll_cond_wait (cond) +#define lll_cond_timedwait(cond, abstime) \ +  __lll_cond_timedwait (cond, abstime) +#define lll_cond_wake(cond) \ +  __lll_cond_wake (cond) +#define lll_cond_broadcast(cond) \ +  __lll_cond_broadcast (cond) + +#endif  /* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/not-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/not-cancel.h new file mode 100644 index 000000000..eb83653d3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/not-cancel.h @@ -0,0 +1,82 @@ +/* Uncancelable versions of cancelable interfaces.  Linux/NPTL version. +   Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 <sysdep.h> + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt +extern int __open_nocancel (const char *, int, ...) attribute_hidden; +extern int __close_nocancel (int) attribute_hidden; +extern int __read_nocancel (int, void *, size_t) attribute_hidden; +extern int __write_nocancel (int, const void *, size_t) attribute_hidden; +extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden; + +libc_hidden_proto(__open_nocancel) +libc_hidden_proto(__close_nocancel) +libc_hidden_proto(__read_nocancel) +libc_hidden_proto(__write_nocancel) +libc_hidden_proto(__waitpid_nocancel) + +#else +#define __open_nocancel(name, ...) __open (name, __VA_ARGS__) +#define __close_nocancel(fd) __close (fd) +#define __read_nocancel(fd, buf, len) __read (fd, buf, len) +#define __write_nocancel(fd, buf, len) __write (fd, buf, len) +#define __waitpid_nocancel(pid, stat_loc, options) \ +  __waitpid (pid, stat_loc, options) +#endif + +/* Uncancelable open.  */ +#define open_not_cancel(name, flags, mode) \ +   __open_nocancel (name, flags, mode) +#define open_not_cancel_2(name, flags) \ +   __open_nocancel (name, flags) + +/* Uncancelable close.  */ +#define close_not_cancel(fd) \ +  __close_nocancel (fd) +#define close_not_cancel_no_status(fd) \ +  (void) ({ INTERNAL_SYSCALL_DECL (err);				      \ +	    INTERNAL_SYSCALL (close, err, 1, (fd)); }) + +/* Uncancelable read.  */ +#define read_not_cancel(fd, buf, n) \ +  __read_nocancel (fd, buf, n) + +/* Uncancelable write.  */ +#define write_not_cancel(fd, buf, n) \ +  __write_nocancel (fd, buf, n) + +/* Uncancelable writev.  */ +#define writev_not_cancel_no_status(fd, iov, n) \ +  (void) ({ INTERNAL_SYSCALL_DECL (err);				      \ +	    INTERNAL_SYSCALL (writev, err, 3, (fd), (iov), (n)); }) + +/* Uncancelable fcntl.  */ +#define fcntl_not_cancel(fd, cmd, val) \ +  __fcntl_nocancel (fd, cmd, val) + +/* Uncancelable waitpid.  */ +#ifdef __NR_waitpid +# define waitpid_not_cancel(pid, stat_loc, options) \ +  __waitpid_nocancel (pid, stat_loc, options) +#else +# define waitpid_not_cancel(pid, stat_loc, options) \ +  INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c new file mode 100644 index 000000000..5391d5cc8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c @@ -0,0 +1,143 @@ +/* Special .init and .fini section support for SH. NPTL version. +   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 Library General Public +   License as published by the Free Software Foundation; either +   version 2 of the License, or (at your option) any later version. + +   In addition to the permissions in the GNU Library General Public +   License, the Free Software Foundation gives you unlimited +   permission to link the compiled version of this file with other +   programs, and to distribute those programs without any restriction +   coming from the use of this file.  (The Library General Public +   License restrictions do apply in other respects; for example, they +   cover modification of the file, and distribution when not linked +   into another program.) + +   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 Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public +   License along with the GNU C Library; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +/* This file is compiled into assembly code which is then munged by a sed +   script into two files: crti.s and crtn.s. + +   * crti.s puts a function prologue at the beginning of the +   .init and .fini sections and defines global symbols for +   those addresses, so they can be called as functions. + +   * crtn.s puts the corresponding function epilogues +   in the .init and .fini sections. */ + +__asm__ ("\n\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ +	.section .init\n\ +	.align 5\n\ +	.global	_init\n\ +	.type	_init,@function\n\ +_init:\n\ +	mov.l	r12,@-r15\n\ +	mov.l	r14,@-r15\n\ +	sts.l	pr,@-r15\n\ +	mova	.L22,r0\n\ +	mov.l	.L22,r12\n\ +	add	r0,r12\n\ +	mova	.L24,r0\n\ +	mov.l	.L24,r1\n\ +	add	r0,r1\n\ +	jsr	@r1\n\ +	 nop\n\ +	mova	.L23,r0\n\ +	mov.l	.L23,r1\n\ +	add	r0,r1\n\ +	jsr	@r1\n\ +	 mov	r15,r14\n\ +	bra	1f\n\ +	 nop\n\ +	.align 2\n\ +.L22:\n\ +	.long	_GLOBAL_OFFSET_TABLE_\n\ +.L23:\n\ +	.long	__gmon_start__@PLT\n\ +.L24:\n\ +	.long	__pthread_initialize_minimal_internal@PLT\n\ +1:\n\ +	ALIGN\n\ +	END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ +	.section .init\n\ +	mov	r14,r15\n\ +	lds.l	@r15+,pr\n\ +	mov.l	@r15+,r14\n\ +	rts	\n\ +	mov.l	@r15+,r12\n\ +	END_INIT\n\ +	.section .text\n\ +	.align 5\n\ +	.weak	__gmon_start__\n\ +	.type	__gmon_start__,@function\n\ +__gmon_start__:\n\ +	mov.l	r14,@-r15\n\ +	mov	r15,r14\n\ +	mov	r14,r15\n\ +	rts	\n\ +	mov.l	@r15+,r14\n\ +	\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ +	.section .fini\n\ +	.align 5\n\ +	.global	_fini\n\ +	.type	_fini,@function\n\ +_fini:\n\ +	mov.l	r12,@-r15\n\ +	mov.l	r14,@-r15\n\ +	sts.l	pr,@-r15\n\ +	mova	.L27,r0\n\ +	mov.l	.L27,r12\n\ +	add	r0,r12\n\ +	mov	r15,r14\n\ +	ALIGN\n\ +	END_FINI\n\ +	bra	1f\n\ +	 nop\n\ +	.align	2\n\ +.L27:\n\ +	.long	_GLOBAL_OFFSET_TABLE_\n\ +1:\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ +	.section .fini\n\ +	mov	r14,r15\n\ +	lds.l	@r15+,pr\n\ +	mov.l	@r15+,r14\n\ +	rts	\n\ +	mov.l	@r15+,r12\n\ +\n\ +	END_FINI\n\ +	\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ +"); diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S new file mode 100644 index 000000000..54f2281d7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S @@ -0,0 +1,65 @@ +/* Copyright (C) 2003, 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.  */ + +#include <sysdep.h> +#define _ERRNO_H	1 +#include <bits/errno.h> +#include <tcb-offsets.h> + +/* 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 process, +   and the process ID of the new process to the old process.  */ + +ENTRY (__vfork) +	/* Save the PID value.  */ +	stc	gbr, r2 +	mov.w	.L2, r0 +	mov.l	@(r0,r2), r4 +	neg	r4, r1 +	mov.l	r1, @(r0,r2) + +	mov.w	.L1, r3 +	trapa	#0x10 +	mov     r0, r1 + +	/* Restore the old PID value in the parent.  */ +	tst	r0, r0 +	bt/s	2f +	 stc	gbr, r2 +	mov.w	.L2, r0 +	mov.l	r4, @(r0,r2) +	mov	r1, r0 +2: +	mov	#-12, r2 +	shad	r2, r1 +	not	r1, r1			// r1=0 means r0 = -1 to -4095 +	tst	r1, r1			// i.e. error in linux +	bf	.Lpseudo_end +	SYSCALL_ERROR_HANDLER +.Lpseudo_end: +	rts +	 nop +.L1: +	.word	__NR_vfork +.L2: +	.word	PID - TLS_PRE_TCB_SIZE + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S new file mode 100644 index 000000000..608c7364c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S @@ -0,0 +1,191 @@ +/* Copyright (C) 2003, 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.  */ + +#include <sysdep.h> +#include <lowlevelbarrier.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT	0 +#define FUTEX_WAKE	1 + + +	.text + +	.globl	pthread_barrier_wait +	.type	pthread_barrier_wait,@function +	.align	5 +pthread_barrier_wait: +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 + +	/* Get the mutex.  */ +	mov	#0, r3 +	mov	#1, r4 +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +	bf	1f + +	/* One less waiter.  If this was the last one needed wake +	   everybody.  */ +2: +	mov.l	@(LEFT,r8), r0 +	add	#-1, r0 +	mov.l	r0, @(LEFT,r8) +	tst	r0, r0 +	bt	3f + +	/* There are more threads to come.  */ +	mov.l	@(CURR_EVENT,r8), r6 + +	/* Release the mutex.  */ +	DEC (@(MUTEX,r8), r2) +	tst	r2, r2 +	bf	6f +7: +	/* Wait for the remaining threads.  The call will return immediately +	   if the CURR_EVENT memory has meanwhile been changed.  */ +	mov	r8, r4 +#if CURR_EVENT != 0 +	add	#CURR_EVENT, r4 +#endif +	mov	#FUTEX_WAIT, r5 +	mov	#0, r7 +8: +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	/* Don't return on spurious wakeups.  The syscall does not change +	   any register except r0 so there is no need to reload any of +	   them.  */ +	mov.l	@(CURR_EVENT,r8), r0 +	cmp/eq	r0, r6 +	bt	8b + +	/* Increment LEFT.  If this brings the count back to the +	   initial count unlock the object.  */ +	INC	(@(LEFT,r8), r2) +	mov.l	@(INIT_COUNT,r8), r4 +	cmp/eq	r2, r4 +	bf	10f + +	/* Release the mutex.  We cannot release the lock before +	   waking the waiting threads since otherwise a new thread might +	   arrive and gets waken up, too.  */ +	DEC (@(MUTEX,r8), r2) +	tst	r2, r2 +	bf	9f + +10: +	mov	#0, r0		/* != PTHREAD_BARRIER_SERIAL_THREAD */ +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	rts +	 mov.l	@r15+, r9 + +3: +	/* The necessary number of threads arrived.  */ +	mov.l	@(CURR_EVENT,r8), r1 +	add	#1, r1 +	mov.l	r1, @(CURR_EVENT,r8) + +	/* Wake up all waiters.  The count is a signed number in the kernel +	   so 0x7fffffff is the highest value.  */ +	mov.l	.Lall, r6 +	mov	r8, r4 +#if CURR_EVENT != 0 +	add	#CURR_EVENT, r4 +#endif +	mov	#0, r7 +	mov	#FUTEX_WAKE, r5 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	/* Increment LEFT.  If this brings the count back to the +	   initial count unlock the object.  */ +	INC	(@(LEFT,r8), r2) +	mov.l	@(INIT_COUNT,r8), r4 +	cmp/eq	r2, r4 +	bf	5f + +	/* Release the mutex.  */ +	DEC (@(MUTEX,r8), r2) +	tst	r2, r2 +	bf	4f +5: +	mov	#-1, r0		/* == PTHREAD_BARRIER_SERIAL_THREAD */ +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	rts +	 mov.l	@r15+, r9 + +1: +	mov	r2, r4 +	mov	r8, r5 +	mov.l	.Lwait0, r1 +	bsrf	r1 +	 add	#MUTEX, r5 +.Lwait0b: +	bra	2b +	 nop + +4: +	mov	r8, r4 +	mov.l	.Lwake0, r1 +	bsrf	r1 +	 add	#MUTEX, r4 +.Lwake0b: +	bra	5b +	 nop + +6: +	mov	r6, r9 +	mov	r8, r4 +	mov.l	.Lwake1, r1 +	bsrf	r1 +	 add	#MUTEX, r4 +.Lwake1b: +	bra	7b +	 mov	r9, r6 + +9: +	mov	r6, r9 +	mov	r8, r4 +	mov.l	.Lwake2, r1 +	bsrf	r1 +	 add	#MUTEX, r4 +.Lwake2b: +	bra	10b +	 mov	r9, r6 + +	.align	2 +.Lall: +	.long	0x7fffffff +.Lwait0: +	.long	__lll_mutex_lock_wait-.Lwait0b +.Lwake0: +	.long	__lll_mutex_unlock_wake-.Lwake0b +.Lwake1: +	.long	__lll_mutex_unlock_wake-.Lwake1b +.Lwake2: +	.long	__lll_mutex_unlock_wake-.Lwake2b +	.size	pthread_barrier_wait,.-pthread_barrier_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S new file mode 100644 index 000000000..36eccf1e6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S @@ -0,0 +1,210 @@ +/* Copyright (C) 2003, 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.  */ + +#include <sysdep.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 +#define FUTEX_CMP_REQUEUE	4 + +#define EINVAL			22 + +	.text + +	/* int pthread_cond_broadcast (pthread_cond_t *cond) */ +	.globl	__pthread_cond_broadcast +	.type	__pthread_cond_broadcast, @function +	.align	5 +__pthread_cond_broadcast: +	mov.l   r10, @-r15 +	mov.l   r9, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 + +	/* Get internal lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bf	1f +2: +	mov.l	@(total_seq+4,r8),r0 +	mov.l	@(total_seq,r8),r1 +	mov.l	@(wakeup_seq+4,r8), r2 +	cmp/hi	r2, r0 +	bt	3f +	cmp/hi	r0, r2 +	bt	4f +	mov.l	@(wakeup_seq,r8), r2 +	cmp/hi	r2, r1 +	bf	4f + +3: +	/* Cause all currently waiting threads to recognize they are +	   woken up.  */ +	mov.l	r1, @(wakeup_seq,r8) +	mov.l	r0, @(wakeup_seq+4,r8) +	mov.l	r1, @(woken_seq,r8) +	mov.l	r0, @(woken_seq+4,r8) +	mov.l	@(broadcast_seq,r8), r2 +	add	#1, r2 +	mov.l	r2, @(broadcast_seq,r8) +	add	r1, r1 +	mov	r1, r10 +	mov.l	r10, @(cond_futex,r8) + +	/* Get the address of the mutex used.  */ +	mov.l	@(dep_mutex,r8), r9 + +	/* Unlock.  */ +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	7f + +8: +	/* Don't use requeue for pshared condvars.  */ +	mov	#-1, r0 +	cmp/eq	r0, r9 +	mov	r8, r4 +	bt/s	9f +	 add	#cond_futex, r4 + +	/* Wake up all threads.  */ +	mov	#FUTEX_CMP_REQUEUE, r5 +	mov	#1, r6 +	mov	#-1, r7 +	shlr	r7		/* r7 = 0x7fffffff */ +	mov	r9, r0 +# if MUTEX_FUTEX != 0 +	add	#MUTEX_FUTEX, r0 +# endif +	mov	r10, r1 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x16 +	SYSCALL_INST_PAD + +	/* For any kind of error, which mainly is EAGAIN, we try again +	   with WAKE.  The general test also covers running on old +	   kernels.  */ +	mov	r0, r1 +	mov	#-12, r2 +	shad	r2, r1 +	not	r1, r1 +	tst	r1, r1 +	mov	r8, r4 +	bt/s	9f +	 add	#cond_futex, r4 + +10: +	mov	#0, r0 +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	rts +	 mov.l	@r15+, r10 + +4: +	/* Unlock.  */ +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	5f +6: +	mov	#0, r0 +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	rts +	 mov.l	@r15+, r10 + +1: +	/* Initial locking failed.  */ +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait5, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait5b: +	bra	2b +	 nop + +5: +	/* Unlock in loop requires wakeup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake5, r1 +	bsrf	r1 +	 nop +.Lmwake5b: +	bra	6b +	 nop + +7: +	/* Unlock in loop requires wakeup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake6, r1 +	bsrf	r1 +	 nop +.Lmwake6b: +	bra	8b +	 nop + +9: +	mov	#FUTEX_WAKE, r5 +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	bra	10b +	 nop + +	.align	2 +.Lmwait5: +	.long	__lll_mutex_lock_wait-.Lmwait5b +.Lmwake5: +	.long	__lll_mutex_unlock_wake-.Lmwake5b +.Lmwake6: +	.long	__lll_mutex_unlock_wake-.Lmwake6b +	.size	__pthread_cond_broadcast, .-__pthread_cond_broadcast +weak_alias (__pthread_cond_broadcast, pthread_cond_broadcast) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S new file mode 100644 index 000000000..d92f11cbb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S @@ -0,0 +1,135 @@ +/* Copyright (C) 2003, 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.  */ + +#include <sysdep.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 + +#define EINVAL			22 + +	.text + +	/* int pthread_cond_signal (pthread_cond_t *cond) */ +	.globl	__pthread_cond_signal +	.type	__pthread_cond_signal, @function +	.align	5 +__pthread_cond_signal: +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 + +	/* Get internal lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bf	1f +2: +	mov.l	@(total_seq+4,r8),r0 +	mov.l	@(total_seq,r8),r1 +	mov.l	@(wakeup_seq+4,r8), r2 +	cmp/hi	r2, r0 +	bt	3f +	cmp/hi	r0, r2 +	bt	4f +	mov.l	@(wakeup_seq,r8), r2 +	cmp/hi	r2, r1 +	bf	4f + +3: +	/* Bump the wakeup number.  */ +	mov	#1, r2 +	mov	#0, r3 +	clrt +	mov.l	@(wakeup_seq,r8),r0 +	mov.l	@(wakeup_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(wakeup_seq,r8) +	mov.l	r1,@(wakeup_seq+4,r8) +	mov.l	@(cond_futex,r8),r0 +	add	r2, r0 +	mov.l	r0,@(cond_futex,r8) + +	/* Wake up one thread.  */ +	mov	r8, r4 +	add	#cond_futex, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +4: +	/* Unlock.  */ +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	5f +6: +	mov	#0, r0 +	lds.l	@r15+, pr +	rts +	 mov.l	@r15+, r8 + +1: +	/* Initial locking failed.  */ +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait4, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait4b: +	bra	2b +	 nop + +5: +	/* Unlock in loop requires wakeup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake4, r1 +	bsrf	r1 +	 nop +.Lmwake4b: +	bra	6b +	 nop + +	.align	2 +.Lmwait4: +	.long	__lll_mutex_lock_wait-.Lmwait4b +.Lmwake4: +	.long	__lll_mutex_unlock_wake-.Lmwake4b +	.size	__pthread_cond_signal, .-__pthread_cond_signal +weak_alias (__pthread_cond_signal, pthread_cond_signal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S new file mode 100644 index 000000000..75ce425f8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S @@ -0,0 +1,768 @@ +/* Copyright (C) 2003, 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.  */ + +#include <sysdep.h> +#include <lowlevelcond.h> +#include <pthread-errnos.h> +#include "lowlevel-atomic.h" + +#define SYS_gettimeofday	__NR_gettimeofday + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, +			       const struct timespec *abstime)  */ +	.globl	__pthread_cond_timedwait +	.type	__pthread_cond_timedwait, @function +	.align	5 +__pthread_cond_timedwait: +.LSTARTCODE: +	mov.l	r8, @-r15 +.Lpush_r8: +	mov.l	r9, @-r15 +.Lpush_r9: +	mov.l	r10, @-r15 +.Lpush_r10: +	mov.l	r11, @-r15 +.Lpush_r11: +	mov.l	r12, @-r15 +.Lpush_r12: +	mov.l	r13, @-r15 +.Lpush_r13: +	sts.l	pr, @-r15 +.Lpush_pr: +	add	#-64, r15 +.Lalloc: +	mov	r4, r8 +	mov	r5, r9 +	mov	r6, r13 +#ifdef PIC +	mova	.Lgot0, r0 +	mov.l	.Lgot0, r12 +	add	r0, r12 +#endif + +	mov.l	@(4,r13), r0 +	mov.l	.L1g, r1 +	cmp/hs	r1, r0 +	bf	0f +	bra	18f +	 mov	#EINVAL, r0 +0: +	/* Get internal lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bt	2f +	bra	1f +	 nop +#ifdef PIC +	.align	2 +.Lgot0: +	.long	_GLOBAL_OFFSET_TABLE_ +#endif + +2: +	/* Store the reference to the mutex.  If there is already a +	   different value in there this is a bad user bug.  */ +	mov.l	@(dep_mutex,r8),r0 +	cmp/eq	#-1, r0 +	bt	17f +	mov.l	r9, @(dep_mutex,r8) + +17: +	/* Unlock the mutex.  */ +	mov.l	.Lmunlock1, r1 +	mov	#0, r5 +	bsrf	r1 +	 mov	r9, r4 +.Lmunlock1b: + +	tst	r0, r0 +	bt	0f +	bra	16f +	 nop +0: +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(total_seq,r8),r0 +	mov.l	@(total_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(total_seq,r8) +	mov.l	r1,@(total_seq+4,r8) +	mov.l	@(cond_futex,r8), r0 +	add	r2, r0 +	mov.l	r0, @(cond_futex,r8) +	mov	#(1 << clock_bits), r2 +	mov.l	@(cond_nwaiters,r8), r0 +	add	r2, r0 +	mov.l	r0, @(cond_nwaiters,r8) + +	/* Get and store current wakeup_seq value.  */ +	mov.l	@(wakeup_seq,r8), r10 +	mov.l	@(wakeup_seq+4,r8), r11 +	mov.l	@(broadcast_seq,r8), r0 +	mov.l	r0, @(4,r15) + +8: +	/* Get current time.  */ +#ifdef __NR_clock_gettime +	/* Get the clock number.	 */ +	mov.l	@(cond_nwaiters,r8), r4 +	mov	#((1 << clock_bits) - 1), r0 +	and	r0, r4 +	/* Only clocks 0 and 1 are allowed.  Both are handled in the +	   kernel.  */ +	mov	r15, r5 +	add	#16, r5 +	mov.w	.L__NR_clock_gettime, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD +# ifndef __ASSUME_POSIX_TIMERS +	cmp/eq	#-ENOSYS, r0 +	bt	19f +# endif + +	/* Compute relative timeout.  */ +	mov.l	@r13, r2 +	mov.l	@(4,r13), r3 +	mov.l	@(16,r15), r0 +	bra	0f +	 mov.l	@(20,r15), r1 +.L__NR_clock_gettime: +	.word	__NR_clock_gettime + +# ifndef __ASSUME_POSIX_TIMERS +19: +	mov	r15, r4 +	add	#16, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	/* Compute relative timeout.  */ +	mov.l	@(20,r15), r0 +	mov.w	.L1k, r1 +	dmulu.l	r0, r1		/* Micro seconds to nano seconds.  */ +	mov.l	@r13, r2 +	mov.l	@(4,r13), r3 +	mov.l	@(16,r15), r0 +	sts	macl, r1 +#endif +0: +#else +	mov	r15, r4 +	add	#16, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	/* Compute relative timeout.  */ +	mov.l	@(20,r15), r0 +	mov.w	.L1k, r1 +	dmulu.l	r0, r1		/* Micro seconds to nano seconds.  */ +	mov.l	@r13, r2 +	mov.l	@(4,r13), r3 +	mov.l	@(16,r15), r0 +	sts	macl, r1 +#endif +	sub	r0, r2 +	clrt +	subc	r1, r3 +	bf	12f +	mov.l	.L1g, r1 +	add	r1, r3 +	add	#-1, r2 +12: +	mov	#-ETIMEDOUT, r1 +	mov.l	r1, @(12,r15) +	cmp/pz	r2 +	bf	6f		/* Time is already up.  */ + +	/* Store relative timeout.  */ +	mov.l	r2, @(16,r15) +	mov.l	r3, @(20,r15) +	mov.l	@(cond_futex,r8), r1 +	mov.l	r1, @(8,r15) + +	/* Unlock.  */ +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bt	4f +	bra	3f +	 nop +4: +.LcleanupSTART: +	mov.l	.Lenable1, r1 +	bsrf	r1 +	 nop +.Lenable1b: +	mov.l	r0, @r15 + +	mov	r15, r7 +	add	#16, r7 +	mov	#FUTEX_WAIT, r5 +	mov.l	@(8,r15), r6 +	mov	r8, r4 +	add	#cond_futex, r4 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov.l	r0, @(12,r15) + +	mov.l	.Ldisable1, r1 +	bsrf	r1 +	 mov.l	@r15, r4 +.Ldisable1b: +.LcleanupEND: + +	/* Lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bf	5f +6: +	mov.l	@(broadcast_seq,r8), r0 +	mov.l	@(4,r15), r1 +	cmp/eq	r0, r1 +	bf	23f + +	mov.l	@(woken_seq,r8), r0 +	mov.l	@(woken_seq+4,r8), r1 + +	mov.l	@(wakeup_seq,r8), r2 +	mov.l	@(wakeup_seq+4,r8), r3 + +	cmp/eq	r3, r11 +	bf	7f +	cmp/eq	r2, r10 +	bt	15f +7: +	cmp/eq	r1, r3 +	bf	9f +	cmp/eq	r0, r2 +	bf	9f +15: +	mov.l	@(12,r15),r0 +	cmp/eq	#-ETIMEDOUT, r0 +	bf	8b + +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(wakeup_seq,r8),r0 +	mov.l	@(wakeup_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(wakeup_seq,r8) +	mov.l	r1,@(wakeup_seq+4,r8) +	mov.l	@(cond_futex,r8),r0 +	add	r2, r0 +	mov.l	r0,@(cond_futex,r8) +	mov	#ETIMEDOUT, r0 +	bra	14f +	 mov.l	r0, @(24,r15) + +23: +	mov	#0, r0 +	bra	24f +	 mov.l	r0, @(24,r15) + +9: +	mov	#0, r0 +	mov.l	r0, @(24,r15) +14: +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(woken_seq,r8),r0 +	mov.l	@(woken_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(woken_seq,r8) +	mov.l	r1,@(woken_seq+4,r8) + +24: +	mov	#(1 << clock_bits), r2 +	mov.l	@(cond_nwaiters,r8),r0 +	sub	r2, r0 +	mov.l	r0,@(cond_nwaiters,r8) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	mov.l	@(total_seq,r8),r0 +	mov.l	@(total_seq+4,r8),r1 +	and	r1, r0 +	not	r0, r0 +	cmp/eq	#0, r0 +	bf/s	25f +	 mov	#((1 << clock_bits) - 1), r1 +	not	r1, r1 +	mov.l	@(cond_nwaiters,r8),r0 +	tst	r1, r0 +	bf	25f + +	mov	r8, r4 +	add	#cond_nwaiters, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +25: +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	10f + +11: +	mov	r9, r4 +	mov.l	.Lmlocki1, r1 +	bsrf	r1 +	 nop +.Lmlocki1b: + +	/* We return the result of the mutex_lock operation if it failed.  */ +	tst	r0, r0 +	bf	18f +	mov.l	@(24,r15), r0 + +18: +	add	#64, r15 +	lds.l	@r15+, pr +	mov.l	@r15+, r13 +	mov.l	@r15+, r12 +	mov.l	@r15+, r11 +	mov.l	@r15+, r10 +	mov.l	@r15+, r9 +	rts +	 mov.l	@r15+, r8 + +.L1k: +	.word	1000 +	.align	2 +.Lmunlock1: +	.long	__pthread_mutex_unlock_usercnt-.Lmunlock1b +.Lenable1: +	.long	__pthread_enable_asynccancel-.Lenable1b +.Ldisable1: +	.long	__pthread_disable_asynccancel-.Ldisable1b +.Lmlocki1: +	.long	__pthread_mutex_cond_lock-.Lmlocki1b +.L1g: +	.long	1000000000 + +1: +	/* Initial locking failed.  */ +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait2, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait2b: +	bra	2b +	 nop + +3: +	/* Unlock in loop requires wakeup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake2, r1 +	bsrf	r1 +	 nop +.Lmwake2b: +	bra	4b +	 nop + +5: +	/* Locking in loop failed.  */ +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait3, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait3b: +	bra	6b +	 nop + +10: +	/* Unlock after loop requires wakeup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake3, r1 +	bsrf	r1 +	 nop +.Lmwake3b: +	bra	11b +	 nop + +16: +	/* The initial unlocking of the mutex failed.  */ +	mov.l	r0, @(24,r15) +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	17f + +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake4, r1 +	bsrf	r1 +	 nop +.Lmwake4b: +17: +	bra	18b +	 mov.l	@(24,r15), r0 + +	.align	2 +.Lmwait2: +	.long	__lll_mutex_lock_wait-.Lmwait2b +.Lmwake2: +	.long	__lll_mutex_unlock_wake-.Lmwake2b +.Lmwait3: +	.long	__lll_mutex_lock_wait-.Lmwait3b +.Lmwake3: +	.long	__lll_mutex_unlock_wake-.Lmwake3b +.Lmwake4: +	.long	__lll_mutex_unlock_wake-.Lmwake4b +	.size	__pthread_cond_timedwait, .-__pthread_cond_timedwait +weak_alias (__pthread_cond_timedwait, pthread_cond_timedwait) + + +	.type	__condvar_tw_cleanup, @function +__condvar_tw_cleanup: +	mov	r4, r11 + +	/* Get internal lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bt	1f +	 nop + +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait5, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait5b: + +1: +	mov.l	@(broadcast_seq,r8), r0 +	mov.l	@(4,r15), r1 +	cmp/eq	r0, r1 +	bf	3f + +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(wakeup_seq,r8),r0 +	mov.l	@(wakeup_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(wakeup_seq,r8) +	mov.l	r1,@(wakeup_seq+4,r8) +	mov.l	@(cond_futex,r8),r0 +	add	r2, r0 +	mov.l	r0,@(cond_futex,r8) + +	clrt +	mov.l	@(woken_seq,r8),r0 +	mov.l	@(woken_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(woken_seq,r8) +	mov.l	r1,@(woken_seq+4,r8) + +3: +	mov	#(1 << clock_bits), r2 +	mov.l	@(cond_nwaiters,r8),r0 +	sub	r2, r0 +	mov.l	r0,@(cond_nwaiters,r8) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	mov	#0, r10 +	mov.l	@(total_seq,r8),r0 +	mov.l	@(total_seq+4,r8),r1 +	and	r1, r0 +	not	r0, r0 +	cmp/eq	#0, r0 +	bf/s	4f +	 mov	#((1 << clock_bits) - 1), r1 +	not	r1, r1 +	mov.l	@(cond_nwaiters,r8),r0 +	tst	r1, r0 +	bf	4f + +	mov	r8, r4 +	add	#cond_nwaiters, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov	#1, r10 + +4: +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bt	2f + +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake5, r1 +	bsrf	r1 +	 nop +.Lmwake5b: + +2: +	/* Wake up all waiters to make sure no signal gets lost.  */ +	tst	r10, r10 +	bf/s	5f +	 mov	r8, r4 +	add	#cond_futex, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +5: +        mov.l   .Lmlocki5, r1 +        bsrf    r1 +         mov     r9, r4 +.Lmlocki5b: + +.LcallUR: +	mov.l	.Lresume, r1 +#ifdef PIC +	add	r12, r1 +#endif +	jsr	@r1 +	 mov	r11, r4 +	sleep + +	.align	2 +.Lmwait5: +	.long   __lll_mutex_lock_wait-.Lmwait5b +.Lmwake5: +        .long   __lll_mutex_unlock_wake-.Lmwake5b +.Lmlocki5: +	.long   __pthread_mutex_cond_lock-.Lmlocki5b +.Lresume: +#ifdef PIC +	.long	_Unwind_Resume@GOTOFF +#else +	.long	_Unwind_Resume +#endif +.LENDCODE: +	.size	__condvar_tw_cleanup, .-__condvar_tw_cleanup + + +	.section .gcc_except_table,"a",@progbits +.LexceptSTART: +	.byte	0xff				! @LPStart format (omit) +	.byte	0xff				! @TType format (omit) +	.byte	0x0b				! call-site format +						! DW_EH_PE_sdata4 +	.uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: +	.ualong	.LcleanupSTART-.LSTARTCODE +	.ualong	.LcleanupEND-.LcleanupSTART +	.ualong	__condvar_tw_cleanup-.LSTARTCODE +	.uleb128  0 +	.ualong	.LcallUR-.LSTARTCODE +	.ualong	.LENDCODE-.LcallUR +	.ualong	0 +	.uleb128  0 +.Lcstend: + +	.section .eh_frame,"a",@progbits +.LSTARTFRAME: +	.ualong	.LENDCIE-.LSTARTCIE		! Length of the CIE. +.LSTARTCIE: +	.ualong	0				! CIE ID. +	.byte	1				! Version number. +#ifdef SHARED +	.string	"zPLR"				! NUL-terminated augmentation +						! string. +#else +	.string	"zPL"				! NUL-terminated augmentation +						! string. +#endif +	.uleb128 1				! Code alignment factor. +	.sleb128 -4				! Data alignment factor. +	.byte	0x11				! Return address register +						! column. +#ifdef SHARED +	.uleb128 7				! Augmentation value length. +	.byte	0x9b				! Personality: DW_EH_PE_pcrel +						! + DW_EH_PE_sdata4 +						! + DW_EH_PE_indirect +	.ualong	DW.ref.__gcc_personality_v0-. +	.byte	0x1b				! LSDA Encoding: DW_EH_PE_pcrel +						! + DW_EH_PE_sdata4. +	.byte	0x1b				! FDE Encoding: DW_EH_PE_pcrel +						! + DW_EH_PE_sdata4. +#else +	.uleb128 6				! Augmentation value length. +	.byte	0x0				! Personality: absolute +	.ualong	__gcc_personality_v0 +	.byte	0x0				! LSDA Encoding: absolute +#endif +	.byte 0x0c				! DW_CFA_def_cfa +	.uleb128 0xf +	.uleb128 0 +	.align 2 +.LENDCIE: + +	.ualong	.LENDFDE-.LSTARTFDE		! Length of the FDE. +.LSTARTFDE: +	.ualong	.LSTARTFDE-.LSTARTFRAME		! CIE pointer. +#ifdef SHARED +	.ualong	.LSTARTCODE-.			! PC-relative start address +						! of the code. +#else +	.ualong	.LSTARTCODE			! Start address of the code. +#endif +	.ualong	.LENDCODE-.LSTARTCODE		! Length of the code. +	.uleb128 4				! Augmentation size +#ifdef SHARED +	.ualong	.LexceptSTART-. +#else +	.ualong	.LexceptSTART +#endif +	.byte	0x4 +	.ualong	.Lpush_r8-.LSTARTCODE +	.byte	0xe +	.uleb128 4 +	.byte	0x88 +	.uleb128 1 +	.byte	0x4 +	.ualong	.Lpush_r9-.Lpush_r8 +	.byte	0xe +	.uleb128 8 +	.byte	0x89 +	.uleb128 2 +	.byte	0x4 +	.ualong	.Lpush_r10-.Lpush_r9 +	.byte	0xe +	.uleb128 12 +	.byte	0x8a +	.uleb128 3 +	.byte	0x4 +	.ualong	.Lpush_r11-.Lpush_r10 +	.byte	0xe +	.uleb128 16 +	.byte	0x8b +	.uleb128 4 +	.byte	0x4 +	.ualong	.Lpush_r12-.Lpush_r11 +	.byte	0xe +	.uleb128 20 +	.byte	0x8c +	.uleb128 5 +	.byte	0x4 +	.ualong	.Lpush_r13-.Lpush_r12 +	.byte	0xe +	.uleb128 24 +	.byte	0x8d +	.uleb128 6 +	.byte	0x4 +	.ualong	.Lpush_pr-.Lpush_r13 +	.byte	0xe +	.uleb128 28 +	.byte	0x91 +	.uleb128 7 +	.byte	0x4 +	.ualong	.Lalloc-.Lpush_pr +	.byte	0xe +	.uleb128 92 +	.align	2 +.LENDFDE: + +#ifdef SHARED +	.hidden DW.ref.__gcc_personality_v0 +	.weak   DW.ref.__gcc_personality_v0 +	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +	.align 4 +	.type   DW.ref.__gcc_personality_v0, @object +	.size   DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: +	.long   __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S new file mode 100644 index 000000000..50d98d395 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S @@ -0,0 +1,625 @@ +/* Copyright (C) 2003, 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.  */ + +#include <sysdep.h> +#include <lowlevelcond.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */ +	.globl	__pthread_cond_wait +	.type	__pthread_cond_wait, @function +	.align	5 +__pthread_cond_wait: +.LSTARTCODE: +	mov.l	r8, @-r15 +.Lpush_r8: +	mov.l	r9, @-r15 +.Lpush_r9: +	mov.l	r10, @-r15 +.Lpush_r10: +	mov.l	r11, @-r15 +.Lpush_r11: +	mov.l	r12, @-r15 +.Lpush_r12: +	sts.l	pr, @-r15 +.Lpush_pr: +	add	#-48, r15 +.Lalloc: +	mov	r4, r8 +	mov	r5, r9 +#ifdef PIC +	mova	.Lgot0, r0 +	mov.l	.Lgot0, r12 +	add	r0, r12 +#endif + +	/* Get internal lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bt	2f +	bra	1f +	 nop +#ifdef PIC +	.align	2 +.Lgot0: +	.long	_GLOBAL_OFFSET_TABLE_ +#endif + +2: +	/* Store the reference to the mutex.  If there is already a +	   different value in there this is a bad user bug.  */ +	mov.l	@(dep_mutex,r8),r0 +	cmp/eq	#-1, r0 +	bt	15f +	mov.l	r9, @(dep_mutex,r8) + +15: +	/* Unlock the mutex.  */ +	mov.l	.Lmunlock0, r1 +	mov	#0, r5 +	bsrf	r1 +	 mov	r9, r4 +.Lmunlock0b: + +	tst	r0, r0 +	bt	0f +	bra	12f +	 nop +0: +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(total_seq,r8),r0 +	mov.l	@(total_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(total_seq,r8) +	mov.l	r1,@(total_seq+4,r8) +	mov.l	@(cond_futex,r8),r0 +	add	r2, r0 +	mov.l	r0,@(cond_futex,r8) +	mov	#(1 << clock_bits), r2 +	mov.l	@(cond_nwaiters,r8), r0 +	add	r2, r0 +	mov.l	r0, @(cond_nwaiters,r8) + +	/* Get and store current wakeup_seq value.  */ +	mov.l	@(wakeup_seq,r8), r10 +	mov.l	@(wakeup_seq+4,r8), r11 +	mov.l	@(broadcast_seq,r8), r0 +	mov.l	r0, @(4,r15) + +8: +	mov.l	@(cond_futex,r8),r0 +	mov.l	r0, @(8,r15) + +	/* Unlock.  */ +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	3f +4: +.LcleanupSTART: +	mov.l	.Lenable0, r1 +	bsrf	r1 +	 nop +.Lenable0b: +	mov.l	r0, @r15 + +	mov	#0, r7 +	mov	#FUTEX_WAIT, r5 +	mov.l	@(8,r15), r6 +	mov	r8, r4 +	add	#cond_futex, r4 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	mov.l	.Ldisable0, r1 +	bsrf	r1 +	 mov.l	@r15, r4 +.Ldisable0b: +.LcleanupEND: + +	/* Lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bf	5f +6: +	mov.l	@(broadcast_seq,r8), r0 +	mov.l	@(4,r15), r1 +	cmp/eq	r0, r1 +	bf	16f + +	mov.l	@(woken_seq,r8), r0 +	mov.l	@(woken_seq+4,r8), r1 + +	mov.l	@(wakeup_seq,r8), r2 +	mov.l	@(wakeup_seq+4,r8), r3 + +	cmp/eq	r3, r11 +	bf	7f +	cmp/eq	r2, r10 +	bt	8b +7: +	cmp/eq	r1, r3 +	bf	9f +	cmp/eq	r0, r2 +	bt	8b +9: +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(woken_seq,r8),r0 +	mov.l	@(woken_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(woken_seq,r8) +	mov.l	r1,@(woken_seq+4,r8) + +16: +	mov	#(1 << clock_bits), r2 +	mov.l	@(cond_nwaiters,r8),r0 +	sub	r2, r0 +	mov.l	r0,@(cond_nwaiters,r8) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	mov.l	@(total_seq,r8),r0 +	mov.l	@(total_seq+4,r8),r1 +	and	r1, r0 +	not	r0, r0 +	cmp/eq	#0, r0 +	bf/s	17f +	 mov	#((1 << clock_bits) - 1), r1 +	not	r1, r1 +	mov.l	@(cond_nwaiters,r8),r0 +	tst	r1, r0 +	bf	17f + +	mov	r8, r4 +	add	#cond_nwaiters, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +17: +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	10f + +11: +	mov.l	.Lmlocki0, r1 +	bsrf	r1 +	 mov	r9, r4 +.Lmlocki0b: +	/* We return the result of the mutex_lock operation.  */ + +14: +	add	#48, r15 +	lds.l	@r15+, pr +	mov.l	@r15+, r12 +	mov.l	@r15+, r11 +	mov.l	@r15+, r10 +	mov.l	@r15+, r9 +	rts +	 mov.l	@r15+, r8 + +	.align	2 +.Lmunlock0: +	.long	__pthread_mutex_unlock_usercnt-.Lmunlock0b +.Lenable0: +	.long	__pthread_enable_asynccancel-.Lenable0b +.Ldisable0: +	.long	__pthread_disable_asynccancel-.Ldisable0b +.Lmlocki0: +	.long	__pthread_mutex_cond_lock-.Lmlocki0b + +1: +	/* Initial locking failed.  */ +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait0, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait0b: +	bra	2b +	 nop +3: +	/* Unlock in loop requires waekup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake0, r1 +	bsrf	r1 +	 nop +.Lmwake0b: +	bra	4b +	 nop + +5: +	/* Locking in loop failed.  */ +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait1, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait1b: +	bra	6b +	 nop + +10: +	/* Unlock after loop requires wakeup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake1, r1 +	bsrf	r1 +	 nop +.Lmwake1b: +	bra	11b +	 nop + +12: +	/* The initial unlocking of the mutex failed.  */ +	mov.l	r0, @(12,r15) +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	13f + +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake2, r1 +	bsrf	r1 +	 nop +.Lmwake2b: + +13: +	bra	14b +	 mov.l	@(12,r15), r0 + +	.align	2 +.Lmwait0: +	.long	__lll_mutex_lock_wait-.Lmwait0b +.Lmwake0: +	.long	__lll_mutex_unlock_wake-.Lmwake0b +.Lmwait1: +	.long	__lll_mutex_lock_wait-.Lmwait1b +.Lmwake1: +	.long	__lll_mutex_unlock_wake-.Lmwake1b +.Lmwake2: +	.long	__lll_mutex_unlock_wake-.Lmwake2b +	.size	__pthread_cond_wait, .-__pthread_cond_wait +weak_alias (__pthread_cond_wait, pthread_cond_wait) + + +	.type	__condvar_w_cleanup, @function +__condvar_w_cleanup: +	mov	r4, r11 + +	/* Get internal lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bt	1f +	 nop + +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait3, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait3b: + +1: +	mov.l	@(broadcast_seq,r8), r0 +	mov.l	@(4,r15), r1 +	cmp/eq	r0, r1 +	bf	3f + +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(wakeup_seq,r8),r0 +	mov.l	@(wakeup_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(wakeup_seq,r8) +	mov.l	r1,@(wakeup_seq+4,r8) +	mov.l	@(cond_futex,r8),r0 +	add	r2, r0 +	mov.l	r0,@(cond_futex,r8) + +	clrt +	mov.l	@(woken_seq,r8),r0 +	mov.l	@(woken_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(woken_seq,r8) +	mov.l	r1,@(woken_seq+4,r8) + +3: +	mov	#(1 << clock_bits), r2 +	mov.l	@(cond_nwaiters,r8),r0 +	sub	r2, r0 +	mov.l	r0,@(cond_nwaiters,r8) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	mov	#0, r10 +	mov.l	@(total_seq,r8),r0 +	mov.l	@(total_seq+4,r8),r1 +	and	r1, r0 +	not	r0, r0 +	cmp/eq	#0, r0 +	bf/s	4f +	 mov	#((1 << clock_bits) - 1), r1 +	not	r1, r1 +	mov.l	@(cond_nwaiters,r8),r0 +	tst	r1, r0 +	bf	4f + +	mov	r8, r4 +	add	#cond_nwaiters, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov	#1, r10 + +4: +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bt	2f + +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake3, r1 +	bsrf	r1 +	 nop +.Lmwake3b: + +2: +	/* Wake up all waiters to make sure no signal gets lost.  */ +	tst	r10, r10 +	bf/s	5f +	 mov	r8, r4 +	add	#cond_futex, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +5: +        mov.l   .Lmlocki3, r1 +        bsrf    r1 +         mov     r9, r4 +.Lmlocki3b: + +.LcallUR: +	mov.l	.Lresume, r1 +#ifdef PIC +	add	r12, r1 +#endif +	jsr	@r1 +	 mov	r11, r4 +	sleep + +	.align	2 +.Lmwait3: +	.long   __lll_mutex_lock_wait-.Lmwait3b +.Lmwake3: +        .long   __lll_mutex_unlock_wake-.Lmwake3b +.Lmlocki3: +	.long   __pthread_mutex_cond_lock-.Lmlocki3b +.Lresume: +#ifdef PIC +	.long	_Unwind_Resume@GOTOFF +#else +	.long	_Unwind_Resume +#endif +.LENDCODE: +	.size	__condvar_w_cleanup, .-__condvar_w_cleanup + + +	.section .gcc_except_table,"a",@progbits +.LexceptSTART: +	.byte	0xff				! @LPStart format (omit) +	.byte	0xff				! @TType format (omit) +	.byte	0x0b				! call-site format +						! DW_EH_PE_sdata4 +	.uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: +	.ualong	.LcleanupSTART-.LSTARTCODE +	.ualong	.LcleanupEND-.LcleanupSTART +	.ualong	__condvar_w_cleanup-.LSTARTCODE +	.uleb128  0 +	.ualong	.LcallUR-.LSTARTCODE +	.ualong	.LENDCODE-.LcallUR +	.ualong	0 +	.uleb128  0 +.Lcstend: + +	.section .eh_frame,"a",@progbits +.LSTARTFRAME: +	.ualong	.LENDCIE-.LSTARTCIE		! Length of the CIE. +.LSTARTCIE: +	.ualong	0				! CIE ID. +	.byte	1				! Version number. +#ifdef SHARED +	.string	"zPLR"				! NUL-terminated augmentation +						! string. +#else +	.string	"zPL"				! NUL-terminated augmentation +						! string. +#endif +	.uleb128 1				! Code alignment factor. +	.sleb128 -4				! Data alignment factor. +	.byte	0x11				! Return address register +						! column. +#ifdef SHARED +	.uleb128 7				! Augmentation value length. +	.byte	0x9b				! Personality: DW_EH_PE_pcrel +						! + DW_EH_PE_sdata4 +						! + DW_EH_PE_indirect +	.ualong	DW.ref.__gcc_personality_v0-. +	.byte	0x1b				! LSDA Encoding: DW_EH_PE_pcrel +						! + DW_EH_PE_sdata4. +	.byte	0x1b				! FDE Encoding: DW_EH_PE_pcrel +						! + DW_EH_PE_sdata4. +#else +	.uleb128 6				! Augmentation value length. +	.byte	0x0				! Personality: absolute +	.ualong	__gcc_personality_v0 +	.byte	0x0				! LSDA Encoding: absolute +#endif +	.byte 0x0c				! DW_CFA_def_cfa +	.uleb128 0xf +	.uleb128 0 +	.align 2 +.LENDCIE: + +	.ualong	.LENDFDE-.LSTARTFDE		! Length of the FDE. +.LSTARTFDE: +	.ualong	.LSTARTFDE-.LSTARTFRAME		! CIE pointer. +#ifdef SHARED +	.ualong	.LSTARTCODE-.			! PC-relative start address +						! of the code. +#else +	.ualong	.LSTARTCODE			! Start address of the code. +#endif +	.ualong	.LENDCODE-.LSTARTCODE		! Length of the code. +	.uleb128 4				! Augmentation size +#ifdef SHARED +	.ualong	.LexceptSTART-. +#else +	.ualong	.LexceptSTART +#endif +	.byte	0x4 +	.ualong	.Lpush_r8-.LSTARTCODE +	.byte	0xe +	.uleb128 4 +	.byte	0x88 +	.uleb128 1 +	.byte	0x4 +	.ualong	.Lpush_r9-.Lpush_r8 +	.byte	0xe +	.uleb128 8 +	.byte	0x89 +	.uleb128 2 +	.byte	0x4 +	.ualong	.Lpush_r10-.Lpush_r9 +	.byte	0xe +	.uleb128 12 +	.byte	0x8a +	.uleb128 3 +	.byte	0x4 +	.ualong	.Lpush_r11-.Lpush_r10 +	.byte	0xe +	.uleb128 16 +	.byte	0x8b +	.uleb128 4 +	.byte	0x4 +	.ualong	.Lpush_r12-.Lpush_r11 +	.byte	0xe +	.uleb128 20 +	.byte	0x8c +	.uleb128 5 +	.byte	0x4 +	.ualong	.Lpush_pr-.Lpush_r12 +	.byte	0xe +	.uleb128 24 +	.byte	0x91 +	.uleb128 6 +	.byte	0x4 +	.ualong	.Lalloc-.Lpush_pr +	.byte	0xe +	.uleb128 72 +	.align	2 +.LENDFDE: + +#ifdef SHARED +	.hidden DW.ref.__gcc_personality_v0 +	.weak   DW.ref.__gcc_personality_v0 +	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +	.align 4 +	.type   DW.ref.__gcc_personality_v0, @object +	.size   DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: +	.long   __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S new file mode 100644 index 000000000..2e8e6a1d5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S @@ -0,0 +1,245 @@ +/* Copyright (C) 2003, 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.  */ + +#include <unwindbuf.h> +#include <sysdep.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT	0 +#define FUTEX_WAKE	1 + +	.comm	__fork_generation, 4, 4 + +	.text +	.globl	__pthread_once +	.type	__pthread_once,@function +	.align	5 +	cfi_startproc +__pthread_once: +	mov.l	@r4, r0 +	tst	#2, r0 +	bt	1f +	rts +	 mov	#0, r0 + +1: +	mov.l	r12, @-r15 +	cfi_adjust_cfa_offset (4) +	cfi_rel_offset (r12, 0) +	mov.l	r9, @-r15 +	cfi_adjust_cfa_offset (4) +	cfi_rel_offset (r9, 0) +	mov.l	r8, @-r15 +	cfi_adjust_cfa_offset (4) +	cfi_rel_offset (r8, 0) +	sts.l	pr, @-r15 +	cfi_adjust_cfa_offset (4) +	cfi_rel_offset (pr, 0) +	mov	r5, r8 +	mov	r4, r9 + +	/* Not yet initialized or initialization in progress. +	   Get the fork generation counter now.  */ +6: +	mov.l	@r4, r1 +	mova	.Lgot, r0 +	mov.l	.Lgot, r12 +	add	r0, r12 + +5: +	mov	r1, r0 + +	tst	#2, r0 +	bf	4f + +	and	#3, r0 +	mov.l	.Lfgen, r2 +#ifdef PIC +	add	r12, r2 +#endif +	mov.l	@r2, r3 +	or	r3, r0 +	or	#1, r0 +	mov	r0, r3 +	mov	r1, r5 + +	CMPXCHG (r5, @r4, r3, r2) +	bf	5b + +	/* Check whether another thread already runs the initializer.  */ +	mov	r2, r0 +	tst	#1, r0 +	bt	3f	/* No -> do it.  */ + +	/* Check whether the initializer execution was interrupted +	   by a fork.  */ +	xor	r3, r0 +	mov	#-4, r1	/* -4 = 0xfffffffc */ +	tst	r1, r0 +	bf	3f	/* Different for generation -> run initializer.  */ + +	/* Somebody else got here first.  Wait.  */ +	mov	#FUTEX_WAIT, r5 +	mov	r3, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	bra	6b +	 nop + +	.align	2 +.Lgot: +	.long	_GLOBAL_OFFSET_TABLE_ +#ifdef PIC +.Lfgen: +	.long	__fork_generation@GOTOFF +#else +.Lfgen: +	.long	__fork_generation +#endif + +3: +	/* Call the initializer function after setting up the +	   cancellation handler.  Note that it is not possible here +	   to use the unwind-based cleanup handling.  This would require +	   that the user-provided function and all the code it calls +	   is compiled with exceptions.  Unfortunately this cannot be +	   guaranteed.  */ +	add	#-UNWINDBUFSIZE, r15 +	cfi_adjust_cfa_offset (UNWINDBUFSIZE) + +	mov.l	.Lsigsetjmp, r1 +	mov	#UWJMPBUF, r4 +	add	r15, r4 +	bsrf	r1 +	 mov	#0, r5 +.Lsigsetjmp0: +	tst	r0, r0 +	bf	7f + +	mov.l	.Lcpush, r1 +	bsrf	r1 +	 mov	r15, r4 +.Lcpush0: + +	/* Call the user-provided initialization function.  */ +	jsr	@r8 +	 nop + +	/* Pop the cleanup handler.  */ +	mov.l	.Lcpop, r1 +	bsrf	r1 +	 mov	r15, r4 +.Lcpop0: + +	add	#UNWINDBUFSIZE, r15 +	cfi_adjust_cfa_offset (-UNWINDBUFSIZE) + +	/* Sucessful run of the initializer.  Signal that we are done.  */ +	INC (@r9, r2) +	/* Wake up all other threads.  */ +	mov	r9, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +4: +	lds.l	@r15+, pr +	cfi_adjust_cfa_offset (-4) +	cfi_restore (pr) +	mov.l	@r15+, r8 +	cfi_adjust_cfa_offset (-4) +	cfi_restore (r8) +	mov.l	@r15+, r9 +	cfi_adjust_cfa_offset (-4) +	cfi_restore (r9) +	mov.l	@r15+, r12 +	cfi_adjust_cfa_offset (-4) +	cfi_restore (r12) +	rts +	 mov	#0, r0 + +7: +	/* __sigsetjmp returned for the second time.  */ +	cfi_adjust_cfa_offset (UNWINDBUFSIZE+16) +	cfi_offset (r12, -4) +	cfi_offset (r9, -8) +	cfi_offset (r8, -12) +	cfi_offset (pr, -16) +	mov	#0, r7 +	mov.l	r7, @r9 +	mov	r9, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	mov.l	.Lunext, r1 +	bsrf	r1 +	 mov	r15, r4 +.Lunext0: +	/* NOTREACHED */ +	sleep +	cfi_endproc + +	.align	2 +.Lsigsetjmp: +	.long	__sigsetjmp@PLT-(.Lsigsetjmp0-.) +.Lcpush: +	.long	HIDDEN_JUMPTARGET(__pthread_register_cancel)-.Lcpush0 +.Lcpop: +	.long	HIDDEN_JUMPTARGET(__pthread_unregister_cancel)-.Lcpop0 +.Lunext: +	.long	HIDDEN_JUMPTARGET(__pthread_unwind_next)-.Lunext0 +	.size	__pthread_once,.-__pthread_once + +	.globl	__pthread_once_internal +__pthread_once_internal = __pthread_once + +	.globl	pthread_once +pthread_once = __pthread_once + + +	.type	clear_once_control,@function +	.align	5 +clear_once_control: +	mov	#0, r0 +	mov.l	r0, @r4 + +	mov	#FUTEX_WAKE, r5 +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	rts +	 nop +	.size	clear_once_control,.-clear_once_control diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S new file mode 100644 index 000000000..ce1ab37c8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S @@ -0,0 +1,220 @@ +/* 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +	.globl	__pthread_rwlock_rdlock +	.type	__pthread_rwlock_rdlock,@function +	.align	5 +__pthread_rwlock_rdlock: +	mov.l	r12, @-r15 +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 + +	/* Get the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	1f +2: +	mov.l	@(WRITER,r8), r0 +	tst	r0, r0 +	bf	14f +	mov.l	@(WRITERS_QUEUED,r8), r0 +	tst	r0, r0 +	bt	5f +	mov.l	@(FLAGS,r8), r0 +	tst	r0, r0 +	bt	5f +3: +	mov.l	@(READERS_QUEUED,r8), r0 +	add	#1, r0 +	mov.l	r0, @(READERS_QUEUED,r8) +	tst	r0, r0 +	bt	4f + +	mov.l	@(READERS_WAKEUP,r8), r9 + +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	10f +11: +	mov	r8, r4 +	add	#READERS_WAKEUP, r4 +	mov	#FUTEX_WAIT, r5 +	mov	r9, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	/* Reget the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	12f +13: +	mov.l	@(READERS_QUEUED,r8), r0 +	add	#-1, r0 +	bra	2b +	 mov.l	r0, @(READERS_QUEUED,r8) + +5: +	mov	#0, r3 +	mov.l	@(NR_READERS,r8), r0 +	add	#1, r0 +	mov.l	r0, @(NR_READERS,r8) +	tst	r0, r0 +	bt	8f + +9: +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	6f +7: +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	mov.l	@r15+, r12 +	rts +	 mov	r3, r0 + +1: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait0, r1 +	bsrf	r1 +	 nop +.Lwait0b: +	bra	2b +	 nop +14: +	stc	gbr, r1 +	mov.w	.Ltidoff, r2 +	add	r2, r1 +	mov.l	@r1, r1 +	cmp/eq	r1, r0 +	bf	3b +	/* Deadlock detected.  */ +	bra	9b +	 mov	#EDEADLK, r3 + +.Ltidoff: +	.word	TID - TLS_PRE_TCB_SIZE + +6: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake0, r1 +	bsrf	r1 +	 nop +.Lwake0b: +	bra	7b +	 mov	#0, r3 + +8: +	/* Overflow.  */ +	mov.l	@(NR_READERS,r8), r1 +	add	#-1, r1 +	mov.l	r1, @(NR_READERS,r8) +	bra	9b +	 mov	#EAGAIN, r3 + +4: +	/* Overflow.  */ +	mov.l	@(READERS_QUEUED,r8), r1 +	add	#-1, r1 +	mov.l	r1, @(READERS_QUEUED,r8) +	bra	9b +	 mov	#EAGAIN, r3 + +10: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake1, r1 +	bsrf	r1 +	 nop +.Lwake1b: +	bra	11b +	 nop + +12: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait1, r1 +	bsrf	r1 +	 nop +.Lwait1b: +	bra	13b +	 nop + +	.align	2 +.Lwait0: +	.long	__lll_mutex_lock_wait-.Lwait0b +.Lwake0: +	.long	__lll_mutex_unlock_wake-.Lwake0b +.Lwait1: +	.long	__lll_mutex_lock_wait-.Lwait1b +.Lwake1: +	.long	__lll_mutex_unlock_wake-.Lwake1b +	.size	__pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock + +	.globl	pthread_rwlock_rdlock +pthread_rwlock_rdlock = __pthread_rwlock_rdlock + +	.globl	__pthread_rwlock_rdlock_internal +__pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S new file mode 100644 index 000000000..8a4e7d3bc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S @@ -0,0 +1,280 @@ +/* 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + +#define SYS_gettimeofday	__NR_gettimeofday +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +	.globl	pthread_rwlock_timedrdlock +	.type	pthread_rwlock_timedrdlock,@function +	.align	5 +pthread_rwlock_timedrdlock: +	mov.l	r12, @-r15 +	mov.l	r10, @-r15 +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	add	#-8, r15 +	mov	r4, r8 +	mov	r5, r9 + +	/* Get the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	1f +2: +	mov.l	@(WRITER,r8), r0 +	tst	r0, r0 +	bf	14f +	mov.l	@(WRITERS_QUEUED,r8), r0 +	tst	r0, r0 +	bt	5f +	mov.l	@(FLAGS,r8), r0 +	tst	r0, r0 +	bt	5f +3: +	/* Check the value of the timeout parameter.  */ +	mov.l	.L1g0, r1 +	mov.l	@(4,r9), r0 +	cmp/hs	r1, r0 +	bt	19f + +	mov.l	@(READERS_QUEUED,r8), r0 +	add	#1, r0 +	mov.l	r0, @(READERS_QUEUED,r8) +	tst	r0, r0 +	bt	4f + +	mov.l	@(READERS_WAKEUP,r8), r10 + +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	10f + +11: +	/* Get current time.  */ +	mov	r15, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	mov.l	@(4,r15), r0 +	mov.w	.L1k0, r1 +	dmulu.l	r0, r1		/* Milli seconds to nano seconds.  */ +	mov.l	@r9, r2 +	mov.l	@(4,r9), r3 +	mov.l	@r15, r0 +	sts	macl, r1 +	sub	r0, r2 +	clrt +	subc	r1, r3 +	bf	15f +	mov.l	.L1g0, r1 +	add	r1, r3 +	add	#-1, r2 +15: +	cmp/pz	r2 +	bf	16f		/* Time is already up.  */ + +	/* Store relative timeout.  */ +	mov.l	r2, @r15 +	mov.l	r3, @(4,r15) + +	/* Futex call.  */ +	mov	r15, r7 +	mov	#FUTEX_WAIT, r5 +	mov	r10, r6 +	mov	r8, r4 +	add	#READERS_WAKEUP, r4 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov	r0, r3 + +17: +	/* Reget the lock.  */ +	mov	#0, r5 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r5, @r8, r4, r2) +#else +	CMPXCHG (r5, @(MUTEX,r8), r4, r2) +#endif +	bf	12f + +13: +	mov.l	@(READERS_QUEUED,r8), r0 +	add	#-1, r0 +	mov.l	r0, @(READERS_QUEUED,r8) +	mov	#-ETIMEDOUT, r0 +	cmp/eq	r0, r3 +	bf	2b + +18: +	bra	9f +	 mov	#ETIMEDOUT, r3 + +5: +	mov	#0, r3 +	mov.l	@(NR_READERS,r8), r0 +	add	#1, r0 +	mov.l	r0, @(NR_READERS,r8) +	tst	r0, r0 +	bt	8f + +9: +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	6f +7: +	add	#8,r15 +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	mov.l	@r15+, r10 +	mov.l	@r15+, r12 +	rts +	 mov	r3, r0 + +	.align	2 +.L1k0: +	.long	1000 +.L1g0: +	.long	1000000000 + +1: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait2, r1 +	bsrf	r1 +	 nop +.Lwait2b: +	bra	2b +	 nop +14: +	stc	gbr, r1 +	mov.w	.Ltidoff, r2 +	add	r2, r1 +	mov.l	@r1, r1 +	cmp/eq	r1, r0 +	bf	3b +	/* Deadlock detected.  */ +	bra	9b +	 mov	#EDEADLK, r3 + +.Ltidoff: +	.word	TID - TLS_PRE_TCB_SIZE + +6: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake2, r1 +	bsrf	r1 +	 nop +.Lwake2b: +	bra	7b +	 mov	#0, r3 + +8: +	/* Overflow.  */ +	mov.l	@(NR_READERS,r8), r1 +	add	#-1, r1 +	mov.l	r1, @(NR_READERS,r8) +	bra	9b +	 mov	#EAGAIN, r3 + +4: +	/* Overflow.  */ +	mov.l	@(READERS_QUEUED,r8), r1 +	add	#-1, r1 +	mov.l	r1, @(READERS_QUEUED,r8) +	bra	9b +	 mov	#EAGAIN, r3 + +10: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake3, r1 +	bsrf	r1 +	 nop +.Lwake3b: +	bra	11b +	 nop + +12: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait3, r1 +	bsrf	r1 +	 nop +.Lwait3b: +	bra	13b +	 nop + +16: +	bra	17b +	 mov	#-ETIMEDOUT, r3 + +19: +	bra	9b +	 mov	#EINVAL, r3 + +	.align	2 +.Lwait2: +	.long	__lll_mutex_lock_wait-.Lwait2b +.Lwake2: +	.long	__lll_mutex_unlock_wake-.Lwake2b +.Lwait3: +	.long	__lll_mutex_lock_wait-.Lwait3b +.Lwake3: +	.long	__lll_mutex_unlock_wake-.Lwake3b +	.size	pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S new file mode 100644 index 000000000..6284140a6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S @@ -0,0 +1,265 @@ +/* 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + +#define SYS_gettimeofday	__NR_gettimeofday +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +	.globl	pthread_rwlock_timedwrlock +	.type	pthread_rwlock_timedwrlock,@function +	.align	5 +pthread_rwlock_timedwrlock: +	mov.l	r12, @-r15 +	mov.l	r10, @-r15 +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	add	#-8, r15 +	mov	r4, r8 +	mov	r5, r9 + +	/* Get the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	1f +2: +	mov.l	@(WRITER,r8), r0 +	tst	r0, r0 +	bf	14f +	mov.l	@(NR_READERS,r8), r0 +	tst	r0, r0 +	bt	5f +3: +	/* Check the value of the timeout parameter.  */ +	mov.l	.L1g1, r1 +	mov.l	@(4,r9), r0 +	cmp/hs	r1, r0 +	bt	19f + +	mov.l	@(WRITERS_QUEUED,r8), r0 +	add	#1, r0 +	mov.l	r0, @(WRITERS_QUEUED,r8) +	tst	r0, r0 +	bt	4f + +	mov.l	@(WRITERS_WAKEUP,r8), r10 + +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	10f + +11: +	/* Get current time.  */ +	mov	r15, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	mov.l	@(4,r15), r0 +	mov.w	.L1k1, r1 +	dmulu.l	r0, r1		/* Milli seconds to nano seconds.  */ +	mov.l	@r9, r2 +	mov.l	@(4,r9), r3 +	mov.l	@r15, r0 +	sts	macl, r1 +	sub	r0, r2 +	clrt +	subc	r1, r3 +	bf	15f +	mov.l	.L1g1, r1 +	add	r1, r3 +	add	#-1, r2 +15: +	cmp/pz	r2 +	bf	16f		/* Time is already up.  */ + +	/* Store relative timeout.  */ +	mov.l	r2, @r15 +	mov.l	r3, @(4,r15) + +	/* Futex call.  */ +	mov	r15, r7 +	mov	#FUTEX_WAIT, r5 +	mov	r10, r6 +	mov	r8, r4 +	add	#WRITERS_WAKEUP, r4 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov	r0, r3 + +17: +	/* Reget the lock.  */ +	mov	#0, r5 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r5, @r8, r4, r2) +#else +	CMPXCHG (r5, @(MUTEX,r8), r4, r2) +#endif +	bf	12f + +13: +	mov.l	@(WRITERS_QUEUED,r8), r0 +	add	#-1, r0 +	mov.l	r0, @(WRITERS_QUEUED,r8) +	mov	#-ETIMEDOUT, r0 +	cmp/eq	r0, r3 +	bf	2b + +18: +	bra	9f +	 mov	#ETIMEDOUT, r3 + +19: +	bra	9f +	 mov	#EINVAL, r3 + +5: +	mov	#0, r3 +	stc	gbr, r0 +	mov.w	.Ltidoff, r1 +	mov.l	@(r0,r1), r0 +	mov.l	r0, @(WRITER,r8) +9: +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	6f +7: +	add	#8,r15 +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	mov.l	@r15+, r10 +	mov.l	@r15+, r12 +	rts +	 mov	r3, r0 + +.L1k1: +	.word	1000 +	.align	2 +.L1g1: +	.long	1000000000 + +1: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait6, r1 +	bsrf	r1 +	 nop +.Lwait6b: +	bra	2b +	 nop +14: +	stc	gbr, r1 +	mov.w	.Ltidoff, r2 +	add	r2, r1 +	mov.l	@r1, r1 +	cmp/eq	r1, r0 +	bf	3b +	bra	9b +	 mov	#EDEADLK, r3 +6: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake6, r1 +	bsrf	r1 +	 nop +.Lwake6b: +	bra	7b +	 mov	#0, r3 + +.Ltidoff: +	.word	TID - TLS_PRE_TCB_SIZE + +4: +	/* Overflow.  */ +	mov.l	@(WRITERS_QUEUED,r8), r1 +	add	#-1, r1 +	mov.l	r1, @(WRITERS_QUEUED,r8) +	bra	9b +	 mov	#EAGAIN, r3 + +10: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake7, r1 +	bsrf	r1 +	 nop +.Lwake7b: +	bra	11b +	 nop + +12: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait7, r1 +	bsrf	r1 +	 nop +.Lwait7b: +	bra	13b +	 nop + +16: +	bra	17b +	 mov	#-ETIMEDOUT, r3 + +	.align	2 +.Lwait6: +	.long	__lll_mutex_lock_wait-.Lwait6b +.Lwake6: +	.long	__lll_mutex_unlock_wake-.Lwake6b +.Lwait7: +	.long	__lll_mutex_lock_wait-.Lwait7b +.Lwake7: +	.long	__lll_mutex_unlock_wake-.Lwake7b +	.size	pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S new file mode 100644 index 000000000..74f32f8f9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S @@ -0,0 +1,169 @@ +/* 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +	.globl	__pthread_rwlock_unlock +	.type	__pthread_rwlock_unlock,@function +	.align	5 +__pthread_rwlock_unlock: +	mov.l	r12, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 + +	/* Get the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	1f +2: +	mov.l	@(WRITER,r8), r0 +	tst	r0, r0 +	bf	5f +	mov.l	@(NR_READERS,r8), r0 +	add	#-1, r0 +	mov.l	r0, @(NR_READERS,r8) +	tst	r0, r0 +	bf	6f +5: +	mov	#0, r0 +	mov.l	r0, @(WRITER,r8) +	mov	#1, r6 +	mov	r8, r4 +	add	#WRITERS_WAKEUP, r4 +	mov.l	@(WRITERS_QUEUED,r8), r0 +	tst	r0, r0 +	bf	0f + +	/* If also no readers waiting nothing to do.  */ +	mov.l	@(READERS_QUEUED,r8), r0 +	tst	r0, r0 +	bt	6f + +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	r8, r4 +	add	#READERS_WAKEUP, r4 + +0: +	mov.l	@r4, r0 +	add	#1, r0 +	mov.l	r0, @r4 +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	7f + +8: +	mov	#FUTEX_WAKE, r5 +	mov	#SYS_futex, r3 +	mov	#0, r7 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r12 +	rts +	 mov	#0, r0 +6: +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	3f +4: +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r12 +	rts +	 mov	#0, r0 + +1: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait8, r1 +	bsrf	r1 +	 nop +.Lwait8b: +	bra	2b +	 nop +3: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake8, r1 +	bsrf	r1 +	 nop +.Lwake8b: +	bra	4b +	 nop + +7: +	mov.l	r4, @-r15 +	mov.l	r6, @-r15 +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake9, r1 +	bsrf	r1 +	 nop +.Lwake9b: + +	mov.l	@r15+, r6 +	bra	8b +	 mov.l	@r15+, r4 + +	.align	2 +.Lwait8: +	.long	__lll_mutex_lock_wait-.Lwait8b +.Lwake8: +	.long	__lll_mutex_unlock_wake-.Lwake8b +.Lwake9: +	.long	__lll_mutex_unlock_wake-.Lwake9b +	.size	__pthread_rwlock_unlock,.-__pthread_rwlock_unlock + +	.globl	pthread_rwlock_unlock +pthread_rwlock_unlock = __pthread_rwlock_unlock + +	.globl	__pthread_rwlock_unlock_internal +__pthread_rwlock_unlock_internal = __pthread_rwlock_unlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S new file mode 100644 index 000000000..d071f7f03 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S @@ -0,0 +1,202 @@ +/* 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +	.globl	__pthread_rwlock_wrlock +	.type	__pthread_rwlock_wrlock,@function +	.align	5 +__pthread_rwlock_wrlock: +	mov.l	r12, @-r15 +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 + +	/* Get the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	1f +2: +	mov.l	@(WRITER,r8), r0 +	tst	r0, r0 +	bf	14f +	mov.l	@(NR_READERS,r8), r0 +	tst	r0, r0 +	bt	5f +3: +	mov.l	@(WRITERS_QUEUED,r8), r0 +	add	#1, r0 +	mov.l	r0, @(WRITERS_QUEUED,r8) +	tst	r0, r0 +	bt	4f + +	mov.l	@(WRITERS_WAKEUP,r8), r9 + +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	10f +11: +	mov	r8, r4 +	add	#WRITERS_WAKEUP, r4 +	mov	#FUTEX_WAIT, r5 +	mov	r9, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	/* Reget the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	12f +13: +	mov.l	@(WRITERS_QUEUED,r8), r0 +	add	#-1, r0 +	bra	2b +	 mov.l	r0, @(WRITERS_QUEUED,r8) + +5: +	mov	#0, r3 +	stc	gbr, r0 +	mov.w	.Ltidoff, r1 +	mov.l	@(r0,r1), r0 +	mov.l	r0, @(WRITER,r8) +9: +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	6f +7: +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	mov.l	@r15+, r12 +	rts +	 mov	r3, r0 + +1: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait4, r1 +	bsrf	r1 +	 nop +.Lwait4b: +	bra	2b +	 nop +14: +	stc	gbr, r1 +	mov.w	.Ltidoff, r2 +	add	r2, r1 +	mov.l	@r1, r1 +	cmp/eq	r1, r0 +	bf	3b +	bra	9b +	 mov	#EDEADLK, r3 +6: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake4, r1 +	bsrf	r1 +	 nop +.Lwake4b: +	bra	7b +	 mov	#0, r3 + +.Ltidoff: +	.word	TID - TLS_PRE_TCB_SIZE + +4: +	mov.l	@(WRITERS_QUEUED,r8), r1 +	add	#-1, r1 +	mov.l	r1, @(WRITERS_QUEUED,r8) +	bra	9b +	 mov	#EAGAIN, r3 + +10: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake5, r1 +	bsrf	r1 +	 nop +.Lwake5b: +	bra	11b +	 nop + +12: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait5, r1 +	bsrf	r1 +	 nop +.Lwait5b: +	bra	13b +	 nop + +	.align	2 +.Lwait4: +	.long	__lll_mutex_lock_wait-.Lwait4b +.Lwake4: +	.long	__lll_mutex_unlock_wake-.Lwake4b +.Lwait5: +	.long	__lll_mutex_lock_wait-.Lwait5b +.Lwake5: +	.long	__lll_mutex_unlock_wake-.Lwake5b +	.globl	pthread_rwlock_wrlock +pthread_rwlock_wrlock = __pthread_rwlock_wrlock + +	.globl	__pthread_rwlock_wrlock_internal +__pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S new file mode 100644 index 000000000..9755b7e16 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S @@ -0,0 +1,84 @@ +/* Copyright (C) 2003, 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.  */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday	__NR_gettimeofday +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +	.text + +	.globl	__new_sem_post +	.type	__new_sem_post,@function +	.align	5 +__new_sem_post: +	INC	(@r4, r6) + +	mov	#FUTEX_WAKE, r5 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	cmp/pz	r0 +	bf	1f +	rts +	 mov	#0, r0 + +1: +	mov	#EINVAL, r2 +	mova	.Lgot3, r0 +	mov.l	.Lgot3, r12 +	add	r0, r12 + +#if USE___THREAD +	mov.l	.Lerrno3, r0 +	stc	gbr, r1 +	mov.l	@(r0, r12), r0 +	bra .Lexit +	add	r1, r0 +	.align 2 +.Lerrno3: +	.long	errno@GOTTPOFF +.Lexit: +#else +	mov.l	.Lerrloc3, r1 +	bsrf	r1 +	 nop +.Lerrloc3b: +#endif +	mov.l	r2, @r0 +	lds.l	@r15+, pr +	mov.l	@r15+, r12 +	rts +	 mov	#-1, r0 + +	.align	2 +.Lgot3: +	.long	_GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc3: +	.long	__errno_location@PLT-(.Lerrloc3b-.) +#endif +	.size	__new_sem_post,.-__new_sem_post +	weak_alias(__new_sem_post, sem_post) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S new file mode 100644 index 000000000..40782fcaf --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S @@ -0,0 +1,240 @@ +/* Copyright (C) 2003, 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.  */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday	__NR_gettimeofday +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +	.text + +	.globl	sem_timedwait +	.type	sem_timedwait,@function +	.align	5 +	cfi_startproc +sem_timedwait: +	/* First check for cancellation.  */ +	stc	gbr, r0 +	mov.w	.Lchand, r1 +	mov.l	@(r0,r1), r0 +	mov	#0xf9, r1 +	and	r1, r0 +	cmp/eq	#8, r0 +	bf	0f +	bra	10f +	 stc	gbr, r0 +0: +	mov.l	@r4, r0 +2: +	tst	r0, r0 +	bt	1f +	mov	r0, r3 +	mov	r0, r6 +	add	#-1, r3 +	CMPXCHG (r6, @r4, r3, r2) +	bf/s	2b +	 mov	r2, r0 +	rts +	 mov	#0, r0 + +1: +	/* Check whether the timeout value is valid.  */ +	mov.l	r8, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r8, 0) +	mov.l	r9, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r9, 0) +	mov.l	r10, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r10, 0) +	mov.l	r12, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r12, 0) +	sts.l	pr, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (pr, 0) +	add	#-8, r15 +	cfi_adjust_cfa_offset(8) +	mov	r4, r8 +	mov	r5, r9 + +	/* Check for invalid nanosecond field.  */ +	mov.l	@(4,r9), r0 +	mov.l	.L1g, r1 +	cmp/hs	r1, r0 +	bt/s	6f +	 mov	#EINVAL, r0 +7: +	mov.l	.Lenable0, r1 +	bsrf	r1 +	 nop +.Lenable0b: +	mov	r0, r10 + +	/* Compute relative timeout.  */ +	mov	r15, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	mov.l	@(4,r15), r0 +	mov.w	.L1k, r1 +	dmulu.l	r0, r1		/* Milli seconds to nano seconds.  */ +	mov.l	@r9, r2 +	mov.l	@(4,r9), r3 +	mov.l	@r15, r0 +	sts	macl, r1 +	sub	r0, r2 +	clrt +	subc	r1, r3 +	bf	5f +	mov.l	.L1g, r1 +	add	r1, r3 +	add	#-1, r2 +5: +	cmp/pz	r2 +	bf/s	6f		/* Time is already up.  */ +	mov	#ETIMEDOUT, r0 + +	/* Store relative timeout.  */ +	mov.l	r2, @r15 +	mov.l	r3, @(4,r15) + +	/* Futex call.  */ +	mov	r8, r4 +	mov	#FUTEX_WAIT, r5 +	mov	#0, r6 +	mov	r15, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	mov.l	.Ldisable0, r1 +	mov	r10, r4 +	bsrf	r1 +	 mov	r0, r10 +.Ldisable0b: +	mov	r10, r0 + +	tst	r0, r0 +	bt	9f +	cmp/eq	#-EWOULDBLOCK, r0 +	bf	3f +9: +	mov.l	@r8, r0 +8: +	tst	r0, r0 +	bt	7b + +	mov	r0, r3 +	mov	r0, r4 +	add	#-1, r3 +	CMPXCHG (r4, @r8, r3, r2) +	bf/s	8b +	 mov	r2, r0 + +	add	#8, r15 +	lds.l	@r15+, pr +	mov.l	@r15+, r12 +	mov.l	@r15+, r10 +	mov.l	@r15+, r9 +	mov.l	@r15+, r8 +	rts +	 mov	#0, r0 + +3: +	neg	r0, r0 +6: +	mov	r0, r8 +	mova	.Lgot2, r0 +	mov.l	.Lgot2, r12 +	add	r0, r12 + +#if USE___THREAD +	mov.l	.Lerrno2, r0 +	stc	gbr, r1 +	mov.l	@(r0, r12), r0 +	bra .Lexit +	add	r1, r0 +	.align 2 +.Lerrno2: +	.long	errno@GOTTPOFF +.Lexit: +#else +	mov.l	.Lerrloc2, r1 +	bsrf	r1 +	 nop +.Lerrloc2b: +#endif +	mov.l	r8, @r0 +	add	#8, r15 +	lds.l	@r15+, pr +	mov.l	@r15+, r12 +	mov.l	@r15+, r10 +	mov.l	@r15+, r9 +	mov.l	@r15+, r8 +	rts +	 mov	#-1, r0 + +10: +	/* Canceled.  */ +	mov.w	.Lresult, r1 +	mov	#-1, r2 +	mov.l	r2, @(r0,r1) +	mov.w	.Lchand, r0 +	or.b	#0x10, @(r0,gbr) +	stc	gbr, r0 +	mov.w	.Lclbuf, r1 +	mov.l	.Lunwind, r2 +	braf	r2 +	 mov.l	@(r0,r1), r4 +.Lunwindb: +	cfi_endproc + +.L1k: +	.word	1000 +.Lchand: +	.word	CANCELHANDLING - TLS_PRE_TCB_SIZE +.Lresult: +	.word	RESULT - TLS_PRE_TCB_SIZE +.Lclbuf: +	.word	CLEANUP_JMP_BUF - TLS_PRE_TCB_SIZE +	.align	2 +.L1g: +	.long	1000000000 +.Lgot2: +	.long	_GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc2: +	.long	__errno_location@PLT-(.Lerrloc2b-.) +#endif +.Lenable0: +	.long	__pthread_enable_asynccancel-.Lenable0b +.Ldisable0: +	.long	__pthread_disable_asynccancel-.Ldisable0b +.Lunwind: +	.long	HIDDEN_JUMPTARGET (__pthread_unwind)-.Lunwindb +	.size	sem_timedwait,.-sem_timedwait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S new file mode 100644 index 000000000..00c61f3bb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S @@ -0,0 +1,89 @@ +/* Copyright (C) 2003, 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.  */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include "lowlevel-atomic.h" + + +	.text + +	.globl	__new_sem_trywait +	.type	__new_sem_trywait,@function +	.align	5 +__new_sem_trywait: +	mov.l	r12, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 +	mov.l	@r8, r0 +2: +	tst	r0, r0 +	bt	1f + +	mov	r0, r3 +	mov	r0, r4 +	add	#-1, r3 +	CMPXCHG (r4, @r8, r3, r2) +	bf/s	2b +	 mov	r2, r0 + +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r12 +	rts +	 mov	#0, r0 + +1: +	mov	#EAGAIN, r8 +	mova	.Lgot1, r0 +	mov.l	.Lgot1, r12 +	add	r0, r12 + +#if USE___THREAD +	mov.l	.Lerrno1, r0 +	stc	gbr, r1 +	mov.l	@(r0, r12), r0 +	bra .Lexit +	add	r1, r0 +	.align 2 +.Lerrno1: +	.long	errno@GOTTPOFF +.Lexit: +#else +	mov.l	.Lerrloc1, r1 +	bsrf	r1 +	 nop +.Lerrloc1b: +#endif +	mov.l	r8, @r0 +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r12 +	rts +	 mov	#-1, r0 + +	.align	2 +.Lgot1: +	.long	_GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc1: +	.long	__errno_location@PLT-(.Lerrloc1b-.) +#endif +	.size	__new_sem_trywait,.-__new_sem_trywait +	weak_alias(__new_sem_trywait, sem_trywait) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S new file mode 100644 index 000000000..7d13fa130 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S @@ -0,0 +1,166 @@ +/* Copyright (C) 2003, 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.  */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday	__NR_gettimeofday +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +	.text + +	.globl	__new_sem_wait +	.type	__new_sem_wait,@function +	.align	5 +	cfi_startproc +__new_sem_wait: +	/* First check for cancellation.  */ +	stc	gbr, r0 +	mov.w	.Lchand, r1 +	mov.l	@(r0,r1), r0 +	mov	#0xf9, r1 +	and	r1, r0 +	cmp/eq	#8, r0 +	bt	5f + +	mov.l	r8, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r8, 0) +	mov.l	r10, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r10, 0) +	mov.l	r12, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r12, 0) +	sts.l	pr, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (pr, 0) +	mov	r4, r8 +3: +	mov.l	@r8, r0 +2: +	tst	r0, r0 +	bt	1f +	mov	r0, r3 +	mov	r0, r4 +	add	#-1, r3 +	CMPXCHG (r4, @r8, r3, r2) +	bf/s	2b +	 mov	r2, r0 +	bra	9f +	 mov	#0, r0 + +1: +	mov.l	.Lenable0, r1 +	bsrf	r1 +	 nop +.Lenable0b: +	mov	r0, r10 + +	mov	r8, r4 +	mov	#FUTEX_WAIT, r5 +	mov	#0, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	mov.l	.Ldisable0, r1 +	mov	r10, r4 +	bsrf	r1 +	 mov	r0, r10 +.Ldisable0b: +	mov	r10, r0 + +	tst	r0, r0 +	bt	3b +	cmp/eq	#-EWOULDBLOCK, r0 +	bt	3b +	neg	r0, r0 + +	mov	r0, r8 +	mova	.Lgot0, r0 +	mov.l	.Lgot0, r12 +	add	r0, r12 + +#if USE___THREAD +	mov.l	.Lerrno0, r0 +	stc	gbr, r1 +	mov.l	@(r0, r12), r0 +	bra .Lexit +	add	r1, r0 +	.align 2 +.Lerrno0: +	.long	errno@GOTTPOFF +.Lexit: +#else +	mov.l	.Lerrloc0, r1 +	bsrf	r1 +	 nop +.Lerrloc0b: +#endif +	mov.l	r8, @r0 +	mov	#-1, r0 +9: +	lds.l	@r15+, pr +	mov.l	@r15+, r12 +	mov.l	@r15+, r10 +	rts +	 mov.l	@r15+, r8 +5: +	/* Canceled.  */ +	stc	gbr, r0 +	mov.w	.Lresult, r1 +	mov	#-1, r2 +	mov.l	r2, @(r0,r1) +	mov.w	.Lchand, r0 +	or.b	#0x10, @(r0,gbr) +	stc	gbr, r0 +	mov.w	.Lclbuf, r1 +	mov.l	.Lunwind, r2 +	braf	r2 +	 mov.l	@(r0,r1), r4 +.Lunwindb: +	cfi_endproc + +.Lchand: +	.word	CANCELHANDLING - TLS_PRE_TCB_SIZE +.Lresult: +	.word	RESULT - TLS_PRE_TCB_SIZE +.Lclbuf: +	.word	CLEANUP_JMP_BUF - TLS_PRE_TCB_SIZE +	.align	2 +.Lgot0: +	.long	_GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc0: +	.long	__errno_location@PLT-(.Lerrloc0b-.) +#endif +.Lenable0: +	.long	__pthread_enable_asynccancel-.Lenable0b +.Ldisable0: +	.long	__pthread_disable_asynccancel-.Ldisable0b +.Lunwind: +	.long	HIDDEN_JUMPTARGET (__pthread_unwind)-.Lunwindb +	.size	__new_sem_wait,.-__new_sem_wait +	weak_alias(__new_sem_wait, sem_wait) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h new file mode 100644 index 000000000..8cdcac556 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h @@ -0,0 +1,4 @@ +/*  4 instruction cycles not accessing cache and TLB are needed after +    trapa instruction to avoid an SH-4 silicon bug.  */ +#define NEED_SYSCALL_INST_PAD +#include <sysdeps/unix/sysv/linux/sh/lowlevellock.h> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/sysdep.h new file mode 100644 index 000000000..1aed1a14a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/sysdep.h @@ -0,0 +1,4 @@ +/*  4 instruction cycles not accessing cache and TLB are needed after +    trapa instruction to avoid an SH-4 silicon bug.  */ +#define NEED_SYSCALL_INST_PAD +#include_next <sysdep.h> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h new file mode 100644 index 000000000..2c0cbe99a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h @@ -0,0 +1,24 @@ +/* Determine whether the host has multiple processors.  SH version. +   Copyright (C) 2002 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 Library General Public License as +   published by the Free Software Foundation; either version 2 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 +   Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public +   License along with the GNU C Library; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +static inline int +is_smp_system (void) +{ +  return 0; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h new file mode 100644 index 000000000..dbaa44385 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h @@ -0,0 +1,247 @@ +/* Copyright (C) 2003, 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.  */ + +#include <tls.h> +#include <sysdep.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# define _IMM12 #-12 +# define _IMM16 #-16 +# define _IMP16 #16 +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ +  .text; \ +  ENTRY (name); \ +  .Lpseudo_start: \ +    SINGLE_THREAD_P; \ +    bf .Lpseudo_cancel; \ +    .type __##syscall_name##_nocancel,@function; \ +    .globl __##syscall_name##_nocancel; \ +    __##syscall_name##_nocancel: \ +    DO_CALL (syscall_name, args); \ +    mov r0,r1; \ +    mov _IMM12,r2; \ +    shad r2,r1; \ +    not r1,r1; \ +    tst r1,r1; \ +    bt .Lsyscall_error; \ +    bra .Lpseudo_end; \ +     nop; \ +    .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + .Lpseudo_cancel: \ +    sts.l pr,@-r15; \ + .LCFI0: \ +    add _IMM16,r15; \ +    SAVE_ARGS_##args; \ + .LCFI1: \ +    CENABLE; \ +    LOAD_ARGS_##args; \ +    add _IMP16,r15; \ + .LCFI2: \ +    lds.l @r15+,pr; \ + .LCFI3: \ +    DO_CALL(syscall_name, args); \ +    SYSCALL_INST_PAD; \ +    sts.l pr,@-r15; \ + .LCFI4: \ +    mov.l r0,@-r15; \ + .LCFI5: \ +    CDISABLE; \ +    mov.l @r15+,r0; \ + .LCFI6: \ +    lds.l @r15+,pr; \ + .LCFI7: \ +    mov r0,r1; \ +    mov _IMM12,r2; \ +    shad r2,r1; \ +    not r1,r1; \ +    tst r1,r1; \ +    bf .Lpseudo_end; \ + .Lsyscall_error: \ +    SYSCALL_ERROR_HANDLER; \ + .Lpseudo_end: \ + /* Create unwinding information for the syscall wrapper.  */ \ + .section .eh_frame,"a",@progbits; \ + .Lframe1: \ +    .ualong .LECIE1-.LSCIE1; \ + .LSCIE1: \ +    .ualong 0x0; \ +    .byte   0x1; \ +    AUGMENTATION_STRING; \ +    .uleb128 0x1; \ +    .sleb128 -4; \ +    .byte   0x11; \ +    AUGMENTATION_PARAM; \ +    .byte   0xc; \ +    .uleb128 0xf; \ +    .uleb128 0x0; \ +    .align 2; \ + .LECIE1: \ + .LSFDE1: \ +    .ualong .LEFDE1-.LASFDE1; \ + .LASFDE1: \ +    .ualong .LASFDE1-.Lframe1; \ +    START_SYMBOL_REF; \ +    .ualong .Lpseudo_end - .Lpseudo_start; \ +    AUGMENTATION_PARAM_FDE; \ +    .byte   0x4; \ +    .ualong .LCFI0-.Lpseudo_start; \ +    .byte   0xe; \ +    .uleb128 0x4; \ +    .byte   0x91; \ +    .uleb128 0x1; \ +    .byte   0x4; \ +    .ualong .LCFI1-.LCFI0; \ +    .byte   0xe; \ +    .uleb128 0x14; \ +    FRAME_REG_##args; \ +    .byte   0x4; \ +    .ualong .LCFI2-.LCFI1; \ +    .byte   0xe; \ +    .uleb128 0x4; \ +    .byte   0x4; \ +    .ualong .LCFI3-.LCFI2; \ +    .byte   0xe; \ +    .uleb128 0x0; \ +    .byte   0xd1; \ +    .byte   0x4; \ +    .ualong .LCFI4-.LCFI3; \ +    .byte   0xe; \ +    .uleb128 0x4; \ +    .byte   0x91; \ +    .uleb128 0x1; \ +    .byte   0x4; \ +    .ualong .LCFI5-.LCFI4; \ +    .byte   0xe; \ +    .uleb128 0x8; \ +    .byte   0x80; \ +    .uleb128 0x2; \ +    .byte   0x4; \ +    .ualong .LCFI6-.LCFI5; \ +    .byte   0xe; \ +    .uleb128 0x4; \ +    .byte   0xc0; \ +    .byte   0x4; \ +    .ualong .LCFI7-.LCFI6; \ +    .byte   0xe; \ +    .uleb128 0x0; \ +    .byte   0xd1; \ +    .align 2; \ + .LEFDE1: \ + .previous + +# ifdef SHARED +#  define AUGMENTATION_STRING .string "zR" +#  define AUGMENTATION_PARAM .uleb128 1; .byte 0x1b +#  define AUGMENTATION_PARAM_FDE .uleb128 0 +#  define START_SYMBOL_REF .long .Lpseudo_start-. +# else +#  define AUGMENTATION_STRING .ascii "\0" +#  define AUGMENTATION_PARAM +#  define AUGMENTATION_PARAM_FDE +#  define START_SYMBOL_REF .long .Lpseudo_start +# endif + +# define FRAME_REG_0	/* Nothing.  */ +# define FRAME_REG_1	FRAME_REG_0; .byte 0x84; .uleb128 5 +# define FRAME_REG_2	FRAME_REG_1; .byte 0x85; .uleb128 4 +# define FRAME_REG_3	FRAME_REG_2; .byte 0x86; .uleb128 3 +# define FRAME_REG_4	FRAME_REG_3; .byte 0x87; .uleb128 2 +# define FRAME_REG_5	FRAME_REG_4 +# define FRAME_REG_6	FRAME_REG_5 + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ +  END (sym) + +# define SAVE_ARGS_0	/* Nothing.  */ +# define SAVE_ARGS_1	SAVE_ARGS_0; mov.l r4,@(0,r15) +# define SAVE_ARGS_2	SAVE_ARGS_1; mov.l r5,@(4,r15) +# define SAVE_ARGS_3	SAVE_ARGS_2; mov.l r6,@(8,r15) +# define SAVE_ARGS_4	SAVE_ARGS_3; mov.l r7,@(12,r15) +# define SAVE_ARGS_5	SAVE_ARGS_4 +# define SAVE_ARGS_6	SAVE_ARGS_5 + +# define LOAD_ARGS_0	/* Nothing.  */ +# define LOAD_ARGS_1	LOAD_ARGS_0; mov.l @(0,r15),r4 +# define LOAD_ARGS_2	LOAD_ARGS_1; mov.l @(4,r15),r5 +# define LOAD_ARGS_3	LOAD_ARGS_2; mov.l @(8,r15),r6 +# define LOAD_ARGS_4	LOAD_ARGS_3; mov.l @(12,r15),r7 +# define LOAD_ARGS_5	LOAD_ARGS_4 +# define LOAD_ARGS_6	LOAD_ARGS_5 + +# ifdef IS_IN_libpthread +#  define __local_enable_asynccancel	__pthread_enable_asynccancel +#  define __local_disable_asynccancel	__pthread_disable_asynccancel +# elif !defined NOT_IN_libc +#  define __local_enable_asynccancel	__libc_enable_asynccancel +#  define __local_disable_asynccancel	__libc_disable_asynccancel +# elif defined IS_IN_librt +#  define __local_enable_asynccancel	__librt_enable_asynccancel +#  define __local_disable_asynccancel	__librt_disable_asynccancel +# else +#  error Unsupported library +# endif + +# define CENABLE \ +	mov.l 1f,r0; \ +	bsrf r0; \ +	 nop; \ +     0: bra 2f; \ +	 mov r0,r2; \ +	.align 2; \ +     1: .long __local_enable_asynccancel - 0b; \ +     2: + +# define CDISABLE \ +	mov.l 1f,r0; \ +	bsrf r0; \ +	 mov r2,r4; \ +     0: bra 2f; \ +	 nop; \ +	.align 2; \ +     1: .long __local_disable_asynccancel - 0b; \ +     2: + +# ifndef __ASSEMBLER__ +#  define SINGLE_THREAD_P \ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ +				   header.multiple_threads) == 0, 1) +# else +#  define SINGLE_THREAD_P \ +	stc gbr,r0; \ +	mov.w 0f,r1; \ +	sub r1,r0; \ +	mov.l @(MULTIPLE_THREADS_OFFSET,r0),r0; \ +	bra 1f; \ +	 tst r0,r0; \ +     0: .word TLS_PRE_TCB_SIZE; \ +     1: + +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep.h new file mode 100644 index 000000000..546a21231 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep.h @@ -0,0 +1,224 @@ +/* Copyright (C) 1992,1993,1995,1996,1997,1998,1999,2000,2002,2003,2004 +	Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995. +   Changed by Kaz Kojima, <kkojima@rr.iij4u.or.jp>. + +   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 _LINUX_SH_SYSDEP_H +#define _LINUX_SH_SYSDEP_H 1 + +/* There is some commonality.  */ +#include <sysdeps/unix/sh/sysdep.h> + +/* For Linux we can use the system call table in the header file +	/usr/include/asm/unistd.h +   of the kernel.  But these symbols do not follow the SYS_* syntax +   so we have to redefine the `SYS_ify' macro here.  */ +#undef SYS_ify +#define SYS_ify(syscall_name)	(__NR_##syscall_name) + + +#ifdef __ASSEMBLER__ + +/* Linux uses a negative return value to indicate syscall errors, +   unlike most Unices, which use the condition codes' carry flag. + +   Since version 2.1 the return value of a system call might be +   negative even if the call succeeded.  E.g., the `lseek' system call +   might return a large offset.  Therefore we must not anymore test +   for < 0, but test for a real error by making sure the value in R0 +   is a real error number.  Linus said he will make sure the no syscall +   returns a value in -1 .. -4095 as a valid result so we can savely +   test with -4095.  */ + +#define _IMM1 #-1 +#define _IMM12 #-12 +#undef	PSEUDO +#define	PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ +    DO_CALL (syscall_name, args); \ +    mov r0,r1; \ +    mov _IMM12,r2; \ +    shad r2,r1; \ +    not r1,r1; \ +    tst r1,r1; \ +    bf .Lpseudo_end; \ +    SYSCALL_ERROR_HANDLER; \ + .Lpseudo_end: + +#undef	PSEUDO_END +#define	PSEUDO_END(name) \ +  END (name) + +#undef	PSEUDO_NOERRNO +#define	PSEUDO_NOERRNO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ +    DO_CALL (syscall_name, args) + +#undef	PSEUDO_END_NOERRNO +#define	PSEUDO_END_NOERRNO(name) \ +  END (name) + +#define ret_NOERRNO ret + +#define	PSEUDO_ERRVAL(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ +    DO_CALL (syscall_name, args); + +#undef	PSEUDO_END_ERRVAL +#define	PSEUDO_END_ERRVAL(name) \ +  END (name) + +#define ret_ERRVAL ret + +#ifndef PIC +# define SYSCALL_ERROR_HANDLER	\ +	mov.l 0f,r1; \ +	jmp @r1; \ +	 mov r0,r4; \ +	.align 2; \ +     0: .long __syscall_error + +#include <libc/sysdeps/linux/sh/syscall_error.S> +#else +# ifdef RTLD_PRIVATE_ERRNO + +#  define SYSCALL_ERROR_HANDLER	\ +	neg r0,r1; \ +	mov.l 0f,r12; \ +	mova 0f,r0; \ +	add r0,r12; \ +	mov.l 1f,r0; \ +	mov.l r1,@(r0,r12) +	bra .Lpseudo_end; \ +	 mov _IMM1,r0; \ +	.align 2; \ +     0: .long _GLOBAL_OFFSET_TABLE_; \ +     1: .long rtld_errno@GOTOFF + +# elif defined _LIBC_REENTRANT + +#  if USE___THREAD + +#   ifndef NOT_IN_libc +#    define SYSCALL_ERROR_ERRNO __libc_errno +#   else +#    define SYSCALL_ERROR_ERRNO errno +#   endif +#   define SYSCALL_ERROR_HANDLER \ +	neg r0,r1; \ +	mov r12,r2; \ +	mov.l 0f,r12; \ +	mova 0f,r0; \ +	add r0,r12; \ +	mov.l 1f,r0; \ +	stc gbr, r4; \ +	mov.l @(r0,r12),r0; \ +	bra .Lskip; \ +	add r4,r0; \ +	.align 2; \ +	1: .long SYSCALL_ERROR_ERRNO@GOTTPOFF; \ +	.Lskip: \ +	mov r2,r12; \ +	mov.l r1,@r0; \ +	bra .Lpseudo_end; \ +	mov _IMM1,r0; \ +	.align 2; \ +	0: .long _GLOBAL_OFFSET_TABLE_ +#  else + +#   define SYSCALL_ERROR_HANDLER \ +	neg r0,r1; \ +	mov.l r14,@-r15; \ +	mov.l r12,@-r15; \ +	mov.l r1,@-r15; \ +	mov.l 0f,r12; \ +	mova 0f,r0; \ +	add r0,r12; \ +	sts.l pr,@-r15; \ +	mov r15,r14; \ +	mov.l 1f,r1; \ +	bsrf r1; \ +         nop; \ +     2: mov r14,r15; \ +	lds.l @r15+,pr; \ +	mov.l @r15+,r1; \ +	mov.l r1,@r0; \ +	mov.l @r15+,r12; \ +	mov.l @r15+,r14; \ +	bra .Lpseudo_end; \ +	 mov _IMM1,r0; \ +	.align 2; \ +     0: .long _GLOBAL_OFFSET_TABLE_; \ +     1: .long PLTJMP(C_SYMBOL_NAME(__errno_location))-(2b-.) +/* A quick note: it is assumed that the call to `__errno_location' does +   not modify the stack!  */ +#  endif +# else + +/* Store (-r0) into errno through the GOT.  */ +#  define SYSCALL_ERROR_HANDLER						      \ +	neg r0,r1; \ +	mov r12,r2; \ +	mov.l 0f,r12; \ +	mova 0f,r0; \ +	add r0,r12; \ +	mov.l 1f,r0; \ +	mov.l @(r0,r12),r0; \ +	mov r2,r12; \ +	mov.l r1,@r0; \ +	bra .Lpseudo_end; \ +	 mov _IMM1,r0; \ +	.align 2; \ +     0: .long _GLOBAL_OFFSET_TABLE_; \ +     1: .long errno@GOT +# endif	/* _LIBC_REENTRANT */ +#endif	/* PIC */ + +# ifdef NEED_SYSCALL_INST_PAD +#  define SYSCALL_INST_PAD \ +	or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0 +# else +#  define SYSCALL_INST_PAD +# endif + +#define SYSCALL_INST0	trapa #0x10 +#define SYSCALL_INST1	trapa #0x11 +#define SYSCALL_INST2	trapa #0x12 +#define SYSCALL_INST3	trapa #0x13 +#define SYSCALL_INST4	trapa #0x14 +#define SYSCALL_INST5	mov.l @(0,r15),r0; trapa #0x15 +#define SYSCALL_INST6	mov.l @(0,r15),r0; mov.l @(4,r15),r1; trapa #0x16 + +#undef	DO_CALL +#define DO_CALL(syscall_name, args)	\ +    mov.l 1f,r3;			\ +    SYSCALL_INST##args;			\ +    SYSCALL_INST_PAD;			\ +    bra 2f;				\ +     nop;				\ +    .align 2;				\ + 1: .long SYS_ify (syscall_name);	\ + 2: + +#endif	/* __ASSEMBLER__ */ + +#endif /* linux/sh/sysdep.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S new file mode 100644 index 000000000..a45c09fd6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S @@ -0,0 +1,71 @@ +/* Copyright (C) 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.  */ + +#include <sysdep.h> +#define _ERRNO_H	1 +#include <bits/errno.h> +#include <tcb-offsets.h> + +/* 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 process, +   and the process ID of the new process to the old process.  */ + +ENTRY (__vfork) +	/* Save the PID value.  */ +	stc	gbr, r2 +	mov.w	.L2, r0 +	mov.l	@(r0,r2), r4 +	neg	r4, r1 +	tst	r1, r1 +	bf	1f +	mov	#1, r1 +	rotr	r1 +1: +	mov.l	r1, @(r0,r2) + +	mov.w	.L1, r3 +	trapa	#0x10 +	mov     r0, r1 + +	/* Restore the old PID value in the parent.  */ +	tst	r0, r0 +	bt.s	2f +	 stc	gbr, r2 +	mov.w	.L2, r0 +	mov.l	r4, @(r0,r2) +	mov	r1, r0 +2: +	mov	#-12, r2 +	shad	r2, r1 +	not	r1, r1			// r1=0 means r0 = -1 to -4095 +	tst	r1, r1			// i.e. error in linux +	bf	.Lpseudo_end +	SYSCALL_ERROR_HANDLER +.Lpseudo_end: +	rts +	 nop +.L1: +	.word	__NR_vfork +.L2: +	.word	PID - TLS_PRE_TCB_SIZE +	.align	2 +PSEUDO_END (__vfork) +hidden_def (vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c new file mode 100644 index 000000000..5159bf9b8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c @@ -0,0 +1,88 @@ +/* Copyright (C) 1997,1998,2000,2002,2003,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.  */ + +#include <pthreadP.h> +#include <errno.h> +#include <signal.h> +#include <string.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> + +#ifdef __NR_rt_sigtimedwait + +static int +do_sigtimedwait (const sigset_t *set, siginfo_t *info, +		 const struct timespec *timeout) +{ +#ifdef SIGCANCEL +  sigset_t tmpset; +  if (set != NULL +      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0) +# ifdef SIGSETXID +	  || __builtin_expect (__sigismember (set, SIGSETXID), 0) +# endif +	  )) +    { +      /* Create a temporary mask without the bit for SIGCANCEL set.  */ +      // We are not copying more than we have to. +      memcpy (&tmpset, set, _NSIG / 8); +      __sigdelset (&tmpset, SIGCANCEL); +# ifdef SIGSETXID +      __sigdelset (&tmpset, SIGSETXID); +# endif +      set = &tmpset; +    } +#endif + +    /* XXX The size argument hopefully will have to be changed to the +       real size of the user-level sigset_t.  */ +  int result = INLINE_SYSCALL (rt_sigtimedwait, 4, set, +			       info, timeout, _NSIG / 8); + +  /* The kernel generates a SI_TKILL code in si_code in case tkill is +     used.  tkill is transparently used in raise().  Since having +     SI_TKILL as a code is useful in general we fold the results +     here.  */ +  if (result != -1 && info != NULL && info->si_code == SI_TKILL) +    info->si_code = SI_USER; + +  return result; +} + + +/* Return any pending signal or wait for one for the given time.  */ +int attribute_hidden +__sigtimedwait (const sigset_t *set, siginfo_t *info, +		const struct timespec *timeout) +{ +  if (SINGLE_THREAD_P) +    return do_sigtimedwait (set, info, timeout); + +  int oldtype = LIBC_CANCEL_ASYNC (); + +  /* XXX The size argument hopefully will have to be changed to the +     real size of the user-level sigset_t.  */ +  int result = do_sigtimedwait (set, info, timeout); + +  LIBC_CANCEL_RESET (oldtype); + +  return result; +} +weak_alias (__sigtimedwait, sigtimedwait) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c new file mode 100644 index 000000000..bde0a9292 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include "../../../../../../libc/signal/sigwait.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c new file mode 100644 index 000000000..6c47fdee6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c @@ -0,0 +1,88 @@ +/* Copyright (C) 1997,1998,2000,2002,2003,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.  */ + +#include <pthreadP.h> +#include <errno.h> +#include <signal.h> +#define __need_NULL +#include <stddef.h> +#include <string.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> + +#ifdef __NR_rt_sigtimedwait + +static int +do_sigwaitinfo (const sigset_t *set, siginfo_t *info) +{ +#ifdef SIGCANCEL +  sigset_t tmpset; +  if (set != NULL +      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0) +# ifdef SIGSETXID +	  || __builtin_expect (__sigismember (set, SIGSETXID), 0) +# endif +	  )) +    { +      /* Create a temporary mask without the bit for SIGCANCEL set.  */ +      // We are not copying more than we have to. +      memcpy (&tmpset, set, _NSIG / 8); +      __sigdelset (&tmpset, SIGCANCEL); +# ifdef SIGSETXID +      __sigdelset (&tmpset, SIGSETXID); +# endif +      set = &tmpset; +    } +#endif + +  /* XXX The size argument hopefully will have to be changed to the +     real size of the user-level sigset_t.  */ +  int result = INLINE_SYSCALL (rt_sigtimedwait, 4, set, +			       info, NULL, _NSIG / 8); + +  /* The kernel generates a SI_TKILL code in si_code in case tkill is +     used.  tkill is transparently used in raise().  Since having +     SI_TKILL as a code is useful in general we fold the results +     here.  */ +  if (result != -1 && info != NULL && info->si_code == SI_TKILL) +    info->si_code = SI_USER; + +  return result; +} + + +/* Return any pending signal or wait for one for the given time.  */ +int +__sigwaitinfo (const sigset_t *set, siginfo_t *info) +{ +  if (SINGLE_THREAD_P) +    return do_sigwaitinfo (set, info); + +  int oldtype = LIBC_CANCEL_ASYNC (); + +  /* XXX The size argument hopefully will have to be changed to the +     real size of the user-level sigset_t.  */ +  int result = do_sigwaitinfo (set, info); + +  LIBC_CANCEL_RESET (oldtype); + +  return result; +} +weak_alias (__sigwaitinfo, sigwaitinfo) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c new file mode 100644 index 000000000..9e948adce --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include <../../../../../../libc/unistd/sleep.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/smp.h b/libpthread/nptl/sysdeps/unix/sysv/linux/smp.h new file mode 100644 index 000000000..41fa97ff4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/smp.h @@ -0,0 +1,52 @@ +/* Determine whether the host has multiple processors.  Linux version. +   Copyright (C) 1996, 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 Library General Public License as +   published by the Free Software Foundation; either version 2 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 +   Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public +   License along with the GNU C Library; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <sys/sysctl.h> +#include <not-cancel.h> + +/* Test whether the machine has more than one processor.  This is not the +   best test but good enough.  More complicated tests would require `malloc' +   which is not available at that time.  */ +static inline int +is_smp_system (void) +{ +  static const int sysctl_args[] = { CTL_KERN, KERN_VERSION }; +  char buf[512]; +  size_t reslen = sizeof (buf); + +  /* Try reading the number using `sysctl' first.  */ +  if (sysctl ((int *) sysctl_args, +		sizeof (sysctl_args) / sizeof (sysctl_args[0]), +		buf, &reslen, NULL, 0) < 0) +    { +      /* This was not successful.  Now try reading the /proc filesystem.  */ +      int fd = open_not_cancel_2 ("/proc/sys/kernel/version", O_RDONLY); +      if (__builtin_expect (fd, 0) == -1 +	  || (reslen = read_not_cancel (fd, buf, sizeof (buf))) <= 0) +	/* This also didn't work.  We give up and say it's a UP machine.  */ +	buf[0] = '\0'; + +      close_not_cancel_no_status (fd); +    } + +  return strstr (buf, "SMP") != NULL; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile @@ -0,0 +1,13 @@ +# 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. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile.arch new file mode 100644 index 000000000..b54731075 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile.arch @@ -0,0 +1,66 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_SSRC = pt-vfork.S clone.S +libpthread_CSRC = pthread_once.c lowlevellock.c + +libc_a_CSRC = fork.c libc-lowlevellock.c +libc_a_SSRC = clone.S vfork.S + +CFLAGS-OMIT-fork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-libc-lowlevellock.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD + +CFLAGS-pthread_once.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-lowlevellock.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +#Needed to use the correct SYSCALL_ERROR_HANDLER +ASFLAGS-clone.S += -DUSE___THREAD +ASFLAGS-vfork.S += -DUSE___THREAD +ASFLAGS-pt-vfork.S += -DUSE___THREAD +endif + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/sparc +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/sparc + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) +LINUX_ARCH_OBJ+=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJS) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) +LIBC_LINUX_ARCH_OBJ+=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libc_a_SSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=nptl_linux_arch_clean + +nptl_linux_arch_clean: +	$(do_rm) $(addprefix $(LINUX_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Versions b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Versions new file mode 100644 index 000000000..d10277248 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Versions @@ -0,0 +1,6 @@ +libpthread { +  GLIBC_2.3.3 { +    # Changed PTHREAD_STACK_MIN. +    pthread_attr_setstack; pthread_attr_setstacksize; +  } +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h new file mode 100644 index 000000000..e082ea8f0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h @@ -0,0 +1,89 @@ +/* Minimum guaranteed maximum values for system limits.  Linux/SPARC version. +   Copyright (C) 1993-1998,2000,2002,2003,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 Library General Public License as +   published by the Free Software Foundation; either version 2 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 +   Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public +   License along with the GNU C Library; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol +   and defines LINK_MAX although filesystems have different maxima.  A +   similar thing is true for OPEN_MAX: the limit can be changed at +   runtime and therefore the macro must not be defined.  Remove this +   after including the header if necessary.  */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information.  */ +#include <linux/limits.h> + +/* Have to remove NR_OPEN?  */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX?  */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX?  */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process.  */ +#define _POSIX_THREAD_KEYS_MAX	128 +/* This is the value this implementation supports.  */ +#define PTHREAD_KEYS_MAX	1024 + +/* Controlling the iterations of destructors for thread-specific data.  */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS	4 +/* Number of iterations this implementation does.  */ +#define PTHREAD_DESTRUCTOR_ITERATIONS	_POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process.  */ +#define _POSIX_THREAD_THREADS_MAX	64 +/* We have no predefined limit on the number of threads.  */ +#undef PTHREAD_THREADS_MAX + +/* Maximum amount by which a process can descrease its asynchronous I/O +   priority level.  */ +#define AIO_PRIO_DELTA_MAX	20 + +/* Minimum size for a thread.  We are free to choose a reasonable value.  */ +#define PTHREAD_STACK_MIN	24576 + +/* Maximum number of timer expiration overruns.  */ +#define DELAYTIMER_MAX	2147483647 + +/* Maximum tty name length.  */ +#define TTY_NAME_MAX		32 + +/* Maximum login name length.  This is arbitrary.  */ +#define LOGIN_NAME_MAX		256 + +/* Maximum host name length.  */ +#define HOST_NAME_MAX		64 + +/* Maximum message queue priority level.  */ +#define MQ_PRIO_MAX		32768 diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h new file mode 100644 index 000000000..459d1ca79 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h @@ -0,0 +1,218 @@ +/* Machine-specific pthread type layouts.  SPARC version. +   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.  */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H	1 + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers.  The structure of the attribute type is +   deliberately not exposed.  */ +typedef unsigned long int pthread_t; + + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_ATTR_T]; +  long int __align; +} pthread_attr_t; + + +#if __WORDSIZE == 64 +typedef struct __pthread_internal_list +{ +  struct __pthread_internal_list *__prev; +  struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ +  struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + + +/* Data structures for mutex handling.  The structure of the attribute +   type is deliberately not exposed.  */ +typedef union +{ +  struct __pthread_mutex_s +  { +    int __lock; +    unsigned int __count; +    int __owner; +#if __WORDSIZE == 64 +    unsigned int __nusers; +#endif +    /* KIND must stay at this position in the structure to maintain +       binary compatibility.  */ +    int __kind; +#if __WORDSIZE == 64 +    int __spins; +    __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV      1 +#else +    unsigned int __nusers; +    __extension__ union +    { +      int __spins; +      __pthread_slist_t __list; +    }; +#endif +  } __data; +  char __size[__SIZEOF_PTHREAD_MUTEX_T]; +  long int __align; +} pthread_mutex_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; +  int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling.  The structure of +   the attribute type is deliberately not exposed.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __futex; +    __extension__ unsigned long long int __total_seq; +    __extension__ unsigned long long int __wakeup_seq; +    __extension__ unsigned long long int __woken_seq; +    void *__mutex; +    unsigned int __nwaiters; +    unsigned int __broadcast_seq; +  } __data; +  char __size[__SIZEOF_PTHREAD_COND_T]; +  __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_CONDATTR_T]; +  int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling.  The +   structure of the attribute type is deliberately not exposed.  */ +typedef union +{ +# if __WORDSIZE == 64 +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    int __writer; +    int __pad1; +    unsigned long int __pad2; +    unsigned long int __pad3; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +  } __data; +# else +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +    int __writer; +  } __data; +# endif +  char __size[__SIZEOF_PTHREAD_RWLOCK_T]; +  long int __align; +} pthread_rwlock_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; +  long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type.  */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type.  The structure of the type is +   deliberately not exposed.  */ +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIER_T]; +  long int __align; +} pthread_barrier_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; +  int __align; +} pthread_barrierattr_t; +#endif + + +#endif	/* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h new file mode 100644 index 000000000..7f3a32832 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h @@ -0,0 +1,44 @@ +/* Machine-specific POSIX semaphore type layouts.  SPARC version. +   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.  */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_SEM_T	32 +#else +# define __SIZEOF_SEM_T	16 +#endif + +/* Value returned if `sem_open' failed.  */ +#define SEM_FAILED      ((sem_t *) 0) + +/* Maximum value the semaphore can have.  */ +#define SEM_VALUE_MAX   (2147483647) + + +typedef union +{ +  char __size[__SIZEOF_SEM_T]; +  long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/clone.S new file mode 100644 index 000000000..dfc5e8261 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/clone.S @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "./sparc64/clone.S" +#else +#include "./sparc32/clone.S" +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/fork.c new file mode 100644 index 000000000..1cd79110a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/fork.c @@ -0,0 +1,29 @@ +/* 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 <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + +#define ARCH_FORK() \ +  INLINE_CLONE_SYSCALL (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, \ +			0, NULL, NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/libc-lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/libc-lowlevellock.c new file mode 100644 index 000000000..b19282281 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/libc-lowlevellock.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.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.  */ + +/* No difference to lowlevellock.c, except we lose a couple of functions.  */ +#include "lowlevellock.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.c new file mode 100644 index 000000000..e9ec4df1e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.c @@ -0,0 +1,131 @@ +/* low level locking for pthread library.  SPARC version. +   Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.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 <sysdep.h> +#include <lowlevellock.h> +#include <sys/time.h> + + +/* These functions don't get included in libc.so  */ +void +__lll_lock_wait (int *futex) +{ +  do +    { +      int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1); +      if (oldval != 0) +	lll_futex_wait (futex, 2); +    } +  while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0); +} + + +#ifdef IS_IN_libpthread +int +__lll_timedlock_wait (int *futex, const struct timespec *abstime) +{ +  /* Reject invalid timeouts.  */ +  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) +    return EINVAL; + +  do +    { +      struct timeval tv; +      struct timespec rt; + +      /* Get the current time.  */ +      (void) gettimeofday (&tv, NULL); + +      /* Compute relative timeout.  */ +      rt.tv_sec = abstime->tv_sec - tv.tv_sec; +      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; +      if (rt.tv_nsec < 0) +	{ +	  rt.tv_nsec += 1000000000; +	  --rt.tv_sec; +	} + +      /* Already timed out?  */ +      if (rt.tv_sec < 0) +	return ETIMEDOUT; + +      /* Wait.  */ +      int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1); +      if (oldval != 0) +	lll_futex_timed_wait (futex, 2, &rt); +    } +  while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0); + +  return 0; +} + +int +lll_unlock_wake_cb(int* futex) +{ +    int val = atomic_exchange_24_rel(futex, 0); + +    if( __builtin_expect( val > 1, 0 ) ) { +        lll_futex_wake( futex, 1 ); +    } + +    return 0; +} + + +int +__lll_timedwait_tid (int *tidp, const struct timespec *abstime) +{ +  int tid; + +  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) +    return EINVAL; + +  /* Repeat until thread terminated.  */ +  while ((tid = *tidp) != 0) +    { +      struct timeval tv; +      struct timespec rt; + +      /* Get the current time.  */ +      (void) gettimeofday (&tv, NULL); + +      /* Compute relative timeout.  */ +      rt.tv_sec = abstime->tv_sec - tv.tv_sec; +      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; +      if (rt.tv_nsec < 0) +	{ +	  rt.tv_nsec += 1000000000; +	  --rt.tv_sec; +	} + +      /* Already timed out?  */ +      if (rt.tv_sec < 0) +	return ETIMEDOUT; + +      /* Wait until thread terminates.  The kernel so far does not use +	 the private futex operations for this.  */ +      if (lll_futex_timed_wait (tidp, tid, &rt) == -ETIMEDOUT) +	return ETIMEDOUT; +    } + +  return 0; +} +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h new file mode 100644 index 000000000..4db6fb0b4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h @@ -0,0 +1,258 @@ +/* Copyright (C) 2003, 2004, 2006, 2007, 2008 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 Libr	\ary; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H	1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> +#include <sysdep.h> + + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 +#define FUTEX_CMP_REQUEUE	4 +#define FUTEX_WAKE_OP		5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE	((4 << 24) | 1) + +/* Initializer for compatibility lock.	*/ +#define LLL_MUTEX_LOCK_INITIALIZER (0) + +#define lll_futex_wait(futexp, val) \ +  lll_futex_timed_wait (futexp, val, NULL) + +#define lll_futex_timed_wait(futexp, val, timespec) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),		  \ +			      FUTEX_WAIT, (val), (timespec));			      \ +    __ret;								      \ +  }) + +#define lll_futex_wake(futexp, nr) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),		      \ +			      FUTEX_WAKE, (nr), 0);					      \ +    __ret;								      \ +  }) + +/* Returns non-zero if error happened, zero if success.  */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),		      \ +			      FUTEX_CMP_REQUEUE, (nr_wake), (nr_move), (mutex), (val));	      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \ +  }) + +#define lll_robust_dead(futexv) \ +  do									      \ +    {									      \ +      int *__futexp = &(futexv);					      \ +      atomic_or (__futexp, FUTEX_OWNER_DIED);				      \ +      lll_futex_wake (__futexp, 1);				      \ +    }									      \ +  while (0) + +/* Returns non-zero if error happened, zero if success.  */ +#ifdef __sparc32_atomic_do_lock +/* Avoid FUTEX_WAKE_OP if supporting pre-v9 CPUs.  */ +# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) 1 +#else +# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +									      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),		      \ +			      FUTEX_WAKE_OP,    \ +			      (nr_wake), (nr_wake2), (futexp2),		      \ +			      FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \ +  }) +#endif + +static inline int +__attribute__ ((always_inline)) +__lll_trylock (int *futex) +{ +  return atomic_compare_and_exchange_val_24_acq (futex, 1, 0) != 0; +} +#define lll_mutex_trylock(futex) __lll_trylock (&(futex)) + +static inline int +__attribute__ ((always_inline)) +__lll_cond_trylock (int *futex) +{ +  return atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0; +} +#define lll_mutex_cond_trylock(futex) __lll_cond_trylock (&(futex)) + +static inline int +__attribute__ ((always_inline)) +__lll_robust_trylock (int *futex, int id) +{ +  return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0; +} +#define lll_robust_trylock(futex, id) \ +  __lll_robust_trylock (&(futex), id) + + +extern void __lll_lock_wait (int *futex) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex) attribute_hidden; + +static inline void +__attribute__ ((always_inline)) +__lll_lock (int *futex) +{ +  int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0); + +  if (__builtin_expect (val != 0, 0)) +    { +	__lll_lock_wait (futex); +    } +} +#define lll_mutex_lock(futex) __lll_lock (&(futex)) + +static inline int +__attribute__ ((always_inline)) +__lll_robust_lock (int *futex, int id) +{ +  int result = 0; +  if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) +    result = __lll_robust_lock_wait (futex); +  return result; +} +#define lll_robust_lock(futex, id) \ +  __lll_robust_lock (&(futex), id) + +static inline void +__attribute__ ((always_inline)) +__lll_cond_lock (int *futex) +{ +  int val = atomic_compare_and_exchange_val_24_acq (futex, 2, 0); + +  if (__builtin_expect (val != 0, 0)) +    __lll_lock_wait (futex); +} +#define lll_mutex_cond_lock(futex) __lll_cond_lock (&(futex)) + +#define lll_robust_cond_lock(futex, id) \ +  __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *) attribute_hidden; + +static inline int +__attribute__ ((always_inline)) +__lll_timedlock (int *futex, const struct timespec *abstime) +{ +  int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0); +  int result = 0; + +  if (__builtin_expect (val != 0, 0)) +    result = __lll_timedlock_wait (futex, abstime); +  return result; +} +#define lll_mutex_timedlock(futex, abstime) \ +  __lll_timedlock (&(futex), abstime) + +static inline int +__attribute__ ((always_inline)) +__lll_robust_timedlock (int *futex, const struct timespec *abstime, +			int id) +{ +  int result = 0; +  if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) +    result = __lll_robust_timedlock_wait (futex, abstime); +  return result; +} +#define lll_robust_timedlock(futex, abstime, id) \ +  __lll_robust_timedlock (&(futex), abstime, id) + +#define lll_mutex_unlock(lock) \ +  ((void) ({								      \ +    int *__futex = &(lock);						      \ +    int __val = atomic_exchange_24_rel (__futex, 0);			      \ +    if (__builtin_expect (__val > 1, 0))				      \ +      lll_futex_wake (__futex, 1);				      \ +  })) + +#define lll_robust_unlock(lock) \ +  ((void) ({								      \ +    int *__futex = &(lock);						      \ +    int __val = atomic_exchange_rel (__futex, 0);			      \ +    if (__builtin_expect (__val & FUTEX_WAITERS, 0))			      \ +      lll_futex_wake (__futex, 1);				      \ +  })) + +#define lll_mutex_islocked(futex) \ +  (futex != 0) + +/* We have a separate internal lock implementation which is not tied +   to binary compatibility.  */ + +/* Type for lock object.  */ +typedef int lll_lock_t; + +/* Initializers for lock.  */ +#define LLL_LOCK_INITIALIZER		(0) +#define LLL_LOCK_INITIALIZER_LOCKED	(1) + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + +#define lll_trylock(lock)	lll_mutex_trylock (lock) +#define lll_lock(lock)		lll_mutex_lock (lock) +#define lll_unlock(lock)	lll_mutex_unlock (lock) +#define lll_islocked(lock)	lll_mutex_islocked (lock) + + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex +   wakeup when the clone terminates.  The memory location contains the +   thread ID while the clone is running and is reset to zero +   afterwards.	*/ +#define lll_wait_tid(tid) \ +  do							\ +    {							\ +      __typeof (tid) __tid;				\ +      while ((__tid = (tid)) != 0)			\ +	lll_futex_wait (&(tid), __tid);	\ +    }							\ +  while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) +     attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ +  ({							\ +    int __res = 0;					\ +    if ((tid) != 0)					\ +      __res = __lll_timedwait_tid (&(tid), (abstime));	\ +    __res;						\ +  }) + +#endif	/* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pt-vfork.S new file mode 100644 index 000000000..e8705c54b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pt-vfork.S @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/pt-vfork.S" +#else +#include "sparc32/pt-vfork.S" +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c new file mode 100644 index 000000000..3b07cc127 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c @@ -0,0 +1,94 @@ +/* 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 "pthreadP.h" +#include <lowlevellock.h> + + +unsigned long int __fork_generation attribute_hidden; + + +static void +clear_once_control (void *arg) +{ +  pthread_once_t *once_control = (pthread_once_t *) arg; + +  *once_control = 0; +  lll_futex_wake (once_control, INT_MAX); +} + + +int +__pthread_once (once_control, init_routine) +     pthread_once_t *once_control; +     void (*init_routine) (void); +{ +  while (1) +    { +      int oldval, val, newval; + +      val = *once_control; +      do +	{ +	  /* Check if the initialized has already been done.  */ +	  if ((val & 2) != 0) +	    return 0; + +	  oldval = val; +	  newval = (oldval & 3) | __fork_generation | 1; +	  val = atomic_compare_and_exchange_val_acq (once_control, newval, +						     oldval); +	} +      while (__builtin_expect (val != oldval, 0)); + +      /* Check if another thread already runs the initializer.	*/ +      if ((oldval & 1) != 0) +	{ +	  /* Check whether the initializer execution was interrupted +	     by a fork.	 */ +	  if (((oldval ^ newval) & -4) == 0) +	    { +	      /* Same generation, some other thread was faster. Wait.  */ +	      lll_futex_wait (once_control, newval); +	      continue; +	    } +	} + +      /* This thread is the first here.  Do the initialization. +	 Register a cleanup handler so that in case the thread gets +	 interrupted the initialization can be restarted.  */ +      pthread_cleanup_push (clear_once_control, once_control); + +      init_routine (); + +      pthread_cleanup_pop (0); + + +      /* Add one to *once_control.  */ +      atomic_increment (once_control); + +      /* Wake up all other threads.  */ +      lll_futex_wake (once_control, INT_MAX); +      break; +    } + +  return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S new file mode 100644 index 000000000..a6142aafe --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <libc/sysdeps/linux/sparc/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S new file mode 100644 index 000000000..fb01242b5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S @@ -0,0 +1,45 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + +   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 <sysdep.h> +#include <tcb-offsets.h> + +	.text +	.globl		__syscall_error +ENTRY(__vfork) +	ld	[%g7 + PID], %o5 +	sub	%g0, %o5, %o4 +	st	%o4, [%g7 + PID] + +	LOADSYSCALL(vfork) +	ta	0x10 +	bcc	2f +	 mov	%o7, %g1 +	st	%o5, [%g7 + PID] +	call	__syscall_error +	 mov	%g1, %o7 +2:	sub	%o1, 1, %o1 +	andcc	%o0, %o1, %o0 +	bne,a	1f +	 st	%o5, [%g7 + PID] +1:	retl +	 nop +END(__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h new file mode 100644 index 000000000..ad650d040 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h @@ -0,0 +1,105 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@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 <tls.h> +#include <sysdep.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args)   \ +        .text;                  \ +    .globl      __syscall_error;    \ +ENTRY(name)                 \ +    ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;\ +    cmp %g1, 0;             \ +    bne 1f;                 \ +.type   __##syscall_name##_nocancel,@function;  \ +.globl  __##syscall_name##_nocancel;        \ +__##syscall_name##_nocancel:            \ +     mov SYS_ify(syscall_name), %g1;    \ +    ta 0x10;                \ +    bcc 8f;                 \ +     mov %o7, %g1;              \ +    call __syscall_error;           \ +     mov %g1, %o7;              \ +8:  jmpl %o7 + 8, %g0;          \ +     nop;                   \ +.size   __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;\ +1:  save %sp, -96, %sp;         \ +    cfi_def_cfa_register(%fp);      \ +    cfi_window_save;            \ +    cfi_register(%o7, %i7);         \ +    CENABLE;                \ +     nop;                   \ +    mov %o0, %l0;               \ +    COPY_ARGS_##args            \ +    mov SYS_ify(syscall_name), %g1;     \ +    ta 0x10;                \ +    bcc 1f;                 \ +     mov %o0, %l1;              \ +    CDISABLE;               \ +     mov %l0, %o0;              \ +    call __syscall_error;           \ +     mov %l1, %o0;              \ +    b 2f;                   \ +     mov -1, %l1;               \ +1:  CDISABLE;               \ +     mov %l0, %o0;              \ +2:  jmpl %i7 + 8, %g0;          \ +     restore %g0, %l1, %o0; + +# ifdef IS_IN_libpthread +#  define CENABLE	call __pthread_enable_asynccancel +#  define CDISABLE	call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +#  define CENABLE	call __libc_enable_asynccancel +#  define CDISABLE	call __libc_disable_asynccancel +# elif defined IS_IN_librt +#  define CENABLE	call __librt_enable_asynccancel +#  define CDISABLE	call __librt_disable_asynccancel +# else +#  error Unsupported library +# endif + +#define COPY_ARGS_0	/* Nothing */ +#define COPY_ARGS_1	COPY_ARGS_0 mov %i0, %o0; +#define COPY_ARGS_2	COPY_ARGS_1 mov %i1, %o1; +#define COPY_ARGS_3	COPY_ARGS_2 mov %i2, %o2; +#define COPY_ARGS_4	COPY_ARGS_3 mov %i3, %o3; +#define COPY_ARGS_5	COPY_ARGS_4 mov %i4, %o4; +#define COPY_ARGS_6	COPY_ARGS_5 mov %i5, %o5; + +# ifndef __ASSEMBLER__ +#  define SINGLE_THREAD_P \ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \ +				   header.multiple_threads) == 0, 1) +# else +#  define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S new file mode 100644 index 000000000..1a3827789 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + +   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 <sysdep.h> +#include <tcb-offsets.h> + +	.text +	.globl		__syscall_error +ENTRY(__vfork) +	ld	[%g7 + PID], %o5 +	cmp	%o5, 0 +	bne	1f +	 sub	%g0, %o5, %o4 +	sethi	%hi(0x80000000), %o4 +1:	st	%o4, [%g7 + PID] + +	LOADSYSCALL(vfork) +	ta	0x10 +	bcc	2f +	 mov	%o7, %g1 +	st	%o5, [%g7 + PID] +	call	__syscall_error +	 mov	%g1, %o7 +2:	sub	%o1, 1, %o1 +	andcc	%o0, %o1, %o0 +	bne,a	1f +	 st	%o5, [%g7 + PID] +1:	retl +	 nop +END(__vfork) + +hidden_def (vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/Versions b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/Versions new file mode 100644 index 000000000..3b111ddb5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/Versions @@ -0,0 +1,7 @@ +librt { +  GLIBC_2.3.3 { +    # Changed timer_t. +    timer_create; timer_delete; timer_getoverrun; timer_gettime; +    timer_settime; +  } +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S new file mode 100644 index 000000000..64e3bfc12 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <libc/sysdeps/linux/sparc/sparcv9/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S new file mode 100644 index 000000000..8941043c3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S @@ -0,0 +1,45 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + +   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 <sysdep.h> +#include <tcb-offsets.h> + +	.text +	.globl	__syscall_error +ENTRY(__vfork) +	ld	[%g7 + PID], %o5 +	sub	%g0, %o5, %o4 +	st	%o4, [%g7 + PID] + +	LOADSYSCALL(vfork) +	ta	0x6d +	bcc,pt	%xcc, 2f +	 mov	%o7, %g1 +	st	%o5, [%g7 + PID] +	call	__syscall_error +	 mov	%g1, %o7 +2:	sub	%o1, 1, %o1 +	andcc	%o0, %o1, %o0 +	bne,a,pt %icc, 1f +	 st	%o5, [%g7 + PID] +1:	retl +	 nop +END(__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h new file mode 100644 index 000000000..aec2d4a86 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h @@ -0,0 +1,110 @@ +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@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 <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args)	\ +	.text;					\ +	.globl		__syscall_error;	\ +ENTRY(name)					\ +	ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;\ +	brnz,pn %g1, 1f;			\ +.type	__##syscall_name##_nocancel,@function;	\ +.globl	__##syscall_name##_nocancel;		\ +__##syscall_name##_nocancel:			\ +	 mov SYS_ify(syscall_name), %g1;	\ +	ta 0x6d;				\ +	bcc,pt %xcc, 8f;			\ +	 mov %o7, %g1;				\ +	call __syscall_error;			\ +	 mov %g1, %o7;				\ +8:	jmpl %o7 + 8, %g0;			\ +	 nop;					\ +.size	__##syscall_name##_nocancel,.-__##syscall_name##_nocancel;\ +1:	save %sp, -192, %sp;			\ +	cfi_def_cfa_register(%fp);		\ +	cfi_window_save;			\ +	cfi_register(%o7, %i7);			\ +	CENABLE;				\ +	 nop;					\ +	mov %o0, %l0;				\ +	COPY_ARGS_##args			\ +	mov SYS_ify(syscall_name), %g1;		\ +	ta 0x6d;				\ +	bcc,pt %xcc, 1f;			\ +	 mov %o0, %l1;				\ +	CDISABLE;				\ +	 mov %l0, %o0;				\ +	call __syscall_error;			\ +	 mov %l1, %o0;				\ +	ba,pt %xcc, 2f;				\ +	 mov -1, %l1;				\ +1:	CDISABLE;				\ +	 mov %l0, %o0;				\ +2:	jmpl %i7 + 8, %g0;			\ +	 restore %g0, %l1, %o0; + +# ifdef IS_IN_libpthread +#  define CENABLE	call __pthread_enable_asynccancel +#  define CDISABLE	call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +#  define CENABLE	call __libc_enable_asynccancel +#  define CDISABLE	call __libc_disable_asynccancel +# elif defined IS_IN_librt +#  define CENABLE	call __librt_enable_asynccancel +#  define CDISABLE	call __librt_disable_asynccancel +# else +#  error Unsupported library +# endif + +#define COPY_ARGS_0	/* Nothing */ +#define COPY_ARGS_1	COPY_ARGS_0 mov %i0, %o0; +#define COPY_ARGS_2	COPY_ARGS_1 mov %i1, %o1; +#define COPY_ARGS_3	COPY_ARGS_2 mov %i2, %o2; +#define COPY_ARGS_4	COPY_ARGS_3 mov %i3, %o3; +#define COPY_ARGS_5	COPY_ARGS_4 mov %i4, %o4; +#define COPY_ARGS_6	COPY_ARGS_5 mov %i5, %o5; + +# ifndef __ASSEMBLER__ +#  define SINGLE_THREAD_P \ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \ +				   header.multiple_threads) == 0, 1) +# else +#  define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ +				   header.multiple_threads) == 0, 1) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c new file mode 100644 index 000000000..0a9c3372b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_create.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c new file mode 100644 index 000000000..f0d4fd21d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_delete.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c new file mode 100644 index 000000000..82121a7a2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_getoverr.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c new file mode 100644 index 000000000..313c05fea --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_gettime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c new file mode 100644 index 000000000..76f549cb4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_settime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S new file mode 100644 index 000000000..b4e89aceb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + +   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 <sysdep.h> +#include <tcb-offsets.h> + +	.text +	.globl	__syscall_error +ENTRY(__vfork) +	ld	[%g7 + PID], %o5 +	sethi	%hi(0x80000000), %o3 +	cmp	%o5, 0 +	sub	%g0, %o5, %o4 +	move	%icc, %o3, %o4 +	st	%o4, [%g7 + PID] + +	LOADSYSCALL(vfork) +	ta	0x6d +	bcc,pt	%xcc, 2f +	 mov	%o7, %g1 +	st	%o5, [%g7 + PID] +	call	__syscall_error +	 mov	%g1, %o7 +2:	sub	%o1, 1, %o1 +	andcc	%o0, %o1, %o0 +	bne,a,pt %icc, 1f +	 st	%o5, [%g7 + PID] +1:	retl +	 nop +END(__vfork) + +hidden_def (vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h new file mode 100644 index 000000000..5be9beb92 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/sysdep-cancel.h" +#else +#include "sparc32/sysdep-cancel.h" +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep.h new file mode 100644 index 000000000..744e587a3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep.h @@ -0,0 +1,65 @@ +#ifndef _LINUX_SPARC_SYSDEP_H +#define _LINUX_SPARC_SYSDEP_H 1 + +#include <sysdeps/unix/sysdep.h> + +#undef ENTRY +#undef END + +#ifdef __ASSEMBLER__ + +#define LOADSYSCALL(x) mov __NR_##x, %g1 + +#define ENTRY(name)                 \ +    .align 4;                       \ +    .global C_SYMBOL_NAME(name);    \ +    .type   name, @function;        \ +C_LABEL(name)                       \ +    cfi_startproc; + +#define END(name)                   \ +    cfi_endproc;                    \ +    .size name, . - name + +#define LOC(name) .L##name + +	/* If the offset to __syscall_error fits into a signed 22-bit +	 * immediate branch offset, the linker will relax the call into +	 * a normal branch. +	 */ +#undef PSEUDO +#undef PSEUDO_END +#undef PSEUDO_NOERRNO +#undef PSEUDO_ERRVAL + +#define PSEUDO(name, syscall_name, args)	\ +	.text;					\ +	.globl		__syscall_error;	\ +ENTRY(name);					\ +	LOADSYSCALL(syscall_name);		\ +	ta		0x10;			\ +	bcc		1f;			\ +	 mov		%o7, %g1;		\ +	call		__syscall_error;	\ +	 mov		%g1, %o7;		\ +1: + +#define PSEUDO_NOERRNO(name, syscall_name, args)\ +	.text;					\ +ENTRY(name);					\ +	LOADSYSCALL(syscall_name);		\ +	ta		0x10; + +#define PSEUDO_ERRVAL(name, syscall_name, args)	\ +	.text;					\ +ENTRY(name);					\ +	LOADSYSCALL(syscall_name);		\ +	ta		0x10; + +#define PSEUDO_END(name)			\ +	END(name) + + +#endif + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/vfork.S new file mode 100644 index 000000000..160cd0b10 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/vfork.S @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/vfork.S" +#else +#include "sparc32/vfork.S" +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c new file mode 100644 index 000000000..9f02fe3b2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c @@ -0,0 +1,236 @@ +/* Copyright (C) 2003,2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include <internaltypes.h> +#include <pthreadP.h> +#include "kernel-posix-timers.h" +#include "kernel-posix-cpu-timers.h" + + +#ifdef __NR_timer_create +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_create (clockid_t clock_id, struct sigevent *evp, +				timer_t *timerid); +#  define timer_create static compat_timer_create +#  include <nptl/sysdeps/pthread/timer_create.c> +#  undef timer_create + +/* Nonzero if the system calls are not available.  */ +int __no_posix_timers attribute_hidden; +# endif + +# ifdef timer_create_alias +#  define timer_create timer_create_alias +# endif + + +int +timer_create ( +     clockid_t clock_id, +     struct sigevent *evp, +     timer_t *timerid) +{ +# undef timer_create +# ifndef __ASSUME_POSIX_TIMERS +  if  (__no_posix_timers >= 0) +# endif +    { +      clockid_t syscall_clockid = (clock_id == CLOCK_PROCESS_CPUTIME_ID +				   ? MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED) +				   : clock_id == CLOCK_THREAD_CPUTIME_ID +				   ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED) +				   : clock_id); + +      /* If the user wants notification via a thread we need to handle +	 this special.  */ +      if (evp == NULL +	  || __builtin_expect (evp->sigev_notify != SIGEV_THREAD, 1)) +	{ +	  struct sigevent local_evp; + +	  /* We avoid allocating too much memory by basically +	     using struct timer as a derived class with the +	     first two elements being in the superclass.  We only +	     need these two elements here.  */ +	  struct timer *newp = (struct timer *) malloc (offsetof (struct timer, +								  thrfunc)); +	  if (newp == NULL) +	    /* No more memory.  */ +	    return -1; + +	  if (evp == NULL) +	    { +	      /* The kernel has to pass up the timer ID which is a +		 userlevel object.  Therefore we cannot leave it up to +		 the kernel to determine it.  */ +	      local_evp.sigev_notify = SIGEV_SIGNAL; +	      local_evp.sigev_signo = SIGALRM; +	      local_evp.sigev_value.sival_ptr = newp; + +	      evp = &local_evp; +	    } + +	  kernel_timer_t ktimerid; +	  int retval = INLINE_SYSCALL (timer_create, 3, syscall_clockid, evp, +				       &ktimerid); + +# ifndef __ASSUME_POSIX_TIMERS +	  if (retval != -1 || errno != ENOSYS) +# endif +	    { +# ifndef __ASSUME_POSIX_TIMERS +	      __no_posix_timers = 1; +# endif + +	      if (retval != -1) +		{ +		  newp->sigev_notify = (evp != NULL +					? evp->sigev_notify : SIGEV_SIGNAL); +		  newp->ktimerid = ktimerid; + +		  *timerid = (timer_t) newp; +		} +	      else +		{ +		  /* Cannot allocate the timer, fail.  */ +		  free (newp); +		  retval = -1; +		} + +	      return retval; +	    } + +	  free (newp); + +# ifndef __ASSUME_POSIX_TIMERS +	  /* When we come here the syscall does not exist.  Make sure we +	     do not try to use it again.  */ +	  __no_posix_timers = -1; +# endif +	} +      else +	{ +# ifndef __ASSUME_POSIX_TIMERS +	  /* Make sure we have the necessary kernel support.  */ +	  if (__no_posix_timers == 0) +	    { +	      INTERNAL_SYSCALL_DECL (err); +	      struct timespec ts; +	      int res; +	      res = INTERNAL_SYSCALL (clock_getres, err, 2, +				      CLOCK_REALTIME, &ts); +	      __no_posix_timers = (INTERNAL_SYSCALL_ERROR_P (res, err) +				   ? -1 : 1); +	    } + +	  if (__no_posix_timers > 0) +# endif +	    { +	      /* Create the helper thread.  */ +	      pthread_once (&__helper_once, __start_helper_thread); +	      if (__helper_tid == 0) +		{ +		  /* No resources to start the helper thread.  */ +		  __set_errno (EAGAIN); +		  return -1; +		} + +	      struct timer *newp; +	      newp = (struct timer *) malloc (sizeof (struct timer)); +	      if (newp == NULL) +		return -1; + +	      /* Copy the thread parameters the user provided.  */ +	      newp->sival = evp->sigev_value; +	      newp->thrfunc = evp->sigev_notify_function; + +	      /* We cannot simply copy the thread attributes since the +		 implementation might keep internal information for +		 each instance.  */ +	      (void) pthread_attr_init (&newp->attr); +	      if (evp->sigev_notify_attributes != NULL) +		{ +		  struct pthread_attr *nattr; +		  struct pthread_attr *oattr; + +		  nattr = (struct pthread_attr *) &newp->attr; +		  oattr = (struct pthread_attr *) evp->sigev_notify_attributes; + +		  nattr->schedparam = oattr->schedparam; +		  nattr->schedpolicy = oattr->schedpolicy; +		  nattr->flags = oattr->flags; +		  nattr->guardsize = oattr->guardsize; +		  nattr->stackaddr = oattr->stackaddr; +		  nattr->stacksize = oattr->stacksize; +		} + +	      /* In any case set the detach flag.  */ +	      (void) pthread_attr_setdetachstate (&newp->attr, +						  PTHREAD_CREATE_DETACHED); + +	      /* Create the event structure for the kernel timer.  */ +	      struct sigevent sev; +	      sev.sigev_value.sival_ptr = newp; +	      sev.sigev_signo = SIGTIMER; +	      sev.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID; +	      /* This is the thread ID of the helper thread.  */ +	      sev._sigev_un._pad[0] = __helper_tid; + +	      /* Create the timer.  */ +	      INTERNAL_SYSCALL_DECL (err); +	      int res; +	      res = INTERNAL_SYSCALL (timer_create, err, 3, +				      syscall_clockid, &sev, &newp->ktimerid); +	      if (! INTERNAL_SYSCALL_ERROR_P (res, err)) +		{ +		  *timerid = (timer_t) newp; +		  return 0; +		} + +	      /* Free the resources.  */ +	      free (newp); + +	      __set_errno (INTERNAL_SYSCALL_ERRNO (res, err)); + +	      return -1; +	    } +	} +    } + +# ifndef __ASSUME_POSIX_TIMERS +  /* Compatibility code.  */ +  return compat_timer_create (clock_id, evp, timerid); +# endif +} +#else +# ifdef timer_create_alias +#  define timer_create timer_create_alias +# endif +/* The new system calls are not available.  Use the userlevel +   implementation.  */ +# include <nptl/sysdeps/pthread/timer_create.c> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_delete.c new file mode 100644 index 000000000..9b92446d5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_delete.c @@ -0,0 +1,93 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <errno.h> +#include <stdlib.h> +#include <time.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_delete +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_delete (timer_t timerid); +#  define timer_delete static compat_timer_delete +#  include <nptl/sysdeps/pthread/timer_delete.c> +#  undef timer_delete +# endif + +# ifdef timer_delete_alias +#  define timer_delete timer_delete_alias +# endif + + +int +timer_delete (timer_t timerid) +{ +# undef timer_delete +# ifndef __ASSUME_POSIX_TIMERS +  if (__no_posix_timers >= 0) +# endif +    { +      struct timer *kt = (struct timer *) timerid; + +      /* Delete the kernel timer object.  */ +      int res = INLINE_SYSCALL (timer_delete, 1, kt->ktimerid); + +      if (res == 0) +	{ +# ifndef __ASSUME_POSIX_TIMERS +	  /* We know the syscall support is available.  */ +	  __no_posix_timers = 1; +# endif + +	  /* Free the memory.  */ +	  (void) free (kt); + +	  return 0; +	} + +      /* The kernel timer is not known or something else bad happened. +	 Return the error.  */ +# ifndef __ASSUME_POSIX_TIMERS +      if (errno != ENOSYS) +	{ +	  __no_posix_timers = 1; +# endif +	  return -1; +# ifndef __ASSUME_POSIX_TIMERS +	} + +      __no_posix_timers = -1; +# endif +    } + +# ifndef __ASSUME_POSIX_TIMERS +  return compat_timer_delete (timerid); +# endif +} +#else +# ifdef timer_delete_alias +#  define timer_delete timer_delete_alias +# endif +/* The new system calls are not available.  Use the userlevel +   implementation.  */ +# include <nptl/sysdeps/pthread/timer_delete.c> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c new file mode 100644 index 000000000..7afc5ec6f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c @@ -0,0 +1,80 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <errno.h> +#include <time.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_getoverrun +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_getoverrun (timer_t timerid); +#  define timer_getoverrun static compat_timer_getoverrun +#  include <nptl/sysdeps/pthread/timer_getoverr.c> +#  undef timer_getoverrun +# endif + +# ifdef timer_getoverrun_alias +#  define timer_getoverrun timer_getoverrun_alias +# endif + + +int +timer_getoverrun (timer_t timerid) +{ +# undef timer_getoverrun +# ifndef __ASSUME_POSIX_TIMERS +  if (__no_posix_timers >= 0) +# endif +    { +      struct timer *kt = (struct timer *) timerid; + +      /* Get the information from the kernel.  */ +      int res = INLINE_SYSCALL (timer_getoverrun, 1, kt->ktimerid); + +# ifndef __ASSUME_POSIX_TIMERS +      if (res != -1 || errno != ENOSYS) +	{ +	  /* We know the syscall support is available.  */ +	  __no_posix_timers = 1; +# endif +	  return res; +# ifndef __ASSUME_POSIX_TIMERS +	} +# endif + +# ifndef __ASSUME_POSIX_TIMERS +      __no_posix_timers = -1; +# endif +    } + +# ifndef __ASSUME_POSIX_TIMERS +  return compat_timer_getoverrun (timerid); +# endif +} +#else +# ifdef timer_getoverrun_alias +#  define timer_getoverrun timer_getoverrun_alias +# endif +/* The new system calls are not available.  Use the userlevel +   implementation.  */ +# include <nptl/sysdeps/pthread/timer_getoverr.c> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c new file mode 100644 index 000000000..31401b19b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c @@ -0,0 +1,83 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <errno.h> +#include <stdlib.h> +#include <time.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_gettime +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_gettime (timer_t timerid, struct itimerspec *value); +#  define timer_gettime static compat_timer_gettime +#  include <nptl/sysdeps/pthread/timer_gettime.c> +#  undef timer_gettime +# endif + +# ifdef timer_gettime_alias +#  define timer_gettime timer_gettime_alias +# endif + + +int +timer_gettime ( +     timer_t timerid, +     struct itimerspec *value) +{ +# undef timer_gettime +# ifndef __ASSUME_POSIX_TIMERS +  if (__no_posix_timers >= 0) +# endif +    { +      struct timer *kt = (struct timer *) timerid; + +      /* Delete the kernel timer object.  */ +      int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value); + +# ifndef __ASSUME_POSIX_TIMERS +      if (res != -1 || errno != ENOSYS) +	{ +	  /* We know the syscall support is available.  */ +	  __no_posix_timers = 1; +# endif +	  return res; +# ifndef __ASSUME_POSIX_TIMERS +	} +# endif + +# ifndef __ASSUME_POSIX_TIMERS +      __no_posix_timers = -1; +# endif +    } + +# ifndef __ASSUME_POSIX_TIMERS +  return compat_timer_gettime (timerid, value); +# endif +} +#else +# ifdef timer_gettime_alias +#  define timer_gettime timer_gettime_alias +# endif +/* The new system calls are not available.  Use the userlevel +   implementation.  */ +# include <nptl/sysdeps/pthread/timer_gettime.c> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_routines.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_routines.c new file mode 100644 index 000000000..0ddfe8a51 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_routines.c @@ -0,0 +1,164 @@ +/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <errno.h> +#include <setjmp.h> +#include <signal.h> +#include <stdbool.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include <pthreadP.h> +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_create +/* Helper thread to call the user-provided function.  */ +static void * +timer_sigev_thread (void *arg) +{ +  /* The parent thread has all signals blocked.  This is a bit +     surprising for user code, although valid.  We unblock all +     signals.  */ +  sigset_t ss; +  sigemptyset (&ss); +  INTERNAL_SYSCALL_DECL (err); +  INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8); + +  struct timer *tk = (struct timer *) arg; + +  /* Call the user-provided function.  */ +  tk->thrfunc (tk->sival); + +  return NULL; +} + + +/* Helper function to support starting threads for SIGEV_THREAD.  */ +static void * +timer_helper_thread (void *arg) +{ +  /* Wait for the SIGTIMER signal, allowing the setXid signal, and +     none else.  */ +  sigset_t ss; +  sigemptyset (&ss); +  __sigaddset (&ss, SIGTIMER); +#ifdef SIGSETXID +  __sigaddset (&ss, SIGSETXID); +#endif + +  /* Endless loop of waiting for signals.  The loop is only ended when +     the thread is canceled.  */ +  while (1) +    { +      siginfo_t si; + +      /* sigwaitinfo cannot be used here, since it deletes +	 SIGCANCEL == SIGTIMER from the set.  */ + +      int oldtype = LIBC_CANCEL_ASYNC (); + +      /* XXX The size argument hopefully will have to be changed to the +	 real size of the user-level sigset_t.  */ +      int result = INLINE_SYSCALL (rt_sigtimedwait, 4, &ss, &si, NULL, +				   _NSIG / 8); + +      LIBC_CANCEL_RESET (oldtype); + +      if (result > 0) +	{ +	  if (si.si_code == SI_TIMER) +	    { +	      struct timer *tk = (struct timer *) si.si_ptr; + +	      /* That the signal we are waiting for.  */ +	      pthread_t th; +	      (void) pthread_create (&th, &tk->attr, timer_sigev_thread, tk); +	    } +	  else if (si.si_code == SI_TKILL) +	    /* The thread is canceled.  */ +	    pthread_exit (NULL); +	} +    } +} + + +/* Control variable for helper thread creation.  */ +pthread_once_t __helper_once attribute_hidden; + + +/* TID of the helper thread.  */ +pid_t __helper_tid attribute_hidden; + + +/* Reset variables so that after a fork a new helper thread gets started.  */ +static void +reset_helper_control (void) +{ +  __helper_once = PTHREAD_ONCE_INIT; +  __helper_tid = 0; +} + + +void +attribute_hidden +__start_helper_thread (void) +{ +  /* The helper thread needs only very little resources +     and should go away automatically when canceled.  */ +  pthread_attr_t attr; +  (void) pthread_attr_init (&attr); +  (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + +  /* Block all signals in the helper thread but SIGSETXID.  To do this +     thoroughly we temporarily have to block all signals here.  The +     helper can lose wakeups if SIGCANCEL is not blocked throughout, +     but sigfillset omits it.  So, we add it back explicitly here.  */ +  sigset_t ss; +  sigset_t oss; +  sigfillset (&ss); +  __sigaddset (&ss, SIGCANCEL); +#ifdef SIGSETXID +  __sigdelset (&ss, SIGSETXID); +#endif +  INTERNAL_SYSCALL_DECL (err); +  INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8); + +  /* Create the helper thread for this timer.  */ +  pthread_t th; +  int res = pthread_create (&th, &attr, timer_helper_thread, NULL); +  if (res == 0) +    /* We managed to start the helper thread.  */ +    __helper_tid = ((struct pthread *) th)->tid; + +  /* Restore the signal mask.  */ +  INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL, +		    _NSIG / 8); + +  /* No need for the attribute anymore.  */ +  (void) pthread_attr_destroy (&attr); + +  /* We have to make sure that after fork()ing a new helper thread can +     be created.  */ +  pthread_atfork (NULL, NULL, reset_helper_control); +} +#endif + +#ifndef __ASSUME_POSIX_TIMERS +# include <nptl/sysdeps/pthread/timer_routines.c> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c new file mode 100644 index 000000000..8c6ad91fa --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <errno.h> +#include <stdlib.h> +#include <time.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_settime +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_settime (timer_t timerid, int flags, +				 const struct itimerspec *value, +				 struct itimerspec *ovalue); +#  define timer_settime static compat_timer_settime +#  include <nptl/sysdeps/pthread/timer_settime.c> +#  undef timer_settime +# endif + +# ifdef timer_settime_alias +#  define timer_settime timer_settime_alias +# endif + + +int +timer_settime ( +     timer_t timerid, +     int flags, +     const struct itimerspec *value, +     struct itimerspec *ovalue) +{ +# undef timer_settime +# ifndef __ASSUME_POSIX_TIMERS +  if (__no_posix_timers >= 0) +# endif +    { +      struct timer *kt = (struct timer *) timerid; + +      /* Delete the kernel timer object.  */ +      int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags, +				value, ovalue); + +# ifndef __ASSUME_POSIX_TIMERS +      if (res != -1 || errno != ENOSYS) +	{ +	  /* We know the syscall support is available.  */ +	  __no_posix_timers = 1; +# endif +	  return res; +# ifndef __ASSUME_POSIX_TIMERS +	} +# endif + +# ifndef __ASSUME_POSIX_TIMERS +      __no_posix_timers = -1; +# endif +    } + +# ifndef __ASSUME_POSIX_TIMERS +  return compat_timer_settime (timerid, flags, value, ovalue); +# endif +} +#else +# ifdef timer_settime_alias +#  define timer_settime timer_settime_alias +# endif +/* The new system calls are not available.  Use the userlevel +   implementation.  */ +# include <nptl/sysdeps/pthread/timer_settime.c> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c new file mode 100644 index 000000000..35955238b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c @@ -0,0 +1,110 @@ +/* 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 <errno.h> +#include <stdlib.h> +#include "fork.h" +#include <atomic.h> + + +void +__unregister_atfork (void *dso_handle) +{ +  /* Check whether there is any entry in the list which we have to +     remove.  It is likely that this is not the case so don't bother +     getting the lock. + +     We do not worry about other threads adding entries for this DSO +     right this moment.  If this happens this is a race and we can do +     whatever we please.  The program will crash anyway seen.  */ +  struct fork_handler *runp = __fork_handlers; +  struct fork_handler *lastp = NULL; + +  while (runp != NULL) +    if (runp->dso_handle == dso_handle) +      break; +    else +      { +	lastp = runp; +	runp = runp->next; +      } + +  if (runp == NULL) +    /* Nothing to do.  */ +    return; + +  /* Get the lock to not conflict with additions or deletions.  Note +     that there couldn't have been another thread deleting something. +     The __unregister_atfork function is only called from the +     dlclose() code which itself serializes the operations.  */ +  lll_lock (__fork_lock); + +  /* We have to create a new list with all the entries we don't remove.  */ +  struct deleted_handler +  { +    struct fork_handler *handler; +    struct deleted_handler *next; +  } *deleted = NULL; + +  /* Remove the entries for the DSO which is unloaded from the list. +     It's a single linked list so readers are.  */ +  do +    { +      if (runp->dso_handle == dso_handle) +	{ +	  if (lastp == NULL) +	    __fork_handlers = runp->next; +	  else +	    lastp->next = runp->next; + +	  /* We cannot overwrite the ->next element now.  Put the deleted +	     entries in a separate list.  */ +	  struct deleted_handler *newp = alloca (sizeof (*newp)); +	  newp->handler = runp; +	  newp->next = deleted; +	  deleted = newp; +	} +      else +	lastp = runp; + +      runp = runp->next; +    } +  while (runp != NULL); + +  /* Release the lock.  */ +  lll_unlock (__fork_lock); + +  /* Walk the list of all entries which have to be deleted.  */ +  while (deleted != NULL) +    { +      /* We need to be informed by possible current users.  */ +      deleted->handler->need_signal = 1; +      /* Make sure this gets written out first.  */ +      atomic_write_barrier (); + +      /* Decrement the reference counter.  If it does not reach zero +	 wait for the last user.  */ +      atomic_decrement (&deleted->handler->refcntr); +      unsigned int val; +      while ((val = deleted->handler->refcntr) != 0) +	lll_futex_wait (&deleted->handler->refcntr, val); + +      deleted = deleted->next; +    } +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym b/libpthread/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym new file mode 100644 index 000000000..8044b4078 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym @@ -0,0 +1,7 @@ +#include <pthread.h> +#include <stddef.h> + +-- + +UNWINDBUFSIZE	sizeof (__pthread_unwind_buf_t) +UWJMPBUF	offsetof (__pthread_unwind_buf_t, __cancel_jmp_buf) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S b/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S new file mode 100644 index 000000000..f55d34629 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S @@ -0,0 +1,19 @@ +#include <sysdep-cancel.h> + +/* +extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + + +PSEUDO (__waitpid, waitpid, 3) +ret +PSEUDO_END(__waitpid) + +libc_hidden_def (__waitpid) +weak_alias (__waitpid, waitpid) +libc_hidden_weak (waitpid) +weak_alias (__waitpid, __libc_waitpid) +libc_hidden_weak (__libc_waitpid) + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/write.S b/libpthread/nptl/sysdeps/unix/sysv/linux/write.S new file mode 100644 index 000000000..43de3320d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/write.S @@ -0,0 +1,19 @@ +#include <sysdep-cancel.h> + +/* +extern int __write_nocancel (int, const void *, size_t) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +PSEUDO (__libc_write, write, 3) +ret +PSEUDO_END(__libc_write) + +libc_hidden_def (__write_nocancel) +libc_hidden_def (__libc_write) +weak_alias (__libc_write, __write) +libc_hidden_weak (__write) +weak_alias (__libc_write, write) +libc_hidden_weak (write) + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile @@ -0,0 +1,13 @@ +# 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. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile.arch new file mode 100644 index 000000000..e50539a36 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile.arch @@ -0,0 +1,73 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/x86_64 +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/x86_64 + + +libpthread_SSRC = pt-vfork.S clone.S pthread_once.S +libpthread_CSRC = pthread_spin_init.c + +libc_a_CSRC = fork.c +libc_a_SSRC = clone.S vfork.S + +libpthread_SSRC += lowlevellock.S pthread_barrier_wait.S pthread_cond_signal.S pthread_cond_broadcast.S \ +		   sem_post.S sem_timedwait.S \ +		   sem_trywait.S sem_wait.S pthread_rwlock_rdlock.S pthread_rwlock_wrlock.S \ +		   pthread_rwlock_timedrdlock.S pthread_rwlock_timedwrlock.S pthread_rwlock_unlock.S \ +		   pthread_cond_timedwait.S pthread_cond_wait.S + +libc_a_SSRC += libc-lowlevellock.S + + +CFLAGS-OMIT-fork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-lowlevellock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_once.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD + + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT +ASFLAGS-libc-lowlevellock.S = -D_LIBC_REENTRANT + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +#Needed to use the correct SYSCALL_ERROR_HANDLER +ASFLAGS-clone.S += -DUSE___THREAD +ASFLAGS-vfork.S += -DUSE___THREAD +endif + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) +LINUX_ARCH_OBJ+=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJS) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) +LIBC_LINUX_ARCH_OBJ+=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libc_a_SSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=nptl_linux_arch_clean + +nptl_linux_arch_clean: +	$(do_rm) $(addprefix $(LINUX_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Versions b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Versions new file mode 100644 index 000000000..3b111ddb5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Versions @@ -0,0 +1,7 @@ +librt { +  GLIBC_2.3.3 { +    # Changed timer_t. +    timer_create; timer_delete; timer_getoverrun; timer_gettime; +    timer_settime; +  } +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h new file mode 100644 index 000000000..7a09c8119 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h @@ -0,0 +1,225 @@ +/* Copyright (C) 2002,2003,2004,2005,2006,2007 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 _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H	1 + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers.  The structure of the attribute type is not +   exposed on purpose.  */ +typedef unsigned long int pthread_t; + + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_ATTR_T]; +  long int __align; +} pthread_attr_t; + + +#if __WORDSIZE == 64 +typedef struct __pthread_internal_list +{ +  struct __pthread_internal_list *__prev; +  struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ +  struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + + +/* Data structures for mutex handling.  The structure of the attribute +   type is not exposed on purpose.  */ +typedef union +{ +  struct __pthread_mutex_s +  { +    int __lock; +    unsigned int __count; +    int __owner; +#if __WORDSIZE == 64 +    unsigned int __nusers; +#endif +    /* KIND must stay at this position in the structure to maintain +       binary compatibility.  */ +    int __kind; +#if __WORDSIZE == 64 +    int __spins; +    __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV	1 +#else +    unsigned int __nusers; +    __extension__ union +    { +      int __spins; +      __pthread_slist_t __list; +    }; +#endif +  } __data; +  char __size[__SIZEOF_PTHREAD_MUTEX_T]; +  long int __align; +} pthread_mutex_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; +  int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling.  The structure of +   the attribute type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __futex; +    __extension__ unsigned long long int __total_seq; +    __extension__ unsigned long long int __wakeup_seq; +    __extension__ unsigned long long int __woken_seq; +    void *__mutex; +    unsigned int __nwaiters; +    unsigned int __broadcast_seq; +  } __data; +  char __size[__SIZEOF_PTHREAD_COND_T]; +  __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_CONDATTR_T]; +  int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling.  The +   structure of the attribute type is not exposed on purpose.  */ +typedef union +{ +# if __WORDSIZE == 64 +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    int __writer; +    int __shared; +    unsigned long int __pad1; +    unsigned long int __pad2; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +  } __data; +# else +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned char __flags; +    unsigned char __shared; +    unsigned char __pad1; +    unsigned char __pad2; +    int __writer; +  } __data; +# endif +  char __size[__SIZEOF_PTHREAD_RWLOCK_T]; +  long int __align; +} pthread_rwlock_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; +  long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type.  */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type.  The structure of the type is +   deliberately not exposed.  */ +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIER_T]; +  long int __align; +} pthread_barrier_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; +  int __align; +} pthread_barrierattr_t; +#endif + + +#if __WORDSIZE == 32 +/* Extra attributes for the cleanup functions.  */ +# define __cleanup_fct_attribute __attribute__ ((__regparm__ (1))) +#endif + +#endif	/* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h new file mode 100644 index 000000000..57edbbbfb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h @@ -0,0 +1,44 @@ +/* Copyright (C) 2002, 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.  */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_SEM_T	32 +#else +# define __SIZEOF_SEM_T	16 +#endif + + +/* Value returned if `sem_open' failed.  */ +#define SEM_FAILED      ((sem_t *) 0) + +/* Maximum value the semaphore can have.  */ +#define SEM_VALUE_MAX   (2147483647) + + +typedef union +{ +  char __size[__SIZEOF_SEM_T]; +  long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S new file mode 100644 index 000000000..680696200 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S @@ -0,0 +1,116 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2009. + +   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 <sysdep.h> +#include <tcb-offsets.h> +#include <kernel-features.h> +#include "lowlevellock.h" + +#ifdef IS_IN_libpthread +# ifdef SHARED +#  define __pthread_unwind __GI___pthread_unwind +# endif +#else +# ifndef SHARED +	.weak __pthread_unwind +# endif +#endif + + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ +	movl	$(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +#else +# if FUTEX_WAIT == 0 +#  define LOAD_PRIVATE_FUTEX_WAIT(reg) \ +	movl	%fs:PRIVATE_FUTEX, reg +# else +#  define LOAD_PRIVATE_FUTEX_WAIT(reg) \ +	movl	%fs:PRIVATE_FUTEX, reg ; \ +	orl	$FUTEX_WAIT, reg +# endif +#endif + +/* It is crucial that the functions in this file don't modify registers +   other than %rax and %r11.  The syscall wrapper code depends on this +   because it doesn't explicitly save the other registers which hold +   relevant values.  */ +	.text + +	.hidden __pthread_enable_asynccancel +ENTRY(__pthread_enable_asynccancel) +	movl	%fs:CANCELHANDLING, %eax +2:	movl	%eax, %r11d +	orl	$TCB_CANCELTYPE_BITMASK, %r11d +	cmpl	%eax, %r11d +	je	1f + +	lock +	cmpxchgl %r11d, %fs:CANCELHANDLING +	jnz	2b + +	andl	$(TCB_CANCELSTATE_BITMASK|TCB_CANCELTYPE_BITMASK|TCB_CANCELED_BITMASK|TCB_EXITING_BITMASK|TCB_CANCEL_RESTMASK|TCB_TERMINATED_BITMASK), %r11d +	cmpl	$(TCB_CANCELTYPE_BITMASK|TCB_CANCELED_BITMASK), %r11d +	je	3f + +1:	ret + +3:	movq	$TCB_PTHREAD_CANCELED, %fs:RESULT +	lock +	orl	$TCB_EXITING_BITMASK, %fs:CANCELHANDLING +	movq	%fs:CLEANUP_JMP_BUF, %rdi +#ifdef SHARED +	call	__pthread_unwind@PLT +#else +	call	__pthread_unwind +#endif +	hlt +END(__pthread_enable_asynccancel) + + +	.hidden __pthread_disable_asynccancel +ENTRY(__pthread_disable_asynccancel) +	testl	$TCB_CANCELTYPE_BITMASK, %edi +	jnz	1f + +	movl	%fs:CANCELHANDLING, %eax +2:	movl	%eax, %r11d +	andl	$~TCB_CANCELTYPE_BITMASK, %r11d +	lock +	cmpxchgl %r11d, %fs:CANCELHANDLING +	jnz	2b + +	movl	%r11d, %eax +3:	andl	$(TCB_CANCELING_BITMASK|TCB_CANCELED_BITMASK), %eax +	cmpl	$TCB_CANCELING_BITMASK, %eax +	je	4f +1:	ret + +	/* Performance doesn't matter in this loop.  We will +	   delay until the thread is canceled.  And we will unlikely +	   enter the loop twice.  */ +4:	movq	%fs:0, %rdi +	movl	$__NR_futex, %eax +	xorq	%r10, %r10 +	addq	$CANCELHANDLING, %rdi +	LOAD_PRIVATE_FUTEX_WAIT (%esi) +	syscall +	movl	%fs:CANCELHANDLING, %eax +	jmp	3b +END(__pthread_disable_asynccancel) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S new file mode 100644 index 000000000..675a997e9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S @@ -0,0 +1,9 @@ +/* We want an #include_next, but we are the main source file. +   So, #include ourselves and in that incarnation we can use #include_next.  */ +#ifndef INCLUDED_SELF +# define INCLUDED_SELF +# include <clone.S> +#else +# define RESET_PID +# include_next <clone.S> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h new file mode 100644 index 000000000..02485daa5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <signal.h> +#include <time.h> +#include <sys/types.h> + +#define OLD_TIMER_MAX	256 + +extern timer_t __compat_timer_list[OLD_TIMER_MAX] attribute_hidden; + + +extern int __timer_create_new (clockid_t clock_id, struct sigevent *evp, +			       timer_t *timerid); +extern int __timer_delete_new (timer_t timerid); +extern int __timer_getoverrun_new (timer_t timerid); +extern int __timer_gettime_new (timer_t timerid, struct itimerspec *value); +extern int __timer_settime_new (timer_t timerid, int flags, +				const struct itimerspec *value, +				struct itimerspec *ovalue); + + +extern int __timer_create_old (clockid_t clock_id, struct sigevent *evp, +			       int *timerid); +extern int __timer_delete_old (int timerid); +extern int __timer_getoverrun_old (int timerid); +extern int __timer_gettime_old (int timerid, struct itimerspec *value); +extern int __timer_settime_old (int timerid, int flags, +				const struct itimerspec *value, +				struct itimerspec *ovalue); diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c new file mode 100644 index 000000000..c828e158d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + + +#define ARCH_FORK() \ +  INLINE_SYSCALL (clone, 4,						      \ +		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,     \ +		  NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S new file mode 100644 index 000000000..110058850 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S @@ -0,0 +1,22 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2009. + +   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 __pthread_enable_asynccancel __libc_enable_asynccancel +#define __pthread_disable_asynccancel __libc_disable_asynccancel +#include "cancellation.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S new file mode 100644 index 000000000..ce8ad27aa --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002, 2003, 2007 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 "lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S new file mode 100644 index 000000000..ce4192b5d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S @@ -0,0 +1,22 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2009. + +   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 __pthread_enable_asynccancel __librt_enable_asynccancel +#define __pthread_disable_asynccancel __librt_disable_asynccancel +#include "cancellation.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S new file mode 100644 index 000000000..1e461ad41 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S @@ -0,0 +1,282 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <pthread-errnos.h> + +	.text + +#ifndef LOCK +# ifdef UP +#  define LOCK +# else +#  define LOCK lock +# endif +#endif + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +/* For the calculation see asm/vsyscall.h.  */ +#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000 + + +	.globl	__lll_mutex_lock_wait +	.type	__lll_mutex_lock_wait,@function +	.hidden	__lll_mutex_lock_wait +	.align	16 +__lll_mutex_lock_wait: +	pushq	%r10 +	pushq	%rdx + +	xorq	%r10, %r10	/* No timeout.  */ +	movl	$2, %edx +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif + +	cmpl	%edx, %eax	/* NB:	 %edx == 2 */ +	jne	2f + +1:	movl	$SYS_futex, %eax +	syscall + +2:	movl	%edx, %eax +	xchgl	%eax, (%rdi)	/* NB:	 lock is implied */ + +	testl	%eax, %eax +	jnz	1b + +	popq	%rdx +	popq	%r10 +	retq +	.size	__lll_mutex_lock_wait,.-__lll_mutex_lock_wait + + +#ifdef NOT_IN_libc +	.globl	__lll_mutex_timedlock_wait +	.type	__lll_mutex_timedlock_wait,@function +	.hidden	__lll_mutex_timedlock_wait +	.align	16 +__lll_mutex_timedlock_wait: +	/* Check for a valid timeout value.  */ +	cmpq	$1000000000, 8(%rdx) +	jae	3f + +	pushq	%r8 +	pushq	%r9 +	pushq	%r12 +	pushq	%r13 +	pushq	%r14 + +	/* Stack frame for the timespec and timeval structs.  */ +	subq	$16, %rsp + +	movq	%rdi, %r12 +	movq	%rdx, %r13 + +1: +	/* Get current time.  */ +	movq	%rsp, %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	/* This is a regular function call, all caller-save registers +	   might be clobbered.  */ +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	8(%rsp), %rax +	movl	$1000, %edi +	mul	%rdi		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rdi +	movq	8(%r13), %rsi +	subq	(%rsp), %rdi +	subq	%rax, %rsi +	jns	4f +	addq	$1000000000, %rsi +	decq	%rdi +4:	testq	%rdi, %rdi +	js	5f		/* Time is already up.  */ + +	/* Futex call.  */ +	movq	%rdi, (%rsp)	/* Store relative timeout.  */ +	movq	%rsi, 8(%rsp) + +	movl	$1, %eax +	movl	$2, %edx +	LOCK +	cmpxchgl %edx, (%r12) + +	testl	%eax, %eax +	je	8f + +	movq	%rsp, %r10 +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movq	%r12, %rdi +	movl	$SYS_futex, %eax +	syscall +	movq	%rax, %rcx + +8:				/* NB: %edx == 2 */ +	xorl	%eax, %eax +	LOCK +	cmpxchgl %edx, (%rdi) +	jnz	7f + +6:	addq	$16, %rsp +	popq	%r14 +	popq	%r13 +	popq	%r12 +	popq	%r9 +	popq	%r8 +	retq + +	/* Check whether the time expired.  */ +7:	cmpq	$-ETIMEDOUT, %rcx +	je	5f + +	/* Make sure the current holder knows we are going to sleep.  */ +	movl	%edx, %eax +	xchgl	%eax, (%rdi) +	testl	%eax, %eax +	jz	6b +	jmp	1b + +3:	movl	$EINVAL, %eax +	retq + +5:	movl	$ETIMEDOUT, %eax +	jmp	6b +	.size	__lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait +#endif + + +#ifdef NOT_IN_libc +	.globl	lll_unlock_wake_cb +	.type	lll_unlock_wake_cb,@function +	.hidden	lll_unlock_wake_cb +	.align	16 +lll_unlock_wake_cb: +	pushq	%rsi +	pushq	%rdx + +	LOCK +	addl	$1, (%rdi) +	jng	1f + +	popq	%rdx +	popq	%rsi +	retq +	.size	lll_unlock_wake_cb,.-lll_unlock_wake_cb +#endif + + +	.globl	__lll_mutex_unlock_wake +	.type	__lll_mutex_unlock_wake,@function +	.hidden	__lll_mutex_unlock_wake +	.align	16 +__lll_mutex_unlock_wake: +	pushq	%rsi +	pushq	%rdx + +	movl	$0, (%rdi) +	movl	$FUTEX_WAKE, %esi +	movl	$1, %edx	/* Wake one thread.  */ +	movl	$SYS_futex, %eax +	syscall + +	popq	%rdx +	popq	%rsi +	retq +	.size	__lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake + + +#ifdef NOT_IN_libc +	.globl	__lll_timedwait_tid +	.type	__lll_timedwait_tid,@function +	.hidden	__lll_timedwait_tid +	.align	16 +__lll_timedwait_tid: +	pushq	%r12 +	pushq	%r13 + +	movq	%rdi, %r12 +	movq	%rsi, %r13 + +	subq	$16, %rsp + +	/* Get current time.  */ +2:	movq	%rsp, %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	8(%rsp), %rax +	movl	$1000, %edi +	mul	%rdi		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rdi +	movq	8(%r13), %rsi +	subq	(%rsp), %rdi +	subq	%rax, %rsi +	jns	5f +	addq	$1000000000, %rsi +	decq	%rdi +5:	testq	%rdi, %rdi +	js	6f		/* Time is already up.  */ + +	movq	%rdi, (%rsp)	/* Store relative timeout.  */ +	movq	%rsi, 8(%rsp) + +	movl	(%r12), %edx +	testl	%edx, %edx +	jz	4f + +	movq	%rsp, %r10 +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movq	%r12, %rdi +	movl	$SYS_futex, %eax +	syscall + +	cmpl	$0, (%rdi) +	jne	1f +4:	xorl	%eax, %eax + +8:	addq	$16, %rsp +	popq	%r13 +	popq	%r12 +	retq + +1:	cmpq	$-ETIMEDOUT, %rax +	jne	2b + +6:	movl	$ETIMEDOUT, %eax +	jmp	8b +	.size	__lll_timedwait_tid,.-__lll_timedwait_tid +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h new file mode 100644 index 000000000..c9f30e962 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h @@ -0,0 +1,342 @@ +/* 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.  */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H	1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> +#include <sysdep.h> + +#ifndef LOCK_INSTR +# ifdef UP +#  define LOCK_INSTR	/* nothing */ +# else +#  define LOCK_INSTR "lock;" +# endif +#endif + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +/* Initializer for compatibility lock.  */ +#define LLL_MUTEX_LOCK_INITIALIZER		(0) +#define LLL_MUTEX_LOCK_INITIALIZER_LOCKED	(1) +#define LLL_MUTEX_LOCK_INITIALIZER_WAITERS	(2) + +/* Delay in spinlock loop.  */ +#define BUSY_WAIT_NOP          __asm__ ("rep; nop") + + +#define lll_futex_wait(futex, val) \ +  do {									      \ +    int __ignore;							      \ +    register __typeof (val) _val __asm__ ("edx") = (val);			      \ +    __asm__ __volatile ("xorq %%r10, %%r10\n\t"				      \ +		      "syscall"						      \ +		      : "=a" (__ignore)					      \ +		      : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAIT),	      \ +			"d" (_val)					      \ +		      : "memory", "cc", "r10", "r11", "cx");		      \ +  } while (0) + + +#define lll_futex_wake(futex, nr) \ +  do {									      \ +    int __ignore;							      \ +    register __typeof (nr) _nr __asm__ ("edx") = (nr);			      \ +    __asm__ __volatile ("syscall"						      \ +		      : "=a" (__ignore)					      \ +		      : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAKE),	      \ +			"d" (_nr)					      \ +		      : "memory", "cc", "r10", "r11", "cx");		      \ +  } while (0) + + +/* Does not preserve %eax and %ecx.  */ +extern int __lll_mutex_lock_wait (int *__futex, int __val) attribute_hidden; +/* Does not preserver %eax, %ecx, and %edx.  */ +extern int __lll_mutex_timedlock_wait (int *__futex, int __val, +				       const struct timespec *__abstime) +     attribute_hidden; +/* Preserves all registers but %eax.  */ +extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden; + + +/* NB: in the lll_mutex_trylock macro we simply return the value in %eax +   after the cmpxchg instruction.  In case the operation succeded this +   value is zero.  In case the operation failed, the cmpxchg instruction +   has loaded the current value of the memory work which is guaranteed +   to be nonzero.  */ +#define lll_mutex_trylock(futex) \ +  ({ int ret;								      \ +     __asm__ __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \ +		       : "=a" (ret), "=m" (futex)			      \ +		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), "m" (futex),\ +			 "0" (LLL_MUTEX_LOCK_INITIALIZER)		      \ +		       : "memory");					      \ +     ret; }) + + +#define lll_mutex_cond_trylock(futex) \ +  ({ int ret;								      \ +     __asm__ __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \ +		       : "=a" (ret), "=m" (futex)			      \ +		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_WAITERS),	      \ +			 "m" (futex), "0" (LLL_MUTEX_LOCK_INITIALIZER)	      \ +		       : "memory");					      \ +     ret; }) + + +#define lll_mutex_lock(futex) \ +  (void) ({ int ignore1, ignore2, ignore3;				      \ +	    __asm__ __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t"		      \ +			      "jnz 1f\n\t"				      \ +			      ".subsection 1\n"				      \ +			      "1:\tleaq %2, %%rdi\n\t"			      \ +			      "subq $128, %%rsp\n\t"			      \ +			      "callq __lll_mutex_lock_wait\n\t"		      \ +			      "addq $128, %%rsp\n\t"			      \ +			      "jmp 2f\n\t"				      \ +			      ".previous\n"				      \ +			      "2:"					      \ +			      : "=S" (ignore1), "=&D" (ignore2), "=m" (futex),\ +				"=a" (ignore3)				      \ +			      : "0" (1), "m" (futex), "3" (0)		      \ +			      : "cx", "r11", "cc", "memory"); }) + + +#define lll_mutex_cond_lock(futex) \ +  (void) ({ int ignore1, ignore2, ignore3;				      \ +	    __asm__ __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t"		      \ +			      "jnz 1f\n\t"				      \ +			      ".subsection 1\n"				      \ +			      "1:\tleaq %2, %%rdi\n\t"			      \ +			      "subq $128, %%rsp\n\t"			      \ +			      "callq __lll_mutex_lock_wait\n\t"		      \ +			      "addq $128, %%rsp\n\t"			      \ +			      "jmp 2f\n\t"				      \ +			      ".previous\n"				      \ +			      "2:"					      \ +			      : "=S" (ignore1), "=&D" (ignore2), "=m" (futex),\ +				"=a" (ignore3)				      \ +			      : "0" (2), "m" (futex), "3" (0)		      \ +			      : "cx", "r11", "cc", "memory"); }) + + +#define lll_mutex_timedlock(futex, timeout) \ +  ({ int _result, ignore1, ignore2, ignore3;				      \ +     __asm__ __volatile (LOCK_INSTR "cmpxchgl %2, %4\n\t"			      \ +		       "jnz 1f\n\t"					      \ +		       ".subsection 1\n"				      \ +		       "1:\tleaq %4, %%rdi\n\t"				      \ +		       "movq %8, %%rdx\n\t"				      \ +		       "subq $128, %%rsp\n\t"				      \ +		       "callq __lll_mutex_timedlock_wait\n\t"		      \ +		       "addq $128, %%rsp\n\t"				      \ +		       "jmp 2f\n\t"					      \ +		       ".previous\n"					      \ +		       "2:"						      \ +		       : "=a" (_result), "=&D" (ignore1), "=S" (ignore2),      \ +			 "=&d" (ignore3), "=m" (futex)			      \ +		       : "0" (0), "2" (1), "m" (futex), "m" (timeout)	      \ +		       : "memory", "cx", "cc", "r10", "r11");		      \ +     _result; }) + + +#define lll_mutex_unlock(futex) \ +  (void) ({ int ignore;							      \ +            __asm__ __volatile (LOCK_INSTR "decl %0\n\t"			      \ +			      "jne 1f\n\t"				      \ +			      ".subsection 1\n"				      \ +			      "1:\tleaq %0, %%rdi\n\t"			      \ +			      "subq $128, %%rsp\n\t"			      \ +			      "callq __lll_mutex_unlock_wake\n\t"	      \ +			      "addq $128, %%rsp\n\t"			      \ +			      "jmp 2f\n\t"				      \ +			      ".previous\n"				      \ +			      "2:"					      \ +			      : "=m" (futex), "=&D" (ignore)		      \ +			      : "m" (futex)				      \ +			      : "ax", "cx", "r11", "cc", "memory"); }) + + +#define lll_mutex_islocked(futex) \ +  (futex != LLL_MUTEX_LOCK_INITIALIZER) + + +/* We have a separate internal lock implementation which is not tied +   to binary compatibility.  */ + +/* Type for lock object.  */ +typedef int lll_lock_t; + +/* Initializers for lock.  */ +#define LLL_LOCK_INITIALIZER		(0) +#define LLL_LOCK_INITIALIZER_LOCKED	(1) + + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + + +/* The states of a lock are: +    0  -  untaken +    1  -  taken by one user +    2  -  taken by more users */ + + +#if defined NOT_IN_libc || defined UP +# define lll_trylock(futex) lll_mutex_trylock (futex) +# define lll_lock(futex) lll_mutex_lock (futex) +# define lll_unlock(futex) lll_mutex_unlock (futex) +#else +/* Special versions of the macros for use in libc itself.  They avoid +   the lock prefix when the thread library is not used. + +   The code sequence to avoid unnecessary lock prefixes is what the AMD +   guys suggested.  If you do not like it, bring it up with AMD. + +   XXX In future we might even want to avoid it on UP machines.  */ + +# define lll_trylock(futex) \ +  ({ unsigned char ret;							      \ +     __asm__ __volatile ("cmpl $0, __libc_multiple_threads(%%rip)\n\t"	      \ +		       "je 0f\n\t"					      \ +		       "lock; cmpxchgl %2, %1\n\t"			      \ +		       "jmp 1f\n"					      \ +		       "0:\tcmpxchgl %2, %1\n\t"			      \ +		       "1:setne %0"					      \ +		       : "=a" (ret), "=m" (futex)			      \ +		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), "m" (futex),\ +			 "0" (LLL_MUTEX_LOCK_INITIALIZER)		      \ +		       : "memory");					      \ +     ret; }) + + +# define lll_lock(futex) \ +  (void) ({ int ignore1, ignore2, ignore3;				      \ +	    __asm__ __volatile ("cmpl $0, __libc_multiple_threads(%%rip)\n\t"   \ +			      "je 0f\n\t"				      \ +			      "lock; cmpxchgl %0, %2\n\t"		      \ +			      "jnz 1f\n\t"				      \ +			      "jmp 2f\n"				      \ +			      "0:\tcmpxchgl %0, %2\n\t"			      \ +			      "jnz 1f\n\t"				      \ +			      ".subsection 1\n"				      \ +			      "1:\tleaq %2, %%rdi\n\t"			      \ +			      "subq $128, %%rsp\n\t"			      \ +			      "callq __lll_mutex_lock_wait\n\t"		      \ +			      "addq $128, %%rsp\n\t"			      \ +			      "jmp 2f\n\t"				      \ +			      ".previous\n"				      \ +			      "2:"					      \ +			      : "=S" (ignore1), "=&D" (ignore2), "=m" (futex),\ +				"=a" (ignore3)				      \ +			      : "0" (1), "m" (futex), "3" (0)		      \ +			      : "cx", "r11", "cc", "memory"); }) + + +# define lll_unlock(futex) \ +  (void) ({ int ignore;							      \ +            __asm__ __volatile ("cmpl $0, __libc_multiple_threads(%%rip)\n\t"   \ +			      "je 0f\n\t"				      \ +			      "lock; decl %0\n\t"			      \ +			      "jne 1f\n\t"				      \ +			      "jmp 2f\n"				      \ +			      "0:\tdecl %0\n\t"				      \ +			      "jne 1f\n\t"				      \ +			      ".subsection 1\n"				      \ +			      "1:\tleaq %0, %%rdi\n\t"			      \ +			      "subq $128, %%rsp\n\t"			      \ +			      "callq __lll_mutex_unlock_wake\n\t"	      \ +			      "addq $128, %%rsp\n\t"			      \ +			      "jmp 2f\n\t"				      \ +			      ".previous\n"				      \ +			      "2:"					      \ +			      : "=m" (futex), "=&D" (ignore)		      \ +			      : "m" (futex)				      \ +			      : "ax", "cx", "r11", "cc", "memory"); }) +#endif + + +#define lll_islocked(futex) \ +  (futex != LLL_MUTEX_LOCK_INITIALIZER) + + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex +   wakeup when the clone terminates.  The memory location contains the +   thread ID while the clone is running and is reset to zero +   afterwards. + +   The macro parameter must not have any side effect.  */ +#define lll_wait_tid(tid) \ +  do {									      \ +    int __ignore;							      \ +    register __typeof (tid) _tid __asm__ ("edx") = (tid);			      \ +    if (_tid != 0)							      \ +      __asm__ __volatile ("xorq %%r10, %%r10\n\t"				      \ +			"1:\tmovq %2, %%rax\n\t"			      \ +			"syscall\n\t"					      \ +			"cmpl $0, (%%rdi)\n\t"				      \ +			"jne 1b"					      \ +			: "=&a" (__ignore)				      \ +			: "S" (FUTEX_WAIT), "i" (SYS_futex), "D" (&tid),      \ +			  "d" (_tid)					      \ +			: "memory", "cc", "r10", "r11", "cx");		      \ +  } while (0) + +extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) +     attribute_hidden; +#define lll_timedwait_tid(tid, abstime) \ +  ({									      \ +    int __result = 0;							      \ +    if (tid != 0)							      \ +      {									      \ +	if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)	      \ +	  __result = EINVAL;						      \ +	else								      \ +	  __result = __lll_timedwait_tid (&tid, abstime);		      \ +      }									      \ +    __result; }) + + +/* Conditional variable handling.  */ + +extern void __lll_cond_wait (pthread_cond_t *cond) attribute_hidden; +extern int __lll_cond_timedwait (pthread_cond_t *cond, +				 const struct timespec *abstime) +     attribute_hidden; +extern void __lll_cond_wake (pthread_cond_t *cond) attribute_hidden; +extern void __lll_cond_broadcast (pthread_cond_t *cond) attribute_hidden; + + +#define lll_cond_wait(cond) \ +  __lll_cond_wait (cond) +#define lll_cond_timedwait(cond, abstime) \ +  __lll_cond_timedwait (cond, abstime) +#define lll_cond_wake(cond) \ +  __lll_cond_wake (cond) +#define lll_cond_broadcast(cond) \ +  __lll_cond_broadcast (cond) + + +#endif	/* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S new file mode 100644 index 000000000..02db0a4f9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S @@ -0,0 +1,306 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009 +   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 <sysdep.h> +#include <pthread-errnos.h> +#include <lowlevellock.h> +#include <lowlevelrobustlock.h> +#include <kernel-features.h> + +	.text + +#define FUTEX_WAITERS		0x80000000 +#define FUTEX_OWNER_DIED	0x40000000 + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_FUTEX_WAIT(reg) \ +	xorl	$(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +# define LOAD_FUTEX_WAIT_ABS(reg) \ +	xorl	$(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg +#else +# if FUTEX_WAIT == 0 +#  define LOAD_FUTEX_WAIT(reg) \ +	xorl	$FUTEX_PRIVATE_FLAG, reg ; \ +	andl	%fs:PRIVATE_FUTEX, reg +# else +#  define LOAD_FUTEX_WAIT(reg) \ +	xorl	$FUTEX_PRIVATE_FLAG, reg ; \ +	andl	%fs:PRIVATE_FUTEX, reg ; \ +	orl	$FUTEX_WAIT, reg +# endif +# define LOAD_FUTEX_WAIT_ABS(reg) \ +	xorl	$FUTEX_PRIVATE_FLAG, reg ; \ +	andl	%fs:PRIVATE_FUTEX, reg ; \ +	orl	$FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg +#endif + +/* For the calculation see asm/vsyscall.h.  */ +#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000 + + +	.globl	__lll_robust_lock_wait +	.type	__lll_robust_lock_wait,@function +	.hidden	__lll_robust_lock_wait +	.align	16 +__lll_robust_lock_wait: +	cfi_startproc +	pushq	%r10 +	cfi_adjust_cfa_offset(8) +	pushq	%rdx +	cfi_adjust_cfa_offset(8) +	cfi_offset(%r10, -16) +	cfi_offset(%rdx, -24) + +	xorq	%r10, %r10	/* No timeout.  */ +	LOAD_FUTEX_WAIT (%esi) + +4:	movl	%eax, %edx +	orl	$FUTEX_WAITERS, %edx + +	testl	$FUTEX_OWNER_DIED, %eax +	jnz	3f + +	cmpl	%edx, %eax +	je	1f + +	LOCK +	cmpxchgl %edx, (%rdi) +	jnz	2f + +1:	movl	$SYS_futex, %eax +	syscall + +	movl	(%rdi), %eax + +2:	testl	%eax, %eax +	jne	4b + +	movl	%fs:TID, %edx +	orl	$FUTEX_WAITERS, %edx +	LOCK +	cmpxchgl %edx, (%rdi) +	jnz	4b +	/* NB:	 %rax == 0 */ + +3:	popq	%rdx +	cfi_adjust_cfa_offset(-8) +	cfi_restore(%rdx) +	popq	%r10 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(%r10) +	retq +	cfi_endproc +	.size	__lll_robust_lock_wait,.-__lll_robust_lock_wait + + +	.globl	__lll_robust_timedlock_wait +	.type	__lll_robust_timedlock_wait,@function +	.hidden	__lll_robust_timedlock_wait +	.align	16 +__lll_robust_timedlock_wait: +	cfi_startproc +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +#  ifdef PIC +	cmpl	$0, __have_futex_clock_realtime(%rip) +#  else +	cmpl	$0, __have_futex_clock_realtime +#  endif +	je	.Lreltmo +# endif + +	pushq	%r9 +	cfi_adjust_cfa_offset(8) +	cfi_rel_offset(%r9, 0) +	movq	%rdx, %r10 +	movl	$0xffffffff, %r9d +	LOAD_FUTEX_WAIT_ABS (%esi) + +1:	testl	$FUTEX_OWNER_DIED, %eax +	jnz	3f + +	movl	%eax, %edx +	orl	$FUTEX_WAITERS, %edx + +	cmpl	%eax, %edx +	je	5f + +	LOCK +	cmpxchgl %edx, (%rdi) +	movq	$0, %rcx	/* Must use mov to avoid changing cc.  */ +	jnz	6f + +5:	movl	$SYS_futex, %eax +	syscall +	movl	%eax, %ecx + +	movl	(%rdi), %eax + +6:	testl	%eax, %eax +	jne	2f + +	movl	%fs:TID, %edx +	orl	$FUTEX_WAITERS, %edx +	LOCK +	cmpxchgl %edx, (%rdi) +	jnz	2f + +3:	popq	%r9 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(%r9) +	retq + +	cfi_adjust_cfa_offset(8) +	cfi_rel_offset(%r9, 0) +	/* Check whether the time expired.  */ +2:	cmpl	$-ETIMEDOUT, %ecx +	je	4f +	cmpl	$-EINVAL, %ecx +	jne	1b + +4:	movl	%ecx, %eax +	negl	%eax +	jmp	3b +	cfi_adjust_cfa_offset(-8) +	cfi_restore(%r9) + + +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +.Lreltmo: +	/* Check for a valid timeout value.  */ +	cmpq	$1000000000, 8(%rdx) +	jae	3f + +	pushq	%r8 +	cfi_adjust_cfa_offset(8) +	pushq	%r9 +	cfi_adjust_cfa_offset(8) +	pushq	%r12 +	cfi_adjust_cfa_offset(8) +	pushq	%r13 +	cfi_adjust_cfa_offset(8) +	cfi_offset(%r8, -16) +	cfi_offset(%r9, -24) +	cfi_offset(%r12, -32) +	cfi_offset(%r13, -40) +	pushq	%rsi +	cfi_adjust_cfa_offset(8) + +	/* Stack frame for the timespec and timeval structs.  */ +	subq	$32, %rsp +	cfi_adjust_cfa_offset(32) + +	movq	%rdi, %r12 +	movq	%rdx, %r13 + +1:	movq	%rax, 16(%rsp) + +	/* Get current time.  */ +	movq	%rsp, %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	/* This is a regular function call, all caller-save registers +	   might be clobbered.  */ +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	8(%rsp), %rax +	movl	$1000, %edi +	mul	%rdi		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rdi +	movq	8(%r13), %rsi +	subq	(%rsp), %rdi +	subq	%rax, %rsi +	jns	4f +	addq	$1000000000, %rsi +	decq	%rdi +4:	testq	%rdi, %rdi +	js	8f		/* Time is already up.  */ + +	/* Futex call.  */ +	movq	%rdi, (%rsp)	/* Store relative timeout.  */ +	movq	%rsi, 8(%rsp) + +	movq	16(%rsp), %rdx +	movl	%edx, %eax +	orl	$FUTEX_WAITERS, %edx + +	testl	$FUTEX_OWNER_DIED, %eax +	jnz	6f + +	cmpl	%eax, %edx +	je	2f + +	LOCK +	cmpxchgl %edx, (%r12) +	movq	$0, %rcx	/* Must use mov to avoid changing cc.  */ +	jnz	5f + +2:	movq	%rsp, %r10 +	movl	32(%rsp), %esi +	LOAD_FUTEX_WAIT (%esi) +	movq	%r12, %rdi +	movl	$SYS_futex, %eax +	syscall +	movq	%rax, %rcx + +	movl	(%r12), %eax + +5:	testl	%eax, %eax +	jne	7f + +	movl	%fs:TID, %edx +	orl	$FUTEX_WAITERS, %edx +	LOCK +	cmpxchgl %edx, (%r12) +	jnz	7f + +6:	addq	$40, %rsp +	cfi_adjust_cfa_offset(-40) +	popq	%r13 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(%r13) +	popq	%r12 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(%r12) +	popq	%r9 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(%r9) +	popq	%r8 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(%r8) +	retq + +3:	movl	$EINVAL, %eax +	retq + +	cfi_adjust_cfa_offset(72) +	cfi_offset(%r8, -16) +	cfi_offset(%r9, -24) +	cfi_offset(%r12, -32) +	cfi_offset(%r13, -40) +	/* Check whether the time expired.  */ +7:	cmpl	$-ETIMEDOUT, %ecx +	jne	1b + +8:	movl	$ETIMEDOUT, %eax +	jmp	6b +#endif +	cfi_endproc +	.size	__lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/not-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/not-cancel.h new file mode 100644 index 000000000..acf1a617e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/not-cancel.h @@ -0,0 +1 @@ +#include "../i386/not-cancel.h" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S new file mode 100644 index 000000000..c20ef73e7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S @@ -0,0 +1,31 @@ +/* Copyright (C) 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.  */ + +#define SAVE_PID \ +	movl	%fs:PID, %esi;						      \ +	movl	%esi, %edx;						      \ +	negl	%edx;							      \ +	movl	%edx, %fs:PID + +#define RESTORE_PID \ +	testq	%rax, %rax;						      \ +	je	1f;							      \ +	movl	%esi, %fs:PID;						      \ +1: + +#include <../../../../../../../libc/sysdeps/linux/x86_64/vfork.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S new file mode 100644 index 000000000..f6e15a2d7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S @@ -0,0 +1,159 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <lowlevelbarrier.h> + +#define FUTEX_WAIT	0 +#define FUTEX_WAKE	1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	pthread_barrier_wait +	.type	pthread_barrier_wait,@function +	.align	16 +pthread_barrier_wait: +	/* Get the mutex.  */ +	xorl	%eax, %eax +	movl	$1, %esi +	LOCK +	cmpxchgl %esi, MUTEX(%rdi) +	jnz	1f + +	/* One less waiter.  If this was the last one needed wake +	   everybody.  */ +2:	decl	LEFT(%rdi) +	je	3f + +	/* There are more threads to come.  */ +#if CURR_EVENT == 0 +	movl	(%rdi), %edx +#else +	movl	CURR_EVENT(%rdi), %edx +#endif + +	/* Release the mutex.  */ +	LOCK +	decl	MUTEX(%rdi) +	jne	6f + +	/* Wait for the remaining threads.  The call will return immediately +	   if the CURR_EVENT memory has meanwhile been changed.  */ +7: +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	xorq	%r10, %r10 +8:	movl	$SYS_futex, %eax +	syscall + +	/* Don't return on spurious wakeups.  The syscall does not change +	   any register except %eax so there is no need to reload any of +	   them.  */ +#if CURR_EVENT == 0 +	cmpl	%edx, (%rdi) +#else +	cmpl	%edx, CURR_EVENT(%rdi) +#endif +	je	8b + +	/* Increment LEFT.  If this brings the count back to the +	   initial count unlock the object.  */ +	movl	$1, %edx +	movl	INIT_COUNT(%rdi), %eax +	LOCK +	xaddl	%edx, LEFT(%rdi) +	subl	$1, %eax +	cmpl	%eax, %edx +	jne,pt	10f + +	/* Release the mutex.  We cannot release the lock before +	   waking the waiting threads since otherwise a new thread might +	   arrive and gets waken up, too.  */ +	LOCK +	decl	MUTEX(%rdi) +	jne	9f + +10:	xorl	%eax, %eax		/* != PTHREAD_BARRIER_SERIAL_THREAD */ + +	retq + +	/* The necessary number of threads arrived.  */ +3: +#if CURR_EVENT == 0 +	incl	(%rdi) +#else +	incl	CURR_EVENT(%rdi) +#endif + +	/* Wake up all waiters.  The count is a signed number in the kernel +	   so 0x7fffffff is the highest value.  */ +	movl	$0x7fffffff, %edx +	movl	$FUTEX_WAKE, %esi +	movl	$SYS_futex, %eax +	syscall + +	/* Increment LEFT.  If this brings the count back to the +	   initial count unlock the object.  */ +	movl	$1, %edx +	movl	INIT_COUNT(%rdi), %eax +	LOCK +	xaddl	%edx, LEFT(%rdi) +	subl	$1, %eax +	cmpl	%eax, %edx +	jne,pt	5f + +	/* Release the mutex.  We cannot release the lock before +	   waking the waiting threads since otherwise a new thread might +	   arrive and gets waken up, too.  */ +	LOCK +	decl	MUTEX(%rdi) +	jne	4f + +5:	orl	$-1, %eax		/* == PTHREAD_BARRIER_SERIAL_THREAD */ + +	retq + +1:	addq	$MUTEX, %rdi +	callq	__lll_mutex_lock_wait +	subq	$MUTEX, %rdi +	jmp	2b + +4:	addq	$MUTEX, %rdi +	callq	__lll_mutex_unlock_wake +	jmp	5b + +6:	addq	$MUTEX, %rdi +	callq	__lll_mutex_unlock_wake +	subq	$MUTEX, %rdi +	jmp	7b + +9:	addq	$MUTEX, %rdi +	callq	__lll_mutex_unlock_wake +	jmp	10b +	.size	pthread_barrier_wait,.-pthread_barrier_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S new file mode 100644 index 000000000..8f878b17e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S @@ -0,0 +1,136 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 +#define FUTEX_CMP_REQUEUE	4 + +#define EINVAL			22 + + +	.text + +	/* int pthread_cond_broadcast (pthread_cond_t *cond) */ +	.globl	__pthread_cond_broadcast +	.type	__pthread_cond_broadcast, @function +	.align	16 +__pthread_cond_broadcast: + +	/* Get internal lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jnz	1f + +2:	addq	$cond_futex, %rdi +	movq	total_seq-cond_futex(%rdi), %r9 +	cmpq	wakeup_seq-cond_futex(%rdi), %r9 +	jna	4f + +	/* Cause all currently waiting threads to recognize they are +	   woken up.  */ +	movq	%r9, wakeup_seq-cond_futex(%rdi) +	movq	%r9, woken_seq-cond_futex(%rdi) +	addq	%r9, %r9 +	movl	%r9d, (%rdi) +	incl	broadcast_seq-cond_futex(%rdi) + +	/* Get the address of the mutex used.  */ +	movq	dep_mutex-cond_futex(%rdi), %r8 + +	/* Unlock.  */ +	LOCK +	decl	cond_lock-cond_futex(%rdi) +	jne	7f + +8:	cmpq	$-1, %r8 +	je	9f + +	/* Wake up all threads.  */ +	movl	$FUTEX_CMP_REQUEUE, %esi +	movl	$SYS_futex, %eax +	movl	$1, %edx +	movl	$0x7fffffff, %r10d +	syscall + +	/* For any kind of error, which mainly is EAGAIN, we try again +	   with WAKE.  The general test also covers running on old +	   kernels.  */ +	cmpq	$-4095, %rax +	jae	9f + +10:	xorl	%eax, %eax +	retq + +	.align	16 +	/* Unlock.  */ +4:	LOCK +	decl	cond_lock-cond_futex(%rdi) +	jne	5f + +6:	xorl	%eax, %eax +	retq + +	/* Initial locking failed.  */ +1: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if cond_lock != 0 +	subq	$cond_lock, %rdi +#endif +	jmp	2b + +	/* Unlock in loop requires wakeup.  */ +5:	addq	$cond_lock-cond_futex, %rdi +	callq	__lll_mutex_unlock_wake +	jmp	6b + +	/* Unlock in loop requires wakeup.  */ +7:	addq	$cond_lock-cond_futex, %rdi +	callq	__lll_mutex_unlock_wake +	subq	$cond_lock-cond_futex, %rdi +	jmp	8b + +9:	/* The futex requeue functionality is not available.  */ +	movl	$0x7fffffff, %edx +	movl	$FUTEX_WAKE, %esi +	movl	$SYS_futex, %eax +	syscall +	jmp	10b +	.size	__pthread_cond_broadcast, .-__pthread_cond_broadcast +versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, +		  GLIBC_2_3_2) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S new file mode 100644 index 000000000..11a9e397e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S @@ -0,0 +1,102 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 + +#define EINVAL			22 + + +	.text + +	/* int pthread_cond_signal (pthread_cond_t *cond) */ +	.globl	__pthread_cond_signal +	.type	__pthread_cond_signal, @function +	.align	16 +__pthread_cond_signal: + +	/* Get internal lock.  */ +	movq	%rdi, %r8 +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jnz	1f + +2:	addq	$cond_futex, %rdi +	movq	total_seq(%r8), %rcx +	cmpq	wakeup_seq(%r8), %rcx +	jbe	4f + +	/* Bump the wakeup number.  */ +	addq	$1, wakeup_seq(%r8) +	addl	$1, (%rdi) + +	/* Wake up one thread.  */ +	movl	$FUTEX_WAKE, %esi +	movl	$SYS_futex, %eax +	movl	$1, %edx +	syscall + +	/* Unlock.  */ +4:	LOCK +#if cond_lock == 0 +	decl	(%r8) +#else +	decl	cond_lock(%r8) +#endif +	jne	5f + +6:	xorl	%eax, %eax +	retq + +	/* Initial locking failed.  */ +1: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if cond_lock != 0 +	subq	$cond_lock, %rdi +#endif +	jmp	2b + +	/* Unlock in loop requires wakeup.  */ +5: +	movq	%r8, %rdi +	callq	__lll_mutex_unlock_wake +	jmp	6b +	.size	__pthread_cond_signal, .-__pthread_cond_signal +versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, +		  GLIBC_2_3_2) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S new file mode 100644 index 000000000..f4fb61f70 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S @@ -0,0 +1,468 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <lowlevelcond.h> +#include <pthread-errnos.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +/* For the calculation see asm/vsyscall.h.  */ +#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000 + + +	.text + +/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, +			       const struct timespec *abstime)  */ +	.globl	__pthread_cond_timedwait +	.type	__pthread_cond_timedwait, @function +	.align	16 +__pthread_cond_timedwait: +.LSTARTCODE: +	pushq	%r12 +.Lpush_r12: +	pushq	%r13 +.Lpush_r13: +	pushq	%r14 +.Lpush_r14: +#define FRAME_SIZE 80 +	subq	$FRAME_SIZE, %rsp +.Lsubq: + +	cmpq	$1000000000, 8(%rdx) +	movl	$EINVAL, %eax +	jae	18f + +	/* Stack frame: + +	   rsp + 80 +	            +--------------------------+ +	   rsp + 48 | cleanup buffer           | +	            +--------------------------+ +	   rsp + 40 | old wake_seq value       | +	            +--------------------------+ +	   rsp + 24 | timeout value            | +	            +--------------------------+ +	   rsp + 16 | mutex pointer            | +	            +--------------------------+ +	   rsp +  8 | condvar pointer          | +	            +--------------------------+ +	   rsp +  4 | old broadcast_seq value  | +	            +--------------------------+ +	   rsp +  0 | old cancellation mode    | +	            +--------------------------+ +	*/ + +	cmpq	$-1, dep_mutex(%rdi) + +	/* Prepare structure passed to cancellation handler.  */ +	movq	%rdi, 8(%rsp) +	movq	%rsi, 16(%rsp) +	movq	%rdx, %r13 + +	je	22f +	movq	%rsi, dep_mutex(%rdi) + +	/* Get internal lock.  */ +22:	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jnz	1f + +	/* Unlock the mutex.  */ +2:	movq	16(%rsp), %rdi +	xorl	%esi, %esi +	callq	__pthread_mutex_unlock_usercnt + +	testl	%eax, %eax +	jne	16f + +	movq	8(%rsp), %rdi +	incq	total_seq(%rdi) +	incl	cond_futex(%rdi) +	addl	$(1 << clock_bits), cond_nwaiters(%rdi) + +	/* Install cancellation handler.  */ +#ifdef PIC +	leaq	__condvar_cleanup(%rip), %rsi +#else +	leaq	__condvar_cleanup, %rsi +#endif +	leaq	48(%rsp), %rdi +	movq	%rsp, %rdx +	callq	__pthread_cleanup_push + +	/* Get and store current wakeup_seq value.  */ +	movq	8(%rsp), %rdi +	movq	wakeup_seq(%rdi), %r9 +	movl	broadcast_seq(%rdi), %edx +	movq	%r9, 40(%rsp) +	movl	%edx, 4(%rsp) + +	/* Get the current time.  */ +8: +#ifdef __NR_clock_gettime +	/* Get the clock number.  Note that the field in the condvar +	   structure stores the number minus 1.  */ +	movq	8(%rsp), %rdi +	movl	cond_nwaiters(%rdi), %edi +	andl	$((1 << clock_bits) - 1), %edi +	/* Only clocks 0 and 1 are allowed so far.  Both are handled in the +	   kernel.  */ +	leaq	24(%rsp), %rsi +	movl	$__NR_clock_gettime, %eax +	syscall +# ifndef __ASSUME_POSIX_TIMERS +	cmpq	$-ENOSYS, %rax +	je	19f +# endif + +	/* Compute relative timeout.  */ +	movq	(%r13), %rcx +	movq	8(%r13), %rdx +	subq	24(%rsp), %rcx +	subq	32(%rsp), %rdx +#else +	leaq	24(%rsp), %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	32(%rsp), %rax +	movl	$1000, %edx +	mul	%rdx		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rcx +	movq	8(%r13), %rdx +	subq	24(%rsp), %rcx +	subq	%rax, %rdx +#endif +	jns	12f +	addq	$1000000000, %rdx +	decq	%rcx +12:	testq	%rcx, %rcx +	movq	8(%rsp), %rdi +	movq	$-ETIMEDOUT, %r14 +	js	6f + +	/* Store relative timeout.  */ +21:	movq	%rcx, 24(%rsp) +	movq	%rdx, 32(%rsp) + +	movl	cond_futex(%rdi), %r12d + +	/* Unlock.  */ +	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	jne	3f + +4:	callq	__pthread_enable_asynccancel +	movl	%eax, (%rsp) + +	leaq	24(%rsp), %r10 +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movq	%r12, %rdx +	addq	$cond_futex, %rdi +	movl	$SYS_futex, %eax +	syscall +	movq	%rax, %r14 + +	movl	(%rsp), %edi +	callq	__pthread_disable_asynccancel + +	/* Lock.  */ +	movq	8(%rsp), %rdi +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jne	5f + +6:	movl	broadcast_seq(%rdi), %edx + +	movq	woken_seq(%rdi), %rax + +	movq	wakeup_seq(%rdi), %r9 + +	cmpl	4(%rsp), %edx +	jne	23f + +	cmpq	40(%rsp), %r9 +	jbe	15f + +	cmpq	%rax, %r9 +	ja	9f + +15:	cmpq	$-ETIMEDOUT, %r14 +	jne	8b + +13:	incq	wakeup_seq(%rdi) +	incl	cond_futex(%rdi) +	movl	$ETIMEDOUT, %r14d +	jmp	14f + +23:	xorq	%r14, %r14 +	jmp	24f + +9:	xorq	%r14, %r14 +14:	incq	woken_seq(%rdi) + +24:	subl	$(1 << clock_bits), cond_nwaiters(%rdi) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	cmpq	$0xffffffffffffffff, total_seq(%rdi) +	jne	25f +	movl	cond_nwaiters(%rdi), %eax +	andl	$~((1 << clock_bits) - 1), %eax +	jne	25f + +	addq	$cond_nwaiters, %rdi +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %esi +	movl	$1, %edx +	syscall +	subq	$cond_nwaiters, %rdi + +25:	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	jne	10f + +	/* Remove cancellation handler.  */ +11:	movq	48+CLEANUP_PREV(%rsp), %rdx +	movq	%rdx, %fs:CLEANUP + +	movq	16(%rsp), %rdi +	callq	__pthread_mutex_cond_lock + +	testq	%rax, %rax +	cmoveq	%r14, %rax + +18:	addq	$FRAME_SIZE, %rsp +.Laddq: +	popq	%r14 +.Lpop_r14: +	popq	%r13 +.Lpop_r13: +	popq	%r12 +.Lpop_r12: + +	retq + +	/* Initial locking failed.  */ +1: +.LSbl1: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +	jmp	2b + +	/* Unlock in loop requires wakeup.  */ +3: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	4b + +	/* Locking in loop failed.  */ +5: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if cond_lock != 0 +	subq	$cond_lock, %rdi +#endif +	jmp	6b + +	/* Unlock after loop requires wakeup.  */ +10: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	11b + +	/* The initial unlocking of the mutex failed.  */ +16:	movq	8(%rsp), %rdi +	movq	%rax, (%rsp) +	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	jne	17f + +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake + +17:	movq	(%rsp), %rax +	jmp	18b + +#if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS +	/* clock_gettime not available.  */ +19:	leaq	24(%rsp), %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	32(%rsp), %rax +	movl	$1000, %edx +	mul	%rdx		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rcx +	movq	8(%r13), %rdx +	subq	24(%rsp), %rcx +	subq	%rax, %rdx +	jns	20f +	addq	$1000000000, %rdx +	decq	%rcx +20:	testq	%rcx, %rcx +	movq	8(%rsp), %rdi +	movq	$-ETIMEDOUT, %r14 +	js	6b +	jmp	21b +#endif +.LENDCODE: +	.size	__pthread_cond_timedwait, .-__pthread_cond_timedwait +versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, +		  GLIBC_2_3_2) + + +	.section .eh_frame,"a",@progbits +.LSTARTFRAME: +	.long	.LENDCIE-.LSTARTCIE		# Length of the CIE. +.LSTARTCIE: +	.long	0				# CIE ID. +	.byte	1				# Version number. +#ifdef SHARED +	.string	"zR"				# NUL-terminated augmentation +						# string. +#else +	.ascii	"\0"				# NUL-terminated augmentation +						# string. +#endif +	.uleb128 1				# Code alignment factor. +	.sleb128 -8				# Data alignment factor. +	.byte	16				# Return address register +						# column. +#ifdef SHARED +	.uleb128 1				# Augmentation value length. +	.byte	0x1b				# Encoding: DW_EH_PE_pcrel +						# + DW_EH_PE_sdata4. +#endif +	.byte 0x0c				# DW_CFA_def_cfa +	.uleb128 7 +	.uleb128 8 +	.byte	0x90				# DW_CFA_offset, column 0x8 +	.uleb128 1 +	.align 8 +.LENDCIE: + +	.long	.LENDFDE-.LSTARTFDE		# Length of the FDE. +.LSTARTFDE: +	.long	.LSTARTFDE-.LSTARTFRAME		# CIE pointer. +#ifdef SHARED +	.long	.LSTARTCODE-.			# PC-relative start address +						# of the code +#else +	.long	.LSTARTCODE			# Start address of the code. +#endif +	.long	.LENDCODE-.LSTARTCODE		# Length of the code. +#ifdef SHARED +	.uleb128 0				# No augmentation data. +#endif +	.byte	0x40+.Lpush_r12-.LSTARTCODE	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0x8c				# DW_CFA_offset %r12 +	.uleb128 2 +	.byte	0x40+.Lpush_r13-.Lpush_r12	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 24 +	.byte	0x8d				# DW_CFA_offset %r13 +	.uleb128 3 +	.byte	0x40+.Lpush_r14-.Lpush_r13	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 32 +	.byte	0x84				# DW_CFA_offset %r14 +	.uleb128 4 +	.byte	0x40+.Lsubq-.Lpush_r14		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 32+FRAME_SIZE +	.byte	3				# DW_CFA_advance_loc2 +	.2byte	.Laddq-.Lsubq +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 32 +	.byte	0x40+.Lpop_r14-.Laddq		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 24 +	.byte	0xce				# DW_CFA_restore %r14 +	.byte	0x40+.Lpop_r13-.Lpop_r14	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0xcd				# DW_CFA_restore %r13 +	.byte	0x40+.Lpop_r12-.Lpop_r13	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 8 +	.byte	0xcc				# DW_CFA_restore %r12 +	.byte	0x40+.LSbl1-.Lpop_r12		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 32+FRAME_SIZE +	.byte	0x8c				# DW_CFA_offset %r12 +	.uleb128 2 +	.byte	0x8d				# DW_CFA_offset %r13 +	.uleb128 3 +	.byte	0x84				# DW_CFA_offset %r14 +	.uleb128 4 +	.align	8 +.LENDFDE: diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S new file mode 100644 index 000000000..7c1c0e29c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S @@ -0,0 +1,420 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <lowlevelcond.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +	.align	16 +	.type	__condvar_cleanup, @function +	.globl	__condvar_cleanup +	.hidden	__condvar_cleanup +__condvar_cleanup: +	pushq	%r12 + +	/* Get internal lock.  */ +	movq	%rdi, %r8 +	movq	8(%rdi), %rdi +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jz	1f + +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if cond_lock != 0 +	subq	$cond_lock, %rdi +#endif + +1:	movl	broadcast_seq(%rdi), %edx +	cmpl	4(%r8), %edx +	jne	3f + +	incq	wakeup_seq(%rdi) +	incq	woken_seq(%rdi) +	incl	cond_futex(%rdi) + +3:	subl	$(1 << clock_bits), cond_nwaiters(%rdi) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	xorq	%r12, %r12 +	cmpq	$0xffffffffffffffff, total_seq(%rdi) +	jne	4f +	movl	cond_nwaiters(%rdi), %eax +	andl	$~((1 << clock_bits) - 1), %eax +	jne	4f + +	addq	$cond_nwaiters, %rdi +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %esi +	movl	$1, %edx +	syscall +	subq	$cond_nwaiters, %rdi +	movl	$1, %r12d + +4:	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	je	2f +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake + +	/* Wake up all waiters to make sure no signal gets lost.  */ +2:	testq	%r12, %r12 +	jnz	5f +	addq	$cond_futex, %rdi +	movl	$FUTEX_WAKE, %esi +	movl	$0x7fffffff, %edx +	movl	$SYS_futex, %eax +	syscall + +5:	movq	16(%r8), %rdi +	callq	__pthread_mutex_cond_lock + +	popq	%r12 + +	retq +	.size	__condvar_cleanup, .-__condvar_cleanup + + +/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */ +	.globl	__pthread_cond_wait +	.type	__pthread_cond_wait, @function +	.align	16 +__pthread_cond_wait: +.LSTARTCODE: +	pushq	%r12 +.Lpush_r12: +#define FRAME_SIZE 64 +	subq	$FRAME_SIZE, %rsp +.Lsubq: +	/* Stack frame: + +	   rsp + 64 +	            +--------------------------+ +	   rsp + 32 | cleanup buffer           | +		    +--------------------------+ +	   rsp + 24 | old wake_seq value       | +	            +--------------------------+ +	   rsp + 16 | mutex pointer            | +	            +--------------------------+ +	   rsp +  8 | condvar pointer          | +	            +--------------------------+ +	   rsp +  4 | old broadcast_seq value  | +	            +--------------------------+ +	   rsp +  0 | old cancellation mode    | +	            +--------------------------+ +	*/ + +	cmpq	$-1, dep_mutex(%rdi) + +		/* Prepare structure passed to cancellation handler.  */ +	movq	%rdi, 8(%rsp) +	movq	%rsi, 16(%rsp) + +	je	15f +	movq	%rsi, dep_mutex(%rdi) + +	/* Get internal lock.  */ +15:	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jne	1f + +	/* Unlock the mutex.  */ +2:	movq	16(%rsp), %rdi +	xorl	%esi, %esi +	callq	__pthread_mutex_unlock_usercnt + +	testl	%eax, %eax +	jne	12f + +	movq	8(%rsp), %rdi +	incq	total_seq(%rdi) +	incl	cond_futex(%rdi) +	addl	$(1 << clock_bits), cond_nwaiters(%rdi) + +	/* Install cancellation handler.  */ +#ifdef PIC +	leaq	__condvar_cleanup(%rip), %rsi +#else +	leaq	__condvar_cleanup, %rsi +#endif +	leaq	32(%rsp), %rdi +	movq	%rsp, %rdx +	callq	__pthread_cleanup_push + +	/* Get and store current wakeup_seq value.  */ +	movq	8(%rsp), %rdi +	movq	wakeup_seq(%rdi), %r9 +	movl	broadcast_seq(%rdi), %edx +	movq	%r9, 24(%rsp) +	movl	%edx, 4(%rsp) + +	/* Unlock.  */ +8:	movl	cond_futex(%rdi), %r12d +	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	jne	3f + +4:	callq	__pthread_enable_asynccancel +	movl	%eax, (%rsp) + +	movq	8(%rsp), %rdi +	xorq	%r10, %r10 +	movq	%r12, %rdx +	addq	$cond_futex-cond_lock, %rdi +	movl	$SYS_futex, %eax +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	syscall + +	movl	(%rsp), %edi +	callq	__pthread_disable_asynccancel + +	/* Lock.  */ +	movq	8(%rsp), %rdi +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jnz	5f + +6:	movl	broadcast_seq(%rdi), %edx + +	movq	woken_seq(%rdi), %rax + +	movq	wakeup_seq(%rdi), %r9 + +	cmpl	4(%rsp), %edx +	jne	16f + +	cmpq	24(%rsp), %r9 +	jbe	8b + +	cmpq	%rax, %r9 +	jna	8b + +	incq	woken_seq(%rdi) + +	/* Unlock */ +16:	subl	$(1 << clock_bits), cond_nwaiters(%rdi) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	cmpq	$0xffffffffffffffff, total_seq(%rdi) +	jne	17f +	movl	cond_nwaiters(%rdi), %eax +	andl	$~((1 << clock_bits) - 1), %eax +	jne	17f + +	addq	$cond_nwaiters, %rdi +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %esi +	movl	$1, %edx +	syscall +	subq	$cond_nwaiters, %rdi + +17:	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	jne	10f + +	/* Remove cancellation handler.  */ +11:	movq	32+CLEANUP_PREV(%rsp), %rdx +	movq	%rdx, %fs:CLEANUP + +	movq	16(%rsp), %rdi +	callq	__pthread_mutex_cond_lock +14:	addq	$FRAME_SIZE, %rsp +.Laddq: + +	popq	%r12 +.Lpop_r12: + +	/* We return the result of the mutex_lock operation.  */ +	retq + +	/* Initial locking failed.  */ +1: +.LSbl1: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +	jmp	2b + +	/* Unlock in loop requires wakeup.  */ +3: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	4b + +	/* Locking in loop failed.  */ +5: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if cond_lock != 0 +	subq	$cond_lock, %rdi +#endif +	jmp	6b + +	/* Unlock after loop requires wakeup.  */ +10: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	11b + +	/* The initial unlocking of the mutex failed.  */ +12:	movq	%rax, %r10 +	movq	8(%rsp), %rdi +	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	jne	13f + +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake + +13:	movq	%r10, %rax +	jmp	14b +.LENDCODE: +	.size	__pthread_cond_wait, .-__pthread_cond_wait +versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, +		  GLIBC_2_3_2) + + +	.section .eh_frame,"a",@progbits +.LSTARTFRAME: +	.long	.LENDCIE-.LSTARTCIE		# Length of the CIE. +.LSTARTCIE: +	.long	0				# CIE ID. +	.byte	1				# Version number. +#ifdef SHARED +	.string	"zR"				# NUL-terminated augmentation +						# string. +#else +	.ascii	"\0"				# NUL-terminated augmentation +						# string. +#endif +	.uleb128 1				# Code alignment factor. +	.sleb128 -8				# Data alignment factor. +	.byte	16				# Return address register +						# column. +#ifdef SHARED +	.uleb128 1				# Augmentation value length. +	.byte	0x1b				# Encoding: DW_EH_PE_pcrel +						# + DW_EH_PE_sdata4. +#endif +	.byte 0x0c				# DW_CFA_def_cfa +	.uleb128 7 +	.uleb128 8 +	.byte	0x90				# DW_CFA_offset, column 0x8 +	.uleb128 1 +	.align 8 +.LENDCIE: + +	.long	.LENDFDE-.LSTARTFDE		# Length of the FDE. +.LSTARTFDE: +	.long	.LSTARTFDE-.LSTARTFRAME		# CIE pointer. +#ifdef SHARED +	.long	.LSTARTCODE-.			# PC-relative start address +						# of the code +#else +	.long	.LSTARTCODE			# Start address of the code. +#endif +	.long	.LENDCODE-.LSTARTCODE		# Length of the code. +#ifdef SHARED +	.uleb128 0				# No augmentation data. +#endif +	.byte	0x40+.Lpush_r12-.LSTARTCODE	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0x8c				# DW_CFA_offset %r12 +	.uleb128 2 +	.byte	0x40+.Lsubq-.Lpush_r12		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16+FRAME_SIZE +	.byte	3				# DW_CFA_advance_loc2 +	.2byte	.Laddq-.Lsubq +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0x40+.Lpop_r12-.Laddq		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 8 +	.byte	0xcc				# DW_CFA_restore %r12 +	.byte	0x40+.LSbl1-.Lpop_r12		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 80 +	.byte	0x8c				# DW_CFA_offset %r12 +	.uleb128 2 +	.align	8 +.LENDFDE: diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S new file mode 100644 index 000000000..3fb89e419 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S @@ -0,0 +1,257 @@ +/* Copyright (C) 2002, 2003, 2005 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 UP +# define LOCK lock +#else +# define LOCK +#endif + +#define FUTEX_WAIT  0 +#define FUTEX_WAKE	1 + +	.comm	__fork_generation, 4, 4 + +	.text + + +	.globl	__pthread_once +	.type	__pthread_once,@function +	.align	16 +__pthread_once: +.LSTARTCODE: +	testl	$2, (%rdi) +	jz	1f +	xorl	%eax, %eax +	retq + +	/* Preserve the function pointer.  */ +1:	pushq	%rsi +.Lpush_rsi: +	xorq	%r10, %r10 + +	/* Not yet initialized or initialization in progress. +	   Get the fork generation counter now.  */ +6:	movl	(%rdi), %eax + +5:	movl	%eax, %edx + +	testl	$2, %eax +	jnz	4f + +	andl	$3, %edx +	orl	__fork_generation(%rip), %edx +	orl	$1, %edx + +	LOCK +	cmpxchgl %edx, (%rdi) +	jnz	5b + +	/* Check whether another thread already runs the initializer.  */ +	testl	$1, %eax +	jz	3f	/* No -> do it.  */ + +	/* Check whether the initializer execution was interrupted +	   by a fork.  */ +	xorl	%edx, %eax +	testl	$0xfffffffc, %eax +	jnz	3f	/* Different for generation -> run initializer.  */ + +	/* Somebody else got here first.  Wait.  */ +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movl	$SYS_futex, %eax +	syscall +	jmp	6b + +	/* Preserve the pointer to the control variable.  */ +3:	pushq	%rdi +.Lpush_rdi: + +.LcleanupSTART: +	callq	*8(%rsp) +.LcleanupEND: + +	/* Get the control variable address back.  */ +	popq	%rdi +.Lpop_rdi: + +	/* Sucessful run of the initializer.  Signal that we are done.  */ +	LOCK +	incl	(%rdi) + +	/* Wake up all other threads.  */ +	movl	$0x7fffffff, %edx +	movl	$FUTEX_WAKE, %esi +	movl	$SYS_futex, %eax +	syscall + +4:	addq	$8, %rsp +.Ladd: +	xorl	%eax, %eax +	retq + +	.size	__pthread_once,.-__pthread_once + + +	.globl	__pthread_once_internal +__pthread_once_internal = __pthread_once + +	.globl	pthread_once +pthread_once = __pthread_once + + +	.type	clear_once_control,@function +	.align	16 +clear_once_control: +	movq	(%rsp), %rdi +	movq	%rax, %r8 +	movl	$0, (%rdi) + +	movl	$0x7fffffff, %edx +	movl	$FUTEX_WAKE, %esi +	movl	$SYS_futex, %eax +	syscall + +	movq	%r8, %rdi +.LcallUR: +	call	_Unwind_Resume@PLT +	hlt +.LENDCODE: +	.size	clear_once_control,.-clear_once_control + + +	.section .gcc_except_table,"a",@progbits +.LexceptSTART: +	.byte	0xff				# @LPStart format (omit) +	.byte	0xff				# @TType format (omit) +	.byte	0x01				# call-site format +						# DW_EH_PE_uleb128 +	.uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: +	.uleb128 .LcleanupSTART-.LSTARTCODE +	.uleb128 .LcleanupEND-.LcleanupSTART +	.uleb128 clear_once_control-.LSTARTCODE +	.uleb128  0 +	.uleb128 .LcallUR-.LSTARTCODE +	.uleb128 .LENDCODE-.LcallUR +	.uleb128 0 +	.uleb128  0 +.Lcstend: + + +	.section .eh_frame,"a",@progbits +.LSTARTFRAME: +	.long	.LENDCIE-.LSTARTCIE		# Length of the CIE. +.LSTARTCIE: +	.long	0				# CIE ID. +	.byte	1				# Version number. +#ifdef SHARED +	.string	"zPLR"				# NUL-terminated augmentation +						# string. +#else +	.string	"zPL"				# NUL-terminated augmentation +						# string. +#endif +	.uleb128 1				# Code alignment factor. +	.sleb128 -8				# Data alignment factor. +	.byte	16				# Return address register +						# column. +#ifdef SHARED +	.uleb128 7				# Augmentation value length. +	.byte	0x9b				# Personality: DW_EH_PE_pcrel +						# + DW_EH_PE_sdata4 +						# + DW_EH_PE_indirect +	.long	DW.ref.__gcc_personality_v0-. +	.byte	0x1b				# LSDA Encoding: DW_EH_PE_pcrel +						# + DW_EH_PE_sdata4. +	.byte	0x1b				# FDE Encoding: DW_EH_PE_pcrel +						# + DW_EH_PE_sdata4. +#else +	.uleb128 10				# Augmentation value length. +	.byte	0x0				# Personality: absolute +	.quad	__gcc_personality_v0 +	.byte	0x0				# LSDA Encoding: absolute +#endif +	.byte 0x0c				# DW_CFA_def_cfa +	.uleb128 7 +	.uleb128 8 +	.byte	0x90				# DW_CFA_offset, column 0x10 +	.uleb128 1 +	.align 8 +.LENDCIE: + +	.long	.LENDFDE-.LSTARTFDE		# Length of the FDE. +.LSTARTFDE: +	.long	.LSTARTFDE-.LSTARTFRAME		# CIE pointer. +#ifdef SHARED +	.long	.LSTARTCODE-.			# PC-relative start address +						# of the code. +	.long	.LENDCODE-.LSTARTCODE		# Length of the code. +	.uleb128 4				# Augmentation size +	.long	.LexceptSTART-. +#else +	.quad	.LSTARTCODE			# Start address of the code. +	.quad	.LENDCODE-.LSTARTCODE		# Length of the code. +	.uleb128 8				# Augmentation size +	.quad	.LexceptSTART +#endif +	.byte	4				# DW_CFA_advance_loc4 +	.long	.Lpush_rsi-.LSTARTCODE +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	4				# DW_CFA_advance_loc4 +	.long	.Lpush_rdi-.Lpush_rsi +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 24 +	.byte	4				# DW_CFA_advance_loc4 +	.long	.Lpop_rdi-.Lpush_rdi +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	4				# DW_CFA_advance_loc4 +	.long	.Ladd-.Lpop_rdi +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 8 +	.byte	4				# DW_CFA_advance_loc4 +	.long	clear_once_control-.Ladd +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 24 +#if 0 +	.byte	4				# DW_CFA_advance_loc4 +	.long	.Lpop_rdi2-clear_once_control +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +#endif +	.align	8 +.LENDFDE: + + +#ifdef SHARED +	.hidden	DW.ref.__gcc_personality_v0 +	.weak	DW.ref.__gcc_personality_v0 +	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +	.align	8 +	.type	DW.ref.__gcc_personality_v0, @object +	.size	DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: +	.quad	__gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S new file mode 100644 index 000000000..524da36f6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S @@ -0,0 +1,176 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> + + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	__pthread_rwlock_rdlock +	.type	__pthread_rwlock_rdlock,@function +	.align	16 +__pthread_rwlock_rdlock: +	xorq	%r10, %r10 + +	/* Get the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	1f + +2:	movl	WRITER(%rdi), %eax +	testl	%eax, %eax +	jne	14f +	cmpl	$0, WRITERS_QUEUED(%rdi) +	je	5f +	cmpl	$0, FLAGS(%rdi) +	je	5f + +3:	incl	READERS_QUEUED(%rdi) +	je	4f + +	movl	READERS_WAKEUP(%rdi), %edx + +	LOCK +#if MUTEX == 0 +	decl	(%rdi) +#else +	decl	MUTEX(%rdi) +#endif +	jne	10f + +11:	addq	$READERS_WAKEUP, %rdi +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movl	$SYS_futex, %eax +	syscall + +	subq	$READERS_WAKEUP, %rdi + +	/* Reget the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	12f + +13:	decl	READERS_QUEUED(%rdi) +	jmp	2b + +5:	xorl	%edx, %edx +	incl	NR_READERS(%rdi) +	je	8f +9:	LOCK +#if MUTEX == 0 +	decl	(%rdi) +#else +	decl	MUTEX(%rdi) +#endif +	jne	6f +7: + +	movq	%rdx, %rax +	retq + +1: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	2b + +14:	cmpl	%fs:TID, %eax +	jne	3b +	/* Deadlock detected.  */ +	movl	$EDEADLK, %edx +	jmp	9b + +6: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_unlock_wake +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	7b + +	/* Overflow.  */ +8:	decl	NR_READERS(%rdi) +	movl	$EAGAIN, %edx +	jmp	9b + +	/* Overflow.  */ +4:	decl	READERS_QUEUED(%rdi) +	movl	$EAGAIN, %edx +	jmp	9b + +10: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_unlock_wake +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	11b + +12: +#if MUTEX == 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	13b +	.size	__pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock + +	.globl	pthread_rwlock_rdlock +pthread_rwlock_rdlock = __pthread_rwlock_rdlock + +	.globl	__pthread_rwlock_rdlock_internal +__pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S new file mode 100644 index 000000000..29696e7da --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S @@ -0,0 +1,219 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> + + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +/* For the calculation see asm/vsyscall.h.  */ +#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000 + + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	pthread_rwlock_timedrdlock +	.type	pthread_rwlock_timedrdlock,@function +	.align	16 +pthread_rwlock_timedrdlock: +	pushq	%r12 +	pushq	%r13 +	pushq	%r14 +	subq	$16, %rsp + +	movq	%rdi, %r12 +	movq	%rsi, %r13 + +	/* Get the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	1f + +2:	movl	WRITER(%r12), %eax +	testl	%eax, %eax +	jne	14f +	cmpl	$0, WRITERS_QUEUED(%r12) +	je	5f +	cmpl	$0, FLAGS(%r12) +	je	5f + +	/* Check the value of the timeout parameter.  */ +3:	cmpq	$1000000000, 8(%r13) +	jae	19f + +	incl	READERS_QUEUED(%r12) +	je	4f + +	movl	READERS_WAKEUP(%r12), %r14d + +	/* Unlock.  */ +	LOCK +#if MUTEX == 0 +	decl	(%r12) +#else +	decl	MUTEX(%r12) +#endif +	jne	10f + +	/* Get current time.  */ +11:	movq	%rsp, %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	8(%rsp), %rax +	movl	$1000, %edi +	mul	%rdi		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rcx +	movq	8(%r13), %rdi +	subq	(%rsp), %rcx +	subq	%rax, %rdi +	jns	15f +	addq	$1000000000, %rdi +	decq	%rcx +15:	testq	%rcx, %rcx +	js	16f		/* Time is already up.  */ + +	/* Futex call.  */ +	movq	%rcx, (%rsp)	/* Store relative timeout.  */ +	movq	%rdi, 8(%rsp) + +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movq	%rsp, %r10 +	movl	%r14d, %edx +	leaq	READERS_WAKEUP(%r12), %rdi +	movl	$SYS_futex, %eax +	syscall +	movq	%rax, %rdx +17: + +	/* Reget the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%r12) +#else +	cmpxchgl %esi, MUTEX(%r12) +#endif +	jnz	12f + +13:	decl	READERS_QUEUED(%r12) +	cmpq	$-ETIMEDOUT, %rdx +	jne	2b + +18:	movl	$ETIMEDOUT, %edx +	jmp	9f + + +5:	xorl	%edx, %edx +	incl	NR_READERS(%r12) +	je	8f +9:	LOCK +#if MUTEX == 0 +	decl	(%r12) +#else +	decl	MUTEX(%r12) +#endif +	jne	6f + +7:	movq	%rdx, %rax + +	addq	$16, %rsp +	popq	%r14 +	popq	%r13 +	popq	%r12 +	retq + +1: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +	jmp	2b + +14:	cmpl	%fs:TID, %eax +	jne	3b +	movl	$EDEADLK, %edx +	jmp	9b + +6: +#if MUTEX == 0 +	movq	%r12, %rdi +#else +	leal	MUTEX(%r12), %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	7b + +	/* Overflow.  */ +8:	decl	NR_READERS(%r12) +	movl	$EAGAIN, %edx +	jmp	9b + +	/* Overflow.  */ +4:	decl	READERS_QUEUED(%r12) +	movl	$EAGAIN, %edx +	jmp	9b + +10: +#if MUTEX == 0 +	movq	%r12, %rdi +#else +	leaq	MUTEX(%r12), %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	11b + +12: +#if MUTEX == 0 +	movq	%r12, %rdi +#else +	leaq	MUTEX(%r12), %rdi +#endif +	callq	__lll_mutex_lock_wait +	jmp	13b + +16:	movq	$-ETIMEDOUT, %rdx +	jmp	17b + +19:	movl	$EINVAL, %edx +	jmp	9b +	.size	pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S new file mode 100644 index 000000000..b6b91f908 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S @@ -0,0 +1,210 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> + + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +/* For the calculation see asm/vsyscall.h.  */ +#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	pthread_rwlock_timedwrlock +	.type	pthread_rwlock_timedwrlock,@function +	.align	16 +pthread_rwlock_timedwrlock: +	pushq	%r12 +	pushq	%r13 +	pushq	%r14 +	subq	$16, %rsp + +	movq	%rdi, %r12 +	movq	%rsi, %r13 + +	/* Get the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	1f + +2:	movl	WRITER(%r12), %eax +	testl	%eax, %eax +	jne	14f +	cmpl	$0, NR_READERS(%r12) +	je	5f + +	/* Check the value of the timeout parameter.  */ +3:	cmpq	$1000000000, 8(%r13) +	jae	19f + +	incl	WRITERS_QUEUED(%r12) +	je	4f + +	movl	WRITERS_WAKEUP(%r12), %r14d + +	LOCK +#if MUTEX == 0 +	decl	(%r12) +#else +	decl	MUTEX(%r12) +#endif +	jne	10f + +	/* Get current time.  */ +11:	movq	%rsp, %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	8(%rsp), %rax +	movl	$1000, %edi +	mul	%rdi		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rcx +	movq	8(%r13), %rdi +	subq	(%rsp), %rcx +	subq	%rax, %rdi +	jns	15f +	addq	$1000000000, %rdi +	decq	%rcx +15:	testq	%rcx, %rcx +	js	16f		/* Time is already up.  */ + +	/* Futex call.  */ +	movq	%rcx, (%rsp)	/* Store relative timeout.  */ +	movq	%rdi, 8(%rsp) + +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movq	%rsp, %r10 +	movl	%r14d, %edx +	leaq	WRITERS_WAKEUP(%r12), %rdi +	movl	$SYS_futex, %eax +	syscall +	movq	%rax, %rdx +17: + +	/* Reget the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%r12) +#else +	cmpxchgl %esi, MUTEX(%r12) +#endif +	jnz	12f + +13:	decl	WRITERS_QUEUED(%r12) +	cmpq	$-ETIMEDOUT, %rdx +	jne	2b + +18:	movl	$ETIMEDOUT, %edx +	jmp	9f + + +5:	xorl	%edx, %edx +	movl	%fs:TID, %eax +	movl	%eax, WRITER(%r12) +9:	LOCK +#if MUTEX == 0 +	decl	(%r12) +#else +	decl	MUTEX(%r12) +#endif +	jne	6f + +7:	movq	%rdx, %rax + +	addq	$16, %rsp +	popq	%r14 +	popq	%r13 +	popq	%r12 +	retq + +1: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +	jmp	2b + +14:	cmpl	%fs:TID, %eax +	jne	3b +20:	movl	$EDEADLK, %edx +	jmp	9b + +6: +#if MUTEX == 0 +	movq	%r12, %rdi +#else +	leal	MUTEX(%r12), %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	7b + +	/* Overflow.  */ +4:	decl	WRITERS_QUEUED(%r12) +	movl	$EAGAIN, %edx +	jmp	9b + +10: +#if MUTEX == 0 +	movq	%r12, %rdi +#else +	leaq	MUTEX(%r12), %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	11b + +12: +#if MUTEX == 0 +	movq	%r12, %rdi +#else +	leaq	MUTEX(%r12), %rdi +#endif +	callq	__lll_mutex_lock_wait +	jmp	13b + +16:	movq	$-ETIMEDOUT, %rdx +	jmp	17b + +19:	movl	$EINVAL, %edx +	jmp	9b +	.size	pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S new file mode 100644 index 000000000..a0f75226a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S @@ -0,0 +1,129 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <lowlevelrwlock.h> + + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	__pthread_rwlock_unlock +	.type	__pthread_rwlock_unlock,@function +	.align	16 +__pthread_rwlock_unlock: +	/* Get the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	1f + +2:	cmpl	$0, WRITER(%rdi) +	jne	5f +	decl	NR_READERS(%rdi) +	jnz	6f + +5:	movl	$0, WRITER(%rdi) + +	movl	$1, %esi +	leaq	WRITERS_WAKEUP(%rdi), %r10 +	movq	%rsi, %rdx +	cmpl	$0, WRITERS_QUEUED(%rdi) +	jne	0f + +	/* If also no readers waiting nothing to do.  */ +	cmpl	$0, READERS_QUEUED(%rdi) +	je	6f + +	movl	$0x7fffffff, %edx +	leaq	READERS_WAKEUP(%rdi), %r10 + +0:	incl	(%r10) +	LOCK +#if MUTEX == 0 +	decl	(%rdi) +#else +	decl	MUTEX(%rdi) +#endif +	jne	7f + +8:	movl	$SYS_futex, %eax +	movq	%r10, %rdi +	syscall + +	xorl	%eax, %eax +	retq + +	.align	16 +6:	LOCK +#if MUTEX == 0 +	decl	(%rdi) +#else +	decl	MUTEX(%rdi) +#endif +	jne	3f + +4:	xorl	%eax, %eax +	retq + +1: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	2b + +3: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	4b + +7: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	8b + +	.size	__pthread_rwlock_unlock,.-__pthread_rwlock_unlock + +	.globl	pthread_rwlock_unlock +pthread_rwlock_unlock = __pthread_rwlock_unlock + +	.globl	__pthread_rwlock_unlock_internal +__pthread_rwlock_unlock_internal = __pthread_rwlock_unlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S new file mode 100644 index 000000000..c675c769e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S @@ -0,0 +1,164 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> + + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	__pthread_rwlock_wrlock +	.type	__pthread_rwlock_wrlock,@function +	.align	16 +__pthread_rwlock_wrlock: +	xorq	%r10, %r10 + +	/* Get the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	1f + +2:	movl	WRITER(%rdi), %eax +	testl	%eax, %eax +	jne	14f +	cmpl	$0, NR_READERS(%rdi) +	je	5f + +3:	incl	WRITERS_QUEUED(%rdi) +	je	4f + +	movl	WRITERS_WAKEUP(%rdi), %edx + +	LOCK +#if MUTEX == 0 +	decl	(%rdi) +#else +	decl	MUTEX(%rdi) +#endif +	jne	10f + +11:	addq	$WRITERS_WAKEUP, %rdi +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movl	$SYS_futex, %eax +	syscall + +	subq	$WRITERS_WAKEUP, %rdi + +	/* Reget the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	12f + +13:	decl	WRITERS_QUEUED(%rdi) +	jmp	2b + +5:	xorl	%edx, %edx +	movl	%fs:TID, %eax +	movl	%eax, WRITER(%rdi) +9:	LOCK +#if MUTEX == 0 +	decl	(%rdi) +#else +	decl	MUTEX(%rdi) +#endif +	jne	6f +7: + +	movq	%rdx, %rax +	retq + +1: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	2b + +14:	cmpl	%fs:TID, %eax +	jne	3b +	movl	$EDEADLK, %edx +	jmp	9b + +6: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	7b + +4:	decl	WRITERS_QUEUED(%rdi) +	movl	$EAGAIN, %edx +	jmp	9b + +10: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_unlock_wake +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	11b + +12: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	13b +	.size	__pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock + +	.globl	pthread_rwlock_wrlock +pthread_rwlock_wrlock = __pthread_rwlock_wrlock + +	.globl	__pthread_rwlock_wrlock_internal +__pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_setaffinity.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_setaffinity.c new file mode 100644 index 000000000..640d3044f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_setaffinity.c @@ -0,0 +1,14 @@ +#include <tls.h> + +#define RESET_VGETCPU_CACHE() \ +  do {			      \ +    asm volatile ("movl %0, %%fs:%P1\n\t"				      \ +		  "movl %0, %%fs:%P2"					      \ +		  :							      \ +		  : "ir" (0), "i" (offsetof (struct pthread,		      \ +					     header.vgetcpu_cache[0])),	      \ +		    "i" (offsetof (struct pthread,			      \ +				   header.vgetcpu_cache[1])));		\ +  } while (0) + +#include "../pthread_setaffinity.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c new file mode 100644 index 000000000..483de8cac --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c @@ -0,0 +1 @@ +#include <sysdeps/x86_64/pthread_spin_init.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S new file mode 100644 index 000000000..7da1c75dc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S @@ -0,0 +1 @@ +#include <nptl/sysdeps/x86_64/pthread_spin_unlock.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S new file mode 100644 index 000000000..5c8a858ad --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S @@ -0,0 +1,64 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define FUTEX_WAKE		1 + + +	.text + +	.globl	sem_post +	.type	sem_post,@function +	.align	16 +sem_post: +	movl	$1, %edx +	LOCK +	xaddl	%edx, (%rdi) + +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %esi +	incl	%edx +	syscall + +	testq	%rax, %rax +	js	1f + +	xorl	%eax, %eax +	retq + +1: +#if USE___THREAD +	movq	errno@gottpoff(%rip), %rdx +	movl	$EINVAL, %fs:(%rdx) +#else +	callq	__errno_location@plt +	movl	$EINVAL, (%rax) +#endif + +	orl	$-1, %eax +	retq +	.size	sem_post,.-sem_post diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S new file mode 100644 index 000000000..e5fbf8eb2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S @@ -0,0 +1,172 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +/* For the calculation see asm/vsyscall.h.  */ +#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000 + + +	.text + +	.globl	sem_timedwait +	.type	sem_timedwait,@function +	.align	16 +	cfi_startproc +sem_timedwait: +	/* First check for cancellation.  */ +	movl	%fs:CANCELHANDLING, %eax +	andl	$0xfffffff9, %eax +	cmpl	$8, %eax +	je	11f + +	movl	(%rdi), %eax +2:	testl	%eax, %eax +	je	1f + +	leaq	-1(%rax), %rdx +	LOCK +	cmpxchgl %edx, (%rdi) +	jne	2b + +	xorl	%eax, %eax +	retq + +	/* Check whether the timeout value is valid.  */ +1:	pushq	%r12 +	cfi_adjust_cfa_offset(8) +	pushq	%r13 +	cfi_adjust_cfa_offset(8) +	pushq	%r14 +	cfi_adjust_cfa_offset(8) +	subq	$24, %rsp +	cfi_adjust_cfa_offset(24) + +	movq	%rdi, %r12 +	cfi_offset(12, -16)		/* %r12 */ +	movq	%rsi, %r13 +	cfi_offset(13, -24)		/* %r13 */ + +	/* Check for invalid nanosecond field.  */ +	cmpq	$1000000000, 8(%r13) +	movl	$EINVAL, %r14d +	cfi_offset(14, -24)		/* %r14 */ +	jae	6f + +7:	call	__pthread_enable_asynccancel +	movl	%eax, 16(%rsp) + +	xorl	%esi, %esi +	movq	%rsp, %rdi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	8(%rsp), %rax +	movl	$1000, %edi +	mul	%rdi		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rdi +	movq	8(%r13), %rsi +	subq	(%rsp), %rdi +	subq	%rax, %rsi +	jns	5f +	addq	$1000000000, %rsi +	decq	%rdi +5:	testq	%rdi, %rdi +	movl	$ETIMEDOUT, %r14d +	js	6f		/* Time is already up.  */ + +	movq	%rdi, (%rsp)	/* Store relative timeout.  */ +	movq	%rsi, 8(%rsp) + +	movq	%rsp, %r10 +	movq	%r12, %rdi +	xorl	%esi, %esi +	movl	$SYS_futex, %eax +	xorl	%edx, %edx +	syscall +	movq	%rax, %r14 + +	movl	16(%rsp), %edi +	call	__pthread_disable_asynccancel + +	testq	%r14, %r14 +	je	9f +	cmpq	$-EWOULDBLOCK, %r14 +	jne	3f + +9:	movl	(%r12), %eax +8:	testl	%eax, %eax +	je	7b + +	leaq	-1(%rax), %rcx +	LOCK +	cmpxchgl %ecx, (%r12) +	jne	8b + +	xorl	%eax, %eax +10:	addq	$24, %rsp +	cfi_adjust_cfa_offset(-24) +	popq	%r14 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(14) +	popq	%r13 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(13) +	popq	%r12 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(12) +	retq + +	cfi_adjust_cfa_offset(48) +	cfi_offset(12, -16)		/* %r12 */ +	cfi_offset(13, -24)		/* %r13 */ +	cfi_offset(14, -32)		/* %r14 */ +3:	negq	%r14 +6: +#if USE___THREAD +	movq	errno@gottpoff(%rip), %rdx +	movl	%r14d, %fs:(%rdx) +#else +	callq	__errno_location@plt +	movl	%r14d, (%rax) +#endif + +	orl	$-1, %eax +	jmp	10b +	cfi_adjust_cfa_offset(-48) +	cfi_restore(14) +	cfi_restore(13) +	cfi_restore(12) + +11:	/* Canceled.  */ +	movq	$0xffffffffffffffff, %fs:RESULT +	LOCK +	orl	$0x10, %fs:CANCELHANDLING +	movq	%fs:CLEANUP_JMP_BUF, %rdi +	jmp	HIDDEN_JUMPTARGET (__pthread_unwind) +	cfi_endproc +	.size	sem_timedwait,.-sem_timedwait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S new file mode 100644 index 000000000..d16ab3ce5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S @@ -0,0 +1,58 @@ +/* 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 <sysdep.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +	.text + +	.globl	sem_trywait +	.type	sem_trywait,@function +	.align	16 +sem_trywait: +	movl	(%rdi), %eax +2:	testl	%eax, %eax +	jz	1f + +	leaq	-1(%rax), %rdx +	LOCK +	cmpxchgl %edx, (%rdi) +	jne	2b + +	xorl	%eax, %eax +	retq + +1: +#if USE___THREAD +	movq	errno@gottpoff(%rip), %rdx +	movl	$EAGAIN, %fs:(%rdx) +#else +	callq	__errno_location@plt +	movl	$EAGAIN, (%rax) +#endif +	orl	$-1, %eax +	retq +	.size	sem_trywait,.-sem_trywait +	versioned_symbol(libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S new file mode 100644 index 000000000..32c24e83d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S @@ -0,0 +1,117 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + + +	.text + +	.globl	sem_wait +	.type	sem_wait,@function +	.align	16 +	cfi_startproc +sem_wait: +	/* First check for cancellation.  */ +	movl	%fs:CANCELHANDLING, %eax +	andl	$0xfffffff9, %eax +	cmpl	$8, %eax +	je	4f + +	pushq	%r12 +	cfi_adjust_cfa_offset(8) +	cfi_offset(12, -16) +	pushq	%r13 +	cfi_adjust_cfa_offset(8) +	movq	%rdi, %r13 +	cfi_offset(13, -24) + +3:	movl	(%r13), %eax +2:	testl	%eax, %eax +	je	1f + +	leaq	-1(%rax), %rdx +	LOCK +	cmpxchgl %edx, (%r13) +	jne	2b +	xorl	%eax, %eax + +	popq	%r13 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(13) +	popq	%r12 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(12) + +	retq + +	cfi_adjust_cfa_offset(16) +	cfi_offset(12, -16) +	cfi_offset(13, -24) +1:	call	__pthread_enable_asynccancel +	movl	%eax, %r8d + +	xorq	%r10, %r10 +	movl	$SYS_futex, %eax +	movq	%r13, %rdi +	movq	%r10, %rsi +	movq	%r10, %rdx +	syscall +	movq	%rax, %r12 + +	movl	%r8d, %edi +	call	__pthread_disable_asynccancel + +	testq	%r12, %r12 +	je	3b +	cmpq	$-EWOULDBLOCK, %r12 +	je	3b +	negq	%r12 +#if USE___THREAD +	movq	errno@gottpoff(%rip), %rdx +	movl	%r12d, %fs:(%rdx) +#else +	callq	__errno_location@plt +	movl	%r12d, (%rax) +#endif +	orl	$-1, %eax + +	popq	%r13 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(13) +	popq	%r12 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(12) + +	retq + +4:	/* Canceled.  */ +	movq	$0xffffffffffffffff, %fs:RESULT +	LOCK +	orl	$0x10, %fs:CANCELHANDLING +	movq	%fs:CLEANUP_JMP_BUF, %rdi +	jmp	HIDDEN_JUMPTARGET (__pthread_unwind) +	cfi_endproc +	.size	sem_wait,.-sem_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h new file mode 100644 index 000000000..1c93952d4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h @@ -0,0 +1,111 @@ +/* Copyright (C) 2002-2006, 2009 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@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 <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +/* The code to disable cancellation depends on the fact that the called +   functions are special.  They don't modify registers other than %rax +   and %r11 if they return.  Therefore we don't have to preserve other +   registers around these calls.  */ +# undef PSEUDO +# define PSEUDO(name, syscall_name, args)				      \ +  .text;								      \ +  ENTRY (name)								      \ +    SINGLE_THREAD_P;							      \ +    jne L(pseudo_cancel);						      \ +  .type __##syscall_name##_nocancel,@function;				      \ +  .globl __##syscall_name##_nocancel;					      \ +  __##syscall_name##_nocancel:						      \ +    DO_CALL (syscall_name, args);					      \ +    cmpq $-4095, %rax;							      \ +    jae SYSCALL_ERROR_LABEL;						      \ +    ret;								      \ +  .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \ +  L(pseudo_cancel):							      \ +    /* We always have to align the stack before calling a function.  */	      \ +    subq $8, %rsp; cfi_adjust_cfa_offset (8);				      \ +    CENABLE								      \ +    /* The return value from CENABLE is argument for CDISABLE.  */	      \ +    movq %rax, (%rsp);							      \ +    DO_CALL (syscall_name, args);					      \ +    movq (%rsp), %rdi;							      \ +    /* Save %rax since it's the error code from the syscall.  */	      \ +    movq %rax, %rdx;							      \ +    CDISABLE								      \ +    movq %rdx, %rax;							      \ +    addq $8,%rsp; cfi_adjust_cfa_offset (-8);				      \ +    cmpq $-4095, %rax;							      \ +    jae SYSCALL_ERROR_LABEL;						      \ +  L(pseudo_end): + + +# ifdef IS_IN_libpthread +#  define CENABLE	call __pthread_enable_asynccancel; +#  define CDISABLE	call __pthread_disable_asynccancel; +#  define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +#  define CENABLE	call __libc_enable_asynccancel; +#  define CDISABLE	call __libc_disable_asynccancel; +#  define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_librt +#  define CENABLE	call __librt_enable_asynccancel; +#  define CDISABLE	call __librt_disable_asynccancel; +# else +#  error Unsupported library +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +#  ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +#   define SINGLE_THREAD_P \ +  __builtin_expect (__local_multiple_threads == 0, 1) +#  else +#   define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip) +#  endif + +# else + +#  ifndef __ASSEMBLER__ +#   define SINGLE_THREAD_P \ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ +				   header.multiple_threads) == 0, 1) +#  else +#   define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET +#  endif + +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ +				   header.multiple_threads) == 0, 1) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep.h new file mode 100644 index 000000000..b13a14f6a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep.h @@ -0,0 +1,259 @@ +/* Copyright (C) 2001-2005, 2007 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 _LINUX_X86_64_SYSDEP_H +#define _LINUX_X86_64_SYSDEP_H 1 + +/* There is some commonality.  */ +#include <sys/syscall.h> +#include <sysdeps/i386/sysdep.h> + +#ifdef IS_IN_rtld +# include <dl-sysdep.h>		/* Defines RTLD_PRIVATE_ERRNO.  */ +#endif + +/* For Linux we can use the system call table in the header file +	/usr/include/asm/unistd.h +   of the kernel.  But these symbols do not follow the SYS_* syntax +   so we have to redefine the `SYS_ify' macro here.  */ +#undef SYS_ify +#define SYS_ify(syscall_name)	__NR_##syscall_name + +/* This is a kludge to make syscalls.list find these under the names +   pread and pwrite, since some kernel headers define those names +   and some define the *64 names for the same system calls.  */ +#if !defined __NR_pread && defined __NR_pread64 +# define __NR_pread __NR_pread64 +#endif +#if !defined __NR_pwrite && defined __NR_pwrite64 +# define __NR_pwrite __NR_pwrite64 +#endif + +/* This is to help the old kernel headers where __NR_semtimedop is not +   available.  */ +#ifndef __NR_semtimedop +# define __NR_semtimedop 220 +#endif + + +#ifdef __ASSEMBLER__ + +/* Linux uses a negative return value to indicate syscall errors, +   unlike most Unices, which use the condition codes' carry flag. + +   Since version 2.1 the return value of a system call might be +   negative even if the call succeeded.	 E.g., the `lseek' system call +   might return a large offset.	 Therefore we must not anymore test +   for < 0, but test for a real error by making sure the value in %eax +   is a real error number.  Linus said he will make sure the no syscall +   returns a value in -1 .. -4095 as a valid result so we can savely +   test with -4095.  */ + +/* We don't want the label for the error handle to be global when we define +   it here.  */ +# ifdef PIC +#  define SYSCALL_ERROR_LABEL 0f +# else +#  define SYSCALL_ERROR_LABEL syscall_error +# endif + +# undef	PSEUDO +# define PSEUDO(name, syscall_name, args)				      \ +  .text;								      \ +  ENTRY (name)								      \ +    DO_CALL (syscall_name, args);					      \ +    cmpq $-4095, %rax;							      \ +    jae SYSCALL_ERROR_LABEL;						      \ +  L(pseudo_end): + +# undef	PSEUDO_END +# define PSEUDO_END(name)						      \ +  SYSCALL_ERROR_HANDLER							      \ +  END (name) + +# undef	PSEUDO_NOERRNO +# define PSEUDO_NOERRNO(name, syscall_name, args) \ +  .text;								      \ +  ENTRY (name)								      \ +    DO_CALL (syscall_name, args) + +# undef	PSEUDO_END_NOERRNO +# define PSEUDO_END_NOERRNO(name) \ +  END (name) + +# define ret_NOERRNO ret + +# undef	PSEUDO_ERRVAL +# define PSEUDO_ERRVAL(name, syscall_name, args) \ +  .text;								      \ +  ENTRY (name)								      \ +    DO_CALL (syscall_name, args);					      \ +    negq %rax + +# undef	PSEUDO_END_ERRVAL +# define PSEUDO_END_ERRVAL(name) \ +  END (name) + +# define ret_ERRVAL ret + +# ifndef PIC +#  define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.S is used.  */ +# elif defined(RTLD_PRIVATE_ERRNO) +#  define SYSCALL_ERROR_HANDLER			\ +0:						\ +  leaq rtld_errno(%rip), %rcx;			\ +  xorl %edx, %edx;				\ +  subq %rax, %rdx;				\ +  movl %edx, (%rcx);				\ +  orq $-1, %rax;				\ +  jmp L(pseudo_end); +# elif USE___THREAD +#  ifndef NOT_IN_libc +#   define SYSCALL_ERROR_ERRNO __libc_errno +#  else +#   define SYSCALL_ERROR_ERRNO errno +#  endif +#  define SYSCALL_ERROR_HANDLER			\ +0:						\ +  movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\ +  xorl %edx, %edx;				\ +  subq %rax, %rdx;				\ +  movl %edx, %fs:(%rcx);			\ +  orq $-1, %rax;				\ +  jmp L(pseudo_end); +# elif defined _LIBC_REENTRANT +/* Store (- %rax) into errno through the GOT. +   Note that errno occupies only 4 bytes.  */ +#  define SYSCALL_ERROR_HANDLER			\ +0:						\ +  xorl %edx, %edx;				\ +  subq %rax, %rdx;				\ +  pushq %rdx;					\ +  cfi_adjust_cfa_offset(8);			\ +  call __errno_location@PLT;		\ +  popq %rdx;					\ +  cfi_adjust_cfa_offset(-8);			\ +  movl %edx, (%rax);				\ +  orq $-1, %rax;				\ +  jmp L(pseudo_end); + +/* A quick note: it is assumed that the call to `__errno_location' does +   not modify the stack!  */ +# else /* Not _LIBC_REENTRANT.  */ +#  define SYSCALL_ERROR_HANDLER			\ +0:movq errno@GOTPCREL(%RIP), %rcx;		\ +  xorl %edx, %edx;				\ +  subq %rax, %rdx;				\ +  movl %edx, (%rcx);				\ +  orq $-1, %rax;				\ +  jmp L(pseudo_end); +# endif	/* PIC */ + +/* The Linux/x86-64 kernel expects the system call parameters in +   registers according to the following table: + +    syscall number	rax +    arg 1		rdi +    arg 2		rsi +    arg 3		rdx +    arg 4		r10 +    arg 5		r8 +    arg 6		r9 + +    The Linux kernel uses and destroys internally these registers: +    return address from +    syscall		rcx +    eflags from syscall	r11 + +    Normal function call, including calls to the system call stub +    functions in the libc, get the first six parameters passed in +    registers and the seventh parameter and later on the stack.  The +    register use is as follows: + +     system call number	in the DO_CALL macro +     arg 1		rdi +     arg 2		rsi +     arg 3		rdx +     arg 4		rcx +     arg 5		r8 +     arg 6		r9 + +    We have to take care that the stack is aligned to 16 bytes.  When +    called the stack is not aligned since the return address has just +    been pushed. + + +    Syscalls of more than 6 arguments are not supported.  */ + +# undef	DO_CALL +# define DO_CALL(syscall_name, args)		\ +    DOARGS_##args				\ +    movl $SYS_ify (syscall_name), %eax;		\ +    syscall; + +# define DOARGS_0 /* nothing */ +# define DOARGS_1 /* nothing */ +# define DOARGS_2 /* nothing */ +# define DOARGS_3 /* nothing */ +# define DOARGS_4 movq %rcx, %r10; +# define DOARGS_5 DOARGS_4 +# define DOARGS_6 DOARGS_5 + +#endif	/* __ASSEMBLER__ */ + + +/* Pointer mangling support.  */ +#if defined NOT_IN_libc && defined IS_IN_rtld +/* We cannot use the thread descriptor because in ld.so we use setjmp +   earlier than the descriptor is initialized.  */ +# ifdef __ASSEMBLER__ +#  define PTR_MANGLE(reg)	xorq __pointer_chk_guard_local(%rip), reg;    \ +				rolq $17, reg +#  define PTR_DEMANGLE(reg)	rorq $17, reg;				      \ +				xorq __pointer_chk_guard_local(%rip), reg +# else +#  define PTR_MANGLE(reg)	asm ("xorq __pointer_chk_guard_local(%%rip), %0\n" \ +				     "rolq $17, %0"			      \ +				     : "=r" (reg) : "0" (reg)) +#  define PTR_DEMANGLE(reg)	asm ("rorq $17, %0\n"			      \ +				     "xorq __pointer_chk_guard_local(%%rip), %0" \ +				     : "=r" (reg) : "0" (reg)) +# endif +#else +# ifdef __ASSEMBLER__ +#  define PTR_MANGLE(reg)	xorq %fs:POINTER_GUARD, reg;		      \ +				rolq $17, reg +#  define PTR_DEMANGLE(reg)	rorq $17, reg;				      \ +				xorq %fs:POINTER_GUARD, reg +# else +#  define PTR_MANGLE(var)	asm ("xorq %%fs:%c2, %0\n"		      \ +				     "rolq $17, %0"			      \ +				     : "=r" (var)			      \ +				     : "0" (var),			      \ +				       "i" (offsetof (tcbhead_t,	      \ +						      pointer_guard))) +#  define PTR_DEMANGLE(var)	asm ("rorq $17, %0\n"			      \ +				     "xorq %%fs:%c2, %0"		      \ +				     : "=r" (var)			      \ +				     : "0" (var),			      \ +				       "i" (offsetof (tcbhead_t,	      \ +						      pointer_guard))) +# endif +#endif + +#endif /* linux/x86_64/sysdep.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S new file mode 100644 index 000000000..9a9912ca8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S @@ -0,0 +1,43 @@ +/* Copyright (C) 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.  */ + +/* We want an #include_next, but we are the main source file. +   So, #include ourselves and in that incarnation we can use #include_next.  */ +#ifndef INCLUDED_SELF +# define INCLUDED_SELF +# include <vfork.S> +#else + +# include <tcb-offsets.h> + +# define SAVE_PID \ +	movl	%fs:PID, %esi;						      \ +	movl	$0x80000000, %ecx;					      \ +	movl	%esi, %edx;						      \ +	negl	%edx;							      \ +	cmove	%ecx, %edx;						      \ +	movl	%edx, %fs:PID + +# define RESTORE_PID \ +	testq	%rax, %rax;						      \ +	je	1f;							      \ +	movl	%esi, %fs:PID;						      \ +1: + +# include_next <vfork.S> +#endif  | 
