diff options
Diffstat (limited to 'libpthread')
366 files changed, 31173 insertions, 588 deletions
diff --git a/libpthread/nptl/ChangeLog b/libpthread/nptl/ChangeLog index 6fb56a93f..b5ec0e44d 100644 --- a/libpthread/nptl/ChangeLog +++ b/libpthread/nptl/ChangeLog @@ -1,3 +1,31 @@ +2005-05-23  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h +	[IS_IN_librt] (CENABLE, CDISABLE): Use JUMPTARGET instead of +	__librt_*_asynccancel@local. + +2005-05-17  Alan Modra  <amodra@bigpond.net.au> + +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Delete +	all occurrences of JUMPTARGET.  Instead append @local to labels. + +2005-05-20  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/i386/tls.h (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN): Define to +	size/alignment of struct pthread rather than tcbhead_t. +	* sysdeps/x86_64/tls.h (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN): +	Likewise. +	* sysdeps/s390/tls.h (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN): +	Likewise. +	* sysdeps/sparc/tls.h (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN): +	Likewise. + +2005-05-19  Richard Henderson  <rth@redhat.com> + +	* sysdeps/ia64/pthread_spin_lock.c (pthread_spin_lock): Use +	__sync_val_compare_and_swap, not explicit _si variant. +	* sysdeps/ia64/pthread_spin_trylock.c (pthread_spin_trylock): Likewise. +  2005-05-03  Ulrich Drepper  <drepper@redhat.com>  	[BZ #915] diff --git a/libpthread/nptl/Makefile b/libpthread/nptl/Makefile index 4c3cf941d..668fad09c 100644 --- a/libpthread/nptl/Makefile +++ b/libpthread/nptl/Makefile @@ -1,592 +1,89 @@ -# 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. - +# Makefile for uClibc's pthread library  # -#	Sub-makefile for NPTL portion of the library. +# Copyright (C) 2002 Erik Andersen <andersen@uclibc.org> +# Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>  # -subdir	:= nptl - -headers := pthread.h semaphore.h bits/semaphore.h - -extra-libs := libpthread -extra-libs-others := $(extra-libs) -install-lib-ldscripts := libpthread.so - -routines = alloca_cutoff forward libc-lowlevellock libc-cancellation -shared-only-routines = forward - -libpthread-routines = init vars events version \ -		      pthread_create pthread_exit pthread_detach \ -		      pthread_join pthread_tryjoin pthread_timedjoin \ -		      pthread_self pthread_equal pthread_yield \ -		      pthread_getconcurrency pthread_setconcurrency \ -		      pthread_getschedparam pthread_setschedparam \ -		      pthread_setschedprio \ -		      pthread_attr_init pthread_attr_destroy \ -		      pthread_attr_getdetachstate pthread_attr_setdetachstate \ -		      pthread_attr_getguardsize pthread_attr_setguardsize \ -		      pthread_attr_getschedparam pthread_attr_setschedparam \ -		      pthread_attr_getschedpolicy pthread_attr_setschedpolicy \ -		      pthread_attr_getinheritsched \ -		      pthread_attr_setinheritsched \ -		      pthread_attr_getscope pthread_attr_setscope \ -		      pthread_attr_getstackaddr pthread_attr_setstackaddr \ -		      pthread_attr_getstacksize pthread_attr_setstacksize \ -		      pthread_attr_getstack pthread_attr_setstack \ -		      pthread_getattr_np \ -		      pthread_mutex_init pthread_mutex_destroy \ -		      pthread_mutex_lock pthread_mutex_trylock \ -		      pthread_mutex_timedlock pthread_mutex_unlock \ -		      pthread_mutexattr_init pthread_mutexattr_destroy \ -		      pthread_mutexattr_getpshared \ -		      pthread_mutexattr_setpshared \ -		      pthread_mutexattr_gettype pthread_mutexattr_settype \ -		      pthread_rwlock_init pthread_rwlock_destroy \ -		      pthread_rwlock_rdlock pthread_rwlock_timedrdlock \ -		      pthread_rwlock_wrlock pthread_rwlock_timedwrlock \ -		      pthread_rwlock_tryrdlock pthread_rwlock_trywrlock \ -		      pthread_rwlock_unlock \ -		      pthread_rwlockattr_init pthread_rwlockattr_destroy \ -		      pthread_rwlockattr_getpshared \ -		      pthread_rwlockattr_setpshared \ -		      pthread_rwlockattr_getkind_np \ -		      pthread_rwlockattr_setkind_np \ -		      pthread_cond_init pthread_cond_destroy \ -		      pthread_cond_wait pthread_cond_timedwait \ -		      pthread_cond_signal pthread_cond_broadcast \ -		      old_pthread_cond_init old_pthread_cond_destroy \ -		      old_pthread_cond_wait old_pthread_cond_timedwait \ -		      old_pthread_cond_signal old_pthread_cond_broadcast \ -		      pthread_condattr_init pthread_condattr_destroy \ -		      pthread_condattr_getpshared pthread_condattr_setpshared \ -		      pthread_condattr_getclock pthread_condattr_setclock \ -		      pthread_spin_init pthread_spin_destroy \ -		      pthread_spin_lock pthread_spin_trylock \ -		      pthread_spin_unlock \ -		      pthread_barrier_init pthread_barrier_destroy \ -		      pthread_barrier_wait \ -		      pthread_barrierattr_init pthread_barrierattr_destroy \ -		      pthread_barrierattr_getpshared \ -		      pthread_barrierattr_setpshared \ -		      pthread_key_create pthread_key_delete \ -		      pthread_getspecific pthread_setspecific \ -		      pthread_sigmask pthread_kill \ -		      pthread_cancel pthread_testcancel \ -		      pthread_setcancelstate pthread_setcanceltype \ -		      pthread_once \ -		      old_pthread_atfork pthread_atfork \ -		      pthread_getcpuclockid \ -		      pthread_clock_gettime pthread_clock_settime \ -		      sem_init sem_destroy \ -		      sem_open sem_close sem_unlink \ -		      sem_getvalue \ -		      sem_wait sem_trywait sem_timedwait sem_post \ -		      cleanup cleanup_defer cleanup_compat \ -		      cleanup_defer_compat unwind \ -		      pt-longjmp pt-cleanup\ -		      cancellation \ -		      lowlevellock \ -		      pt-vfork \ -		      ptw-write ptw-read ptw-close ptw-fcntl ptw-accept \ -		      ptw-connect ptw-recv ptw-recvfrom ptw-recvmsg ptw-send \ -		      ptw-sendmsg ptw-sendto ptw-fsync ptw-lseek ptw-llseek \ -		      ptw-msync ptw-nanosleep ptw-open ptw-open64 ptw-pause \ -		      ptw-pread ptw-pread64 ptw-pwrite ptw-pwrite64 \ -		      ptw-tcdrain ptw-wait ptw-waitpid ptw-msgrcv ptw-msgsnd \ -		      ptw-sigwait \ -		      pt-raise pt-system \ -		      flockfile ftrylockfile funlockfile \ -		      sigaction \ -		      herrno res pt-allocrtsig \ -		      pthread_kill_other_threads \ -		      pthread_getaffinity pthread_setaffinity \ -		      pthread_attr_getaffinity pthread_attr_setaffinity \ -		      cleanup_routine unwind-forcedunwind -#		      pthread_setuid pthread_seteuid pthread_setreuid \ -#		      pthread_setresuid \ -#		      pthread_setgid pthread_setegid pthread_setregid \ -#		      pthread_setresgid - -libpthread-shared-only-routines = version pt-allocrtsig unwind-forcedunwind -libpthread-static-only-routines = pthread_atfork - -CFLAGS-pthread_atfork.c = -DNOT_IN_libc - -# Since cancellation handling is in large parts handled using exceptions -# we have to compile some files with exception handling enabled, some -# even with asynchronous unwind tables. - -# init.c contains sigcancel_handler(). -CFLAGS-init.c = -fexceptions -fasynchronous-unwind-tables -# The unwind code itself, -CFLAGS-unwind.c = -fexceptions -CFLAGS-unwind-forcedunwind.c = -fexceptions -fasynchronous-unwind-tables - -# The following three functions must be async-cancel safe. -CFLAGS-pthread_cancel.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-pthread_setcancelstate.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-pthread_setcanceltype.c = -fexceptions -fasynchronous-unwind-tables - -# These are internal functions which similar functionality as setcancelstate -# and setcanceltype. -CFLAGS-cancellation.c = -fasynchronous-unwind-tables -CFLAGS-libc-cancellation.c = -fasynchronous-unwind-tables - -# Calling pthread_exit() must cause the registered cancel handlers to -# be executed.  Therefore exceptions have to be thrown through this -# function. -CFLAGS-pthread_exit.c = -fexceptions - -# Among others, __pthread_unwind is forwarded.  This function must handle -# exceptions. -CFLAGS-forward.c = -fexceptions - -# The following are cancellation points.  Some of the functions can -# block and therefore temporarily enable asynchronous cancellation. -# Those must be compiled asynchronous unwind tables. -CFLAGS-pthread_testcancel.c = -fexceptions -CFLAGS-pthread_join.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-pthread_timedjoin.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-pthread_once.c = $(uses-callbacks) -fexceptions \ -			-fasynchronous-unwind-tables -CFLAGS-pthread_cond_wait.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-pthread_cond_timedwait.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-sem_wait.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-sem_timedwait.c = -fexceptions -fasynchronous-unwind-tables - -# These are the function wrappers we have to duplicate here. -CFLAGS-fcntl.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-lockf.c = -fexceptions -CFLAGS-pread.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-pread64.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-pwrite.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-pwrite64.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-wait.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-waitpid.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-sigwait.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-msgrcv.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-msgsnd.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-tcdrain.c = -fexceptions -fasynchronous-unwind-tables - -CFLAGS-pt-system.c = -fexceptions - -# Don't generate deps for calls with no sources.  See sysdeps/unix/Makefile. -omit-deps = $(unix-syscalls:%=ptw-%) - - -tests = tst-attr1 tst-attr2 tst-attr3 \ -	tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \ -	tst-mutex7 tst-mutex8 tst-mutex9 tst-mutex5a tst-mutex7a \ -	tst-spin1 tst-spin2 tst-spin3 \ -	tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ -	tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ -	tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \ -	tst-cond20 tst-cond21 \ -	tst-rwlock1 tst-rwlock2 tst-rwlock3 tst-rwlock4 tst-rwlock5 \ -	tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 tst-rwlock10 \ -	tst-rwlock11 tst-rwlock12 tst-rwlock13 tst-rwlock14 \ -	tst-once1 tst-once2 tst-once3 tst-once4 \ -	tst-key1 tst-key2 tst-key3 tst-key4 \ -	tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \ -	tst-sem8 tst-sem9 \ -	tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \ -	tst-align tst-align2 \ -	tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \ -	tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \ -	tst-raise1 \ -	tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 \ -	tst-detach1 \ -	tst-eintr1 tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \ -	tst-tsd1 tst-tsd2 tst-tsd3 tst-tsd4 tst-tsd5 \ -	tst-tls1 tst-tls2 \ -	tst-fork1 tst-fork2 tst-fork3 tst-fork4 \ -	tst-atfork1 \ -	tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \ -	tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \ -	tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \ -	tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \ -	tst-cancel21 tst-cancel22 tst-cancel23 \ -	tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \ -	tst-flock1 tst-flock2 \ -	tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \ -	tst-signal6 \ -	tst-exec1 tst-exec2 tst-exec3 tst-exec4 \ -	tst-exit1 tst-exit2 tst-exit3 \ -	tst-stdio1 tst-stdio2 \ -	tst-stack1 tst-stack2 tst-stack3 \ -	tst-unload \ -	tst-dlsym1 \ -	tst-sysconf \ -	tst-locale1 tst-locale2 \ -	tst-umask1 \ -	tst-popen1 \ -	tst-clock1 \ -	tst-context1 \ -	tst-sched1 \ -	tst-backtrace1 \ -	tst-oddstacklimit \ -	tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \ -	tst-getpid1 tst-getpid2 -xtests = tst-setuid1 tst-setuid1-static - -# Files which must not be linked with libpthread. -tests-nolibpthread = tst-unload - -# This sets the stack resource limit to 1023kb, which is not a multiple -# of the page size since every architecture's page size is > 1k. -tst-oddstacklimit-ENV = ; ulimit -s 1023; - -distribute = eintr.c tst-cleanup4aux.c - -gen-as-const-headers = pthread-errnos.sym - -LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst - - -include ../Makeconfig - -ifeq ($(have-forced-unwind),yes) -tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \ -	 tst-cancelx6 tst-cancelx7 tst-cancelx8 tst-cancelx9 tst-cancelx10 \ -	 tst-cancelx11 tst-cancelx12 tst-cancelx13 tst-cancelx14 tst-cancelx15 \ -	 tst-cancelx16 tst-cancelx17 tst-cancelx18 tst-cancelx20 tst-cancelx21 \ -	 tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 \ -	 tst-oncex3 tst-oncex4 -endif -ifeq ($(build-shared),yes) -tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 -tests-nolibpthread += tst-fini1 -ifeq ($(have-z-execstack),yes) -tests += tst-execstack -endif -endif - -modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \ -		tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \ -		tst-tls5modd tst-tls5mode tst-tls5modf \ -		tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod -extra-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o -test-extras += $(modules-names) -test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) - -tst-atfork2mod.so-no-z-defs = yes -tst-tls3mod.so-no-z-defs = yes -tst-tls5mod.so-no-z-defs = yes -tst-tls5moda.so-no-z-defs = yes -tst-tls5modb.so-no-z-defs = yes -tst-tls5modc.so-no-z-defs = yes -tst-tls5modd.so-no-z-defs = yes -tst-tls5mode.so-no-z-defs = yes -tst-tls5modf.so-no-z-defs = yes - -$(test-modules): $(objpfx)%.so: $(objpfx)%.os $(common-objpfx)shlib.lds -	$(build-module) - -ifeq ($(build-shared),yes) -# Build all the modules even when not actually running test programs. -tests: $(test-modules) -endif - -ifeq ($(build-shared),yes) - -# Set the `multidir' variable by grabbing the variable from the compiler. -# We do it once and save the result in a generated makefile. --include $(objpfx)multidir.mk -$(objpfx)multidir.mk: $(common-objpfx)config.make -	$(make-target-directory) -	dir=`$(CC) $(CFLAGS) $(CPPFLAGS) -print-multi-directory`; \ -	echo "multidir := $$dir" > $@T -	mv -f $@T $@ - -crti-objs := crti.o -crtn-objs := crtn.o -ifneq (,$(patsubst .,,$(multidir))) -generated-dirs := $(firstword $(subst /, , $(multidir))) -crti-objs += $(multidir)/crti.o -crtn-objs += $(multidir)/crtn.o -omit-deps += $(multidir)/crti $(multidir)/crtn -$(objpfx)$(multidir): -	mkdir $@ -endif -extra-objs += $(crti-objs) $(crtn-objs) -omit-deps += crti crtn - -CFLAGS-pt-initfini.s = -g0 -fPIC -fno-inline-functions $(fno-unit-at-a-time) -endif - -CFLAGS-flockfile.c = -D_IO_MTSAFE_IO -CFLAGS-ftrylockfile.c = -D_IO_MTSAFE_IO -CFLAGS-funlockfile.c = -D_IO_MTSAFE_IO - -link-libc-static := $(common-objpfx)libc.a $(static-gnulib) \ -		    $(common-objpfx)libc.a - -ifeq ($(build-static),yes) -tests-static += tst-locale1 tst-locale2 -xtests-static += tst-setuid1-static -endif -# These tests are linked with libc before libpthread -tests-reverse += tst-cancel5 tst-cancel23 tst-vfork1x tst-vfork2x - -include ../Rules - -ifeq (yes,$(build-shared)) -# Make sure these things are built in the `make lib' pass so they can be used -# to run programs during the `make others' pass. -lib-noranlib: $(addprefix $(objpfx),$(extra-objs)) - -# What we install as libpthread.so for programs to link against is in fact a -# link script.  It contains references for the various libraries we need. -# The libpthread.so object is not complete since some functions are only -# defined in libpthread_nonshared.a. -# We need to use absolute paths since otherwise local copies (if they exist) -# of the files are taken by the linker. -install: $(inst_libdir)/libpthread.so - -$(inst_libdir)/libpthread.so: $(common-objpfx)format.lds \ -			      $(objpfx)libpthread.so$(libpthread.so-version) \ -			      $(inst_libdir)/$(patsubst %,$(libtype.oS),\ -							$(libprefix)pthread) \ -			      $(+force) -	(echo '/* GNU ld script';\ -	 echo '   Use the shared library, but some functions are only in';\ -	 echo '   the static library, so try that secondarily.  */';\ -	 cat $<; \ -	 echo 'GROUP ( $(slibdir)/libpthread.so$(libpthread.so-version)' \ -	      '$(libdir)/$(patsubst %,$(libtype.oS),$(libprefix)pthread)'\ -	      ')' \ -	) > $@.new -	mv -f $@.new $@ -endif - - -# 'pthread_self' is a simple memory or register load.  Setting up the -# stack frame is more work than the actual operation.  Disable the -# frame creation entirely.  This will help applications which call the -# function frequently to get a thread-specific handle. -CFLAGS-pthread_self.os += -fomit-frame-pointer - -# Run the cancellation and cleanup tests also for the modern, exception-based -# implementation.  For this we have to pass the -fexceptions parameter. -CFLAGS-tst-cancelx2.c += -fexceptions -CFLAGS-tst-cancelx3.c += -fexceptions -CFLAGS-tst-cancelx4.c += -fexceptions -CFLAGS-tst-cancelx5.c += -fexceptions -CFLAGS-tst-cancelx6.c += -fexceptions -CFLAGS-tst-cancelx7.c += -fexceptions -CFLAGS-tst-cancelx8.c += -fexceptions -CFLAGS-tst-cancelx9.c += -fexceptions -CFLAGS-tst-cancelx10.c += -fexceptions -CFLAGS-tst-cancelx11.c += -fexceptions -CFLAGS-tst-cancelx12.c += -fexceptions -CFLAGS-tst-cancelx13.c += -fexceptions -CFLAGS-tst-cancelx14.c += -fexceptions -CFLAGS-tst-cancelx15.c += -fexceptions -CFLAGS-tst-cancelx16.c += -fexceptions -CFLAGS-tst-cancelx17.c += -fexceptions -CFLAGS-tst-cancelx18.c += -fexceptions -CFLAGS-tst-cancelx20.c += -fexceptions -fasynchronous-unwind-tables -CFLAGS-tst-cancelx21.c += -fexceptions -fasynchronous-unwind-tables -CFLAGS-tst-cleanupx0.c += -fexceptions -fasynchronous-unwind-tables -CFLAGS-tst-cleanupx1.c += -fexceptions -fasynchronous-unwind-tables -CFLAGS-tst-cleanupx2.c += -fexceptions -CFLAGS-tst-cleanupx3.c += -fexceptions -CFLAGS-tst-cleanupx4.c += -fexceptions -CFLAGS-tst-oncex3.c += -fexceptions -CFLAGS-tst-oncex4.c += -fexceptions -CFLAGS-tst-align.c += $(stack-align-test-flags) - -tst-cancel7-ARGS = --command "$(built-program-cmd)" -tst-cancelx7-ARGS = $(tst-cancel7-ARGS) -tst-umask1-ARGS = $(objpfx)tst-umask1.temp - -$(objpfx)tst-atfork2: $(libdl) $(shared-thread-library) -LDFLAGS-tst-atfork2 = -rdynamic -tst-atfork2-ENV = MALLOC_TRACE=$(objpfx)tst-atfork2.mtrace -$(objpfx)tst-atfork2mod.so: $(shared-thread-library) - -tests: $(objpfx)tst-stack3-mem -tst-stack3-ENV = MALLOC_TRACE=$(objpfx)tst-stack3.mtrace -$(objpfx)tst-stack3-mem: $(objpfx)tst-stack3.out -	$(common-objpfx)malloc/mtrace $(objpfx)tst-stack3.mtrace > $@ -generated += tst-stack3-mem tst-stack3.mtrace - -$(objpfx)tst-cleanup4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library) -$(objpfx)tst-cleanupx4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library) - -$(objpfx)tst-tls3: $(libdl) $(shared-thread-library) -LDFLAGS-tst-tls3 = -rdynamic -$(objpfx)tst-tls3.out: $(objpfx)tst-tls3mod.so -$(objpfx)tst-tls3mod.so: $(shared-thread-library) - -$(objpfx)tst-tls4: $(libdl) $(shared-thread-library) -$(objpfx)tst-tls4.out: $(objpfx)tst-tls4moda.so $(objpfx)tst-tls4modb.so - -$(objpfx)tst-tls5: $(objpfx)tst-tls5mod.so $(shared-thread-library) -LDFLAGS-tst-tls5mod.so = -Wl,-soname,tst-tls5mod.so - -ifeq ($(build-shared),yes) -tests: $(objpfx)tst-tls6.out -$(objpfx)tst-tls6.out: tst-tls6.sh $(objpfx)tst-tls5 \ -		       $(objpfx)tst-tls5moda.so $(objpfx)tst-tls5modb.so \ -		       $(objpfx)tst-tls5modc.so $(objpfx)tst-tls5modd.so \ -		       $(objpfx)tst-tls5mode.so $(objpfx)tst-tls5modf.so -	$(SHELL) -e tst-tls6.sh $(common-objpfx) $(elf-objpfx) \ -		    $(rtld-installed-name) -endif - -$(objpfx)tst-dlsym1: $(libdl) $(shared-thread-library) - -$(objpfx)tst-fini1: $(shared-thread-library) $(objpfx)tst-fini1mod.so - -ifeq (yes,$(build-shared)) -$(objpfx)tst-cond11: $(common-objpfx)rt/librt.so -$(objpfx)tst-cond19: $(common-objpfx)rt/librt.so -$(objpfx)tst-cancel17: $(common-objpfx)rt/librt.so -$(objpfx)tst-cancelx17: $(common-objpfx)rt/librt.so -$(objpfx)tst-cancel18: $(common-objpfx)rt/librt.so -$(objpfx)tst-cancelx18: $(common-objpfx)rt/librt.so -$(objpfx)tst-clock2: $(common-objpfx)rt/librt.so -$(objpfx)tst-rwlock14: $(common-objpfx)rt/librt.so -$(objpfx)tst-_res1mod2.so: $(objpfx)tst-_res1mod1.so -LDFLAGS-tst-_res1mod1.so = -Wl,-soname,tst-_res1mod1.so -LDFLAGS-tst-_res1mod2.so = -Wl,-soname,tst-_res1mod2.so -$(objpfx)tst-_res1: $(objpfx)tst-_res1mod2.so $(shared-thread-library) -else -$(objpfx)tst-cond11: $(common-objpfx)rt/librt.a -$(objpfx)tst-cond19: $(common-objpfx)rt/librt.a -$(objpfx)tst-cancel17: $(common-objpfx)rt/librt.a -$(objpfx)tst-cancelx17: $(common-objpfx)rt/librt.a -$(objpfx)tst-cancel18: $(common-objpfx)rt/librt.a -$(objpfx)tst-cancelx18: $(common-objpfx)rt/librt.a -$(objpfx)tst-clock2: $(common-objpfx)rt/librt.a -$(objpfx)tst-rwlock14: $(common-objpfx)rt/librt.a -endif - -extra-B-pthread.so = -B$(common-objpfx)nptl/ -$(objpfx)libpthread.so: $(addprefix $(objpfx),$(crti-objs) $(crtn-objs)) -$(objpfx)libpthread.so: +preinit += $(addprefix $(objpfx),$(crti-objs)) -$(objpfx)libpthread.so: +postinit += $(addprefix $(objpfx),$(crtn-objs)) - -# Depend on libc.so so a DT_NEEDED is generated in the shared objects. -# This ensures they will load libc.so for needed symbols if loaded by -# a statically-linked program that hasn't already loaded it. -# Depend on ld.so too to get proper versions of ld.so symbols. -$(objpfx)libpthread.so: $(common-objpfx)libc.so \ -			$(common-objpfx)libc_nonshared.a \ -			$(if $(filter yes,$(elf)), $(elfobjdir)/ld.so) - -# Make sure we link with the thread library. -ifeq ($(build-shared),yes) -$(addprefix $(objpfx), \ -  $(filter-out $(tests-static) $(xtests-static) $(tests-reverse) \ -    $(tests-nolibpthread), \ -    $(tests) $(xtests) $(test-srcs))): $(objpfx)libpthread.so \ -				       $(objpfx)libpthread_nonshared.a -$(objpfx)tst-unload: $(common-objpfx)dlfcn/libdl.so -# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so, -# since otherwise libpthread.so comes before libc.so when linking. -$(addprefix $(objpfx), $(tests-reverse)): \ -  $(objpfx)../libc.so $(objpfx)libpthread.so \ -  $(objpfx)libpthread_nonshared.a -$(objpfx)../libc.so: $(common-objpfx)libc.so ; -$(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a - -$(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so +# This program 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. +# +# This program 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 this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# Makefile for uClibc + +TOPDIR=../../ +include $(TOPDIR)Rules.mak + +# As long as there is only one subdir, we don't  +# have to worry about race conditions with multiple  +# $(AR)'s in subdirs running on linuxthreads.a. +DIRS = sysdeps + +#Adjust the soname version to avoid namespace collisions with glibc's libpthread +LIBPTHREAD:=../libpthread.a +ifeq ($(strip $(TARGET_ARCH)),sparc) +SYSDEPS_DIR:=$(TARGET_ARCH)/sparc32  else -$(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a +SYSDEPS_DIR:=$(TARGET_ARCH)  endif +#This stuff will not compile without at least -O1 +CFLAGS :=$(CFLAGS:-O0=-O1) -ifeq ($(build-shared),yes) -vpath pt-initfini.c $(full_config_sysdirs) - -$(objpfx)pt-initfini.s: pt-initfini.c -	$(compile.c) -S $(CFLAGS-pt-initfini.s) -finhibit-size-directive \ -		$(patsubst -f%,-fno-%,$(exceptions)) -o $@ - -$(objpfx)tst-cleanup0.out: /dev/null $(objpfx)tst-cleanup0 -	$(make-test-out) 2>&1 | cmp - tst-cleanup0.expect >& $@ - -# We only have one kind of startup code files.  Static binaries and -# shared libraries are build using the PIC version. -$(objpfx)crti.S: $(objpfx)pt-initfini.s -	sed -n -e '1,/@HEADER_ENDS/p' \ -	       -e '/@_.*_PROLOG_BEGINS/,/@_.*_PROLOG_ENDS/p' \ -	       -e '/@TRAILER_BEGINS/,$$p' $< > $@ -$(objpfx)crtn.S: $(objpfx)pt-initfini.s -	sed -n -e '1,/@HEADER_ENDS/p' \ -	       -e '/@_.*_EPILOG_BEGINS/,/@_.*_EPILOG_ENDS/p' \ -	       -e '/@TRAILER_BEGINS/,$$p' $< > $@ - -$(objpfx)defs.h: $(objpfx)pt-initfini.s -	sed -n -e '/@TESTS_BEGIN/,/@TESTS_END/p' $< | \ -		$(AWK) -f ../csu/defs.awk > $@ -$(objpfx)crti.o: $(objpfx)crti.S $(objpfx)defs.h -	$(compile.S) -g0 $(ASFLAGS-.os) -o $@ +# set up system dependencies include dirs (NOTE: order matters!) +PTDIR = $(TOPDIR)libpthread/nptl/ +SYSDEPINC = -I$(PTDIR)sysdeps/unix \ +            -I$(PTDIR)sysdeps/unix/sysv/linux \ +	    -I$(PTDIR)sysdeps/unix/sysv/linux/$(TARGET_ARCH) \ +	    -I$(PTDIR)sysdeps/$(TARGET_ARCH) \ +            -I$(PTDIR)sysdeps/pthread \ +            -I$(PTDIR)sysdeps \ +            -I$(TOPDIR)libc/sysdeps/linux/$(TARGET_ARCH) \ +	    -I$(TOPDIR)ldso/include +CFLAGS += $(SYSDEPINC) -$(objpfx)crtn.o: $(objpfx)crtn.S $(objpfx)defs.h -	$(compile.S) -g0 $(ASFLAGS-.os) -o $@ +CSRC=init.c vars.c events.c pthread_create.c pthread_exit.c -ifneq ($(multidir),.) -$(objpfx)$(multidir)/crti.o: $(objpfx)crti.o $(objpfx)$(multidir)/ -	ln -f $< $@ +COBJS=$(patsubst %.c,%.o, $(CSRC)) +OBJS=$(COBJS) -$(objpfx)$(multidir)/crtn.o: $(objpfx)crtn.o $(objpfx)$(multidir)/ -	ln -f $< $@ -endif +# We need to make sure that we put all the top-level $(OBJS) into +# our archive before executing subdirs.  That way, when $(AR) is  +# run in the subdirs, it'll bump the generic top-level objects  +# out of our archive in favor of the machine-specific ones. +all: version.h $(LIBPTHREAD) subdirs -generated += crti.S crtn.S defs.h pt-initfini.s  libpthread_nonshared.a \ -	     multidir.mk tst-atfork2.mtrace tst-cancel-wrappers.out \ -	     tst-tls6.out +version.h: +	@echo "#define VERSION \""$(VERSION)"\"" > version.h -generated += $(objpfx)tst-atfork2.mtrace \ -	     $(addsuffix .so,$(strip $(modules-names))) +$(LIBPTHREAD) ar-target: $(OBJS) +	$(AR) $(ARFLAGS) $(LIBPTHREAD) $(OBJS) -$(objpfx)version.d: $(objpfx)banner.h -$(objpfx)version.os: $(objpfx)banner.h -$(objpfx)banner.h: Banner -	sed 's/\(.*\)/"\1\\n"/' $< > $@ -generated += banner.h -# Give libpthread.so an entry point and make it directly runnable itself. -LDFLAGS-pthread.so += -e __nptl_main +$(COBJS): %.o : %.c +	$(CC) $(CFLAGS) -c $< -o $@ +ifeq ($(strip $(PTHREADS_DEBUG_SUPPORT)),y) +	$(STRIPTOOL) -X --strip-debug -R .note -R .comment $*.o +else +	$(STRIPTOOL) -x -R .note -R .comment $*.o  endif -ifeq (no,$(cross-compiling)) -ifeq (yes,$(build-shared)) -tests: $(objpfx)tst-cancel-wrappers.out -$(objpfx)tst-cancel-wrappers.out: tst-cancel-wrappers.sh -	$(SHELL) $< $(common-objpfx)libc_pic.a \ -		    $(common-objpfx)libc.a \ -		    $(objpfx)libpthread_pic.a \ -		    $(objpfx)libpthread.a > $@ -endif -endif +clean: subdirs_clean +	$(RM) *.[oa] *~ core version.h -tst-exec4-ARGS = $(built-program-cmd) +subdirs: $(patsubst %, _dir_%, $(DIRS)) +subdirs_clean: $(patsubst %, _dirclean_%, $(DIRS)) -$(objpfx)tst-execstack: $(libdl) -$(objpfx)tst-execstack.out: $(objpfx)tst-execstack-mod.so -LDFLAGS-tst-execstack = -Wl,-z,noexecstack +$(patsubst %, _dir_%, $(DIRS)): $(LIBPTHREAD) +	$(MAKE) -C $(patsubst _dir_%, %, $@) -$(objpfx)tst-fini1mod.so: $(shared-thread-library) +$(patsubst %, _dirclean_%, $(DIRS)): +	$(MAKE) -C $(patsubst _dirclean_%, %, $@) clean -# The tests here better do not run in parallel -ifneq ($(filter %tests,$(MAKECMDGOALS)),) -.NOTPARALLEL: -endif +.PHONY: dummy diff --git a/libpthread/nptl/descr.h b/libpthread/nptl/descr.h index 1dd1cc506..cf071dd81 100644 --- a/libpthread/nptl/descr.h +++ b/libpthread/nptl/descr.h @@ -28,7 +28,14 @@  #include <list.h>  #include <lowlevellock.h>  #include <pthreaddef.h> +#if 0 +/* + * MIPS NPTL - defines a total of two symbols used by the glibc + *             dynamic loader. Hopefully we will not need it for + *             uClibc. + */  #include <dl-sysdep.h> +#endif  #include "../nptl_db/thread_db.h"  #include <tls.h>  #ifdef HAVE_FORCED_UNWIND diff --git a/libpthread/nptl/init.c b/libpthread/nptl/init.c index c1e94e7ac..a5383625f 100644 --- a/libpthread/nptl/init.c +++ b/libpthread/nptl/init.c @@ -263,13 +263,13 @@ __pthread_initialize_minimal_internal (void)    sa.sa_flags = SA_SIGINFO;    __sigemptyset (&sa.sa_mask); -  (void) __libc_sigaction (SIGCANCEL, &sa, NULL); +  (void) sigaction (SIGCANCEL, &sa, NULL);    /* Install the handle to change the threads' uid/gid.  */    sa.sa_sigaction = sighandler_setxid;    sa.sa_flags = SA_SIGINFO | SA_RESTART; -  (void) __libc_sigaction (SIGSETXID, &sa, NULL); +  (void) sigaction (SIGSETXID, &sa, NULL);    /* The parent process might have left the signals blocked.  Just in       case, unblock it.  We reuse the signal mask in the sigaction @@ -295,7 +295,7 @@ __pthread_initialize_minimal_internal (void)    else      {        /* Round the resource limit up to page size.  */ -      const uintptr_t pagesz = __sysconf (_SC_PAGESIZE); +      const uintptr_t pagesz = sysconf (_SC_PAGESIZE);        __default_stacksize = (limit.rlim_cur + pagesz - 1) & -pagesz;      } diff --git a/libpthread/nptl/sysdeps/generic/lowlevellock.h b/libpthread/nptl/sysdeps/generic/lowlevellock.h new file mode 100644 index 000000000..7f95daada --- /dev/null +++ b/libpthread/nptl/sysdeps/generic/lowlevellock.h @@ -0,0 +1,89 @@ +/* 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 <atomic.h> + + +/* Implement generic mutex.  Basic futex syscall support is required: + +     lll_futex_wait(futex, value) - call sys_futex with FUTEX_WAIT +				    and third parameter VALUE + +     lll_futex_wake(futex, value) - call sys_futex with FUTEX_WAKE +				    and third parameter VALUE +*/ + + +/* Mutex lock counter: +   bit 31 clear means unlocked; +   bit 31 set means locked. + +   All code that looks at bit 31 first increases the 'number of +   interested threads' usage counter, which is in bits 0-30. + +   All negative mutex values indicate that the mutex is still locked.  */ + + +static inline void +__generic_mutex_lock (int *mutex) +{ +  unsigned int v; + +  /* Bit 31 was clear, we got the mutex.  (this is the fastpath).  */ +  if (atomic_bit_test_set (mutex, 31) == 0) +    return; + +  atomic_increment (mutex); + +  while (1) +    { +      if (atomic_bit_test_set (mutex, 31) == 0) +	{ +	  atomic_decrement (mutex); +	  return; +	} + +      /* We have to wait now. First make sure the futex value we are +	 monitoring is truly negative (i.e. locked). */ +      v = *mutex; +      if (v >= 0) +	continue; + +      lll_futex_wait (mutex, v); +    } +} + + +static inline void +__generic_mutex_unlock (int *mutex) +{ +  /* Adding 0x80000000 to the counter results in 0 if and only if +     there are not other interested threads - we can return (this is +     the fastpath).  */ +  if (atomic_add_zero (mutex, 0x80000000)) +    return; + +  /* There are other threads waiting for this mutex, wake one of them +     up.  */ +  lll_futex_wake (mutex, 1); +} + + +#define lll_mutex_lock(futex) __generic_mutex_lock (&(futex)) +#define lll_mutex_unlock(futex) __generic_mutex_unlock (&(futex)) diff --git a/libpthread/nptl/sysdeps/generic/pt-raise.c b/libpthread/nptl/sysdeps/generic/pt-raise.c new file mode 100644 index 000000000..59d9590e6 --- /dev/null +++ b/libpthread/nptl/sysdeps/generic/pt-raise.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 <signal.h> + + +int +raise (sig) +     int sig; +{ +  /* This is what POSIX says must happen.  */ +  return pthread_kill (pthread_self (), sig); +} diff --git a/libpthread/nptl/sysdeps/i386/tls.h b/libpthread/nptl/sysdeps/i386/tls.h index 06def42a5..c0331140f 100644 --- a/libpthread/nptl/sysdeps/i386/tls.h +++ b/libpthread/nptl/sysdeps/i386/tls.h @@ -1,5 +1,5 @@  /* Definition for thread-local data handling.  nptl/i386 version. -   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   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 @@ -102,11 +102,13 @@ union user_desc_init  /* Get the thread descriptor definition.  */  # include <nptl/descr.h> -/* This is the size of the initial TCB.  */ -# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) +/* This is the size of the initial TCB.  Can't be just sizeof (tcbhead_t), +   because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole +   struct pthread even when not linked with -lpthread.  */ +# define TLS_INIT_TCB_SIZE sizeof (struct pthread)  /* Alignment requirements for the initial TCB.  */ -# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)  /* This is the size of the TCB.  */  # define TLS_TCB_SIZE sizeof (struct pthread) diff --git a/libpthread/nptl/sysdeps/mips/tls.h b/libpthread/nptl/sysdeps/mips/tls.h index 1cef16101..2737488da 100644 --- a/libpthread/nptl/sysdeps/mips/tls.h +++ b/libpthread/nptl/sysdeps/mips/tls.h @@ -20,7 +20,14 @@  #ifndef _TLS_H  #define _TLS_H	1 +#if 0 +/* + * MIPS NPTL - defines a total of two symbols used by the glibc + *             dynamic loader. Hopefully we will not need it for + *             uClibc. + */  #include <dl-sysdep.h> +#endif  #ifndef __ASSEMBLER__  # include <stdbool.h> @@ -57,6 +64,15 @@ typedef union dtv  /* We require TLS support in the tools.  */ +#ifdef __PTHREADS_NATIVE__ +/* + * MIPS NPTL - HAVE_TLS_MODEL_ATTRIBUTE may need to be defined also and + *             is used in 'glibc/include/libc-symbols.h'. We will see if + *             it is needed later on. + */ +#define HAVE_TLS_SUPPORT	1 +#endif +  #ifndef HAVE_TLS_SUPPORT  # error "TLS support is required."  #endif @@ -73,7 +89,14 @@ typedef union dtv  # define TLS_DTV_AT_TP	1  /* Get the thread descriptor definition.  */ +#if 0 +/* + * MIPS NPTL - we have different include paths than glibc. + */  # include <nptl/descr.h> +#else +# include <descr.h> +#endif  typedef struct  { diff --git a/libpthread/nptl/sysdeps/pthread/Makefile b/libpthread/nptl/sysdeps/pthread/Makefile new file mode 100644 index 000000000..207e10fad --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/Makefile @@ -0,0 +1,52 @@ +# 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. + +ifeq ($(subdir),csu) +CFLAGS-libc-start.c += -I../nptl +routines += unwind-resume +shared-only-routines += unwind-resume +CFLAGS-unwind-resume.c += -fexceptions -fasynchronous-unwind-tables +endif + +ifeq ($(subdir),nptl) +libpthread-sysdep_routines += errno-loc +endif + +ifeq ($(subdir),rt) +librt-sysdep_routines += timer_routines librt-cancellation rt-unwind-resume +librt-shared-only-routines += rt-unwind-resume +CPPFLAGS-timer_routines.c = -I../nptl +CFLAGS-librt-cancellation.c += -fexceptions -fasynchronous-unwind-tables +CFLAGS-rt-unwind-resume.c += -fexceptions -fasynchronous-unwind-tables + +ifeq (yes,$(build-shared)) +$(objpfx)tst-timer: $(objpfx)librt.so $(shared-thread-library) +else +$(objpfx)tst-timer: $(objpfx)librt.a $(static-thread-library) +endif + +ifeq ($(have-forced-unwind),yes) +tests += tst-mqueue8x +CFLAGS-tst-mqueue8x.c += -fexceptions +endif +endif + +ifeq ($(subdir),posix) +CFLAGS-confstr.c += -DLIBPTHREAD_VERSION='"NPTL $(version)"' +endif diff --git a/libpthread/nptl/sysdeps/pthread/Subdirs b/libpthread/nptl/sysdeps/pthread/Subdirs new file mode 100644 index 000000000..4d1f4d876 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/Subdirs @@ -0,0 +1 @@ +nptl_db diff --git a/libpthread/nptl/sysdeps/pthread/allocalim.h b/libpthread/nptl/sysdeps/pthread/allocalim.h new file mode 100644 index 000000000..35224ec74 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/allocalim.h @@ -0,0 +1,29 @@ +/* Determine whether block of given size can be allocated on the stack or not. +   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 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 <alloca.h> +#include <limits.h> + + +extern inline int +__libc_use_alloca (size_t size) +{ +  return (__builtin_expect (size <= PTHREAD_STACK_MIN / 4, 1) +	  || __libc_alloca_cutoff (size)); +} diff --git a/libpthread/nptl/sysdeps/pthread/configure b/libpthread/nptl/sysdeps/pthread/configure new file mode 100755 index 000000000..3cbe55e14 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/configure @@ -0,0 +1,159 @@ +# This file is generated from configure.in by Autoconf.  DO NOT EDIT! + +if test "x$libc_cv_gcc___thread" != xyes; then +  { { echo "$as_me:$LINENO: error: compiler support for __thread is required" >&5 +echo "$as_me: error: compiler support for __thread is required" >&2;} +   { (exit 1); exit 1; }; } +fi + +if test "x${libc_cv_visibility_attribute}" != xyes || +   test "x${libc_cv_broken_visibility_attribute}" != xno; then +  { { echo "$as_me:$LINENO: error: working compiler support for visibility attribute is required" >&5 +echo "$as_me: error: working compiler support for visibility attribute is required" >&2;} +   { (exit 1); exit 1; }; } +fi + +if test "x$libc_cv_asm_cfi_directives" != xyes; then +    case "$base_machine" in +    i386 | x86_64 | powerpc | s390) +      { { echo "$as_me:$LINENO: error: CFI directive support in assembler is required" >&5 +echo "$as_me: error: CFI directive support in assembler is required" >&2;} +   { (exit 1); exit 1; }; } ;; +    *) ;; +  esac +fi + + +echo "$as_me:$LINENO: checking for forced unwind support" >&5 +echo $ECHO_N "checking for forced unwind support... $ECHO_C" >&6 +if test "${libc_cv_forced_unwind+set}" = set; then +  echo $ECHO_N "(cached) $ECHO_C" >&6 +else +  cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h.  */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h.  */ +#include <unwind.h> +int +main () +{ + +struct _Unwind_Exception exc; +struct _Unwind_Context *context; +_Unwind_GetCFA (context) +  ; +  return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 +  (eval $ac_link) 2>conftest.er1 +  ac_status=$? +  grep -v '^ *+' conftest.er1 >conftest.err +  rm -f conftest.er1 +  cat conftest.err >&5 +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); } && +	 { ac_try='test -z "$ac_c_werror_flag" +			 || test ! -s conftest.err' +  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 +  (eval $ac_try) 2>&5 +  ac_status=$? +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); }; } && +	 { ac_try='test -s conftest$ac_exeext' +  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 +  (eval $ac_try) 2>&5 +  ac_status=$? +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); }; }; then +  libc_cv_forced_unwind=yes +else +  echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +libc_cv_forced_unwind=no +fi +rm -f conftest.err conftest.$ac_objext \ +      conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $libc_cv_forced_unwind" >&5 +echo "${ECHO_T}$libc_cv_forced_unwind" >&6 +if test $libc_cv_forced_unwind = yes; then +  cat >>confdefs.h <<\_ACEOF +#define HAVE_FORCED_UNWIND 1 +_ACEOF + +  old_CFLAGS="$CFLAGS" +  CFLAGS="$CFLAGS -Werror -fexceptions" +  echo "$as_me:$LINENO: checking for C cleanup handling" >&5 +echo $ECHO_N "checking for C cleanup handling... $ECHO_C" >&6 +if test "${libc_cv_c_cleanup+set}" = set; then +  echo $ECHO_N "(cached) $ECHO_C" >&6 +else +    cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h.  */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h.  */ + +#include <stdio.h> +void cl (void *a) { } +int +main () +{ + +  int a __attribute__ ((cleanup (cl))); +  puts ("test") +  ; +  return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 +  (eval $ac_link) 2>conftest.er1 +  ac_status=$? +  grep -v '^ *+' conftest.er1 >conftest.err +  rm -f conftest.er1 +  cat conftest.err >&5 +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); } && +	 { ac_try='test -z "$ac_c_werror_flag" +			 || test ! -s conftest.err' +  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 +  (eval $ac_try) 2>&5 +  ac_status=$? +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); }; } && +	 { ac_try='test -s conftest$ac_exeext' +  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 +  (eval $ac_try) 2>&5 +  ac_status=$? +  echo "$as_me:$LINENO: \$? = $ac_status" >&5 +  (exit $ac_status); }; }; then +  libc_cv_c_cleanup=yes +else +  echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +libc_cv_c_cleanup=no +fi +rm -f conftest.err conftest.$ac_objext \ +      conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $libc_cv_c_cleanup" >&5 +echo "${ECHO_T}$libc_cv_c_cleanup" >&6 +  CFLAGS="$old_CFLAGS" +  if test $libc_cv_c_cleanup = no; then +    { { echo "$as_me:$LINENO: error: the compiler must support C cleanup handling" >&5 +echo "$as_me: error: the compiler must support C cleanup handling" >&2;} +   { (exit 1); exit 1; }; } +  fi +else +  { { echo "$as_me:$LINENO: error: forced unwind support is required" >&5 +echo "$as_me: error: forced unwind support is required" >&2;} +   { (exit 1); exit 1; }; } +fi diff --git a/libpthread/nptl/sysdeps/pthread/configure.in b/libpthread/nptl/sysdeps/pthread/configure.in new file mode 100644 index 000000000..17f18f0fb --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/configure.in @@ -0,0 +1,49 @@ +dnl configure fragment for new libpthread implementation. +GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. + +if test "x$libc_cv_gcc___thread" != xyes; then +  AC_MSG_ERROR(compiler support for __thread is required) +fi + +if test "x${libc_cv_visibility_attribute}" != xyes || +   test "x${libc_cv_broken_visibility_attribute}" != xno; then +  AC_MSG_ERROR(working compiler support for visibility attribute is required) +fi + +if test "x$libc_cv_asm_cfi_directives" != xyes; then +  dnl We need this only for some architectures. +  case "$base_machine" in +    i386 | x86_64 | powerpc | s390) +      AC_MSG_ERROR(CFI directive support in assembler is required) ;; +    *) ;; +  esac +fi + +dnl Iff <unwind.h> is available, make sure it is the right one and it +dnl contains struct _Unwind_Exception. +AC_CACHE_CHECK(dnl +for forced unwind support, libc_cv_forced_unwind, [dnl +AC_TRY_LINK([#include <unwind.h>], [ +struct _Unwind_Exception exc; +struct _Unwind_Context *context; +_Unwind_GetCFA (context)], +libc_cv_forced_unwind=yes, libc_cv_forced_unwind=no)]) +if test $libc_cv_forced_unwind = yes; then +  AC_DEFINE(HAVE_FORCED_UNWIND) +dnl Check for C cleanup handling. +  old_CFLAGS="$CFLAGS" +  CFLAGS="$CFLAGS -Werror -fexceptions" +  AC_CACHE_CHECK([for C cleanup handling], libc_cv_c_cleanup, [dnl +  AC_TRY_LINK([ +#include <stdio.h> +void cl (void *a) { }], [ +  int a __attribute__ ((cleanup (cl))); +  puts ("test")], +libc_cv_c_cleanup=yes, libc_cv_c_cleanup=no)]) +  CFLAGS="$old_CFLAGS" +  if test $libc_cv_c_cleanup = no; then +    AC_MSG_ERROR([the compiler must support C cleanup handling]) +  fi +else +  AC_MSG_ERROR(forced unwind support is required) +fi diff --git a/libpthread/nptl/sysdeps/pthread/createthread.c b/libpthread/nptl/sysdeps/pthread/createthread.c new file mode 100644 index 000000000..03a0f1aa3 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/createthread.c @@ -0,0 +1,255 @@ +/* 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 <sched.h> +#include <setjmp.h> +#include <signal.h> +#include <stdlib.h> +#include <atomic.h> +#include <ldsodefs.h> +#include <tls.h> + +#include "kernel-features.h" + + +#define CLONE_SIGNAL    	(CLONE_SIGHAND | CLONE_THREAD) + +/* Unless otherwise specified, the thread "register" is going to be +   initialized with a pointer to the TCB.  */ +#ifndef TLS_VALUE +# define TLS_VALUE pd +#endif + +#ifndef ARCH_CLONE +# define ARCH_CLONE __clone +#endif + + +#ifndef TLS_MULTIPLE_THREADS_IN_TCB +/* Pointer to the corresponding variable in libc.  */ +int *__libc_multiple_threads_ptr attribute_hidden; +#endif + + +static int +do_clone (struct pthread *pd, const struct pthread_attr *attr, +	  int clone_flags, int (*fct) (void *), STACK_VARIABLES_PARMS, +	  int stopped) +{ +#ifdef PREPARE_CREATE +  PREPARE_CREATE; +#endif + +  if (stopped) +    /* We Make sure the thread does not run far by forcing it to get a +       lock.  We lock it here too so that the new thread cannot continue +       until we tell it to.  */ +    lll_lock (pd->lock); + +  /* One more thread.  We cannot have the thread do this itself, since it +     might exist but not have been scheduled yet by the time we've returned +     and need to check the value to behave correctly.  We must do it before +     creating the thread, in case it does get scheduled first and then +     might mistakenly think it was the only thread.  In the failure case, +     we momentarily store a false value; this doesn't matter because there +     is no kosher thing a signal handler interrupting us right here can do +     that cares whether the thread count is correct.  */ +  atomic_increment (&__nptl_nthreads); + +  if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags, +		  pd, &pd->tid, TLS_VALUE, &pd->tid) == -1) +    { +      atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second.  */ + +      /* Failed.  If the thread is detached, remove the TCB here since +	 the caller cannot do this.  The caller remembered the thread +	 as detached and cannot reverify that it is not since it must +	 not access the thread descriptor again.  */ +      if (IS_DETACHED (pd)) +	__deallocate_stack (pd); + +      return errno; +    } + +  /* Now we have the possibility to set scheduling parameters etc.  */ +  if (__builtin_expect (stopped != 0, 0)) +    { +      INTERNAL_SYSCALL_DECL (err); +      int res = 0; + +      /* Set the affinity mask if necessary.  */ +      if (attr->cpuset != NULL) +	{ +	  res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, +				  sizeof (cpu_set_t), attr->cpuset); + +	  if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) +	    { +	      /* The operation failed.  We have to kill the thread.  First +		 send it the cancellation signal.  */ +	      INTERNAL_SYSCALL_DECL (err2); +	    err_out: +#if __ASSUME_TGKILL +	      (void) INTERNAL_SYSCALL (tgkill, err2, 3, +				       THREAD_GETMEM (THREAD_SELF, pid), +				       pd->tid, SIGCANCEL); +#else +	      (void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCANCEL); +#endif + +	      return (INTERNAL_SYSCALL_ERROR_P (res, err) +		      ? INTERNAL_SYSCALL_ERRNO (res, err) +		      : 0); +	    } +	} + +      /* Set the scheduling parameters.  */ +      if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0) +	{ +	  res = INTERNAL_SYSCALL (sched_setscheduler, err, 3, pd->tid, +				  pd->schedpolicy, &pd->schedparam); + +	  if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) +	    goto err_out; +	} +    } + +  /* We now have for sure more than one thread.  The main thread might +     not yet have the flag set.  No need to set the global variable +     again if this is what we use.  */ +  THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1); + +  return 0; +} + + +static int +create_thread (struct pthread *pd, const struct pthread_attr *attr, +	       STACK_VARIABLES_PARMS) +{ +#ifdef TLS_TCB_AT_TP +  assert (pd->header.tcb != NULL); +#endif + +  /* We rely heavily on various flags the CLONE function understands: + +     CLONE_VM, CLONE_FS, CLONE_FILES +	These flags select semantics with shared address space and +	file descriptors according to what POSIX requires. + +     CLONE_SIGNAL +	This flag selects the POSIX signal semantics. + +     CLONE_SETTLS +	The sixth parameter to CLONE determines the TLS area for the +	new thread. + +     CLONE_PARENT_SETTID +	The kernels writes the thread ID of the newly created thread +	into the location pointed to by the fifth parameters to CLONE. + +	Note that it would be semantically equivalent to use +	CLONE_CHILD_SETTID but it is be more expensive in the kernel. + +     CLONE_CHILD_CLEARTID +	The kernels clears the thread ID of a thread that has called +	sys_exit() in the location pointed to by the seventh parameter +	to CLONE. + +     CLONE_DETACHED +	No signal is generated if the thread exists and it is +	automatically reaped. + +     The termination signal is chosen to be zero which means no signal +     is sent.  */ +  int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL +		     | CLONE_SETTLS | CLONE_PARENT_SETTID +		     | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM +#if __ASSUME_NO_CLONE_DETACHED == 0 +		     | CLONE_DETACHED +#endif +		     | 0); + +  if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0)) +    { +      /* The parent thread is supposed to report events.  Check whether +	 the TD_CREATE event is needed, too.  */ +      const int _idx = __td_eventword (TD_CREATE); +      const uint32_t _mask = __td_eventmask (TD_CREATE); + +      if ((_mask & (__nptl_threads_events.event_bits[_idx] +		    | pd->eventbuf.eventmask.event_bits[_idx])) != 0) +	{ +	  /* We always must have the thread start stopped.  */ +	  pd->stopped_start = true; + +	  /* Create the thread.  We always create the thread stopped +	     so that it does not get far before we tell the debugger.  */ +	  int res = do_clone (pd, attr, clone_flags, start_thread, +			      STACK_VARIABLES_ARGS, 1); +	  if (res == 0) +	    { +	      /* Now fill in the information about the new thread in +		 the newly created thread's data structure.  We cannot let +		 the new thread do this since we don't know whether it was +		 already scheduled when we send the event.  */ +	      pd->eventbuf.eventnum = TD_CREATE; +	      pd->eventbuf.eventdata = pd; + +	      /* Enqueue the descriptor.  */ +	      do +		pd->nextevent = __nptl_last_event; +	      while (atomic_compare_and_exchange_bool_acq (&__nptl_last_event, +							   pd, pd->nextevent) +		     != 0); + +	      /* Now call the function which signals the event.  */ +	      __nptl_create_event (); + +	      /* And finally restart the new thread.  */ +	      lll_unlock (pd->lock); +	    } + +	  return res; +	} +    } + +#ifdef NEED_DL_SYSINFO +  assert (THREAD_SELF_SYSINFO == THREAD_SYSINFO (pd)); +#endif + +  /* Determine whether the newly created threads has to be started +     stopped since we have to set the scheduling parameters or set the +     affinity.  */ +  bool stopped = false; +  if (attr != NULL && (attr->cpuset != NULL +		       || (attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0)) +    stopped = true; +  pd->stopped_start = stopped; + +  /* Actually create the thread.  */ +  int res = do_clone (pd, attr, clone_flags, start_thread, +		      STACK_VARIABLES_ARGS, stopped); + +  if (res == 0 && stopped) +    /* And finally restart the new thread.  */ +    lll_unlock (pd->lock); + +  return res; +} diff --git a/libpthread/nptl/sysdeps/pthread/flockfile.c b/libpthread/nptl/sysdeps/pthread/flockfile.c new file mode 100644 index 000000000..918cb84f6 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/flockfile.c @@ -0,0 +1,33 @@ +/* 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 <stdio.h> +#include <libio.h> +#include <bits/stdio-lock.h> + + +void +__flockfile (stream) +     FILE *stream; +{ +  _IO_lock_lock (*stream->_lock); +} +strong_alias (__flockfile, _IO_flockfile) +weak_alias (__flockfile, flockfile) diff --git a/libpthread/nptl/sysdeps/pthread/ftrylockfile.c b/libpthread/nptl/sysdeps/pthread/ftrylockfile.c new file mode 100644 index 000000000..21c1ea01e --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/ftrylockfile.c @@ -0,0 +1,33 @@ +/* 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 <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <bits/stdio-lock.h> + + +int +__ftrylockfile (stream) +     FILE *stream; +{ +  return _IO_lock_trylock (*stream->_lock); +} +strong_alias (__ftrylockfile, _IO_ftrylockfile) +weak_alias (__ftrylockfile, ftrylockfile) diff --git a/libpthread/nptl/sysdeps/pthread/funlockfile.c b/libpthread/nptl/sysdeps/pthread/funlockfile.c new file mode 100644 index 000000000..f941fc985 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/funlockfile.c @@ -0,0 +1,33 @@ +/* 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 <stdio.h> +#include <libio.h> +#include <bits/stdio-lock.h> + + +void +__funlockfile (stream) +     FILE *stream; +{ +  _IO_lock_unlock (*stream->_lock); +} +strong_alias (__funlockfile, _IO_funlockfile) +weak_alias (__funlockfile, funlockfile) diff --git a/libpthread/nptl/sysdeps/pthread/librt-cancellation.c b/libpthread/nptl/sysdeps/pthread/librt-cancellation.c new file mode 100644 index 000000000..753a2d831 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/librt-cancellation.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 <setjmp.h> +#include <signal.h> +#include <stdlib.h> +#include "pthreadP.h" +#include "atomic.h" + + +#ifdef IS_IN_librt +/* The next two functions are similar to pthread_setcanceltype() but +   more specialized for the use in the cancelable functions like write(). +   They do not need to check parameters etc.  */ +int +attribute_hidden +__librt_enable_asynccancel (void) +{ +  struct pthread *self = THREAD_SELF; +  int oldval = THREAD_GETMEM (self, cancelhandling); + +  while (1) +    { +      int newval = oldval | CANCELTYPE_BITMASK; + +      if (__builtin_expect ((oldval & CANCELED_BITMASK) != 0, 0)) +	{ +	  /* If we are already exiting or if PTHREAD_CANCEL_DISABLED, +	     stop right here.  */ +	  if ((oldval & (EXITING_BITMASK | CANCELSTATE_BITMASK)) != 0) +	    break; + +	  int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, +						  newval, oldval); +	  if (__builtin_expect (curval != oldval, 0)) +	    { +	      /* Somebody else modified the word, try again.  */ +	      oldval = curval; +	      continue; +	    } + +	  THREAD_SETMEM (self, result, PTHREAD_CANCELED); + +	  __do_cancel (); + +	  /* NOTREACHED */ +	} + +      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, +					      oldval); +      if (__builtin_expect (curval == oldval, 1)) +	break; + +      /* Prepare the next round.  */ +      oldval = curval; +    } + +  return oldval; +} + + +void +internal_function attribute_hidden +__librt_disable_asynccancel (int oldtype) +{ +  /* If asynchronous cancellation was enabled before we do not have +     anything to do.  */ +  if (oldtype & CANCELTYPE_BITMASK) +    return; + +  struct pthread *self = THREAD_SELF; +  int oldval = THREAD_GETMEM (self, cancelhandling); + +  while (1) +    { +      int newval = oldval & ~CANCELTYPE_BITMASK; + +      if (newval == oldval) +	break; + +      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, +					      oldval); +      if (__builtin_expect (curval == oldval, 1)) +	break; + +      /* Prepare the next round.  */ +      oldval = curval; +    } +} + + +#endif diff --git a/libpthread/nptl/sysdeps/pthread/malloc-machine.h b/libpthread/nptl/sysdeps/pthread/malloc-machine.h new file mode 100644 index 000000000..efab230aa --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/malloc-machine.h @@ -0,0 +1,62 @@ +/* Basic platform-independent macro definitions for mutexes, +   thread-specific data and parameters for malloc. +   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 _MALLOC_MACHINE_H +#define _MALLOC_MACHINE_H + +#undef thread_atfork_static + +#include <atomic.h> +#include <bits/libc-lock.h> + +__libc_lock_define (typedef, mutex_t) + +#define mutex_init(m)		__libc_lock_init (*(m)) +#define mutex_lock(m)		__libc_lock_lock (*(m)) +#define mutex_trylock(m)	__libc_lock_trylock (*(m)) +#define mutex_unlock(m)		__libc_lock_unlock (*(m)) + +/* This is defined by newer gcc version unique for each module.  */ +extern void *__dso_handle __attribute__ ((__weak__)); + +#include <fork.h> + +#ifdef SHARED +# define thread_atfork(prepare, parent, child) \ +   __register_atfork (prepare, parent, child, __dso_handle) +#else +# define thread_atfork(prepare, parent, child) \ +   __register_atfork (prepare, parent, child,				      \ +		      &__dso_handle == NULL ? NULL : __dso_handle) +#endif + +/* thread specific data for glibc */ + +#include <bits/libc-tsd.h> + +typedef int tsd_key_t[1];	/* no key data structure, libc magic does it */ +__libc_tsd_define (static, MALLOC)	/* declaration/common definition */ +#define tsd_key_create(key, destr)	((void) (key)) +#define tsd_setspecific(key, data)	__libc_tsd_set (MALLOC, (data)) +#define tsd_getspecific(key, vptr)	((vptr) = __libc_tsd_get (MALLOC)) + +#include <sysdeps/generic/malloc-machine.h> + +#endif /* !defined(_MALLOC_MACHINE_H) */ diff --git a/libpthread/nptl/sysdeps/pthread/posix-timer.h b/libpthread/nptl/sysdeps/pthread/posix-timer.h new file mode 100644 index 000000000..8b4cbc8cd --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/posix-timer.h @@ -0,0 +1,197 @@ +/* Definitions for POSIX timer implementation on top of NPTL. +   Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + +   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 <limits.h> +#include <signal.h> + +/* Double linked list.  */ +struct list_links +{ +  struct list_links *next; +  struct list_links *prev; +}; + + +/* Forward declaration.  */ +struct timer_node; + + +/* Definitions for an internal thread of the POSIX timer implementation.  */ +struct thread_node +{ +  struct list_links links; +  pthread_attr_t attr; +  pthread_t id; +  unsigned int exists; +  struct list_links timer_queue; +  pthread_cond_t cond; +  struct timer_node *current_timer; +  pthread_t captured; +  clockid_t clock_id; +}; + + +/* Internal representation of a timer.  */ +struct timer_node +{ +  struct list_links links; +  struct sigevent event; +  clockid_t clock; +  struct itimerspec value; +  struct timespec expirytime; +  pthread_attr_t attr; +  unsigned int abstime; +  unsigned int armed; +  enum { +    TIMER_FREE, TIMER_INUSE, TIMER_DELETED +  } inuse; +  struct thread_node *thread; +  pid_t creator_pid; +  int refcount; +  int overrun_count; +}; + + +/* The limit is not published if we are compiled with kernel timer support. +   But we still compiled in this implementation with its limit unless built +   to require the kernel support.  */ +#ifndef TIMER_MAX +# define TIMER_MAX 256 +#endif + +/* Static array with the structures for all the timers.  */ +extern struct timer_node __timer_array[TIMER_MAX]; + +/* Global lock to protect operation on the lists.  */ +extern pthread_mutex_t __timer_mutex; + +/* Variable to protext initialization.  */ +extern pthread_once_t __timer_init_once_control; + +/* Nonzero if initialization of timer implementation failed.  */ +extern int __timer_init_failed; + +/* Node for the thread used to deliver signals.  */ +extern struct thread_node __timer_signal_thread_rclk; + + +/* Return pointer to timer structure corresponding to ID.  */ +#define timer_id2ptr(timerid) ((struct timer_node *) timerid) +#define timer_ptr2id(timerid) ((void *) timerid) + +/* Check whether timer is valid; global mutex must be held. */ +static inline int +timer_valid (struct timer_node *timer) +{ +  return timer && timer->inuse == TIMER_INUSE; +} + +/* Timer refcount functions; need global mutex. */ +extern void __timer_dealloc (struct timer_node *timer); + +static inline void +timer_addref (struct timer_node *timer) +{ +  timer->refcount++; +} + +static inline void +timer_delref (struct timer_node *timer) +{ +  if (--timer->refcount == 0) +    __timer_dealloc (timer); +} + +/* Timespec helper routines.  */ +static inline int +__attribute ((always_inline)) +timespec_compare (const struct timespec *left, const struct timespec *right) +{ +  if (left->tv_sec < right->tv_sec) +    return -1; +  if (left->tv_sec > right->tv_sec) +    return 1; + +  if (left->tv_nsec < right->tv_nsec) +    return -1; +  if (left->tv_nsec > right->tv_nsec) +    return 1; + +  return 0; +} + +static inline void +timespec_add (struct timespec *sum, const struct timespec *left, +	      const struct timespec *right) +{ +  sum->tv_sec = left->tv_sec + right->tv_sec; +  sum->tv_nsec = left->tv_nsec + right->tv_nsec; + +  if (sum->tv_nsec >= 1000000000) +    { +      ++sum->tv_sec; +      sum->tv_nsec -= 1000000000; +    } +} + +static inline void +timespec_sub (struct timespec *diff, const struct timespec *left, +	      const struct timespec *right) +{ +  diff->tv_sec = left->tv_sec - right->tv_sec; +  diff->tv_nsec = left->tv_nsec - right->tv_nsec; + +  if (diff->tv_nsec < 0) +    { +      --diff->tv_sec; +      diff->tv_nsec += 1000000000; +    } +} + + +/* We need one of the list functions in the other modules.  */ +static inline void +list_unlink_ip (struct list_links *list) +{ +  struct list_links *lnext = list->next, *lprev = list->prev; + +  lnext->prev = lprev; +  lprev->next = lnext; + +  /* The suffix ip means idempotent; list_unlink_ip can be called +   * two or more times on the same node. +   */ + +  list->next = list; +  list->prev = list; +} + + +/* Functions in the helper file.  */ +extern void __timer_mutex_cancel_handler (void *arg); +extern void __timer_init_once (void); +extern struct timer_node *__timer_alloc (void); +extern int __timer_thread_start (struct thread_node *thread); +extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t); +extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t); +extern void __timer_thread_dealloc (struct thread_node *thread); +extern int __timer_thread_queue_timer (struct thread_node *thread, +				       struct timer_node *insert); +extern void __timer_thread_wakeup (struct thread_node *thread); diff --git a/libpthread/nptl/sysdeps/pthread/pt-initfini.c b/libpthread/nptl/sysdeps/pthread/pt-initfini.c new file mode 100644 index 000000000..1e35edd3e --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pt-initfini.c @@ -0,0 +1,125 @@ +/* Special .init and .fini section support.  Linuxthread version. +   Copyright (C) 1995,1996,1997,2000,2001,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 of the License, or (at your option) any later version. + +   In addition to the permissions in the GNU Lesser 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 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, 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. */ + +#include <stdlib.h> + +/* We use embedded asm for .section unconditionally, as this makes it +   easier to insert the necessary directives into crtn.S. */ +#define SECTION(x) asm (".section " x ) + +/* Embed an #include to pull in the alignment and .end directives. */ +asm ("\n#include \"defs.h\""); + +/* The initial common code ends here. */ +asm ("\n/*@HEADER_ENDS*/"); + +/* To determine whether we need .end and .align: */ +asm ("\n/*@TESTS_BEGIN*/"); +extern void dummy (void (*foo) (void)); +void +dummy (void (*foo) (void)) +{ +  if (foo) +    (*foo) (); +} +asm ("\n/*@TESTS_END*/"); + +/* The beginning of _init:  */ +asm ("\n/*@_init_PROLOG_BEGINS*/"); + +static void +call_initialize_minimal (void) +{ +  extern void __pthread_initialize_minimal_internal (void) +    __attribute ((visibility ("hidden"))); + +  __pthread_initialize_minimal_internal (); +} + +SECTION (".init"); +extern void _init (void); +void +_init (void) +{ +  /* The very first thing we must do is to set up the registers.  */ +  call_initialize_minimal (); + +  asm ("ALIGN"); +  asm("END_INIT"); +  /* Now the epilog. */ +  asm ("\n/*@_init_PROLOG_ENDS*/"); +  asm ("\n/*@_init_EPILOG_BEGINS*/"); +  SECTION(".init"); +} +asm ("END_INIT"); + +/* End of the _init epilog, beginning of the _fini prolog. */ +asm ("\n/*@_init_EPILOG_ENDS*/"); +asm ("\n/*@_fini_PROLOG_BEGINS*/"); + +SECTION (".fini"); +extern void _fini (void); +void +_fini (void) +{ + +  /* End of the _fini prolog. */ +  asm ("ALIGN"); +  asm ("END_FINI"); +  asm ("\n/*@_fini_PROLOG_ENDS*/"); + +  { +    /* Let GCC know that _fini is not a leaf function by having a dummy +       function call here.  We arrange for this call to be omitted from +       either crt file.  */ +    extern void i_am_not_a_leaf (void); +    i_am_not_a_leaf (); +  } + +  /* Beginning of the _fini epilog. */ +  asm ("\n/*@_fini_EPILOG_BEGINS*/"); +  SECTION (".fini"); +} +asm ("END_FINI"); + +/* End of the _fini epilog.  Any further generated assembly (e.g. .ident) +   is shared between both crt files. */ +asm ("\n/*@_fini_EPILOG_ENDS*/"); +asm ("\n/*@TRAILER_BEGINS*/"); + +/* End of file. */ diff --git a/libpthread/nptl/sysdeps/pthread/pt-longjmp.c b/libpthread/nptl/sysdeps/pthread/pt-longjmp.c new file mode 100644 index 000000000..f161380ea --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pt-longjmp.c @@ -0,0 +1,29 @@ +/* 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 "pthreadP.h" + +void +longjmp (jmp_buf env, int val) +{ +  __libc_longjmp (env, val); +} +weak_alias (longjmp, siglongjmp) diff --git a/libpthread/nptl/sysdeps/pthread/pthread-functions.h b/libpthread/nptl/sysdeps/pthread/pthread-functions.h new file mode 100644 index 000000000..d75bbbb11 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread-functions.h @@ -0,0 +1,103 @@ +/* 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; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifndef _PTHREAD_FUNCTIONS_H +#define _PTHREAD_FUNCTIONS_H	1 + +#include <pthread.h> +#include <setjmp.h> +#include <internaltypes.h> + +struct xid_command; + +/* Data type shared with libc.  The libc uses it to pass on calls to +   the thread functions.  */ +struct pthread_functions +{ +  int (*ptr_pthread_attr_destroy) (pthread_attr_t *); +  int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *); +  int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *); +  int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); +  int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); +  int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); +  int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); +  int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, +					 struct sched_param *); +  int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, +					 const struct sched_param *); +  int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); +  int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); +  int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); +  int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); +  int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); +  int (*ptr_pthread_condattr_init) (pthread_condattr_t *); +  int (*ptr___pthread_cond_broadcast) (pthread_cond_t *); +  int (*ptr___pthread_cond_destroy) (pthread_cond_t *); +  int (*ptr___pthread_cond_init) (pthread_cond_t *, +				  const pthread_condattr_t *); +  int (*ptr___pthread_cond_signal) (pthread_cond_t *); +  int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); +  int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, +				       const struct timespec *); +  int (*ptr___pthread_cond_broadcast_2_0) (pthread_cond_2_0_t *); +  int (*ptr___pthread_cond_destroy_2_0) (pthread_cond_2_0_t *); +  int (*ptr___pthread_cond_init_2_0) (pthread_cond_2_0_t *, +				      const pthread_condattr_t *); +  int (*ptr___pthread_cond_signal_2_0) (pthread_cond_2_0_t *); +  int (*ptr___pthread_cond_wait_2_0) (pthread_cond_2_0_t *, pthread_mutex_t *); +  int (*ptr___pthread_cond_timedwait_2_0) (pthread_cond_2_0_t *, +					   pthread_mutex_t *, +					   const struct timespec *); +  int (*ptr_pthread_equal) (pthread_t, pthread_t); +  void (*ptr___pthread_exit) (void *); +  int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); +  int (*ptr_pthread_setschedparam) (pthread_t, int, +				    const struct sched_param *); +  int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); +  int (*ptr_pthread_mutex_init) (pthread_mutex_t *, +				 const pthread_mutexattr_t *); +  int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); +  int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); +  pthread_t (*ptr_pthread_self) (void); +  int (*ptr_pthread_setcancelstate) (int, int *); +  int (*ptr_pthread_setcanceltype) (int, int *); +  void (*ptr___pthread_cleanup_upto) (__jmp_buf, char *); +  int (*ptr___pthread_once) (pthread_once_t *, void (*) (void)); +  int (*ptr___pthread_rwlock_rdlock) (pthread_rwlock_t *); +  int (*ptr___pthread_rwlock_wrlock) (pthread_rwlock_t *); +  int (*ptr___pthread_rwlock_unlock) (pthread_rwlock_t *); +  int (*ptr___pthread_key_create) (pthread_key_t *, void (*) (void *)); +  void *(*ptr___pthread_getspecific) (pthread_key_t); +  int (*ptr___pthread_setspecific) (pthread_key_t, const void *); +  void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer *, +					   void (*) (void *), void *); +  void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer *, +					    int); +#define HAVE_PTR_NTHREADS +  unsigned int *ptr_nthreads; +  void (*ptr___pthread_unwind) (__pthread_unwind_buf_t *) +       __attribute ((noreturn)) __cleanup_fct_attribute; +  void (*ptr__nptl_deallocate_tsd) (void); +  int (*ptr__nptl_setxid) (struct xid_command *); +}; + +/* Variable in libc.so.  */ +extern struct pthread_functions __libc_pthread_functions attribute_hidden; + +#endif	/* pthread-functions.h */ diff --git a/libpthread/nptl/sysdeps/pthread/pthread.h b/libpthread/nptl/sysdeps/pthread/pthread.h new file mode 100644 index 000000000..9bc104d31 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread.h @@ -0,0 +1,962 @@ +/* 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.  */ + +#ifndef _PTHREAD_H +#define _PTHREAD_H	1 + +#include <features.h> +#include <sched.h> +#include <time.h> + +#define __need_sigset_t +#include <signal.h> +#include <bits/pthreadtypes.h> +#include <setjmp.h> +#include <bits/wordsize.h> + + +/* Detach state.  */ +enum +{ +  PTHREAD_CREATE_JOINABLE, +#define PTHREAD_CREATE_JOINABLE	PTHREAD_CREATE_JOINABLE +  PTHREAD_CREATE_DETACHED +#define PTHREAD_CREATE_DETACHED	PTHREAD_CREATE_DETACHED +}; + + +/* Mutex types.  */ +enum +{ +  PTHREAD_MUTEX_TIMED_NP, +  PTHREAD_MUTEX_RECURSIVE_NP, +  PTHREAD_MUTEX_ERRORCHECK_NP, +  PTHREAD_MUTEX_ADAPTIVE_NP +#ifdef __USE_UNIX98 +  , +  PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP, +  PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, +  PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, +  PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +#endif +#ifdef __USE_GNU +  /* For compatibility.  */ +  , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP +#endif +}; + +/* Mutex initializers.  */ +#define PTHREAD_MUTEX_INITIALIZER \ +  { { 0, } } +#ifdef __USE_GNU +# if __WORDSIZE == 64 +#  define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ +  { { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP } } +#  define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ +  { { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP } } +#  define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ +  { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP } } +# else +#  define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ +  { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP } } +#  define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ +  { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP } } +#  define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ +  { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP } } +# endif +#endif + + +/* Read-write lock types.  */ +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +enum +{ +  PTHREAD_RWLOCK_PREFER_READER_NP, +  PTHREAD_RWLOCK_PREFER_WRITER_NP, +  PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, +  PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_READER_NP +}; + +/* Read-write lock initializers.  */ +# define PTHREAD_RWLOCK_INITIALIZER \ +  { { 0, } } +# ifdef __USE_GNU +#  if __WORDSIZE == 64 +#   define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ +  { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,					      \ +      PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP } } +#  else +#   define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ +  { { 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP } } +#  endif +# endif +#endif  /* Unix98 or XOpen2K */ + + +/* Scheduler inheritance.  */ +enum +{ +  PTHREAD_INHERIT_SCHED, +#define PTHREAD_INHERIT_SCHED   PTHREAD_INHERIT_SCHED +  PTHREAD_EXPLICIT_SCHED +#define PTHREAD_EXPLICIT_SCHED  PTHREAD_EXPLICIT_SCHED +}; + + +/* Scope handling.  */ +enum +{ +  PTHREAD_SCOPE_SYSTEM, +#define PTHREAD_SCOPE_SYSTEM    PTHREAD_SCOPE_SYSTEM +  PTHREAD_SCOPE_PROCESS +#define PTHREAD_SCOPE_PROCESS   PTHREAD_SCOPE_PROCESS +}; + + +/* Process shared or private flag.  */ +enum +{ +  PTHREAD_PROCESS_PRIVATE, +#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE +  PTHREAD_PROCESS_SHARED +#define PTHREAD_PROCESS_SHARED  PTHREAD_PROCESS_SHARED +}; + + + +/* Conditional variable handling.  */ +#define PTHREAD_COND_INITIALIZER { { 0, } } + + +/* Cleanup buffers */ +struct _pthread_cleanup_buffer +{ +  void (*__routine) (void *);             /* Function to call.  */ +  void *__arg;                            /* Its argument.  */ +  int __canceltype;                       /* Saved cancellation type. */ +  struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions.  */ +}; + +/* Cancellation */ +enum +{ +  PTHREAD_CANCEL_ENABLE, +#define PTHREAD_CANCEL_ENABLE   PTHREAD_CANCEL_ENABLE +  PTHREAD_CANCEL_DISABLE +#define PTHREAD_CANCEL_DISABLE  PTHREAD_CANCEL_DISABLE +}; +enum +{ +  PTHREAD_CANCEL_DEFERRED, +#define PTHREAD_CANCEL_DEFERRED	PTHREAD_CANCEL_DEFERRED +  PTHREAD_CANCEL_ASYNCHRONOUS +#define PTHREAD_CANCEL_ASYNCHRONOUS	PTHREAD_CANCEL_ASYNCHRONOUS +}; +#define PTHREAD_CANCELED ((void *) -1) + + +/* Single execution handling.  */ +#define PTHREAD_ONCE_INIT 0 + + +#ifdef __USE_XOPEN2K +/* Value returned by 'pthread_barrier_wait' for one of the threads after +   the required number of threads have called this function. +   -1 is distinct from 0 and all errno constants */ +# define PTHREAD_BARRIER_SERIAL_THREAD -1 +#endif + + +__BEGIN_DECLS + +/* Create a new thread, starting with execution of START-ROUTINE +   getting passed ARG.  Creation attributed come from ATTR.  The new +   handle is stored in *NEWTHREAD.  */ +extern int pthread_create (pthread_t *__restrict __newthread, +			   __const pthread_attr_t *__restrict __attr, +			   void *(*__start_routine) (void *), +			   void *__restrict __arg) __THROW; + +/* Terminate calling thread. + +   The registered cleanup handlers are called via exception handling +   so we cannot mark this function with __THROW.*/ +extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__)); + +/* Make calling thread wait for termination of the thread TH.  The +   exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN +   is not NULL. + +   This function is a cancellation point and therefore not marked with +   __THROW.  */ +extern int pthread_join (pthread_t __th, void **__thread_return); + +#ifdef __USE_GNU +/* Check whether thread TH has terminated.  If yes return the status of +   the thread in *THREAD_RETURN, if THREAD_RETURN is not NULL.  */ +extern int pthread_tryjoin_np (pthread_t __th, void **__thread_return) __THROW; + +/* Make calling thread wait for termination of the thread TH, but only +   until TIMEOUT.  The exit status of the thread is stored in +   *THREAD_RETURN, if THREAD_RETURN is not NULL. + +   This function is a cancellation point and therefore not marked with +   __THROW.  */ +extern int pthread_timedjoin_np (pthread_t __th, void **__thread_return, +				 __const struct timespec *__abstime); +#endif + +/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN. +   The resources of TH will therefore be freed immediately when it +   terminates, instead of waiting for another thread to perform PTHREAD_JOIN +   on it.  */ +extern int pthread_detach (pthread_t __th) __THROW; + + +/* Obtain the identifier of the current thread.  */ +extern pthread_t pthread_self (void) __THROW __attribute__ ((__const__)); + +/* Compare two thread identifiers.  */ +extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW; + + +/* Thread attribute handling.  */ + +/* Initialize thread attribute *ATTR with default attributes +   (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER, +    no user-provided stack).  */ +extern int pthread_attr_init (pthread_attr_t *__attr) __THROW; + +/* Destroy thread attribute *ATTR.  */ +extern int pthread_attr_destroy (pthread_attr_t *__attr) __THROW; + +/* Get detach state attribute.  */ +extern int pthread_attr_getdetachstate (__const pthread_attr_t *__attr, +					int *__detachstate) __THROW; + +/* Set detach state attribute.  */ +extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, +					int __detachstate) __THROW; + + +/* Get the size of the guard area created for stack overflow protection.  */ +extern int pthread_attr_getguardsize (__const pthread_attr_t *__attr, +				      size_t *__guardsize) __THROW; + +/* Set the size of the guard area created for stack overflow protection.  */ +extern int pthread_attr_setguardsize (pthread_attr_t *__attr, +				      size_t __guardsize) __THROW; + + +/* Return in *PARAM the scheduling parameters of *ATTR.  */ +extern int pthread_attr_getschedparam (__const pthread_attr_t *__restrict +				       __attr, +				       struct sched_param *__restrict __param) +     __THROW; + +/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM.  */ +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, +				       __const struct sched_param *__restrict +				       __param) __THROW; + +/* Return in *POLICY the scheduling policy of *ATTR.  */ +extern int pthread_attr_getschedpolicy (__const pthread_attr_t *__restrict +					__attr, int *__restrict __policy) +     __THROW; + +/* Set scheduling policy in *ATTR according to POLICY.  */ +extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy) +     __THROW; + +/* Return in *INHERIT the scheduling inheritance mode of *ATTR.  */ +extern int pthread_attr_getinheritsched (__const pthread_attr_t *__restrict +					 __attr, int *__restrict __inherit) +     __THROW; + +/* Set scheduling inheritance mode in *ATTR according to INHERIT.  */ +extern int pthread_attr_setinheritsched (pthread_attr_t *__attr, +					 int __inherit) __THROW; + + +/* Return in *SCOPE the scheduling contention scope of *ATTR.  */ +extern int pthread_attr_getscope (__const pthread_attr_t *__restrict __attr, +				  int *__restrict __scope) __THROW; + +/* Set scheduling contention scope in *ATTR according to SCOPE.  */ +extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope) +     __THROW; + +/* Return the previously set address for the stack.  */ +extern int pthread_attr_getstackaddr (__const pthread_attr_t *__restrict +				      __attr, void **__restrict __stackaddr) +     __THROW __attribute_deprecated__; + +/* Set the starting address of the stack of the thread to be created. +   Depending on whether the stack grows up or down the value must either +   be higher or lower than all the address in the memory block.  The +   minimal size of the block must be PTHREAD_STACK_MIN.  */ +extern int pthread_attr_setstackaddr (pthread_attr_t *__attr, +				      void *__stackaddr) +     __THROW __attribute_deprecated__; + +/* Return the currently used minimal stack size.  */ +extern int pthread_attr_getstacksize (__const pthread_attr_t *__restrict +				      __attr, size_t *__restrict __stacksize) +     __THROW; + +/* Add information about the minimum stack size needed for the thread +   to be started.  This size must never be less than PTHREAD_STACK_MIN +   and must also not exceed the system limits.  */ +extern int pthread_attr_setstacksize (pthread_attr_t *__attr, +				      size_t __stacksize) __THROW; + +#ifdef __USE_XOPEN2K +/* Return the previously set address for the stack.  */ +extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr, +				  void **__restrict __stackaddr, +				  size_t *__restrict __stacksize) __THROW; + +/* The following two interfaces are intended to replace the last two.  They +   require setting the address as well as the size since only setting the +   address will make the implementation on some architectures impossible.  */ +extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, +				  size_t __stacksize) __THROW; +#endif + +#ifdef __USE_GNU +/* Thread created with attribute ATTR will be limited to run only on +   the processors represented in CPUSET.  */ +extern int pthread_attr_setaffinity_np (pthread_attr_t *__attr, +					size_t __cpusetsize, +					__const cpu_set_t *__cpuset) __THROW; + +/* Get bit set in CPUSET representing the processors threads created with +   ATTR can run on.  */ +extern int pthread_attr_getaffinity_np (__const pthread_attr_t *__attr, +					size_t __cpusetsize, +					cpu_set_t *__cpuset) __THROW; + + +/* Initialize thread attribute *ATTR with attributes corresponding to the +   already running thread TH.  It shall be called on unitialized ATTR +   and destroyed with pthread_attr_destroy when no longer needed.  */ +extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW; +#endif + + +/* Functions for scheduling control.  */ + +/* Set the scheduling parameters for TARGET_THREAD according to POLICY +   and *PARAM.  */ +extern int pthread_setschedparam (pthread_t __target_thread, int __policy, +				  __const struct sched_param *__param) +     __THROW; + +/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */ +extern int pthread_getschedparam (pthread_t __target_thread, +				  int *__restrict __policy, +				  struct sched_param *__restrict __param) +     __THROW; + +/* Set the scheduling priority for TARGET_THREAD.  */ +extern int pthread_setschedprio (pthread_t __target_thread, int __prio) +     __THROW; + + +#ifdef __USE_UNIX98 +/* Determine level of concurrency.  */ +extern int pthread_getconcurrency (void) __THROW; + +/* Set new concurrency level to LEVEL.  */ +extern int pthread_setconcurrency (int __level) __THROW; +#endif + +#ifdef __USE_GNU +/* Yield the processor to another thread or process. +   This function is similar to the POSIX `sched_yield' function but +   might be differently implemented in the case of a m-on-n thread +   implementation.  */ +extern int pthread_yield (void) __THROW; + + +/* Limit specified thread TH to run only on the processors represented +   in CPUSET.  */ +extern int pthread_setaffinity_np (pthread_t __th, size_t __cpusetsize, +				   __const cpu_set_t *__cpuset) __THROW; + +/* Get bit set in CPUSET representing the processors TH can run on.  */ +extern int pthread_getaffinity_np (pthread_t __th, size_t __cpusetsize, +				   cpu_set_t *__cpuset) __THROW; +#endif + + +/* Functions for handling initialization.  */ + +/* Guarantee that the initialization function INIT_ROUTINE will be called +   only once, even if pthread_once is executed several times with the +   same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or +   extern variable initialized to PTHREAD_ONCE_INIT. + +   The initialization functions might throw exception which is why +   this function is not marked with __THROW.  */ +extern int pthread_once (pthread_once_t *__once_control, +			 void (*__init_routine) (void)); + + +/* Functions for handling cancellation. + +   Note that these functions are explicitly not marked to not throw an +   exception in C++ code.  If cancellation is implemented by unwinding +   this is necessary to have the compiler generate the unwind information.  */ + +/* Set cancelability state of current thread to STATE, returning old +   state in *OLDSTATE if OLDSTATE is not NULL.  */ +extern int pthread_setcancelstate (int __state, int *__oldstate); + +/* Set cancellation state of current thread to TYPE, returning the old +   type in *OLDTYPE if OLDTYPE is not NULL.  */ +extern int pthread_setcanceltype (int __type, int *__oldtype); + +/* Cancel THREAD immediately or at the next possibility.  */ +extern int pthread_cancel (pthread_t __th); + +/* Test for pending cancellation for the current thread and terminate +   the thread as per pthread_exit(PTHREAD_CANCELED) if it has been +   cancelled.  */ +extern void pthread_testcancel (void); + + +/* Cancellation handling with integration into exception handling.  */ + +typedef struct +{ +  struct +  { +    __jmp_buf __cancel_jmp_buf; +    int __mask_was_saved; +  } __cancel_jmp_buf[1]; +  void *__pad[4]; +} __pthread_unwind_buf_t __attribute__ ((__aligned__)); + +/* No special attributes by default.  */ +#ifndef __cleanup_fct_attribute +# define __cleanup_fct_attribute +#endif + + +/* Structure to hold the cleanup handler information.  */ +struct __pthread_cleanup_frame +{ +  void (*__cancel_routine) (void *); +  void *__cancel_arg; +  int __do_it; +  int __cancel_type; +}; + +#if defined __GNUC__ && defined __EXCEPTIONS +# ifdef __cplusplus +/* Class to handle cancellation handler invocation.  */ +class __pthread_cleanup_class +{ +  void (*__cancel_routine) (void *); +  void *__cancel_arg; +  int __do_it; +  int __cancel_type; + + public: +  __pthread_cleanup_class (void (*__fct) (void *), void *__arg) +    : __cancel_routine (__fct), __cancel_arg (__arg), __do_it (1) { } +  ~__pthread_cleanup_class () { if (__do_it) __cancel_routine (__cancel_arg); } +  void __setdoit (int __newval) { __do_it = __newval; } +  void __defer () { pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, +					   &__cancel_type); } +  void __restore () const { pthread_setcanceltype (__cancel_type, 0); } +}; + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG +   when the thread is canceled or calls pthread_exit.  ROUTINE will also +   be called with arguments ARG when the matching pthread_cleanup_pop +   is executed with non-zero EXECUTE argument. + +   pthread_cleanup_push and pthread_cleanup_pop are macros and must always +   be used in matching pairs at the same nesting level of braces.  */ +#  define pthread_cleanup_push(routine, arg) \ +  do {									      \ +    __pthread_cleanup_class __clframe (routine, arg) + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. +   If EXECUTE is non-zero, the handler function is called. */ +#  define pthread_cleanup_pop(execute) \ +    __clframe.__setdoit (execute);					      \ +  } while (0) + +#  ifdef __USE_GNU +/* Install a cleanup handler as pthread_cleanup_push does, but also +   saves the current cancellation type and sets it to deferred +   cancellation.  */ +#   define pthread_cleanup_push_defer_np(routine, arg) \ +  do {									      \ +    __pthread_cleanup_class __clframe (routine, arg);			      \ +    __clframe.__defer () + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also +   restores the cancellation type that was in effect when the matching +   pthread_cleanup_push_defer was called.  */ +#   define pthread_cleanup_pop_restore_np(execute) \ +    __clframe.__restore ();						      \ +    __clframe.__setdoit (execute);					      \ +  } while (0) +#  endif +# else +/* Function called to call the cleanup handler.  As an extern inline +   function the compiler is free to decide inlining the change when +   needed or fall back on the copy which must exist somewhere +   else.  */ +extern __inline void +__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame) +{ +  if (__frame->__do_it) +    __frame->__cancel_routine (__frame->__cancel_arg); +} + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG +   when the thread is canceled or calls pthread_exit.  ROUTINE will also +   be called with arguments ARG when the matching pthread_cleanup_pop +   is executed with non-zero EXECUTE argument. + +   pthread_cleanup_push and pthread_cleanup_pop are macros and must always +   be used in matching pairs at the same nesting level of braces.  */ +#  define pthread_cleanup_push(routine, arg) \ +  do {									      \ +    struct __pthread_cleanup_frame __clframe				      \ +      __attribute__ ((__cleanup__ (__pthread_cleanup_routine)))		      \ +      = { .__cancel_routine = (routine), .__cancel_arg = (arg),	 	      \ +	  .__do_it = 1 }; + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. +   If EXECUTE is non-zero, the handler function is called. */ +#  define pthread_cleanup_pop(execute) \ +    __clframe.__do_it = (execute);					      \ +  } while (0) + +#  ifdef __USE_GNU +/* Install a cleanup handler as pthread_cleanup_push does, but also +   saves the current cancellation type and sets it to deferred +   cancellation.  */ +#   define pthread_cleanup_push_defer_np(routine, arg) \ +  do {									      \ +    struct __pthread_cleanup_frame __clframe				      \ +      __attribute__ ((__cleanup__ (__pthread_cleanup_routine)))		      \ +      = { .__cancel_routine = (routine), .__cancel_arg = (arg),		      \ +	  .__do_it = 1 };						      \ +    (void) pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED,		      \ +				  &__clframe.__cancel_type) + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also +   restores the cancellation type that was in effect when the matching +   pthread_cleanup_push_defer was called.  */ +#   define pthread_cleanup_pop_restore_np(execute) \ +    (void) pthread_setcanceltype (__clframe.__cancel_type, NULL);	      \ +    __clframe.__do_it = (execute);					      \ +  } while (0) +#  endif +# endif +#else +/* Install a cleanup handler: ROUTINE will be called with arguments ARG +   when the thread is canceled or calls pthread_exit.  ROUTINE will also +   be called with arguments ARG when the matching pthread_cleanup_pop +   is executed with non-zero EXECUTE argument. + +   pthread_cleanup_push and pthread_cleanup_pop are macros and must always +   be used in matching pairs at the same nesting level of braces.  */ +# define pthread_cleanup_push(routine, arg) \ +  do {									      \ +    __pthread_unwind_buf_t __cancel_buf;				      \ +    void (*__cancel_routine) (void *) = (routine);			      \ +    void *__cancel_arg = (arg);						      \ +    int not_first_call = __sigsetjmp ((struct __jmp_buf_tag *)		      \ +				      __cancel_buf.__cancel_jmp_buf, 0);      \ +    if (__builtin_expect (not_first_call, 0))				      \ +      {									      \ +	__cancel_routine (__cancel_arg);				      \ +	__pthread_unwind_next (&__cancel_buf);				      \ +	/* NOTREACHED */						      \ +      }									      \ +									      \ +    __pthread_register_cancel (&__cancel_buf);				      \ +    do { +extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf) +     __cleanup_fct_attribute; + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. +   If EXECUTE is non-zero, the handler function is called. */ +# define pthread_cleanup_pop(execute) \ +    } while (0);							      \ +    __pthread_unregister_cancel (&__cancel_buf);			      \ +    if (execute)							      \ +      __cancel_routine (__cancel_arg);					      \ +  } while (0) +extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf) +  __cleanup_fct_attribute; + +# ifdef __USE_GNU +/* Install a cleanup handler as pthread_cleanup_push does, but also +   saves the current cancellation type and sets it to deferred +   cancellation.  */ +#  define pthread_cleanup_push_defer_np(routine, arg) \ +  do {									      \ +    __pthread_unwind_buf_t __cancel_buf;				      \ +    void (*__cancel_routine) (void *) = (routine);			      \ +    void *__cancel_arg = (arg);						      \ +    int not_first_call = __sigsetjmp ((struct __jmp_buf_tag *)		      \ +				      __cancel_buf.__cancel_jmp_buf, 0);      \ +    if (__builtin_expect (not_first_call, 0))				      \ +      {									      \ +	__cancel_routine (__cancel_arg);				      \ +	__pthread_unwind_next (&__cancel_buf);				      \ +	/* NOTREACHED */						      \ +      }									      \ +									      \ +    __pthread_register_cancel_defer (&__cancel_buf);			      \ +    do { +extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf) +     __cleanup_fct_attribute; + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also +   restores the cancellation type that was in effect when the matching +   pthread_cleanup_push_defer was called.  */ +#  define pthread_cleanup_pop_restore_np(execute) \ +    } while (0);							      \ +    __pthread_unregister_cancel_restore (&__cancel_buf);		      \ +    if (execute)							      \ +      __cancel_routine (__cancel_arg);					      \ +  } while (0) +extern void __pthread_unregister_cancel_restore (__pthread_unwind_buf_t *__buf) +  __cleanup_fct_attribute; +# endif + +/* Internal interface to initiate cleanup.  */ +extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) +     __cleanup_fct_attribute __attribute ((__noreturn__)) +# ifndef SHARED +     __attribute ((__weak__)) +# endif +     ; +#endif + +/* Function used in the macros.  */ +struct __jmp_buf_tag; +extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROW; + + +/* Mutex handling.  */ + +/* Initialize a mutex.  */ +extern int pthread_mutex_init (pthread_mutex_t *__mutex, +			       __const pthread_mutexattr_t *__mutexattr) +     __THROW; + +/* Destroy a mutex.  */ +extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW; + +/* Try locking a mutex.  */ +extern int pthread_mutex_trylock (pthread_mutex_t *_mutex) __THROW; + +/* Lock a mutex.  */ +extern int pthread_mutex_lock (pthread_mutex_t *__mutex) __THROW; + +#ifdef __USE_XOPEN2K +/* Wait until lock becomes available, or specified time passes. */ +extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, +                                    __const struct timespec *__restrict +                                    __abstime) __THROW; +#endif + +/* Unlock a mutex.  */ +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW; + + +/* Functions for handling mutex attributes.  */ + +/* Initialize mutex attribute object ATTR with default attributes +   (kind is PTHREAD_MUTEX_TIMED_NP).  */ +extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) __THROW; + +/* Destroy mutex attribute object ATTR.  */ +extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) __THROW; + +/* Get the process-shared flag of the mutex attribute ATTR.  */ +extern int pthread_mutexattr_getpshared (__const pthread_mutexattr_t * +					 __restrict __attr, +					 int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the mutex attribute ATTR.  */ +extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, +					 int __pshared) __THROW; + +#ifdef __USE_UNIX98 +/* Return in *KIND the mutex kind attribute in *ATTR.  */ +extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict +				      __attr, int *__restrict __kind) __THROW; + +/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL, +   PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or +   PTHREAD_MUTEX_DEFAULT).  */ +extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) +     __THROW; +#endif + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Functions for handling read-write locks.  */ + +/* Initialize read-write lock RWLOCK using attributes ATTR, or use +   the default values if later is NULL.  */ +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, +				__const pthread_rwlockattr_t *__restrict +				__attr) __THROW; + +/* Destroy read-write lock RWLOCK.  */ +extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) __THROW; + +/* Acquire read lock for RWLOCK.  */ +extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire read lock for RWLOCK.  */ +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire read lock for RWLOCK or return after specfied time.  */ +extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, +				       __const struct timespec *__restrict +				       __abstime) __THROW; +# endif + +/* Acquire write lock for RWLOCK.  */ +extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire write lock for RWLOCK.  */ +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire write lock for RWLOCK or return after specfied time.  */ +extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, +				       __const struct timespec *__restrict +				       __abstime) __THROW; +# endif + +/* Unlock RWLOCK.  */ +extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) __THROW; + + +/* Functions for handling read-write lock attributes.  */ + +/* Initialize attribute object ATTR with default values.  */ +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) __THROW; + +/* Destroy attribute object ATTR.  */ +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) __THROW; + +/* Return current setting of process-shared attribute of ATTR in PSHARED.  */ +extern int pthread_rwlockattr_getpshared (__const pthread_rwlockattr_t * +					  __restrict __attr, +					  int *__restrict __pshared) __THROW; + +/* Set process-shared attribute of ATTR to PSHARED.  */ +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr, +					  int __pshared) __THROW; + +/* Return current setting of reader/writer preference.  */ +extern int pthread_rwlockattr_getkind_np (__const pthread_rwlockattr_t * +					  __restrict __attr, +					  int *__restrict __pref) __THROW; + +/* Set reader/write preference.  */ +extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr, +					  int __pref) __THROW; +#endif + + +/* Functions for handling conditional variables.  */ + +/* Initialize condition variable COND using attributes ATTR, or use +   the default values if later is NULL.  */ +extern int pthread_cond_init (pthread_cond_t *__restrict __cond, +			      __const pthread_condattr_t *__restrict +			      __cond_attr) __THROW; + +/* Destroy condition variable COND.  */ +extern int pthread_cond_destroy (pthread_cond_t *__cond) __THROW; + +/* Wake up one thread waiting for condition variable COND.  */ +extern int pthread_cond_signal (pthread_cond_t *__cond) __THROW; + +/* Wake up all threads waiting for condition variables COND.  */ +extern int pthread_cond_broadcast (pthread_cond_t *__cond) __THROW; + +/* Wait for condition variable COND to be signaled or broadcast. +   MUTEX is assumed to be locked before. + +   This function is a cancellation point and therefore not marked with +   __THROW.  */ +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, +			      pthread_mutex_t *__restrict __mutex); + +/* Wait for condition variable COND to be signaled or broadcast until +   ABSTIME.  MUTEX is assumed to be locked before.  ABSTIME is an +   absolute time specification; zero is the beginning of the epoch +   (00:00:00 GMT, January 1, 1970). + +   This function is a cancellation point and therefore not marked with +   __THROW.  */ +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, +				   pthread_mutex_t *__restrict __mutex, +				   __const struct timespec *__restrict +				   __abstime); + +/* Functions for handling condition variable attributes.  */ + +/* Initialize condition variable attribute ATTR.  */ +extern int pthread_condattr_init (pthread_condattr_t *__attr) __THROW; + +/* Destroy condition variable attribute ATTR.  */ +extern int pthread_condattr_destroy (pthread_condattr_t *__attr) __THROW; + +/* Get the process-shared flag of the condition variable attribute ATTR.  */ +extern int pthread_condattr_getpshared (__const pthread_condattr_t * +                                        __restrict __attr, +                                        int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the condition variable attribute ATTR.  */ +extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, +                                        int __pshared) __THROW; + +#ifdef __USE_XOPEN2K +/* Get the clock selected for the conditon variable attribute ATTR.  */ +extern int pthread_condattr_getclock (__const pthread_condattr_t * +				      __restrict __attr, +				      __clockid_t *__restrict __clock_id) +     __THROW; + +/* Set the clock selected for the conditon variable attribute ATTR.  */ +extern int pthread_condattr_setclock (pthread_condattr_t *__attr, +				      __clockid_t __clock_id) __THROW; + +#endif + + +#ifdef __USE_XOPEN2K +/* Functions to handle spinlocks.  */ + +/* Initialize the spinlock LOCK.  If PSHARED is nonzero the spinlock can +   be shared between different processes.  */ +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) +     __THROW; + +/* Destroy the spinlock LOCK.  */ +extern int pthread_spin_destroy (pthread_spinlock_t *__lock) __THROW; + +/* Wait until spinlock LOCK is retrieved.  */ +extern int pthread_spin_lock (pthread_spinlock_t *__lock) __THROW; + +/* Try to lock spinlock LOCK.  */ +extern int pthread_spin_trylock (pthread_spinlock_t *__lock) __THROW; + +/* Release spinlock LOCK.  */ +extern int pthread_spin_unlock (pthread_spinlock_t *__lock) __THROW; + + +/* Functions to handle barriers.  */ + +/* Initialize BARRIER with the attributes in ATTR.  The barrier is +   opened when COUNT waiters arrived.  */ +extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier, +				 __const pthread_barrierattr_t *__restrict +				 __attr, unsigned int __count) __THROW; + +/* Destroy a previously dynamically initialized barrier BARRIER.  */ +extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) __THROW; + +/* Wait on barrier BARRIER.  */ +extern int pthread_barrier_wait (pthread_barrier_t *__barrier) __THROW; + + +/* Initialize barrier attribute ATTR.  */ +extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) __THROW; + +/* Destroy previously dynamically initialized barrier attribute ATTR.  */ +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) __THROW; + +/* Get the process-shared flag of the barrier attribute ATTR.  */ +extern int pthread_barrierattr_getpshared (__const pthread_barrierattr_t * +					   __restrict __attr, +					   int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the barrier attribute ATTR.  */ +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr, +                                           int __pshared) __THROW; +#endif + + +/* Functions for handling thread-specific data.  */ + +/* Create a key value identifying a location in the thread-specific +   data area.  Each thread maintains a distinct thread-specific data +   area.  DESTR_FUNCTION, if non-NULL, is called with the value +   associated to that key when the key is destroyed. +   DESTR_FUNCTION is not called if the value associated is NULL when +   the key is destroyed.  */ +extern int pthread_key_create (pthread_key_t *__key, +			       void (*__destr_function) (void *)) __THROW; + +/* Destroy KEY.  */ +extern int pthread_key_delete (pthread_key_t __key) __THROW; + +/* Return current value of the thread-specific data slot identified by KEY.  */ +extern void *pthread_getspecific (pthread_key_t __key) __THROW; + +/* Store POINTER in the thread-specific data slot identified by KEY. */ +extern int pthread_setspecific (pthread_key_t __key, +				__const void *__pointer) __THROW; + + +#ifdef __USE_XOPEN2K +/* Get ID of CPU-time clock for thread THREAD_ID.  */ +extern int pthread_getcpuclockid (pthread_t __thread_id, +				  __clockid_t *__clock_id) __THROW; +#endif + + +/* Install handlers to be called when a new process is created with FORK. +   The PREPARE handler is called in the parent process just before performing +   FORK. The PARENT handler is called in the parent process just after FORK. +   The CHILD handler is called in the child process.  Each of the three +   handlers can be NULL, meaning that no handler needs to be called at that +   point. +   PTHREAD_ATFORK can be called several times, in which case the PREPARE +   handlers are called in LIFO order (last added with PTHREAD_ATFORK, +   first called before FORK), and the PARENT and CHILD handlers are called +   in FIFO (first added, first called).  */ + +extern int pthread_atfork (void (*__prepare) (void), +			   void (*__parent) (void), +			   void (*__child) (void)) __THROW; + +__END_DECLS + +#endif	/* pthread.h */ diff --git a/libpthread/nptl/sysdeps/pthread/pthread_barrier_wait.c b/libpthread/nptl/sysdeps/pthread/pthread_barrier_wait.c new file mode 100644 index 000000000..c6b563f24 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_barrier_wait.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <pthreadP.h> + + +/* Wait on barrier.  */ +int +pthread_barrier_wait (barrier) +     pthread_barrier_t *barrier; +{ +  struct pthread_barrier *ibarrier = (struct pthread_barrier *) barrier; +  int result = 0; + +  /* Make sure we are alone.  */ +  lll_lock (ibarrier->lock); + +  /* One more arrival.  */ +  --ibarrier->left; + +  /* Are these all?  */ +  if (ibarrier->left == 0) +    { +      /* Yes. Increment the event counter to avoid invalid wake-ups and +	 tell the current waiters that it is their turn.  */ +      ++ibarrier->curr_event; + +      /* Wake up everybody.  */ +      lll_futex_wake (&ibarrier->curr_event, INT_MAX); + +      /* This is the thread which finished the serialization.  */ +      result = PTHREAD_BARRIER_SERIAL_THREAD; +    } +  else +    { +      /* The number of the event we are waiting for.  The barrier's event +	 number must be bumped before we continue.  */ +      unsigned int event = ibarrier->curr_event; + +      /* Before suspending, make the barrier available to others.  */ +      lll_unlock (ibarrier->lock); + +      /* Wait for the event counter of the barrier to change.  */ +      do +	lll_futex_wait (&ibarrier->curr_event, event); +      while (event == ibarrier->curr_event); +    } + +  /* Make sure the init_count is stored locally or in a register.  */ +  unsigned int init_count = ibarrier->init_count; + +  /* If this was the last woken thread, unlock.  */ +  if (atomic_increment_val (&ibarrier->left) == init_count) +    /* We are done.  */ +    lll_unlock (ibarrier->lock); + +  return result; +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_broadcast.c b/libpthread/nptl/sysdeps/pthread/pthread_cond_broadcast.c new file mode 100644 index 000000000..1eac8ecf8 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_broadcast.c @@ -0,0 +1,80 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <endian.h> +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> + +#include <shlib-compat.h> +#include <kernel-features.h> + + +int +__pthread_cond_broadcast (cond) +     pthread_cond_t *cond; +{ +  /* Make sure we are alone.  */ +  lll_mutex_lock (cond->__data.__lock); + +  /* Are there any waiters to be woken?  */ +  if (cond->__data.__total_seq > cond->__data.__wakeup_seq) +    { +      /* Yes.  Mark them all as woken.  */ +      cond->__data.__wakeup_seq = cond->__data.__total_seq; +      cond->__data.__woken_seq = cond->__data.__total_seq; +      cond->__data.__futex = (unsigned int) cond->__data.__total_seq * 2; +      int futex_val = cond->__data.__futex; +      /* Signal that a broadcast happened.  */ +      ++cond->__data.__broadcast_seq; + +      /* We are done.  */ +      lll_mutex_unlock (cond->__data.__lock); + +      /* Do not use requeue for pshared condvars.  */ +      if (cond->__data.__mutex == (void *) ~0l) +	goto wake_all; + +      /* Wake everybody.  */ +      pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; +      /* lll_futex_requeue returns 0 for success and non-zero +	 for errors.  */ +      if (__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1, +					       INT_MAX, &mut->__data.__lock, +					       futex_val), 0)) +	{ +	  /* The requeue functionality is not available.  */ +	wake_all: +	  lll_futex_wake (&cond->__data.__futex, INT_MAX); +	} + +      /* That's all.  */ +      return 0; +    } + +  /* We are done.  */ +  lll_mutex_unlock (cond->__data.__lock); + +  return 0; +} + +versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, +		  GLIBC_2_3_2); diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_signal.c b/libpthread/nptl/sysdeps/pthread/pthread_cond_signal.c new file mode 100644 index 000000000..f5623480f --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_signal.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <endian.h> +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> + +#include <shlib-compat.h> +#include <kernel-features.h> + + +int +__pthread_cond_signal (cond) +     pthread_cond_t *cond; +{ +  /* Make sure we are alone.  */ +  lll_mutex_lock (cond->__data.__lock); + +  /* Are there any waiters to be woken?  */ +  if (cond->__data.__total_seq > cond->__data.__wakeup_seq) +    { +      /* Yes.  Mark one of them as woken.  */ +      ++cond->__data.__wakeup_seq; +      ++cond->__data.__futex; + +      /* Wake one.  */ +      lll_futex_wake (&cond->__data.__futex, 1); +    } + +  /* We are done.  */ +  lll_mutex_unlock (cond->__data.__lock); + +  return 0; +} + +versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, +		  GLIBC_2_3_2); diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c new file mode 100644 index 000000000..fdbf43eae --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c @@ -0,0 +1,214 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <endian.h> +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> + +#include <shlib-compat.h> + + +/* Cleanup handler, defined in pthread_cond_wait.c.  */ +extern void __condvar_cleanup (void *arg) +     __attribute__ ((visibility ("hidden"))); + +struct _condvar_cleanup_buffer +{ +  int oldtype; +  pthread_cond_t *cond; +  pthread_mutex_t *mutex; +  unsigned int bc_seq; +}; + +int +__pthread_cond_timedwait (cond, mutex, abstime) +     pthread_cond_t *cond; +     pthread_mutex_t *mutex; +     const struct timespec *abstime; +{ +  struct _pthread_cleanup_buffer buffer; +  struct _condvar_cleanup_buffer cbuffer; +  int result = 0; + +  /* Catch invalid parameters.  */ +  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) +    return EINVAL; + +  /* Make sure we are along.  */ +  lll_mutex_lock (cond->__data.__lock); + +  /* Now we can release the mutex.  */ +  int err = __pthread_mutex_unlock_usercnt (mutex, 0); +  if (err) +    { +      lll_mutex_unlock (cond->__data.__lock); +      return err; +    } + +  /* We have one new user of the condvar.  */ +  ++cond->__data.__total_seq; +  ++cond->__data.__futex; +  cond->__data.__nwaiters += 1 << COND_CLOCK_BITS; + +  /* Remember the mutex we are using here.  If there is already a +     different address store this is a bad user bug.  Do not store +     anything for pshared condvars.  */ +  if (cond->__data.__mutex != (void *) ~0l) +    cond->__data.__mutex = mutex; + +  /* Prepare structure passed to cancellation handler.  */ +  cbuffer.cond = cond; +  cbuffer.mutex = mutex; + +  /* Before we block we enable cancellation.  Therefore we have to +     install a cancellation handler.  */ +  __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer); + +  /* The current values of the wakeup counter.  The "woken" counter +     must exceed this value.  */ +  unsigned long long int val; +  unsigned long long int seq; +  val = seq = cond->__data.__wakeup_seq; +  /* Remember the broadcast counter.  */ +  cbuffer.bc_seq = cond->__data.__broadcast_seq; + +  while (1) +    { +      struct timespec rt; +      { +#ifdef __NR_clock_gettime +	INTERNAL_SYSCALL_DECL (err); +	int ret; +	ret = INTERNAL_SYSCALL (clock_gettime, err, 2, +				(cond->__data.__nwaiters +				 & ((1 << COND_CLOCK_BITS) - 1)), +				&rt); +# ifndef __ASSUME_POSIX_TIMERS +	if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (ret, err), 0)) +	  { +	    struct timeval tv; +	    (void) gettimeofday (&tv, NULL); + +	    /* Convert the absolute timeout value to a relative timeout.  */ +	    rt.tv_sec = abstime->tv_sec - tv.tv_sec; +	    rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; +	  } +	else +# endif +	  { +	    /* Convert the absolute timeout value to a relative timeout.  */ +	    rt.tv_sec = abstime->tv_sec - rt.tv_sec; +	    rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec; +	  } +#else +	/* Get the current time.  So far we support only one clock.  */ +	struct timeval tv; +	(void) gettimeofday (&tv, NULL); + +	/* Convert the absolute timeout value to a relative timeout.  */ +	rt.tv_sec = abstime->tv_sec - tv.tv_sec; +	rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; +#endif +      } +      if (rt.tv_nsec < 0) +	{ +	  rt.tv_nsec += 1000000000; +	  --rt.tv_sec; +	} +      /* Did we already time out?  */ +      if (__builtin_expect (rt.tv_sec < 0, 0)) +	{ +	  if (cbuffer.bc_seq != cond->__data.__broadcast_seq) +	    goto bc_out; + +	  goto timeout; +	} + +      unsigned int futex_val = cond->__data.__futex; + +      /* Prepare to wait.  Release the condvar futex.  */ +      lll_mutex_unlock (cond->__data.__lock); + +      /* Enable asynchronous cancellation.  Required by the standard.  */ +      cbuffer.oldtype = __pthread_enable_asynccancel (); + +      /* Wait until woken by signal or broadcast.  */ +      err = lll_futex_timed_wait (&cond->__data.__futex, +				  futex_val, &rt); + +      /* Disable asynchronous cancellation.  */ +      __pthread_disable_asynccancel (cbuffer.oldtype); + +      /* We are going to look at shared data again, so get the lock.  */ +      lll_mutex_lock(cond->__data.__lock); + +      /* If a broadcast happened, we are done.  */ +      if (cbuffer.bc_seq != cond->__data.__broadcast_seq) +	goto bc_out; + +      /* Check whether we are eligible for wakeup.  */ +      val = cond->__data.__wakeup_seq; +      if (val != seq && cond->__data.__woken_seq != val) +	break; + +      /* Not woken yet.  Maybe the time expired?  */ +      if (__builtin_expect (err == -ETIMEDOUT, 0)) +	{ +	timeout: +	  /* Yep.  Adjust the counters.  */ +	  ++cond->__data.__wakeup_seq; +	  ++cond->__data.__futex; + +	  /* The error value.  */ +	  result = ETIMEDOUT; +	  break; +	} +    } + +  /* Another thread woken up.  */ +  ++cond->__data.__woken_seq; + + bc_out: + +  cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS; + +  /* If pthread_cond_destroy was called on this variable already, +     notify the pthread_cond_destroy caller all waiters have left +     and it can be successfully destroyed.  */ +  if (cond->__data.__total_seq == -1ULL +      && cond->__data.__nwaiters < (1 << COND_CLOCK_BITS)) +    lll_futex_wake (&cond->__data.__nwaiters, 1); + +  /* We are done with the condvar.  */ +  lll_mutex_unlock (cond->__data.__lock); + +  /* The cancellation handling is back to normal, remove the handler.  */ +  __pthread_cleanup_pop (&buffer, 0); + +  /* Get the mutex before returning.  */ +  err = __pthread_mutex_cond_lock (mutex); + +  return err ?: result; +} + +versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, +		  GLIBC_2_3_2); diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_wait.c b/libpthread/nptl/sysdeps/pthread/pthread_cond_wait.c new file mode 100644 index 000000000..86669458a --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_wait.c @@ -0,0 +1,185 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <endian.h> +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> + +#include <shlib-compat.h> + + +struct _condvar_cleanup_buffer +{ +  int oldtype; +  pthread_cond_t *cond; +  pthread_mutex_t *mutex; +  unsigned int bc_seq; +}; + + +void +__attribute__ ((visibility ("hidden"))) +__condvar_cleanup (void *arg) +{ +  struct _condvar_cleanup_buffer *cbuffer = +    (struct _condvar_cleanup_buffer *) arg; +  unsigned int destroying; + +  /* We are going to modify shared data.  */ +  lll_mutex_lock (cbuffer->cond->__data.__lock); + +  if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq) +    { +      /* This thread is not waiting anymore.  Adjust the sequence counters +	 appropriately.  */ +      ++cbuffer->cond->__data.__wakeup_seq; +      ++cbuffer->cond->__data.__woken_seq; +      ++cbuffer->cond->__data.__futex; +    } + +  cbuffer->cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS; + +  /* If pthread_cond_destroy was called on this variable already, +     notify the pthread_cond_destroy caller all waiters have left +     and it can be successfully destroyed.  */ +  destroying = 0; +  if (cbuffer->cond->__data.__total_seq == -1ULL +      && cbuffer->cond->__data.__nwaiters < (1 << COND_CLOCK_BITS)) +    { +      lll_futex_wake (&cbuffer->cond->__data.__nwaiters, 1); +      destroying = 1; +    } + +  /* We are done.  */ +  lll_mutex_unlock (cbuffer->cond->__data.__lock); + +  /* Wake everybody to make sure no condvar signal gets lost.  */ +  if (! destroying) +    lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX); + +  /* Get the mutex before returning unless asynchronous cancellation +     is in effect.  */ +  __pthread_mutex_cond_lock (cbuffer->mutex); +} + + +int +__pthread_cond_wait (cond, mutex) +     pthread_cond_t *cond; +     pthread_mutex_t *mutex; +{ +  struct _pthread_cleanup_buffer buffer; +  struct _condvar_cleanup_buffer cbuffer; +  int err; + +  /* Make sure we are along.  */ +  lll_mutex_lock (cond->__data.__lock); + +  /* Now we can release the mutex.  */ +  err = __pthread_mutex_unlock_usercnt (mutex, 0); +  if (__builtin_expect (err, 0)) +    { +      lll_mutex_unlock (cond->__data.__lock); +      return err; +    } + +  /* We have one new user of the condvar.  */ +  ++cond->__data.__total_seq; +  ++cond->__data.__futex; +  cond->__data.__nwaiters += 1 << COND_CLOCK_BITS; + +  /* Remember the mutex we are using here.  If there is already a +     different address store this is a bad user bug.  Do not store +     anything for pshared condvars.  */ +  if (cond->__data.__mutex != (void *) ~0l) +    cond->__data.__mutex = mutex; + +  /* Prepare structure passed to cancellation handler.  */ +  cbuffer.cond = cond; +  cbuffer.mutex = mutex; + +  /* Before we block we enable cancellation.  Therefore we have to +     install a cancellation handler.  */ +  __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer); + +  /* The current values of the wakeup counter.  The "woken" counter +     must exceed this value.  */ +  unsigned long long int val; +  unsigned long long int seq; +  val = seq = cond->__data.__wakeup_seq; +  /* Remember the broadcast counter.  */ +  cbuffer.bc_seq = cond->__data.__broadcast_seq; + +  do +    { +      unsigned int futex_val = cond->__data.__futex; + +      /* Prepare to wait.  Release the condvar futex.  */ +      lll_mutex_unlock (cond->__data.__lock); + +      /* Enable asynchronous cancellation.  Required by the standard.  */ +      cbuffer.oldtype = __pthread_enable_asynccancel (); + +      /* Wait until woken by signal or broadcast.  */ +      lll_futex_wait (&cond->__data.__futex, futex_val); + +      /* Disable asynchronous cancellation.  */ +      __pthread_disable_asynccancel (cbuffer.oldtype); + +      /* We are going to look at shared data again, so get the lock.  */ +      lll_mutex_lock (cond->__data.__lock); + +      /* If a broadcast happened, we are done.  */ +      if (cbuffer.bc_seq != cond->__data.__broadcast_seq) +	goto bc_out; + +      /* Check whether we are eligible for wakeup.  */ +      val = cond->__data.__wakeup_seq; +    } +  while (val == seq || cond->__data.__woken_seq == val); + +  /* Another thread woken up.  */ +  ++cond->__data.__woken_seq; + + bc_out: + +  cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS; + +  /* If pthread_cond_destroy was called on this varaible already, +     notify the pthread_cond_destroy caller all waiters have left +     and it can be successfully destroyed.  */ +  if (cond->__data.__total_seq == -1ULL +      && cond->__data.__nwaiters < (1 << COND_CLOCK_BITS)) +    lll_futex_wake (&cond->__data.__nwaiters, 1); + +  /* We are done with the condvar.  */ +  lll_mutex_unlock (cond->__data.__lock); + +  /* The cancellation handling is back to normal, remove the handler.  */ +  __pthread_cleanup_pop (&buffer, 0); + +  /* Get the mutex before returning.  */ +  return __pthread_mutex_cond_lock (mutex); +} + +versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, +		  GLIBC_2_3_2); diff --git a/libpthread/nptl/sysdeps/pthread/pthread_getcpuclockid.c b/libpthread/nptl/sysdeps/pthread/pthread_getcpuclockid.c new file mode 100644 index 000000000..8506f94eb --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_getcpuclockid.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2000, 2001, 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; 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> + + +int +pthread_getcpuclockid (threadid, clockid) +     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 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/pthread/pthread_once.c b/libpthread/nptl/sysdeps/pthread/pthread_once.c new file mode 100644 index 000000000..9b2cef864 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_once.c @@ -0,0 +1,54 @@ +/* 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 "pthreadP.h" +#include <lowlevellock.h> + + + +static lll_lock_t once_lock = LLL_LOCK_INITIALIZER; + + +int +__pthread_once (once_control, init_routine) +     pthread_once_t *once_control; +     void (*init_routine) (void); +{ +  /* XXX Depending on whether the LOCK_IN_ONCE_T is defined use a +     global lock variable or one which is part of the pthread_once_t +     object.  */ +  if (*once_control == PTHREAD_ONCE_INIT) +    { +      lll_lock (once_lock); + +      /* XXX This implementation is not complete.  It doesn't take +	 cancelation and fork into account.  */ +      if (*once_control == PTHREAD_ONCE_INIT) +	{ +	  init_routine (); + +	  *once_control = !PTHREAD_ONCE_INIT; +	} + +      lll_unlock (once_lock); +    } + +  return 0; +} +strong_alias (__pthread_once, pthread_once) diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c new file mode 100644 index 000000000..e225d7030 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c @@ -0,0 +1,95 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <pthread.h> +#include <pthreadP.h> + + +/* Acquire read lock for RWLOCK.  */ +int +__pthread_rwlock_rdlock (rwlock) +     pthread_rwlock_t *rwlock; +{ +  int result = 0; + +  /* Make sure we are along.  */ +  lll_mutex_lock (rwlock->__data.__lock); + +  while (1) +    { +      /* Get the rwlock if there is no writer...  */ +      if (rwlock->__data.__writer == 0 +	  /* ...and if either no writer is waiting or we prefer readers.  */ +	  && (!rwlock->__data.__nr_writers_queued +	      || rwlock->__data.__flags == 0)) +	{ +	  /* Increment the reader counter.  Avoid overflow.  */ +	  if (__builtin_expect (++rwlock->__data.__nr_readers == 0, 0)) +	    { +	      /* Overflow on number of readers.	 */ +	      --rwlock->__data.__nr_readers; +	      result = EAGAIN; +	    } + +	  break; +	} + +      /* Make sure we are not holding the rwlock as a writer.  This is +	 a deadlock situation we recognize and report.  */ +      if (__builtin_expect (rwlock->__data.__writer +			    == THREAD_GETMEM (THREAD_SELF, tid), 0)) +	{ +	  result = EDEADLK; +	  break; +	} + +      /* Remember that we are a reader.  */ +      if (__builtin_expect (++rwlock->__data.__nr_readers_queued == 0, 0)) +	{ +	  /* Overflow on number of queued readers.  */ +	  --rwlock->__data.__nr_readers_queued; +	  result = EAGAIN; +	  break; +	} + +      int waitval = rwlock->__data.__readers_wakeup; + +      /* Free the lock.  */ +      lll_mutex_unlock (rwlock->__data.__lock); + +      /* Wait for the writer to finish.  */ +      lll_futex_wait (&rwlock->__data.__readers_wakeup, waitval); + +      /* Get the lock.  */ +      lll_mutex_lock (rwlock->__data.__lock); + +      --rwlock->__data.__nr_readers_queued; +    } + +  /* We are done, free the lock.  */ +  lll_mutex_unlock (rwlock->__data.__lock); + +  return result; +} + +weak_alias (__pthread_rwlock_rdlock, pthread_rwlock_rdlock) +strong_alias (__pthread_rwlock_rdlock, __pthread_rwlock_rdlock_internal) diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c new file mode 100644 index 000000000..80ea83a3d --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <pthread.h> +#include <pthreadP.h> + + +/* Try to acquire read lock for RWLOCK or return after specfied time.  */ +int +pthread_rwlock_timedrdlock (rwlock, abstime) +     pthread_rwlock_t *rwlock; +     const struct timespec *abstime; +{ +  int result = 0; + +  /* Make sure we are along.  */ +  lll_mutex_lock(rwlock->__data.__lock); + +  while (1) +    { +      int err; + +      /* Get the rwlock if there is no writer...  */ +      if (rwlock->__data.__writer == 0 +	  /* ...and if either no writer is waiting or we prefer readers.  */ +	  && (!rwlock->__data.__nr_writers_queued +	      || rwlock->__data.__flags == 0)) +	{ +	  /* Increment the reader counter.  Avoid overflow.  */ +	  if (++rwlock->__data.__nr_readers == 0) +	    { +	      /* Overflow on number of readers.	 */ +	      --rwlock->__data.__nr_readers; +	      result = EAGAIN; +	    } + +	  break; +	} + +      /* Make sure we are not holding the rwlock as a writer.  This is +	 a deadlock situation we recognize and report.  */ +      if (__builtin_expect (rwlock->__data.__writer +			    == THREAD_GETMEM (THREAD_SELF, tid), 0)) +	{ +	  result = EDEADLK; +	  break; +	} + +      /* Make sure the passed in timeout value is valid.  Ideally this +	 test would be executed once.  But since it must not be +	 performed if we would not block at all simply moving the test +	 to the front is no option.  Replicating all the code is +	 costly while this test is not.  */ +      if (__builtin_expect (abstime->tv_nsec >= 1000000000 +                            || abstime->tv_nsec < 0, 0)) +	{ +	  result = EINVAL; +	  break; +	} + +      /* Get the current time.  So far we support only one clock.  */ +      struct timeval tv; +      (void) gettimeofday (&tv, NULL); + +      /* Convert the absolute timeout value to a relative timeout.  */ +      struct timespec rt; +      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; +	} +      /* Did we already time out?  */ +      if (rt.tv_sec < 0) +	{ +	  /* Yep, return with an appropriate error.  */ +	  result = ETIMEDOUT; +	  break; +	} + +      /* Remember that we are a reader.  */ +      if (++rwlock->__data.__nr_readers_queued == 0) +	{ +	  /* Overflow on number of queued readers.  */ +	  --rwlock->__data.__nr_readers_queued; +	  result = EAGAIN; +	  break; +	} + +      int waitval = rwlock->__data.__readers_wakeup; + +      /* Free the lock.  */ +      lll_mutex_unlock (rwlock->__data.__lock); + +      /* Wait for the writer to finish.  */ +      err = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup, +				  waitval, &rt); + +      /* Get the lock.  */ +      lll_mutex_lock (rwlock->__data.__lock); + +      --rwlock->__data.__nr_readers_queued; + +      /* Did the futex call time out?  */ +      if (err == -ETIMEDOUT) +	{ +	  /* Yep, report it.  */ +	  result = ETIMEDOUT; +	  break; +	} +    } + +  /* We are done, free the lock.  */ +  lll_mutex_unlock (rwlock->__data.__lock); + +  return result; +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c new file mode 100644 index 000000000..97c0598f9 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c @@ -0,0 +1,127 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <pthread.h> +#include <pthreadP.h> + + +/* Try to acquire write lock for RWLOCK or return after specfied time.	*/ +int +pthread_rwlock_timedwrlock (rwlock, abstime) +     pthread_rwlock_t *rwlock; +     const struct timespec *abstime; +{ +  int result = 0; + +  /* Make sure we are along.  */ +  lll_mutex_lock (rwlock->__data.__lock); + +  while (1) +    { +      int err; + +      /* Get the rwlock if there is no writer and no reader.  */ +      if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0) +	{ +	  /* Mark self as writer.  */ +	  rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid); +	  break; +	} + +      /* Make sure we are not holding the rwlock as a writer.  This is +	 a deadlock situation we recognize and report.  */ +      if (__builtin_expect (rwlock->__data.__writer +			    == THREAD_GETMEM (THREAD_SELF, tid), 0)) +	{ +	  result = EDEADLK; +	  break; +	} + +      /* Make sure the passed in timeout value is valid.  Ideally this +	 test would be executed once.  But since it must not be +	 performed if we would not block at all simply moving the test +	 to the front is no option.  Replicating all the code is +	 costly while this test is not.  */ +      if (__builtin_expect (abstime->tv_nsec >= 1000000000 +                            || abstime->tv_nsec < 0, 0)) +	{ +	  result = EINVAL; +	  break; +	} + +      /* Get the current time.  So far we support only one clock.  */ +      struct timeval tv; +      (void) gettimeofday (&tv, NULL); + +      /* Convert the absolute timeout value to a relative timeout.  */ +      struct timespec rt; +      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; +	} +      /* Did we already time out?  */ +      if (rt.tv_sec < 0) +	{ +	  result = ETIMEDOUT; +	  break; +	} + +      /* Remember that we are a writer.  */ +      if (++rwlock->__data.__nr_writers_queued == 0) +	{ +	  /* Overflow on number of queued writers.  */ +	  --rwlock->__data.__nr_writers_queued; +	  result = EAGAIN; +	  break; +	} + +      int waitval = rwlock->__data.__writer_wakeup; + +      /* Free the lock.  */ +      lll_mutex_unlock (rwlock->__data.__lock); + +      /* Wait for the writer or reader(s) to finish.  */ +      err = lll_futex_timed_wait (&rwlock->__data.__writer_wakeup, +				  waitval, &rt); + +      /* Get the lock.  */ +      lll_mutex_lock (rwlock->__data.__lock); + +      /* To start over again, remove the thread from the writer list.  */ +      --rwlock->__data.__nr_writers_queued; + +      /* Did the futex call time out?  */ +      if (err == -ETIMEDOUT) +	{ +	  result = ETIMEDOUT; +	  break; +	} +    } + +  /* We are done, free the lock.  */ +  lll_mutex_unlock (rwlock->__data.__lock); + +  return result; +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_unlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_unlock.c new file mode 100644 index 000000000..9cae8b6c2 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_unlock.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <pthread.h> +#include <pthreadP.h> + +/* Unlock RWLOCK.  */ +int +__pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +{ +  lll_mutex_lock (rwlock->__data.__lock); +  if (rwlock->__data.__writer) +    rwlock->__data.__writer = 0; +  else +    --rwlock->__data.__nr_readers; +  if (rwlock->__data.__nr_readers == 0) +    { +      if (rwlock->__data.__nr_writers_queued) +	{ +	  ++rwlock->__data.__writer_wakeup; +	  lll_mutex_unlock (rwlock->__data.__lock); +	  lll_futex_wake (&rwlock->__data.__writer_wakeup, 1); +	  return 0; +	} +      else if (rwlock->__data.__nr_readers_queued) +	{ +	  ++rwlock->__data.__readers_wakeup; +	  lll_mutex_unlock (rwlock->__data.__lock); +	  lll_futex_wake (&rwlock->__data.__readers_wakeup, INT_MAX); +	  return 0; +	} +    } +  lll_mutex_unlock (rwlock->__data.__lock); +  return 0; +} + +weak_alias (__pthread_rwlock_unlock, pthread_rwlock_unlock) +strong_alias (__pthread_rwlock_unlock, __pthread_rwlock_unlock_internal) diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c new file mode 100644 index 000000000..822aeed79 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c @@ -0,0 +1,87 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <pthread.h> +#include <pthreadP.h> + + +/* Acquire write lock for RWLOCK.  */ +int +__pthread_rwlock_wrlock (rwlock) +     pthread_rwlock_t *rwlock; +{ +  int result = 0; + +  /* Make sure we are along.  */ +  lll_mutex_lock (rwlock->__data.__lock); + +  while (1) +    { +      /* Get the rwlock if there is no writer and no reader.  */ +      if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0) +	{ +	  /* Mark self as writer.  */ +	  rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid); +	  break; +	} + +      /* Make sure we are not holding the rwlock as a writer.  This is +	 a deadlock situation we recognize and report.  */ +      if (__builtin_expect (rwlock->__data.__writer +			    == THREAD_GETMEM (THREAD_SELF, tid), 0)) +	{ +	  result = EDEADLK; +	  break; +	} + +      /* Remember that we are a writer.  */ +      if (++rwlock->__data.__nr_writers_queued == 0) +	{ +	  /* Overflow on number of queued writers.  */ +	  --rwlock->__data.__nr_writers_queued; +	  result = EAGAIN; +	  break; +	} + +      int waitval = rwlock->__data.__writer_wakeup; + +      /* Free the lock.  */ +      lll_mutex_unlock (rwlock->__data.__lock); + +      /* Wait for the writer or reader(s) to finish.  */ +      lll_futex_wait (&rwlock->__data.__writer_wakeup, waitval); + +      /* Get the lock.  */ +      lll_mutex_lock (rwlock->__data.__lock); + +      /* To start over again, remove the thread from the writer list.  */ +      --rwlock->__data.__nr_writers_queued; +    } + +  /* We are done, free the lock.  */ +  lll_mutex_unlock (rwlock->__data.__lock); + +  return result; +} + +weak_alias (__pthread_rwlock_wrlock, pthread_rwlock_wrlock) +strong_alias (__pthread_rwlock_wrlock, __pthread_rwlock_wrlock_internal) diff --git a/libpthread/nptl/sysdeps/pthread/pthread_sigmask.c b/libpthread/nptl/sysdeps/pthread/pthread_sigmask.c new file mode 100644 index 000000000..0d12fe6bf --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_sigmask.c @@ -0,0 +1,58 @@ +/* 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 <sysdep.h> + + +int +pthread_sigmask (how, newmask, oldmask) +     int how; +     const sigset_t *newmask; +     sigset_t *oldmask; +{ +  sigset_t local_newmask; + +  /* The only thing we have to make sure here is that SIGCANCEL and +     SIGSETXID is not blocked.  */ +  if (newmask != NULL +      && (__builtin_expect (__sigismember (newmask, SIGCANCEL), 0) +	  || __builtin_expect (__sigismember (newmask, SIGSETXID), 0))) +    { +      local_newmask = *newmask; +      __sigdelset (&local_newmask, SIGCANCEL); +      __sigdelset (&local_newmask, SIGSETXID); +      newmask = &local_newmask; +    } + +#ifdef INTERNAL_SYSCALL +  /* We know that realtime signals are available if NPTL is used.  */ +  INTERNAL_SYSCALL_DECL (err); +  int result = INTERNAL_SYSCALL (rt_sigprocmask, err, 4, how, newmask, +				 oldmask, _NSIG / 8); + +  return (INTERNAL_SYSCALL_ERROR_P (result, err) +	  ? INTERNAL_SYSCALL_ERRNO (result, err) +	  : 0); +#else +  return sigprocmask (how, newmask, oldmask) == -1 ? errno : 0; +#endif +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_spin_destroy.c b/libpthread/nptl/sysdeps/pthread/pthread_spin_destroy.c new file mode 100644 index 000000000..4d0109cf0 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_spin_destroy.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 "pthreadP.h" + + +int +pthread_spin_destroy (lock) +     pthread_spinlock_t *lock; +{ +  /* Nothing to do.  */ +  return 0; +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_spin_init.c b/libpthread/nptl/sysdeps/pthread/pthread_spin_init.c new file mode 100644 index 000000000..c2275085e --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_spin_init.c @@ -0,0 +1,28 @@ +/* pthread_spin_init -- initialize a spin lock.  Generic 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 "pthreadP.h" + +int +pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ +  *lock = 0; +  return 0; +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_spin_unlock.c b/libpthread/nptl/sysdeps/pthread/pthread_spin_unlock.c new file mode 100644 index 000000000..f97cadfbd --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_spin_unlock.c @@ -0,0 +1,30 @@ +/* pthread_spin_unlock -- unlock a spin lock.  Generic 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 "pthreadP.h" +#include <atomic.h> + +int +pthread_spin_unlock (pthread_spinlock_t *lock) +{ +  atomic_full_barrier (); +  *lock = 0; +  return 0; +} diff --git a/libpthread/nptl/sysdeps/pthread/rt-unwind-resume.c b/libpthread/nptl/sysdeps/pthread/rt-unwind-resume.c new file mode 100644 index 000000000..743e675d4 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/rt-unwind-resume.c @@ -0,0 +1 @@ +#include <unwind-resume.c> diff --git a/libpthread/nptl/sysdeps/pthread/setxid.h b/libpthread/nptl/sysdeps/pthread/setxid.h new file mode 100644 index 000000000..8ec382f40 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/setxid.h @@ -0,0 +1,64 @@ +/* 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 <pthreadP.h> +#include <sysdep.h> + +#define __SETXID_1(cmd, arg1) \ +  cmd.id[0] = arg1 +#define __SETXID_2(cmd, arg1, arg2) \ +  __SETXID_1 (cmd, arg1); cmd.id[1] = arg2 +#define __SETXID_3(cmd, arg1, arg2, arg3) \ +  __SETXID_2 (cmd, arg1, arg2); cmd.id[2] = arg3 + +#ifdef SINGLE_THREAD +# define INLINE_SETXID_SYSCALL(name, nr, args...) \ +  INLINE_SYSCALL (name, nr, args) +#elif defined SHARED +# define INLINE_SETXID_SYSCALL(name, nr, args...) \ +  ({									\ +    int __result;							\ +    if (__builtin_expect (__libc_pthread_functions.ptr__nptl_setxid	\ +			  != NULL, 0))					\ +      {									\ +	struct xid_command __cmd;					\ +	__cmd.syscall_no = __NR_##name;					\ +	__SETXID_##nr (__cmd, args);					\ +	__result = __libc_pthread_functions.ptr__nptl_setxid (&__cmd);	\ +	}								\ +    else								\ +      __result = INLINE_SYSCALL (name, nr, args);			\ +    __result;								\ +   }) +#else +# define INLINE_SETXID_SYSCALL(name, nr, args...) \ +  ({									\ +    extern __typeof (__nptl_setxid) __nptl_setxid __attribute__((weak));\ +    int __result;							\ +    if (__builtin_expect (__nptl_setxid	!= NULL, 0))			\ +      {									\ +	struct xid_command __cmd;					\ +	__cmd.syscall_no = __NR_##name;					\ +	__SETXID_##nr (__cmd, args);					\ +	__result =__nptl_setxid (&__cmd);				\ +      }									\ +    else								\ +      __result = INLINE_SYSCALL (name, nr, args);			\ +    __result;								\ +   }) +#endif diff --git a/libpthread/nptl/sysdeps/pthread/sigaction.c b/libpthread/nptl/sysdeps/pthread/sigaction.c new file mode 100644 index 000000000..4d36150a9 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/sigaction.c @@ -0,0 +1,54 @@ +/* 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.  */ + +/* This is tricky.  GCC doesn't like #include_next in the primary +   source file and even if it did, the first #include_next is this +   exact file anyway.  */ +#ifndef LIBC_SIGACTION + +#include <nptl/pthreadP.h> + +/* We use the libc implementation but we tell it to not allow +   SIGCANCEL or SIGTIMER to be handled.  */ +# define LIBC_SIGACTION	1 + +# include <nptl/sysdeps/pthread/sigaction.c> + +int +__sigaction (sig, act, oact) +     int sig; +     const struct sigaction *act; +     struct sigaction *oact; +{ +  if (__builtin_expect (sig == SIGCANCEL || sig == SIGSETXID, 0)) +    { +      __set_errno (EINVAL); +      return -1; +    } + +  return __libc_sigaction (sig, act, oact); +} +libc_hidden_weak (__sigaction) +weak_alias (__sigaction, sigaction) + +#else + +# include_next <sigaction.c> + +#endif /* LIBC_SIGACTION */ diff --git a/libpthread/nptl/sysdeps/pthread/sigfillset.c b/libpthread/nptl/sysdeps/pthread/sigfillset.c new file mode 100644 index 000000000..fe58ccd53 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/sigfillset.c @@ -0,0 +1,21 @@ +/* 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 <nptl/pthreadP.h> + +#include <sysdeps/generic/sigfillset.c> diff --git a/libpthread/nptl/sysdeps/pthread/sigprocmask.c b/libpthread/nptl/sysdeps/pthread/sigprocmask.c new file mode 100644 index 000000000..855b43396 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/sigprocmask.c @@ -0,0 +1,20 @@ +/* Copyright (C) 1997,1998,1999,2000,2001,2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   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 <nptl/pthreadP.h> +#include <sysdeps/unix/sysv/linux/sigprocmask.c> diff --git a/libpthread/nptl/sysdeps/pthread/tcb-offsets.h b/libpthread/nptl/sysdeps/pthread/tcb-offsets.h new file mode 100644 index 000000000..3fe13702e --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/tcb-offsets.h @@ -0,0 +1 @@ +/* This is overridden by generated tcb-offsets.h on arches which need it.  */ diff --git a/libpthread/nptl/sysdeps/pthread/timer_create.c b/libpthread/nptl/sysdeps/pthread/timer_create.c new file mode 100644 index 000000000..2809ac744 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/timer_create.c @@ -0,0 +1,170 @@ +/* Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + +   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 <signal.h> +#include <pthread.h> +#include <time.h> +#include <unistd.h> + +#include "posix-timer.h" + + +/* Create new per-process timer using CLOCK.  */ +int +timer_create (clock_id, evp, timerid) +     clockid_t clock_id; +     struct sigevent *evp; +     timer_t *timerid; +{ +  int retval = -1; +  struct timer_node *newtimer = NULL; +  struct thread_node *thread = NULL; + +  if (0 +#if defined _POSIX_CPUTIME && _POSIX_CPUTIME >= 0 +      || clock_id == CLOCK_PROCESS_CPUTIME_ID +#endif +#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0 +      || clock_id == CLOCK_THREAD_CPUTIME_ID +#endif +      ) +    { +      /* We don't allow timers for CPU clocks.  At least not in the +	 moment.  */ +      __set_errno (ENOTSUP); +      return -1; +    } + +  if (clock_id != CLOCK_REALTIME) +    { +      __set_errno (EINVAL); +      return -1; +    } + +  pthread_once (&__timer_init_once_control, __timer_init_once); + +  if (__timer_init_failed) +    { +      __set_errno (ENOMEM); +      return -1; +    } + +  pthread_mutex_lock (&__timer_mutex); + +  newtimer = __timer_alloc (); +  if (__builtin_expect (newtimer == NULL, 0)) +    { +      __set_errno (EAGAIN); +      goto unlock_bail; +    } + +  if (evp != NULL) +    newtimer->event = *evp; +  else +    { +      newtimer->event.sigev_notify = SIGEV_SIGNAL; +      newtimer->event.sigev_signo = SIGALRM; +      newtimer->event.sigev_value.sival_ptr = timer_ptr2id (newtimer); +      newtimer->event.sigev_notify_function = 0; +    } + +  newtimer->event.sigev_notify_attributes = &newtimer->attr; +  newtimer->creator_pid = getpid (); + +  switch (__builtin_expect (newtimer->event.sigev_notify, SIGEV_SIGNAL)) +    { +    case SIGEV_NONE: +    case SIGEV_SIGNAL: +      /* We have a global thread for delivering timed signals. +	 If it is not running, try to start it up.  */ +      thread = &__timer_signal_thread_rclk; +      if (! thread->exists) +	{ +	  if (__builtin_expect (__timer_thread_start (thread), +				1) < 0) +	    { +	      __set_errno (EAGAIN); +	      goto unlock_bail; +            } +        } +      break; + +    case SIGEV_THREAD: +      /* Copy over thread attributes or set up default ones.  */ +      if (evp->sigev_notify_attributes) +	newtimer->attr = *(pthread_attr_t *) evp->sigev_notify_attributes; +      else +	pthread_attr_init (&newtimer->attr); + +      /* Ensure thread attributes call for deatched thread.  */ +      pthread_attr_setdetachstate (&newtimer->attr, PTHREAD_CREATE_DETACHED); + +      /* Try to find existing thread having the right attributes.  */ +      thread = __timer_thread_find_matching (&newtimer->attr, clock_id); + +      /* If no existing thread has these attributes, try to allocate one.  */ +      if (thread == NULL) +	thread = __timer_thread_alloc (&newtimer->attr, clock_id); + +      /* Out of luck; no threads are available.  */ +      if (__builtin_expect (thread == NULL, 0)) +	{ +	  __set_errno (EAGAIN); +	  goto unlock_bail; +	} + +      /* If the thread is not running already, try to start it.  */ +      if (! thread->exists +	  && __builtin_expect (! __timer_thread_start (thread), 0)) +	{ +	  __set_errno (EAGAIN); +	  goto unlock_bail; +	} +      break; + +    default: +      __set_errno (EINVAL); +      goto unlock_bail; +    } + +  newtimer->clock = clock_id; +  newtimer->abstime = 0; +  newtimer->armed = 0; +  newtimer->thread = thread; + +  *timerid = timer_ptr2id (newtimer); +  retval = 0; + +  if (__builtin_expect (retval, 0) == -1) +    { +    unlock_bail: +      if (thread != NULL) +	__timer_thread_dealloc (thread); +      if (newtimer != NULL) +	{ +	  timer_delref (newtimer); +	  __timer_dealloc (newtimer); +	} +    } + +  pthread_mutex_unlock (&__timer_mutex); + +  return retval; +} diff --git a/libpthread/nptl/sysdeps/pthread/timer_delete.c b/libpthread/nptl/sysdeps/pthread/timer_delete.c new file mode 100644 index 000000000..48ba1f272 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/timer_delete.c @@ -0,0 +1,70 @@ +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + +   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 <assert.h> +#include <errno.h> +#include <pthread.h> +#include <time.h> + +#include "posix-timer.h" + + +/* Delete timer TIMERID.  */ +int +timer_delete (timerid) +     timer_t timerid; +{ +  struct timer_node *timer; +  int retval = -1; + +  pthread_mutex_lock (&__timer_mutex); + +  timer = timer_id2ptr (timerid); +  if (! timer_valid (timer)) +    /* Invalid timer ID or the timer is not in use.  */ +    __set_errno (EINVAL); +  else +    { +      if (timer->armed && timer->thread != NULL) +	{ +	  struct thread_node *thread = timer->thread; +	  assert (thread != NULL); + +	  /* If thread is cancelled while waiting for handler to terminate, +	     the mutex is unlocked and timer_delete is aborted.  */ +	  pthread_cleanup_push (__timer_mutex_cancel_handler, &__timer_mutex); + +	  /* If timer is currently being serviced, wait for it to finish.  */ +	  while (thread->current_timer == timer) +	    pthread_cond_wait (&thread->cond, &__timer_mutex); + +	  pthread_cleanup_pop (0); +        } + +      /* Remove timer from whatever queue it may be on and deallocate it.  */ +      timer->inuse = TIMER_DELETED; +      list_unlink_ip (&timer->links); +      timer_delref (timer); +      retval = 0; +    } + +  pthread_mutex_unlock (&__timer_mutex); + +  return retval; +} diff --git a/libpthread/nptl/sysdeps/pthread/timer_getoverr.c b/libpthread/nptl/sysdeps/pthread/timer_getoverr.c new file mode 100644 index 000000000..f3e22215b --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/timer_getoverr.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + +   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 <time.h> + +#include "posix-timer.h" + + +/* Get expiration overrun for timer TIMERID.  */ +int +timer_getoverrun (timerid) +     timer_t timerid; +{ +  struct timer_node *timer; +  int retval = -1; + +  pthread_mutex_lock (&__timer_mutex); + +  if (! timer_valid (timer = timer_id2ptr (timerid))) +    __set_errno (EINVAL); +  else +    retval = timer->overrun_count; + +  pthread_mutex_unlock (&__timer_mutex); + +  return retval; +} diff --git a/libpthread/nptl/sysdeps/pthread/timer_gettime.c b/libpthread/nptl/sysdeps/pthread/timer_gettime.c new file mode 100644 index 000000000..723a61632 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/timer_gettime.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2000, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + +   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 <time.h> + +#include "posix-timer.h" + + +/* Get current value of timer TIMERID and store it in VLAUE.  */ +int +timer_gettime (timerid, value) +     timer_t timerid; +     struct itimerspec *value; +{ +  struct timer_node *timer; +  struct timespec now, expiry; +  int retval = -1, armed = 0, valid; +  clock_t clock = 0; + +  pthread_mutex_lock (&__timer_mutex); + +  timer = timer_id2ptr (timerid); +  valid = timer_valid (timer); + +  if (valid) { +    armed = timer->armed; +    expiry = timer->expirytime; +    clock = timer->clock; +    value->it_interval = timer->value.it_interval; +  } + +  pthread_mutex_unlock (&__timer_mutex); + +  if (valid) +    { +      if (armed) +	{ +	  clock_gettime (clock, &now); +	  if (timespec_compare (&now, &expiry) < 0) +	    timespec_sub (&value->it_value, &expiry, &now); +	  else +	    { +	      value->it_value.tv_sec = 0; +	      value->it_value.tv_nsec = 0; +	    } +	} +      else +	{ +	  value->it_value.tv_sec = 0; +	  value->it_value.tv_nsec = 0; +	} + +      retval = 0; +    } +  else +    __set_errno (EINVAL); + +  return retval; +} diff --git a/libpthread/nptl/sysdeps/pthread/timer_routines.c b/libpthread/nptl/sysdeps/pthread/timer_routines.c new file mode 100644 index 000000000..8d5b1d13a --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/timer_routines.c @@ -0,0 +1,578 @@ +/* Helper code for POSIX timer implementation on NPTL. +   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + +   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 <assert.h> +#include <errno.h> +#include <pthread.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <sysdep.h> +#include <time.h> +#include <unistd.h> +#include <sys/syscall.h> + +#include "posix-timer.h" +#include <pthreadP.h> + + +/* Number of threads used.  */ +#define THREAD_MAXNODES	16 + +/* Array containing the descriptors for the used threads.  */ +static struct thread_node thread_array[THREAD_MAXNODES]; + +/* Static array with the structures for all the timers.  */ +struct timer_node __timer_array[TIMER_MAX]; + +/* Global lock to protect operation on the lists.  */ +pthread_mutex_t __timer_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Variable to protext initialization.  */ +pthread_once_t __timer_init_once_control = PTHREAD_ONCE_INIT; + +/* Nonzero if initialization of timer implementation failed.  */ +int __timer_init_failed; + +/* Node for the thread used to deliver signals.  */ +struct thread_node __timer_signal_thread_rclk; + +/* Lists to keep free and used timers and threads.  */ +struct list_links timer_free_list; +struct list_links thread_free_list; +struct list_links thread_active_list; + + +#ifdef __NR_rt_sigqueueinfo +extern int __syscall_rt_sigqueueinfo (int, int, siginfo_t *); +#endif + + +/* List handling functions.  */ +static inline void +list_init (struct list_links *list) +{ +  list->next = list->prev = list; +} + +static inline void +list_append (struct list_links *list, struct list_links *newp) +{ +  newp->prev = list->prev; +  newp->next = list; +  list->prev->next = newp; +  list->prev = newp; +} + +static inline void +list_insbefore (struct list_links *list, struct list_links *newp) +{ +  list_append (list, newp); +} + +/* + * Like list_unlink_ip, except that calling it on a node that + * is already unlinked is disastrous rather than a noop. + */ + +static inline void +list_unlink (struct list_links *list) +{ +  struct list_links *lnext = list->next, *lprev = list->prev; + +  lnext->prev = lprev; +  lprev->next = lnext; +} + +static inline struct list_links * +list_first (struct list_links *list) +{ +  return list->next; +} + +static inline struct list_links * +list_null (struct list_links *list) +{ +  return list; +} + +static inline struct list_links * +list_next (struct list_links *list) +{ +  return list->next; +} + +static inline int +list_isempty (struct list_links *list) +{ +  return list->next == list; +} + + +/* Functions build on top of the list functions.  */ +static inline struct thread_node * +thread_links2ptr (struct list_links *list) +{ +  return (struct thread_node *) ((char *) list +				 - offsetof (struct thread_node, links)); +} + +static inline struct timer_node * +timer_links2ptr (struct list_links *list) +{ +  return (struct timer_node *) ((char *) list +				- offsetof (struct timer_node, links)); +} + + +/* Initialize a newly allocated thread structure.  */ +static void +thread_init (struct thread_node *thread, const pthread_attr_t *attr, clockid_t clock_id) +{ +  if (attr != NULL) +    thread->attr = *attr; +  else +    { +      pthread_attr_init (&thread->attr); +      pthread_attr_setdetachstate (&thread->attr, PTHREAD_CREATE_DETACHED); +    } + +  thread->exists = 0; +  list_init (&thread->timer_queue); +  pthread_cond_init (&thread->cond, 0); +  thread->current_timer = 0; +  thread->captured = pthread_self (); +  thread->clock_id = clock_id; +} + + +/* Initialize the global lists, and acquire global resources.  Error +   reporting is done by storing a non-zero value to the global variable +   timer_init_failed.  */ +static void +init_module (void) +{ +  int i; + +  list_init (&timer_free_list); +  list_init (&thread_free_list); +  list_init (&thread_active_list); + +  for (i = 0; i < TIMER_MAX; ++i) +    { +      list_append (&timer_free_list, &__timer_array[i].links); +      __timer_array[i].inuse = TIMER_FREE; +    } + +  for (i = 0; i < THREAD_MAXNODES; ++i) +    list_append (&thread_free_list, &thread_array[i].links); + +  thread_init (&__timer_signal_thread_rclk, 0, CLOCK_REALTIME); +} + + +/* This is a handler executed in a child process after a fork() +   occurs.  It reinitializes the module, resetting all of the data +   structures to their initial state.  The mutex is initialized in +   case it was locked in the parent process.  */ +static void +reinit_after_fork (void) +{ +  init_module (); +  pthread_mutex_init (&__timer_mutex, 0); +} + + +/* Called once form pthread_once in timer_init. This initializes the +   module and ensures that reinit_after_fork will be executed in any +   child process.  */ +void +__timer_init_once (void) +{ +  init_module (); +  pthread_atfork (0, 0, reinit_after_fork); +} + + +/* Deinitialize a thread that is about to be deallocated.  */ +static void +thread_deinit (struct thread_node *thread) +{ +  assert (list_isempty (&thread->timer_queue)); +  pthread_cond_destroy (&thread->cond); +} + + +/* Allocate a thread structure from the global free list.  Global +   mutex lock must be held by caller.  The thread is moved to +   the active list. */ +struct thread_node * +__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t clock_id) +{ +  struct list_links *node = list_first (&thread_free_list); + +  if (node != list_null (&thread_free_list)) +    { +      struct thread_node *thread = thread_links2ptr (node); +      list_unlink (node); +      thread_init (thread, desired_attr, clock_id); +      list_append (&thread_active_list, node); +      return thread; +    } + +  return 0; +} + + +/* Return a thread structure to the global free list.  Global lock +   must be held by caller.  */ +void +__timer_thread_dealloc (struct thread_node *thread) +{ +  thread_deinit (thread); +  list_unlink (&thread->links); +  list_append (&thread_free_list, &thread->links); +} + + +/* Each of our threads which terminates executes this cleanup +   handler. We never terminate threads ourselves; if a thread gets here +   it means that the evil application has killed it.  If the thread has +   timers, these require servicing and so we must hire a replacement +   thread right away.  We must also unblock another thread that may +   have been waiting for this thread to finish servicing a timer (see +   timer_delete()).  */ + +static void +thread_cleanup (void *val) +{ +  if (val != NULL) +    { +      struct thread_node *thread = val; + +      /* How did the signal thread get killed?  */ +      assert (thread != &__timer_signal_thread_rclk); + +      pthread_mutex_lock (&__timer_mutex); + +      thread->exists = 0; + +      /* We are no longer processing a timer event.  */ +      thread->current_timer = 0; + +      if (list_isempty (&thread->timer_queue)) +	__timer_thread_dealloc (thread); +      else +	(void) __timer_thread_start (thread); + +      pthread_mutex_unlock (&__timer_mutex); + +      /* Unblock potentially blocked timer_delete().  */ +      pthread_cond_broadcast (&thread->cond); +    } +} + + +/* Handle a timer which is supposed to go off now.  */ +static void +thread_expire_timer (struct thread_node *self, struct timer_node *timer) +{ +  self->current_timer = timer; /* Lets timer_delete know timer is running. */ + +  pthread_mutex_unlock (&__timer_mutex); + +  switch (__builtin_expect (timer->event.sigev_notify, SIGEV_SIGNAL)) +    { +    case SIGEV_NONE: +      break; + +    case SIGEV_SIGNAL: +#ifdef __NR_rt_sigqueueinfo +      { +	siginfo_t info; + +	/* First, clear the siginfo_t structure, so that we don't pass our +	   stack content to other tasks.  */ +	memset (&info, 0, sizeof (siginfo_t)); +	/* We must pass the information about the data in a siginfo_t +           value.  */ +	info.si_signo = timer->event.sigev_signo; +	info.si_code = SI_TIMER; +	info.si_pid = timer->creator_pid; +	info.si_uid = getuid (); +	info.si_value = timer->event.sigev_value; + +	INLINE_SYSCALL (rt_sigqueueinfo, 3, info.si_pid, info.si_signo, &info); +      } +#else +      if (pthread_kill (self->captured, timer->event.sigev_signo) != 0) +	{ +	  if (pthread_kill (self->id, timer->event.sigev_signo) != 0) +	    abort (); +        } +#endif +      break; + +    case SIGEV_THREAD: +      timer->event.sigev_notify_function (timer->event.sigev_value); +      break; + +    default: +      assert (! "unknown event"); +      break; +    } + +  pthread_mutex_lock (&__timer_mutex); + +  self->current_timer = 0; + +  pthread_cond_broadcast (&self->cond); +} + + +/* Thread function; executed by each timer thread. The job of this +   function is to wait on the thread's timer queue and expire the +   timers in chronological order as close to their scheduled time as +   possible.  */ +static void +__attribute__ ((noreturn)) +thread_func (void *arg) +{ +  struct thread_node *self = arg; + +  /* Register cleanup handler, in case rogue application terminates +     this thread.  (This cannot happen to __timer_signal_thread, which +     doesn't invoke application callbacks). */ + +  pthread_cleanup_push (thread_cleanup, self); + +  pthread_mutex_lock (&__timer_mutex); + +  while (1) +    { +      struct list_links *first; +      struct timer_node *timer = NULL; + +      /* While the timer queue is not empty, inspect the first node.  */ +      first = list_first (&self->timer_queue); +      if (first != list_null (&self->timer_queue)) +	{ +	  struct timespec now; + +	  timer = timer_links2ptr (first); + +	  /* This assumes that the elements of the list of one thread +	     are all for the same clock.  */ +	  clock_gettime (timer->clock, &now); + +	  while (1) +	    { +	      /* If the timer is due or overdue, remove it from the queue. +		 If it's a periodic timer, re-compute its new time and +		 requeue it.  Either way, perform the timer expiry. */ +	      if (timespec_compare (&now, &timer->expirytime) < 0) +		break; + +	      list_unlink_ip (first); + +	      if (__builtin_expect (timer->value.it_interval.tv_sec, 0) != 0 +		  || timer->value.it_interval.tv_nsec != 0) +		{ +		  timer->overrun_count = 0; +		  timespec_add (&timer->expirytime, &timer->expirytime, +				&timer->value.it_interval); +		  while (timespec_compare (&timer->expirytime, &now) < 0) +		    { +		      timespec_add (&timer->expirytime, &timer->expirytime, +				    &timer->value.it_interval); +		      if (timer->overrun_count < DELAYTIMER_MAX) +			++timer->overrun_count; +		    } +		  __timer_thread_queue_timer (self, timer); +		} + +	      thread_expire_timer (self, timer); + +	      first = list_first (&self->timer_queue); +	      if (first == list_null (&self->timer_queue)) +		break; + +	      timer = timer_links2ptr (first); +	    } +	} + +      /* If the queue is not empty, wait until the expiry time of the +	 first node.  Otherwise wait indefinitely.  Insertions at the +	 head of the queue must wake up the thread by broadcasting +	 this condition variable.  */ +      if (timer != NULL) +	pthread_cond_timedwait (&self->cond, &__timer_mutex, +				&timer->expirytime); +      else +	pthread_cond_wait (&self->cond, &__timer_mutex); +    } +  /* This macro will never be executed since the while loop loops +     forever - but we have to add it for proper nesting.  */ +  pthread_cleanup_pop (1); +} + + +/* Enqueue a timer in wakeup order in the thread's timer queue. +   Returns 1 if the timer was inserted at the head of the queue, +   causing the queue's next wakeup time to change. */ + +int +__timer_thread_queue_timer (struct thread_node *thread, +			    struct timer_node *insert) +{ +  struct list_links *iter; +  int athead = 1; + +  for (iter = list_first (&thread->timer_queue); +       iter != list_null (&thread->timer_queue); +        iter = list_next (iter)) +    { +      struct timer_node *timer = timer_links2ptr (iter); + +      if (timespec_compare (&insert->expirytime, &timer->expirytime) < 0) +	  break; +      athead = 0; +    } + +  list_insbefore (iter, &insert->links); +  return athead; +} + + +/* Start a thread and associate it with the given thread node.  Global +   lock must be held by caller.  */ +int +__timer_thread_start (struct thread_node *thread) +{ +  int retval = 1; + +  assert (!thread->exists); +  thread->exists = 1; + +  if (pthread_create (&thread->id, &thread->attr, +		      (void *(*) (void *)) thread_func, thread) != 0) +    { +      thread->exists = 0; +      retval = -1; +    } + +  return retval; +} + + +void +__timer_thread_wakeup (struct thread_node *thread) +{ +  pthread_cond_broadcast (&thread->cond); +} + + +/* Compare two pthread_attr_t thread attributes for exact equality. +   Returns 1 if they are equal, otherwise zero if they are not equal +   or contain illegal values.  This version is NPTL-specific for +   performance reason.  One could use the access functions to get the +   values of all the fields of the attribute structure.  */ +static int +thread_attr_compare (const pthread_attr_t *left, const pthread_attr_t *right) +{ +  struct pthread_attr *ileft = (struct pthread_attr *) left; +  struct pthread_attr *iright = (struct pthread_attr *) right; + +  return (ileft->flags == iright->flags +	  && ileft->schedpolicy == iright->schedpolicy +	  && (ileft->schedparam.sched_priority +	      == iright->schedparam.sched_priority) +	  && ileft->guardsize == iright->guardsize +	  && ileft->stackaddr == iright->stackaddr +	  && ileft->stacksize == iright->stacksize +	  && ((ileft->cpuset == NULL && iright->cpuset == NULL) +	      || (ileft->cpuset != NULL && iright->cpuset != NULL +		  && ileft->cpusetsize == iright->cpusetsize +		  && memcmp (ileft->cpuset, iright->cpuset, +			     ileft->cpusetsize) == 0))); +} + + +/* Search the list of active threads and find one which has matching +   attributes.  Global mutex lock must be held by caller.  */ +struct thread_node * +__timer_thread_find_matching (const pthread_attr_t *desired_attr, +			      clockid_t desired_clock_id) +{ +  struct list_links *iter = list_first (&thread_active_list); + +  while (iter != list_null (&thread_active_list)) +    { +      struct thread_node *candidate = thread_links2ptr (iter); + +      if (thread_attr_compare (desired_attr, &candidate->attr) +	  && desired_clock_id == candidate->clock_id) +	return candidate; + +      iter = list_next (iter); +    } + +  return NULL; +} + + +/* Grab a free timer structure from the global free list.  The global +   lock must be held by the caller.  */ +struct timer_node * +__timer_alloc (void) +{ +  struct list_links *node = list_first (&timer_free_list); + +  if (node != list_null (&timer_free_list)) +    { +      struct timer_node *timer = timer_links2ptr (node); +      list_unlink_ip (node); +      timer->inuse = TIMER_INUSE; +      timer->refcount = 1; +      return timer; +    } + +  return NULL; +} + + +/* Return a timer structure to the global free list.  The global lock +   must be held by the caller.  */ +void +__timer_dealloc (struct timer_node *timer) +{ +  assert (timer->refcount == 0); +  timer->thread = NULL;	/* Break association between timer and thread.  */ +  timer->inuse = TIMER_FREE; +  list_append (&timer_free_list, &timer->links); +} + + +/* Thread cancellation handler which unlocks a mutex.  */ +void +__timer_mutex_cancel_handler (void *arg) +{ +  pthread_mutex_unlock (arg); +} diff --git a/libpthread/nptl/sysdeps/pthread/timer_settime.c b/libpthread/nptl/sysdeps/pthread/timer_settime.c new file mode 100644 index 000000000..592b5271b --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/timer_settime.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + +   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 <time.h> + +#include "posix-timer.h" + + +/* Set timer TIMERID to VALUE, returning old value in OVLAUE.  */ +int +timer_settime (timerid, flags, value, ovalue) +     timer_t timerid; +     int flags; +     const struct itimerspec *value; +     struct itimerspec *ovalue; +{ +  struct timer_node *timer; +  struct thread_node *thread = NULL; +  struct timespec now; +  int have_now = 0, need_wakeup = 0; +  int retval = -1; + +  timer = timer_id2ptr (timerid); +  if (timer == NULL) +    { +      __set_errno (EINVAL); +      goto bail; +    } + +  if (value->it_interval.tv_nsec < 0 +      || value->it_interval.tv_nsec >= 1000000000 +      || value->it_value.tv_nsec < 0 +      || value->it_value.tv_nsec >= 1000000000) +    { +      __set_errno (EINVAL); +      goto bail; +    } + +  /* Will need to know current time since this is a relative timer; +     might as well make the system call outside of the lock now! */ + +  if ((flags & TIMER_ABSTIME) == 0) +    { +      clock_gettime (timer->clock, &now); +      have_now = 1; +    } + +  pthread_mutex_lock (&__timer_mutex); +  timer_addref (timer); + +  /* One final check of timer validity; this one is possible only +     until we have the mutex, because it accesses the inuse flag. */ + +  if (! timer_valid(timer)) +    { +      __set_errno (EINVAL); +      goto unlock_bail; +    } + +  if (ovalue != NULL) +    { +      ovalue->it_interval = timer->value.it_interval; + +      if (timer->armed) +	{ +	  if (! have_now) +	    { +	      pthread_mutex_unlock (&__timer_mutex); +	      clock_gettime (timer->clock, &now); +	      have_now = 1; +	      pthread_mutex_lock (&__timer_mutex); +	      timer_addref (timer); +	    } + +	  timespec_sub (&ovalue->it_value, &timer->expirytime, &now); +	} +      else +	{ +	  ovalue->it_value.tv_sec = 0; +	  ovalue->it_value.tv_nsec = 0; +	} +    } + +  timer->value = *value; + +  list_unlink_ip (&timer->links); +  timer->armed = 0; + +  thread = timer->thread; + +  /* A value of { 0, 0 } causes the timer to be stopped. */ +  if (value->it_value.tv_sec != 0 +      || __builtin_expect (value->it_value.tv_nsec != 0, 1)) +    { +      if ((flags & TIMER_ABSTIME) != 0) +	/* The user specified the expiration time.  */ +	timer->expirytime = value->it_value; +      else +	timespec_add (&timer->expirytime, &now, &value->it_value); + +      /* Only need to wake up the thread if timer is inserted +	 at the head of the queue. */ +      if (thread != NULL) +	need_wakeup = __timer_thread_queue_timer (thread, timer); +      timer->armed = 1; +    } + +  retval = 0; + +unlock_bail: +  timer_delref (timer); +  pthread_mutex_unlock (&__timer_mutex); + +bail: +  if (thread != NULL && need_wakeup) +    __timer_thread_wakeup (thread); + +  return retval; +} diff --git a/libpthread/nptl/sysdeps/pthread/unwind-forcedunwind.c b/libpthread/nptl/sysdeps/pthread/unwind-forcedunwind.c new file mode 100644 index 000000000..b0f848708 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/unwind-forcedunwind.c @@ -0,0 +1,97 @@ +/* Copyright (C) 2003 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 <unwind.h> +#include <pthreadP.h> + +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) +  (int, _Unwind_Action, _Unwind_Exception_Class, 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 +      ) +    __libc_fatal ("libgcc_s.so.1 must be installed for pthread_cancel to work\n"); + +  libgcc_s_resume = resume; +  libgcc_s_personality = personality; +  libgcc_s_forcedunwind = forcedunwind; +  libgcc_s_getcfa = getcfa; +} + +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ +  if (__builtin_expect (libgcc_s_resume == NULL, 0)) +    pthread_cancel_init (); +  libgcc_s_resume (exc); +} + +_Unwind_Reason_Code +__gcc_personality_v0 (int version, _Unwind_Action actions, +		      _Unwind_Exception_Class exception_class, +                      struct _Unwind_Exception *ue_header, +                      struct _Unwind_Context *context) +{ +  if (__builtin_expect (libgcc_s_personality == NULL, 0)) +    pthread_cancel_init (); +  return libgcc_s_personality (version, actions, exception_class, +			       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/pthread/unwind-resume.c b/libpthread/nptl/sysdeps/pthread/unwind-resume.c new file mode 100644 index 000000000..088f4c6f6 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/unwind-resume.c @@ -0,0 +1,64 @@ +/* Copyright (C) 2003 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 <unwind.h> + +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) +  (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, +   struct _Unwind_Context *); + +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) +    __libc_fatal ("libgcc_s.so.1 must be installed for pthread_cancel to work\n"); + +  libgcc_s_resume = resume; +  libgcc_s_personality = personality; +} + +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ +  if (__builtin_expect (libgcc_s_resume == NULL, 0)) +    init (); +  libgcc_s_resume (exc); +} + +_Unwind_Reason_Code +__gcc_personality_v0 (int version, _Unwind_Action actions, +		      _Unwind_Exception_Class exception_class, +                      struct _Unwind_Exception *ue_header, +                      struct _Unwind_Context *context) +{ +  if (__builtin_expect (libgcc_s_personality == NULL, 0)) +    init (); +  return libgcc_s_personality (version, actions, exception_class, +			       ue_header, context); +} diff --git a/libpthread/nptl/sysdeps/sparc/tls.h b/libpthread/nptl/sysdeps/sparc/tls.h index 8f54a0bb2..54b54859d 100644 --- a/libpthread/nptl/sysdeps/sparc/tls.h +++ b/libpthread/nptl/sysdeps/sparc/tls.h @@ -69,11 +69,13 @@ typedef struct  register struct pthread *__thread_self __asm__("%g7"); -/* This is the size of the initial TCB.  */ -# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) +/* This is the size of the initial TCB.  Can't be just sizeof (tcbhead_t), +   because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole +   struct pthread even when not linked with -lpthread.  */ +# define TLS_INIT_TCB_SIZE sizeof (struct pthread)  /* Alignment requirements for the initial TCB.  */ -# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)  /* This is the size of the TCB.  */  # define TLS_TCB_SIZE sizeof (struct pthread) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/Implies b/libpthread/nptl/sysdeps/unix/sysv/linux/Implies new file mode 100644 index 000000000..f1b3e8939 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/Implies @@ -0,0 +1 @@ +pthread diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile new file mode 100644 index 000000000..991398242 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile @@ -0,0 +1,34 @@ +# 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.  */ + +ifeq ($(subdir),nptl) +sysdep_routines += register-atfork unregister-atfork libc_pthread_init \ +		   libc_multiple_threads + +libpthread-sysdep_routines += pt-fork pthread_mutex_cond_lock + +gen-as-const-headers += lowlevelcond.sym lowlevelrwlock.sym \ +			lowlevelbarrier.sym unwindbuf.sym +endif + +ifeq ($(subdir),posix) +CFLAGS-fork.c = -D_IO_MTSAFE_IO +CFLAGS-getpid.o = -fomit-frame-pointer +CFLAGS-getpid.os = -fomit-frame-pointer +endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/Versions b/libpthread/nptl/sysdeps/unix/sysv/linux/Versions new file mode 100644 index 000000000..d18255521 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/Versions @@ -0,0 +1,15 @@ +libc { +  GLIBC_2.3.2 { +    __register_atfork; +  } +  GLIBC_PRIVATE { +    __libc_pthread_init; +    __libc_current_sigrtmin_private; __libc_current_sigrtmax_private; +    __libc_allocate_rtsig_private; +  } +} +libpthread { +  GLIBC_2.0 { +    fork; __fork; +  } +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/aio_misc.h b/libpthread/nptl/sysdeps/unix/sysv/linux/aio_misc.h new file mode 100644 index 000000000..7b0bac75f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/aio_misc.h @@ -0,0 +1,67 @@ +/* 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; 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 _AIO_MISC_H +# include_next <aio_misc.h> +# include <signal.h> +# include <sysdep.h> +# include <pthread.h> + +# define aio_start_notify_thread __aio_start_notify_thread +# define aio_create_helper_thread __aio_create_helper_thread + +extern inline void +__aio_start_notify_thread (void) +{ +  sigset_t ss; +  sigemptyset (&ss); +  INTERNAL_SYSCALL_DECL (err); +  INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8); +} + +extern inline int +__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), void *arg) +{ +  pthread_attr_t attr; + +  /* Make sure the thread is created detached.  */ +  pthread_attr_init (&attr); +  pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + +  /* The helper thread needs only very little resources.  */ +  (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + +  /* Block all signals in the helper thread.  To do this thoroughly we +     temporarily have to block all signals here.  */ +  sigset_t ss; +  sigset_t oss; +  sigfillset (&ss); +  INTERNAL_SYSCALL_DECL (err); +  INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8); + +  int ret = pthread_create (threadp, &attr, tf, arg); + +  /* Restore the signal mask.  */ +  INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL, +		    _NSIG / 8); + +  (void) pthread_attr_destroy (&attr); +  return ret; +}                                                                                  +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/allocrtsig.c b/libpthread/nptl/sysdeps/unix/sysv/linux/allocrtsig.c new file mode 100644 index 000000000..b37d54d65 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/allocrtsig.c @@ -0,0 +1,56 @@ +/* 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 <signal.h> + + +static int current_rtmin = __SIGRTMIN + 2; +static int current_rtmax = __SIGRTMAX; + + +/* We reserve __SIGRTMIN for use as the cancelation signal.  This +   signal is used internally.  */ +int +__libc_current_sigrtmin (void) +{ +  return current_rtmin; +} +libc_hidden_def (__libc_current_sigrtmin) +strong_alias (__libc_current_sigrtmin, __libc_current_sigrtmin_private) + + +int +__libc_current_sigrtmax (void) +{ +  return current_rtmax; +} +libc_hidden_def (__libc_current_sigrtmax) +strong_alias (__libc_current_sigrtmax, __libc_current_sigrtmax_private) + + +int +__libc_allocate_rtsig (int high) +{ +  if (current_rtmin == -1 || current_rtmin > current_rtmax) +    /* We don't have anymore signal available.  */ +    return -1; + +  return high ? current_rtmin++ : current_rtmax--; +} +strong_alias (__libc_allocate_rtsig, __libc_allocate_rtsig_private) 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/aio_cancel.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/aio_cancel.c new file mode 100644 index 000000000..0d6da8291 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/aio_cancel.c @@ -0,0 +1,33 @@ +#include <shlib-compat.h> + +#define aio_cancel64 XXX +#include <aio.h> +#undef aio_cancel64 +#include <errno.h> + +extern __typeof (aio_cancel) __new_aio_cancel; +extern __typeof (aio_cancel) __old_aio_cancel; + +#define aio_cancel	__new_aio_cancel + +#include <sysdeps/pthread/aio_cancel.c> + +#undef aio_cancel +strong_alias (__new_aio_cancel, __new_aio_cancel64); +versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); +versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); + +#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) + +#undef ECANCELED +#define aio_cancel	__old_aio_cancel +#define ECANCELED	125 + +#include <sysdeps/pthread/aio_cancel.c> + +#undef aio_cancel +strong_alias (__old_aio_cancel, __old_aio_cancel64); +compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); +compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); + +#endif 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..d13d6e86a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h @@ -0,0 +1,158 @@ +/* Machine-specific pthread type layouts.  Alpha version. +   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 _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; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is deliberately not exposed.  */ +typedef union +{ +  struct +  { +    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; +  } __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; + +    unsigned int __reserved[6]; +    /* 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..f4ed9311b --- /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) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) 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/configure b/libpthread/nptl/sysdeps/unix/sysv/linux/configure new file mode 100644 index 000000000..229414dd7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/configure @@ -0,0 +1,3 @@ +# Local configure fragment for sysdeps/unix/sysv/linux. + +DEFINES="$DEFINES -D_LIBC_REENTRANT" 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..9defac619 --- /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 <nptl/sysdeps/pthread/createthread.c> 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..840974401 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c @@ -0,0 +1,213 @@ +/* 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 <unistd.h> +#include <sys/types.h> +#include <sysdep.h> +#include <libio/libioP.h> +#include <tls.h> +#include "fork.h" +#include <hp-timing.h> +#include <ldsodefs.h> +#include <bits/stdio-lock.h> +#include <atomic.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) +{ +  _IO_ITER i; + +  for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i)) +    _IO_lock_init (*((_IO_lock_t *) _IO_iter_file(i)->_lock)); +} + + +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; +    } + +  _IO_list_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.  */ +      _IO_list_resetlock (); + +      /* Reset the lock the dynamic loader uses to protect its data.  */ +      __rtld_lock_initialize (GL(dl_load_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.  */ +      _IO_list_unlock (); + +      /* 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_def (__fork) +weak_alias (__libc_fork, 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..98307ff21 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/getpid.c @@ -0,0 +1,65 @@ +/* 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> + + +#ifndef NOT_IN_libc +static inline __attribute__((always_inline)) pid_t really_getpid (pid_t oldval); + +static inline __attribute__((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_def (__getpid) +weak_alias (__getpid, getpid) +libc_hidden_def (getpid) 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..4d1c9450b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h @@ -0,0 +1,160 @@ +/* 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; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    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; +    int __spins; +  } __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..95c17f18e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/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..37e3d9499 --- /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 <nptl/sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/dl-sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/dl-sysdep.h new file mode 100644 index 000000000..109ffd1cf --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/dl-sysdep.h @@ -0,0 +1,64 @@ +/* System-specific settings for dynamic linker code.  IA-32 version. +   Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifndef _DL_SYSDEP_H +#define _DL_SYSDEP_H	1 + +/* This macro must be defined to either 0 or 1. + +   If 1, then an errno global variable hidden in ld.so will work right with +   all the errno-using libc code compiled for ld.so, and there is never a +   need to share the errno location with libc.  This is appropriate only if +   all the libc functions that ld.so uses are called without PLT and always +   get the versions linked into ld.so rather than the libc ones.  */ + +#ifdef IS_IN_rtld +# define RTLD_PRIVATE_ERRNO 1 +#else +# define RTLD_PRIVATE_ERRNO 0 +#endif + +/* Traditionally system calls have been made using int $0x80.  A +   second method was introduced which, if possible, will use the +   sysenter/syscall instructions.  To signal the presence and where to +   find the code the kernel passes an AT_SYSINFO value in the +   auxiliary vector to the application. +   sysenter/syscall is not useful on i386 through i586, but the dynamic +   linker and dl code in libc.a has to be able to load i686 compiled +   libraries.  */ +#define NEED_DL_SYSINFO	1 +#undef USE_DL_SYSINFO + +#if defined NEED_DL_SYSINFO && !defined __ASSEMBLER__ +extern void _dl_sysinfo_int80 (void) attribute_hidden; +# define DL_SYSINFO_DEFAULT (uintptr_t) _dl_sysinfo_int80 +# define DL_SYSINFO_IMPLEMENTATION \ +  asm (".text\n\t"							      \ +       ".type _dl_sysinfo_int80,@function\n\t"				      \ +       ".hidden _dl_sysinfo_int80\n\t"					      \ +       CFI_STARTPROC "\n"						      \ +       "_dl_sysinfo_int80:\n\t"						      \ +       "int $0x80;\n\t"							      \ +       "ret;\n\t"							      \ +       CFI_ENDPROC "\n"							      \ +       ".size _dl_sysinfo_int80,.-_dl_sysinfo_int80\n\t"		      \ +       ".previous;"); +#endif + +#endif	/* dl-sysdep.h */ 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..813e5299a --- /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 <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..dc65b709a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S @@ -0,0 +1,285 @@ +/* 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 SYS_gettimeofday	__NR_gettimeofday +#define SYS_futex		240 +#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..114284c44 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S @@ -0,0 +1,163 @@ +/* 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 SYS_futex	240 +#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..5471c1c92 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S @@ -0,0 +1,164 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include <kernel-features.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define SYS_futex		240 +#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 +versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, +		  GLIBC_2_3_2) 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..3c5a1db59 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S @@ -0,0 +1,114 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include <kernel-features.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define SYS_futex		240 +#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 +versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, +		  GLIBC_2_3_2) 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..699c2cb22 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S @@ -0,0 +1,637 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include <pthread-errnos.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define SYS_gettimeofday	__NR_gettimeofday +#define SYS_futex		240 +#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 +versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, +		  GLIBC_2_3_2) + + +	.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 + + +	.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: +	.long	.LcleanupSTART-.LSTARTCODE +	.long	.Ladd_cond_futex-.LcleanupSTART +	.long	__condvar_tw_cleanup-.LSTARTCODE +	.uleb128  0 +	.long	.Ladd_cond_futex-.LSTARTCODE +	.long	.Lsub_cond_futex-.Ladd_cond_futex +	.long	__condvar_tw_cleanup2-.LSTARTCODE +	.uleb128  0 +	.long	.Lsub_cond_futex-.LSTARTCODE +	.long	.LcleanupEND-.Lsub_cond_futex +	.long	__condvar_tw_cleanup-.LSTARTCODE +	.uleb128  0 +	.long	.LcallUR-.LSTARTCODE +	.long	.LENDCODE-.LcallUR +	.long	0 +	.uleb128  0 +.Lcstend: + + +	.section .eh_frame,"a",@progbits +.LSTARTFRAME: +	.long	L(ENDCIE)-L(STARTCIE)		# 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 -4				# Data alignment factor. +	.byte	8				# 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 6				# Augmentation value length. +	.byte	0x0				# Personality: absolute +	.long	__gcc_personality_v0 +	.byte	0x0				# LSDA Encoding: absolute +#endif +	.byte 0x0c				# DW_CFA_def_cfa +	.uleb128 4 +	.uleb128 4 +	.byte	0x88				# DW_CFA_offset, column 0x8 +	.uleb128 1 +	.align 4 +.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. +	.uleb128 4				# Augmentation size +#ifdef SHARED +	.long	.LexceptSTART-. +#else +	.long	.LexceptSTART +#endif +	.byte	0x40+.Lpush_ebp-.LSTARTCODE	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 8 +	.byte	0x85				# DW_CFA_offset %ebp +	.uleb128 2 +	.byte	0x40+ .Lpush_edi-.Lpush_ebp	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 12 +	.byte	0x87				# DW_CFA_offset %edi +	.uleb128 3 +	.byte	0x40+.Lpush_esi-.Lpush_edi	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0x86				# DW_CFA_offset %esi +	.uleb128 4 +	.byte	0x40+.Lpush_ebx-.Lpush_esi	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 20 +	.byte	0x83				# DW_CFA_offset %ebx +	.uleb128 5 +	.byte	2				# DW_CFA_advance_loc1 +	.byte	.Lsubl-.Lpush_ebx +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 20+FRAME_SIZE +	.byte	3				# DW_CFA_advance_loc2 +	.2byte	.Laddl-.Lsubl +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 20 +	.byte	0x40+.Lpop_ebx-.Laddl		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0xc3				# DW_CFA_restore %ebx +	.byte	0x40+.Lpop_esi-.Lpop_ebx	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 12 +	.byte	0xc6				# DW_CFA_restore %esi +	.byte	0x40+.Lpop_edi-.Lpop_esi	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 8 +	.byte	0xc7				# DW_CFA_restore %edi +	.byte	0x40+.Lpop_ebp-.Lpop_edi	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 4 +	.byte	0xc5				# DW_CFA_restore %ebp +	.byte	0x40+.LSbl1-.Lpop_edi		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 20 +	.byte	0x40+.LSbl2-.LSbl1		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 20+FRAME_SIZE +	.byte	0x85				# DW_CFA_offset %ebp +	.uleb128 2 +	.byte	0x87				# DW_CFA_offset %edi +	.uleb128 3 +	.byte	0x86				# DW_CFA_offset %esi +	.uleb128 4 +	.byte	0x83				# DW_CFA_offset %ebx +	.uleb128 5 +	.byte	0x40+.LSbl3-.LSbl2		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 20 +#if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS +	.byte	0x40+.LSbl4-.LSbl3		# DW_CFA_advance_loc+N +#else +	.byte	4				# DW_CFA_advance_loc4 +	.long	.LSbl5-.LSbl3 +#endif +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 20+FRAME_SIZE +	.align	4 +.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/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..d28278515 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S @@ -0,0 +1,523 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include <tcb-offsets.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define SYS_futex		240 +#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 +versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, +		  GLIBC_2_3_2) + + +	.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 + + +	.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: +	.long	.LcleanupSTART-.LSTARTCODE +	.long	.Ladd_cond_futex-.LcleanupSTART +	.long	__condvar_w_cleanup-.LSTARTCODE +	.uleb128  0 +	.long	.Ladd_cond_futex-.LSTARTCODE +	.long	.Lsub_cond_futex-.Ladd_cond_futex +	.long	__condvar_w_cleanup2-.LSTARTCODE +	.uleb128  0 +	.long	.Lsub_cond_futex-.LSTARTCODE +	.long	.LcleanupEND-.Lsub_cond_futex +	.long	__condvar_w_cleanup-.LSTARTCODE +	.uleb128  0 +	.long	.LcallUR-.LSTARTCODE +	.long	.LENDCODE-.LcallUR +	.long	0 +	.uleb128  0 +.Lcstend: + +	.section .eh_frame,"a",@progbits +.LSTARTFRAME: +	.long	L(ENDCIE)-L(STARTCIE)		# 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 -4				# Data alignment factor. +	.byte	8				# 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 6				# Augmentation value length. +	.byte	0x0				# Personality: absolute +	.long	__gcc_personality_v0 +	.byte	0x0				# LSDA Encoding: absolute +#endif +	.byte 0x0c				# DW_CFA_def_cfa +	.uleb128 4 +	.uleb128 4 +	.byte	0x88				# DW_CFA_offset, column 0x8 +	.uleb128 1 +	.align 4 +.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. +	.uleb128 4				# Augmentation size +#ifdef SHARED +	.long	.LexceptSTART-. +#else +	.long	.LexceptSTART +#endif +	.byte	0x40+.Lpush_edi-.LSTARTCODE	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 8 +	.byte	0x87				# DW_CFA_offset %edi +	.uleb128 2 +	.byte	0x40+.Lpush_esi-.Lpush_edi	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 12 +	.byte	0x86				# DW_CFA_offset %esi +	.uleb128 3 +	.byte	0x40+.Lpush_ebx-.Lpush_esi	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0x83				# DW_CFA_offset %ebx +	.uleb128 4 +	.byte	2				# DW_CFA_advance_loc1 +	.byte	.Lsubl-.Lpush_ebx +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16+FRAME_SIZE +	.byte	2				# DW_CFA_advance_loc1 +	.byte	.Laddl-.Lsubl +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0x40+ .Lpop_ebx-.Laddl		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 12 +	.byte	0xc3				# DW_CFA_restore %ebx +	.byte	0x40+.Lpop_esi-.Lpop_ebx	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 8 +	.byte	0xc6				# DW_CFA_restore %esi +	.byte	0x40+.Lpop_edi-.Lpop_esi	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 4 +	.byte	0xc7				# DW_CFA_restore %edi +	.byte	0x40+.LSbl1-.Lpop_edi		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0x87				# DW_CFA_offset %edi +	.uleb128 2 +	.byte	0x86				# DW_CFA_offset %esi +	.uleb128 3 +	.byte	0x83				# DW_CFA_offset %ebx +	.uleb128 4 +	.byte	0x40+.LSbl2-.LSbl1		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16+FRAME_SIZE +	.byte	0x40+.LSbl3-.LSbl2		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0x40+.LSbl4-.LSbl3		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16+FRAME_SIZE +	.align	4 +.LENDFDE: + + +#ifdef PIC +	.section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits +	.globl	__i686.get_pc_thunk.cx +	.hidden	__i686.get_pc_thunk.cx +	.type	__i686.get_pc_thunk.cx,@function +__i686.get_pc_thunk.cx: +	movl (%esp), %ecx; +	ret +	.size	__i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx +#endif + +#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/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..db0639d21 --- /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> + + +#define SYS_futex		240 +#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..eb5665b43 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S @@ -0,0 +1,215 @@ +/* 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> + + +#define SYS_gettimeofday	__NR_gettimeofday +#define SYS_futex		240 +#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..d9db77ba0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S @@ -0,0 +1,208 @@ +/* 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> + + +#define SYS_gettimeofday	__NR_gettimeofday +#define SYS_futex		240 +#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..64aac3255 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S @@ -0,0 +1,141 @@ +/* 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 SYS_futex		240 +#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..ea9cc170d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S @@ -0,0 +1,166 @@ +/* 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> + + +#define SYS_futex		240 +#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..71e96d222 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S @@ -0,0 +1,102 @@ +/* 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 <shlib-compat.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define SYS_futex		240 +#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	__i686.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 +	versioned_symbol(libpthread, __new_sem_post, sem_post, GLIBC_2_1) +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +	.global	__old_sem_post +__old_sem_post = __new_sem_post +	compat_symbol(libpthread, __old_sem_post, sem_post, GLIBC_2_0) +#endif + + +#ifdef PIC +	.section .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits +	.globl	__i686.get_pc_thunk.bx +	.hidden	__i686.get_pc_thunk.bx +	.type	__i686.get_pc_thunk.bx,@function +__i686.get_pc_thunk.bx: +	movl (%esp), %ebx; +	ret +	.size	__i686.get_pc_thunk.bx,.-__i686.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..318b53a87 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S @@ -0,0 +1,195 @@ +/* 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 <shlib-compat.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define SYS_gettimeofday	__NR_gettimeofday +#define SYS_futex		240 +#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	__i686.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..d36a1088f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S @@ -0,0 +1,90 @@ +/* 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 <shlib-compat.h> +#include <pthread-errnos.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	__i686.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 +	versioned_symbol(libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1) +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +	.global	__old_sem_trywait +__old_sem_trywait = __new_sem_trywait +	compat_symbol(libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0) +#endif + + +#ifdef PIC +	.section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits +	.globl	__i686.get_pc_thunk.cx +	.hidden	__i686.get_pc_thunk.cx +	.type	__i686.get_pc_thunk.cx,@function +__i686.get_pc_thunk.cx: +	movl (%esp), %ecx; +	ret +	.size	__i686.get_pc_thunk.cx,.-__i686.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..1605b69b6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S @@ -0,0 +1,139 @@ +/* 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 <shlib-compat.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define SYS_futex		240 +#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	__i686.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 +	versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1) +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +	.global	__old_sem_wait +__old_sem_wait = __new_sem_wait +	compat_symbol(libpthread, __old_sem_wait, sem_wait, GLIBC_2_0) +#endif 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/dl-sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h new file mode 100644 index 000000000..b7771318a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h @@ -0,0 +1,61 @@ +/* System-specific settings for dynamic linker code.  IA-32 version. +   Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifndef _DL_SYSDEP_H +#define _DL_SYSDEP_H	1 + +/* This macro must be defined to either 0 or 1. + +   If 1, then an errno global variable hidden in ld.so will work right with +   all the errno-using libc code compiled for ld.so, and there is never a +   need to share the errno location with libc.  This is appropriate only if +   all the libc functions that ld.so uses are called without PLT and always +   get the versions linked into ld.so rather than the libc ones.  */ + +#ifdef IS_IN_rtld +# define RTLD_PRIVATE_ERRNO 1 +#else +# define RTLD_PRIVATE_ERRNO 0 +#endif + +/* Traditionally system calls have been made using int $0x80.  A +   second method was introduced which, if possible, will use the +   sysenter/syscall instructions.  To signal the presence and where to +   find the code the kernel passes an AT_SYSINFO value in the +   auxiliary vector to the application.  */ +#define NEED_DL_SYSINFO	1 +#define USE_DL_SYSINFO	1 + +#if defined NEED_DL_SYSINFO && !defined __ASSEMBLER__ +extern void _dl_sysinfo_int80 (void) attribute_hidden; +# define DL_SYSINFO_DEFAULT (uintptr_t) _dl_sysinfo_int80 +# define DL_SYSINFO_IMPLEMENTATION \ +  asm (".text\n\t"							      \ +       ".type _dl_sysinfo_int80,@function\n\t"				      \ +       ".hidden _dl_sysinfo_int80\n"					      \ +       CFI_STARTPROC "\n"						      \ +       "_dl_sysinfo_int80:\n\t"						      \ +       "int $0x80;\n\t"							      \ +       "ret;\n\t"							      \ +       CFI_ENDPROC "\n"							      \ +       ".size _dl_sysinfo_int80,.-_dl_sysinfo_int80\n\t"		      \ +       ".previous"); +#endif + +#endif	/* dl-sysdep.h */ 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..b86f11c9b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -0,0 +1,374 @@ +/* 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> + +#ifndef LOCK_INSTR +# ifdef UP +#  define LOCK_INSTR	/* nothing */ +# else +#  define LOCK_INSTR "lock;" +# endif +#endif + +#define SYS_futex		240 +#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 + +#ifdef I386_USE_SYSENTER +# ifdef SHARED +#  define LLL_ENTER_KERNEL	"call *%%gs:%P6\n\t" +# else +#  define LLL_ENTER_KERNEL	"call *_dl_sysinfo\n\t" +# endif +#else +# define LLL_ENTER_KERNEL	"int $0x80\n\t" +#endif + +/* 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 (LLL_EBX_LOAD					      \ +		      LLL_ENTER_KERNEL					      \ +		      LLL_EBX_LOAD					      \ +		      : "=a" (__ignore)					      \ +		      : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (0),	      \ +			"c" (FUTEX_WAIT), "d" (_val),			      \ +			"i" (offsetof (tcbhead_t, sysinfo)));		      \ +  } while (0) + + +#define lll_futex_wake(futex, nr) \ +  do {									      \ +    int __ignore;							      \ +    register __typeof (nr) _nr asm ("edx") = (nr);			      \ +    __asm __volatile (LLL_EBX_LOAD					      \ +		      LLL_ENTER_KERNEL					      \ +		      LLL_EBX_LOAD					      \ +		      : "=a" (__ignore)					      \ +		      : "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)));		      \ +  } while (0) + + +/* 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) + + +/* 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_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 || 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. + +   XXX In future we might even want to avoid it on UP machines.  */ +# include <tls.h> + +# 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) \ +  do {									      \ +    int __ignore;							      \ +    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" (__ignore)				      \ +			: "i" (SYS_futex), LLL_EBX_REG (&tid), "S" (0),	      \ +			  "c" (FUTEX_WAIT), "d" (_tid),			      \ +			  "i" (offsetof (tcbhead_t, sysinfo)));		      \ +  } while (0) + +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..cc3282fbd --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h @@ -0,0 +1,75 @@ +/* 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; +#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-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S new file mode 100644 index 000000000..24f5a1d29 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S @@ -0,0 +1,68 @@ +/* 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 <sysdep.h> +#define _ERRNO_H	1 +#include <bits/errno.h> +#include <kernel-features.h> +#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: + +/* 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) +	/* Pop the return PC value into ECX.  */ +	popl	%ecx + +	SAVE_PID + +	/* Stuff the syscall number in EAX and enter into the kernel.  */ +	movl	$SYS_ify (vfork), %eax +	int	$0x80 + +	RESTORE_PID + +	/* Jump to the return PC.  Don't jump directly since this +	   disturbs the branch target cache.  Instead push the return +	   address back on the stack.  */ +	pushl	%ecx + +	cmpl	$-4095, %eax +	jae	SYSCALL_ERROR_LABEL	/* Branch forward if it failed.  */ +.Lpseudo_end: +	ret +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) 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..312933c5e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S @@ -0,0 +1,182 @@ +/* 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 SYS_futex	240 +#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	__i686.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.__i686.get_pc_thunk.cx,"ax",@progbits +	.globl	__i686.get_pc_thunk.cx +	.hidden	__i686.get_pc_thunk.cx +	.type	__i686.get_pc_thunk.cx,@function +__i686.get_pc_thunk.cx: +	movl (%esp), %ecx; +	ret +	.size	__i686.get_pc_thunk.cx,.-__i686.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..80c0b5216 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_init.c @@ -0,0 +1 @@ +#include <nptl/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..41c71f348 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_unlock.S @@ -0,0 +1 @@ +#include <nptl/sysdeps/i386/pthread_spin_unlock.S> 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..147f5c847 --- /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 <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)				      \ +  .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/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/vfork.S new file mode 100644 index 000000000..52336102c --- /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 <sysdeps/unix/sysv/linux/i386/vfork.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/Makefile new file mode 100644 index 000000000..ff98f1a49 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),nptl) +libpthread-sysdep_routines += __ia64_longjmp unwind_longjmp __sigstack_longjmp +endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/Versions b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/Versions new file mode 100644 index 000000000..437c4da28 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/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/ia64/__ia64_longjmp.S b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/__ia64_longjmp.S new file mode 100644 index 000000000..1ceb210c2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/__ia64_longjmp.S @@ -0,0 +1,156 @@ +/* Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc. +   Contributed by David Mosberger-Tang <davidm@hpl.hp.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.  */ + +#include <sysdep.h> +#include <features.h> + +LEAF(__ia64_flush_rbs) +	flushrs +	mov r9 = ar.rsc		// 12 cyc latency +	;; +	mov r8 = ar.bsp		// 12 cyc latency +	;; +	and r16 = ~0x3, r9	// clear ar.rsc.mode +	;; +	mov ar.rsc = r16	// put RSE into enforced-lazy mode +	;; +	mov r10 = ar.rnat	// 5 cyc latency +	ret +END(__ia64_flush_rbs) + + +#	define	pPos	p6	/* is rotate count positive? */ +#	define	pNeg	p7	/* is rotate count negative? */ + +/* __ia64_longjmp(__jmp_buf buf, int val, long rnat, long rsc)  */ + + +LEAF(__ia64_longjmp) +	alloc r8=ar.pfs,4,0,0,0 +	add r2=0x98,in0		// r2 <- &jmpbuf.orig_jmp_buf_addr +	add r3=0x88,in0		// r3 <- &jmpbuf.ar_bsp +	;; +	ld8 r8=[r2]		// r8 <- orig_jmp_buf_addr +	ld8 r23=[r3],8		// r23 <- jmpbuf.ar_bsp +	mov r2=in0 +	;; +	// +	// Note: we need to redo the "flushrs" here even though it's +	// already been done by __ia64_flush_rbs.  It is needed to +	// ensure that ar.bspstore == ar.bsp. +	// +	flushrs			// flush dirty regs to backing store +	ld8 r25=[r3]		// r25 <- jmpbuf.ar_unat +	sub r8=r8,in0		// r8 <- &orig_jmpbuf - &jmpbuf +	;; +	add r3=8,in0		// r3 <- &jmpbuf.r1 +	extr.u r8=r8,3,6	// r8 <- (&orig_jmpbuf - &jmpbuf)/8 & 0x3f +	;; +	cmp.lt pNeg,pPos=r8,r0 +	;; +(pPos)	mov r16=r8 +(pNeg)	add r16=64,r8 +(pPos)	sub r17=64,r8 +(pNeg)	sub r17=r0,r8 +	;; +	shr.u r8=r25,r16 +	shl r9=r25,r17 +	;; +	or r25=r8,r9 +	;; +	mov ar.unat=r25 // setup ar.unat (NaT bits for r1, r4-r7, and r12) +	;; +	ld8.fill.nta sp=[r2],16	// r12 (sp) +	ld8.fill.nta gp=[r3],16 // r1 (gp) +	dep r11=-1,r23,3,6	// r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp) +	;; +	ld8.nta r16=[r2],16		// caller's unat +	ld8.nta r17=[r3],16		// fpsr +	;; +	ld8.fill.nta r4=[r2],16		// r4 +	ld8.fill.nta r5=[r3],16		// r5 (gp) +	;; +	ld8.fill.nta r6=[r2],16		// r6 +	ld8.fill.nta r7=[r3],16		// r7 +	;; +	mov ar.unat=r16			// restore caller's unat +	mov ar.fpsr=r17			// restore fpsr +	;; +	ld8.nta r16=[r2],16		// b0 +	ld8.nta r17=[r3],16		// b1 +	;; +	mov ar.bspstore=r23	// restore ar.bspstore +	ld8.nta r18=[r2],16		// b2 +	;; +	mov ar.rnat=in2		// restore ar.rnat +	ld8.nta r19=[r3],16		// b3 +	;; +	ld8.nta r20=[r2],16		// b4 +	ld8.nta r21=[r3],16		// b5 +	;; +	ld8.nta r11=[r2],16		// ar.pfs +	ld8.nta r22=[r3],56		// ar.lc +	;; +	ld8.nta r24=[r2],32		// pr +	mov ar.rsc=in3		// restore ar.rsc +	mov b0=r16 +	;; +	ldf.fill.nta f2=[r2],32 +	ldf.fill.nta f3=[r3],32 +	mov b1=r17 +	;; +	ldf.fill.nta f4=[r2],32 +	ldf.fill.nta f5=[r3],32 +	mov b2=r18 +	;; +	ldf.fill.nta f16=[r2],32 +	ldf.fill.nta f17=[r3],32 +	mov b3=r19 +	;; +	ldf.fill.nta f18=[r2],32 +	ldf.fill.nta f19=[r3],32 +	mov b4=r20 +	;; +	ldf.fill.nta f20=[r2],32 +	ldf.fill.nta f21=[r3],32 +	mov b5=r21 +	;; +	ldf.fill.nta f22=[r2],32 +	ldf.fill.nta f23=[r3],32 +	mov ar.lc=r22 +	;; +	ldf.fill.nta f24=[r2],32 +	ldf.fill.nta f25=[r3],32 +	cmp.eq p8,p9=0,in1 +	;; +	ldf.fill.nta f26=[r2],32 +	ldf.fill.nta f27=[r3],32 +	mov ar.pfs=r11 +	;; +	ldf.fill.nta f28=[r2],32 +	ldf.fill.nta f29=[r3],32 +(p8)	mov r8=1 +	;; +	ldf.fill.nta f30=[r2] +	ldf.fill.nta f31=[r3] +(p9)	mov r8=in1 + +	invala			// virt. -> phys. regnum mapping may change +	mov pr=r24,-1 +	ret +END(__ia64_longjmp) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/__sigstack_longjmp.c b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/__sigstack_longjmp.c new file mode 100644 index 000000000..8f552eaad --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/__sigstack_longjmp.c @@ -0,0 +1,168 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by David Mosberger-Tang <davidm@hpl.hp.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.  */ + +/* The public __longjmp() implementation is limited to jumping within +   the same stack.  That is, in general it is not possible to use this +   __longjmp() implementation to cross from one stack to another. +   In constrast, the __sigstack_longjmp() implemented here allows +   crossing from the alternate signal stack to the normal stack +   as a special case.  */ + +#include <assert.h> +#include <setjmp.h> +#include <signal.h> +#include <stdint.h> +#include <stdlib.h> + +#include <sysdep.h> +#include <sys/rse.h> + +#define JB_SP	0 +#define JB_BSP	17 + +struct rbs_flush_values +  { +    unsigned long bsp; +    unsigned long rsc; +    unsigned long rnat; +  }; + +extern struct rbs_flush_values __ia64_flush_rbs (void); +extern void __ia64_longjmp (__jmp_buf buf, int val, long rnat, long rsc) +     __attribute__ ((__noreturn__)); + +static void +copy_rbs (unsigned long *dst, unsigned long *dst_end, unsigned long dst_rnat, +	  unsigned long *src, unsigned long *src_end, +	  unsigned long current_rnat) +{ +  unsigned long dst_slot, src_rnat = 0, src_slot, *src_rnat_addr, nat_bit; +  int first_time = 1; + +  while (dst < dst_end) +    { +      dst_slot = ia64_rse_slot_num (dst); +      if (dst_slot == 63) +	{ +	  *dst++ = dst_rnat; +	  dst_rnat = 0; +	} +      else +	{ +	  /* read source value, including NaT bit: */ +	  src_slot = ia64_rse_slot_num (src); +	  if (src_slot == 63) +	    { +	      /* skip src RNaT slot */ +	      ++src; +	      src_slot = 0; +	    } +	  if (first_time || src_slot == 0) +	    { +	      first_time = 0; +	      src_rnat_addr = ia64_rse_rnat_addr (src); +	      if (src_rnat_addr < src_end) +		src_rnat = *src_rnat_addr; +	      else +		src_rnat = current_rnat; +	    } +	  nat_bit = (src_rnat >> src_slot) & 1; + +	  assert (src < src_end); + +	  *dst++ = *src++; +	  if (nat_bit) +	    dst_rnat |=  (1UL << dst_slot); +	  else +	    dst_rnat &= ~(1UL << dst_slot); +	} +    } +  dst_slot = ia64_rse_slot_num (dst); +  if (dst_slot > 0) +    *ia64_rse_rnat_addr (dst) = dst_rnat; +} + +void +__sigstack_longjmp (__jmp_buf buf, int val) +{ +  unsigned long *rbs_base, *bsp, *bspstore, *jb_bsp, jb_sp, ss_sp; +  unsigned long ndirty, rnat, load_rnat, *jb_rnat_addr; +  struct sigcontext *sc; +  stack_t stk; +  struct rbs_flush_values c; + +  /* put RSE into enforced-lazy mode and return current bsp/rsc/rnat: */ +  c = __ia64_flush_rbs (); + +  jb_sp  = ((unsigned long *)  buf)[JB_SP]; +  jb_bsp = ((unsigned long **) buf)[JB_BSP]; + +  INTERNAL_SYSCALL_DECL (err); +  (void) INTERNAL_SYSCALL (sigaltstack, err, 2, NULL, &stk); + +  ss_sp = (unsigned long) stk.ss_sp; +  jb_rnat_addr = ia64_rse_rnat_addr (jb_bsp); + +  if ((stk.ss_flags & SS_ONSTACK) == 0 || jb_sp - ss_sp < stk.ss_size) +    /* Normal non-stack-crossing longjmp; if the RNaT slot for the bsp +       saved in the jump-buffer is the same as the one for the current +       BSP, use the current AR.RNAT value, otherwise, load it from the +       jump-buffer's RNaT-slot.  */ +    load_rnat = (ia64_rse_rnat_addr ((unsigned long *) c.bsp) != jb_rnat_addr); +  else +    { +      /* If we are on the alternate signal-stack and the jump-buffer +	 lies outside the signal-stack, we may need to copy back the +	 dirty partition which was torn off and saved on the +	 signal-stack when the signal was delivered. + +	 Caveat: we assume that the top of the alternate signal-stack +		 stores the sigcontext structure of the signal that +		 caused the switch to the signal-stack.	 This should +		 be a fairly safe assumption but the kernel _could_ +		 do things differently.. */ +      sc = ((struct sigcontext *) ((ss_sp + stk.ss_size) & -16) - 1); + +      /* As a sanity-check, verify that the register-backing-store base +	 of the alternate signal-stack is where we expect it.  */ +      rbs_base = (unsigned long *) +	((ss_sp + sizeof (long) - 1) & -sizeof (long)); + +      assert ((unsigned long) rbs_base == sc->sc_rbs_base); + +      ndirty = ia64_rse_num_regs (rbs_base, rbs_base + (sc->sc_loadrs >> 19)); +      bsp = (unsigned long *) sc->sc_ar_bsp; +      bspstore = ia64_rse_skip_regs (bsp, -ndirty); + +      if (bspstore < jb_bsp) +	/* AR.BSPSTORE at the time of the signal was below the value +	   of AR.BSP saved in the jump-buffer => copy the missing +	   portion from the torn off dirty partition which got saved +	   on the alternate signal-stack.  */ +	copy_rbs (bspstore, jb_bsp, sc->sc_ar_rnat, +		  rbs_base, (unsigned long *) c.bsp, c.rnat); + +      load_rnat = 1; +    } +  if (load_rnat) +    rnat = *jb_rnat_addr; +  else +    rnat = c.rnat; +  __ia64_longjmp (buf, val, rnat, c.rsc); +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h new file mode 100644 index 000000000..f837250b9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h @@ -0,0 +1,89 @@ +/* Minimum guaranteed maximum values for system limits.  Linux/IA-64 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	196608 + +/* 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/ia64/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h new file mode 100644 index 000000000..afb8800ac --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h @@ -0,0 +1,160 @@ +/* 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 + +#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 not +   exposed on purpose.  */ +typedef unsigned long int pthread_t; + + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_ATTR_T]; +  long int __align; +} pthread_attr_t; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    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; +  } __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]; +  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 +{ +  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/ia64/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h new file mode 100644 index 000000000..2329e9866 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h @@ -0,0 +1,39 @@ +/* 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.  */ + +#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/ia64/clone2.S b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/clone2.S new file mode 100644 index 000000000..8664056f2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/clone2.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/linux/ia64/clone2.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/createthread.c new file mode 100644 index 000000000..8ac06e810 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/createthread.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2003 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; 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) + +#define ARCH_CLONE __clone2 + +/* Get the real implementation.	 */ +#include <nptl/sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h new file mode 100644 index 000000000..af835c44b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h @@ -0,0 +1,68 @@ +/* System-specific settings for dynamic linker code.  IA-64 version. +   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 _DL_SYSDEP_H +#define _DL_SYSDEP_H	1 + +/* This macro must be defined to either 0 or 1. + +   If 1, then an errno global variable hidden in ld.so will work right with +   all the errno-using libc code compiled for ld.so, and there is never a +   need to share the errno location with libc.  This is appropriate only if +   all the libc functions that ld.so uses are called without PLT and always +   get the versions linked into ld.so rather than the libc ones.  */ + +#ifdef IS_IN_rtld +# define RTLD_PRIVATE_ERRNO 1 +#else +# define RTLD_PRIVATE_ERRNO 0 +#endif + +/* Traditionally system calls have been made using break 0x100000.  A +   second method was introduced which, if possible, will use the EPC +   instruction.  To signal the presence and where to find the code the +   kernel passes an AT_SYSINFO_EHDR pointer in the auxiliary vector to +   the application.  */ +#define NEED_DL_SYSINFO	1 +#define USE_DL_SYSINFO	1 + +#if defined NEED_DL_SYSINFO && !defined __ASSEMBLER__ +/* Don't declare this as a function---we want it's entry-point, not +   it's function descriptor... */ +extern int _dl_sysinfo_break attribute_hidden; +# define DL_SYSINFO_DEFAULT ((uintptr_t) &_dl_sysinfo_break) +# define DL_SYSINFO_IMPLEMENTATION		\ +  asm (".text\n\t"				\ +       ".hidden _dl_sysinfo_break\n\t"		\ +       ".proc _dl_sysinfo_break\n\t"		\ +       "_dl_sysinfo_break:\n\t"			\ +       ".prologue\n\t"				\ +       ".altrp b6\n\t"				\ +       ".body\n\t"				\ +       "break 0x100000;\n\t"			\ +       "br.ret.sptk.many b6;\n\t"		\ +       ".endp _dl_sysinfo_break"		\ +       ".previous"); +#endif + +/* _dl_argv cannot be attribute_relro, because _dl_start_user +   might write into it after _dl_start returns.  */ +#define DL_ARGV_NOT_RELRO 1 + +#endif	/* dl-sysdep.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/fork.c new file mode 100644 index 000000000..1502310f1 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/fork.c @@ -0,0 +1,31 @@ +/* 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_SYSCALL (clone2, 6,						      \ +		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,	      \ +		  NULL, 0, NULL, &THREAD_SELF->tid, NULL) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h new file mode 100644 index 000000000..c6ef5f7fb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ +  ({ uintptr_t _cfa = (uintptr_t) _Unwind_GetCFA (_context) - (_adj);	\ +     (_cfa < (uintptr_t)(((long *)(_jmpbuf))[0]) - (_adj)		\ +      || (_cfa == (uintptr_t)(((long *)(_jmpbuf))[0]) - (_adj)		\ +	  && (uintptr_t) _Unwind_GetBSP (_context) - (_adj)		\ +	     >= (uintptr_t)(((long *)(_jmpbuf))[17]) - (_adj)));	\ +  }) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ +  ((uintptr_t)(_address) - (_adj) < (uintptr_t)(((long *)_jmpbuf)[0]) - (_adj)) + +/* We use a longjmp() which can cross from the alternate signal-stack +   to the normal stack.  */ +extern void __libc_unwind_longjmp (sigjmp_buf env, int val) +          __attribute__ ((noreturn)); +hidden_proto (__libc_unwind_longjmp) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h new file mode 100644 index 000000000..e13358ffe --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h @@ -0,0 +1,204 @@ +/* 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 _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H	1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <ia64intrin.h> +#include <atomic.h> + +#define __NR_futex		1230 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 +#define FUTEX_CMP_REQUEUE	4 + +/* Delay in spinlock loop.  */ +#define BUSY_WAIT_NOP          asm ("hint @pause") + +/* Initializer for compatibility lock.	*/ +#define LLL_MUTEX_LOCK_INITIALIZER (0) + +#define lll_futex_wait(futex, val) lll_futex_timed_wait (futex, val, 0) + +#define lll_futex_timed_wait(ftx, val, timespec)			\ +({									\ +   DO_INLINE_SYSCALL(futex, 4, (long) (ftx), FUTEX_WAIT, (int) (val),	\ +		     (long) (timespec));				\ +   _r10 == -1 ? -_retval : _retval;					\ +}) + +#define lll_futex_wake(ftx, nr)						\ +({									\ +   DO_INLINE_SYSCALL(futex, 3, (long) (ftx), FUTEX_WAKE, (int) (nr));	\ +   _r10 == -1 ? -_retval : _retval;					\ +}) + +/* Returns non-zero if error happened, zero if success.  */ +#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex, val)		     \ +({									     \ +   DO_INLINE_SYSCALL(futex, 6, (long) (ftx), FUTEX_CMP_REQUEUE,		     \ +		     (int) (nr_wake), (int) (nr_move), (long) (mutex),	     \ +		     (int) val);					     \ +   _r10 == -1;								     \ +}) + + +#define __lll_mutex_trylock(futex) \ +  (atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0) +#define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex)) + + +#define __lll_mutex_cond_trylock(futex) \ +  (atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0) +#define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex)) + + +extern void __lll_lock_wait (int *futex) attribute_hidden; + + +#define __lll_mutex_lock(futex)						\ +  ((void) ({								\ +    int *__futex = (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)) + + +#define __lll_mutex_cond_lock(futex)					\ +  ((void) ({								\ +    int *__futex = (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; + + +#define __lll_mutex_timedlock(futex, abstime)				\ +  ({									\ +     int *__futex = (futex);						\ +     int __val = 0;							\ +									\ +     if (atomic_compare_and_exchange_bool_acq (__futex, 1, 0) != 0)	\ +       __val = __lll_timedlock_wait (__futex, abstime);			\ +     __val;								\ +  }) +#define lll_mutex_timedlock(futex, abstime) \ +  __lll_mutex_timedlock (&(futex), abstime) + + +#define __lll_mutex_unlock(futex)			\ +  ((void) ({						\ +    int *__futex = (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)) + + +#define __lll_mutex_unlock_force(futex)		\ +  ((void) ({					\ +    int *__futex = (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) + + +/* We have a separate internal lock implementation which is not tied +   to binary compatibility.  We can use the lll_mutex_*.  */ + +/* Type for lock object.  */ +typedef int lll_lock_t; + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + +/* Initializers for lock.  */ +#define LLL_LOCK_INITIALIZER		(0) +#define LLL_LOCK_INITIALIZER_LOCKED	(1) + +#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)	lll_mutex_islocked (futex) + + +/* 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;						\ +  }) + + +/* 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/ia64/pt-initfini.c b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c new file mode 100644 index 000000000..b7d4e5794 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c @@ -0,0 +1,143 @@ +/* Special .init and .fini section support for ia64. NPTL version. +   Copyright (C) 2000, 2001, 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. + +   In addition to the permissions in the GNU Lesser 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 Lesser 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 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, 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. */ + +#include <stddef.h> + +#ifdef HAVE_INITFINI_ARRAY + +__asm__ ("\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ +	.xdata8 \".init_array\",@fptr(__pthread_initialize_minimal_internal)\n\ +/*@_init_PROLOG_ENDS*/\n\ +"); + +#else + +__asm__ ("\n\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ +	.section .init\n\ +	.align 16\n\ +	.global _init#\n\ +	.proc _init#\n\ +_init:\n\ +	.prologue\n\ +	.save ar.pfs, r34\n\ +	alloc r34 = ar.pfs, 0, 3, 0, 0\n\ +	.vframe r32\n\ +	mov r32 = r12\n\ +	.save rp, r33\n\ +	mov r33 = b0\n\ +	.body\n\ +	adds r12 = -16, r12\n\ +	;;\n\ +	st8 [r12] = gp, -16\n\ +	br.call.sptk.many b0 = __pthread_initialize_minimal_internal# ;;\n\ +	;;\n\ +	adds r12 = 16, r12\n\ +	;;\n\ +	ld8 gp = [r12]\n\ +	;;\n\ +	.endp _init#\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ +	.section .init\n\ +	.proc _init#\n\ +	.prologue\n\ +	.save ar.pfs, r34\n\ +	.vframe r32\n\ +	.save rp, r33\n\ +	.body\n\ +	mov r12 = r32\n\ +	mov ar.pfs = r34\n\ +	mov b0 = r33\n\ +	br.ret.sptk.many b0\n\ +	.endp _init#\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ +	.section .fini\n\ +	.align 16\n\ +	.global _fini#\n\ +	.proc _fini#\n\ +_fini:\n\ +	.prologue\n\ +	.save ar.pfs, r34\n\ +	alloc r34 = ar.pfs, 0, 3, 0, 0\n\ +	.vframe r32\n\ +	mov r32 = r12\n\ +	.save rp, r33\n\ +	mov r33 = b0\n\ +	.body\n\ +	adds r12 = -16, r12\n\ +	;;\n\ +	.endp _fini#\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ +	.section .fini\n\ +	.proc _fini#\n\ +	.prologue\n\ +	.save ar.pfs, r34\n\ +	.vframe r32\n\ +	.save rp, r33\n\ +	.body\n\ +	mov r12 = r32\n\ +	mov ar.pfs = r34\n\ +	mov b0 = r33\n\ +	br.ret.sptk.many b0\n\ +	.endp _fini#\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ +	.weak	__gmon_start__#\n\ +"); + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/pt-vfork.S new file mode 100644 index 000000000..a28528003 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/pt-vfork.S @@ -0,0 +1,60 @@ +/* Copyright (C) 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 <sysdep.h> +#define _SIGNAL_H +#include <bits/signum.h> +#include <tcb-offsets.h> + +/* The following are defined in linux/sched.h, which unfortunately	*/ +/* is not safe for inclusion in an assembly file.			*/ +#define CLONE_VM        0x00000100      /* set if VM shared between processes */ +#define CLONE_VFORK     0x00004000      /* set if the parent wants the child to wake it up on mm_release */ + +/* pid_t vfork(void); */ +/* Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)	*/ + +ENTRY(__vfork) +	.prologue	// work around a GAS bug which triggers if +	.body		// first .prologue is not at the beginning of proc. +	alloc r2=ar.pfs,0,0,2,0 +	adds r14=PID,r13 +	;; +	ld4 r16=[r14] +	;; +	sub r15=0,r16 +	mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD +	mov out1=0		/* Standard sp value.			*/ +	;; +	st4 [r14]=r15 +	DO_CALL (SYS_ify (clone)) +	cmp.eq p0,p7=0,r8 +	adds r14=PID,r13 +	;; +(p7)	ld4 r16=[r14] +	cmp.eq p6,p0=-1,r10 +	;; +(p7)	sub r15=0,r16 +	;; +(p7)	st4 [r14]=r15 +(p6)	br.cond.spnt.few __syscall_error +	ret +PSEUDO_END(__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c new file mode 100644 index 000000000..3b07cc127 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/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/ia64/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h new file mode 100644 index 000000000..63aaa96eb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h @@ -0,0 +1,222 @@ +/* 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 <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 + +# if USE___THREAD +#  ifndef NOT_IN_libc +#   define SYSDEP_CANCEL_ERRNO __libc_errno +#  else +#   define SYSDEP_CANCEL_ERRNO errno +#  endif +#  define SYSDEP_CANCEL_ERROR(args)					      \ +.section .gnu.linkonce.t.__syscall_error_##args, "ax";			      \ +     .align 32;								      \ +     .proc __syscall_error_##args;					      \ +     .global __syscall_error_##args;					      \ +     .hidden __syscall_error_##args;					      \ +     .size __syscall_error_##args, 64;					      \ +__syscall_error_##args:							      \ +     .prologue;								      \ +     .regstk args, 5, args, 0;						      \ +     .save ar.pfs, loc0;						      \ +     .save rp, loc1;							      \ +     .body;								      \ +     addl loc4 = @ltoff(@tprel(SYSDEP_CANCEL_ERRNO)), gp;;		      \ +     ld8 loc4 = [loc4];							      \ +     mov rp = loc1;;							      \ +     mov r8 = -1;							      \ +     add loc4 = loc4, r13;;						      \ +     st4 [loc4] = loc3;							      \ +     mov ar.pfs = loc0 +# else +#  define SYSDEP_CANCEL_ERROR(args)					      \ +.section .gnu.linkonce.t.__syscall_error_##args, "ax";			      \ +     .align 32;								      \ +     .proc __syscall_error_##args;					      \ +     .global __syscall_error_##args;					      \ +     .hidden __syscall_error_##args;					      \ +     .size __syscall_error_##args, 64;					      \ +__syscall_error_##args:							      \ +     .prologue;								      \ +     .regstk args, 5, args, 0;						      \ +     .save ar.pfs, loc0;						      \ +     .save rp, loc1;							      \ +     .body;								      \ +     mov loc4 = r1;;							      \ +     br.call.sptk.many b0 = __errno_location;;				      \ +     st4 [r8] = loc3;							      \ +     mov r1 = loc4;							      \ +     mov rp = loc1;							      \ +     mov r8 = -1;							      \ +     mov ar.pfs = loc0 +# endif + +# ifndef USE_DL_SYSINFO + +#  define PSEUDO(name, syscall_name, args)				      \ +.text;									      \ +ENTRY (name)								      \ +     adds r14 = MULTIPLE_THREADS_OFFSET, r13;;				      \ +     ld4 r14 = [r14];							      \ +     mov r15 = SYS_ify(syscall_name);;					      \ +     cmp4.ne p6, p7 = 0, r14;						      \ +(p6) br.cond.spnt .Lpseudo_cancel;;					      \ +     break __BREAK_SYSCALL;;						      \ +     cmp.eq p6,p0=-1,r10;						      \ +(p6) br.cond.spnt.few __syscall_error;					      \ +     ret;;								      \ +     .endp name;							      \ +     .proc __GC_##name;							      \ +     .globl __GC_##name;						      \ +     .hidden __GC_##name;						      \ +__GC_##name:								      \ +.Lpseudo_cancel:							      \ +     .prologue;								      \ +     .regstk args, 5, args, 0;						      \ +     .save ar.pfs, loc0;						      \ +     alloc loc0 = ar.pfs, args, 5, args, 0;				      \ +     .save rp, loc1;							      \ +     mov loc1 = rp;;							      \ +     .body;								      \ +     CENABLE;;								      \ +     mov loc2 = r8;							      \ +     COPY_ARGS_##args							      \ +     mov r15 = SYS_ify(syscall_name);					      \ +     break __BREAK_SYSCALL;;						      \ +     mov loc3 = r8;							      \ +     mov loc4 = r10;							      \ +     mov out0 = loc2;							      \ +     CDISABLE;;								      \ +     cmp.eq p6,p0=-1,loc4;						      \ +(p6) br.cond.spnt.few __syscall_error_##args;				      \ +     mov r8 = loc3;							      \ +     mov rp = loc1;							      \ +     mov ar.pfs = loc0;							      \ +.Lpseudo_end:								      \ +     ret;								      \ +     .endp __GC_##name;							      \ +     SYSDEP_CANCEL_ERROR(args) + +# else /* USE_DL_SYSINFO */ + +#  define PSEUDO(name, syscall_name, args)				      \ +.text;									      \ +ENTRY (name)								      \ +     .prologue;								      \ +     adds r2 = SYSINFO_OFFSET, r13;					      \ +     adds r14 = MULTIPLE_THREADS_OFFSET, r13;				      \ +     .save ar.pfs, r11;							      \ +     mov r11 = ar.pfs;;							      \ +     .body;								      \ +     ld4 r14 = [r14];							      \ +     ld8 r2 = [r2];							      \ +     mov r15 = SYS_ify(syscall_name);;					      \ +     cmp4.ne p6, p7 = 0, r14;						      \ +     mov b7 = r2;							      \ +(p6) br.cond.spnt .Lpseudo_cancel;					      \ +     br.call.sptk.many b6 = b7;;					      \ +     mov ar.pfs = r11;							      \ +     cmp.eq p6,p0 = -1, r10;						      \ +(p6) br.cond.spnt.few __syscall_error;					      \ +     ret;;								      \ +     .endp name;							      \ +     .proc __GC_##name;							      \ +     .globl __GC_##name;						      \ +     .hidden __GC_##name;						      \ +__GC_##name:								      \ +.Lpseudo_cancel:							      \ +     .prologue;								      \ +     .regstk args, 5, args, 0;						      \ +     .save ar.pfs, loc0;						      \ +     alloc loc0 = ar.pfs, args, 5, args, 0;				      \ +     adds loc4 = SYSINFO_OFFSET, r13;					      \ +     .save rp, loc1;							      \ +     mov loc1 = rp;;							      \ +     .body;								      \ +     ld8 loc4 = [loc4];							      \ +     CENABLE;;								      \ +     mov loc2 = r8;							      \ +     mov b7 = loc4;							      \ +     COPY_ARGS_##args							      \ +     mov r15 = SYS_ify(syscall_name);					      \ +     br.call.sptk.many b6 = b7;;					      \ +     mov loc3 = r8;							      \ +     mov loc4 = r10;							      \ +     mov out0 = loc2;							      \ +     CDISABLE;;								      \ +     cmp.eq p6,p0=-1,loc4;						      \ +(p6) br.cond.spnt.few __syscall_error_##args;				      \ +     mov r8 = loc3;							      \ +     mov rp = loc1;							      \ +     mov ar.pfs = loc0;							      \ +.Lpseudo_end:								      \ +     ret;								      \ +     .endp __GC_##name;							      \ +     SYSDEP_CANCEL_ERROR(args) + +# endif /* USE_DL_SYSINFO */ + +# undef PSEUDO_END +# define PSEUDO_END(name) .endp + +# ifdef IS_IN_libpthread +#  define CENABLE	br.call.sptk.many b0 = __pthread_enable_asynccancel +#  define CDISABLE	br.call.sptk.many b0 = __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +#  define CENABLE	br.call.sptk.many b0 = __libc_enable_asynccancel +#  define CDISABLE	br.call.sptk.many b0 = __libc_disable_asynccancel +# elif defined IS_IN_librt +#  define CENABLE	br.call.sptk.many b0 = __librt_enable_asynccancel +#  define CDISABLE	br.call.sptk.many b0 = __librt_disable_asynccancel +# else +#  error Unsupported library +# endif + +# define COPY_ARGS_0	/* Nothing */ +# define COPY_ARGS_1	COPY_ARGS_0 mov out0 = in0; +# define COPY_ARGS_2	COPY_ARGS_1 mov out1 = in1; +# define COPY_ARGS_3	COPY_ARGS_2 mov out2 = in2; +# define COPY_ARGS_4	COPY_ARGS_3 mov out3 = in3; +# define COPY_ARGS_5	COPY_ARGS_4 mov out4 = in4; +# define COPY_ARGS_6	COPY_ARGS_5 mov out5 = in5; +# define COPY_ARGS_7	COPY_ARGS_6 mov out6 = in6; + +# ifndef __ASSEMBLER__ +#  define SINGLE_THREAD_P \ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF, header.multiple_threads) == 0, 1) +# else +#  define SINGLE_THREAD_P \ +  adds r14 = MULTIPLE_THREADS_OFFSET, r13 ;; ld4 r14 = [r14] ;; cmp4.ne p6, p7 = 0, r14 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_create.c new file mode 100644 index 000000000..172223af3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_create.c @@ -0,0 +1 @@ +#include "../x86_64/timer_create.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_delete.c new file mode 100644 index 000000000..537516e0a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_delete.c @@ -0,0 +1 @@ +#include "../x86_64/timer_delete.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_getoverr.c new file mode 100644 index 000000000..3f21a73c9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_getoverr.c @@ -0,0 +1 @@ +#include "../x86_64/timer_getoverr.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_gettime.c new file mode 100644 index 000000000..a50143adc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_gettime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_gettime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_settime.c new file mode 100644 index 000000000..37baeffac --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/timer_settime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_settime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c new file mode 100644 index 000000000..fb44b426b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2003 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 <unwind.h> +#include <pthreadP.h> + +static _Unwind_Word (*libgcc_s_getbsp) (struct _Unwind_Context *); + +#define ARCH_CANCEL_INIT(handle) \ +  ((libgcc_s_getbsp = __libc_dlsym (handle, "_Unwind_GetBSP")) == NULL) + +#include <sysdeps/pthread/unwind-forcedunwind.c> + +_Unwind_Word +_Unwind_GetBSP (struct _Unwind_Context *context) +{ +  if (__builtin_expect (libgcc_s_getbsp == NULL, 0)) +    pthread_cancel_init (); +  return libgcc_s_getbsp (context); +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/unwind_longjmp.c b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/unwind_longjmp.c new file mode 100644 index 000000000..7976ff8f1 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/unwind_longjmp.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1991,92,94,95,97,98,2000,02,04 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 <stddef.h> +#include <setjmp.h> +#include <signal.h> +#include <pthreadP.h> +#include <jmpbuf-unwind.h> + +extern void __sigstack_longjmp (__jmp_buf, int) +     __attribute__ ((noreturn)); + +/* Like __libc_siglongjmp(), but safe for crossing from alternate +   signal stack to normal stack.  Needed by NPTL.  */ +void +__libc_unwind_longjmp (sigjmp_buf env, int val) +{ +  /* Perform any cleanups needed by the frames being unwound.  */ +  __pthread_cleanup_upto (env->__jmpbuf, CURRENT_STACK_FRAME); + +  if (env[0].__mask_was_saved) +    /* Restore the saved signal mask.  */ +    (void) __sigprocmask (SIG_SETMASK, &env[0].__saved_mask, +			  (sigset_t *) NULL); + +  /* Call the machine-dependent function to restore machine state.  */ +  __sigstack_longjmp (env[0].__jmpbuf, val ?: 1); +} +hidden_def (__libc_unwind_longjmp) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/vfork.S new file mode 100644 index 000000000..3bd721f14 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/ia64/vfork.S @@ -0,0 +1,69 @@ +/* Copyright (C) 2000, 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 <sysdep.h> +#define _SIGNAL_H +#include <bits/signum.h> +#include <tcb-offsets.h> + +/* The following are defined in linux/sched.h, which unfortunately	*/ +/* is not safe for inclusion in an assembly file.			*/ +#define CLONE_VM        0x00000100      /* set if VM shared between processes */ +#define CLONE_VFORK     0x00004000      /* set if the parent wants the child to wake it up on mm_release */ + +/* pid_t vfork(void); */ +/* Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)	*/ + +ENTRY(__vfork) +	.prologue	// work around a GAS bug which triggers if +	.body		// first .prologue is not at the beginning of proc. +	alloc r2=ar.pfs,0,0,2,0 +	adds r14=PID,r13 +	;; +	ld4 r16=[r14] +	;; +	sub r15=0,r16 +	cmp.eq p6,p0=0,r16 +	;; +(p6)	movl r15=0x80000000 +	mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD +	mov out1=0		/* Standard sp value.			*/ +	;; +	st4 [r14]=r15 +	DO_CALL (SYS_ify (clone)) +	cmp.eq p6,p0=0,r8 +	adds r14=PID,r13 +(p6)	br.cond.dptk 1f +	;; +	ld4 r15=[r14] +	;; +	extr.u r16=r15,0,31 +	;; +	cmp.eq p0,p6=0,r16 +	;; +(p6)	sub r16=0,r15 +	;; +	st4 [r14]=r16 +1: +	cmp.eq p6,p0=-1,r10 +(p6)	br.cond.spnt.few __syscall_error +	ret +PSEUDO_END(__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) 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..1dec19e57 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h @@ -0,0 +1,152 @@ +/* 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> + + +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..3ff4cda3f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h @@ -0,0 +1,60 @@ +/* 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 <pthread.h> +#include <setjmp.h> +#include <signal.h> +#include <sys/types.h> + + +/* Nonzero if the system calls are not available.  */ +extern int __no_posix_timers attribute_hidden; + +/* Callback to start helper thread.  */ +extern void __start_helper_thread (void) attribute_hidden; + +/* Control variable for helper thread creation.  */ +extern pthread_once_t __helper_once attribute_hidden; + +/* TID of the helper thread.  */ +extern pid_t __helper_tid attribute_hidden; + + +/* Type of timers in the kernel.  */ +typedef int kernel_timer_t; + + +/* Internal representation of timer.  */ +struct timer +{ +  /* Notification mechanism.  */ +  int sigev_notify; + +  /* Timer ID returned by the kernel.  */ +  kernel_timer_t ktimerid; + +  /* All new elements must be added after ktimerid.  And if the thrfunc +     element is not the third element anymore the memory allocation in +     timer_create needs to be changed.  */ + +  /* Parameters for the thread to be started for SIGEV_THREAD.  */ +  void (*thrfunc) (sigval_t); +  sigval_t sival; +  pthread_attr_t attr; +}; 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..3d1c02181 --- /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 <dl-sysdep.h> +#include <tls.h> +#include <string.h> +#include <pthreadP.h> +#include <bits/libc-lock.h> + + +#ifdef TLS_MULTIPLE_THREADS_IN_TCB +void +#else +extern int __libc_multiple_threads attribute_hidden; + +int * +#endif +__libc_pthread_init (ptr, reclaim, functions) +     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..932e27300 --- /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/mips/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h new file mode 100644 index 000000000..e14a48750 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h @@ -0,0 +1,193 @@ +/* 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 + +#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; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is deliberately not exposed.  */ +typedef union +{ +  struct +  { +    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 +    unsigned int __nusers; +#endif +    int __spins; +  } __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/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/clone.S new file mode 100644 index 000000000..80c265bf6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/linux/mips/clone.S> 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..5b2234f47 --- /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 <nptl/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/not-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/not-cancel.h new file mode 100644 index 000000000..9418417b4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/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/mips/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S new file mode 100644 index 000000000..fe2b81bc1 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S @@ -0,0 +1,37 @@ +/* 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 <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 <../sysdeps/unix/sysv/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..02508e215 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h @@ -0,0 +1,170 @@ +/* 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 <sysdeps/generic/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 __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/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/vfork.S new file mode 100644 index 000000000..874a2e2bf --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/vfork.S @@ -0,0 +1,42 @@ +/* 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 <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.  */		\ +	bnez	a2, 1f;			/* If it was zero... */		\ +	lui	a2, 0x8000;		/* use 0x80000000 instead.  */	\ +1:	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.  */		\ +	lui	a0, 0x8000;		/* Load 0x80000000... */	\ +	bne	a2, a0, 2f;		/* ... compare against it... */	\ +	li	a2, 0;			/* ... use 0 instead.  */	\ +2:	sw	a2, PID_OFFSET(v1);	/* Restore the PID.  */		\ +1: + +#include <../sysdeps/unix/sysv/linux/mips/vfork.S> 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..e9c2b6e79 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mq_notify.c @@ -0,0 +1,287 @@ +/* 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; +} + +#else +# include <sysdeps/generic/mq_notify.c> +#endif 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..90c069569 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h @@ -0,0 +1,196 @@ +/* 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; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is deliberately not exposed.  */ +typedef union +{ +  struct +  { +    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 +    unsigned int __nusers; +#endif +    int __spins; +  } __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..002af8590 --- /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 <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..393c171ee --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h @@ -0,0 +1,115 @@ +/* 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);							\ +    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);								\ +    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 + +# 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) +# 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..4b035a61f --- /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 <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) +libc_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..82864c91f --- /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 <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..793762270 --- /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 <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) +libc_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..3c795e37e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c @@ -0,0 +1,68 @@ +/* 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" +#include  <shlib-compat.h> +#if defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3_4) + +/* These functions are not declared anywhere since they shouldn't be +   used at another place but here.  */ +extern void __novmx__libc_siglongjmp (sigjmp_buf env, int val) +     __attribute__ ((noreturn)); +extern void __novmx__libc_longjmp (sigjmp_buf env, int val) +     __attribute__ ((noreturn)); + + +void __novmx_siglongjmp (sigjmp_buf env, int val) +{ +  __novmx__libc_siglongjmp (env, val); +} + +void __novmx_longjmp (jmp_buf env, int val) +{ +  __novmx__libc_longjmp (env, val); +} + +# if __WORDSIZE == 64 +symbol_version (__novmx_longjmp,longjmp,GLIBC_2.3); +symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.3); +# else +symbol_version (__novmx_longjmp,longjmp,GLIBC_2.0); +symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.0); +# endif +#endif /* defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4))  */  + +void +__vmx_longjmp (jmp_buf env, int val) +{ +  __libc_longjmp (env, val); +} + +void +__vmx_siglongjmp (jmp_buf env, int val) +{ +  __libc_siglongjmp (env, val); +} + +versioned_symbol (libc, __vmx_longjmp, longjmp, GLIBC_2_3_4); +versioned_symbol (libc, __vmx_siglongjmp, siglongjmp, GLIBC_2_3_4); + 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..91b995518 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c @@ -0,0 +1,48 @@ +/* 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> + +#include <shlib-compat.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; +} +versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1); +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_post, __old_sem_post) +compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0); +#endif 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..a1e228ee2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c @@ -0,0 +1,28 @@ +/* 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> + + +pid_t +__fork (void) +{ +  return __libc_fork (); +} +strong_alias (__fork, fork) 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..9161e29e2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-raise.c @@ -0,0 +1,52 @@ +/* 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 <kernel-features.h> + + +int +raise (sig) +     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 +} 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..1c92f314d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c @@ -0,0 +1,69 @@ +/* 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> +#include <shlib-compat.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.  */ +      for (size_t 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; +} +versioned_symbol (libpthread, __pthread_attr_getaffinity_new, +		  pthread_attr_getaffinity_np, GLIBC_2_3_4); + + +#if SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_3_4) +int +__pthread_attr_getaffinity_old (const pthread_attr_t *attr, cpu_set_t *cpuset) +{ +  /* The old interface by default assumed a 1024 processor bitmap.  */ +  return __pthread_attr_getaffinity_new (attr, 128, cpuset); +} +compat_symbol (libpthread, __pthread_attr_getaffinity_old, +	       pthread_attr_getaffinity_np, GLIBC_2_3_3); +#endif 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..ca84f1c9b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c @@ -0,0 +1,95 @@ +/* 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> +#include <shlib-compat.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.  */ +      for (size_t 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; +} +versioned_symbol (libpthread, __pthread_attr_setaffinity_new, +		  pthread_attr_setaffinity_np, GLIBC_2_3_4); + + +#if SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_3_4) +int +__pthread_attr_setaffinity_old (pthread_attr_t *attr, cpu_set_t *cpuset) +{ +  /* The old interface by default assumed a 1024 processor bitmap.  */ +  return __pthread_attr_setaffinity_new (attr, 128, cpuset); +} +compat_symbol (libpthread, __pthread_attr_setaffinity_old, +	       pthread_attr_setaffinity_np, GLIBC_2_3_3); +#endif 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..c382ed53a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c @@ -0,0 +1,60 @@ +/* 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> +#include <shlib-compat.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) +versioned_symbol (libpthread, __pthread_getaffinity_new, +		  pthread_getaffinity_np, GLIBC_2_3_4); + + +#if SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_3_4) +int +__pthread_getaffinity_old (pthread_t th, cpu_set_t *cpuset) +{ +  /* The old interface by default assumed a 1024 processor bitmap.  */ +  return __pthread_getaffinity_new (th, 128, cpuset); +} +compat_symbol (libpthread, __pthread_getaffinity_old, pthread_getaffinity_np, +	       GLIBC_2_3_3); +#endif 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..82c2446d5 --- /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 <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 (threadid, clockid) +     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..9115d6f40 --- /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 <kernel-features.h> + + +int +__pthread_kill (threadid, signo) +     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..990db8741 --- /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 <nptl/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..5b24c694a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c @@ -0,0 +1,99 @@ +/* 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> +#include <shlib-compat.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.  */ +  for (size_t 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); +} +versioned_symbol (libpthread, __pthread_setaffinity_new, +		  pthread_setaffinity_np, GLIBC_2_3_4); + + +#if SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_3_4) +int +__pthread_setaffinity_old (pthread_t th, cpu_set_t *cpuset) +{ +  /* The old interface by default assumed a 1024 processor bitmap.  */ +  return __pthread_setaffinity_new (th, 128, cpuset); +} +compat_symbol (libpthread, __pthread_setaffinity_old, pthread_setaffinity_np, +	       GLIBC_2_3_3); +#endif 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..28d03c383 --- /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 <nptl/pthreadP.h> +#include <kernel-features.h> + + +int +raise (sig) +     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_def (raise) +weak_alias (raise, gsignal) 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..9707e4663 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/register-atfork.c @@ -0,0 +1,135 @@ +/* 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 (prepare, parent, child, dso_handle) +     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; +} +libc_hidden_def (__register_atfork) + + +libc_freeres_fn (free_mem) +{ +  /* Get the lock to not conflict with running forks.  */ +  lll_lock (__fork_lock); + +  /* No more fork handlers.  */ +  __fork_handlers = NULL; + +  /* Free eventually alloated memory blocks for the object pool.  */ +  struct fork_handler_pool *runp = fork_handler_pool.next; + +  memset (&fork_handler_pool, '\0', sizeof (fork_handler_pool)); + +  /* Release the lock.  */ +  lll_unlock (__fork_lock); + +  /* We can free the memory after releasing the lock.  */ +  while (runp != NULL) +    { +      struct fork_handler_pool *oldp = runp; +      runp = runp->next; +      free (oldp); +    } +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h new file mode 100644 index 000000000..6b3618cd5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h @@ -0,0 +1,195 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 not +   exposed on purpose.  */ +typedef unsigned long int pthread_t; + + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_ATTR_T]; +  long int __align; +} pthread_attr_t; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    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 +    unsigned int __nusers; +#endif +    int __spins; +  } __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 __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/s390/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/bits/semaphore.h new file mode 100644 index 000000000..ead266304 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/bits/semaphore.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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/s390/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/fork.c new file mode 100644 index 000000000..06635ab81 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/fork.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + + +#define ARCH_FORK() \ +  INLINE_SYSCALL (clone, 5,						      \ +		  0, CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,     \ +		  NULL, &THREAD_SELF->tid, NULL) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c new file mode 100644 index 000000000..36886f58a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c @@ -0,0 +1,41 @@ +/* Clean up stack frames unwound by longjmp.  Linux/s390 version. +   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 <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 + +  unsigned char local_var; + +  if (fptr != NULL) +    fptr (env->__jmpbuf, &local_var); +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h new file mode 100644 index 000000000..f4ed98a50 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h @@ -0,0 +1,282 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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> + +#define SYS_futex		238 +#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(futex, val) \ +  ({									      \ +     register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \ +     register unsigned long int __r3 asm ("3") = FUTEX_WAIT;		      \ +     register unsigned long int __r4 asm ("4") = (unsigned long int) (val);   \ +     register unsigned long int __r5 asm ("5") = 0ul;			      \ +     register unsigned long __result asm ("2");				      \ +									      \ +    __asm __volatile ("svc %b1"						      \ +		      : "=d" (__result)					      \ +		      : "i" (SYS_futex), "0" (__r2), "d" (__r3),	      \ +			"d" (__r4), "d" (__r5)				      \ +		      : "cc", "memory" );				      \ +    __result;								      \ +  }) + + +#define lll_futex_timed_wait(futex, val, timespec) \ +  ({									      \ +    register unsigned long int __r2 asm ("2") = (unsigned long int) (futex);  \ +    register unsigned long int __r3 asm ("3") = FUTEX_WAIT;		      \ +    register unsigned long int __r4 asm ("4") = (unsigned long int) (val);    \ +    register unsigned long int __r5 asm ("5") = (unsigned long int)(timespec);\ +    register unsigned long int __result asm ("2");			      \ +									      \ +    __asm __volatile ("svc %b1"						      \ +		      : "=d" (__result)					      \ +		      : "i" (SYS_futex), "0" (__r2), "d" (__r3),	      \ +			"d" (__r4), "d" (__r5)				      \ +		      : "cc", "memory" );				      \ +    __result;								      \ +  }) + + +#define lll_futex_wake(futex, nr) \ +  ({									      \ +    register unsigned long int __r2 asm ("2") = (unsigned long int) (futex);  \ +    register unsigned long int __r3 asm ("3") = FUTEX_WAKE;		      \ +    register unsigned long int __r4 asm ("4") = (unsigned long int) (nr);     \ +    register unsigned long int __result asm ("2");			      \ +									      \ +    __asm __volatile ("svc %b1"						      \ +		      : "=d" (__result)					      \ +		      : "i" (SYS_futex), "0" (__r2), "d" (__r3), "d" (__r4)   \ +		      : "cc", "memory" );				      \ +    __result;								      \ +  }) + + +/* Returns non-zero if error happened, zero if success.  */ +#define lll_futex_requeue(futex, nr_wake, nr_move, mutex, val) \ +  ({									      \ +    register unsigned long int __r2 asm ("2") = (unsigned long int) (futex);  \ +    register unsigned long int __r3 asm ("3") = FUTEX_CMP_REQUEUE;	      \ +    register unsigned long int __r4 asm ("4") = (long int) (nr_wake);	      \ +    register unsigned long int __r5 asm ("5") = (long int) (nr_move);	      \ +    register unsigned long int __r6 asm ("6") = (unsigned long int) (mutex);  \ +    register unsigned long int __r7 asm ("7") = (int) (val);		      \ +    register unsigned long __result asm ("2");				      \ +									      \ +    __asm __volatile ("svc %b1"						      \ +		      : "=d" (__result)					      \ +		      : "i" (SYS_futex), "0" (__r2), "d" (__r3),	      \ +			"d" (__r4), "d" (__r5), "d" (__r6), "d" (__r7)	      \ +		      : "cc", "memory" );				      \ +    __result > -4096UL;							      \ +  }) + + +#define lll_compare_and_swap(futex, oldval, newval, operation) \ +  do {									      \ +    __typeof (futex) __futex = (futex);					      \ +    __asm __volatile ("	  l   %1,%0\n"					      \ +		      "0: " operation "\n"				      \ +		      "	  cs  %1,%2,%0\n"				      \ +		      "	  jl  0b\n"					      \ +		      "1:"						      \ +		      : "=Q" (*__futex), "=&d" (oldval), "=&d" (newval)	      \ +		      : "m" (*__futex) : "cc", "memory" );		      \ +  } while (0) + + +static inline int +__attribute__ ((always_inline)) +__lll_mutex_trylock (int *futex) +{ +    unsigned int old; + +    __asm __volatile ("cs %0,%3,%1" +		       : "=d" (old), "=Q" (*futex) +		       : "0" (0), "d" (1), "m" (*futex) : "cc", "memory" ); +    return old != 0; +} +#define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex)) + + +static inline int +__attribute__ ((always_inline)) +__lll_mutex_cond_trylock (int *futex) +{ +    unsigned int old; + +    __asm __volatile ("cs %0,%3,%1" +		       : "=d" (old), "=Q" (*futex) +		       : "0" (0), "d" (2), "m" (*futex) : "cc", "memory" ); +    return old != 0; +} +#define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex)) + + +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 oldval; +  int newval = 0; + +  lll_compare_and_swap (futex, oldval, newval, "slr %2,%2"); +  if (oldval > 1) +    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) +{ +  *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) + + +/* We have a separate internal lock implementation which is not tied +   to binary compatibility.  We can use the lll_mutex_*.  */ + +/* Type for lock object.  */ +typedef int lll_lock_t; + +/* Initializers for lock.  */ +#define LLL_LOCK_INITIALIZER		(0) +#define LLL_LOCK_INITIALIZER_LOCKED	(1) + +#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)     lll_mutex_islocked (futex) + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + +/* The states of a lock are: +    1  -  untaken +    0  -  taken by one user +   <0  -  taken by more users */ + + +/* 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.	*/ +static inline void +__attribute__ ((always_inline)) +__lll_wait_tid (int *ptid) +{ +  int tid; + +  while ((tid = *ptid) != 0) +    lll_futex_wait (ptid, tid); +} +#define lll_wait_tid(tid) __lll_wait_tid(&(tid)) + +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/s390/not-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/not-cancel.h new file mode 100644 index 000000000..acf1a617e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/not-cancel.h @@ -0,0 +1 @@ +#include "../i386/not-cancel.h" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c new file mode 100644 index 000000000..f29e23fd4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c @@ -0,0 +1,111 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 (once_control, init_routine) +     pthread_once_t *once_control; +     void (*init_routine) (void); +{ +  while (1) +    { +      int oldval; +      int newval; + +      /* Pseudo code: +	   oldval = *once_control; +	   if ((oldval & 2) == 0) +	    { +	      newval = (oldval & 3) | __fork_generation | 1; +	      *once_control = newval; +	    } +	 Do this atomically.  */ +      __asm __volatile ("   l	 %1,%0\n" +			"0: lhi	 %2,2\n" +			"   tml	 %1,2\n" +			"   jnz	 1f\n" +			"   nr	 %2,%1\n" +			"   ahi	 %2,1\n" +			"   o	 %2,%3\n" +			"   cs	 %1,%2,%0\n" +			"   jl	 0b\n" +			"1:" +			: "=Q" (*once_control), "=&d" (oldval), "=&d" (newval) +			: "m" (__fork_generation), "m" (*once_control) +			: "cc" ); +      /* Check if the initialized has already been done.  */ +      if ((oldval & 2) != 0) +	  break; +      /* 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.  */ +      __asm __volatile ("   l	 %1,%0\n" +			"0: lr	 %2,%1\n" +			"   ahi	 %2,1\n" +			"   cs	 %1,%2,%0\n" +			"   jl	 0b\n" +			: "=Q" (*once_control), "=&d" (oldval), "=&d" (newval) +			: "m" (*once_control) : "cc" ); + +      /* 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/s390/s390-32/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/clone.S new file mode 100644 index 000000000..682f94dae --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/linux/s390/s390-32/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c new file mode 100644 index 000000000..40d4d50c3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c @@ -0,0 +1,154 @@ +/* Special .init and .fini section support for S/390. +   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. + +   In addition to the permissions in the GNU Lesser 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 Lesser 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 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, 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\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ +\n\ +	.section .init\n\ +#NO_APP\n\ +	.align 4\n\ +.globl _init\n\ +	.type	 _init,@function\n\ +_init:\n\ +#	leaf function           0\n\ +#	automatics              0\n\ +#	outgoing args           0\n\ +#	need frame pointer      0\n\ +#	call alloca             0\n\ +#	has varargs             0\n\ +#	incoming args (stack)   0\n\ +#	function length         36\n\ +	STM	6,15,24(15)\n\ +	BRAS	13,.LTN1_0\n\ +.LT1_0:\n\ +.LC13:\n\ +	.long	__pthread_initialize_minimal_internal-.LT1_0\n\ +.LC14:\n\ +	.long	__gmon_start__@GOT\n\ +.LC15:\n\ +	.long	_GLOBAL_OFFSET_TABLE_-.LT1_0\n\ +.LTN1_0:\n\ +	LR	1,15\n\ +	AHI	15,-96\n\ +	ST	1,0(15)\n\ +	L	12,.LC15-.LT1_0(13)\n\ +	AR	12,13\n\ +	L     1,.LC13-.LT1_0(13)\n\ +	LA    1,0(1,13)\n\ +	BASR  14,1\n\ +	L     1,.LC14-.LT1_0(13)\n\ +	L     1,0(1,12)\n\ +	LTR   1,1\n\ +	JE    .L22\n\ +	BASR  14,1\n\ +.L22:\n\ +#APP\n\ +	.align 4,0x07\n\ +	END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ +	.align 4\n\ +	.section .init\n\ +#NO_APP\n\ +	.align 4\n\ +	L	4,152(15)\n\ +	LM	6,15,120(15)\n\ +	BR	4\n\ +#APP\n\ +	END_INIT\n\ +\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ +	.section .fini\n\ +#NO_APP\n\ +	.align 4\n\ +.globl _fini\n\ +	.type	 _fini,@function\n\ +_fini:\n\ +#	leaf function           0\n\ +#	automatics              0\n\ +#	outgoing args           0\n\ +#	need frame pointer      0\n\ +#	call alloca             0\n\ +#	has varargs             0\n\ +#	incoming args (stack)   0\n\ +#	function length         30\n\ +	STM	6,15,24(15)\n\ +	BRAS	13,.LTN2_0\n\ +.LT2_0:\n\ +.LC17:\n\ +	.long	_GLOBAL_OFFSET_TABLE_-.LT2_0\n\ +.LTN2_0:\n\ +	LR	1,15\n\ +	AHI	15,-96\n\ +	ST	1,0(15)\n\ +	L	12,.LC17-.LT2_0(13)\n\ +	AR	12,13\n\ +#APP\n\ +	.align 4,0x07\n\ +	END_FINI\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ +	.align 4\n\ +	.section .fini\n\ +#NO_APP\n\ +	.align 4\n\ +	L	4,152(15)\n\ +	LM	6,15,120(15)\n\ +	BR	4\n\ +#APP\n\ +	END_FINI\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\ +"); diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S new file mode 100644 index 000000000..60d6dbdef --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S @@ -0,0 +1,54 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <sysdep.h> +#define _ERRNO_H	1 +#include <bits/errno.h> +#include <kernel-features.h> +#include <bits/wordsize.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) +	ear	%r4,%a0 +	l	%r3,PID(%r4) +	lcr	%r1,%r3 +	st	%r1,PID(%r4) + +	/* Do vfork system call.  */ +	svc	SYS_ify (vfork) + +	ltr	%r2,%r2 +	je	1f +	st	%r3,PID(%r4) +1: +	/* Check for error.  */ +	lhi	%r4,-4095 +	clr	%r2,%r4 +	jnl	SYSCALL_ERROR_LABEL + +	/* Normal return.  */ +	br	%r14 +PSEUDO_END(__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h new file mode 100644 index 000000000..09dac2c90 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h @@ -0,0 +1,115 @@ +/* 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 <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)				      \ +	.text;								      \ +L(pseudo_cancel):							      \ +	cfi_startproc;							      \ +	STM_##args							      \ +	stm	%r12,%r15,48(%r15);					      \ +	cfi_offset (%r15, -36);						      \ +	cfi_offset (%r14, -40);						      \ +	cfi_offset (%r13, -44);						      \ +	cfi_offset (%r12, -48);						      \ +	lr	%r14,%r15;						      \ +	ahi	%r15,-96;						      \ +	cfi_adjust_cfa_offset (96);					      \ +	st	%r14,0(%r15);						      \ +	basr    %r13,0;							      \ +0:	l	%r1,1f-0b(%r13);					      \ +	bas	%r14,0(%r1,%r13);					      \ +	lr	%r0,%r2;						      \ +	LM_##args							      \ +	DO_CALL(syscall_name, args);					      \ +	l	%r1,2f-0b(%r13);					      \ +	lr	%r12,%r2;						      \ +	lr	%r2,%r0;						      \ +	bas	%r14,0(%r1,%r13);					      \ +	lr	%r2,%r12;						      \ +	lm	%r12,%r15,48+96(%r15);					      \ +	cfi_endproc;							      \ +	j	L(pseudo_check);					      \ +1:	.long	CENABLE-0b;						      \ +2:	.long	CDISABLE-0b;						      \ +ENTRY(name)								      \ +	SINGLE_THREAD_P(%r1)						      \ +	jne	L(pseudo_cancel);					      \ +.type	__##syscall_name##_nocancel,@function;				      \ +.globl	__##syscall_name##_nocancel;					      \ +__##syscall_name##_nocancel:						      \ +	DO_CALL(syscall_name, args);					      \ +L(pseudo_check):							      \ +	lhi	%r4,-4095;						      \ +	clr	%r2,%r4;						      \ +	jnl	SYSCALL_ERROR_LABEL;					      \ +.size	__##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \ +L(pseudo_end): + +# ifdef IS_IN_libpthread +#  define CENABLE	__pthread_enable_asynccancel +#  define CDISABLE	__pthread_disable_asynccancel +# elif !defined NOT_IN_libc +#  define CENABLE	__libc_enable_asynccancel +#  define CDISABLE	__libc_disable_asynccancel +# elif defined IS_IN_librt +#  define CENABLE	__librt_enable_asynccancel +#  define CDISABLE	__librt_disable_asynccancel +# else +#  error Unsupported library +# endif + +#define STM_0		/* Nothing */ +#define STM_1		st %r2,8(%r15); +#define STM_2		stm %r2,%r3,8(%r15); +#define STM_3		stm %r2,%r4,8(%r15); +#define STM_4		stm %r2,%r5,8(%r15); +#define STM_5		stm %r2,%r5,8(%r15); + +#define LM_0		/* Nothing */ +#define LM_1		l %r2,8+96(%r15); +#define LM_2		lm %r2,%r3,8+96(%r15); +#define LM_3		lm %r2,%r4,8+96(%r15); +#define LM_4		lm %r2,%r5,8+96(%r15); +#define LM_5		lm %r2,%r5,8+96(%r15); + +# ifndef __ASSEMBLER__ +#  define SINGLE_THREAD_P \ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \ +				   header.multiple_threads) == 0, 1) +# else +#  define SINGLE_THREAD_P(reg) \ +	ear	reg,%a0;						      \ +	icm	reg,15,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/s390/s390-32/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S new file mode 100644 index 000000000..7b139341f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-32/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 <kernel-features.h> +#include <bits/wordsize.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) +	ear	%r4,%a0 +	lhi	%r1,1 +	icm	%r3,15,PID(%r4) +	sll	%r1,31 +	je	1f +	lcr	%r1,%r3 +1:	st	%r1,PID(%r4) + +	/* Do vfork system call.  */ +	svc	SYS_ify (vfork) + +	ltr	%r2,%r2 +	je	1f +	st	%r3,PID(%r4) +1: +	/* Check for error.  */ +	lhi	%r4,-4095 +	clr	%r2,%r4 +	jnl	SYSCALL_ERROR_LABEL + +	/* Normal return.  */ +	br	%r14 +PSEUDO_END(__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/Versions b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/Versions new file mode 100644 index 000000000..3b111ddb5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-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/s390/s390-64/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/clone.S new file mode 100644 index 000000000..87ee2e184 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/linux/s390/s390-64/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c new file mode 100644 index 000000000..a102d07d6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c @@ -0,0 +1,136 @@ +/* Special .init and .fini section support for 64 bit S/390. +   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. + +   In addition to the permissions in the GNU Lesser 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 Lesser 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 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, 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\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ +\n\ +	.section .init\n\ +#NO_APP\n\ +	.align 4\n\ +.globl _init\n\ +	.type	 _init,@function\n\ +_init:\n\ +#	leaf function           0\n\ +#	automatics              0\n\ +#	outgoing args           0\n\ +#	need frame pointer      0\n\ +#	call alloca             0\n\ +#	has varargs             0\n\ +#	incoming args (stack)   0\n\ +#	function length         36\n\ +	STMG	6,15,48(15)\n\ +	LGR	1,15\n\ +	AGHI	15,-160\n\ +	STG	1,0(15)\n\ +	LARL	12,_GLOBAL_OFFSET_TABLE_\n\ +	BRASL	14,__pthread_initialize_minimal_internal\n\ +	LARL	1,__gmon_start__@GOTENT\n\ +	LG	1,0(1)\n\ +	LTGR	1,1\n\ +	JE	.L22\n\ +	BASR	14,1\n\ +.L22:\n\ +#APP\n\ +	.align 4,0x07\n\ +	END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ +	.align 4\n\ +	.section .init\n\ +#NO_APP\n\ +	.align 4\n\ +	LG	4,272(15)\n\ +	LMG	6,15,208(15)\n\ +	BR	4\n\ +#APP\n\ +	END_INIT\n\ +\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ +	.section .fini\n\ +#NO_APP\n\ +	.align 4\n\ +.globl _fini\n\ +	.type	 _fini,@function\n\ +_fini:\n\ +#	leaf function           0\n\ +#	automatics              0\n\ +#	outgoing args           0\n\ +#	need frame pointer      0\n\ +#	call alloca             0\n\ +#	has varargs             0\n\ +#	incoming args (stack)   0\n\ +#	function length         30\n\ +	STMG	6,15,48(15)\n\ +	LGR	1,15\n\ +	AGHI	15,-160\n\ +	STG	1,0(15)\n\ +	LARL	12,_GLOBAL_OFFSET_TABLE_\n\ +#APP\n\ +	.align 4,0x07\n\ +	END_FINI\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ +	.align 4\n\ +	.section .fini\n\ +#NO_APP\n\ +	.align 4\n\ +	LG	4,272(15)\n\ +	LMG	6,15,208(15)\n\ +	BR	4\n\ +#APP\n\ +	END_FINI\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ +	"); diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S new file mode 100644 index 000000000..04ae5bf59 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S @@ -0,0 +1,57 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Martin Schwidefsky <schwidefsky@de.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 <sysdep.h> +#define _ERRNO_H	1 +#include <bits/errno.h> +#include <kernel-features.h> +#include <bits/wordsize.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) + +	ear	%r4,%a0 +	sllg	%r4,%r4,32 +	ear	%r4,%a1 +	l	%r3,PID(%r4) +	lcr	%r1,%r3 +	st	%r1,PID(%r4) + +	/* Do vfork system call.  */ +	svc	SYS_ify (vfork) + +	ltgr	%r2,%r2 +	je	1f +	st	%r3,PID(%r4) +1: +	/* Check for error.  */ +	lghi	%r4,-4095 +	clgr	%r2,%r4 +	jgnl	SYSCALL_ERROR_LABEL + +	/* Normal return.  */ +	br	%r14 +PSEUDO_END(__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h new file mode 100644 index 000000000..f8eb6a9eb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h @@ -0,0 +1,128 @@ +/* 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 <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)				      \ +	.text;								      \ +L(pseudo_cancel):							      \ +	cfi_startproc;							      \ +	STM_##args							      \ +	stmg	%r13,%r15,104(%r15);					      \ +	cfi_offset (%r15,-40);						      \ +	cfi_offset (%r14,-48);						      \ +	cfi_offset (%r13,-56);						      \ +	lgr	%r14,%r15;						      \ +	aghi	%r15,-160;						      \ +	cfi_adjust_cfa_offset (160);					      \ +	stg	%r14,0(%r15);						      \ +	brasl	%r14,CENABLE;						      \ +	lgr	%r0,%r2;						      \ +	LM_##args							      \ +	DO_CALL(syscall_name, args);					      \ +	lgr	%r13,%r2;						      \ +	lgr	%r2,%r0;						      \ +	brasl	%r14,CDISABLE;						      \ +	lgr	%r2,%r13;						      \ +	lmg	%r13,%r15,104+160(%r15);				      \ +	cfi_endproc;							      \ +	j	L(pseudo_check);					      \ +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);					      \ +L(pseudo_check):							      \ +	lghi	%r4,-4095;						      \ +	clgr	%r2,%r4;						      \ +	jgnl	SYSCALL_ERROR_LABEL;					      \ +.size	__##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \ +L(pseudo_end): + +# ifdef IS_IN_libpthread +#  define CENABLE	__pthread_enable_asynccancel +#  define CDISABLE	__pthread_disable_asynccancel +#  define __local_multiple_threads	__pthread_multiple_threads +# elif !defined NOT_IN_libc +#  define CENABLE	__libc_enable_asynccancel +#  define CDISABLE	__libc_disable_asynccancel +#  define __local_multiple_threads	__libc_multiple_threads +# elif defined IS_IN_librt +#  define CENABLE	__librt_enable_asynccancel +#  define CDISABLE	__librt_disable_asynccancel +# else +#  error Unsupported library +# endif + +#define STM_0		/* Nothing */ +#define STM_1		stg %r2,16(%r15); +#define STM_2		stmg %r2,%r3,16(%r15); +#define STM_3		stmg %r2,%r4,16(%r15); +#define STM_4		stmg %r2,%r5,16(%r15); +#define STM_5		stmg %r2,%r5,16(%r15); + +#define LM_0		/* Nothing */ +#define LM_1		lg %r2,16+160(%r15); +#define LM_2		lmg %r2,%r3,16+160(%r15); +#define LM_3		lmg %r2,%r4,16+160(%r15); +#define LM_4		lmg %r2,%r5,16+160(%r15); +#define LM_5		lmg %r2,%r5,16+160(%r15); + +# 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 \ +	larl	%r1,__local_multiple_threads;				      \ +	icm	%r0,15,0(%r1); +#  endif + +# else + +#  ifndef __ASSEMBLER__ +#   define SINGLE_THREAD_P \ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \ +				   header.multiple_threads) == 0, 1) +#  else +#   define SINGLE_THREAD_P \ +	ear	%r1,%a0;						      \ +	sllg	%r1,%r1,32;						      \ +	ear	%r1,%a1;						      \ +	icm	%r1,15,MULTIPLE_THREADS_OFFSET(%r1); +#  endif + +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_create.c new file mode 100644 index 000000000..172223af3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_create.c @@ -0,0 +1 @@ +#include "../x86_64/timer_create.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_delete.c new file mode 100644 index 000000000..537516e0a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_delete.c @@ -0,0 +1 @@ +#include "../x86_64/timer_delete.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_getoverr.c new file mode 100644 index 000000000..3f21a73c9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_getoverr.c @@ -0,0 +1 @@ +#include "../x86_64/timer_getoverr.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_gettime.c new file mode 100644 index 000000000..a50143adc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_gettime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_gettime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_settime.c new file mode 100644 index 000000000..37baeffac --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/timer_settime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_settime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S new file mode 100644 index 000000000..f43e9c34b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S @@ -0,0 +1,59 @@ +/* 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 <kernel-features.h> +#include <bits/wordsize.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) + +	ear	%r4,%a0 +	sllg	%r4,%r4,32 +	ear	%r4,%a1 +	icm	%r3,15,PID(%r4) +	llilh	%r1,32768 +	je	1f +	lcr	%r1,%r3 +1:	st	%r1,PID(%r4) + +	/* Do vfork system call.  */ +	svc	SYS_ify (vfork) + +	ltgr	%r2,%r2 +	je	1f +	st	%r3,PID(%r4) +1: +	/* Check for error.  */ +	lghi	%r4,-4095 +	clgr	%r2,%r4 +	jgnl	SYSCALL_ERROR_LABEL + +	/* Normal return.  */ +	br	%r14 +PSEUDO_END(__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) 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..671b43f7f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_post.c @@ -0,0 +1,47 @@ +/* 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> + +#include <shlib-compat.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; +} +versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1); +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_post, __old_sem_post) +compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0); +#endif 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..ef897c1e9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c @@ -0,0 +1,99 @@ +/* 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> +#include <shlib-compat.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..f50036114 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_trywait.c @@ -0,0 +1,50 @@ +/* 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> + +#include <shlib-compat.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; +} +versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1); +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_trywait, __old_sem_trywait) +compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0); +#endif 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..e6733e88a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c @@ -0,0 +1,63 @@ +/* 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> +#include <shlib-compat.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; +} + +versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1); +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_wait, __old_sem_wait) +compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0); +#endif 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..5125408dc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h @@ -0,0 +1,158 @@ +/* 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 _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; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    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; +    int __spins; +  } __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..62a11972d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/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..8e6821538 --- /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 <nptl/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..6868b9bcd --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/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> + +/* 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..76d22c88f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h @@ -0,0 +1,79 @@ +/* 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, old) \ +	.align	2; \ +	mova	99f, r0; \ +	mov	r15, r1; \ +	mov	_IMM6, r15; \ +98:	mov.l	mem, old; \ +	add	old, reg; \ +	mov.l	reg, 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..bcb15615e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S @@ -0,0 +1,302 @@ +/* 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 SYS_futex		240 +#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 +__lll_mutex_lock_wait: +	mov.l	r8, @-r15 +	mov	r4, r6 +	mov	r5, r8 +	mov	#0, r7		/* No timeout.  */ +	mov	#FUTEX_WAIT, r5 + +	mov	#2, r4 +	cmp/eq	r4, r6 +	bf	2f + +1: +	mov	r8, r4 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +2: +	mov	#2, r4 +	XCHG (r4, @r8, r2) +	tst	r2, r2 +	bf	1b + +	mov.l	@r15+, r8 +	ret +	 mov	r2, r0 +	.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 +__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	r10, @-r15 +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	mov	r4, r10 +	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, r4 +	CMPXCHG (r3, @r8, r4, r2) +	tst	r2, r2 +	bt	8f + +	mov	r8, r4 +	mov	#FUTEX_WAIT, r5 +	mov	r10, r6 +	mov	r15, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov	r0, r5 + +8: +	mov	#0, r3 +	mov	#2, r4 +	CMPXCHG (r3, @r8, r4, r2) +	bf/s	7f +	 mov	#0, r0 + +6: +	add	#8, r15 +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	rts +	 mov.l	@r15+, r10 +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 +__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..d9376d45a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h @@ -0,0 +1,278 @@ +/* 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 <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> + +#define SYS_futex		240 +#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, val, *__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, val, *__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, val, *__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_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..acf1a617e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/not-cancel.h @@ -0,0 +1 @@ +#include "../i386/not-cancel.h" 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..2d1148daa --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S @@ -0,0 +1,66 @@ +/* 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) +libc_hidden_def (__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..1fbb23a5a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S @@ -0,0 +1,196 @@ +/* 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 SYS_futex	240 +#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.  */ +	mov	#1, r3 +	mov.l	@(INIT_COUNT,r8), r4 +	XADD	(r3, @(LEFT,r8), r2) +	add	#-1, 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.  */ +	mov	#1, r3 +	mov.l	@(INIT_COUNT,r8), r4 +	XADD	(r3, @(LEFT,r8), r2) +	add	#-1, 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 +	ret +	 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..6bd6e60ec --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S @@ -0,0 +1,213 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include <kernel-features.h> +#include "lowlevel-atomic.h" + +#define SYS_futex		240 +#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 +versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, +		  GLIBC_2_3_2) 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..8b0196fdc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S @@ -0,0 +1,139 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include <kernel-features.h> +#include "lowlevel-atomic.h" + +#define SYS_futex		240 +#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 +versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, +		  GLIBC_2_3_2) + 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..74206a71e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S @@ -0,0 +1,770 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include <pthread-errnos.h> +#include "lowlevel-atomic.h" + +#define SYS_gettimeofday	__NR_gettimeofday +#define SYS_futex		240 +#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 +versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, +		  GLIBC_2_3_2) + + +	.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..2d6b68566 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S @@ -0,0 +1,628 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include "lowlevel-atomic.h" + +#define SYS_futex		240 +#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 +versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, +		  GLIBC_2_3_2) + + +	.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..02af56b4c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S @@ -0,0 +1,246 @@ +/* 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 SYS_futex	240 +#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..f64c7217c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S @@ -0,0 +1,221 @@ +/* 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_futex		240 +#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..633a14b1a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S @@ -0,0 +1,281 @@ +/* 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 SYS_futex		240 +#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..29e29b6f6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S @@ -0,0 +1,266 @@ +/* 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 SYS_futex		240 +#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..172689bec --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S @@ -0,0 +1,170 @@ +/* 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 SYS_futex		240 +#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..995d823e8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S @@ -0,0 +1,203 @@ +/* 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_futex		240 +#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..9bc12da7e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S @@ -0,0 +1,87 @@ +/* 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 <shlib-compat.h> +#include <pthread-errnos.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday	__NR_gettimeofday +#define SYS_futex		240 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +	.text + +	.globl	__new_sem_post +	.type	__new_sem_post,@function +	.align	5 +__new_sem_post: +	mov	#1, r3 +	XADD (r3, @r4, r2) + +	mov	#FUTEX_WAKE, r5 +	mov	r2, r6 +	add	#1, r6 +	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 +	add	r1, r0 +#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 +.Lerrno3: +	.long	errno@GOTTPOFF +#else +.Lerrloc3: +	.long	__errno_location@PLT-(.Lerrloc3b-.) +#endif +	.size	__new_sem_post,.-__new_sem_post +	versioned_symbol(libpthread, __new_sem_post, sem_post, GLIBC_2_1) 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..acb7d0f78 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S @@ -0,0 +1,241 @@ +/* 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 <shlib-compat.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday	__NR_gettimeofday +#define SYS_futex		240 +#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 +	add	r1, r0 +	mov.l	r8, @r0 +#else +	mov.l	.Lerrloc2, r1 +	bsrf	r1 +	 nop +.Lerrloc2b: +	mov.l	r8, @r0 +#endif +	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 +.Lerrno2: +	.long	errno@GOTTPOFF +#else +.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..ccdf3a0db --- /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 <shlib-compat.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 +	add	r1, r0 +	mov.l	r8, @r0 +#else +	mov.l	.Lerrloc1, r1 +	bsrf	r1 +	 nop +.Lerrloc1b: +	mov.l	r8, @r0 +#endif +	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 +.Lerrno1: +	.long	errno@GOTTPOFF +#else +.Lerrloc1: +	.long	__errno_location@PLT-(.Lerrloc1b-.) +#endif +	.size	__new_sem_trywait,.-__new_sem_trywait +	versioned_symbol(libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1) 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..9ceb8f1c2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S @@ -0,0 +1,167 @@ +/* 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 <shlib-compat.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday	__NR_gettimeofday +#define SYS_futex		240 +#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 +	add	r1, r0 +	mov.l	r8, @r0 +#else +	mov.l	.Lerrloc0, r1 +	bsrf	r1 +	 nop +.Lerrloc0b: +	mov.l	r8, @r0 +#endif +	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 +.Lerrno0: +	.long	errno@GOTTPOFF +#else +.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 +	versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1) 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/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..fc3c2340b --- /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 <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 + +# 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/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S new file mode 100644 index 000000000..5433eacbe --- /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) +libc_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..8560e8b40 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c @@ -0,0 +1,2 @@ +#include <nptl/pthreadP.h> +#include "../../../../../sysdeps/unix/sysv/linux/sigtimedwait.c" 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..c358bfbee --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c @@ -0,0 +1,2 @@ +#include <nptl/pthreadP.h> +#include "../../../../../sysdeps/unix/sysv/linux/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..a4f9fe8f5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c @@ -0,0 +1,2 @@ +#include <nptl/pthreadP.h> +#include "../../../../../sysdeps/unix/sysv/linux/sigwaitinfo.c" 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..c56b49b39 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c @@ -0,0 +1,2 @@ +#include <nptl/pthreadP.h> +#include <sysdeps/unix/sysv/linux/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/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/aio_cancel.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/aio_cancel.c new file mode 100644 index 000000000..0d6da8291 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/aio_cancel.c @@ -0,0 +1,33 @@ +#include <shlib-compat.h> + +#define aio_cancel64 XXX +#include <aio.h> +#undef aio_cancel64 +#include <errno.h> + +extern __typeof (aio_cancel) __new_aio_cancel; +extern __typeof (aio_cancel) __old_aio_cancel; + +#define aio_cancel	__new_aio_cancel + +#include <sysdeps/pthread/aio_cancel.c> + +#undef aio_cancel +strong_alias (__new_aio_cancel, __new_aio_cancel64); +versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); +versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); + +#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) + +#undef ECANCELED +#define aio_cancel	__old_aio_cancel +#define ECANCELED	125 + +#include <sysdeps/pthread/aio_cancel.c> + +#undef aio_cancel +strong_alias (__old_aio_cancel, __old_aio_cancel64); +compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); +compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); + +#endif 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..3c5a28944 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h @@ -0,0 +1,196 @@ +/* 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; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is deliberately not exposed.  */ +typedef union +{ +  struct +  { +    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 +    unsigned int __nusers; +#endif +    int __spins; +  } __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/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/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h new file mode 100644 index 000000000..4626aec52 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h @@ -0,0 +1,228 @@ +/* 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 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> + + +#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);		      \ +    __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;								      \ +  }) + +/* 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 __sparc32_atomic_do_lock +#error SPARC < v9 does not support compare and swap which is essential for futex based locking +#endif + +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(futex) __lll_mutex_trylock (&(futex)) + +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(futex) __lll_mutex_cond_trylock (&(futex)) + + +extern void __lll_lock_wait (int *futex) attribute_hidden; + + +static inline void +__attribute__ ((always_inline)) +__lll_mutex_lock (int *futex) +{ +  int val = atomic_compare_and_exchange_val_acq (futex, 1, 0); + +  if (__builtin_expect (val != 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) +{ +  int val = atomic_compare_and_exchange_val_acq (futex, 2, 0); + +  if (__builtin_expect (val != 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 val = atomic_compare_and_exchange_val_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_mutex_timedlock (&(futex), abstime) + +#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);						      \ +    (void) atomic_exchange_rel (__futex, 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.  We can use the lll_mutex_*.  */ + +/* Type for lock object.  */ +typedef int lll_lock_t; + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + +/* Initializers for lock.  */ +#define LLL_LOCK_INITIALIZER		(0) +#define LLL_LOCK_INITIALIZER_LOCKED	(1) + +#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)	lll_mutex_islocked (futex) + + +/* 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;						\ +  }) + + +/* 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/sparc/not-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/not-cancel.h new file mode 100644 index 000000000..acf1a617e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/not-cancel.h @@ -0,0 +1 @@ +#include "../i386/not-cancel.h" 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..da6197c00 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/linux/sparc/sparc32/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..55229c9e6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S @@ -0,0 +1,42 @@ +/* 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 +ENTRY(__vfork) +	ld	[%g7 + PID], %o5 +	sub	%g0, %o5, %o4 +	st	%o4, [%g7 + PID] + +	LOADSYSCALL(vfork) +	ta	0x10 +	bcs,a	__syscall_error_handler +	 st	%o5, [%g7 + PID] +	SYSCALL_ERROR_HANDLER +	sub	%o1, 1, %o1 +	andcc	%o0, %o1, %o0 +	bne,a	1f +	 st	%o5, [%g7 + PID] +1:	retl +	 nop + +PSEUDO_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..5edf4b377 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h @@ -0,0 +1,113 @@ +/* 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 <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)				      \ +	.text;								      \ +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;							      \ +	bcs __syscall_error_handler;					      \ +	 nop;								      \ +.size	__##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \ +	.subsection 2;							      \ +	cfi_startproc;							      \ +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;							      \ +	bcs __syscall_error_handler2;					      \ +	 mov %o0, %l1;							      \ +	CDISABLE;							      \ +	 mov %l0, %o0;							      \ +	jmpl %i7 + 8, %g0;						      \ +	 restore %g0, %l1, %o0;						      \ +	cfi_endproc;							      \ +	.previous;							      \ +	SYSCALL_ERROR_HANDLER						      \ +	SYSCALL_ERROR_HANDLER2 + +#define SYSCALL_ERROR_HANDLER2						      \ +SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2)			      \ +	.global __errno_location;					      \ +        .type   __errno_location,@function;				      \ +	CDISABLE;							      \ +	 mov	%l0, %o0;						      \ +	call	__errno_location;					      \ +	 nop;								      \ +	st	%l1, [%o0];						      \ +	jmpl	%i7 + 8, %g0;						      \ +	 restore %g0, -1, %o0;						      \ +	.previous; + +# 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..722960814 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S @@ -0,0 +1,46 @@ +/* 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 +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 +	bcs,a	__syscall_error_handler +	 st	%o5, [%g7 + PID] +	SYSCALL_ERROR_HANDLER +	sub	%o1, 1, %o1 +	andcc	%o0, %o1, %o0 +	bne,a	1f +	 st	%o5, [%g7 + PID] +1:	retl +	 nop + +PSEUDO_END (__vfork) +libc_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..410f32017 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/linux/sparc/sparc64/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..e9018b2e9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S @@ -0,0 +1,42 @@ +/* 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 +ENTRY(__vfork) +	ld	[%g7 + PID], %o5 +	sub	%g0, %o5, %o4 +	st	%o4, [%g7 + PID] + +	LOADSYSCALL(vfork) +	ta	0x6d +	bcs,a,pn %xcc, __syscall_error_handler +	 st	%o5, [%g7 + PID] +	SYSCALL_ERROR_HANDLER +	sub	%o1, 1, %o1 +	andcc	%o0, %o1, %o0 +	bne,a,pt %icc, 1f +	 st	%o5, [%g7 + PID] +1:	retl +	 nop + +PSEUDO_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..d8c65aeff --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h @@ -0,0 +1,107 @@ +/* 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 <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)				      \ +	.text;								      \ +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;							      \ +	bcs,pn %xcc, __syscall_error_handler;				      \ +	 nop;								      \ +.size	__##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \ +	.subsection 2;							      \ +1:	save %sp, -192, %sp;						      \ +	CENABLE;							      \ +	 nop;								      \ +	mov %o0, %l0;							      \ +	COPY_ARGS_##args						      \ +	mov SYS_ify(syscall_name), %g1;					      \ +	ta 0x6d;							      \ +	bcs,pn %xcc, __syscall_error_handler2;				      \ +	 mov %o0, %l1;							      \ +	CDISABLE;							      \ +	 mov %l0, %o0;							      \ +	jmpl %i7 + 8, %g0;						      \ +	 restore %g0, %l1, %o0;						      \ +	.previous;							      \ +	SYSCALL_ERROR_HANDLER						      \ +	SYSCALL_ERROR_HANDLER2 + +#define SYSCALL_ERROR_HANDLER2						      \ +SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2)			      \ +	.global __errno_location;					      \ +        .type   __errno_location,@function;				      \ +	CDISABLE;							      \ +	 mov	%l0, %o0;						      \ +	call	__errno_location;					      \ +	 nop;								      \ +	st	%l1, [%o0];						      \ +	jmpl	%i7 + 8, %g0;						      \ +	 restore %g0, -1, %o0;						      \ +	.previous; + +# 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/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..d6b2455d4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S @@ -0,0 +1,46 @@ +/* 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 +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 +	bcs,a,pn %xcc, __syscall_error_handler +	 st	%o5, [%g7 + PID] +	SYSCALL_ERROR_HANDLER +	sub	%o1, 1, %o1 +	andcc	%o0, %o1, %o0 +	bne,a,pt %icc, 1f +	 st	%o5, [%g7 + PID] +1:	retl +	 nop + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/stackinfo.h b/libpthread/nptl/sysdeps/unix/sysv/linux/stackinfo.h new file mode 100644 index 000000000..733c7210e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/stackinfo.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 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 <bits/stackinfo.h> 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..5e9951395 --- /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 <kernel-features.h> +#include <internaltypes.h> +#include <nptl/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 (clock_id, evp, timerid) +     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..35055212a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_delete.c @@ -0,0 +1,94 @@ +/* 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 <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 (timerid) +     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..fdbdaa7c8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c @@ -0,0 +1,81 @@ +/* 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 <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 (timerid) +     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..a2fcfd1b5 --- /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 <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 (timerid, value) +     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..23c800f98 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_routines.c @@ -0,0 +1,157 @@ +/* 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 <setjmp.h> +#include <signal.h> +#include <stdbool.h> +#include <sysdep.h> +#include <kernel-features.h> +#include <nptl/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 and none else.  */ +  sigset_t ss; +  sigemptyset (&ss); +  sigaddset (&ss, SIGTIMER); + +  /* 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.  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); +  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..fe08080a1 --- /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 <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 (timerid, flags, value, ovalue) +     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..72c8d615e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c @@ -0,0 +1,111 @@ +/* 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 (dso_handle) +     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/x86_64/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile new file mode 100644 index 000000000..b32ce29ef --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile @@ -0,0 +1,4 @@ +ifeq ($(subdir),nptl) +CFLAGS-pt-initfini.s = -g0 -fPIC -fno-inline-functions \ +		       -fno-asynchronous-unwind-tables $(fno-unit-at-a-time) +endif 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..92fb08c95 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h @@ -0,0 +1,195 @@ +/* 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 _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; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    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 +    unsigned int __nusers; +#endif +    int __spins; +  } __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 __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/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/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S new file mode 100644 index 000000000..dfa6adb3e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/linux/x86_64/clone.S> 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-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S new file mode 100644 index 000000000..3621efa4f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/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, __libc_multiple_threads(%rip); 			      \ +	je	0f;							      \ +	lock;								      \ +0: +#endif + +#include "lowlevellock.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..3a49e25dd --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S @@ -0,0 +1,283 @@ +/* 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 SYS_futex		202 +#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..40c2518af --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h @@ -0,0 +1,341 @@ +/* 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> + +#ifndef LOCK_INSTR +# ifdef UP +#  define LOCK_INSTR	/* nothing */ +# else +#  define LOCK_INSTR "lock;" +# endif +#endif + +#define SYS_futex		202 +#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/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..653b6b12f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S @@ -0,0 +1,33 @@ +/* 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 <tcb-offsets.h> + +#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 <../../../../../../sysdeps/unix/sysv/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..fa8125dd8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S @@ -0,0 +1,160 @@ +/* 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 SYS_futex	202 +#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..72e7bc5b2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S @@ -0,0 +1,138 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include <kernel-features.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define SYS_futex		202 +#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..de9e109f4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S @@ -0,0 +1,104 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include <kernel-features.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define SYS_futex		202 +#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..ad3ae1e76 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S @@ -0,0 +1,470 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include <pthread-errnos.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define SYS_futex		202 +#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	L(ENDCIE)-L(STARTCIE)		# 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..b837d466b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S @@ -0,0 +1,423 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include <tcb-offsets.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define SYS_futex		202 +#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	L(ENDCIE)-L(STARTCIE)		# 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..6bf8d095b --- /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 SYS_futex	202 +#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..5e9d8fb1d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S @@ -0,0 +1,177 @@ +/* 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 SYS_futex		202 +#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..b44660418 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S @@ -0,0 +1,220 @@ +/* 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 SYS_futex		202 +#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..525e5b6b9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S @@ -0,0 +1,211 @@ +/* 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 SYS_futex		202 +#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..3a6b9f0ba --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S @@ -0,0 +1,130 @@ +/* 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 SYS_futex		202 +#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..0e82f890a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S @@ -0,0 +1,165 @@ +/* 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 SYS_futex		202 +#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_spin_init.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c new file mode 100644 index 000000000..dc811787e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c @@ -0,0 +1 @@ +#include <nptl/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..7f608a597 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S @@ -0,0 +1,66 @@ +/* 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 <shlib-compat.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define SYS_futex		202 +#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..c44d3f5e7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S @@ -0,0 +1,175 @@ +/* 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 <shlib-compat.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define SYS_futex		202 + +/* 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..31271bb94 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S @@ -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 <sysdep.h> +#include <shlib-compat.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..63ecd063a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S @@ -0,0 +1,120 @@ +/* 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 <shlib-compat.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define SYS_futex		202 + + +	.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..97debaba9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h @@ -0,0 +1,138 @@ +/* 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 <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)				      \ +  .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):							      \ +    /* Save registers that might get destroyed.  */			      \ +    SAVESTK_##args							      \ +    PUSHARGS_##args							      \ +    CENABLE								      \ +    /* Restore registers.  */						      \ +    POPARGS_##args							      \ +    /* The return value from CENABLE is argument for CDISABLE.  */	      \ +    movq %rax, (%rsp);							      \ +    movl $SYS_ify (syscall_name), %eax;					      \ +    syscall;								      \ +    movq (%rsp), %rdi;							      \ +    /* Save %rax since it's the error code from the syscall.  */	      \ +    movq %rax, 8(%rsp);							      \ +    CDISABLE								      \ +    movq 8(%rsp), %rax;							      \ +    RESTSTK_##args							      \ +    cmpq $-4095, %rax;							      \ +    jae SYSCALL_ERROR_LABEL;						      \ +  L(pseudo_end): + + +# define PUSHARGS_0	/* Nothing.  */ +# define PUSHARGS_1	PUSHARGS_0 movq %rdi, 8(%rsp); +# define PUSHARGS_2	PUSHARGS_1 movq %rsi, 16(%rsp); +# define PUSHARGS_3	PUSHARGS_2 movq %rdx, 24(%rsp); +# define PUSHARGS_4	PUSHARGS_3 movq %rcx, 32(%rsp); +# define PUSHARGS_5	PUSHARGS_4 movq %r8, 40(%rsp); +# define PUSHARGS_6	PUSHARGS_5 movq %r9, 48(%rsp); + +# define POPARGS_0	/* Nothing.  */ +# define POPARGS_1	POPARGS_0 movq 8(%rsp), %rdi; +# define POPARGS_2	POPARGS_1 movq 16(%rsp), %rsi; +# define POPARGS_3	POPARGS_2 movq 24(%rsp), %rdx; +# define POPARGS_4	POPARGS_3 movq 32(%rsp), %r10; +# define POPARGS_5	POPARGS_4 movq 40(%rsp), %r8; +# define POPARGS_6	POPARGS_5 movq 48(%rsp), %r9; + +/* We always have to align the stack before calling a function.  */ +# define SAVESTK_0	subq $24, %rsp; cfi_adjust_cfa_offset (24); +# define SAVESTK_1	SAVESTK_0 +# define SAVESTK_2	SAVESTK_1 +# define SAVESTK_3	subq $40, %rsp; cfi_adjust_cfa_offset (40); +# define SAVESTK_4	SAVESTK_3 +# define SAVESTK_5	subq $56, %rsp; cfi_adjust_cfa_offset (56); +# define SAVESTK_6	SAVESTK_5 + +# define RESTSTK_0	addq $24,%rsp; cfi_adjust_cfa_offset (-24); +# define RESTSTK_1	RESTSTK_0 +# define RESTSTK_2	RESTSTK_1 +# define RESTSTK_3	addq $40, %rsp; cfi_adjust_cfa_offset (-40); +# define RESTSTK_4	RESTSTK_3 +# define RESTSTK_5	addq $56, %rsp; cfi_adjust_cfa_offset (-56); +# define RESTSTK_6	RESTSTK_5 + +# 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 diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_create.c new file mode 100644 index 000000000..1849f72a4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_create.c @@ -0,0 +1,66 @@ +/* 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 <shlib-compat.h> +#include "compat-timer.h" +#include <atomic.h> + + +#define timer_create_alias __timer_create_new +#include "../timer_create.c" + +#undef timer_create +versioned_symbol (librt, __timer_create_new, timer_create, GLIBC_2_3_3); + + +#if SHLIB_COMPAT (librt, GLIBC_2_2, GLIBC_2_3_3) +timer_t __compat_timer_list[OLD_TIMER_MAX] attribute_hidden; + + +int +__timer_create_old (clockid_t clock_id, struct sigevent *evp, int *timerid) +{ +  timer_t newp; + +  int res = __timer_create_new (clock_id, evp, &newp); +  if (res == 0) +    { +      int i; +      for (i = 0; i < OLD_TIMER_MAX; ++i) +	if (__compat_timer_list[i] == NULL +	    && ! atomic_compare_and_exchange_bool_acq (&__compat_timer_list[i], +						       newp, NULL)) +	  { +	    *timerid = i; +	    break; +	  } + +      if (__builtin_expect (i == OLD_TIMER_MAX, 0)) +	{ +	  /* No free slot.  */ +	  (void) __timer_delete_new (newp); +	  __set_errno (EINVAL); +	  res = -1; +	} +    } + +  return res; +} +compat_symbol (librt, __timer_create_old, timer_create, GLIBC_2_2); +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_delete.c new file mode 100644 index 000000000..6e0d9d033 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_delete.c @@ -0,0 +1,45 @@ +/* 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 <shlib-compat.h> +#include "compat-timer.h" + + +#define timer_delete_alias __timer_delete_new +#include "../timer_delete.c" + +#undef timer_delete +versioned_symbol (librt, __timer_delete_new, timer_delete, GLIBC_2_3_3); + + +#if SHLIB_COMPAT (librt, GLIBC_2_2, GLIBC_2_3_3) +int +__timer_delete_old (int timerid) +{ +  int res = __timer_delete_new (__compat_timer_list[timerid]); + +  if (res == 0) +    /* Successful timer deletion, now free the index.  We only need to +       store a word and that better be atomic.  */ +    __compat_timer_list[timerid] = NULL; + +  return res; +} +compat_symbol (librt, __timer_delete_old, timer_delete, GLIBC_2_2); +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_getoverr.c new file mode 100644 index 000000000..d75636c99 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_getoverr.c @@ -0,0 +1,39 @@ +/* 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 <shlib-compat.h> +#include "compat-timer.h" + + +#define timer_getoverrun_alias __timer_getoverrun_new +#include "../timer_getoverr.c" + +#undef timer_getoverrun +versioned_symbol (librt, __timer_getoverrun_new, timer_getoverrun, +		  GLIBC_2_3_3); + + +#if SHLIB_COMPAT (librt, GLIBC_2_2, GLIBC_2_3_3) +int +__timer_getoverrun_old (int timerid) +{ +  return __timer_getoverrun_new (__compat_timer_list[timerid]); +} +compat_symbol (librt, __timer_getoverrun_old, timer_getoverrun, GLIBC_2_2); +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_gettime.c new file mode 100644 index 000000000..1f1253af2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_gettime.c @@ -0,0 +1,38 @@ +/* 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 <shlib-compat.h> +#include "compat-timer.h" + + +#define timer_gettime_alias __timer_gettime_new +#include "../timer_gettime.c" + +#undef timer_gettime +versioned_symbol (librt, __timer_gettime_new, timer_gettime, GLIBC_2_3_3); + + +#if SHLIB_COMPAT (librt, GLIBC_2_2, GLIBC_2_3_3) +int +__timer_gettime_old (int timerid, struct itimerspec *value) +{ +  return __timer_gettime_new (__compat_timer_list[timerid], value); +} +compat_symbol (librt, __timer_gettime_old, timer_gettime, GLIBC_2_2); +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_settime.c new file mode 100644 index 000000000..4c945ec51 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_settime.c @@ -0,0 +1,40 @@ +/* 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 <shlib-compat.h> +#include "compat-timer.h" + + +#define timer_settime_alias __timer_settime_new +#include "../timer_settime.c" + +#undef timer_settime +versioned_symbol (librt, __timer_settime_new, timer_settime, GLIBC_2_3_3); + + +#if SHLIB_COMPAT (librt, GLIBC_2_2, GLIBC_2_3_3) +int +__timer_settime_old (int timerid, int flags, const struct itimerspec *value, +		     struct itimerspec *ovalue) +{ +  return __timer_settime_new (__compat_timer_list[timerid], flags, +			      value, ovalue); +} +compat_symbol (librt, __timer_settime_old, timer_settime, GLIBC_2_2); +#endif 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..f68d40439 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S @@ -0,0 +1,35 @@ +/* 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 <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 <sysdeps/unix/sysv/linux/x86_64/vfork.S> diff --git a/libpthread/nptl/sysdeps/x86_64/tls.h b/libpthread/nptl/sysdeps/x86_64/tls.h index 12da9dc81..3fc9b384a 100644 --- a/libpthread/nptl/sysdeps/x86_64/tls.h +++ b/libpthread/nptl/sysdeps/x86_64/tls.h @@ -1,5 +1,5 @@  /* Definition for thread-local data handling.  nptl/x86_64 version. -   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   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 @@ -82,11 +82,13 @@ typedef struct  # endif  #endif -/* This is the size of the initial TCB.  */ -# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) +/* This is the size of the initial TCB.  Can't be just sizeof (tcbhead_t), +   because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole +   struct pthread even when not linked with -lpthread.  */ +# define TLS_INIT_TCB_SIZE sizeof (struct pthread)  /* Alignment requirements for the initial TCB.  */ -# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)  /* This is the size of the TCB.  */  # define TLS_TCB_SIZE sizeof (struct pthread)  | 
