diff options
Diffstat (limited to 'libpthread')
272 files changed, 15380 insertions, 0 deletions
diff --git a/libpthread/ChangeLog b/libpthread/ChangeLog new file mode 100644 index 00000000..e991eac7 --- /dev/null +++ b/libpthread/ChangeLog @@ -0,0 +1,6 @@ +51839d398b0f9885a17ab5c0768b8dec4dd9eb79 is the last commit imported from CVS. +All commits after that one have valid author and committer information. + +Use this to examine the change log for earlier changes: + + $ git show 51839d398b0f9885a17ab5c0768b8dec4dd9eb79:ChangeLog diff --git a/libpthread/Makefile b/libpthread/Makefile new file mode 100644 index 00000000..2b895e88 --- /dev/null +++ b/libpthread/Makefile @@ -0,0 +1,248 @@ +# +# Copyright (C) 1994, 1995, 1996, 1997, 2000, 2002, 2004, 2005, 2006, 2007, +# 2008 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2, or (at +# your option) any later version. +# +# 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +dir := libpthread +makemode := library + +MICROKERNEL := mach +SYSDEPS := lockfile.c + +LCLHDRS := + +SRCS := pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ + pt-attr-getguardsize.c pt-attr-getinheritsched.c \ + pt-attr-getschedparam.c pt-attr-getschedpolicy.c pt-attr-getscope.c \ + pt-attr-getstack.c pt-attr-getstackaddr.c pt-attr-getstacksize.c \ + pt-attr-init.c pt-attr-setdetachstate.c pt-attr-setguardsize.c \ + pt-attr-setinheritsched.c pt-attr-setschedparam.c \ + pt-attr-setschedpolicy.c pt-attr-setscope.c pt-attr-setstack.c \ + pt-attr-setstackaddr.c pt-attr-setstacksize.c \ + \ + pt-barrier-destroy.c pt-barrier-init.c pt-barrier-wait.c \ + pt-barrier.c pt-barrierattr-destroy.c pt-barrierattr-init.c \ + pt-barrierattr-getpshared.c pt-barrierattr-setpshared.c \ + \ + pt-destroy-specific.c pt-init-specific.c \ + pt-key-create.c pt-key-delete.c \ + pt-getspecific.c pt-setspecific.c \ + \ + pt-once.c \ + \ + pt-alloc.c \ + pt-create.c \ + pt-getattr.c \ + pt-equal.c \ + pt-dealloc.c \ + pt-detach.c \ + pt-exit.c \ + pt-initialize.c \ + pt-join.c \ + pt-self.c \ + pt-sigmask.c \ + pt-spin-inlines.c \ + pt-cleanup.c \ + pt-setcancelstate.c \ + pt-setcanceltype.c \ + pt-testcancel.c \ + pt-cancel.c \ + \ + pt-mutexattr.c \ + pt-mutexattr-destroy.c pt-mutexattr-init.c \ + pt-mutexattr-getprioceiling.c pt-mutexattr-getprotocol.c \ + pt-mutexattr-getpshared.c pt-mutexattr-gettype.c \ + pt-mutexattr-setprioceiling.c pt-mutexattr-setprotocol.c \ + pt-mutexattr-setpshared.c pt-mutexattr-settype.c \ + \ + pt-mutex-init.c pt-mutex-destroy.c \ + pt-mutex-lock.c pt-mutex-trylock.c pt-mutex-timedlock.c \ + pt-mutex-unlock.c \ + pt-mutex-transfer-np.c \ + pt-mutex-getprioceiling.c pt-mutex-setprioceiling.c \ + \ + pt-rwlock-attr.c \ + pt-rwlockattr-init.c pt-rwlockattr-destroy.c \ + pt-rwlockattr-getpshared.c pt-rwlockattr-setpshared.c \ + \ + pt-rwlock-init.c pt-rwlock-destroy.c \ + pt-rwlock-rdlock.c pt-rwlock-tryrdlock.c \ + pt-rwlock-trywrlock.c pt-rwlock-wrlock.c \ + pt-rwlock-timedrdlock.c pt-rwlock-timedwrlock.c \ + pt-rwlock-unlock.c \ + \ + pt-cond.c \ + pt-condattr-init.c pt-condattr-destroy.c \ + pt-condattr-getclock.c pt-condattr-getpshared.c \ + pt-condattr-setclock.c pt-condattr-setpshared.c \ + \ + pt-cond-destroy.c pt-cond-init.c \ + pt-cond-brdcast.c \ + pt-cond-signal.c \ + pt-cond-wait.c \ + pt-cond-timedwait.c \ + \ + pt-stack-alloc.c \ + pt-thread-alloc.c \ + pt-thread-dealloc.c \ + pt-thread-start.c \ + pt-thread-halt.c \ + pt-startup.c \ + \ + pt-getconcurrency.c pt-setconcurrency.c \ + \ + pt-block.c \ + pt-timedblock.c \ + pt-wakeup.c \ + pt-docancel.c \ + pt-sysdep.c \ + pt-setup.c \ + pt-machdep.c \ + pt-spin.c \ + \ + pt-sigstate-init.c \ + pt-sigstate-destroy.c \ + pt-sigstate.c \ + \ + pt-atfork.c \ + pt-kill.c \ + pt-getcpuclockid.c \ + \ + pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c \ + pt-yield.c \ + \ + sem-close.c sem-destroy.c sem-getvalue.c sem-init.c sem-open.c \ + sem-post.c sem-timedwait.c sem-trywait.c sem-unlink.c \ + sem-wait.c \ + \ + cthreads-compat.c \ + $(SYSDEPS) + +OBJS = $(addsuffix .o,$(basename $(notdir $(SRCS)))) + +OTHERTAGS = + +libname = libpthread + +sysdeps_headers = \ + pthread.h \ + pthread/pthread.h \ + pthread/pthreadtypes.h \ + semaphore.h \ + \ + bits/pthread.h \ + bits/pthread-np.h \ + bits/mutex.h \ + bits/condition.h \ + bits/condition-attr.h \ + bits/spin-lock.h \ + bits/spin-lock-inline.h \ + bits/cancelation.h \ + bits/thread-attr.h \ + bits/barrier-attr.h \ + bits/barrier.h \ + bits/thread-specific.h \ + bits/once.h \ + bits/mutex-attr.h \ + bits/rwlock.h \ + bits/rwlock-attr.h \ + bits/semaphore.h + +SYSDEP_PATH = $(srcdir)/sysdeps/$(MICROKERNEL)/hurd/ia32 \ + $(srcdir)/sysdeps/$(MICROKERNEL)/ia32 \ + $(srcdir)/sysdeps/ia32 \ + $(srcdir)/sysdeps/$(MICROKERNEL)/hurd \ + $(srcdir)/sysdeps/$(MICROKERNEL) \ + $(srcdir)/sysdeps/hurd \ + $(srcdir)/sysdeps/generic \ + $(srcdir)/sysdeps/posix \ + $(srcdir)/pthread \ + $(srcdir)/include + +VPATH += $(SYSDEP_PATH) + +HURDLIBS = ihash + +installhdrs := +installhdrsubdir := . + +include ../Makeconf + +CPPFLAGS += \ + $(addprefix -I, $(SYSDEP_PATH)) \ + -imacros $(srcdir)/include/libc-symbols.h \ + -imacros $(srcdir)/not-in-libc.h + + +install: install-headers $(libdir)/libpthread2.a $(libdir)/libpthread2_pic.a +install-headers: $(addprefix $(includedir)/, $(sysdeps_headers)) + +# XXX: If $(libdir)/libpthread2.a is installed and +# $(libdir)/libpthread is not, we can have some issues. +.PHONY: $(libdir)/libpthread.a $(libdir)/libpthread_pic.a + +# XXX: These rules are a hack. But it is better than messing with +# ../Makeconf at the moment. Note that the linker scripts +# $(srcdir)/libpthread.a and $(srcdir)/libpthread_pic.a get overwritten +# when building in $(srcdir) and not a seperate build directory. +$(libdir)/libpthread2.a: $(libdir)/libpthread.a + mv $< $@ + $(INSTALL_DATA) $(srcdir)/libpthread.a $< + +$(libdir)/libpthread2_pic.a: $(libdir)/libpthread_pic.a + mv $< $@ + $(INSTALL_DATA) $(srcdir)/libpthread_pic.a $< + +.PHONY: $(addprefix $(includedir)/, $(sysdeps_headers)) + +$(addprefix $(includedir)/, $(sysdeps_headers)): + @set -e; \ + t="$@"; \ + t=$${t#$(includedir)/}; \ + header_ok=0; \ + for dir in $(SYSDEP_PATH); \ + do \ + if test -e "$$dir/$$t"; \ + then \ + tdir=`dirname "$@"`; \ + if test ! -e $$tdir; \ + then \ + mkdir $$tdir; \ + fi; \ + echo $(INSTALL_DATA) "$$dir/$$t" "$@"; \ + $(INSTALL_DATA) "$$dir/$$t" "$@"; \ + header_ok=1; \ + break; \ + fi; \ + done; \ + if test "$${header_ok}" -ne 1; \ + then \ + echo; \ + echo '*** 'The header file \`$@\' is required, but not \ +provided, by; \ + echo '*** 'this configuration. Please report this to the \ +maintainer.; \ + echo; \ + false; \ + fi + +# ifeq ($(VERSIONING),yes) +# +# # Adding this dependency gets it included in the command line, +# # where ld will read it as a linker script. +# $(libname).so.$(hurd-version): $(srcdir)/$(libname).map +# +# endif diff --git a/libpthread/Makefile.am b/libpthread/Makefile.am new file mode 100644 index 00000000..e1c062c1 --- /dev/null +++ b/libpthread/Makefile.am @@ -0,0 +1,168 @@ +# Makefile.am - Makefile template for libpthread. +# Copyright (C) 2003, 2008 Free Software Foundation, Inc. +# +# This file is part of the GNU Hurd. +# +# The GNU Hurd is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# The GNU Hurd is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +if ARCH_IA32 + arch=ia32 +endif +if ARCH_POWERPC + arch=powerpc +endif + +# The source files are scattered over several directories. Add +# all these directories to the vpath. +SYSDEP_PATH = $(srcdir)/sysdeps/l4/hurd/${arch} \ + $(srcdir)/sysdeps/l4/${arch} \ + $(srcdir)/sysdeps/${arch} \ + $(srcdir)/sysdeps/l4/hurd \ + $(srcdir)/sysdeps/l4 \ + $(srcdir)/sysdeps/hurd \ + $(srcdir)/sysdeps/generic \ + $(srcdir)/sysdeps/posix \ + $(srcdir)/pthread \ + $(srcdir)/signal \ + $(srcdir)/include +vpath %.c $(SYSDEP_PATH) + +AM_CPPFLAGS = $(USER_CPPFLAGS) -I$(srcdir)/pthread \ + $(addprefix -I, $(SYSDEP_PATH)) -imacros $(srcdir)/include/libc-symbols.h +AM_CFLAGS = $(USER_CFLAGS) + +# Sources. +SYSDEPS := lockfile.c + +if ! ENABLE_TESTS +noinst_LIBRARIES = libpthread.a +endif + +libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ + pt-attr-getguardsize.c pt-attr-getinheritsched.c \ + pt-attr-getschedparam.c pt-attr-getschedpolicy.c pt-attr-getscope.c \ + pt-attr-getstack.c pt-attr-getstackaddr.c pt-attr-getstacksize.c \ + pt-attr-init.c pt-attr-setdetachstate.c pt-attr-setguardsize.c \ + pt-attr-setinheritsched.c pt-attr-setschedparam.c \ + pt-attr-setschedpolicy.c pt-attr-setscope.c pt-attr-setstack.c \ + pt-attr-setstackaddr.c pt-attr-setstacksize.c pt-attr.c \ + pt-barrier-destroy.c pt-barrier-init.c pt-barrier-wait.c \ + pt-barrier.c pt-barrierattr-destroy.c pt-barrierattr-init.c \ + pt-barrierattr-getpshared.c pt-barrierattr-setpshared.c \ + pt-destroy-specific.c pt-init-specific.c \ + pt-key-create.c pt-key-delete.c \ + pt-getspecific.c pt-setspecific.c \ + pt-once.c \ + pt-alloc.c \ + pt-create.c \ + pt-getattr.c \ + pt-pool-np.c \ + pt-equal.c \ + pt-dealloc.c \ + pt-detach.c \ + pt-exit.c \ + pt-initialize.c \ + pt-join.c \ + pt-self.c \ + pt-sigmask.c \ + pt-spin-inlines.c \ + pt-cleanup.c \ + pt-setcancelstate.c \ + pt-setcanceltype.c \ + pt-testcancel.c \ + pt-cancel.c \ + pt-mutexattr.c \ + pt-mutexattr-destroy.c pt-mutexattr-init.c \ + pt-mutexattr-getprioceiling.c pt-mutexattr-getprotocol.c \ + pt-mutexattr-getpshared.c pt-mutexattr-gettype.c \ + pt-mutexattr-setprioceiling.c pt-mutexattr-setprotocol.c \ + pt-mutexattr-setpshared.c pt-mutexattr-settype.c \ + pt-mutex-init.c pt-mutex-destroy.c \ + pt-mutex-lock.c pt-mutex-trylock.c pt-mutex-timedlock.c \ + pt-mutex-unlock.c \ + pt-mutex-transfer-np.c \ + pt-mutex-getprioceiling.c pt-mutex-setprioceiling.c \ + pt-rwlock-attr.c \ + pt-rwlockattr-init.c pt-rwlockattr-destroy.c \ + pt-rwlockattr-getpshared.c pt-rwlockattr-setpshared.c \ + pt-rwlock-init.c pt-rwlock-destroy.c \ + pt-rwlock-rdlock.c pt-rwlock-tryrdlock.c \ + pt-rwlock-trywrlock.c pt-rwlock-wrlock.c \ + pt-rwlock-timedrdlock.c pt-rwlock-timedwrlock.c \ + pt-rwlock-unlock.c \ + pt-cond.c \ + pt-condattr-init.c pt-condattr-destroy.c \ + pt-condattr-getclock.c pt-condattr-getpshared.c \ + pt-condattr-setclock.c pt-condattr-setpshared.c \ + pt-cond-destroy.c pt-cond-init.c \ + pt-cond-brdcast.c \ + pt-cond-signal.c \ + pt-cond-wait.c \ + pt-cond-timedwait.c \ + pt-stack-alloc.c \ + pt-thread-alloc.c \ + pt-thread-dealloc.c \ + pt-thread-start.c \ + pt-thread-halt.c \ + pt-startup.c \ + pt-getconcurrency.c pt-setconcurrency.c \ + pt-block.c \ + pt-timedblock.c \ + pt-wakeup.c \ + pt-docancel.c \ + pt-sysdep.c \ + pt-setup.c \ + pt-machdep.c \ + pt-spin.c \ + pt-sigstate-init.c \ + pt-sigstate-destroy.c \ + pt-sigstate.c \ + pt-atfork.c \ + pt-kill.c \ + pt-getcpuclockid.c \ + pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c \ + pt-yield.c \ + sem-close.c sem-init.c sem-timedwait.c sem-wait.c \ + sem-destroy.c sem-open.c sem-trywait.c sem-getvalue.c \ + sem-post.c sem-unlink.c \ + \ + pt-setactivity-np.c \ + \ + kill.c \ + killpg.c \ + pt-kill-siginfo-np.c \ + raise.c \ + sigaction.c \ + sigaddset.c \ + sigaltstack.c \ + sigdelset.c \ + sigemptyset.c \ + sigfillset.c \ + sig-internal.c \ + sig-internal.h \ + siginterrupt.c \ + sigismember.c \ + signal.c \ + signal-dispatch.c \ + signal.h \ + sigpending.c \ + sigprocmask.c \ + sigsuspend.c \ + sigtimedwait.c \ + sigwait.c \ + sigwaiter.c \ + sigwaitinfo.c \ + signal-dispatch-lowlevel.c \ + sigprocmask.c diff --git a/libpthread/TODO b/libpthread/TODO new file mode 100644 index 00000000..45b4cdc2 --- /dev/null +++ b/libpthread/TODO @@ -0,0 +1,174 @@ +-*- Mode: outline -*- + +* Interfaces +** All interfaces specified by IEEE Std 1003.1-2001 are present, however, + pthread_kill and pthread_sigmask are defined in <pthread.h> and not + <signal.h> as they should be. Once we are compiled with glibc, + this should be eaiser. + +* Test cases. Can never have enough. + +* Ports + Port to other kernels (e.g. Linux and FreeBSD) and test on other + platforms. + +* Implementation details +** pthread_atfork + This cannot be implemented without either changing glibc to export + some hooks (c.f. libc/sysdeps/mach/hurd/fork.c) or by providing a + custom fork implementation that wraps the origial using dlopen et + al. + +** Scheduling and priorities + + We do not support scheduling right now in any way what so ever. + + This affects: + pthread_attr_getinheritsched + pthread_attr_setinheritsched + pthread_attr_getschedparam + pthread_attr_setschedparam + pthread_attr_getschedpolicy + pthread_attr_setschedpolicy + pthread_attr_getscope + pthread_attr_setscope + + pthread_mutexattr_getprioceiling + pthread_mutexattr_setprioceiling + pthread_mutexattr_getprotocol + pthread_mutexattr_setprotocol + pthread_mutex_getprioceiling + pthread_mutex_setprioceiling + + pthread_setschedprio + pthread_getschedparam + pthread_setschedparam + +** Alternate stacks + + Supporting alternate stacks (via pthread_attr_getstackaddr, + pthread_attr_setstackaddr, pthread_attr_getstack, + pthread_attr_setstack, pthread_attr_getstacksize and + pthread_attr_setstacksize) is no problem as long as they are of the + correct size and have the correct alignment. This is due to + limitations in the Hurd TSD implementation + (c.f. <hurd/threadvar.h>). + +** Cancelation +*** Cancelation points + The only cancelation points are pthread_join, pthread_cond_wait, + pthead_cond_timedwait and pthread_testcancel. Need to explore if + the hurd_sigstate->cancel_hook (c.f. <hurd/signal.h>) provides the + desired semantics. If not, must either wrap the some functions + using dlsym or wait until integration with glibc. +*** Async cancelation + We inject a new IP into the cancelled (running) thread and then + run the cancelation handlers + (c.f. sysdeps/mach/hurd/pt-docancel.c). The handlers need to have + access to the stack as they may use local variables. I think that + this method may leave the frame pointer in a corrupted state if + the thread was in, for instance, the middle of a function call. + The robustness needs to be confirmed. + +** Process Shared Attribute + + Currently, there is no real support for the process shared + attribute. spinlocks work because we just use a test and set loop, + however, barriers, conditions mutexes and rwlocks, however, signal + wakeups via ports of which the names are process local. + + We could have some process local data that is hashed to via the + address of the data structure. Then the first thread that blocks + per process would spin on the shared memory area and all others + would then block as normal. When the resource became available, + the first thread would signal the other local threads as necessary. + Alternatively, there could be some server, however, this opens a + new question: what can we use as an authentication agent. + +** Locking algorithm + + When a thread blocks, it puts itself on a queue and then waits for + a message on a thread local port. The thread which eventually does + the wakeup sends a message to the waiter thereby waking it up. If + the wakeup is a broadcast wakeup (e.g. pthread_cond_broadcast, + pthread_barrier_wait and pthread_rdlock_unlock), the thread must + send O(N) messages where N is the number of waiting threads. If + all the threads instead received on a lock local (rather than + thread local) port then the thread which eventually does the wake + need just do one operation, mach_port_destroy and all of the + waiting threads would wakeup and get MACH_RCV_PORT_DIED back from + mach_msg. Note that the trade off is that the port must be + recreated. This needs to be benchmarked. + + A possible problem with this is scheduling priorities. There may + be a preference for certain threads to wakeup before others + (especially if we are not doing a broadcast, for instance, + pthread_mutex_unlock and pthread_cond_signal). If we take this + approach, the kernel chooses which threads are awakened. If we + find that the kernel makes the wrong choices, we can still overcome + this by merging the two algorithms: have a list of ports sorted in + priority order and the waker does a mach_port_destroy on each as + appropriate. + +** Barriers + + Barriers can be very slow and the contention can be very high. The + above algorithm is very appealing, however, this may be augmented + with an initial number of spins and yields. It is expected that + all of the threads reach the barrier within close succession, thus + queuing a message may be more expensive. This needs to be + benchmarked. + +** Clocks +*** pthread_condattr_setclock allows a process to specify a clock for + use with pthread_cond_timedwaits. What is the correct default for + this, right now, we use CLOCK_REALTIME, however, we are really + using the system clock which, if I understand correctly, is + completely different. +*** Could we even use other clocks? mach_msg uses a relative time against + the system clock. +*** pthread_getcpuclockid just returns CLOCK_THREAD_CPUTIME_ID if defined. + Is this the correct behavior? + +** Timed Blocking +*** pthread_cond_timedwait, pthead_mutex_timedlock, pthread_rwlock_timedrdlock + and pthread_rwlock_timedwrlock all take absolute times. We need + to convert them to relative times for mach_msg. Is there a way + around this? How will clock skew affect us? + +** weak aliases + Use them consistently and correctly and start by reading + http://sources.redhat.com/ml/libc-alpha/2002-08/msg00278.html. + +* L4 Specific Issues +** Stack +*** Size + The stack size is defined to be a single page in + sysdeps/l4/hurd/pt-sysdep.h. Once we are able to setup regions, + this can be expanded to two megs as suggested by the Mach version. + Until then, however, we need to allocate too much physical memory. +*** Deallocation + __thread_stack_dealloc currently does not deallocate the stack. + For a proper implementation, we need a working memory manager. + +** Scheduling +*** yield + [L4] We cannot use yield for spin locks as L4 only yields to threads of + priority which are greater than or equal to the yielding thread. + If there are threads of lower priority, they are not considered; + the yielding thread is just placed back on the processor. This + introduces priority inversion quite quickly. L4 will not add a + priority suppression function call. As such, we need to do + an ipc with a small time out and then use exponential back off to + do the actual waiting. This sucks. + +** Stub code + [L4] We include <task_client.h> in pt-start.c, however, we need a library + so we do not have to play with the corba stuff. + +** Root server and Task server +*** Getting the tids. + pt-start.c has a wonderfully evil hack that will never work well. + +** Paging + We set the pager to the root server. Evil. Fix this in pt-start.c. diff --git a/libpthread/headers.m4 b/libpthread/headers.m4 new file mode 100644 index 00000000..5a58b9bf --- /dev/null +++ b/libpthread/headers.m4 @@ -0,0 +1,45 @@ +# headers.m4 - Autoconf snippets to install links for header files. +# Copyright 2003, 2008 Free Software Foundation, Inc. +# Written by Marcus Brinkmann <marcus@gnu.org>. +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +AC_CONFIG_LINKS([ + sysroot/include/pthread.h:libpthread/include/pthread.h + sysroot/include/pthread/pthread.h:libpthread/include/pthread/pthread.h + sysroot/include/pthread/pthreadtypes.h:libpthread/include/pthread/pthreadtypes.h + sysroot/include/bits/memory.h:libpthread/sysdeps/${arch}/bits/memory.h + sysroot/include/bits/spin-lock.h:libpthread/sysdeps/${arch}/bits/spin-lock.h + sysroot/include/bits/spin-lock-inline.h:libpthread/sysdeps/${arch}/bits/spin-lock-inline.h + sysroot/include/bits/pthreadtypes.h:libpthread/sysdeps/generic/bits/pthreadtypes.h + sysroot/include/bits/barrier-attr.h:libpthread/sysdeps/generic/bits/barrier-attr.h + sysroot/include/bits/barrier.h:libpthread/sysdeps/generic/bits/barrier.h + sysroot/include/bits/cancelation.h:libpthread/sysdeps/generic/bits/cancelation.h + sysroot/include/bits/condition-attr.h:libpthread/sysdeps/generic/bits/condition-attr.h + sysroot/include/bits/condition.h:libpthread/sysdeps/generic/bits/condition.h + sysroot/include/bits/mutex-attr.h:libpthread/sysdeps/generic/bits/mutex-attr.h + sysroot/include/bits/mutex.h:libpthread/sysdeps/generic/bits/mutex.h + sysroot/include/bits/once.h:libpthread/sysdeps/generic/bits/once.h + sysroot/include/bits/pthread.h:libpthread/sysdeps/generic/bits/pthread.h + sysroot/include/bits/rwlock-attr.h:libpthread/sysdeps/generic/bits/rwlock-attr.h + sysroot/include/bits/rwlock.h:libpthread/sysdeps/generic/bits/rwlock.h + sysroot/include/bits/thread-attr.h:libpthread/sysdeps/generic/bits/thread-attr.h + sysroot/include/bits/thread-barrier.h:libpthread/sysdeps/generic/bits/thread-barrier.h + sysroot/include/bits/thread-specific.h:libpthread/sysdeps/generic/bits/thread-specific.h + sysroot/include/bits/pthread-np.h:libpthread/sysdeps/l4/hurd/bits/pthread-np.h + sysroot/include/semaphore.h:libpthread/include/semaphore.h + sysroot/include/bits/semaphore.h:libpthread/sysdeps/generic/bits/semaphore.h + sysroot/include/signal.h:libpthread/signal/signal.h +]) + +AC_CONFIG_COMMANDS_POST([ + mkdir -p sysroot/lib libpthread && + ln -sf ../../libpthread/libpthread.a sysroot/lib/ && + touch libpthread/libpthread.a +]) diff --git a/libpthread/include/libc-symbols.h b/libpthread/include/libc-symbols.h new file mode 100644 index 00000000..54dd6e26 --- /dev/null +++ b/libpthread/include/libc-symbols.h @@ -0,0 +1,395 @@ +/* Support macros for making weak and strong aliases for symbols, + and for using symbol sets and linker warnings with GNU ld. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2008 + 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 _LIBC_SYMBOLS_H +#define _LIBC_SYMBOLS_H 1 + +/* This file's macros are included implicitly in the compilation of every + file in the C library by -imacros. + + We include config.h which is generated by configure. + It should define for us the following symbols: + + * HAVE_ASM_SET_DIRECTIVE if we have `.set B, A' instead of `A = B'. + * ASM_GLOBAL_DIRECTIVE with `.globl' or `.global'. + * HAVE_GNU_LD if using GNU ld, with support for weak symbols in a.out, + and for symbol set and warning messages extensions in a.out and ELF. + * HAVE_ELF if using ELF, which supports weak symbols using `.weak'. + * HAVE_ASM_WEAK_DIRECTIVE if we have weak symbols using `.weak'. + * HAVE_ASM_WEAKEXT_DIRECTIVE if we have weak symbols using `.weakext'. + + */ + +/* This is defined for the compilation of all C library code. features.h + tests this to avoid inclusion of stubs.h while compiling the library, + before stubs.h has been generated. Some library code that is shared + with other packages also tests this symbol to see if it is being + compiled as part of the C library. We must define this before including + config.h, because it makes some definitions conditional on whether libc + itself is being compiled, or just some generator program. */ +// #define _LIBC 1 + +/* Enable declarations of GNU extensions, since we are compiling them. */ +#define _GNU_SOURCE 1 +/* And we also need the data for the reentrant functions. */ +#define _REENTRANT 1 + +// #include <config.h> +#define HAVE_ASM_WEAK_DIRECTIVE +#define HAVE_WEAK_SYMBOLS +#define HAVE_ASM_SET_DIRECTIVE +#define HAVE_BUILTIN_EXPECT +#define HAVE_GNU_LD +#define HAVE_ELF +#define HAVE_SECTION_QUOTES +#define HAVE_VISIBILITY_ATTRIBUTE +#define HAVE_ASM_PREVIOUS_DIRECTIVE +// #define SHARED + +/* The symbols in all the user (non-_) macros are C symbols. + HAVE_GNU_LD without HAVE_ELF implies a.out. */ + +#if defined HAVE_ASM_WEAK_DIRECTIVE || defined HAVE_ASM_WEAKEXT_DIRECTIVE +# define HAVE_WEAK_SYMBOLS +#endif + +#ifndef __SYMBOL_PREFIX +# ifdef NO_UNDERSCORES +# define __SYMBOL_PREFIX +# else +# define __SYMBOL_PREFIX "_" +# endif +#endif + +#ifndef C_SYMBOL_NAME +# ifdef NO_UNDERSCORES +# define C_SYMBOL_NAME(name) name +# else +# define C_SYMBOL_NAME(name) _##name +# endif +#endif + +#ifndef ASM_LINE_SEP +# define ASM_LINE_SEP ; +#endif + +#ifndef C_SYMBOL_DOT_NAME +# define C_SYMBOL_DOT_NAME(name) .##name +#endif + +#ifndef __ASSEMBLER__ +/* GCC understands weak symbols and aliases; use its interface where + possible, instead of embedded assembly language. */ + +/* Define ALIASNAME as a strong alias for NAME. */ +# define strong_alias(name, aliasname) _strong_alias(name, aliasname) +# define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); + +/* This comes between the return type and function name in + a function definition to make that definition weak. */ +# define weak_function __attribute__ ((weak)) +# define weak_const_function __attribute__ ((weak, __const__)) + +# ifdef HAVE_WEAK_SYMBOLS + +/* Define ALIASNAME as a weak alias for NAME. + If weak aliases are not available, this defines a strong alias. */ +# define weak_alias(name, aliasname) _weak_alias (name, aliasname) +# define _weak_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))); + +/* Declare SYMBOL as weak undefined symbol (resolved to 0 if not defined). */ +# define weak_extern(symbol) _weak_extern (symbol) +# ifdef HAVE_ASM_WEAKEXT_DIRECTIVE +# define _weak_extern(symbol) asm (".weakext " __SYMBOL_PREFIX #symbol); +# else +# define _weak_extern(symbol) asm (".weak " __SYMBOL_PREFIX #symbol); +# endif + +# else + +# define weak_alias(name, aliasname) strong_alias(name, aliasname) +# define weak_extern(symbol) /* Nothing. */ + +# endif + +#else /* __ASSEMBLER__ */ + +# ifdef HAVE_ASM_SET_DIRECTIVE +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME (alias),C_SYMBOL_NAME (original) +# else +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) ASM_LINE_SEP \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_DOT_NAME (alias) = C_SYMBOL_DOT_NAME (original) +# else +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) +# endif +# endif + +# ifdef HAVE_WEAK_SYMBOLS +# ifdef HAVE_ASM_WEAKEXT_DIRECTIVE +# define weak_alias(original, alias) \ + .weakext C_SYMBOL_NAME (alias), C_SYMBOL_NAME (original) +# define weak_extern(symbol) \ + .weakext C_SYMBOL_NAME (symbol) + +# else /* ! HAVE_ASM_WEAKEXT_DIRECTIVE */ + +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define weak_alias(original, alias) \ + .weak C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) ASM_LINE_SEP \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_DOT_NAME (alias) = C_SYMBOL_DOT_NAME (original) +# else +# define weak_alias(original, alias) \ + .weak C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) +# endif + +# define weak_extern(symbol) \ + .weak C_SYMBOL_NAME (symbol) + +# endif /* ! HAVE_ASM_WEAKEXT_DIRECTIVE */ + +# else /* ! HAVE_WEAK_SYMBOLS */ + +# define weak_alias(original, alias) strong_alias(original, alias) +# define weak_extern(symbol) /* Nothing */ +# endif /* ! HAVE_WEAK_SYMBOLS */ + +#endif /* __ASSEMBLER__ */ + +/* On some platforms we can make internal function calls (i.e., calls of + functions not exported) a bit faster by using a different calling + convention. */ +#ifndef internal_function +# define internal_function /* empty */ +#endif + +/* Prepare for the case that `__builtin_expect' is not available. */ +#ifndef HAVE_BUILTIN_EXPECT +# define __builtin_expect(expr, val) (expr) +#endif + +/* Determine the return address. */ +#define RETURN_ADDRESS(nr) \ + __builtin_extract_return_addr (__builtin_return_address (nr)) + +/* When a reference to SYMBOL is encountered, the linker will emit a + warning message MSG. */ +#ifdef HAVE_GNU_LD +# ifdef HAVE_ELF + +/* We want the .gnu.warning.SYMBOL section to be unallocated. */ +# ifdef HAVE_ASM_PREVIOUS_DIRECTIVE +# define __make_section_unallocated(section_string) \ + asm (".section " section_string "\n\t.previous"); +# elif defined HAVE_ASM_POPSECTION_DIRECTIVE +# define __make_section_unallocated(section_string) \ + asm (".pushsection " section_string "\n\t.popsection"); +# else +# define __make_section_unallocated(section_string) +# endif + +/* Tacking on "\n\t#" to the section name makes gcc put it's bogus + section attributes on what looks like a comment to the assembler. */ +# ifdef HAVE_SECTION_QUOTES +# define link_warning(symbol, msg) \ + __make_section_unallocated (".gnu.warning." #symbol) \ + static const char __evoke_link_warning_##symbol[] \ + __attribute__ ((unused, section (".gnu.warning." #symbol "\"\n\t#\""))) \ + = msg; +# else +# define link_warning(symbol, msg) \ + __make_section_unallocated (".gnu.warning." #symbol) \ + static const char __evoke_link_warning_##symbol[] \ + __attribute__ ((unused, section (".gnu.warning." #symbol "\n\t#"))) = msg; +# endif +# else /* Not ELF: a.out */ +# ifdef HAVE_XCOFF +/* XCOFF does not support .stabs. + The native aix linker will remove the .stab and .stabstr sections + The gnu linker will have a fatal error if there is a relocation for + symbol in the .stab section. Silently disable this macro. */ +# define link_warning(symbol, msg) +# else +# define link_warning(symbol, msg) \ + asm (".stabs \"" msg "\",30,0,0,0\n\t" \ + ".stabs \"" __SYMBOL_PREFIX #symbol "\",1,0,0,0\n"); +# endif /* XCOFF */ +# endif +#else +/* We will never be heard; they will all die horribly. */ +# define link_warning(symbol, msg) +#endif + +/* A canned warning for sysdeps/stub functions. */ +#define stub_warning(name) \ + link_warning (name, \ + "warning: " #name " is not implemented and will always fail") + +/* + +*/ + +#ifdef HAVE_GNU_LD + +/* Symbol set support macros. */ + +# ifdef HAVE_ELF + +/* Make SYMBOL, which is in the text segment, an element of SET. */ +# define text_set_element(set, symbol) _elf_set_element(set, symbol) +/* Make SYMBOL, which is in the data segment, an element of SET. */ +# define data_set_element(set, symbol) _elf_set_element(set, symbol) +/* Make SYMBOL, which is in the bss segment, an element of SET. */ +# define bss_set_element(set, symbol) _elf_set_element(set, symbol) + +/* These are all done the same way in ELF. + There is a new section created for each set. */ +# ifdef SHARED +/* When building a shared library, make the set section writable, + because it will need to be relocated at run time anyway. */ +# define _elf_set_element(set, symbol) \ + static const void *__elf_set_##set##_element_##symbol##__ \ + __attribute__ ((unused, section (#set))) = &(symbol) +# else +# define _elf_set_element(set, symbol) \ + static const void *const __elf_set_##set##_element_##symbol##__ \ + __attribute__ ((unused, section (#set))) = &(symbol) +# endif + +/* Define SET as a symbol set. This may be required (it is in a.out) to + be able to use the set's contents. */ +# define symbol_set_define(set) symbol_set_declare(set) + +/* Declare SET for use in this module, if defined in another module. */ +# define symbol_set_declare(set) \ + extern void *const __start_##set __attribute__ ((__weak__)); \ + extern void *const __stop_##set __attribute__ ((__weak__)); \ + weak_extern (__start_##set) weak_extern (__stop_##set) + +/* Return a pointer (void *const *) to the first element of SET. */ +# define symbol_set_first_element(set) (&__start_##set) + +/* Return true iff PTR (a void *const *) has been incremented + past the last element in SET. */ +# define symbol_set_end_p(set, ptr) ((ptr) >= &__stop_##set) + +# else /* Not ELF: a.out. */ + +# ifdef HAVE_XCOFF +/* XCOFF does not support .stabs. + The native aix linker will remove the .stab and .stabstr sections + The gnu linker will have a fatal error if there is a relocation for + symbol in the .stab section. Silently disable these macros. */ +# define text_set_element(set, symbol) +# define data_set_element(set, symbol) +# define bss_set_element(set, symbol) +# else +# define text_set_element(set, symbol) \ + asm (".stabs \"" __SYMBOL_PREFIX #set "\",23,0,0," __SYMBOL_PREFIX #symbol) +# define data_set_element(set, symbol) \ + asm (".stabs \"" __SYMBOL_PREFIX #set "\",25,0,0," __SYMBOL_PREFIX #symbol) +# define bss_set_element(set, symbol) ?error Must use initialized data. +# endif /* XCOFF */ +# define symbol_set_define(set) void *const (set)[1]; +# define symbol_set_declare(set) extern void *const (set)[1]; + +# define symbol_set_first_element(set) &(set)[1] +# define symbol_set_end_p(set, ptr) (*(ptr) == 0) + +# endif /* ELF. */ +#else +/* We cannot do anything in generial. */ +# define text_set_element(set, symbol) asm ("") +# define data_set_element(set, symbol) asm ("") +# define bss_set_element(set, symbol) asm ("") +# define symbol_set_define(set) void *const (set)[1]; +# define symbol_set_declare(set) extern void *const (set)[1]; + +# define symbol_set_first_element(set) &(set)[1] +# define symbol_set_end_p(set, ptr) (*(ptr) == 0) +#endif /* Have GNU ld. */ + +#if DO_VERSIONING +# define symbol_version(real, name, version) \ + _symbol_version(real, name, version) +# define default_symbol_version(real, name, version) \ + _default_symbol_version(real, name, version) +# ifdef __ASSEMBLER__ +# define _symbol_version(real, name, version) \ + .symver real, name##@##version +# define _default_symbol_version(real, name, version) \ + .symver real, name##@##@##version +# else +# define _symbol_version(real, name, version) \ + __asm__ (".symver " #real "," #name "@" #version) +# define _default_symbol_version(real, name, version) \ + __asm__ (".symver " #real "," #name "@@" #version) +# endif +#else +# define symbol_version(real, name, version) +# define default_symbol_version(real, name, version) \ + strong_alias(real, name) +#endif + +#if defined HAVE_VISIBILITY_ATTRIBUTE && defined SHARED +# define attribute_hidden __attribute__ ((visibility ("hidden"))) +#else +# define attribute_hidden +#endif + +/* Handling on non-exported internal names. We have to do this only + for shared code. */ +#ifdef SHARED +# define INTUSE(name) name##_internal +# define INTDEF(name) strong_alias (name, name##_internal) +# define INTVARDEF(name) \ + _INTVARDEF (name, name##_internal) +# if defined HAVE_VISIBILITY_ATTRIBUTE +# define _INTVARDEF(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name), \ + visibility ("hidden"))); +# else +# define _INTVARDEF(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); +# endif +# define INTDEF2(name, newname) strong_alias (name, newname##_internal) +# define INTVARDEF2(name, newname) _INTVARDEF (name, newname##_internal) +#else +# define INTUSE(name) name +# define INTDEF(name) +# define INTVARDEF(name) +# define INTDEF2(name, newname) +# define INTVARDEF2(name, newname) +#endif + +#endif /* libc-symbols.h */ diff --git a/libpthread/include/pthread.h b/libpthread/include/pthread.h new file mode 100644 index 00000000..1d4d3c7b --- /dev/null +++ b/libpthread/include/pthread.h @@ -0,0 +1,7 @@ +#ifndef _PTHREAD_H +#include <pthread/pthread.h> + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +#endif diff --git a/libpthread/include/pthread/pthread.h b/libpthread/include/pthread/pthread.h new file mode 100644 index 00000000..e6b92495 --- /dev/null +++ b/libpthread/include/pthread/pthread.h @@ -0,0 +1,754 @@ +/* Copyright (C) 2000, 2002, 2005, 2006, 2007, 2008, 2009, 2010 + 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. */ + +/* + * POSIX Threads Extension: ??? <pthread.h> + */ + +#ifndef _PTHREAD_H +#define _PTHREAD_H 1 + +#include <features.h> + +#include <sys/cdefs.h> +#ifndef __extern_inline +/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 + inline semantics, unless -fgnu89-inline is used. */ +# if !defined __cplusplus || __GNUC_PREREQ (4,3) +# if defined __GNUC_STDC_INLINE__ || defined __cplusplus +# define __extern_inline extern __inline __attribute__ ((__gnu_inline__)) +# if __GNUC_PREREQ (4,3) +# define __extern_always_inline \ + extern __always_inline __attribute__ ((__gnu_inline__, __artificial__)) +# else +# define __extern_always_inline \ + extern __always_inline __attribute__ ((__gnu_inline__)) +# endif +# else +# define __extern_inline extern __inline +# define __extern_always_inline extern __always_inline +# endif +# endif +#endif + +#include <sched.h> + +__BEGIN_DECLS + +#include <pthread/pthreadtypes.h> + +#include <bits/pthread.h> + +/* Possible values for the process shared attribute. */ +#define PTHREAD_PROCESS_PRIVATE __PTHREAD_PROCESS_PRIVATE +#define PTHREAD_PROCESS_SHARED __PTHREAD_PROCESS_SHARED + + +/* Thread attributes. */ + +/* Possible values for the inheritsched attribute. */ +#define PTHREAD_EXPLICIT_SCHED __PTHREAD_EXPLICIT_SCHED +#define PTHREAD_INHERIT_SCHED __PTHREAD_INHERIT_SCHED + +/* Possible values for the `contentionscope' attribute. */ +#define PTHREAD_SCOPE_SYSTEM __PTHREAD_SCOPE_SYSTEM +#define PTHREAD_SCOPE_PROCESS __PTHREAD_SCOPE_PROCESS + +/* Possible values for the `detachstate' attribute. */ +#define PTHREAD_CREATE_JOINABLE __PTHREAD_CREATE_JOINABLE +#define PTHREAD_CREATE_DETACHED __PTHREAD_CREATE_DETACHED + +#include <bits/thread-attr.h> + +/* Initialize the thread attribute object in *ATTR to the default + values. */ +extern int pthread_attr_init (pthread_attr_t *attr); + +/* Destroy the thread attribute object in *ATTR. */ +extern int pthread_attr_destroy (pthread_attr_t *attr); + + +/* Return the value of the inheritsched attribute in *ATTR in + *INHERITSCHED. */ +extern int pthread_attr_getinheritsched (const pthread_attr_t *__restrict attr, + int *__restrict inheritsched); + +/* Set the value of the inheritsched attribute in *ATTR to + INHERITSCHED. */ +extern int pthread_attr_setinheritsched (pthread_attr_t *attr, + int inheritsched); + + +/* Return the value of the schedparam attribute in *ATTR in *PARAM. */ +extern int pthread_attr_getschedparam (const pthread_attr_t *__restrict attr, + struct sched_param *__restrict param); + +/* Set the value of the schedparam attribute in *ATTR to PARAM. */ +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict attr, + const struct sched_param *__restrict param); + + +/* Return the value of the schedpolicy attribute in *ATTR to *POLICY. */ +extern int pthread_attr_getschedpolicy (const pthread_attr_t *__restrict attr, + int *__restrict policy); + +/* Set the value of the schedpolicy attribute in *ATTR to POLICY. */ +extern int pthread_attr_setschedpolicy (pthread_attr_t *attr, + int policy); + + +/* Return the value of the contentionscope attribute in *ATTR in + *CONTENTIONSCOPE. */ +extern int pthread_attr_getscope (const pthread_attr_t *__restrict attr, + int *__restrict contentionscope); + +/* Set the value of the contentionscope attribute in *ATTR to + CONTENTIONSCOPE. */ +extern int pthread_attr_setscope (pthread_attr_t *attr, + int contentionscope); + + +/* Return the value of the stackaddr attribute in *ATTR in + *STACKADDR. */ +extern int pthread_attr_getstackaddr (const pthread_attr_t *__restrict attr, + void **__restrict stackaddr); + +/* Set the value of the stackaddr attribute in *ATTR to STACKADDR. */ +extern int pthread_attr_setstackaddr (pthread_attr_t *attr, + void *stackaddr); + + +#ifdef __USE_XOPEN2K +/* Return the value of the stackaddr and stacksize attributes in *ATTR + in *STACKADDR and *STACKSIZE respectively. */ +extern int pthread_attr_getstack (const pthread_attr_t *__restrict attr, + void **__restrict stackaddr, + size_t *__restrict stacksize); + +/* Set the value of the stackaddr and stacksize attributes in *ATTR to + STACKADDR and STACKSIZE respectively. */ +extern int pthread_attr_setstack (pthread_attr_t *attr, + void *stackaddr, + size_t stacksize); +#endif + + +/* Return the value of the detachstate attribute in *ATTR in + *DETACHSTATE. */ +extern int pthread_attr_getdetachstate (const pthread_attr_t *attr, + int *detachstate); + +/* Set the value of the detachstate attribute in *ATTR to + DETACHSTATE. */ +extern int pthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate); + + +/* Return the value of the guardsize attribute in *ATTR in + *GUARDSIZE. */ +extern int pthread_attr_getguardsize (const pthread_attr_t *__restrict attr, + size_t *__restrict guardsize); + +/* Set the value of the guardsize attribute in *ATTR to GUARDSIZE. */ +extern int pthread_attr_setguardsize (pthread_attr_t *attr, + size_t guardsize); + + +/* Return the value of the stacksize attribute in *ATTR in + *STACKSIZE. */ +extern int pthread_attr_getstacksize (const pthread_attr_t *__restrict attr, + size_t *__restrict stacksize); + +/* Set the value of the stacksize attribute in *ATTR to STACKSIZE. */ +extern int pthread_attr_setstacksize (pthread_attr_t *attr, + size_t stacksize); + +#ifdef __USE_GNU +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread THREAD. It shall be called on an uninitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +extern int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr); +#endif + + +/* Create a thread with attributes given by ATTR, executing + START_ROUTINE with argument ARG. */ +extern int pthread_create (pthread_t *__restrict __threadp, + __const pthread_attr_t *__restrict __attr, + void *(*__start_routine)(void *), + void *__restrict __arg); + +/* Terminate the current thread and make STATUS available to any + thread that might join us. */ +extern void pthread_exit (void *__status) __attribute__ ((noreturn)); + +/* Make calling thread wait for termination of thread THREAD. Return + the exit status of the thread in *STATUS. */ +extern int pthread_join (pthread_t __threadp, void **__status); + +/* Indicate that the storage for THREAD can be reclaimed when it + terminates. */ +extern int pthread_detach (pthread_t __threadp); + +/* Compare thread IDs T1 and T2. Return nonzero if they are equal, 0 + if they are not. */ +extern int pthread_equal (pthread_t __t1, pthread_t __t2); + +# ifdef __USE_EXTERN_INLINES + +__extern_inline int +pthread_equal (pthread_t __t1, pthread_t __t2) +{ + return __pthread_equal (__t1, __t2); +} + +# endif /* Use extern inlines. */ + + +/* Return the thread ID of the calling thread. */ +extern pthread_t pthread_self (void); + + +/* Mutex attributes. */ + +#define PTHREAD_PRIO_NONE_NP __PTHREAD_PRIO_NONE +#define PTHREAD_PRIO_INHERIT_NP __PTHREAD_PRIO_INHERIT +#define PTHREAD_PRIO_PROTECT_NP __PTHREAD_PRIO_PROTECT +#ifdef __USE_UNIX98 +#define PTHREAD_PRIO_NONE PTHREAD_PRIO_NONE_NP +#define PTHREAD_PRIO_INHERIT PTHREAD_PRIO_INHERIT_NP +#define PTHREAD_PRIO_PROTECT PTHREAD_PRIO_PROTECT_NP +#endif + +#define PTHREAD_MUTEX_TIMED_NP __PTHREAD_MUTEX_TIMED +#define PTHREAD_MUTEX_ERRORCHECK_NP __PTHREAD_MUTEX_ERRORCHECK +#define PTHREAD_MUTEX_RECURSIVE_NP __PTHREAD_MUTEX_RECURSIVE +#ifdef __USE_UNIX98 +#define PTHREAD_MUTEX_NORMAL PTHREAD_MUTEX_TIMED_NP +#define PTHREAD_MUTEX_ERRORCHECK PTHREAD_MUTEX_ERRORCHECK_NP +#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP +#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL +#endif +#ifdef __USE_GNU +/* For compatibility. */ +#define PTHREAD_MUTEX_FAST_NP PTHREAD_MUTEX_TIMED_NP +#endif + +#include <bits/mutex-attr.h> + +/* Initialize the mutex attribute object in *ATTR to the default + values. */ +extern int pthread_mutexattr_init(pthread_mutexattr_t *attr); + +/* Destroy the mutex attribute structure in *ATTR. */ +extern int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); + + +#ifdef __USE_UNIX98 +/* Return the value of the prioceiling attribute in *ATTR in + *PRIOCEILING. */ +extern int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *__restrict attr, + int *__restrict prioceiling); + +/* Set the value of the prioceiling attribute in *ATTR to + PRIOCEILING. */ +extern int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, + int prioceiling); + + +/* Return the value of the protocol attribute in *ATTR in + *PROTOCOL. */ +extern int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *__restrict attr, + int *__restrict protocol); + +/* Set the value of the protocol attribute in *ATTR to PROTOCOL. */ +extern int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, + int protocol); +#endif + + +/* Return the value of the process shared attribute in *ATTR in + *PSHARED. */ +extern int pthread_mutexattr_getpshared(const pthread_mutexattr_t *__restrict attr, + int *__restrict pshared); + +/* Set the value of the process shared attribute in *ATTR to + PSHARED. */ +extern int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, + int pshared); + + +#ifdef __USE_UNIX98 +/* Return the value of the type attribute in *ATTR in *TYPE. */ +extern int pthread_mutexattr_gettype(const pthread_mutexattr_t *__restrict attr, + int *__restrict type); + +/* Set the value of the type attribute in *ATTR to TYPE. */ +extern int pthread_mutexattr_settype(pthread_mutexattr_t *attr, + int type); +#endif + + +/* Mutexes. */ + +#include <bits/mutex.h> + +#define PTHREAD_MUTEX_INITIALIZER __PTHREAD_MUTEX_INITIALIZER +/* Static initializer for recursive mutexes. */ + +#ifdef __USE_GNU +# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ + __PTHREAD_ERRORCHECK_MUTEX_INITIALIZER +# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ + __PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#endif + +/* Create a mutex with attributes given by ATTR and store it in + *__MUTEX. */ +extern int pthread_mutex_init (struct __pthread_mutex *__restrict __mutex, + const pthread_mutexattr_t *__restrict attr); + +/* Destroy the mutex __MUTEX. */ +extern int pthread_mutex_destroy (struct __pthread_mutex *__mutex); + +/* Wait until lock for MUTEX becomes available and lock it. */ +extern int pthread_mutex_lock (pthread_mutex_t *__mutex); + +/* Try to lock MUTEX. */ +extern int pthread_mutex_trylock (pthread_mutex_t *__mutex); + +#ifdef __USE_XOPEN2K +/* Try to lock MUTEX, block until *ABSTIME if it is already held. */ +extern int pthread_mutex_timedlock (struct __pthread_mutex *__restrict mutex, + const struct timespec *__restrict abstime); +#endif + +/* Unlock MUTEX. */ +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex); + +/* Transfer ownership of the mutex MUTEX to the thread TID. The + caller must own the lock. */ +extern int __pthread_mutex_transfer_np (struct __pthread_mutex *mutex, + pthread_t tid); + + +#ifdef __USE_UNIX98 +/* Return the priority ceiling of mutex *MUTEX in *PRIOCEILING. */ +extern int pthread_mutex_getprioceiling (const pthread_mutex_t *__restrict mutex, + int *__restrict prioceiling); + +/* After acquiring the mutex *MUTEX, set its priority ceiling to PRIO + and return the old priority ceiling in *OLDPRIO. Before returning, + release the mutex. */ +extern int pthread_mutex_setprioceiling (pthread_mutex_t *__restrict mutex, + int prio, int *__restrict oldprio); +#endif + + + +/* Condition attributes. */ + +#include <bits/condition-attr.h> + +/* Initialize the condition attribute in *ATTR to the default + values. */ +extern int pthread_condattr_init (pthread_condattr_t *attr); + +/* Destroy the condition attribute structure in *ATTR. */ +extern int pthread_condattr_destroy (pthread_condattr_t *attr); + + +#ifdef __USE_XOPEN2K +/* Return the value of the clock attribute in *ATTR in *CLOCK_ID. */ +extern int pthread_condattr_getclock (const pthread_condattr_t *__restrict attr, + clockid_t *__restrict clock_id); + +/* Set the value of the clock attribute in *ATTR to CLOCK_ID. */ +extern int pthread_condattr_setclock (pthread_condattr_t *attr, + clockid_t clock_id); +#endif + + +/* Return the value of the process shared attribute in *ATTR in + *PSHARED. */ +extern int pthread_condattr_getpshared (const pthread_condattr_t *__restrict attr, + int *__restrict pshared); + +/* Set the value of the process shared attribute in *ATTR to + PSHARED. */ +extern int pthread_condattr_setpshared (pthread_condattr_t *attr, + int pshared); + + +/* Condition variables. */ + +#include <bits/condition.h> + +#define PTHREAD_COND_INITIALIZER __PTHREAD_COND_INITIALIZER + +extern int pthread_cond_init (pthread_cond_t *__restrict cond, + const pthread_condattr_t *__restrict attr); + +extern int pthread_cond_destroy (pthread_cond_t *cond); + +/* Unblock at least one of the threads that are blocked on condition + variable COND. */ +extern int pthread_cond_signal (pthread_cond_t *__cond); + +/* Unblock all threads that are blocked on condition variable COND. */ +extern int pthread_cond_broadcast (pthread_cond_t *__cond); + +/* Block on condition variable COND. MUTEX should be held by the + calling thread. On success, MUTEX will be held by the calling + thread. */ +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex); + +/* Block on condition variable COND. MUTEX should be held by the + calling thread. On success, MUTEX will be held by the calling + thread. If the time specified by ABSTIME passes, ETIMEDOUT is + returned, and MUTEX will nevertheless be held. */ +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict __abstime); + + +/* Spin locks. */ + +#ifdef __USE_XOPEN2K + +# include <bits/spin-lock.h> + +#define PTHREAD_SPINLOCK_INITIALIZER __PTHREAD_SPIN_LOCK_INITIALIZER + +/* Destroy the spin lock object LOCK. */ +extern int pthread_spin_destroy (pthread_spinlock_t *__lock); + +/* Initialize the spin lock object LOCK. PSHARED determines whether + the spin lock can be operated upon by multiple processes. */ +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared); + +/* Lock the spin lock object LOCK. If the lock is held by another + thread spin until it becomes available. */ +extern int pthread_spin_lock (pthread_spinlock_t *__lock); + +/* Lock the spin lock object LOCK. Fail if the lock is held by + another thread. */ +extern int pthread_spin_trylock (pthread_spinlock_t *__lock); + +/* Unlock the spin lock object LOCK. */ +extern int pthread_spin_unlock (pthread_spinlock_t *__lock); + +# ifdef __USE_EXTERN_INLINES + +# include <bits/spin-lock-inline.h> + +__extern_inline int +pthread_spin_destroy (pthread_spinlock_t *__lock) +{ + return __pthread_spin_destroy (__lock); +} + +__extern_inline int +pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) +{ + return __pthread_spin_init (__lock, __pshared); +} + +__extern_inline int +pthread_spin_lock (pthread_spinlock_t *__lock) +{ + return __pthread_spin_lock (__lock); +} + +__extern_inline int +pthread_spin_trylock (pthread_spinlock_t *__lock) +{ + return __pthread_spin_trylock (__lock); +} + +__extern_inline int +pthread_spin_unlock (pthread_spinlock_t *__lock) +{ + return __pthread_spin_unlock (__lock); +} + +# endif /* Use extern inlines. */ + +#endif /* XPG6. */ + + +/* rwlock attributes. */ + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K + +#include <bits/rwlock-attr.h> + +/* Initialize rwlock attribute object in *ATTR to the default + values. */ +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *attr); + +/* Destroy the rwlock attribute object in *ATTR. */ +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr); + + +/* Return the value of the process shared attribute in *ATTR in + *PSHARED. */ +extern int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *__restrict attr, + int *__restrict pshared); + +/* Set the value of the process shared atrribute in *ATTR to + PSHARED. */ +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, + int pshared); + + +/* rwlocks. */ + +#include <bits/rwlock.h> + +#define PTHREAD_RWLOCK_INITIALIZER __PTHREAD_RWLOCK_INITIALIZER +/* Create a rwlock object with attributes given by ATTR and strore the + result in *RWLOCK. */ +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict rwlock, + const pthread_rwlockattr_t *__restrict attr); + +/* Destroy the rwlock *RWLOCK. */ +extern int pthread_rwlock_destroy (pthread_rwlock_t *rwlock); + +/* Acquire the rwlock *RWLOCK for reading. */ +extern int pthread_rwlock_rdlock (pthread_rwlock_t *rwlock); + +/* Acquire the rwlock *RWLOCK for reading. */ +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock); + +# ifdef __USE_XOPEN2K +/* Acquire the rwlock *RWLOCK for reading blocking until *ABSTIME if + it is already held. */ +extern int pthread_rwlock_timedrdlock (struct __pthread_rwlock *__restrict rwlock, + const struct timespec *__restrict abstime); +# endif + +/* Acquire the rwlock *RWLOCK for writing. */ +extern int pthread_rwlock_wrlock (pthread_rwlock_t *rwlock); + +/* Try to acquire the rwlock *RWLOCK for writing. */ +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock); + +# ifdef __USE_XOPEN2K +/* Acquire the rwlock *RWLOCK for writing blocking until *ABSTIME if + it is already held. */ +extern int pthread_rwlock_timedwrlock (struct __pthread_rwlock *__restrict rwlock, + const struct timespec *__restrict abstime); +# endif + +/* Release the lock held by the current thread on *RWLOCK. */ +extern int pthread_rwlock_unlock (pthread_rwlock_t *rwlock); + +#endif /* __USE_UNIX98 || __USE_XOPEN2K */ + + + +/* Cancelation. */ + +/* Register a cleanup handler. */ +extern void pthread_cleanup_push (void (*routine) (void *), void *arg); + +/* Unregister a cleanup handler. */ +extern void pthread_cleanup_pop (int execute); + +#include <bits/cancelation.h> + +#define pthread_cleanup_push(rt, rtarg) __pthread_cleanup_push(rt, rtarg) +#define pthread_cleanup_pop(execute) __pthread_cleanup_pop(execute) + +#define PTHREAD_CANCEL_DISABLE 0 +#define PTHREAD_CANCEL_ENABLE 1 + +/* Return the calling thread's cancelation state in *OLDSTATE and set + its state to STATE. */ +extern int pthread_setcancelstate (int state, int *oldstate); + +#define PTHREAD_CANCEL_DEFERRED 0 +#define PTHREAD_CANCEL_ASYNCHRONOUS 1 + +/* Return the calling thread's cancelation type in *OLDTYPE and set + its type to TYPE. */ +extern int pthread_setcanceltype (int type, int *oldtype); + +/* Value returned by pthread_join if the target thread was + canceled. */ +#define PTHREAD_CANCELED ((void *) -1) + +/* Cancel THEAD. */ +extern int pthread_cancel (pthread_t thread); + +/* Add an explicit cancelation point. */ +extern void pthread_testcancel (void); + + +/* Barriers attributes. */ + +#ifdef __USE_XOPEN2K + +#include <bits/barrier-attr.h> + +/* Initialize barrier attribute object in *ATTR to the default + values. */ +extern int pthread_barrierattr_init (pthread_barrierattr_t *attr); + +/* Destroy the barrier attribute object in *ATTR. */ +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *attr); + + +/* Return the value of the process shared attribute in *ATTR in + *PSHARED. */ +extern int pthread_barrierattr_getpshared (const pthread_barrierattr_t *__restrict attr, + int *__restrict pshared); + +/* Set the value of the process shared atrribute in *ATTR to + PSHARED. */ +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *attr, + int pshared); + + +/* Barriers. */ + +#include <bits/barrier.h> + +/* Returned by pthread_barrier_wait to exactly one thread each time a + barrier is passed. */ +#define PTHREAD_BARRIER_SERIAL_THREAD -1 + +/* Initialize barrier BARRIER. */ +extern int pthread_barrier_init (pthread_barrier_t *__restrict barrier, + const pthread_barrierattr_t *__restrict attr, + unsigned count); + +/* Destroy barrier BARRIER. */ +extern int pthread_barrier_destroy (pthread_barrier_t *barrier); + +/* Wait on barrier BARRIER. */ +extern int pthread_barrier_wait (pthread_barrier_t *barrier); + +#endif /* __USE_XOPEN2K */ + + + +/* Thread specific data. */ + +#include <bits/thread-specific.h> + +/* Create a thread specific data key in KEY visible to all threads. + On thread destruction, DESTRUCTOR shall be called with the thread + specific data associate with KEY if it is not NULL. */ +extern int pthread_key_create (pthread_key_t *key, + void (*destructor) (void *)); + +/* Delete the thread specific data key KEY. The associated destructor + function is not called. */ +extern int pthread_key_delete (pthread_key_t key); + +/* Return the caller thread's thread specific value of KEY. */ +extern void *pthread_getspecific (pthread_key_t key); + +/* Set the caller thread's thread specific value of KEY to VALUE. */ +extern int pthread_setspecific (pthread_key_t key, const void *value); + + +/* Dynamic package initialization. */ + +#include <bits/once.h> + +#define PTHREAD_ONCE_INIT __PTHREAD_ONCE_INIT + +/* Call INIT_ROUTINE if this function has never been called with + *ONCE_CONTROL, otherwise do nothing. */ +extern int pthread_once (pthread_once_t *once_control, + void (*init_routine) (void)); + + +/* Concurrency. */ + +#ifdef __USE_UNIX98 +/* Set the desired concurrency level to NEW_LEVEL. */ +extern int pthread_setconcurrency (int new_level); + +/* Get the current concurrency level. */ +extern int pthread_getconcurrency (void); +#endif + + +/* Forking. */ + +/* Register the function PREPARE to be run before the process forks, + the function PARENT to be run after a fork in the parent and the + function CHILD to be run in the child after the fork. If no + handling is desired then any of PREPARE, PARENT and CHILD may be + NULL. The prepare handles will be called in the reverse order + which they were registered and the parent and child handlers in the + order in which they were registered. */ +extern int pthread_atfork (void (*prepare) (void), void (*parent) (void), + void (*child) (void)); + + +/* Signals (should be in <signal.h>). */ + +/* Send signal SIGNO to thread THREAD. */ +extern int pthread_kill (pthread_t thread, int signo); + + +/* Time. */ + +#ifdef __USE_XOPEN2K +/* Return the thread cpu clock. */ +extern int pthread_getcpuclockid (pthread_t thread, clockid_t *clock); +#endif + + +/* Scheduling. */ + +/* Return thread THREAD's scheduling paramters. */ +extern int pthread_getschedparam (pthread_t thread, int *__restrict policy, + struct sched_param *__restrict param); + +/* Set thread THREAD's scheduling paramters. */ +extern int pthread_setschedparam (pthread_t thread, int policy, + const struct sched_param *param); + +/* Set thread THREAD's scheduling priority. */ +extern int pthread_setschedprio (pthread_t thread, int prio); + +#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); +#endif + + +/* Kernel-specific interfaces. */ + +#include <bits/pthread-np.h> + + +__END_DECLS + +#endif /* pthread.h */ diff --git a/libpthread/include/pthread/pthreadtypes.h b/libpthread/include/pthread/pthreadtypes.h new file mode 100644 index 00000000..471e08ed --- /dev/null +++ b/libpthread/include/pthread/pthreadtypes.h @@ -0,0 +1,136 @@ +/* Copyright (C) 2000, 2002, 2005, 2008 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. */ + +/* + * POSIX Threads Extension: ??? <pthreadtypes.h> + */ + +#ifndef _PTHREADTYPES_H +#define _PTHREADTYPES_H 1 + +#include <features.h> + +#define __need_clockid_t +#include <time.h> + +/* If we are in a mode where clockid_t is not automatically defined + and another header has already included <time.h> then defining + __need_clockid_t was not enough. */ +#ifndef __clockid_t_defined +# define __clockid_t_defined 1 +# include <bits/types.h> +/* Clock ID used in clock and timer functions. */ +typedef __clockid_t clockid_t; +#endif + +__BEGIN_DECLS + +#include <bits/pthread.h> +typedef __pthread_t pthread_t; + +/* Possible values for the process shared attribute. */ +enum __pthread_process_shared + { + __PTHREAD_PROCESS_PRIVATE = 0, + __PTHREAD_PROCESS_SHARED + }; + +/* Possible values for the inheritsched attribute. */ +enum __pthread_inheritsched + { + __PTHREAD_EXPLICIT_SCHED = 0, + __PTHREAD_INHERIT_SCHED + }; + +/* Possible values for the `contentionscope' attribute. */ +enum __pthread_contentionscope + { + __PTHREAD_SCOPE_SYSTEM = 0, + __PTHREAD_SCOPE_PROCESS + }; + +/* Possible values for the `detachstate' attribute. */ +enum __pthread_detachstate + { + __PTHREAD_CREATE_JOINABLE = 0, + __PTHREAD_CREATE_DETACHED + }; + +#include <bits/thread-attr.h> +typedef struct __pthread_attr pthread_attr_t; + +enum __pthread_mutex_protocol + { + __PTHREAD_PRIO_NONE= 0, + __PTHREAD_PRIO_INHERIT, + __PTHREAD_PRIO_PROTECT + }; + +enum __pthread_mutex_type + { + __PTHREAD_MUTEX_TIMED, + __PTHREAD_MUTEX_ERRORCHECK, + __PTHREAD_MUTEX_RECURSIVE + }; + +#include <bits/mutex-attr.h> +typedef struct __pthread_mutexattr pthread_mutexattr_t; + +#include <bits/mutex.h> +typedef struct __pthread_mutex pthread_mutex_t; + +#include <bits/condition-attr.h> +typedef struct __pthread_condattr pthread_condattr_t; + +#include <bits/condition.h> +typedef struct __pthread_cond pthread_cond_t; + +#ifdef __USE_XOPEN2K +# include <bits/spin-lock.h> +typedef __pthread_spinlock_t pthread_spinlock_t; +#endif /* XPG6. */ + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K + +#include <bits/rwlock-attr.h> +typedef struct __pthread_rwlockattr pthread_rwlockattr_t; + +#include <bits/rwlock.h> +typedef struct __pthread_rwlock pthread_rwlock_t; + +#endif /* __USE_UNIX98 || __USE_XOPEN2K */ + +#ifdef __USE_XOPEN2K + +#include <bits/barrier-attr.h> +typedef struct __pthread_barrierattr pthread_barrierattr_t; + +#include <bits/barrier.h> +typedef struct __pthread_barrier pthread_barrier_t; + +#endif /* __USE_XOPEN2K */ + +#include <bits/thread-specific.h> +typedef __pthread_key pthread_key_t; + +#include <bits/once.h> +typedef struct __pthread_once pthread_once_t; + +__END_DECLS + +#endif /* pthreadtypes.h */ diff --git a/libpthread/include/semaphore.h b/libpthread/include/semaphore.h new file mode 100644 index 00000000..657e796e --- /dev/null +++ b/libpthread/include/semaphore.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +#ifndef _SEMAPHORE_H +#define _SEMAPHORE_H 1 + +#include <features.h> + +__BEGIN_DECLS + +#include <bits/semaphore.h> + +#define SEM_FAILED ((void *) 0) + +typedef struct __semaphore sem_t; + +/* Initialize semaphore *SEM with value VALUE. */ +extern int sem_init (sem_t *sem, int pshared, unsigned value); + +/* Destroy semaphore *SEM created with sem_init. */ +extern int sem_destroy (sem_t *sem); + +/* Store the value of semaphore *SEM in *VALUE. */ +extern int sem_getvalue (sem_t *__restrict sem, int *__restrict value); + +/* Perform a down operation on semaphore *SEM. */ +extern int sem_wait (sem_t *sem); + +/* Perform a down operation on semaphore *SEM if it can be done so + without blocking. */ +extern int sem_trywait (sem_t *sem); + +#ifdef __USE_XOPEN2K +/* Perform a down operation on semaphore *SEM but don't wait longer + than TIMEOUT. */ +extern int sem_timedwait (sem_t *__restrict sem, + const struct timespec *__restrict timeout); +#endif + +/* Perform an up operation on semaphore *SEM. */ +extern int sem_post (sem_t *sem); + +/* Open a named semaphore. */ +extern sem_t *sem_open (const char *name, int open_flags, ...); + +/* Close a semaphore returned by sem_open. */ +extern int sem_close (sem_t *sem); + +/* Unlink a named semaphore. */ +extern int sem_unlink (const char *name); + +__END_DECLS + +#endif /* semaphore.h */ diff --git a/libpthread/include/set-hooks.h b/libpthread/include/set-hooks.h new file mode 100644 index 00000000..9ed71b32 --- /dev/null +++ b/libpthread/include/set-hooks.h @@ -0,0 +1,72 @@ +/* Macros for using symbol sets for running lists of functions. + Copyright (C) 1994, 1995, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SET_HOOKS_H +#define _SET_HOOKS_H 1 + +#define __need_size_t +#include <stddef.h> +// #include <sys/cdefs.h> +#define __unbounded + +#ifdef symbol_set_define +/* Define a hook variable called NAME. Functions put on this hook take + arguments described by PROTO. Use `text_set_element (NAME, FUNCTION)' + from gnu-stabs.h to add a function to the hook. */ + +# define DEFINE_HOOK(NAME, PROTO) \ + typedef void __##NAME##_hook_function_t PROTO; \ + symbol_set_define (NAME) + +# define DECLARE_HOOK(NAME, PROTO) \ + typedef void __##NAME##_hook_function_t PROTO;\ + symbol_set_declare (NAME) + +/* Run all the functions hooked on the set called NAME. + Each function is called like this: `function ARGS'. */ + +# define RUN_HOOK(NAME, ARGS) \ +do { \ + void *const *__unbounded ptr; \ + for (ptr = symbol_set_first_element (NAME); \ + ! symbol_set_end_p (NAME, ptr); ++ptr) \ + (*(__##NAME##_hook_function_t *) *ptr) ARGS; \ +} while (0) + +/* Define a hook variable with NAME and PROTO, and a function called RUNNER + which calls each function on the hook in turn, with ARGS. */ + +# define DEFINE_HOOK_RUNNER(name, runner, proto, args) \ +DEFINE_HOOK (name, proto); \ +extern void runner proto; void runner proto { RUN_HOOK (name, args); } + +#else + +/* The system does not provide necessary support for this. */ +# define DEFINE_HOOK(NAME, PROTO) + +# define DECLARE_HOOK(NAME, PROTO) + +# define RUN_HOOK(NAME, ARGS) + +# define DEFINE_HOOK_RUNNER(name, runner, proto, args) + +#endif + +#endif /* set-hooks.h */ diff --git a/libpthread/libpthread.a b/libpthread/libpthread.a new file mode 100644 index 00000000..d0e689e9 --- /dev/null +++ b/libpthread/libpthread.a @@ -0,0 +1,20 @@ +/* pthread initializer is weak in glibc. It must be included if glibc + is to start threading. */ +EXTERN(_cthread_init_routine) + +/* Weak references in glibc that must be filled if glibc is to be + thread safe. */ +EXTERN(cthread_detach) +EXTERN(cthread_fork) +EXTERN(cthread_keycreate) +EXTERN(cthread_getspecific) +EXTERN(__libc_getspecific) +EXTERN(cthread_setspecific) +EXTERN(__mutex_lock_solid) +EXTERN(__mutex_unlock_solid) +/* For libio stream locking. */ +EXTERN(_cthreads_flockfile) +EXTERN(_cthreads_funlockfile) +EXTERN(_cthreads_ftrylockfile) + +GROUP(-lpthread2 -lihash) diff --git a/libpthread/libpthread_pic.a b/libpthread/libpthread_pic.a new file mode 100644 index 00000000..5673b4e7 --- /dev/null +++ b/libpthread/libpthread_pic.a @@ -0,0 +1,20 @@ +/* pthread initializer is weak in glibc. It must be included if glibc + is to start threading. */ +EXTERN(_cthread_init_routine) + +/* Weak references in glibc that must be filled if glibc is to be + thread safe. */ +EXTERN(cthread_detach) +EXTERN(cthread_fork) +EXTERN(cthread_keycreate) +EXTERN(cthread_getspecific) +EXTERN(__libc_getspecific) +EXTERN(cthread_setspecific) +EXTERN(__mutex_lock_solid) +EXTERN(__mutex_unlock_solid) +/* For libio stream locking. */ +EXTERN(_cthreads_flockfile) +EXTERN(_cthreads_funlockfile) +EXTERN(_cthreads_ftrylockfile) + +GROUP(-lpthread2_pic -lihash_pic) diff --git a/libpthread/lockfile.c b/libpthread/lockfile.c new file mode 100644 index 00000000..040cbfb4 --- /dev/null +++ b/libpthread/lockfile.c @@ -0,0 +1,65 @@ +/* lockfile - Handle locking and unlocking of streams. Hurd cthreads version. + Copyright (C) 2000,01,02 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 <cthreads.h> +#include <pthread.h> /* Must come before <stdio.h>! */ +#include <stdio.h> + +#ifdef _STDIO_USES_IOSTREAM + +void +_cthreads_flockfile (_IO_FILE *fp) +{ + _IO_lock_lock (*fp->_lock); +} + +void +_cthreads_funlockfile (_IO_FILE *fp) +{ + _IO_lock_unlock (*fp->_lock); +} + +int +_cthreads_ftrylockfile (_IO_FILE *fp) +{ + return __libc_lock_trylock_recursive (*fp->_lock); +} + +# undef _IO_flockfile +# undef _IO_funlockfile +# undef _IO_ftrylockfile +# undef flockfile +# undef funlockfile +# undef ftrylockfile + +void _IO_flockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_flockfile"))); +void _IO_funlockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_funlockfile"))); +int _IO_ftrylockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_ftrylockfile"))); + +void flockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_flockfile"))); +void funlockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_funlockfile"))); +int ftrylockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_ftrylockfile"))); + +#endif /* _STDIO_USES_IOSTREAM */ diff --git a/libpthread/not-in-libc.h b/libpthread/not-in-libc.h new file mode 100644 index 00000000..516d4d13 --- /dev/null +++ b/libpthread/not-in-libc.h @@ -0,0 +1,11 @@ +#define __mach_port_insert_right mach_port_insert_right +#define __mach_port_allocate mach_port_allocate +#define __mig_init mig_init +#define __thread_create thread_create +#define __thread_get_state thread_get_state +#define __thread_resume thread_resume +#define __thread_set_state thread_set_state +#define __thread_terminate thread_terminate +#define __vm_allocate vm_allocate +#define __vm_deallocate vm_deallocate +#define __sched_yield sched_yield diff --git a/libpthread/pt-yield.c b/libpthread/pt-yield.c new file mode 100644 index 00000000..27848bb7 --- /dev/null +++ b/libpthread/pt-yield.c @@ -0,0 +1,26 @@ +/* Yield the processor to another thread or process. + Copyright (C) 2010 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 <pthread.h> +#include <sched.h> + +int pthread_yield(void) +{ + return sched_yield (); +} diff --git a/libpthread/pthread/Versions b/libpthread/pthread/Versions new file mode 100644 index 00000000..e4b4e8bf --- /dev/null +++ b/libpthread/pthread/Versions @@ -0,0 +1,15 @@ +libc { + GLIBC_2.2 { + # XXX + __vm_deallocate; __mach_port_insert_right; __mach_reply_port; + __mig_init; __vm_allocate; + + # functions used in inline functions or macros + __pthread_spin_destroy; __pthread_spin_init; __pthread_spin_lock; + _pthread_spin_lock; __pthread_spin_trylock; __pthread_spin_unlock; + + # p* + pthread_spin_destroy; pthread_spin_init; pthread_spin_lock; + pthread_spin_trylock; pthread_spin_unlock; + } +} diff --git a/libpthread/pthread/cthreads-compat.c b/libpthread/pthread/cthreads-compat.c new file mode 100644 index 00000000..e0536ef2 --- /dev/null +++ b/libpthread/pthread/cthreads-compat.c @@ -0,0 +1,104 @@ +/* Compatibility routines for cthreads. + Copyright (C) 2000, 2002, 2008 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 <assert.h> +#include <pthread.h> + +typedef void *cthread_t; +typedef void *(*cthread_fn_t) (void *arg); +typedef int cthread_key_t; + +#define CTHREAD_KEY_INVALID (cthread_key_t) -1 + +void +cthread_detach (cthread_t thread) +{ + int err; + + err = pthread_detach ((pthread_t) thread); + assert_perror (err); +} + +cthread_t +cthread_fork (cthread_fn_t func, void *arg) +{ + pthread_t thread; + int err; + + err = pthread_create (&thread, NULL, func, arg); + assert_perror (err); + + return (cthread_t) thread; +} + +int +cthread_keycreate (cthread_key_t *key) +{ + error_t err; + + err = pthread_key_create (key, 0); + if (err) + { + errno = err; + *key = CTHREAD_KEY_INVALID; + err = -1; + } + + return err; +} + +int +cthread_getspecific (cthread_key_t key, void **val) +{ + *val = pthread_getspecific (key); + return 0; +} + +void * +__libc_getspecific (cthread_key_t key) +{ + return pthread_getspecific (key); +} + +int +cthread_setspecific (cthread_key_t key, void *val) +{ + error_t err; + + err = pthread_setspecific (key, (const void *) val); + if (err) + { + errno = err; + err = -1; + } + + return err; +} + +void +__mutex_lock_solid (void *lock) +{ + __pthread_mutex_lock (lock); +} + +void +__mutex_unlock_solid (void *lock) +{ + __pthread_mutex_unlock (lock); +} diff --git a/libpthread/pthread/pt-alloc.c b/libpthread/pthread/pt-alloc.c new file mode 100644 index 00000000..6af2da92 --- /dev/null +++ b/libpthread/pthread/pt-alloc.c @@ -0,0 +1,215 @@ +/* Allocate a new thread structure. + Copyright (C) 2000, 2002, 2005, 2007, 2008 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 <assert.h> +#include <errno.h> +#include <pthread.h> +#include <stdlib.h> +#include <string.h> + +#include <pt-internal.h> + +/* This braindamage is necessary because the standard says that some + of the threads functions "shall fail" if "No thread could be found + corresponding to that specified by the given thread ID." */ + +/* Thread ID lookup table. */ +struct __pthread **__pthread_threads; + +/* The size of the thread ID lookup table. */ +int __pthread_max_threads; + +/* The total number of thread IDs currently in use, or on the list of + available thread IDs. */ +int __pthread_num_threads; + +/* A lock for the table, and the other variables above. */ +pthread_rwlock_t __pthread_threads_lock; + +/* List of thread structures corresponding to free thread IDs. */ +struct __pthread *__pthread_free_threads; +pthread_mutex_t __pthread_free_threads_lock; + +static inline error_t +initialize_pthread (struct __pthread *new, int recycling) +{ + error_t err; + + err = __pthread_init_specific (new); + if (err) + return err; + + new->cancel_state = PTHREAD_CANCEL_ENABLE; + new->cancel_type = PTHREAD_CANCEL_DEFERRED; + new->cancel_pending = 0; + + if (recycling) + /* Since we are recycling PTHREAD, we can assume certains things + about PTHREAD's current state and save some cycles by not + rewriting the memory. */ + return 0; + + new->stack = 0; + + new->state_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; + new->state_cond = (pthread_cond_t) PTHREAD_COND_INITIALIZER; + + new->cancelation_handlers = 0; + + new->next = 0; + new->prevp = 0; + + return 0; +} + + +/* Allocate a new thread structure and its pthread thread ID (but not + a kernel thread). */ +int +__pthread_alloc (struct __pthread **pthread) +{ + error_t err; + + struct __pthread *new; + struct __pthread **threads; + struct __pthread **old_threads; + int max_threads; + int new_max_threads; + + pthread_mutex_lock (&__pthread_free_threads_lock); + for (new = __pthread_free_threads; new; new = new->next) + { + /* There is no need to take NEW->STATE_LOCK: if NEW is on this + list, then it is protected by __PTHREAD_FREE_THREADS_LOCK + except in __pthread_dealloc where after it is added to the + list (with the lock held), it drops the lock and then sets + NEW->STATE and immediately stops using NEW. */ + if (new->state == PTHREAD_TERMINATED) + { + __pthread_dequeue (new); + break; + } + } + pthread_mutex_unlock (&__pthread_free_threads_lock); + + if (new) + { + /* The thread may still be running. Make sure it is stopped. + If this is the case, then the thread is either at the end of + __pthread_dealloc or in __pthread_thread_halt. In both + cases, we are interrupt it. */ + __pthread_thread_halt (new); + + err = initialize_pthread (new, 1); + if (! err) + *pthread = new; + return err; + } + + /* Allocate a new thread structure. */ + new = malloc (sizeof (struct __pthread)); + if (new == NULL) + return ENOMEM; + + err = initialize_pthread (new, 0); + if (err) + { + free (new); + return err; + } + + retry: + pthread_rwlock_wrlock (&__pthread_threads_lock); + + if (__pthread_num_threads < __pthread_max_threads) + { + /* We have a free slot. Use the slot number plus one as the + thread ID for the new thread. */ + new->thread = 1 + __pthread_num_threads++; + __pthread_threads[new->thread - 1] = NULL; + + pthread_rwlock_unlock (&__pthread_threads_lock); + + *pthread = new; + return 0; + } +#ifdef PTHREAD_THREADS_MAX + else if (__pthread_num_threads >= PTHREAD_THREADS_MAX) + { + /* We have reached the limit on the number of threads per process. */ + pthread_rwlock_unlock (&__pthread_threads_lock); + + free (new); + return EAGAIN; + } +#endif + + /* We are going to enlarge the threads table. Save its current + size. We're going to release the lock before doing the necessary + memory allocation, since that's a potentially blocking operation. */ + max_threads = __pthread_max_threads; + + pthread_rwlock_unlock (&__pthread_threads_lock); + + /* Allocate a new lookup table that's twice as large. */ + new_max_threads + = max_threads > 0 ? max_threads * 2 : _POSIX_THREAD_THREADS_MAX; + threads = malloc (new_max_threads * sizeof (struct __pthread *)); + if (threads == NULL) + { + free (new); + return ENOMEM; + } + + pthread_rwlock_wrlock (&__pthread_threads_lock); + + /* Check if nobody else has already enlarged the table. */ + if (max_threads != __pthread_max_threads) + { + /* Yep, they did. */ + pthread_rwlock_unlock (&__pthread_threads_lock); + + /* Free the newly allocated table and try again to allocate a slot. */ + free (threads); + goto retry; + } + + /* Copy over the contents of the old table. */ + memcpy (threads, __pthread_threads, + __pthread_max_threads * sizeof (struct __pthread *)); + + /* Save the location of the old table. We want to deallocate its + storage after we released the lock. */ + old_threads = __pthread_threads; + + /* Replace the table with the new one. */ + __pthread_max_threads = new_max_threads; + __pthread_threads = threads; + + /* And allocate ourselves one of the newly created slots. */ + new->thread = 1 + __pthread_num_threads++; + __pthread_threads[new->thread - 1] = NULL; + + pthread_rwlock_unlock (&__pthread_threads_lock); + + free (old_threads); + + *pthread = new; + return 0; +} diff --git a/libpthread/pthread/pt-cancel.c b/libpthread/pthread/pt-cancel.c new file mode 100644 index 00000000..d19c557d --- /dev/null +++ b/libpthread/pthread/pt-cancel.c @@ -0,0 +1,40 @@ +/* Cancel a thread. + 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. */ + +#include <pthread.h> + +#include <pt-internal.h> + +int +pthread_cancel (pthread_t t) +{ + int err = 0; + struct __pthread *p; + + p = __pthread_getid (t); + if (! p) + return ESRCH; + + p->cancel_pending = 1; + if (p->cancel_state == PTHREAD_CANCEL_ENABLE + && p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS) + err = __pthread_do_cancel (p); + + return err; +} diff --git a/libpthread/pthread/pt-cleanup.c b/libpthread/pthread/pt-cleanup.c new file mode 100644 index 00000000..58865aa4 --- /dev/null +++ b/libpthread/pthread/pt-cleanup.c @@ -0,0 +1,28 @@ +/* Add a cancelation handler to the stack. + 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. */ + +#include <pthread.h> + +#include <pt-internal.h> + +struct __pthread_cancelation_handler ** +__pthread_get_cleanup_stack (void) +{ + return &_pthread_self ()->cancelation_handlers; +} diff --git a/libpthread/pthread/pt-create.c b/libpthread/pthread/pt-create.c new file mode 100644 index 00000000..8f62b78e --- /dev/null +++ b/libpthread/pthread/pt-create.c @@ -0,0 +1,206 @@ +/* Thread creation. + Copyright (C) 2000, 2002, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <assert.h> +#include <errno.h> +#include <pthread.h> +#include <signal.h> + +#include <bits/atomic.h> + +#include <pt-internal.h> + +#ifdef HAVE_USELOCALE +# include <locale.h> +#endif + +/* The total number of pthreads currently active. This is defined + here since it would be really stupid to have a threads-using + program that doesn't call `pthread_create'. */ +__atomic_t __pthread_total; + + +/* The entry-point for new threads. */ +static void +entry_point (void *(*start_routine)(void *), void *arg) +{ +#ifdef HAVE_USELOCALE + /* A fresh thread needs to be bound to the global locale. */ + uselocale (LC_GLOBAL_LOCALE); +#endif + + __pthread_startup (); + + pthread_exit (start_routine (arg)); +} + +/* Create a thread with attributes given by ATTR, executing + START_ROUTINE with argument ARG. */ +int +pthread_create (pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + int err; + struct __pthread *pthread; + + err = __pthread_create_internal (&pthread, attr, start_routine, arg); + if (! err) + *thread = pthread->thread; + + return err; +} + +/* Internal version of pthread_create. See comment in + pt-internal.h. */ +int +__pthread_create_internal (struct __pthread **thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + int err; + struct __pthread *pthread; + const struct __pthread_attr *setup; + sigset_t sigset; + + /* Allocate a new thread structure. */ + err = __pthread_alloc (&pthread); + if (err) + goto failed; + + /* Use the default attributes if ATTR is NULL. */ + setup = attr ? attr : &__pthread_default_attr; + + /* Initialize the thread state. */ + pthread->state = (setup->detachstate == PTHREAD_CREATE_DETACHED + ? PTHREAD_DETACHED : PTHREAD_JOINABLE); + + /* If the user supplied a stack, it is not our responsibility to + setup a stack guard. */ + if (setup->stackaddr) + pthread->guardsize = 0; + else + pthread->guardsize = (setup->guardsize <= setup->stacksize + ? setup->guardsize : setup->stacksize); + + /* Find a stack. There are several scenarios: if a detached thread + kills itself, it has no way to deallocate its stack, thus it + leaves PTHREAD->stack set to true. We try to reuse it here, + however, if the user supplied a stack, we cannot use the old one. + Right now, we simply deallocate it. */ + if (pthread->stack) + { + if (setup->stackaddr != __pthread_default_attr.stackaddr) + { + __pthread_stack_dealloc (pthread->stackaddr, + pthread->stacksize); + pthread->stackaddr = setup->stackaddr; + pthread->stacksize = setup->stacksize; + } + } + else + { + err = __pthread_stack_alloc (&pthread->stackaddr, + setup->stacksize); + if (err) + goto failed_stack_alloc; + + pthread->stacksize = setup->stacksize; + pthread->stack = 1; + } + + /* Allocate the kernel thread and other required resources. */ + err = __pthread_thread_alloc (pthread); + if (err) + goto failed_thread_alloc; + + /* And initialize the rest of the machine context. This may include + additional machine- and system-specific initializations that + prove convenient. */ + err = __pthread_setup (pthread, entry_point, start_routine, arg); + if (err) + goto failed_setup; + + /* Initialize the system-specific signal state for the new + thread. */ + err = __pthread_sigstate_init (pthread); + if (err) + goto failed_sigstate; + + /* Set the new thread's signal mask and set the pending signals to + empty. POSIX says: "The signal mask shall be inherited from the + creating thread. The set of signals pending for the new thread + shall be empty." If the currnet thread is not a pthread then we + just inherit the process' sigmask. */ + if (__pthread_num_threads == 1) + err = sigprocmask (0, 0, &sigset); + else + err = __pthread_sigstate (_pthread_self (), 0, 0, &sigset, 0); + assert_perror (err); + + err = __pthread_sigstate (pthread, SIG_SETMASK, &sigset, 0, 1); + assert_perror (err); + + /* Increase the total number of threads. We do this before actually + starting the new thread, since the new thread might immediately + call `pthread_exit' which decreases the number of threads and + calls `exit' if the number of threads reaches zero. Increasing + the number of threads from within the new thread isn't an option + since this thread might return and call `pthread_exit' before the + new thread runs. */ + __atomic_inc (&__pthread_total); + + /* Store a pointer to this thread in the thread ID lookup table. We + could use __thread_setid, however, we only lock for reading as no + other thread should be using this entry (we also assume that the + store is atomic). */ + pthread_rwlock_rdlock (&__pthread_threads_lock); + __pthread_threads[pthread->thread - 1] = pthread; + pthread_rwlock_unlock (&__pthread_threads_lock); + + /* At this point it is possible to guess our pthread ID. We have to + make sure that all functions taking a pthread_t argument can + handle the fact that this thread isn't really running yet. */ + + /* Schedule the new thread. */ + err = __pthread_thread_start (pthread); + if (err) + goto failed_starting; + + /* At this point the new thread is up and running. */ + + *thread = pthread; + + return 0; + + failed_starting: + __pthread_setid (pthread->thread, NULL); + __atomic_dec (&__pthread_total); + failed_sigstate: + __pthread_sigstate_destroy (pthread); + failed_setup: + __pthread_thread_dealloc (pthread); + __pthread_thread_halt (pthread); + failed_thread_alloc: + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); + pthread->stack = 0; + failed_stack_alloc: + __pthread_dealloc (pthread); + failed: + return err; +} diff --git a/libpthread/pthread/pt-dealloc.c b/libpthread/pthread/pt-dealloc.c new file mode 100644 index 00000000..92fe1fda --- /dev/null +++ b/libpthread/pthread/pt-dealloc.c @@ -0,0 +1,64 @@ +/* Deallocate a thread structure. + Copyright (C) 2000, 2008 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 <assert.h> +#include <pthread.h> +#include <stdlib.h> + +#include <pt-internal.h> + +/* List of thread structures corresponding to free thread IDs. */ +extern struct __pthread *__pthread_free_threads; +extern pthread_mutex_t __pthread_free_threads_lock; + + +/* Deallocate the thread structure for PTHREAD. */ +void +__pthread_dealloc (struct __pthread *pthread) +{ + assert (pthread->state != PTHREAD_TERMINATED); + + /* Withdraw this thread from the thread ID lookup table. */ + __pthread_setid (pthread->thread, NULL); + + /* Mark the thread as terminated. We broadcast the condition + here to prevent pthread_join from waiting for this thread to + exit where it was never really started. Such a call to + pthread_join is completely bogus, but unfortunately allowed + by the standards. */ + __pthread_mutex_lock (&pthread->state_lock); + if (pthread->state != PTHREAD_EXITED) + pthread_cond_broadcast (&pthread->state_cond); + __pthread_mutex_unlock (&pthread->state_lock); + + /* We do not actually deallocate the thread structure, but add it to + a list of re-usable thread structures. */ + pthread_mutex_lock (&__pthread_free_threads_lock); + __pthread_enqueue (&__pthread_free_threads, pthread); + pthread_mutex_unlock (&__pthread_free_threads_lock); + + /* Setting PTHREAD->STATE to PTHREAD_TERMINATED makes this TCB + available for reuse. After that point, we can no longer assume + that PTHREAD is valid. + + Note that it is safe to not lock this update to PTHREAD->STATE: + the only way that it can now be accessed is in __pthread_alloc, + which reads this variable. */ + pthread->state = PTHREAD_TERMINATED; +} diff --git a/libpthread/pthread/pt-detach.c b/libpthread/pthread/pt-detach.c new file mode 100644 index 00000000..1e42c452 --- /dev/null +++ b/libpthread/pthread/pt-detach.c @@ -0,0 +1,92 @@ +/* Detach a thread. + Copyright (C) 2000, 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 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 <pthread.h> +#include <stddef.h> + +#include <pt-internal.h> + +/* Indicate that the storage for THREAD can be reclaimed when it + terminates. */ +int +pthread_detach (pthread_t thread) +{ + struct __pthread *pthread; + int err = 0; + + /* Lookup the thread structure for THREAD. */ + pthread = __pthread_getid (thread); + if (pthread == NULL) + return ESRCH; + + __pthread_mutex_lock (&pthread->state_lock); + + switch (pthread->state) + { + case PTHREAD_JOINABLE: + /* THREAD still running. Mark it as detached such that its + resources can be reclaimed as soon as the thread exits. */ + pthread->state = PTHREAD_DETACHED; + + /* Broadcast the condition. This will make threads that are + waiting to join THREAD continue with hopefully disastrous + consequences instead of blocking indefinitely. */ + pthread_cond_broadcast (&pthread->state_cond); + __pthread_mutex_unlock (&pthread->state_lock); + break; + + case PTHREAD_EXITED: + /* THREAD has already exited. Make sure that nobody can + reference it anymore, and mark it as terminated. */ + + __pthread_mutex_unlock (&pthread->state_lock); + + /* Make sure the thread is not running before we remove its + stack. (The only possibility is that it is in a call to + __pthread_thread_halt itself, but that is enough to cause a + sigsegv.) */ + __pthread_thread_halt (pthread); + + /* Destroy the stack, the kernel resources and the control + block. */ + assert (pthread->stack); + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); + pthread->stack = 0; + + __pthread_thread_dealloc (pthread); + + __pthread_dealloc (pthread); + break; + + case PTHREAD_TERMINATED: + /* Pretend THREAD wasn't there in the first place. */ + __pthread_mutex_unlock (&pthread->state_lock); + err = ESRCH; + break; + + default: + /* Thou shalt not detach non-joinable threads! */ + __pthread_mutex_unlock (&pthread->state_lock); + err = EINVAL; + break; + } + + return err; +} diff --git a/libpthread/pthread/pt-exit.c b/libpthread/pthread/pt-exit.c new file mode 100644 index 00000000..5fe0ba86 --- /dev/null +++ b/libpthread/pthread/pt-exit.c @@ -0,0 +1,118 @@ +/* Thread termination. + Copyright (C) 2000, 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 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 <assert.h> +#include <errno.h> +#include <pthread.h> +#include <stdlib.h> + +#include <pt-internal.h> + +#include <bits/atomic.h> + + +/* Terminate the current thread and make STATUS available to any + thread that might join it. */ +void +pthread_exit (void *status) +{ + struct __pthread *self = _pthread_self (); + struct __pthread_cancelation_handler **handlers; + int oldstate; + int need_dealloc; + + /* Run any cancelation handlers. According to POSIX, the + cancellation cleanup handlers should be called with cancellation + disabled. */ + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); + + for (handlers = __pthread_get_cleanup_stack (); + *handlers; + *handlers = (*handlers)->next) + (*handlers)->handler ((*handlers)->arg); + + pthread_setcancelstate (oldstate, &oldstate); + + /* Destory any thread specific data. */ + __pthread_destroy_specific (self); + + /* Destroy any signal state. */ + __pthread_sigstate_destroy (self); + + /* Decrease the number of threads. We use an atomic operation to + make sure that only the last thread calls `exit'. */ + if (__atomic_dec_and_test (&__pthread_total)) + /* We are the last thread. */ + exit (0); + + /* Note that after this point the process can be terminated at any + point if another thread calls `pthread_exit' and happens to be + the last thread. */ + + __pthread_mutex_lock (&self->state_lock); + + if (self->cancel_state == PTHREAD_CANCEL_ENABLE && self->cancel_pending) + status = PTHREAD_CANCELED; + + switch (self->state) + { + default: + assert (! "Consistency error: unexpected self->state"); + abort (); + break; + + case PTHREAD_DETACHED: + /* Make sure that nobody can reference this thread anymore, and + mark it as terminated. Our thread ID will immediately become + available for re-use. For obvious reasons, we cannot + deallocate our own stack. However, it will eventually be + reused when this thread structure is recycled. */ + __pthread_mutex_unlock (&self->state_lock); + + __pthread_dealloc (self); + + break; + + case PTHREAD_JOINABLE: + /* We need to stay around for a while since another thread + might want to join us. */ + self->state = PTHREAD_EXITED; + + /* We need to remember the exit status. A thread joining us + might ask for it. */ + self->status = status; + + /* Broadcast the condition. This will wake up threads that are + waiting to join us. */ + pthread_cond_broadcast (&self->state_cond); + __pthread_mutex_unlock (&self->state_lock); + + break; + } + + /* Note that after this point the resources used by this thread can + be freed at any moment if another thread joins or detaches us. + This means that before freeing any resources, such a thread + should make sure that this thread is really halted. */ + + __pthread_thread_halt (self); + + /* NOTREACHED */ + abort (); +} diff --git a/libpthread/pthread/pt-getattr.c b/libpthread/pthread/pt-getattr.c new file mode 100644 index 00000000..24599c6e --- /dev/null +++ b/libpthread/pthread/pt-getattr.c @@ -0,0 +1,49 @@ +/* Thread attributes retrieval. + Copyright (C) 2008 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 <assert.h> +#include <errno.h> +#include <pthread.h> + +#include <pt-internal.h> + +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread THREAD. It shall be called on an uninitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +int +pthread_getattr_np (pthread_t thread, pthread_attr_t *attr) +{ + struct __pthread *pthread; + + pthread = __pthread_getid(thread); + if (pthread == NULL) + return ESRCH; + + /* Some attributes (schedparam, inheritsched, contentionscope and schedpolicy) + are not supported yet, so fill them with our default values. */ + *attr = __pthread_default_attr; + + attr->stackaddr = pthread->stackaddr; + attr->stacksize = pthread->stacksize; + attr->guardsize = pthread->guardsize; + attr->detachstate = (pthread->state == PTHREAD_DETACHED + ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); + + return 0; +} diff --git a/libpthread/pthread/pt-initialize.c b/libpthread/pthread/pt-initialize.c new file mode 100644 index 00000000..cf32b8b5 --- /dev/null +++ b/libpthread/pthread/pt-initialize.c @@ -0,0 +1,33 @@ +/* Initialize pthreads library. + Copyright (C) 2000,02 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 <assert.h> +#include <string.h> + +#include <pt-internal.h> +#include <set-hooks.h> + +DEFINE_HOOK (__pthread_init, (void)); + +/* Initialize the pthreads library. */ +void +__pthread_initialize (void) +{ + RUN_HOOK (__pthread_init, ()); +} diff --git a/libpthread/pthread/pt-internal.h b/libpthread/pthread/pt-internal.h new file mode 100644 index 00000000..cb441d09 --- /dev/null +++ b/libpthread/pthread/pt-internal.h @@ -0,0 +1,290 @@ +/* Internal defenitions for pthreads library. + Copyright (C) 2000, 2005, 2006, 2008 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. */ + +#ifndef _PT_INTERNAL_H +#define _PT_INTERNAL_H 1 + +#include <pthread.h> +#include <stddef.h> +#include <sched.h> +#include <signal.h> +#include <assert.h> + +#include <bits/atomic.h> + +#include <pt-key.h> + +#include <pt-sysdep.h> +#include <pt-machdep.h> + +/* Thread state. */ +enum pthread_state +{ + /* The thread is running and joinable. */ + PTHREAD_JOINABLE = 0, + /* The thread is running and detached. */ + PTHREAD_DETACHED, + /* A joinable thread exited and its return code is available. */ + PTHREAD_EXITED, + /* The thread structure is unallocated and available for reuse. */ + PTHREAD_TERMINATED +}; + +#ifndef PTHREAD_KEY_MEMBERS +# define PTHREAD_KEY_MEMBERS +#endif + +#ifndef PTHREAD_SYSDEP_MEMBERS +# define PTHREAD_SYSDEP_MEMBERS +#endif + +/* This structure describes a POSIX thread. */ +struct __pthread +{ + /* Thread ID. */ + pthread_t thread; + + /* Cancellation. */ + int cancel_state; + int cancel_type; + int cancel_pending; + struct __pthread_cancelation_handler *cancelation_handlers; + + /* Thread stack. */ + void *stackaddr; + size_t stacksize; + size_t guardsize; /* Included in STACKSIZE (i.e. total + stack memory is STACKSIZE, not + STACKSIZE + GUARDSIZE). */ + int stack; /* Nonzero if the stack was allocated. */ + + /* Exit status. */ + void *status; + + /* Thread state. */ + enum pthread_state state; + pthread_mutex_t state_lock; /* Locks the state. */ + pthread_cond_t state_cond; /* Signalled when the state changes. */ + + /* Thread context. */ + struct pthread_mcontext mcontext; + + PTHREAD_KEY_MEMBERS + + PTHREAD_SYSDEP_MEMBERS + + struct __pthread *next, **prevp; +}; + +/* Enqueue an element THREAD on the queue *HEAD. */ +static inline void +__pthread_enqueue (struct __pthread **head, struct __pthread *thread) +{ + assert (thread->prevp == 0); + + thread->next = *head; + thread->prevp = head; + if (*head) + (*head)->prevp = &thread->next; + *head = thread; +} + +/* Dequeue the element THREAD from the queue it is connected to. */ +static inline void +__pthread_dequeue (struct __pthread *thread) +{ + assert (thread); + + if (thread->next) + thread->next->prevp = thread->prevp; + *thread->prevp = thread->next; + thread->prevp = 0; +} + +/* Iterate over QUEUE storing each element in ELEMENT. */ +#define __pthread_queue_iterate(queue, element) \ + for (struct __pthread *__pdi_next = (queue); \ + ((element) = __pdi_next) \ + && ((__pdi_next = __pdi_next->next), \ + 1); \ + ) + +/* Iterate over QUEUE dequeuing each element, storing it in + ELEMENT. */ +#define __pthread_dequeuing_iterate(queue, element) \ + for (struct __pthread *__pdi_next = (queue); \ + ((element) = __pdi_next) \ + && ((__pdi_next = __pdi_next->next), \ + ((element)->prevp = 0), \ + 1); \ + ) + +/* The total number of threads currently active. */ +extern __atomic_t __pthread_total; + +/* The total number of thread IDs currently in use, or on the list of + available thread IDs. */ +extern int __pthread_num_threads; + +/* Concurrency hint. */ +extern int __pthread_concurrency; + +/* Array of __pthread structures and its lock. Indexed by the pthread + id minus one. (Why not just use the pthread id? Because some + brain-dead users of the pthread interface incorrectly assume that 0 + is an invalid pthread id.) */ +extern struct __pthread **__pthread_threads; +extern pthread_rwlock_t __pthread_threads_lock; + +#define __pthread_getid(thread) \ + ({ struct __pthread *__t; \ + pthread_rwlock_rdlock (&__pthread_threads_lock); \ + __t = __pthread_threads[thread - 1]; \ + pthread_rwlock_unlock (&__pthread_threads_lock); \ + __t; }) + +#define __pthread_setid(thread, pthread) \ + pthread_rwlock_wrlock (&__pthread_threads_lock); \ + __pthread_threads[thread - 1] = pthread; \ + pthread_rwlock_unlock (&__pthread_threads_lock); + +/* Similar to pthread_self, but returns the thread descriptor instead + of the thread ID. */ +#ifndef _pthread_self +extern struct __pthread *_pthread_self (void); +#endif + + +/* Initialize the pthreads library. */ +extern void __pthread_initialize (void); + +/* Internal version of pthread_create. Rather than return the new + tid, we return the whole __pthread structure in *PTHREAD. */ +extern int __pthread_create_internal (struct __pthread **__restrict pthread, + const pthread_attr_t *__restrict attr, + void *(*start_routine)(void *), + void *__restrict arg); + +/* Allocate a new thread structure and a pthread thread ID (but not a + kernel thread or a stack). */ +extern int __pthread_alloc (struct __pthread **thread); + +/* Deallocate the thread structure. This is the dual of + __pthread_alloc (N.B. it does not call __pthread_stack_alloc nor + __pthread_thread_halt). */ +extern void __pthread_dealloc (struct __pthread *thread); + + +/* Allocate a stack of size STACKSIZE. The stack base shall be + returned in *STACKADDR. */ +extern int __pthread_stack_alloc (void **stackaddr, size_t stacksize); + +/* Deallocate the stack STACKADDR of size STACKSIZE. */ +extern void __pthread_stack_dealloc (void *stackaddr, size_t stacksize); + + +/* Setup thread THREAD's context. */ +extern int __pthread_setup (struct __pthread *__restrict thread, + void (*entry_point)(void *(*)(void *), + void *), + void *(*start_routine)(void *), + void *__restrict arg); + + +/* Allocate a kernel thread (and any miscellaneous system dependent + resources) for THREAD; it must not be placed on the run queue. */ +extern int __pthread_thread_alloc (struct __pthread *thread); + +/* Deallocate any kernel resources associated with THREAD. The thread + must not be running (that is, if __pthread_thread_start was called, + __pthread_thread_halt must first be called). This function will + never be called by a thread on itself. In the case that a thread + exits, its thread structure will be cached and cleaned up + later. */ +extern void __pthread_thread_dealloc (struct __pthread *thread); + +/* Start THREAD making it eligible to run. */ +extern int __pthread_thread_start (struct __pthread *thread); + +/* Stop the kernel thread associated with THREAD. This function may + be called by two threads in parallel. In particular, by the thread + itself and another thread trying to join it. This function must be + implemented such that this is safe. */ +extern void __pthread_thread_halt (struct __pthread *thread); + + +/* Called by a thread just before it calls the provided start + routine. */ +extern void __pthread_startup (void); + +/* Block THREAD. */ +extern void __pthread_block (struct __pthread *thread); + +/* Block THREAD until *ABSTIME is reached. */ +extern error_t __pthread_timedblock (struct __pthread *__restrict thread, + const struct timespec *__restrict abstime); + +/* Wakeup THREAD. */ +extern void __pthread_wakeup (struct __pthread *thread); + + +/* Perform a cancelation. */ +extern int __pthread_do_cancel (struct __pthread *thread); + + +/* Initialize the thread specific data structures. THREAD must be the + calling thread. */ +extern error_t __pthread_init_specific (struct __pthread *thread); + +/* Call the destructors on all of the thread specific data in THREAD. + THREAD must be the calling thread. */ +extern void __pthread_destroy_specific (struct __pthread *thread); + + +/* Initialize newly create thread *THREAD's signal state data + structures. */ +extern error_t __pthread_sigstate_init (struct __pthread *thread); + +/* Destroy the signal state data structures associcated with thread + *THREAD. */ +extern void __pthread_sigstate_destroy (struct __pthread *thread); + +/* Modify thread *THREAD's signal state. */ +extern error_t __pthread_sigstate (struct __pthread *__restrict thread, int how, + const sigset_t *__restrict set, + sigset_t *__restrict oset, + int clear_pending); + + +/* Default thread attributes. */ +extern const struct __pthread_attr __pthread_default_attr; + +/* Default barrier attributes. */ +extern const struct __pthread_barrierattr __pthread_default_barrierattr; + +/* Default mutex attributes. */ +extern const struct __pthread_mutexattr __pthread_default_mutexattr; + +/* Default rdlock attributes. */ +const struct __pthread_rwlockattr __pthread_default_rwlockattr; + +/* Default condition attributes. */ +const struct __pthread_condattr __pthread_default_condattr; + +#endif /* pt-internal.h */ diff --git a/libpthread/pthread/pt-join.c b/libpthread/pthread/pt-join.c new file mode 100644 index 00000000..153058b5 --- /dev/null +++ b/libpthread/pthread/pt-join.c @@ -0,0 +1,88 @@ +/* Wait for thread termination. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <pthread.h> +#include <stddef.h> + +#include <pt-internal.h> + +/* Make calling thread wait for termination of thread THREAD. Return + the exit status of the thread in *STATUS. */ +int +pthread_join (pthread_t thread, void **status) +{ + struct __pthread *pthread; + int err = 0; + + /* Lookup the thread structure for THREAD. */ + pthread = __pthread_getid (thread); + if (pthread == NULL) + return ESRCH; + + __pthread_mutex_lock (&pthread->state_lock); + pthread_cleanup_push ((void (*)(void *)) __pthread_mutex_unlock, + &pthread->state_lock); + + while (pthread->state == PTHREAD_JOINABLE) + pthread_cond_wait (&pthread->state_cond, &pthread->state_lock); + + pthread_cleanup_pop (0); + + switch (pthread->state) + { + case PTHREAD_EXITED: + __pthread_mutex_unlock (&pthread->state_lock); + + /* THREAD has already exited. Salvage its exit status. */ + if (status) + *status = pthread->status; + + /* Make sure the thread is not running before we remove its + stack. (The only possibility is that it is in a call to + __pthread_thread_halt itself, but that is enough to cause a + sigsegv.) */ + __pthread_thread_halt (pthread); + + /* Destroy the stack, the kernel resources and the control + block. */ + assert (pthread->stack); + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); + pthread->stack = 0; + + __pthread_thread_dealloc (pthread); + + __pthread_dealloc (pthread); + break; + + case PTHREAD_TERMINATED: + /* Pretend THREAD wasn't there in the first place. */ + __pthread_mutex_unlock (&pthread->state_lock); + err = ESRCH; + break; + + default: + /* Thou shalt not join non-joinable threads! */ + __pthread_mutex_unlock (&pthread->state_lock); + err = EINVAL; + break; + } + + return err; +} diff --git a/libpthread/pthread/pt-self.c b/libpthread/pthread/pt-self.c new file mode 100644 index 00000000..49768643 --- /dev/null +++ b/libpthread/pthread/pt-self.c @@ -0,0 +1,32 @@ +/* Get calling thread's ID. + Copyright (C) 2000, 2008 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 <pthread.h> + +#include <pt-internal.h> + +/* Return the thread ID of the calling thread. */ +pthread_t +pthread_self (void) +{ + struct __pthread *self = _pthread_self (); + assert (self); + + return self->thread; +} diff --git a/libpthread/pthread/pt-setcancelstate.c b/libpthread/pthread/pt-setcancelstate.c new file mode 100644 index 00000000..e2d81833 --- /dev/null +++ b/libpthread/pthread/pt-setcancelstate.c @@ -0,0 +1,43 @@ +/* Set the cancel state for the calling thread. + 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. */ + +#include <pthread.h> + +#include <pt-internal.h> + +int +pthread_setcancelstate (int state, int *oldstate) +{ + struct __pthread *p = _pthread_self (); + + switch (state) + { + default: + return EINVAL; + case PTHREAD_CANCEL_ENABLE: + case PTHREAD_CANCEL_DISABLE: + break; + } + + if (oldstate) + *oldstate = p->cancel_state; + p->cancel_state = state; + + return 0; +} diff --git a/libpthread/pthread/pt-setcanceltype.c b/libpthread/pthread/pt-setcanceltype.c new file mode 100644 index 00000000..3ce4259c --- /dev/null +++ b/libpthread/pthread/pt-setcanceltype.c @@ -0,0 +1,43 @@ +/* Set the cancel type for the calling thread. + 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. */ + +#include <pthread.h> + +#include <pt-internal.h> + +int +pthread_setcanceltype (int type, int *oldtype) +{ + struct __pthread *p = _pthread_self (); + + switch (type) + { + default: + return EINVAL; + case PTHREAD_CANCEL_DEFERRED: + case PTHREAD_CANCEL_ASYNCHRONOUS: + break; + } + + if (oldtype) + *oldtype = p->cancel_type; + p->cancel_type = type; + + return 0; +} diff --git a/libpthread/pthread/pt-sigmask.c b/libpthread/pthread/pt-sigmask.c new file mode 100644 index 00000000..1b53873e --- /dev/null +++ b/libpthread/pthread/pt-sigmask.c @@ -0,0 +1,33 @@ +/* Get or set a thread's signal mask. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <pthread.h> +#include <signal.h> + +#include <pt-internal.h> + +int +pthread_sigmask (int how, const sigset_t *set, + sigset_t *oset) +{ + struct __pthread *self = _pthread_self (); + + /* Do not clear SELF's pending signals. */ + return __pthread_sigstate (self, how, set, oset, 0); +} diff --git a/libpthread/pthread/pt-spin-inlines.c b/libpthread/pthread/pt-spin-inlines.c new file mode 100644 index 00000000..cfb21dd3 --- /dev/null +++ b/libpthread/pthread/pt-spin-inlines.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +/* <bits/spin-lock.h> declares some extern inline functions. These + functions are declared additionally here for use when inlining is + not possible. */ + +#define _FORCE_INLINES +#define __PT_SPIN_INLINE /* empty */ + +#include <pthread.h> + +/* Weak aliases for the spin lock functions. Note that + pthread_spin_lock is left out deliberately. We already provide an + implementation for it in pt-spin.c. */ +weak_alias (__pthread_spin_destroy, pthread_spin_destroy); +weak_alias (__pthread_spin_init, pthread_spin_init); +weak_alias (__pthread_spin_trylock, pthread_spin_trylock); +weak_alias (__pthread_spin_unlock, pthread_spin_unlock); diff --git a/libpthread/pthread/pt-testcancel.c b/libpthread/pthread/pt-testcancel.c new file mode 100644 index 00000000..01f1ac9c --- /dev/null +++ b/libpthread/pthread/pt-testcancel.c @@ -0,0 +1,31 @@ +/* Add an explicit cancelation point. + 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. */ + +#include <pthread.h> + +#include <pt-internal.h> + +void +pthread_testcancel (void) +{ + struct __pthread *p = _pthread_self (); + + if (p->cancel_state == PTHREAD_CANCEL_ENABLE && p->cancel_pending) + pthread_exit (PTHREAD_CANCELED); +} diff --git a/libpthread/signal/README b/libpthread/signal/README new file mode 100644 index 00000000..5487e2e3 --- /dev/null +++ b/libpthread/signal/README @@ -0,0 +1,4 @@ +This directory provides a signal implementation, which is appropriate +for operating systems where signals are managed at user-level. It is +up to the run-time to catch the signals and forward them to the +implementation via, e.g., the pthread_kill_info_np call. diff --git a/libpthread/signal/TODO b/libpthread/signal/TODO new file mode 100644 index 00000000..1148abb3 --- /dev/null +++ b/libpthread/signal/TODO @@ -0,0 +1,29 @@ +Unimplemented Functionality +--------------------------- + +We don't support interruptible functions. That is, if a signal is +delivered when a thread is in e.g. the write system call, then the +write function should be interrupted and return EINTR when the signal +handler is finished. To realize this behavior, we could have a thread +local interruptible flag and a setjmp buffer. A function that is +interruptible would fill the jump buffer and set the interruptible +flag. If a signal comes in and the interruptible flag is set, rather +than resuming the thread, we longjmp to the buffer. + +If a signal action has set the SA_SIGINFO, the third argument must be +a pointer to a ucontext describing the thread's interrupted state; +this implementation passes NULL. This isn't as bad as it sounds as +the the ucontext family of functions are marked obsolete in SUSv3 with +the advisory that any use of them should be replaced by the use of +pthread functionality (cf. makecontext rationale). + +stop and continue signals are not implemented (as we need to stop all +threads, this requires being in bed with libpthread). + +Implementation is not yet cancellation-safe. + +There are not even stubs for sighold, sigingore, sigpause, sigrelse, +however, according to posix: "Use of any of these functions is +unspecified in a multi-threaded process." + +Implement sigtimedwait, sigqueue.
\ No newline at end of file diff --git a/libpthread/signal/kill.c b/libpthread/signal/kill.c new file mode 100644 index 00000000..27c9c32a --- /dev/null +++ b/libpthread/signal/kill.c @@ -0,0 +1,70 @@ +/* kill.c - Generic kill implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +int +kill (pid_t pid, int signo) +{ + if (pid != getpid ()) + { + errno = EOPNOTSUPP; + return -1; + } + + /* "Signals generated for the process shall be delivered to exactly + one of those threads within the process which is in a call to a + sigwait() function selecting that signal or has not blocked + delivery of the signal. If there are no threads in a call to a + sigwait() function selecting that signal, and if all threads + within the process block delivery of the signal, the signal shall + remaing pending on the process" (2.4.1). */ + + /* First, see if there is a waiter, which is interested in this + signal. */ + pthread_mutex_lock (&sig_lock); + + struct sigwaiter *waiter; + for (waiter = sigwaiters; waiter; waiter = waiter->next) + if ((waiter->signals & sigmask (signo))) + /* Got a winner. */ + { + sigdelset (&process_pending, signo); + + pthread_mutex_lock (&waiter->ss->lock); + sigdelset (&waiter->ss->pending, signo); + + memset (&waiter->info, 0, sizeof (waiter->info)); + waiter->info.si_signo = signo; + + sigwaiter_unblock (waiter); + + return 0; + } + + pthread_mutex_unlock (&sig_lock); + + /* XXX: We just generate the signal for the current thread. If the + current thread has blocked the signal, the correct thing to do is + to iterate over all the other threads and find on that hasn't + blocked it. */ + return pthread_kill (pthread_self (), signo); +} + diff --git a/libpthread/signal/pt-kill-siginfo-np.c b/libpthread/signal/pt-kill-siginfo-np.c new file mode 100644 index 00000000..9bdf6cc4 --- /dev/null +++ b/libpthread/signal/pt-kill-siginfo-np.c @@ -0,0 +1,88 @@ +/* pthread-kill-siginfo-np.c - Generic pthread_kill_siginfo_np implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "pt-internal.h" +#include "sig-internal.h" + +int +pthread_kill_siginfo_np (pthread_t tid, siginfo_t si) +{ + int sig = si.si_signo; + + if (sig < 0 || sig >= NSIG) + return EINVAL; + + if (sig == 0) + return 0; + + struct signal_state *ss = &__pthread_getid (tid)->ss; + + pthread_mutex_lock (&sig_lock); + pthread_mutex_lock (&ss->lock); + + if (ss->sigwaiter && (ss->sigwaiter->signals & sigmask (si.si_signo))) + /* The thread is in a call to sigwait. */ + { + ss->sigwaiter->info = si; + sigwaiter_unblock (ss->sigwaiter); + return 0; + } + + pthread_mutex_unlock (&sig_lock); + + if (ss->actions[sig - 1].sa_handler == (void *) SIG_IGN + || (ss->actions[sig - 1].sa_handler == (void *) SIG_DFL + && default_action (sig) == sig_ignore)) + /* It is unclear (to me) what is supposed to happen when a signal + is generated for a thread, which is blocking that signal and + ignoring it. POSIX does say that when the action associated + with a pending, blocked signal is set to SIG_IGN, the pending + signal is to be cleared. Thus, it makes sense that any signal + set to ignore is discarded at generation. */ + { + pthread_mutex_unlock (&ss->lock); + return 0; + } + + + if ((sigmask (sig) & ss->blocked)) + /* The signal is blocked. Mark it pending. */ + { + ss->pending |= sigmask (sig); + pthread_mutex_unlock (&ss->lock); + return 0; + } + + if (pthread_self () == tid + && (! (ss->actions[si.si_signo - 1].sa_flags & SA_ONSTACK) + || (ss->stack.ss_flags & SS_DISABLE) + || (ss->stack.ss_flags & SS_ONSTACK))) + /* We are sending a signal to ourself and we don't use an + alternate stack. */ + signal_dispatch (ss, &si); + else + signal_dispatch_lowlevel (ss, tid, si); + + /* Don't unlock ss: signal_dispatch and signal_dispatch_lowlevel + assume ownership of the lock. */ + + return 0; +} + diff --git a/libpthread/signal/sig-internal.c b/libpthread/signal/sig-internal.c new file mode 100644 index 00000000..f73f38b4 --- /dev/null +++ b/libpthread/signal/sig-internal.c @@ -0,0 +1,26 @@ +/* sig-internal.c - Signal state functions. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +pthread_mutex_t sig_lock = PTHREAD_MUTEX_INITIALIZER; + +sigset_t process_pending; +siginfo_t process_pending_info[NSIG]; diff --git a/libpthread/signal/sig-internal.h b/libpthread/signal/sig-internal.h new file mode 100644 index 00000000..6c86c796 --- /dev/null +++ b/libpthread/signal/sig-internal.h @@ -0,0 +1,177 @@ +/* sig-internal.h - Internal signal handling interface. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef SIG_INTERNAL_H +#define SIG_INTERNAL_H + +#include <signal.h> + +#include <sig-sysdep.h> + +#define sigmask(sig) (1ULL << (sig - 1)) +#define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \ + sigmask (SIGSTOP) | sigmask (SIGTSTP)) + +/* General lock. Protects PROCESS_PENDING, PROCESS_PENDING_INFO, + SIGWAITERS. */ +extern pthread_mutex_t sig_lock; + +/* "Signals generated for the process shall be delivered to exactly + one of those threads within the process which is in a call to a + sigwait() function selecting that signal or has not blocked + delivery of the signal. If there are no threads in a call to a + sigwait() function selecting that signal, and if all threads within + the process block delivery of the signal, the signal shall remaing + pending on the process" (2.4.1). + + This variable is protected by SIG_LOCK. */ +extern sigset_t process_pending; +extern siginfo_t process_pending_info[NSIG]; + +struct sigwaiter; + +/* The per-thread signal state. */ +struct signal_state +{ + /* Protects the following fields. STACK.SA_FLAGS may be accessed + using atomic operations. */ + pthread_mutex_t lock; + + /* Pending signals. */ + sigset_t pending; + + /* Blocked signals (i.e., the signal mask). */ + sigset_t blocked; + + stack_t stack; + struct sigaction actions[NSIG]; + siginfo_t info[NSIG]; + + /* If the thread is blocked in a call to sigwait. */ + struct sigwaiter *sigwaiter; +}; + +#define PTHREAD_SIGNAL_MEMBERS struct signal_state ss; + +/* Arranges for thread TID to call signal_dispatch. Must not be + called if TID is the caller and an alternate stack is not required. + In this case, the caller should call signal_dispatch directly. */ +extern void signal_dispatch_lowlevel (struct signal_state *ss, + pthread_t tid, siginfo_t si); + +/* This is the signal handler entry point. A thread is forced into + this state when it receives a signal. We need to save the thread's + state and then invoke the high-level signal dispatcher. SS->LOCK + is locked by the caller. */ +extern void signal_dispatch (struct signal_state *ss, siginfo_t *si); + +#ifndef SIGNAL_DISPATCH_ENTRY +#define SIGNAL_DISPATCH_ENTRY +#endif + +#ifndef SIGNAL_DISPATCH_EXIT +#define SIGNAL_DISPATCH_EXIT +#endif + +/* When a thread calls sigwait and a requested signal is not pending, + it allocates the following structure, fills it in, adds it to + sigwaiters and sleeps. */ +struct sigwaiter +{ + struct sigwaiter *next; + struct sigwaiter *prev; + + /* Thread's signal state. */ + struct signal_state *ss; + + /* Signals this thread is waiting for. */ + sigset_t signals; + + /* The selected signal is returned here. The waiter also + futex_waits on this info.si_signo. */ + siginfo_t info; +}; + +/* This variable is protected by SIG_LOCK. */ +extern struct sigwaiter *sigwaiters; + +/* Block the caller waiting for a signal in set SET. SIG_LOCK and + SS->LOCK must be held and will be unlocked by this function before + blocking. */ +extern siginfo_t sigwaiter_block (struct signal_state *ss, + const sigset_t *restrict set); + +/* Unblock the waiter WAITER. SIG_LOCK and WAITER->SS->LOCK must be + held. Both will be dropped on return. */ +extern void sigwaiter_unblock (struct sigwaiter *waiter); + +enum sig_action { sig_core, sig_terminate, sig_ignore, sig_cont, sig_stop }; + +static inline enum sig_action +default_action (int signo) +{ + switch (signo) + { + case SIGABRT: + case SIGBUS: + case SIGFPE: + case SIGILL: + case SIGQUIT: + case SIGSEGV: + case SIGSTKFLT: + case SIGSYS: + case SIGTRAP: + case SIGXCPU: + case SIGXFSZ: + return sig_core; + + case SIGALRM: + case SIGHUP: + case SIGINT: + case SIGIO: /* Perhaps ignore? */ + case SIGKILL: + case SIGPIPE: + case SIGPROF: + case SIGTERM: + case SIGUSR1: + case SIGUSR2: + case SIGVTALRM: + return sig_terminate; + + case SIGCHLD: + case SIGPWR: + case SIGURG: + case SIGWINCH: + return sig_ignore; + + case SIGCONT: + return sig_cont; + + case SIGSTOP: + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + return sig_stop; + } + + panic ("Unknown signal number: %d", signo); +} + +#endif diff --git a/libpthread/signal/sigaction.c b/libpthread/signal/sigaction.c new file mode 100644 index 00000000..0126c99d --- /dev/null +++ b/libpthread/signal/sigaction.c @@ -0,0 +1,72 @@ +/* sigaction.c - Generic sigaction implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" +#include "pt-internal.h" + +int +sigaction (int sig, const struct sigaction *restrict sa, + struct sigaction *restrict osa) +{ + if (sig <= 0 || sig >= NSIG) + { + errno = EINVAL; + return -1; + } + + struct signal_state *ss = &_pthread_self ()->ss; + + pthread_mutex_lock (&ss->lock); + + if (osa) + *osa = ss->actions[sig - 1]; + + if (sa) + { + ss->actions[sig - 1] = *sa; + + /* "The SIGKILL and SIGSTOP signals shall not be added to the + signal mask using this mechanism; this restriction shall be + enforced by the system without causing an error to be + indicated" (sigaction). */ + sigdelset (&ss->blocked, SIGKILL); + sigdelset (&ss->blocked, SIGSTOP); + + /* A "signal shall remain pending on the process until it is + unblocked, it is accepted when ..., or the action associated + with it is set to ignore the signal" (2.4.1). + + "Setting a signal action to SIG_DFL for a signal that is + pending, and whose default action is to ignore the signal, + ..., shall cause the pending signal to be discarded, whether + or not it is blocked" (2.4.3). */ + if (sa->sa_handler == SIG_IGN + || (sa->sa_handler == SIG_DFL && default_action (sig) == sig_ignore)) + { + sigdelset (&ss->pending, sig); + sigdelset (&process_pending, sig); + } + } + + pthread_mutex_unlock (&ss->lock); + + return 0; +} + diff --git a/libpthread/signal/sigaltstack.c b/libpthread/signal/sigaltstack.c new file mode 100644 index 00000000..8334811a --- /dev/null +++ b/libpthread/signal/sigaltstack.c @@ -0,0 +1,69 @@ +/* sigaltstack.c - Generic sigaltstack implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" +#include "pt-internal.h" + +int +sigaltstack (const stack_t *restrict stack, stack_t *restrict old) +{ + int err = 0; + struct signal_state *ss = &_pthread_self ()->ss; + + pthread_mutex_lock (&ss->lock); + + if (old) + *old = ss->stack; + + if (stack) + { + if (stack->ss_size < MINSIGSTKSZ) + { + err = ENOMEM; + goto out; + } + + if ((stack->ss_flags & ~(SS_DISABLE))) + /* Flags contains a value other than SS_DISABLE. */ + { + err = EINVAL; + goto out; + } + + if ((ss->stack.ss_flags & SS_ONSTACK)) + /* Stack in use. */ + { + err = EPERM; + goto out; + } + + ss->stack = *stack; + } + + out: + pthread_mutex_unlock (&ss->lock); + + if (err) + { + errno = err; + return -1; + } + return 0; +} diff --git a/libpthread/signal/signal-dispatch.c b/libpthread/signal/signal-dispatch.c new file mode 100644 index 00000000..40440b70 --- /dev/null +++ b/libpthread/signal/signal-dispatch.c @@ -0,0 +1,117 @@ +/* signal-dispatch.c - Signal dispatcher. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +/* This is the signal handler entry point. A thread is forced into + this state when it receives a signal. We need to save the thread's + state and then invoke the high-level signal dispatcher. SS->LOCK + is locked by the caller. */ +void +signal_dispatch (struct signal_state *ss, siginfo_t *si) +{ + SIGNAL_DISPATCH_ENTRY; + + int signo = si->si_signo; + + assert (signo > 0 && signo < NSIG); + assert (pthread_mutex_trylock (&ss->lock) == EBUSY); + + do + { + if ((sigmask (signo) & STOPSIGS)) + /* Stop signals clear a pending SIGCONT even if they + are handled or ignored (but not if preempted). */ + { + sigdelset (&ss->pending, SIGCONT); + sigdelset (&process_pending, SIGCONT); + } + else if ((signo == SIGCONT)) + /* Even if handled or ignored (but not preempted), SIGCONT + clears stop signals and resumes the process. */ + { + ss->pending &= ~STOPSIGS; + process_pending &= ~STOPSIGS; + } + + void (*handler)(int, siginfo_t *, void *) + = ss->actions[signo - 1].sa_sigaction; + + /* Reset to SIG_DFL if requested. SIGILL and SIGTRAP cannot + be automatically reset when delivered; the system silently + enforces this restriction (sigaction). */ + if (ss->actions[signo - 1].sa_flags & SA_RESETHAND + && signo != SIGILL && signo != SIGTRAP) + ss->actions[signo - 1].sa_handler = SIG_DFL; + + sigset_t orig_blocked = ss->blocked; + /* Block requested signals while running the handler. */ + ss->blocked |= ss->actions[signo - 1].sa_mask; + + /* Block SIGNO unless we're asked not to. */ + if (! (ss->actions[signo - 1].sa_flags & (SA_RESETHAND | SA_NODEFER))) + sigaddset (&ss->blocked, signo); + + sigdelset (&ss->pending, signo); + pthread_mutex_unlock (&ss->lock); + + pthread_mutex_lock (&sig_lock); + sigdelset (&process_pending, signo); + pthread_mutex_unlock (&sig_lock); + + if (handler == (void *) SIG_DFL) + { + enum sig_action action = default_action (signo); + + if (action == sig_terminate || action == sig_core) + _exit (128 + signo); + + if (action == sig_stop) + /* XXX: Implement me. */ + panic ("Stopping process unimplemented."); + + if (action == sig_cont) + /* XXX: Implement me. */; + panic ("Continuing process unimplemented."); + } + else if (handler == (void *) SIG_IGN) + ; + else + handler (signo, si, NULL); + + pthread_mutex_lock (&ss->lock); + + /* "When a thread's signal mask is changed in a signal-catching + function that is installed by sigaction(), the restoration of + the signal mask on return from the signal-catching function + overrides that change (see sigaction())" (sigprocmask). */ + ss->blocked = orig_blocked; + + sigset_t pending = ~ss->blocked & ss->pending; + if (! pending) + pending = ~ss->blocked & process_pending; + signo = l4_lsb64 (pending); + } + while (signo); + + pthread_mutex_unlock (&ss->lock); + + SIGNAL_DISPATCH_EXIT; +} diff --git a/libpthread/signal/signal.h b/libpthread/signal/signal.h new file mode 100644 index 00000000..a33d995c --- /dev/null +++ b/libpthread/signal/signal.h @@ -0,0 +1,275 @@ +/* signal.h - Signal handling interface. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _SIGNAL_H +#define _SIGNAL_H 1 + +#include <stdint.h> +#include <sys/types.h> + +typedef volatile int sig_atomic_t; + +typedef uint64_t sigset_t; + +int sigaddset (sigset_t *, int); +int sigdelset (sigset_t *, int); +int sigemptyset (sigset_t *); +int sigfillset (sigset_t *); +int sigismember (const sigset_t *, int); + +/* These values are consistent with Linux. */ +#define SIGRTMIN 34 +#define SIGRTMAX 64 + +enum + { + SIGHUP = 1, +#define SIGHUP SIGHUP + SIGINT, +#define SIGINT SIGINT + SIGQUIT, +#define SIGQUIT SIGQUIT + SIGILL, +#define SIGILL SIGILL + SIGTRAP, +#define SIGTRAP SIGTRAP + SIGABRT, +#define SIGABRT SIGABRT + SIGBUS, +#define SIGBUS SIGBUS + SIGFPE, +#define SIGFPE SIGFPE + SIGKILL, +#define SIGKILL SIGKILL + SIGUSR1, +#define SIGUSR1 SIGUSR1 + SIGSEGV, +#define SIGSEGV SIGSEGV + SIGUSR2, +#define SIGUSR2 SIGUSR2 + SIGPIPE, +#define SIGPIPE SIGPIPE + SIGALRM, +#define SIGALRM SIGALRM + SIGTERM, +#define SIGTERM SIGTERM + SIGSTKFLT, +#define SIGSTKFLT SIGSTKFLT + SIGCHLD, +#define SIGCHLD SIGCHLD + SIGCONT, +#define SIGCONT SIGCONT + SIGSTOP, +#define SIGSTOP SIGSTOP + SIGTSTP, +#define SIGTSTP SIGTSTP + SIGTTIN, +#define SIGTTIN SIGTTIN + SIGTTOU, +#define SIGTTOU SIGTTOU + SIGURG, +#define SIGURG SIGURG + SIGXCPU, +#define SIGXCPU SIGXCPU + SIGXFSZ, +#define SIGXFSZ SIGXFSZ + SIGVTALRM, +#define SIGVTALRM SIGVTALRM + SIGPROF, +#define SIGPROF SIGPROF + SIGWINCH, +#define SIGWINCH SIGWINCH + SIGIO, +#define SIGIO SIGIO + SIGPWR, +#define SIGPWR SIGPWR + SIGSYS, +#define SIGSYS SIGSYS + NSIG + }; + +/* The resulting set is the union of the current set and the signal + set pointed to by the argument set. */ +#define SIG_BLOCK 1 +/* The resulting set is the intersection of the current set and the + complement of the signal set pointed to by the argument set. */ +#define SIG_UNBLOCK 2 +/* The resulting set is the signal set pointed to by the argument + set. */ +#define SIG_SETMASK 3 + +int pthread_sigmask (int how, const sigset_t *mask, sigset_t *old); +int sigprocmask (int how, const sigset_t *restrict mask, + sigset_t *restrict old); + +/* Return set of pending signals. */ +int sigpending(sigset_t *set); + +union sigval +{ + int sival_int; + void *sival_ptr; +}; + +#define SIG_DFL ((void (*)(int)) (0)) +#define SIG_ERR ((void (*)(int)) (-1)) +#define SIG_IGN ((void (*)(int)) (1)) + +/* Causes signal delivery to occur on an alternate stack. */ +#define SA_ONSTACK (1 << 0) +/* Do not generate SIGCHLD when children stop or stopped children + continue. */ +#define SA_NOCLDSTOP (1 << 1) +/* Causes signal dispositions to be set to SIG_DFL on entry to signal + handlers. */ +#define SA_RESETHAND (1 << 2) +/* Causes certain functions to become restartable. */ +#define SA_RESTART (1 << 3) +/* Causes extra information to be passed to signal handlers at the + time of receipt of a signal. */ +#define SA_SIGINFO (1 << 4) +/* Causes implementations not to create zombie processes on child + death. */ +#define SA_NOCLDWAIT (1 << 5) +/* Causes signal not to be automatically blocked on entry to + signal handler. */ +#define SA_NODEFER (1 << 6) + +typedef struct +{ + int si_signo; + int si_code; + int si_errno; + pid_t si_pid; + uid_t si_uid; + void *si_addr; + int si_status; + long si_band; + union sigval si_value; +} siginfo_t; + +struct sigaction +{ + union + { + /* Pointer to a signal-catching function or one of the macros + SIG_IGN or SIG_DFL. */ + void (*sa_handler)(int); + + /* Pointer to a signal-catching function. */ + void (*sa_sigaction)(int, siginfo_t *, void *); + }; + + /* Set of signals to be blocked during execution of the signal + handling function. */ + sigset_t sa_mask; + + /* Special flags. */ + int sa_flags; +}; + +int sigaction (int signo, const struct sigaction *restrict newaction, + struct sigaction *restrict oldaction); + +void (*signal (int signo, void (*handler)(int)))(int); +void (*bsd_signal (int signo, void (*handler)(int)))(int); + +/* Process is executing on an alternate signal stack. */ +#define SS_ONSTACK (1 << 0) +/* Alternate signal stack is disabled. */ +#define SS_DISABLE (1 << 1) + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ PAGESIZE +/* Default size in bytes for the alternate signal stack. */ +#define SIGSTKSZ (16 * PAGESIZE) + +typedef struct +{ + void *ss_sp; + size_t ss_size; + int ss_flags; +} stack_t; + +int sigaltstack(const stack_t *restrict stack, stack_t *restrict old); + +#include <pthread.h> + +/* Send SIGNO to the process PID. */ +int kill(pid_t pid, int signo); + +/* Send SIGNO to the process group PG. */ +int killpg(pid_t pg, int signo); + +/* Send SIGNO to thread TID. */ +int pthread_kill(pthread_t tid, int signo); + +/* Send a signal to thread TID using SIGINFO. */ +int pthread_kill_siginfo_np (pthread_t tid, siginfo_t siginfo); + +/* Send SIGNO to the calling thread. */ +int raise(int signo); + +typedef struct sigevent +{ + /* Notification type. */ + int sigev_notify; + + /* Signal number. */ + int sigev_signo; + + /* Signal value. */ + union sigval sigev_value; + + /* Notification function. */ + void (*sigev_notify_function) (union sigval); + + /* Notification attributes. */ + pthread_attr_t *sigev_notify_attributes; +} sigevent_t; + +enum + { + SIGEV_NONE = 0, +#define SIGEV_NONE SIGEV_NONE + SIGEV_SIGNAL, +#define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_THREAD +#define SIGEV_THREAD SIGEV_THREAD + }; + +#define SIG_HOLD + +int sighold (int); +int sigignore (int); +int siginterrupt (int, int); +int sigpause (int); +int sigqueue (pid_t, int, const union sigval); +int sigrelse (int); +void (*sigset (int, void (*)(int)))(int); +int sigsuspend (const sigset_t *); + +/* Wait for a signal. */ +int sigwait (const sigset_t *restrict set, int *restrict signo); +int sigwaitinfo (const sigset_t *restrict set, siginfo_t *restrict info); +int sigtimedwait (const sigset_t *restrict set, siginfo_t *restrict info, + const struct timespec *restrict timespec); + +#endif diff --git a/libpthread/signal/sigpending.c b/libpthread/signal/sigpending.c new file mode 100644 index 00000000..609b55d6 --- /dev/null +++ b/libpthread/signal/sigpending.c @@ -0,0 +1,38 @@ +/* sigpending.c - Generic sigpending implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <sig-internal.h> +#include <pt-internal.h> + +int +sigpending (sigset_t *set) +{ + struct signal_state *ss = &_pthread_self ()->ss; + + pthread_mutex_lock (&ss->lock); + + /* There is no need to lock SIG_LOCK for process_pending since we + just read it, which is atomic. */ + *set = (ss->pending | process_pending) & ss->blocked; + + pthread_mutex_unlock (&ss->lock); + + return 0; +} diff --git a/libpthread/signal/sigsuspend.c b/libpthread/signal/sigsuspend.c new file mode 100644 index 00000000..73cf12a1 --- /dev/null +++ b/libpthread/signal/sigsuspend.c @@ -0,0 +1,29 @@ +/* sigsuspend.c - Generic sigsuspend implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +int +sigsuspend (const sigset_t *set) +{ + /* XXX: Implement me. */ + errno = EOPNOTSUPP; + return -1; +} diff --git a/libpthread/signal/sigtimedwait.c b/libpthread/signal/sigtimedwait.c new file mode 100644 index 00000000..52cd0176 --- /dev/null +++ b/libpthread/signal/sigtimedwait.c @@ -0,0 +1,30 @@ +/* sigtimedwait.c - Generic sigtimedwait implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +int +sigtimedwait (const sigset_t *restrict set, siginfo_t *restrict info, + const struct timespec *restrict timeout) +{ + errno = EOPNOTSUPP; + return -1; +} + diff --git a/libpthread/signal/sigwaiter.c b/libpthread/signal/sigwaiter.c new file mode 100644 index 00000000..8d041ac1 --- /dev/null +++ b/libpthread/signal/sigwaiter.c @@ -0,0 +1,91 @@ +/* sigwaiter.c - Signal handling functions. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +#include <hurd/futex.h> + +struct sigwaiter *sigwaiters; + +siginfo_t +sigwaiter_block (struct signal_state *ss, const sigset_t *restrict set) +{ + assert (pthread_mutex_trylock (&sig_lock) == EBUSY); + assert (pthread_mutex_trylock (&ss->lock) == EBUSY); + + assert (! ss->sigwaiter); + + struct sigwaiter waiter; + + waiter.next = sigwaiters; + if (waiter.next) + { + assert (! waiter.next->prev); + waiter.next->prev = &waiter; + } + waiter.prev = 0; + sigwaiters = &waiter; + + waiter.ss = ss; + waiter.info.si_signo = 0; + waiter.signals = *set; + + ss->sigwaiter = &waiter; + + pthread_mutex_unlock (&ss->lock); + pthread_mutex_unlock (&sig_lock); + + futex_wait (&waiter.info.si_signo, 0); + +#ifndef NDEBUG + pthread_mutex_lock (&ss->lock); + ss->sigwaiter = 0; + pthread_mutex_unlock (&ss->lock); +#endif + + assert (waiter.info.si_signo); + return waiter.info; +} + +void +sigwaiter_unblock (struct sigwaiter *waiter) +{ + assert (pthread_mutex_trylock (&sig_lock) == EBUSY); + assert (pthread_mutex_trylock (&waiter->ss->lock) == EBUSY); + + struct sigwaiter *prev = waiter->prev; + struct sigwaiter *next = waiter->next; + + if (next) + next->prev = prev; + + if (prev) + prev->next = next; + else + sigwaiters = next; + + sigdelset (&process_pending, waiter->info.si_signo); + sigdelset (&waiter->ss->pending, waiter->info.si_signo); + + pthread_mutex_unlock (&waiter->ss->lock); + pthread_mutex_unlock (&sig_lock); + + futex_wake (&waiter->info.si_signo, 1); +} diff --git a/libpthread/signal/sigwaitinfo.c b/libpthread/signal/sigwaitinfo.c new file mode 100644 index 00000000..1b47079e --- /dev/null +++ b/libpthread/signal/sigwaitinfo.c @@ -0,0 +1,74 @@ +/* sigwaitinfo.c - Generic sigwaitinfo implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <sig-internal.h> +#include <pt-internal.h> + +int +sigwaitinfo (const sigset_t *restrict set, siginfo_t *restrict info) +{ + pthread_mutex_lock (&sig_lock); + + struct signal_state *ss = &_pthread_self ()->ss; + + pthread_mutex_lock (&ss->lock); + + if ((process_pending & *set) || (ss->pending & *set)) + /* There is at least one signal pending. */ + { + bool local = true; + sigset_t extant = process_pending & *set; + if (! extant) + { + local = false; + extant = ss->pending & *set; + } + + assert (extant); + + int signo = l4_msb64 (extant); + + if (info) + { + if (local) + *info = ss->info[signo - 1]; + else + *info = process_pending_info[signo - 1]; + info->si_signo = signo; + } + + sigdelset (&process_pending, signo); + sigdelset (&ss->pending, signo); + + pthread_mutex_unlock (&ss->lock); + pthread_mutex_unlock (&sig_lock); + return 0; + } + + siginfo_t i = sigwaiter_block (ss, set); + assert (i.si_signo); + assert ((sigmask (i.si_signo) & *set)); + + if (info) + *info = i; + + return 0; +} + diff --git a/libpthread/sysdeps/generic/bits/barrier-attr.h b/libpthread/sysdeps/generic/bits/barrier-attr.h new file mode 100644 index 00000000..a9900b71 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/barrier-attr.h @@ -0,0 +1,32 @@ +/* Thread barrier attribute type. Generic version. + Copyright (C) 2002, 2008 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. */ + +#ifndef _BITS_BARRIER_ATTR_H +#define _BITS_BARRIER_ATTR_H 1 + +enum __pthread_process_shared; + +/* This structure describes the attributes of a POSIX thread barrier. + Note that not all of them are supported on all systems. */ +struct __pthread_barrierattr +{ + enum __pthread_process_shared pshared; +}; + +#endif /* bits/barrier-attr.h */ diff --git a/libpthread/sysdeps/generic/bits/barrier.h b/libpthread/sysdeps/generic/bits/barrier.h new file mode 100644 index 00000000..5e559312 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/barrier.h @@ -0,0 +1,39 @@ +/* Thread barrier attribute type. Generic 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. */ + +#ifndef _BITS_BARRIER_H +#define _BITS_BARRIER_H 1 + +#include <bits/spin-lock.h> + +/* This structure describes the attributes of a POSIX barrier. */ +struct __pthread_barrier +{ + __pthread_spinlock_t lock; + struct __pthread *queue; /* List of waiters. */ + unsigned pending; /* Number of that still need to wait on + barrier. */ + unsigned count; /* Number of threads that must wait before + barrier is passed. */ + struct __pthread_barrierattr *attr; + void *data; +}; + + +#endif /* bits/barrier.h */ diff --git a/libpthread/sysdeps/generic/bits/cancelation.h b/libpthread/sysdeps/generic/bits/cancelation.h new file mode 100644 index 00000000..46486f5e --- /dev/null +++ b/libpthread/sysdeps/generic/bits/cancelation.h @@ -0,0 +1,51 @@ +/* Cancelation. Generic version. + Copyright (C) 2002, 2008 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. */ + +#ifndef _BITS_CANCELATION_H +#define _BITS_CANCELATION_H 1 + +struct __pthread_cancelation_handler +{ + void (*handler)(void *); + void *arg; + struct __pthread_cancelation_handler *next; +}; + +/* Returns the thread local location of the cleanup handler stack. */ +struct __pthread_cancelation_handler **__pthread_get_cleanup_stack (void); + +#define __pthread_cleanup_push(rt, rtarg) \ + { \ + struct __pthread_cancelation_handler **__handlers \ + = __pthread_get_cleanup_stack (); \ + struct __pthread_cancelation_handler __handler = \ + { \ + (rt), \ + (rtarg), \ + *__handlers \ + }; \ + *__handlers = &__handler; + +#define __pthread_cleanup_pop(execute) \ + if (execute) \ + __handler.handler (__handler.arg); \ + *__handlers = __handler.next; \ + } + +#endif /* _BITS_CANCELATION_H */ diff --git a/libpthread/sysdeps/generic/bits/condition-attr.h b/libpthread/sysdeps/generic/bits/condition-attr.h new file mode 100644 index 00000000..a1311286 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/condition-attr.h @@ -0,0 +1,34 @@ +/* Condition attribute type. Generic version. + Copyright (C) 2002, 2008 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. */ + +#ifndef _BITS_CONDITION_ATTR_H +#define _BITS_CONDITION_ATTR_H 1 + +#include <time.h> + +enum __pthread_process_shared; + +/* User visible part of a condition attribute variable. */ +struct __pthread_condattr + { + enum __pthread_process_shared pshared; + clockid_t clock; + }; + +#endif /* bits/condition.h */ diff --git a/libpthread/sysdeps/generic/bits/condition.h b/libpthread/sysdeps/generic/bits/condition.h new file mode 100644 index 00000000..bf13adab --- /dev/null +++ b/libpthread/sysdeps/generic/bits/condition.h @@ -0,0 +1,39 @@ +/* Condition type. Generic version. + Copyright (C) 2000, 2005, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +#ifndef _BITS_CONDITION_H +#define _BITS_CONDITION_H 1 + +#include <bits/spin-lock.h> + +/* User visible part of a condition variable. */ +struct __pthread_cond + { + __pthread_spinlock_t __lock; + struct __pthread *__queue; + struct __pthread_condattr *__attr; + struct __pthread_condimpl *__impl; + void *__data; + }; + +/* Initializer for a condition variable. */ +#define __PTHREAD_COND_INITIALIZER \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, NULL } + +#endif /* bits/condition.h */ diff --git a/libpthread/sysdeps/generic/bits/mutex-attr.h b/libpthread/sysdeps/generic/bits/mutex-attr.h new file mode 100644 index 00000000..8514ebe8 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/mutex-attr.h @@ -0,0 +1,41 @@ +/* Mutex attribute type. Generic version. + Copyright (C) 2002, 2008 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. */ + +#ifndef _BITS_MUTEX_ATTR_H +#define _BITS_MUTEX_ATTR_H 1 + +enum __pthread_mutex_protocol; +enum __pthread_process_shared; +enum __pthread_mutex_type; + +/* This structure describes the attributes of a POSIX mutex + attribute. */ +struct __pthread_mutexattr +{ + int prioceiling; + enum __pthread_mutex_protocol protocol; + enum __pthread_process_shared pshared; + enum __pthread_mutex_type mutex_type; +}; + +/* Attributes for a recursive mutex. */ +extern const struct __pthread_mutexattr __pthread_errorcheck_mutexattr; +extern const struct __pthread_mutexattr __pthread_recursive_mutexattr; + +#endif /* bits/mutex-attr.h */ diff --git a/libpthread/sysdeps/generic/bits/mutex.h b/libpthread/sysdeps/generic/bits/mutex.h new file mode 100644 index 00000000..c734c393 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/mutex.h @@ -0,0 +1,75 @@ +/* Mutex type. Generic version. + + Copyright (C) 2000, 2002, 2005, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +#ifndef _BITS_MUTEX_H + +#ifndef __need_pthread_mutex +# define _BITS_MUTEX_H 1 +#endif + +#ifndef __pthread_mutex_defined +# if defined __need_pthread_mutex || defined _BITS_MUTEX_H +# undef __need_pthread_mutex +# define __pthread_mutex_defined + +# include <bits/spin-lock.h> +# include <bits/mutex-attr.h> + +/* User visible part of a mutex. */ +struct __pthread_mutex + { + __pthread_spinlock_t __held; + __pthread_spinlock_t __lock; + /* In cthreads, mutex_init does not initialized thre third + pointer, as such, we cannot rely on its value for anything. */ + char *cthreadscompat1; + struct __pthread *__queue; + struct __pthread_mutexattr *attr; + void *data; + /* Up to this point, we are completely compatible with cthreads + and what libc expects. */ + void *owner; + unsigned locks; + /* If NULL then the default attributes apply. */ + }; + +/* Initializer for a mutex. N.B. this also happens to be compatible + with the cthread mutex initializer. */ +# define __PTHREAD_MUTEX_INITIALIZER \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0, 0 } + +# define __PTHREAD_ERRORCHECK_MUTEXATTR ((struct __pthread_mutexattr *) ((unsigned long) __PTHREAD_MUTEX_ERRORCHECK + 1)) + +# define __PTHREAD_ERRORCHECK_MUTEX_INITIALIZER \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, \ + __PTHREAD_ERRORCHECK_MUTEXATTR, 0, 0, 0 } + +# define __PTHREAD_RECURSIVE_MUTEXATTR ((struct __pthread_mutexattr *) ((unsigned long) __PTHREAD_MUTEX_RECURSIVE + 1)) + +# define __PTHREAD_RECURSIVE_MUTEX_INITIALIZER \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, \ + __PTHREAD_RECURSIVE_MUTEXATTR, 0, 0, 0 } + +# endif +#endif /* Not __pthread_mutex_defined. */ + +#endif /* bits/mutex.h */ diff --git a/libpthread/sysdeps/generic/bits/once.h b/libpthread/sysdeps/generic/bits/once.h new file mode 100644 index 00000000..f4985d6f --- /dev/null +++ b/libpthread/sysdeps/generic/bits/once.h @@ -0,0 +1,34 @@ +/* Dynamic package initialization data structures. Generic version. + Copyright (C) 2002, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +#ifndef _BITS_ONCE_H +#define _BITS_ONCE_H 1 + +#include <bits/spin-lock.h> + +struct __pthread_once +{ + int run; + __pthread_spinlock_t lock; +}; + +#define __PTHREAD_ONCE_INIT \ + { 0, __PTHREAD_SPIN_LOCK_INITIALIZER } + +#endif /* bits/once.h */ diff --git a/libpthread/sysdeps/generic/bits/pthread-np.h b/libpthread/sysdeps/generic/bits/pthread-np.h new file mode 100644 index 00000000..d5ddbb05 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/pthread-np.h @@ -0,0 +1,27 @@ +/* Non-portable functions. Generic version. + Copyright (C) 2008 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. */ + +/* + * Never include this file directly; use <pthread.h> or <cthreads.h> instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +#endif /* bits/pthread-np.h */ diff --git a/libpthread/sysdeps/generic/bits/pthread.h b/libpthread/sysdeps/generic/bits/pthread.h new file mode 100644 index 00000000..80e6b096 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/pthread.h @@ -0,0 +1,38 @@ +/* Pthread data structures. Generic version. + Copyright (C) 2002, 2008 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. */ + +#ifndef _BITS_PTHREAD_H +#define _BITS_PTHREAD_H 1 + +typedef int __pthread_t; + +/* Return true if __T1 and __T2 both name the same thread. Otherwise, + false. */ +extern int +__pthread_equal (__pthread_t __t1, __pthread_t __t2); + +#ifdef __USE_EXTERN_INLINES +__extern_inline int +__pthread_equal (__pthread_t __t1, __pthread_t __t2) +{ + return __t1 == __t2; +} +#endif + +#endif /* bits/pthread.h */ diff --git a/libpthread/sysdeps/generic/bits/pthreadtypes.h b/libpthread/sysdeps/generic/bits/pthreadtypes.h new file mode 100644 index 00000000..e5cbfd2a --- /dev/null +++ b/libpthread/sysdeps/generic/bits/pthreadtypes.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +#if !defined _BITS_TYPES_H && !defined _PTHREAD_H +# error "Never include <bits/pthreadtypes.h> directly; use <sys/types.h> instead." +#endif + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include <pthread.h> + +#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/sysdeps/generic/bits/rwlock-attr.h b/libpthread/sysdeps/generic/bits/rwlock-attr.h new file mode 100644 index 00000000..dba99f1d --- /dev/null +++ b/libpthread/sysdeps/generic/bits/rwlock-attr.h @@ -0,0 +1,32 @@ +/* Thread rwlock attribute type. Generic version. + Copyright (C) 2002, 2008 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. */ + +#ifndef _BITS_RWLOCK_ATTR_H +#define _BITS_RWLOCK_ATTR_H 1 + +enum __pthread_process_shared; + +/* This structure describes the attributes of a POSIX thread rwlock. + Note that not all of them are supported on all systems. */ +struct __pthread_rwlockattr +{ + enum __pthread_process_shared pshared; +}; + +#endif /* bits/rwlock-attr.h */ diff --git a/libpthread/sysdeps/generic/bits/rwlock.h b/libpthread/sysdeps/generic/bits/rwlock.h new file mode 100644 index 00000000..af6b1c86 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/rwlock.h @@ -0,0 +1,46 @@ +/* rwlock type. Generic version. + Copyright (C) 2002, 2005, 2006, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +#ifndef _BITS_RWLOCK_H +#define _BITS_RWLOCK_H + +#include <bits/spin-lock.h> + +/* User visible part of a rwlock. If __held is not held and readers + is 0, then the lock is unlocked. If __held is held and readers is + 0, then the lock is held by a writer. If __held is held and + readers is greater than 0, then the lock is held by READERS + readers. */ +struct __pthread_rwlock + { + __pthread_spinlock_t __held; + __pthread_spinlock_t __lock; + int readers; + struct __pthread *readerqueue; + struct __pthread *writerqueue; + struct __pthread_rwlockattr *__attr; + void *__data; + }; + +/* Initializer for a rwlock. */ +#define __PTHREAD_RWLOCK_INITIALIZER \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0 } + + +#endif /* bits/rwlock.h */ diff --git a/libpthread/sysdeps/generic/bits/semaphore.h b/libpthread/sysdeps/generic/bits/semaphore.h new file mode 100644 index 00000000..5e987c15 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/semaphore.h @@ -0,0 +1,43 @@ +/* Semaphore type. Generic version. + Copyright (C) 2005, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +#ifndef _BITS_SEMAPHORE_H +#define _BITS_SEMAPHORE_H 1 + +#ifndef _SEMAPHORE_H +#error Never include <bits/semaphore.h> directly. +#endif + +#include <pthread.h> + +/* User visible part of a semaphore. */ +struct __semaphore + { + __pthread_spinlock_t __lock; + struct __pthread *__queue; + int __pshared; + int __value; + void *__data; + }; + +/* Initializer for a semaphore. */ +#define __SEMAPHORE_INITIALIZER(pshared, value) \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, NULL, (pshared), (value), NULL } + +#endif /* bits/mutex.h */ diff --git a/libpthread/sysdeps/generic/bits/thread-attr.h b/libpthread/sysdeps/generic/bits/thread-attr.h new file mode 100644 index 00000000..f2e55f2b --- /dev/null +++ b/libpthread/sysdeps/generic/bits/thread-attr.h @@ -0,0 +1,44 @@ +/* Thread attribute type. Generic version. + Copyright (C) 2000, 2002, 2008 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. */ + +#ifndef _BITS_THREAD_ATTR_H +#define _BITS_THREAD_ATTR_H 1 + +#define __need_schedparam +#include <bits/sched.h> + +enum __pthread_detachstate; +enum __pthread_inheritsched; +enum __pthread_contentionscope; + +/* This structure describes the attributes of a POSIX thread. Note + that not all of them are supported on all systems. */ +struct __pthread_attr +{ + struct __sched_param schedparam; + void *stackaddr; + size_t stacksize; + size_t guardsize; + enum __pthread_detachstate detachstate; + enum __pthread_inheritsched inheritsched; + enum __pthread_contentionscope contentionscope; + int schedpolicy; +}; + +#endif /* bits/thread-attr.h */ diff --git a/libpthread/sysdeps/generic/bits/thread-specific.h b/libpthread/sysdeps/generic/bits/thread-specific.h new file mode 100644 index 00000000..b42d99e7 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/thread-specific.h @@ -0,0 +1,25 @@ +/* Thread specific data. Generic 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. */ + +#ifndef _BITS_THREAD_SPECIFIC_H +#define _BITS_THREAD_SPECIFIC_H 1 + +typedef int __pthread_key; + +#endif /* bits/thread-specific.h */ diff --git a/libpthread/sysdeps/generic/killpg.c b/libpthread/sysdeps/generic/killpg.c new file mode 100644 index 00000000..7f7ed87d --- /dev/null +++ b/libpthread/sysdeps/generic/killpg.c @@ -0,0 +1,27 @@ +/* killpg.c - Generic killpg implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +int +killpg (pid_t pid, int sig) +{ + return kill (-pid, sig); +} diff --git a/libpthread/sysdeps/generic/pt-atfork.c b/libpthread/sysdeps/generic/pt-atfork.c new file mode 100644 index 00000000..32e1e78c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-atfork.c @@ -0,0 +1,29 @@ +/* Register fork handlers. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_atfork (void (*prepare) (void), + void (*parent) (void), + void (*child) (void)) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-attr-destroy.c b/libpthread/sysdeps/generic/pt-attr-destroy.c new file mode 100644 index 00000000..c4b9aa54 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_attr_destroy. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_destroy (pthread_attr_t *attr) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getdetachstate.c b/libpthread/sysdeps/generic/pt-attr-getdetachstate.c new file mode 100644 index 00000000..be406f1d --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getdetachstate.c @@ -0,0 +1,29 @@ +/* pthread_attr_getdetachstate. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_getdetachstate (const pthread_attr_t *attr, + int *detachstate) +{ + *detachstate = attr->detachstate; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getguardsize.c b/libpthread/sysdeps/generic/pt-attr-getguardsize.c new file mode 100644 index 00000000..c1d9f13e --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getguardsize.c @@ -0,0 +1,29 @@ +/* pthread_attr_getguardsize. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_getguardsize (const pthread_attr_t *attr, + size_t *guardsize) +{ + *guardsize = attr->guardsize; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getinheritsched.c b/libpthread/sysdeps/generic/pt-attr-getinheritsched.c new file mode 100644 index 00000000..cca4e3d7 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getinheritsched.c @@ -0,0 +1,29 @@ +/* pthread_attr_getinheritsched. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_getinheritsched (const pthread_attr_t *attr, + int *inheritsched) +{ + *inheritsched = attr->inheritsched; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getschedparam.c b/libpthread/sysdeps/generic/pt-attr-getschedparam.c new file mode 100644 index 00000000..6c3f15be --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getschedparam.c @@ -0,0 +1,31 @@ +/* pthread_attr_getschedparam. Generic 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. */ + +#include <pthread.h> +#include <sched.h> + +#include <pt-internal.h> + +int +pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param) +{ + memcpy (param, &attr->schedparam, sizeof *param); + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getschedpolicy.c b/libpthread/sysdeps/generic/pt-attr-getschedpolicy.c new file mode 100644 index 00000000..4349a238 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getschedpolicy.c @@ -0,0 +1,29 @@ +/* pthread_attr_getschedpolicy. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_getschedpolicy (const pthread_attr_t *attr, + int *policy) +{ + *policy = attr->schedpolicy; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getscope.c b/libpthread/sysdeps/generic/pt-attr-getscope.c new file mode 100644 index 00000000..97198fa5 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getscope.c @@ -0,0 +1,29 @@ +/* pthread_attr_getscope. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_getscope (const pthread_attr_t *attr, + int *contentionscope) +{ + *contentionscope = attr->contentionscope; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getstack.c b/libpthread/sysdeps/generic/pt-attr-getstack.c new file mode 100644 index 00000000..7beb79f0 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getstack.c @@ -0,0 +1,31 @@ +/* pthread_attr_getstack. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_getstack (const pthread_attr_t *attr, + void **stackaddr, + size_t *stacksize) +{ + pthread_attr_getstackaddr (attr, stackaddr); + pthread_attr_getstacksize (attr, stacksize); + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getstackaddr.c b/libpthread/sysdeps/generic/pt-attr-getstackaddr.c new file mode 100644 index 00000000..d43eeff7 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getstackaddr.c @@ -0,0 +1,29 @@ +/* pthread_attr_getstackaddr. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_getstackaddr (const pthread_attr_t *attr, + void **stackaddr) +{ + *stackaddr = attr->stackaddr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getstacksize.c b/libpthread/sysdeps/generic/pt-attr-getstacksize.c new file mode 100644 index 00000000..c1bc6617 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getstacksize.c @@ -0,0 +1,29 @@ +/* pthread_attr_getstacksize. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_getstacksize (const pthread_attr_t *attr, + size_t *stacksize) +{ + *stacksize = attr->stacksize; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-init.c b/libpthread/sysdeps/generic/pt-attr-init.c new file mode 100644 index 00000000..6a930e30 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-init.c @@ -0,0 +1,28 @@ +/* pthread_attr_init. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_init (pthread_attr_t *attr) +{ + *attr = __pthread_default_attr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setdetachstate.c b/libpthread/sysdeps/generic/pt-attr-setdetachstate.c new file mode 100644 index 00000000..688ba5d6 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setdetachstate.c @@ -0,0 +1,38 @@ +/* pthread_attr_setdetachstate. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate) +{ + switch (detachstate) + { + case PTHREAD_CREATE_DETACHED: + case PTHREAD_CREATE_JOINABLE: + attr->detachstate = detachstate; + break; + default: + return EINVAL; + } + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setguardsize.c b/libpthread/sysdeps/generic/pt-attr-setguardsize.c new file mode 100644 index 00000000..b2ba0f0f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setguardsize.c @@ -0,0 +1,29 @@ +/* pthread_attr_setguardsize. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_setguardsize (pthread_attr_t *attr, + size_t guardsize) +{ + attr->guardsize = guardsize; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setinheritsched.c b/libpthread/sysdeps/generic/pt-attr-setinheritsched.c new file mode 100644 index 00000000..e9012c58 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setinheritsched.c @@ -0,0 +1,38 @@ +/* pthread_attr_setinheritsched. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_setinheritsched (pthread_attr_t *attr, + int inheritsched) +{ + switch (inheritsched) + { + case PTHREAD_INHERIT_SCHED: + case PTHREAD_EXPLICIT_SCHED: + attr->inheritsched = inheritsched; + break; + default: + return EINVAL; + } + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setschedparam.c b/libpthread/sysdeps/generic/pt-attr-setschedparam.c new file mode 100644 index 00000000..5459f108 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setschedparam.c @@ -0,0 +1,38 @@ +/* pthread_attr_getschedparam. Generic 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. */ + +#include <pthread.h> +#include <sched.h> +#include <string.h> + +#include <pt-internal.h> + +int +pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param) +{ + if (memcmp (param, &__pthread_default_attr.schedparam, + sizeof *param) == 0) + { + memcpy (&attr->schedparam, param, sizeof *param); + return 0; + } + + return ENOTSUP; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setschedpolicy.c b/libpthread/sysdeps/generic/pt-attr-setschedpolicy.c new file mode 100644 index 00000000..e481d04c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setschedpolicy.c @@ -0,0 +1,42 @@ +/* pthread_attr_getschedpolicy. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_setschedpolicy (pthread_attr_t *attr, + int policy) +{ + switch (policy) + { + case SCHED_OTHER: + attr->schedpolicy = policy; + break; + + case SCHED_FIFO: + case SCHED_RR: + return ENOTSUP; + + default: + return EINVAL; + } + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setscope.c b/libpthread/sysdeps/generic/pt-attr-setscope.c new file mode 100644 index 00000000..c74a4f67 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setscope.c @@ -0,0 +1,41 @@ +/* pthread_attr_setscope. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_setscope (pthread_attr_t *attr, + int contentionscope) +{ + if (contentionscope == __pthread_default_attr.contentionscope) + { + attr->contentionscope = contentionscope; + return 0; + } + + switch (contentionscope) + { + case PTHREAD_SCOPE_PROCESS: + case PTHREAD_SCOPE_SYSTEM: + return ENOTSUP; + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-attr-setstack.c b/libpthread/sysdeps/generic/pt-attr-setstack.c new file mode 100644 index 00000000..360d27a3 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setstack.c @@ -0,0 +1,51 @@ +/* pthread_attr_setstack. Generic 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. */ + +#include <pthread.h> +#include <assert.h> + +#include <pt-internal.h> + +int +pthread_attr_setstack (pthread_attr_t *attr, + void *stackaddr, + size_t stacksize) +{ + int err; + size_t s; + + /* pthread_attr_setstack should always succeed, thus we set the size + first as it is more discriminating. */ + pthread_attr_getstacksize (attr, &s); + + err = pthread_attr_setstacksize (attr, stacksize); + if (err) + return err; + + err = pthread_attr_setstackaddr (attr, stackaddr); + if (err) + { + int e = pthread_attr_setstacksize (attr, s); + assert_perror (e); + + return err; + } + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setstackaddr.c b/libpthread/sysdeps/generic/pt-attr-setstackaddr.c new file mode 100644 index 00000000..431f2d0c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setstackaddr.c @@ -0,0 +1,29 @@ +/* pthread_attr_setstackaddr. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_setstackaddr (pthread_attr_t *attr, + void *stackaddr) +{ + attr->stackaddr = stackaddr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setstacksize.c b/libpthread/sysdeps/generic/pt-attr-setstacksize.c new file mode 100644 index 00000000..d0e51022 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setstacksize.c @@ -0,0 +1,41 @@ +/* pthread_attr_setstacksize. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_setstacksize (pthread_attr_t *attr, + size_t stacksize) +{ + if (stacksize == __pthread_default_attr.stacksize) + { + attr->stacksize = stacksize; + + /* The guard size cannot be larger than the stack itself, as + such, if the new stack size is smaller than the guard size, + we squash the guard size. */ + if (attr->guardsize > attr->stacksize) + attr->guardsize = attr->stacksize; + + return 0; + } + + return ENOTSUP; +} diff --git a/libpthread/sysdeps/generic/pt-attr.c b/libpthread/sysdeps/generic/pt-attr.c new file mode 100644 index 00000000..769f292a --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr.c @@ -0,0 +1,41 @@ +/* Default attributes. Generic version. + Copyright (C) 2000,02 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 <pthread.h> +#include <sched.h> +#include <stddef.h> +#include <limits.h> + +#include <pt-internal.h> + +const struct __pthread_attr __pthread_default_attr = +{ + schedparam: { sched_priority: 0 }, + stacksize: PTHREAD_STACK_DEFAULT, + stackaddr: NULL, +#ifdef PAGESIZE + guardsize: PAGESIZE, +#else + guardsize: 0, +#endif /* PAGESIZE */ + detachstate: PTHREAD_CREATE_JOINABLE, + inheritsched: PTHREAD_EXPLICIT_SCHED, + contentionscope: PTHREAD_SCOPE_SYSTEM, + schedpolicy: SCHED_OTHER +}; diff --git a/libpthread/sysdeps/generic/pt-barrier-destroy.c b/libpthread/sysdeps/generic/pt-barrier-destroy.c new file mode 100644 index 00000000..01b938b4 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrier-destroy.c @@ -0,0 +1,27 @@ +/* pthread_barrier_destroy. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_barrier_destroy (pthread_barrier_t *barrier) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-barrier-init.c b/libpthread/sysdeps/generic/pt-barrier-init.c new file mode 100644 index 00000000..c42b3bb6 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrier-init.c @@ -0,0 +1,53 @@ +/* pthread_barrier_init. Generic version. + 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 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 <pthread.h> +#include <string.h> +#include <assert.h> + +#include <pt-internal.h> + +int +pthread_barrier_init (pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned count) +{ + if (count == 0) + return EINVAL; + + memset (barrier, 0, sizeof *barrier); + + barrier->lock = PTHREAD_SPINLOCK_INITIALIZER; + barrier->pending = count; + barrier->count = count; + + if (! attr + || memcmp (attr, &__pthread_default_barrierattr, sizeof (*attr) == 0)) + /* Use the default attributes. */ + return 0; + + /* Non-default attributes. */ + + barrier->attr = malloc (sizeof *attr); + if (! barrier->attr) + return ENOMEM; + + *barrier->attr = *attr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-barrier-wait.c b/libpthread/sysdeps/generic/pt-barrier-wait.c new file mode 100644 index 00000000..f1de250a --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrier-wait.c @@ -0,0 +1,61 @@ +/* pthread_barrier_wait. Generic 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. */ + +#include <pthread.h> +#include <assert.h> + +#include <pt-internal.h> + +int +pthread_barrier_wait (pthread_barrier_t *barrier) +{ + __pthread_spin_lock (&barrier->lock); + if (-- barrier->pending == 0) + { + barrier->pending = barrier->count; + + if (barrier->count > 1) + { + struct __pthread *wakeup; + + wakeup = barrier->queue; + barrier->queue = NULL; + __pthread_spin_unlock (&barrier->lock); + + /* We can safely walk the list of waiting threads without + holding the lock since it is decoupled from the barrier + variable now. */ + __pthread_dequeuing_iterate (wakeup, wakeup) + __pthread_wakeup (wakeup); + } + + return PTHREAD_BARRIER_SERIAL_THREAD; + } + else + { + struct __pthread *self = _pthread_self (); + + /* Add ourselves to the list of waiters. */ + __pthread_enqueue (&barrier->queue, self); + __pthread_spin_unlock (&barrier->lock); + + __pthread_block (self); + return 0; + } +} diff --git a/libpthread/sysdeps/generic/pt-barrier.c b/libpthread/sysdeps/generic/pt-barrier.c new file mode 100644 index 00000000..d772719f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrier.c @@ -0,0 +1,26 @@ +/* Default barrier attributes. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +const struct __pthread_barrierattr __pthread_default_barrierattr = +{ + pshared: PTHREAD_PROCESS_PRIVATE +}; diff --git a/libpthread/sysdeps/generic/pt-barrierattr-destroy.c b/libpthread/sysdeps/generic/pt-barrierattr-destroy.c new file mode 100644 index 00000000..eb396347 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrierattr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_barrierattr_destroy. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_barrierattr_destroy (pthread_barrierattr_t *attr) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-barrierattr-getpshared.c b/libpthread/sysdeps/generic/pt-barrierattr-getpshared.c new file mode 100644 index 00000000..ed2cdd24 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrierattr-getpshared.c @@ -0,0 +1,29 @@ +/* pthread_barrierattr_getpshared. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_barrierattr_getpshared (const pthread_barrierattr_t *attr, + int *pshared) +{ + *pshared = attr->pshared; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-barrierattr-init.c b/libpthread/sysdeps/generic/pt-barrierattr-init.c new file mode 100644 index 00000000..45f16cc8 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrierattr-init.c @@ -0,0 +1,28 @@ +/* pthread_barrierattr_init. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_barrierattr_init (pthread_barrierattr_t *attr) +{ + *attr = __pthread_default_barrierattr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-barrierattr-setpshared.c b/libpthread/sysdeps/generic/pt-barrierattr-setpshared.c new file mode 100644 index 00000000..84ef2df8 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrierattr-setpshared.c @@ -0,0 +1,39 @@ +/* pthread_barrierattr_setpshared. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_barrierattr_setpshared (pthread_barrierattr_t *attr, + int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->pshared = pshared; + return 0; + + case PTHREAD_PROCESS_SHARED: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-cond-brdcast.c b/libpthread/sysdeps/generic/pt-cond-brdcast.c new file mode 100644 index 00000000..3f55e33e --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond-brdcast.c @@ -0,0 +1,42 @@ +/* Broadcast a condition. Generic version. + Copyright (C) 2000, 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. */ + +#include <pthread.h> + +#include <pt-internal.h> + +/* Unblock all threads that are blocked on condition variable COND. */ +int +pthread_cond_broadcast (pthread_cond_t *cond) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&cond->__lock); + + wakeup = cond->__queue; + cond->__queue = NULL; + __pthread_spin_unlock (&cond->__lock); + + /* We can safely walk the list of waiting threads without holding + the lock since it is now decoupled from the condition. */ + __pthread_dequeuing_iterate (wakeup, wakeup) + __pthread_wakeup (wakeup); + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-cond-destroy.c b/libpthread/sysdeps/generic/pt-cond-destroy.c new file mode 100644 index 00000000..eba47784 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond-destroy.c @@ -0,0 +1,27 @@ +/* pthread_cond_destroy. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_cond_destroy (pthread_cond_t *cond) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-cond-init.c b/libpthread/sysdeps/generic/pt-cond-init.c new file mode 100644 index 00000000..b9e9fb7a --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond-init.c @@ -0,0 +1,45 @@ +/* pthread_cond_init. Generic 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. */ + +#include <pthread.h> +#include <assert.h> +#include <string.h> + +#include <pt-internal.h> + +int +pthread_cond_init (pthread_cond_t *cond, + const pthread_condattr_t *attr) +{ + *cond = (pthread_cond_t) __PTHREAD_COND_INITIALIZER; + + if (! attr + || memcmp (attr, &__pthread_default_condattr, sizeof (*attr) == 0)) + /* Use the default attributes. */ + return 0; + + /* Non-default attributes. */ + + cond->__attr = malloc (sizeof *attr); + if (! cond->__attr) + return ENOMEM; + + *cond->__attr = *attr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-cond-signal.c b/libpthread/sysdeps/generic/pt-cond-signal.c new file mode 100644 index 00000000..c5e1bc1d --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond-signal.c @@ -0,0 +1,54 @@ +/* Signal a condition. Generic version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <pthread.h> + +#include <pt-internal.h> + +static int +cond_signal (struct __pthread_cond *cond, int *unblocked) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&cond->__lock); + wakeup = cond->__queue; + if (wakeup) + __pthread_dequeue (wakeup); + __pthread_spin_unlock (&cond->__lock); + + if (wakeup) + { + /* We found a thread waiting for the condition to be signalled. + Wake it up! */ + __pthread_wakeup (wakeup); + *unblocked = 1; + } + + return 0; +} + +/* Unblock at least one of the threads that are blocked on condition + variable COND. */ +int +pthread_cond_signal (pthread_cond_t *cond) +{ + int unblocked = 0; + + return cond_signal (cond, &unblocked); +} diff --git a/libpthread/sysdeps/generic/pt-cond-timedwait.c b/libpthread/sysdeps/generic/pt-cond-timedwait.c new file mode 100644 index 00000000..c10bdb30 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond-timedwait.c @@ -0,0 +1,106 @@ +/* Wait on a condition. Generic version. + Copyright (C) 2000, 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 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 <pthread.h> + +#include <pt-internal.h> + +extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); + +int +pthread_cond_timedwait (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + return __pthread_cond_timedwait_internal (cond, mutex, abstime); +} + +/* Block on condition variable COND until ABSTIME. As a GNU + extension, if ABSTIME is NULL, then wait forever. MUTEX should be + held by the calling thread. On return, MUTEX will be held by the + calling thread. */ +int +__pthread_cond_timedwait_internal (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + error_t err; + int canceltype; + + void cleanup (void *arg) + { + struct __pthread *self = _pthread_self (); + + __pthread_spin_lock (&cond->__lock); + if (self->prevp) + __pthread_dequeue (self); + __pthread_spin_unlock (&cond->__lock); + + pthread_setcanceltype (canceltype, &canceltype); + __pthread_mutex_lock (mutex); + } + + if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + + struct __pthread *self = _pthread_self (); + + /* Add ourselves to the list of waiters. */ + __pthread_spin_lock (&cond->__lock); + __pthread_enqueue (&cond->__queue, self); + __pthread_spin_unlock (&cond->__lock); + + __pthread_mutex_unlock (mutex); + + /* Enter async cancelation mode. If cancelation is disabled, then + this does not change anything which is exactly what we want. */ + pthread_cleanup_push (cleanup, 0); + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &canceltype); + + if (abstime) + { + err = __pthread_timedblock (self, abstime); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err == ETIMEDOUT); + + __pthread_spin_lock (&mutex->__lock); + if (self->prevp) + __pthread_dequeue (self); + __pthread_spin_unlock (&mutex->__lock); + } + } + else + { + err = 0; + __pthread_block (self); + } + + pthread_cleanup_pop (1); + + return err; +} diff --git a/libpthread/sysdeps/generic/pt-cond-wait.c b/libpthread/sysdeps/generic/pt-cond-wait.c new file mode 100644 index 00000000..a03476df --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond-wait.c @@ -0,0 +1,37 @@ +/* Wait on a condition. Generic version. + Copyright (C) 2000,02 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 <pthread.h> + +#include <pt-internal.h> + +/* Implemented in pt-cond-timedwait.c. */ +extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); + + +/* Block on condition variable COND. MUTEX should be held by the + calling thread. On return, MUTEX will be held by the calling + thread. */ +int +pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + return __pthread_cond_timedwait_internal (cond, mutex, 0); +} diff --git a/libpthread/sysdeps/generic/pt-cond.c b/libpthread/sysdeps/generic/pt-cond.c new file mode 100644 index 00000000..033e767f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond.c @@ -0,0 +1,29 @@ +/* Default condition attributes. Generic 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. */ + +#include <pthread.h> +#include <time.h> + +#include <pt-internal.h> + +const struct __pthread_condattr __pthread_default_condattr = +{ + pshared: PTHREAD_PROCESS_PRIVATE, + clock: CLOCK_REALTIME +}; diff --git a/libpthread/sysdeps/generic/pt-condattr-destroy.c b/libpthread/sysdeps/generic/pt-condattr-destroy.c new file mode 100644 index 00000000..c8fd71b9 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-condattr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_condattr_destroy. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_condattr_destroy (pthread_condattr_t *cond) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-condattr-getclock.c b/libpthread/sysdeps/generic/pt-condattr-getclock.c new file mode 100644 index 00000000..5b9f8893 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-condattr-getclock.c @@ -0,0 +1,31 @@ +/* pthread_condattr_getclock. Generic 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. */ + +#include <pthread.h> +#include <time.h> + +#include <pt-internal.h> + +int +pthread_condattr_getclock (const pthread_condattr_t *attr, + clockid_t *clock) +{ + *clock = attr->clock; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-condattr-getpshared.c b/libpthread/sysdeps/generic/pt-condattr-getpshared.c new file mode 100644 index 00000000..c072a507 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-condattr-getpshared.c @@ -0,0 +1,29 @@ +/* pthread_condattr_getpshared. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_condattr_getpshared (const pthread_condattr_t *attr, + int *pshared) +{ + *pshared = attr->pshared; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-condattr-init.c b/libpthread/sysdeps/generic/pt-condattr-init.c new file mode 100644 index 00000000..cf9e1989 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-condattr-init.c @@ -0,0 +1,28 @@ +/* pthread_condattr_init. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_condattr_init (pthread_condattr_t *attr) +{ + *attr = __pthread_default_condattr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-condattr-setclock.c b/libpthread/sysdeps/generic/pt-condattr-setclock.c new file mode 100644 index 00000000..984c17e2 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-condattr-setclock.c @@ -0,0 +1,33 @@ +/* pthread_condattr_setclock. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock) +{ + if (__pthread_default_condattr.clock == clock) + { + attr->clock = clock; + return 0; + } + + return EINVAL; +} diff --git a/libpthread/sysdeps/generic/pt-condattr-setpshared.c b/libpthread/sysdeps/generic/pt-condattr-setpshared.c new file mode 100644 index 00000000..b9f0af83 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-condattr-setpshared.c @@ -0,0 +1,39 @@ +/* pthread_condattr_setpshared. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_condattr_setpshared (pthread_condattr_t *attr, + int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->pshared = pshared; + return 0; + + case PTHREAD_PROCESS_SHARED: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-destroy-specific.c b/libpthread/sysdeps/generic/pt-destroy-specific.c new file mode 100644 index 00000000..b627f872 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-destroy-specific.c @@ -0,0 +1,28 @@ +/* __pthread_destory_specific. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +void +__pthread_destory_specifc (struct __pthread *thread) +{ + /* Not support, thus there cannot be any. */ + return; +} diff --git a/libpthread/sysdeps/generic/pt-equal.c b/libpthread/sysdeps/generic/pt-equal.c new file mode 100644 index 00000000..8fbc519c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-equal.c @@ -0,0 +1,29 @@ +/* Default attributes. Generic version. + Copyright (C) 2000,02 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 <pthread.h> +#include <pt-internal.h> + +/* Return true if __T1 and __T2 both name the same thread. Otherwise, + false. */ +int +pthread_equal (pthread_t __t1, pthread_t __t2) +{ + return __t1 == __t2; +} diff --git a/libpthread/sysdeps/generic/pt-getconcurrency.c b/libpthread/sysdeps/generic/pt-getconcurrency.c new file mode 100644 index 00000000..b55c8eef --- /dev/null +++ b/libpthread/sysdeps/generic/pt-getconcurrency.c @@ -0,0 +1,27 @@ +/* Get the current level of desired concurrency. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_getconcurrency (void) +{ + return __pthread_concurrency; +} diff --git a/libpthread/sysdeps/generic/pt-getcpuclockid.c b/libpthread/sysdeps/generic/pt-getcpuclockid.c new file mode 100644 index 00000000..81f6aabd --- /dev/null +++ b/libpthread/sysdeps/generic/pt-getcpuclockid.c @@ -0,0 +1,34 @@ +/* Return a thread's cpu clockid. Generic 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. */ + +#include <pthread.h> +#include <time.h> + +#include <pt-internal.h> + +int +pthread_getcpuclockid (pthread_t thread, clockid_t *clock) +{ +#ifdef CLOCK_THREAD_CPUTIME_ID + *clock = CLOCK_THREAD_CPUTIME_ID; + return 0; +#else + return ENOSYS; +#endif +} diff --git a/libpthread/sysdeps/generic/pt-getschedparam.c b/libpthread/sysdeps/generic/pt-getschedparam.c new file mode 100644 index 00000000..c128d02e --- /dev/null +++ b/libpthread/sysdeps/generic/pt-getschedparam.c @@ -0,0 +1,28 @@ +/* Get the scheduling parameters for a thread. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_getschedparam (pthread_t thread, int *policy, + struct sched_param *param) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-getspecific.c b/libpthread/sysdeps/generic/pt-getspecific.c new file mode 100644 index 00000000..2a7c4a9e --- /dev/null +++ b/libpthread/sysdeps/generic/pt-getspecific.c @@ -0,0 +1,27 @@ +/* pthread_getspecific. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_getspecific (pthread_key_t key) +{ + return EINVAL; +} diff --git a/libpthread/sysdeps/generic/pt-init-specific.c b/libpthread/sysdeps/generic/pt-init-specific.c new file mode 100644 index 00000000..00744fb6 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-init-specific.c @@ -0,0 +1,27 @@ +/* __pthread_init_specific. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +error_t +__pthread_init_specific (struct __pthread *thread) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-key-create.c b/libpthread/sysdeps/generic/pt-key-create.c new file mode 100644 index 00000000..7ef4b991 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-key-create.c @@ -0,0 +1,27 @@ +/* pthread_key_create. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_key_create (pthread_key_t *key, void (*destructor) (void *)) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-key-delete.c b/libpthread/sysdeps/generic/pt-key-delete.c new file mode 100644 index 00000000..6c86f8e2 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-key-delete.c @@ -0,0 +1,27 @@ +/* pthread_key_delete. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_key_delete (pthread_key_t key) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-key.h b/libpthread/sysdeps/generic/pt-key.h new file mode 100644 index 00000000..544eb20f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-key.h @@ -0,0 +1,22 @@ +/* pthread_key internal declatations. Generic 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. */ + +#include <pthread.h> + +#define PTHREAD_KEY_MEMBERS diff --git a/libpthread/sysdeps/generic/pt-kill.c b/libpthread/sysdeps/generic/pt-kill.c new file mode 100644 index 00000000..0dfac344 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-kill.c @@ -0,0 +1,32 @@ +/* pthread-kill.c - Generic pthread-kill implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +int +pthread_kill (pthread_t tid, int signo) +{ + siginfo_t si; + memset (&si, 0, sizeof (si)); + si.si_signo = signo; + + return pthread_kill_siginfo_np (tid, si); +} + diff --git a/libpthread/sysdeps/generic/pt-mutex-destroy.c b/libpthread/sysdeps/generic/pt-mutex-destroy.c new file mode 100644 index 00000000..3bbc73fe --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-destroy.c @@ -0,0 +1,39 @@ +/* Destroy a mutex. Generic version. + Copyright (C) 2000, 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <pthread.h> +#include <stdlib.h> +#include <assert.h> + +#include <pt-internal.h> + +int +_pthread_mutex_destroy (pthread_mutex_t *mutex) +{ + if (mutex->attr == __PTHREAD_ERRORCHECK_MUTEXATTR + || mutex->attr == __PTHREAD_RECURSIVE_MUTEXATTR) + /* Static attributes. */ + ; + else + free (mutex->attr); + + return 0; +} + +strong_alias (_pthread_mutex_destroy, pthread_mutex_destroy); diff --git a/libpthread/sysdeps/generic/pt-mutex-getprioceiling.c b/libpthread/sysdeps/generic/pt-mutex-getprioceiling.c new file mode 100644 index 00000000..eb51639b --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-getprioceiling.c @@ -0,0 +1,28 @@ +/* Get a mutex' priority ceiling. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, + int *prioceiling) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-mutex-init.c b/libpthread/sysdeps/generic/pt-mutex-init.c new file mode 100644 index 00000000..2f960286 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-init.c @@ -0,0 +1,50 @@ +/* Initialize a mutex. Generic version. + Copyright (C) 2000, 2002, 2005, 2006, 2008 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 <pthread.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> + +#include <pt-internal.h> + +int +_pthread_mutex_init (pthread_mutex_t *mutex, + const pthread_mutexattr_t *attr) +{ + *mutex = (pthread_mutex_t) __PTHREAD_MUTEX_INITIALIZER; + + if (! attr + || memcmp (attr, &__pthread_default_mutexattr, sizeof (*attr) == 0)) + /* The default attributes. */ + return 0; + + if (! mutex->attr + || mutex->attr == __PTHREAD_ERRORCHECK_MUTEXATTR + || mutex->attr == __PTHREAD_RECURSIVE_MUTEXATTR) + mutex->attr = malloc (sizeof *attr); + + if (! mutex->attr) + return ENOMEM; + + *mutex->attr = *attr; + return 0; +} + +strong_alias (_pthread_mutex_init, pthread_mutex_init); diff --git a/libpthread/sysdeps/generic/pt-mutex-lock.c b/libpthread/sysdeps/generic/pt-mutex-lock.c new file mode 100644 index 00000000..528e593f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-lock.c @@ -0,0 +1,37 @@ +/* Lock a mutex. Generic version. + Copyright (C) 2000, 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <pthread.h> +#include <assert.h> + +#include <pt-internal.h> + +/* Implemented in pt-mutex-timedlock.c. */ +extern int __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, + const struct timespec *abstime); + +/* Lock MUTEX, block if we can't get it. */ +int +__pthread_mutex_lock (struct __pthread_mutex *mutex) +{ + return __pthread_mutex_timedlock_internal (mutex, 0); +} + +strong_alias (__pthread_mutex_lock, _pthread_mutex_lock); +strong_alias (__pthread_mutex_lock, pthread_mutex_lock); diff --git a/libpthread/sysdeps/generic/pt-mutex-setprioceiling.c b/libpthread/sysdeps/generic/pt-mutex-setprioceiling.c new file mode 100644 index 00000000..9fa8e50d --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-setprioceiling.c @@ -0,0 +1,28 @@ +/* Set a mutex' priority ceiling. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prio, + int *oldprio) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-mutex-timedlock.c b/libpthread/sysdeps/generic/pt-mutex-timedlock.c new file mode 100644 index 00000000..883e50af --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-timedlock.c @@ -0,0 +1,187 @@ +/* Lock a mutex with a timeout. Generic version. + Copyright (C) 2000, 2002, 2005, 2008 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 <pthread.h> +#include <assert.h> + +#include <pt-internal.h> + +#define LOSE do { * (int *) 0 = 0; } while (1) + +/* Try to lock MUTEX, block until *ABSTIME if it is already held. As + a GNU extension, if TIMESPEC is NULL then wait forever. */ +int +__pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, + const struct timespec *abstime) +{ + struct __pthread *self; + const struct __pthread_mutexattr *attr = mutex->attr; + + if (attr == __PTHREAD_ERRORCHECK_MUTEXATTR) + attr = &__pthread_errorcheck_mutexattr; + if (attr == __PTHREAD_RECURSIVE_MUTEXATTR) + attr = &__pthread_recursive_mutexattr; + + __pthread_spin_lock (&mutex->__lock); + if (__pthread_spin_trylock (&mutex->__held) == 0) + /* Successfully acquired the lock. */ + { +#ifdef ALWAYS_TRACK_MUTEX_OWNER +#ifndef NDEBUG + self = _pthread_self (); + if (self) + /* The main thread may take a lock before the library is fully + initialized, in particular, before the main thread has a + TCB. */ + { + assert (! mutex->owner); + mutex->owner = _pthread_self (); + } +#endif +#endif + + if (attr) + switch (attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_RECURSIVE: + mutex->locks = 1; + case PTHREAD_MUTEX_ERRORCHECK: + mutex->owner = _pthread_self (); + break; + + default: + LOSE; + } + + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + + /* The lock is busy. */ + + self = _pthread_self (); + assert (self); + + if (! attr || attr->mutex_type == PTHREAD_MUTEX_NORMAL) + { +#if defined(ALWAYS_TRACK_MUTEX_OWNER) + assert (mutex->owner != self); +#endif + } + else + { + switch (attr->mutex_type) + { + case PTHREAD_MUTEX_ERRORCHECK: + if (mutex->owner == self) + { + __pthread_spin_unlock (&mutex->__lock); + return EDEADLK; + } + break; + + case PTHREAD_MUTEX_RECURSIVE: + if (mutex->owner == self) + { + mutex->locks ++; + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + break; + + default: + LOSE; + } + } + +#if !defined(ALWAYS_TRACK_MUTEX_OWNER) + if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL) +#endif + assert (mutex->owner); + + if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + + /* Add ourselves to the queue. */ + __pthread_enqueue (&mutex->__queue, self); + __pthread_spin_unlock (&mutex->__lock); + + /* Block the thread. */ + if (abstime) + { + error_t err; + + err = __pthread_timedblock (self, abstime); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err == ETIMEDOUT); + + __pthread_spin_lock (&mutex->__lock); + if (self->prevp) + __pthread_dequeue (self); + __pthread_spin_unlock (&mutex->__lock); + + return err; + } + } + else + __pthread_block (self); + +#if !defined(ALWAYS_TRACK_MUTEX_OWNER) + if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL) +#endif + { + assert (mutex->owner == self); + } + + if (attr) + switch (attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_RECURSIVE: + assert (mutex->locks == 0); + mutex->locks = 1; + case PTHREAD_MUTEX_ERRORCHECK: + mutex->owner = self; + break; + + default: + LOSE; + } + + return 0; +} + +int +pthread_mutex_timedlock (struct __pthread_mutex *mutex, + const struct timespec *abstime) +{ + return __pthread_mutex_timedlock_internal (mutex, abstime); +} diff --git a/libpthread/sysdeps/generic/pt-mutex-transfer-np.c b/libpthread/sysdeps/generic/pt-mutex-transfer-np.c new file mode 100644 index 00000000..967f1c7c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-transfer-np.c @@ -0,0 +1,66 @@ +/* Transfer ownership of a mutex. Generic version. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <pthread.h> +#include <assert.h> + +#include <pt-internal.h> + +int +__pthread_mutex_transfer_np (struct __pthread_mutex *mutex, pthread_t tid) +{ + assert (mutex->owner == _pthread_self ()); + + struct __pthread *thread = __pthread_getid (tid); + const struct __pthread_mutexattr *attr = mutex->attr; + + if (! thread) + return ESRCH; + + if (thread == _pthread_self ()) + return 0; + + if (attr == __PTHREAD_ERRORCHECK_MUTEXATTR) + attr = &__pthread_errorcheck_mutexattr; + if (attr == __PTHREAD_RECURSIVE_MUTEXATTR) + attr = &__pthread_recursive_mutexattr; + + if (attr && attr->mutex_type == PTHREAD_MUTEX_ERRORCHECK) + { + + if (mutex->owner != _pthread_self ()) + return EPERM; + + mutex->owner = thread; + } + +#ifndef NDEBUG +# if !defined(ALWAYS_TRACK_MUTEX_OWNER) + if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL) +# endif + { + mutex->owner = thread; + } +#endif + + return 0; +} + +strong_alias (__pthread_mutex_transfer_np, pthread_mutex_transfer_np) diff --git a/libpthread/sysdeps/generic/pt-mutex-trylock.c b/libpthread/sysdeps/generic/pt-mutex-trylock.c new file mode 100644 index 00000000..7a54cc9a --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-trylock.c @@ -0,0 +1,112 @@ +/* Try to Lock a mutex. Generic version. + Copyright (C) 2002, 2005, 2008 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 <pthread.h> + +#include <pt-internal.h> + +#define LOSE do { * (int *) 0 = 0; } while (1) + +/* Lock MUTEX, return EBUSY if we can't get it. */ +int +__pthread_mutex_trylock (struct __pthread_mutex *mutex) +{ + int err; + struct __pthread *self; + const struct __pthread_mutexattr *attr = mutex->attr; + + if (attr == __PTHREAD_ERRORCHECK_MUTEXATTR) + attr = &__pthread_errorcheck_mutexattr; + if (attr == __PTHREAD_RECURSIVE_MUTEXATTR) + attr = &__pthread_recursive_mutexattr; + + __pthread_spin_lock (&mutex->__lock); + if (__pthread_spin_trylock (&mutex->__held) == 0) + /* Acquired the lock. */ + { +#if defined(ALWAYS_TRACK_MUTEX_OWNER) +#ifndef NDEBUG + self = _pthread_self (); + if (self) + /* The main thread may take a lock before the library is fully + initialized, in particular, before the main thread has a + TCB. */ + { + assert (! mutex->owner); + mutex->owner = _pthread_self (); + } +#endif +#endif + + if (attr) + switch (attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_RECURSIVE: + mutex->locks = 1; + case PTHREAD_MUTEX_ERRORCHECK: + mutex->owner = _pthread_self (); + break; + + default: + LOSE; + } + + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + + err = EBUSY; + + if (attr) + { + self = _pthread_self (); + switch (attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_ERRORCHECK: + /* We could check if MUTEX->OWNER is SELF, however, POSIX + does not permit pthread_mutex_trylock to return EDEADLK + instead of EBUSY, only pthread_mutex_lock. */ + break; + + case PTHREAD_MUTEX_RECURSIVE: + if (mutex->owner == self) + { + mutex->locks ++; + err = 0; + } + break; + + default: + LOSE; + } + } + + __pthread_spin_unlock (&mutex->__lock); + + return err; +} + +strong_alias (__pthread_mutex_trylock, _pthread_mutex_trylock); +strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock); diff --git a/libpthread/sysdeps/generic/pt-mutex-unlock.c b/libpthread/sysdeps/generic/pt-mutex-unlock.c new file mode 100644 index 00000000..09d70f8f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-unlock.c @@ -0,0 +1,108 @@ +/* Unlock a mutex. Generic version. + Copyright (C) 2000, 2002, 2008 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 <pthread.h> + +#include <pt-internal.h> + +#define LOSE do { * (int *) 0 = 0; } while (1) + +/* Unlock MUTEX, rescheduling a waiting thread. */ +int +__pthread_mutex_unlock (pthread_mutex_t *mutex) +{ + struct __pthread *wakeup; + const struct __pthread_mutexattr *attr = mutex->attr; + + if (attr == __PTHREAD_ERRORCHECK_MUTEXATTR) + attr = &__pthread_errorcheck_mutexattr; + if (attr == __PTHREAD_RECURSIVE_MUTEXATTR) + attr = &__pthread_recursive_mutexattr; + + __pthread_spin_lock (&mutex->__lock); + + if (! attr || attr->mutex_type == PTHREAD_MUTEX_NORMAL) + { +#if defined(ALWAYS_TRACK_MUTEX_OWNER) +# ifndef NDEBUG + if (_pthread_self ()) + { + assert (mutex->owner); + assert (mutex->owner == _pthread_self ()); + mutex->owner = NULL; + } +# endif +#endif + } + else + switch (attr->mutex_type) + { + case PTHREAD_MUTEX_ERRORCHECK: + case PTHREAD_MUTEX_RECURSIVE: + if (mutex->owner != _pthread_self ()) + { + __pthread_spin_unlock (&mutex->__lock); + return EPERM; + } + + if (attr->mutex_type == PTHREAD_MUTEX_RECURSIVE) + if (--mutex->locks > 0) + { + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + + mutex->owner = 0; + break; + + default: + LOSE; + } + + + if (mutex->__queue == NULL) + { + __pthread_spin_unlock (&mutex->__held); + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + + wakeup = mutex->__queue; + __pthread_dequeue (wakeup); + +#ifndef NDEBUG +# if !defined (ALWAYS_TRACK_MUTEX_OWNER) + if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL) +# endif + { + mutex->owner = wakeup; + } +#endif + + /* We do not unlock MUTEX->held: we are transferring the ownership + to the thread that we are waking up. */ + + __pthread_spin_unlock (&mutex->__lock); + __pthread_wakeup (wakeup); + + return 0; +} + +strong_alias (__pthread_mutex_unlock, _pthread_mutex_unlock); +strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock); diff --git a/libpthread/sysdeps/generic/pt-mutexattr-destroy.c b/libpthread/sysdeps/generic/pt-mutexattr-destroy.c new file mode 100644 index 00000000..fe7e95d2 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_mutexattr_destroy. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_mutexattr_destroy (pthread_mutexattr_t *attr) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-getprioceiling.c b/libpthread/sysdeps/generic/pt-mutexattr-getprioceiling.c new file mode 100644 index 00000000..d03d7192 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-getprioceiling.c @@ -0,0 +1,28 @@ +/* pthread_mutexattr_getprioceiling. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *attr, + int *prioceiling) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-getprotocol.c b/libpthread/sysdeps/generic/pt-mutexattr-getprotocol.c new file mode 100644 index 00000000..d75021a3 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-getprotocol.c @@ -0,0 +1,29 @@ +/* pthread_mutexattr_getprotocol. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attr, + int *protocol) +{ + *protocol = attr->protocol; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-getpshared.c b/libpthread/sysdeps/generic/pt-mutexattr-getpshared.c new file mode 100644 index 00000000..0dad13b8 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-getpshared.c @@ -0,0 +1,29 @@ +/* pthread_mutexattr_getpshared. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr, + int *pshared) +{ + *pshared = attr->pshared; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-gettype.c b/libpthread/sysdeps/generic/pt-mutexattr-gettype.c new file mode 100644 index 00000000..ff2caea4 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-gettype.c @@ -0,0 +1,28 @@ +/* pthread_mutexattr_gettype. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type) +{ + *type = attr->mutex_type; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-init.c b/libpthread/sysdeps/generic/pt-mutexattr-init.c new file mode 100644 index 00000000..2f23673c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-init.c @@ -0,0 +1,28 @@ +/* pthread_mutexattr_init. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_mutexattr_init (pthread_mutexattr_t *attr) +{ + *attr = __pthread_default_mutexattr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-setprioceiling.c b/libpthread/sysdeps/generic/pt-mutexattr-setprioceiling.c new file mode 100644 index 00000000..a9bbd327 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-setprioceiling.c @@ -0,0 +1,28 @@ +/* pthread_mutexattr_setprioceiling. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr, + int prioceiling) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-setprotocol.c b/libpthread/sysdeps/generic/pt-mutexattr-setprotocol.c new file mode 100644 index 00000000..9a0d1b1f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-setprotocol.c @@ -0,0 +1,42 @@ +/* pthread_mutexattr_setprotocol. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_mutexattr_setprotocol (pthread_mutexattr_t *attr, + int protocol) +{ + if (protocol == __pthread_default_mutexattr.protocol) + { + attr->protocol = protocol; + return 0; + } + + switch (protocol) + { + case PTHREAD_PRIO_NONE: + case PTHREAD_PRIO_INHERIT: + case PTHREAD_PRIO_PROTECT: + return ENOTSUP; + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-setpshared.c b/libpthread/sysdeps/generic/pt-mutexattr-setpshared.c new file mode 100644 index 00000000..bcbc4d91 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-setpshared.c @@ -0,0 +1,39 @@ +/* pthread_mutexattr_setpshared. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, + int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->pshared = pshared; + return 0; + + case PTHREAD_PROCESS_SHARED: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-settype.c b/libpthread/sysdeps/generic/pt-mutexattr-settype.c new file mode 100644 index 00000000..e7ae213a --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-settype.c @@ -0,0 +1,37 @@ +/* pthread_mutexattr_settype. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type) +{ + switch (type) + { + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_ERRORCHECK: + case PTHREAD_MUTEX_RECURSIVE: + attr->mutex_type = type; + return 0; + + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr.c b/libpthread/sysdeps/generic/pt-mutexattr.c new file mode 100644 index 00000000..5ebde6ea --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr.c @@ -0,0 +1,45 @@ +/* Default mutex attributes. Generic version. + Copyright (C) 2000, 2002, 2008 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 <pthread.h> +#include <pt-internal.h> + +const struct __pthread_mutexattr __pthread_default_mutexattr = +{ + prioceiling: 0, + protocol: PTHREAD_PRIO_NONE, + pshared: PTHREAD_PROCESS_PRIVATE, + mutex_type: PTHREAD_MUTEX_DEFAULT +}; + +const struct __pthread_mutexattr __pthread_errorcheck_mutexattr = +{ + prioceiling: 0, + protocol: PTHREAD_PRIO_NONE, + pshared: PTHREAD_PROCESS_PRIVATE, + mutex_type: PTHREAD_MUTEX_ERRORCHECK +}; + +const struct __pthread_mutexattr __pthread_recursive_mutexattr = +{ + prioceiling: 0, + protocol: PTHREAD_PRIO_NONE, + pshared: PTHREAD_PROCESS_PRIVATE, + mutex_type: PTHREAD_MUTEX_RECURSIVE +}; diff --git a/libpthread/sysdeps/generic/pt-once.c b/libpthread/sysdeps/generic/pt-once.c new file mode 100644 index 00000000..5be5e484 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-once.c @@ -0,0 +1,43 @@ +/* pthread_once. Generic 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. */ + +#include <pthread.h> +#include <bits/memory.h> + +#include <pt-internal.h> + +int +pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ + if (once_control->run == 0) + { + __pthread_spin_lock (&once_control->lock); + + if (once_control->run == 0) + { + init_routine (); + __memory_barrier (); + once_control->run = 1; + } + + __pthread_spin_unlock (&once_control->lock); + } + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-attr.c b/libpthread/sysdeps/generic/pt-rwlock-attr.c new file mode 100644 index 00000000..1587feef --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-attr.c @@ -0,0 +1,26 @@ +/* Default rwlock attributes. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +const struct __pthread_rwlockattr __pthread_default_rwlockattr = +{ + pshared: PTHREAD_PROCESS_PRIVATE +}; diff --git a/libpthread/sysdeps/generic/pt-rwlock-destroy.c b/libpthread/sysdeps/generic/pt-rwlock-destroy.c new file mode 100644 index 00000000..045eebd8 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-destroy.c @@ -0,0 +1,29 @@ +/* Destroy a rwlock. Generic version. + Copyright (C) 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <pthread.h> +#include <pt-internal.h> + +int +_pthread_rwlock_destroy (pthread_rwlock_t *rwlock) +{ + return 0; +} + +strong_alias (_pthread_rwlock_destroy, pthread_rwlock_destroy); diff --git a/libpthread/sysdeps/generic/pt-rwlock-init.c b/libpthread/sysdeps/generic/pt-rwlock-init.c new file mode 100644 index 00000000..c9ff9b28 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-init.c @@ -0,0 +1,45 @@ +/* Initialize a rwlock. Generic version. + Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <pthread.h> +#include <string.h> +#include <pt-internal.h> + +int +_pthread_rwlock_init (pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) +{ + *rwlock = (pthread_rwlock_t) __PTHREAD_RWLOCK_INITIALIZER; + + if (! attr + || memcmp (attr, &__pthread_default_rwlockattr, sizeof (*attr) == 0)) + /* Use the default attributes. */ + return 0; + + /* Non-default attributes. */ + + rwlock->__attr = malloc (sizeof *attr); + if (! rwlock->__attr) + return ENOMEM; + + *rwlock->__attr = *attr; + return 0; +} + +strong_alias (_pthread_rwlock_init, pthread_rwlock_init); diff --git a/libpthread/sysdeps/generic/pt-rwlock-rdlock.c b/libpthread/sysdeps/generic/pt-rwlock-rdlock.c new file mode 100644 index 00000000..480cf489 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-rdlock.c @@ -0,0 +1,32 @@ +/* Acquire a rwlock for reading. Generic version. + 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 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 <pthread.h> +#include <pt-internal.h> + +/* Implemented in pt-rwlock-timedrdlock.c. */ +extern int __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, + const struct timespec *abstime); + +/* Acquire RWLOCK for reading, block if we can't get it. */ +int +pthread_rwlock_rdlock (struct __pthread_rwlock *rwlock) +{ + return __pthread_rwlock_timedrdlock_internal (rwlock, 0); +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-timedrdlock.c b/libpthread/sysdeps/generic/pt-rwlock-timedrdlock.c new file mode 100644 index 00000000..ba610fa5 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-timedrdlock.c @@ -0,0 +1,113 @@ +/* Acquire a rwlock for reading. Generic version. + 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 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 <pthread.h> +#include <assert.h> + +#include <pt-internal.h> + +/* Acquire the rwlock *RWLOCK for reading blocking until *ABSTIME if + it is already held. As a GNU extension, if TIMESPEC is NULL then + wait forever. */ +int +__pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + struct __pthread *self; + + __pthread_spin_lock (&rwlock->__lock); + if (__pthread_spin_trylock (&rwlock->__held) == 0) + /* Successfully acquired the lock. */ + { + assert (rwlock->readerqueue == 0); + assert (rwlock->writerqueue == 0); + assert (rwlock->readers == 0); + + rwlock->readers = 1; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + else + /* Lock is held, but is held by a reader? */ + if (rwlock->readers > 0) + /* Just add ourself to number of readers. */ + { + assert (rwlock->readerqueue == 0); + rwlock->readers ++; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + /* The lock is busy. */ + + /* Better be blocked by a writer. */ + assert (rwlock->readers == 0); + + if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + + self = _pthread_self (); + + /* Add ourself to the queue. */ + __pthread_enqueue (&rwlock->readerqueue, self); + __pthread_spin_unlock (&rwlock->__lock); + + /* Block the thread. */ + if (abstime) + { + error_t err; + + err = __pthread_timedblock (self, abstime); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err == ETIMEDOUT); + + __pthread_spin_lock (&rwlock->__lock); + if (self->prevp) + /* Disconnect ourself. */ + __pthread_dequeue (self); + __pthread_spin_unlock (&rwlock->__lock); + + return err; + } + } + else + __pthread_block (self); + + + /* The reader count has already been increment by whoever woke us + up. */ + + assert (rwlock->readers > 0); + + return 0; +} + +int +pthread_rwlock_timedrdlock (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + return __pthread_rwlock_timedrdlock_internal (rwlock, abstime); +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-timedwrlock.c b/libpthread/sysdeps/generic/pt-rwlock-timedwrlock.c new file mode 100644 index 00000000..04eab51f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-timedwrlock.c @@ -0,0 +1,95 @@ +/* Acquire a rwlock for writing. Generic version. + 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 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 <pthread.h> +#include <assert.h> + +#include <pt-internal.h> + +/* Acquire RWLOCK for writing blocking until *ABSTIME if we cannot get + it. As a special GNU extension, if ABSTIME is NULL then the wait + shall not time out. */ +int +__pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + struct __pthread *self; + + __pthread_spin_lock (&rwlock->__lock); + if (__pthread_spin_trylock (&rwlock->__held) == 0) + /* Successfully acquired the lock. */ + { + assert (rwlock->readerqueue == 0); + assert (rwlock->writerqueue == 0); + assert (rwlock->readers == 0); + + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + /* The lock is busy. */ + + if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + + self = _pthread_self (); + + /* Add ourselves to the queue. */ + __pthread_enqueue (&rwlock->writerqueue, self); + __pthread_spin_unlock (&rwlock->__lock); + + /* Block the thread. */ + if (abstime) + { + error_t err; + + err = __pthread_timedblock (self, abstime); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err == ETIMEDOUT); + + __pthread_spin_lock (&rwlock->__lock); + if (self->prevp) + /* Disconnect ourself. */ + __pthread_dequeue (self); + __pthread_spin_unlock (&rwlock->__lock); + + return err; + } + } + else + __pthread_block (self); + + assert (rwlock->readers == 0); + + return 0; +} + +int +pthread_rwlock_timedwrlock (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + return __pthread_rwlock_timedwrlock_internal (rwlock, abstime); +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-tryrdlock.c b/libpthread/sysdeps/generic/pt-rwlock-tryrdlock.c new file mode 100644 index 00000000..2419efb1 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-tryrdlock.c @@ -0,0 +1,56 @@ +/* Try to acquire a rwlock for reading. Generic 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. */ + +#include <pthread.h> +#include <assert.h> + +#include <pt-internal.h> + +/* Try to acquire RWLOCK. */ +int +pthread_rwlock_tryrdlock (struct __pthread_rwlock *rwlock) +{ + __pthread_spin_lock (&rwlock->__lock); + if (__pthread_spin_trylock (&rwlock->__held) == 0) + /* Successfully acquired the lock. */ + { + assert (rwlock->readerqueue == 0); + assert (rwlock->writerqueue == 0); + assert (rwlock->readers == 0); + + rwlock->readers = 1; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + else + /* Lock is held, but is held by a reader? */ + if (rwlock->readers > 0) + { + assert (rwlock->readerqueue == 0); + rwlock->readers ++; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + /* The lock is busy. */ + + __pthread_spin_unlock (&rwlock->__lock); + + return EBUSY; +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-trywrlock.c b/libpthread/sysdeps/generic/pt-rwlock-trywrlock.c new file mode 100644 index 00000000..6b9c5b56 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-trywrlock.c @@ -0,0 +1,46 @@ +/* Try to acquire a rwlock for writing. Generic 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. */ + +#include <pthread.h> +#include <assert.h> + +#include <pt-internal.h> + +/* Try to acquire RWLOCK for writing. */ +int +pthread_rwlock_trywrlock (struct __pthread_rwlock *rwlock) +{ + __pthread_spin_lock (&rwlock->__lock); + if (__pthread_spin_trylock (&rwlock->__held) == 0) + /* Successfully acquired the lock. */ + { + assert (rwlock->readerqueue == 0); + assert (rwlock->writerqueue == 0); + assert (rwlock->readers == 0); + + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + /* The lock is busy. */ + + __pthread_spin_unlock (&rwlock->__lock); + + return EBUSY; +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-unlock.c b/libpthread/sysdeps/generic/pt-rwlock-unlock.c new file mode 100644 index 00000000..fb23a0b9 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-unlock.c @@ -0,0 +1,90 @@ +/* Unlock a rwlock. Generic version. + Copyright (C) 2000,02 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 <pthread.h> + +#include <pt-internal.h> + +/* Unlock *RWLOCK, rescheduling a waiting writer thread or, if there + are no threads waiting for a write lock, rescheduling the reader + threads. */ +int +pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&rwlock->__lock); + + assert (__pthread_spin_trylock (&rwlock->__held) == EBUSY); + + if (rwlock->readers > 1) + /* There are other readers. */ + { + rwlock->readers --; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + if (rwlock->readers == 1) + /* Last reader. */ + rwlock->readers = 0; + + + /* Wake someone else up. Try the writer queue first, then the + reader queue if that is empty. */ + + if (rwlock->writerqueue) + { + wakeup = rwlock->writerqueue; + __pthread_dequeue (wakeup); + + /* We do not unlock RWLOCK->held: we are transferring the ownership + to the thread that we are waking up. */ + + __pthread_spin_unlock (&rwlock->__lock); + __pthread_wakeup (wakeup); + + return 0; + } + + if (rwlock->readerqueue) + { + __pthread_queue_iterate (rwlock->readerqueue, wakeup) + rwlock->readers ++; + + wakeup = rwlock->readerqueue; + rwlock->readerqueue = 0; + + __pthread_spin_unlock (&rwlock->__lock); + + /* We can safely walk the list of waiting threads without holding + the lock since it is now decoupled from the rwlock. */ + __pthread_dequeuing_iterate (wakeup, wakeup) + __pthread_wakeup (wakeup); + + return 0; + } + + + /* Noone is waiting. Just unlock it. */ + + __pthread_spin_unlock (&rwlock->__held); + __pthread_spin_unlock (&rwlock->__lock); + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-wrlock.c b/libpthread/sysdeps/generic/pt-rwlock-wrlock.c new file mode 100644 index 00000000..be85b906 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-wrlock.c @@ -0,0 +1,34 @@ +/* Acquire a rwlock for writing. Generic 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. */ + +#include <pthread.h> +#include <assert.h> + +#include <pt-internal.h> + +/* Implemented in pt-rwlock-timedwrlock.c. */ +extern int __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, + const struct timespec *abstime); + +/* Acquire RWLOCK for writing. */ +int +pthread_rwlock_wrlock (struct __pthread_rwlock *rwlock) +{ + return __pthread_rwlock_timedwrlock_internal (rwlock, 0); +} diff --git a/libpthread/sysdeps/generic/pt-rwlockattr-destroy.c b/libpthread/sysdeps/generic/pt-rwlockattr-destroy.c new file mode 100644 index 00000000..eabfcbe8 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlockattr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_rwlockattr_destroy. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-rwlockattr-getpshared.c b/libpthread/sysdeps/generic/pt-rwlockattr-getpshared.c new file mode 100644 index 00000000..e8752c0c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlockattr-getpshared.c @@ -0,0 +1,29 @@ +/* pthread_rwlockattr_getpshared. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, + int *pshared) +{ + *pshared = attr->pshared; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-rwlockattr-init.c b/libpthread/sysdeps/generic/pt-rwlockattr-init.c new file mode 100644 index 00000000..34da6bf0 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlockattr-init.c @@ -0,0 +1,28 @@ +/* pthread_rwlockattr_init. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_rwlockattr_init (pthread_rwlockattr_t *attr) +{ + *attr = __pthread_default_rwlockattr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-rwlockattr-setpshared.c b/libpthread/sysdeps/generic/pt-rwlockattr-setpshared.c new file mode 100644 index 00000000..a861d034 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlockattr-setpshared.c @@ -0,0 +1,39 @@ +/* pthread_rwlockattr_setpshared. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, + int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->pshared = pshared; + return 0; + + case PTHREAD_PROCESS_SHARED: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-setconcurrency.c b/libpthread/sysdeps/generic/pt-setconcurrency.c new file mode 100644 index 00000000..cd55b1ba --- /dev/null +++ b/libpthread/sysdeps/generic/pt-setconcurrency.c @@ -0,0 +1,34 @@ +/* Set the desired level of concurrency. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int __pthread_concurrency; + +int +pthread_setconcurrency (int new_level) +{ + if (new_level < 0) + return EINVAL; + + __pthread_concurrency = new_level; + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-setschedparam.c b/libpthread/sysdeps/generic/pt-setschedparam.c new file mode 100644 index 00000000..a70b0796 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-setschedparam.c @@ -0,0 +1,28 @@ +/* Set the scheduling parameters for a thread. Generic version. + 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 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 <pthread.h> +#include <pt-internal.h> + +int +pthread_setschedparam (pthread_t thread, int policy, + const struct sched_param *param) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-setschedprio.c b/libpthread/sysdeps/generic/pt-setschedprio.c new file mode 100644 index 00000000..60668eb1 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-setschedprio.c @@ -0,0 +1,27 @@ +/* Set the scheduling priority of a thread. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_setschedprio (pthread_t thread, int prio) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-setspecific.c b/libpthread/sysdeps/generic/pt-setspecific.c new file mode 100644 index 00000000..d520c5df --- /dev/null +++ b/libpthread/sysdeps/generic/pt-setspecific.c @@ -0,0 +1,27 @@ +/* pthread_setspecific. Generic 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +int +pthread_setspecific (pthread_key_t key, const void *value) +{ + return EINVAL; +} diff --git a/libpthread/sysdeps/generic/pt-startup.c b/libpthread/sysdeps/generic/pt-startup.c new file mode 100644 index 00000000..c21a1819 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-startup.c @@ -0,0 +1,25 @@ +/* Thread initialization. Generic version. + Copyright (C) 2008 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 <pt-internal.h> + +void +__pthread_startup (void) +{ +} diff --git a/libpthread/sysdeps/generic/raise.c b/libpthread/sysdeps/generic/raise.c new file mode 100644 index 00000000..410f557d --- /dev/null +++ b/libpthread/sysdeps/generic/raise.c @@ -0,0 +1,41 @@ +/* raise.c - Generic raise implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +int +raise (int signo) +{ + /* According to POSIX, if we implement threads (and we do), then + "the effect of the raise() function shall be equivalent to + calling: pthread_kill(pthread_self(), sig);" */ + +debug (0, ""); + int err = pthread_kill (pthread_self (), signo); +debug (0, ""); + if (err) + { + errno = err; + return -1; + } + + return 0; +} + diff --git a/libpthread/sysdeps/generic/sem-close.c b/libpthread/sysdeps/generic/sem-close.c new file mode 100644 index 00000000..9f48032f --- /dev/null +++ b/libpthread/sysdeps/generic/sem-close.c @@ -0,0 +1,32 @@ +/* Close a named semaphore. Generic 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 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 <semaphore.h> +#include <errno.h> + +#include <pt-internal.h> + +int +__sem_close (sem_t *sem) +{ + errno = EOPNOTSUPP; + return -1; +} + +strong_alias (__sem_close, sem_close); diff --git a/libpthread/sysdeps/generic/sem-destroy.c b/libpthread/sysdeps/generic/sem-destroy.c new file mode 100644 index 00000000..6486599c --- /dev/null +++ b/libpthread/sysdeps/generic/sem-destroy.c @@ -0,0 +1,38 @@ +/* Destroy a semaphore. Generic version. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <semaphore.h> +#include <errno.h> + +#include <pt-internal.h> + +int +__sem_destroy (sem_t *sem) +{ + if (sem->__queue) + /* There are threads waiting on *SEM. */ + { + errno = EBUSY; + return -1; + } + + return 0; +} + +strong_alias (__sem_destroy, sem_destroy); diff --git a/libpthread/sysdeps/generic/sem-getvalue.c b/libpthread/sysdeps/generic/sem-getvalue.c new file mode 100644 index 00000000..7762089b --- /dev/null +++ b/libpthread/sysdeps/generic/sem-getvalue.c @@ -0,0 +1,33 @@ +/* Get the value of a semaphore. Generic version. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <semaphore.h> +#include <pt-internal.h> + +int +__sem_getvalue (sem_t *restrict sem, int *restrict value) +{ + __pthread_spin_lock (&sem->__lock); + *value = sem->__value; + __pthread_spin_unlock (&sem->__lock); + + return 0; +} + +strong_alias (__sem_getvalue, sem_getvalue); diff --git a/libpthread/sysdeps/generic/sem-init.c b/libpthread/sysdeps/generic/sem-init.c new file mode 100644 index 00000000..d2414f5d --- /dev/null +++ b/libpthread/sysdeps/generic/sem-init.c @@ -0,0 +1,46 @@ +/* Initialize a semaphore. Generic version. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <semaphore.h> +#include <errno.h> + +#include <pt-internal.h> + +int +__sem_init (sem_t *sem, int pshared, unsigned value) +{ + if (pshared != 0) + { + errno = EOPNOTSUPP; + return -1; + } + +#ifdef SEM_VALUE_MAX + if (value > SEM_VALUE_MAX) + { + errno = EINVAL; + return -1; + } +#endif + + *sem = (sem_t) __SEMAPHORE_INITIALIZER (pshared, value); + return 0; +} + +strong_alias (__sem_init, sem_init); diff --git a/libpthread/sysdeps/generic/sem-open.c b/libpthread/sysdeps/generic/sem-open.c new file mode 100644 index 00000000..bae87ed0 --- /dev/null +++ b/libpthread/sysdeps/generic/sem-open.c @@ -0,0 +1,32 @@ +/* Open a named semaphore. Generic version. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <semaphore.h> +#include <errno.h> + +#include <pt-internal.h> + +sem_t * +__sem_open (const char *name, int open_flags, ...) +{ + errno = EOPNOTSUPP; + return SEM_FAILED; +} + +strong_alias (__sem_open, sem_open); diff --git a/libpthread/sysdeps/generic/sem-post.c b/libpthread/sysdeps/generic/sem-post.c new file mode 100644 index 00000000..6d438bf2 --- /dev/null +++ b/libpthread/sysdeps/generic/sem-post.c @@ -0,0 +1,62 @@ +/* Post a semaphore. Generic version. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <semaphore.h> +#include <assert.h> + +#include <pt-internal.h> + +int +__sem_post (sem_t *sem) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&sem->__lock); + if (sem->__value > 0) + /* Do a quick up. */ + { + assert (! sem->__queue); + sem->__value ++; + __pthread_spin_unlock (&sem->__lock); + return 0; + } + + if (! sem->__queue) + /* No one waiting. */ + { + sem->__value = 1; + __pthread_spin_unlock (&sem->__lock); + return 0; + } + + /* Wake someone up. */ + + /* First dequeue someone. */ + wakeup = sem->__queue; + __pthread_dequeue (wakeup); + + /* Then drop the lock and transfer control. */ + __pthread_spin_unlock (&sem->__lock); + + __pthread_wakeup (wakeup); + + return 0; +} + +strong_alias (__sem_post, sem_post); diff --git a/libpthread/sysdeps/generic/sem-timedwait.c b/libpthread/sysdeps/generic/sem-timedwait.c new file mode 100644 index 00000000..e34539a9 --- /dev/null +++ b/libpthread/sysdeps/generic/sem-timedwait.c @@ -0,0 +1,91 @@ +/* Wait on a semaphore with a timeout. Generic version. + Copyright (C) 2005, 2006, 2008 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 <semaphore.h> +#include <errno.h> +#include <assert.h> + +#include <pt-internal.h> + +int +__sem_timedwait_internal (sem_t *restrict sem, + const struct timespec *restrict timeout) +{ + struct __pthread *self; + + __pthread_spin_lock (&sem->__lock); + if (sem->__value > 0) + /* Successful down. */ + { + sem->__value --; + __pthread_spin_unlock (&sem->__lock); + return 0; + } + + if (timeout && (timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000)) + { + errno = EINVAL; + return -1; + } + + /* Add ourselves to the queue. */ + self = _pthread_self (); + + __pthread_enqueue (&sem->__queue, self); + __pthread_spin_unlock (&sem->__lock); + + /* Block the thread. */ + if (timeout) + { + error_t err; + + err = __pthread_timedblock (self, timeout); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err == ETIMEDOUT); + + __pthread_spin_lock (&sem->__lock); + if (self->prevp) + __pthread_dequeue (self); + __pthread_spin_unlock (&sem->__lock); + + errno = err; + return -1; + } + } + else + __pthread_block (self); + + return 0; +} + +int +__sem_timedwait (sem_t *restrict sem, + const struct timespec *restrict timeout) +{ + return __sem_timedwait_internal (sem, timeout); +} + +strong_alias (__sem_timedwait, sem_timedwait); diff --git a/libpthread/sysdeps/generic/sem-trywait.c b/libpthread/sysdeps/generic/sem-trywait.c new file mode 100644 index 00000000..437e2822 --- /dev/null +++ b/libpthread/sysdeps/generic/sem-trywait.c @@ -0,0 +1,42 @@ +/* Lock a semaphore if it does not require blocking. Generic version. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <semaphore.h> +#include <errno.h> + +#include <pt-internal.h> + +int +__sem_trywait (sem_t *sem) +{ + __pthread_spin_lock (&sem->__lock); + if (sem->__value > 0) + /* Successful down. */ + { + sem->__value --; + __pthread_spin_unlock (&sem->__lock); + return 0; + } + __pthread_spin_unlock (&sem->__lock); + + errno = EAGAIN; + return -1; +} + +strong_alias (__sem_trywait, sem_trywait); diff --git a/libpthread/sysdeps/generic/sem-unlink.c b/libpthread/sysdeps/generic/sem-unlink.c new file mode 100644 index 00000000..570ed614 --- /dev/null +++ b/libpthread/sysdeps/generic/sem-unlink.c @@ -0,0 +1,32 @@ +/* Unlink a named semaphore. Generic version. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <semaphore.h> +#include <errno.h> + +#include <pt-internal.h> + +int +__sem_unlink (const char *name) +{ + errno = EOPNOTSUPP; + return -1; +} + +strong_alias (__sem_unlink, sem_unlink); diff --git a/libpthread/sysdeps/generic/sem-wait.c b/libpthread/sysdeps/generic/sem-wait.c new file mode 100644 index 00000000..8347480c --- /dev/null +++ b/libpthread/sysdeps/generic/sem-wait.c @@ -0,0 +1,32 @@ +/* Wait on a semaphore. Generic version. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <semaphore.h> +#include <pt-internal.h> + +extern int __sem_timedwait_internal (sem_t *restrict sem, + const struct timespec *restrict timeout); + +int +__sem_wait (sem_t *sem) +{ + return __sem_timedwait_internal (sem, 0); +} + +strong_alias (__sem_wait, sem_wait); diff --git a/libpthread/sysdeps/generic/sigaddset.c b/libpthread/sysdeps/generic/sigaddset.c new file mode 100644 index 00000000..14edb71c --- /dev/null +++ b/libpthread/sysdeps/generic/sigaddset.c @@ -0,0 +1,35 @@ +/* sigaddset.c - Generic sigaddset implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +int +sigaddset (sigset_t *sigset, int signo) +{ + if (signo <= 0 || signo >= NSIG) + { + errno = EINVAL; + return -1; + } + + *sigset |= sigmask (signo); + return 0; +} + diff --git a/libpthread/sysdeps/generic/sigdelset.c b/libpthread/sysdeps/generic/sigdelset.c new file mode 100644 index 00000000..5456467f --- /dev/null +++ b/libpthread/sysdeps/generic/sigdelset.c @@ -0,0 +1,35 @@ +/* sigdelset.c - Generic sigdelset implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +int +sigdelset (sigset_t *sigset, int signo) +{ + if (signo <= 0 || signo >= NSIG) + { + errno = EINVAL; + return -1; + } + + *sigset &= ~sigmask (signo); + return 0; +} + diff --git a/libpthread/sysdeps/generic/sigemptyset.c b/libpthread/sysdeps/generic/sigemptyset.c new file mode 100644 index 00000000..690c15b6 --- /dev/null +++ b/libpthread/sysdeps/generic/sigemptyset.c @@ -0,0 +1,29 @@ +/* sigemptyset.c - Generic sigemptyset implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <signal.h> + +int +sigemptyset (sigset_t *sigset) +{ + *sigset = 0; + return 0; +} + diff --git a/libpthread/sysdeps/generic/sigfillset.c b/libpthread/sysdeps/generic/sigfillset.c new file mode 100644 index 00000000..f0ac0781 --- /dev/null +++ b/libpthread/sysdeps/generic/sigfillset.c @@ -0,0 +1,29 @@ +/* sigfillset.c - Generic sigfillset implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <signal.h> + +int +sigfillset (sigset_t *sigset) +{ + *sigset = (1ULL << (NSIG - 1)) - 1; + return 0; +} + diff --git a/libpthread/sysdeps/generic/siginterrupt.c b/libpthread/sysdeps/generic/siginterrupt.c new file mode 100644 index 00000000..0899efbb --- /dev/null +++ b/libpthread/sysdeps/generic/siginterrupt.c @@ -0,0 +1,36 @@ +/* siginterrupt.c - Generic siginterrupt implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +int +siginterrupt (int sig, int flag) +{ + int ret; + struct sigaction act; + + sigaction (sig, NULL, &act); + if (flag) + act.sa_flags &= ~SA_RESTART; + else + act.sa_flags |= SA_RESTART; + ret = sigaction(sig, &act, NULL); + return ret; +} diff --git a/libpthread/sysdeps/generic/sigismember.c b/libpthread/sysdeps/generic/sigismember.c new file mode 100644 index 00000000..b3d65c97 --- /dev/null +++ b/libpthread/sysdeps/generic/sigismember.c @@ -0,0 +1,36 @@ +/* sigismember.c - Generic sigismember implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +int +sigismember (const sigset_t *sigset, int signo) +{ + if (signo <= 0 || signo >= NSIG) + { + errno = EINVAL; + return -1; + } + + if (*sigset & sigmask (signo)) + return 1; + else + return 0; +} diff --git a/libpthread/sysdeps/generic/signal.c b/libpthread/sysdeps/generic/signal.c new file mode 100644 index 00000000..7555d0a1 --- /dev/null +++ b/libpthread/sysdeps/generic/signal.c @@ -0,0 +1,44 @@ +/* signal.c - Generic signal implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +void (*signal (int sig, void (*handler)(int)))(int) +{ + struct sigaction sa; + + sa.sa_handler = handler; + sa.sa_flags = SA_RESTART; + + if (sigemptyset (&sa.sa_mask) < 0 + || sigaddset (&sa.sa_mask, sig) < 0) + return SIG_ERR; + + struct sigaction osa; + if (sigaction (sig, &sa, &osa) < 0) + return SIG_ERR; + + return osa.sa_handler; +} + +void (*bsd_signal (int sig, void (*func)(int)))(int) +{ + return signal (sig, func); +} diff --git a/libpthread/sysdeps/generic/sigwait.c b/libpthread/sysdeps/generic/sigwait.c new file mode 100644 index 00000000..7d10bf8b --- /dev/null +++ b/libpthread/sysdeps/generic/sigwait.c @@ -0,0 +1,34 @@ +/* sigwait.c - Generic sigwait implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "sig-internal.h" + +int +sigwait (const sigset_t *restrict set, int *restrict signo) +{ + siginfo_t info; + + if (sigwaitinfo (set, &info) < 0) + return -1; + + *signo = info.si_signo; + return 0; +} + diff --git a/libpthread/sysdeps/hurd/pt-destroy-specific.c b/libpthread/sysdeps/hurd/pt-destroy-specific.c new file mode 100644 index 00000000..23c7fbc0 --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-destroy-specific.c @@ -0,0 +1,79 @@ +/* __pthread_destory_specific. Hurd 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. */ + +#include <pthread.h> +#include <stdlib.h> +#include <hurd/ihash.h> + +#include <pt-internal.h> + +void +__pthread_destroy_specific (struct __pthread *thread) +{ + error_t err; + int i; + int seen_one; + + /* Check if there is any thread specific data. */ + if (! thread->thread_specifics) + return; + + __pthread_key_lock_ready (); + + /* Iterate and call the destructors on any thread specific data. */ + for (;;) + { + seen_one = 0; + + __pthread_mutex_lock (&__pthread_key_lock); + + for (i = 0; i < __pthread_key_count; i ++) + { + void *value; + + if (__pthread_key_destructors[i] == PTHREAD_KEY_INVALID) + break; + + value = hurd_ihash_find (thread->thread_specifics, i); + if (value) + { + err = hurd_ihash_remove (thread->thread_specifics, i); + assert (err == 1); + + if (__pthread_key_destructors[i]) + { + seen_one = 1; + __pthread_key_destructors[i] (value); + } + } + } + + __pthread_mutex_unlock (&__pthread_key_lock); + + if (! seen_one) + break; + + /* This may take a very long time. Let those blocking on + pthread_key_create or pthread_key_delete make progress. */ + sched_yield (); + } + + hurd_ihash_free (thread->thread_specifics); + thread->thread_specifics = 0; +} diff --git a/libpthread/sysdeps/hurd/pt-getspecific.c b/libpthread/sysdeps/hurd/pt-getspecific.c new file mode 100644 index 00000000..30605984 --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-getspecific.c @@ -0,0 +1,37 @@ +/* pthread_getspecific. Hurd 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. */ + +#include <pthread.h> +#include <hurd/ihash.h> + +#include <pt-internal.h> + +void * +pthread_getspecific (pthread_key_t key) +{ + struct __pthread *self; + + assert (key < __pthread_key_count); + + self = _pthread_self (); + if (! self->thread_specifics) + return 0; + + return hurd_ihash_find (self->thread_specifics, key); +} diff --git a/libpthread/sysdeps/hurd/pt-init-specific.c b/libpthread/sysdeps/hurd/pt-init-specific.c new file mode 100644 index 00000000..c1bacbcb --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-init-specific.c @@ -0,0 +1,30 @@ +/* __pthread_init_specific. Hurd 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. */ + +#include <pthread.h> +#include <stdlib.h> + +#include <pt-internal.h> + +error_t +__pthread_init_specific (struct __pthread *thread) +{ + thread->thread_specifics = 0; + return 0; +} diff --git a/libpthread/sysdeps/hurd/pt-key-create.c b/libpthread/sysdeps/hurd/pt-key-create.c new file mode 100644 index 00000000..b3e01412 --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-key-create.c @@ -0,0 +1,109 @@ +/* pthread_key_create. Hurd 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. */ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> + +#include <pt-internal.h> + +pthread_mutex_t __pthread_key_lock; + +void (**__pthread_key_destructors) (void *arg); +int __pthread_key_size; +int __pthread_key_count; +int __pthread_key_invalid_count; + +int +pthread_key_create (pthread_key_t *key, void (*destructor) (void *)) +{ + /* Where to look for the next key slot. */ + static int index; + + __pthread_key_lock_ready (); + + __pthread_mutex_lock (&__pthread_key_lock); + + do_search: + /* Use the search hint and try to find a free slot. */ + for (; index < __pthread_key_count + && __pthread_key_destructors[index] != PTHREAD_KEY_INVALID; + index ++) + ; + + /* See if we actually found a free element. */ + if (index < __pthread_key_count) + { + assert (__pthread_key_destructors[index] == PTHREAD_KEY_INVALID); + assert (__pthread_key_invalid_count > 0); + + __pthread_key_invalid_count --; + __pthread_key_destructors[index] = destructor; + *key = index ++; + + __pthread_mutex_unlock (&__pthread_key_lock); + return 0; + } + + assert (index == __pthread_key_count); + + /* No space at the end. */ + if (__pthread_key_size == __pthread_key_count) + { + /* See if it is worth looking for a free element. */ + if (__pthread_key_invalid_count > 4 + && __pthread_key_invalid_count > __pthread_key_size / 8) + { + index = 0; + goto do_search; + } + + + /* Resize the array. */ + { + void *t; + int newsize; + + if (__pthread_key_size == 0) + newsize = 8; + else + newsize = __pthread_key_size * 2; + + t = realloc (__pthread_key_destructors, + newsize * sizeof (*__pthread_key_destructors)); + if (! t) + { + __pthread_mutex_unlock (&__pthread_key_lock); + return ENOMEM; + } + + __pthread_key_size = newsize; + __pthread_key_destructors = t; + } + } + + __pthread_key_destructors[index] = destructor; + *key = index; + + index ++; + __pthread_key_count ++; + + __pthread_mutex_unlock (&__pthread_key_lock); + return 0; +} diff --git a/libpthread/sysdeps/hurd/pt-key-delete.c b/libpthread/sysdeps/hurd/pt-key-delete.c new file mode 100644 index 00000000..2426bb11 --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-key-delete.c @@ -0,0 +1,45 @@ +/* pthread_key_delete. Hurd 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. */ + +#include <pthread.h> + +#include <pt-internal.h> + +int +pthread_key_delete (pthread_key_t key) +{ + error_t err = 0; + + __pthread_key_lock_ready (); + + __pthread_mutex_lock (&__pthread_key_lock); + + if (key < 0 || key >= __pthread_key_count + || __pthread_key_destructors[key] == PTHREAD_KEY_INVALID) + err = EINVAL; + else + { + __pthread_key_destructors[key] = PTHREAD_KEY_INVALID; + __pthread_key_invalid_count ++; + } + + __pthread_mutex_unlock (&__pthread_key_lock); + + return err; +} diff --git a/libpthread/sysdeps/hurd/pt-key.h b/libpthread/sysdeps/hurd/pt-key.h new file mode 100644 index 00000000..494e01d7 --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-key.h @@ -0,0 +1,76 @@ +/* pthread_key internal declatations for the Hurd 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. */ + +#include <pthread.h> +#include <hurd/ihash.h> + +#define PTHREAD_KEY_MEMBERS \ + hurd_ihash_t thread_specifics; + +#define PTHREAD_KEY_INVALID (void *) (-1) + + +/* __PTHREAD_KEY_DESTRUCTORS is an array of destructors with + __PTHREAD_KEY_SIZE elements. If an element with index less than + __PTHREAD_KEY_COUNT is invalid, it shall contain the value + PTHREAD_KEY_INVALID which shall be distinct from NULL. + + Normally, we just add new keys to the end of the array and realloc + it as necessary. The pthread_key_create routine may decide to + rescan the array if __PTHREAD_KEY_FREE is large. */ +extern void (**__pthread_key_destructors) (void *arg); +extern int __pthread_key_size; +extern int __pthread_key_count; +/* Number of invalid elements in the array. Does not include elements + for which memory has been allocated but which have not yet been + used (i.e. those elements with indexes greater than + __PTHREAD_KEY_COUNT). */ +extern int __pthread_key_invalid_count; + +/* Protects the above variables. This must be a recursive lock: the + destructors may call pthread_key_delete. */ +extern pthread_mutex_t __pthread_key_lock; + +#include <assert.h> + +static inline void +__pthread_key_lock_ready (void) +{ + static pthread_once_t o = PTHREAD_ONCE_INIT; + + void do_init (void) + { + int err; + pthread_mutexattr_t attr; + + err = pthread_mutexattr_init (&attr); + assert_perror (err); + + err = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); + assert_perror (err); + + err = pthread_mutex_init (&__pthread_key_lock, &attr); + assert_perror (err); + + err = pthread_mutexattr_destroy (&attr); + assert_perror (err); + } + + pthread_once (&o, do_init); +} diff --git a/libpthread/sysdeps/hurd/pt-kill.c b/libpthread/sysdeps/hurd/pt-kill.c new file mode 100644 index 00000000..d204e3f6 --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-kill.c @@ -0,0 +1,52 @@ +/* pthread_kill. Hurd 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. */ + +#include <pthread.h> +#include <assert.h> +#include <signal.h> +#include <hurd/signal.h> + +#include <pt-internal.h> + +int +pthread_kill (pthread_t thread, int sig) +{ + struct __pthread *pthread; + struct hurd_signal_detail detail; + struct hurd_sigstate *ss; + + /* Lookup the thread structure for THREAD. */ + pthread = __pthread_getid (thread); + if (pthread == NULL) + return ESRCH; + + ss = _hurd_thread_sigstate (pthread->kernel_thread); + assert (ss); + + if (!sig) + return 0; + + detail.exc = 0; + detail.code = sig; + detail.error = 0; + + _hurd_raise_signal (ss, sig, &detail); + + return 0; +} diff --git a/libpthread/sysdeps/hurd/pt-setspecific.c b/libpthread/sysdeps/hurd/pt-setspecific.c new file mode 100644 index 00000000..89ca4d7f --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-setspecific.c @@ -0,0 +1,43 @@ +/* pthread_setspecific. Generic 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. */ + +#include <pthread.h> +#include <hurd/ihash.h> + +#include <pt-internal.h> + +int +pthread_setspecific (pthread_key_t key, const void *value) +{ + error_t err; + struct __pthread *self = _pthread_self (); + + if (! self->thread_specifics) + { + err = hurd_ihash_create (&self->thread_specifics, HURD_IHASH_NO_LOCP); + if (err) + return ENOMEM; + } + + err = hurd_ihash_add (self->thread_specifics, key, (void *) value); + if (err) + return ENOMEM; + + return 0; +} diff --git a/libpthread/sysdeps/ia32/bits/atomic.h b/libpthread/sysdeps/ia32/bits/atomic.h new file mode 100644 index 00000000..0dfc1f60 --- /dev/null +++ b/libpthread/sysdeps/ia32/bits/atomic.h @@ -0,0 +1,66 @@ +/* Atomic operations. i386 version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +#ifndef _BITS_ATOMIC_H +#define _BITS_ATOMIC_H 1 + +typedef __volatile int __atomic_t; + +static inline void +__atomic_inc (__atomic_t *__var) +{ + __asm__ __volatile ("lock; incl %0" : "=m" (*__var) : "m" (*__var)); +} + +static inline void +__atomic_dec (__atomic_t *__var) +{ + __asm__ __volatile ("lock; decl %0" : "=m" (*__var) : "m" (*__var)); +} + +static inline int +__atomic_dec_and_test (__atomic_t *__var) +{ + unsigned char __ret; + + __asm__ __volatile ("lock; decl %0; sete %1" + : "=m" (*__var), "=qm" (__ret) : "m" (*__var)); + return __ret != 0; +} + +/* We assume that an __atomicptr_t is only used for pointers to + word-aligned objects, and use the lowest bit for a simple lock. */ +typedef __volatile int * __atomicptr_t; + +/* Actually we don't implement that yet, and assume that we run on + something that has the i486 instruction set. */ +static inline int +__atomicptr_compare_and_swap (__atomicptr_t *__ptr, void *__oldval, + void * __newval) +{ + char __ret; + int __dummy; + + __asm__ __volatile ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (__ret), "=m" (*__ptr), "=a" (__dummy) + : "r" (__newval), "m" (*__ptr), "a" (__oldval)); + return __ret; +} + +#endif diff --git a/libpthread/sysdeps/ia32/bits/memory.h b/libpthread/sysdeps/ia32/bits/memory.h new file mode 100644 index 00000000..932c4086 --- /dev/null +++ b/libpthread/sysdeps/ia32/bits/memory.h @@ -0,0 +1,40 @@ +/* Memory barrier operations. i386 version. + Copyright (C) 2002, 2008 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. */ + +#ifndef _BITS_MEMORY_H +#define _BITS_MEMORY_H 1 + +/* Prevent read and write reordering across this function. */ +static inline void +__memory_barrier (void) +{ + int i; + + /* Any lock'ed instruction will do. We just do a simple + increment. */ + __asm__ __volatile ("lock; incl %0" : "=m" (i) : "m" (i) : "memory"); +} + +/* Prevent read reordering across this function. */ +#define __memory_read_barrier __memory_barrier + +/* Prevent write reordering across this function. */ +#define __memory_write_barrier __memory_barrier + +#endif diff --git a/libpthread/sysdeps/ia32/bits/spin-lock-inline.h b/libpthread/sysdeps/ia32/bits/spin-lock-inline.h new file mode 100644 index 00000000..e5ed3def --- /dev/null +++ b/libpthread/sysdeps/ia32/bits/spin-lock-inline.h @@ -0,0 +1,98 @@ +/* Machine-specific definitions for spin locks. i386 version. + Copyright (C) 2000, 2005, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +/* + * Never include this file directly; use <pthread.h> or <cthreads.h> instead. + */ + +#ifndef _BITS_SPIN_LOCK_INLINE_H +#define _BITS_SPIN_LOCK_INLINE_H 1 + +#include <features.h> +#include <bits/spin-lock.h> + +__BEGIN_DECLS + +#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES + +# ifndef __EBUSY +# include <errno.h> +# define __EBUSY EBUSY +# endif + +# ifndef __PT_SPIN_INLINE +# define __PT_SPIN_INLINE __extern_inline +# endif + +__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_destroy (__pthread_spinlock_t *__lock) +{ + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, + int __pshared); + +__PT_SPIN_INLINE int +__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) +{ + *__lock = __PTHREAD_SPIN_LOCK_INITIALIZER; + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_trylock (__pthread_spinlock_t *__lock) +{ + int __locked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__locked), "=m" (*__lock) : "0" (1) : "memory"); + return __locked ? __EBUSY : 0; +} + +__extern_inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +__extern_inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__lock); + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_unlock (__pthread_spinlock_t *__lock) +{ + int __unlocked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__unlocked), "=m" (*__lock) : "0" (0) : "memory"); + return 0; +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/libpthread/sysdeps/ia32/bits/spin-lock.h b/libpthread/sysdeps/ia32/bits/spin-lock.h new file mode 100644 index 00000000..5ae81e18 --- /dev/null +++ b/libpthread/sysdeps/ia32/bits/spin-lock.h @@ -0,0 +1,39 @@ +/* Machine-specific definitions for spin locks. i386 version. + Copyright (C) 2000, 2005, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +/* + * Never include this file directly; use <pthread.h> or <cthreads.h> instead. + */ + +#ifndef _BITS_SPIN_LOCK_H +#define _BITS_SPIN_LOCK_H 1 + +#include <features.h> + +__BEGIN_DECLS + +/* The type of a spin lock object. */ +typedef __volatile int __pthread_spinlock_t; + +/* Initializer for a spin lock object. */ +# define __PTHREAD_SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/libpthread/sysdeps/ia32/machine-sp.h b/libpthread/sysdeps/ia32/machine-sp.h new file mode 100644 index 00000000..cef6ab72 --- /dev/null +++ b/libpthread/sysdeps/ia32/machine-sp.h @@ -0,0 +1,30 @@ +/* Machine-specific function to return the stack pointer. i386 version. + Copyright (C) 1994, 1997, 2001, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#define __thread_stack_pointer() ({ \ + register void *__sp__ asm("esp"); \ + __sp__; \ +}) + +#endif /* machine-sp.h */ diff --git a/libpthread/sysdeps/ia32/pt-machdep.h b/libpthread/sysdeps/ia32/pt-machdep.h new file mode 100644 index 00000000..6d456367 --- /dev/null +++ b/libpthread/sysdeps/ia32/pt-machdep.h @@ -0,0 +1,29 @@ +/* Machine dependent pthreads internal defenitions. i386 version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +#ifndef _PT_MACHDEP_H +#define _PT_MACHDEP_H 1 + +struct pthread_mcontext +{ + void *pc; + void *sp; +}; + +#endif /* pt-machdep.h */ diff --git a/libpthread/sysdeps/l4/bits/pthread-np.h b/libpthread/sysdeps/l4/bits/pthread-np.h new file mode 100644 index 00000000..6a02bdc0 --- /dev/null +++ b/libpthread/sysdeps/l4/bits/pthread-np.h @@ -0,0 +1,35 @@ +/* Non-portable functions. L4 version. + Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +/* + * Never include this file directly; use <pthread.h> or <cthreads.h> instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +#include <l4.h> + +/* Add the thread TID to the internal kernel thread pool. */ +extern int pthread_pool_add_np (l4_thread_id_t tid); + +/* Get the first thread from the pool. */ +extern l4_thread_id_t pthread_pool_get_np (void); + +#endif /* bits/pthread-np.h */ diff --git a/libpthread/sysdeps/l4/hurd/bits/pthread-np.h b/libpthread/sysdeps/l4/hurd/bits/pthread-np.h new file mode 100644 index 00000000..a90793df --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/bits/pthread-np.h @@ -0,0 +1,31 @@ +/* Non-portable functions. Viengoos version. + Copyright (C) 2008 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. */ + +/* + * Never include this file directly; use <pthread.h> or <cthreads.h> instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +#include <hurd/addr.h> + +int pthread_setactivity_np (addr_t activity); + +#endif /* bits/pthread-np.h */ diff --git a/libpthread/sysdeps/l4/hurd/ia32/pt-machdep.c b/libpthread/sysdeps/l4/hurd/ia32/pt-machdep.c new file mode 100644 index 00000000..dbf5cd7e --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/ia32/pt-machdep.c @@ -0,0 +1,20 @@ +/* Machine dependent pthreads code. Hurd/i386 version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +/* Nothing to do. */ diff --git a/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c b/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c new file mode 100644 index 00000000..579905c9 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c @@ -0,0 +1,117 @@ +/* Setup thread stack. Viengoos/i386 version. + Copyright (C) 2000, 2002, 2008 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 <l4.h> + +#include <pt-internal.h> +#include <hurd/thread.h> +#include <hurd/exceptions.h> + +/* The stack layout used on the i386 is: + + ----------------- + | ARG | + ----------------- + | START_ROUTINE | + ----------------- + | Return address | + ----------------- <- %ebp + | Frame pointer | + ----------------- + + We do the following: setup the stack to return to the entry routine. + + +*/ + +/* The stack contains: + + arg + start_routine + 0 <- fake return address + C entry_point +*/ +extern uintptr_t _pthread_entry_point; +__asm__ ("\n\ + .globl _pthread_entry_point, __pthread_entry_point\n\ +_pthread_entry_point:\n\ +__pthread_entry_point:\n\ + pushl $0\n\ + popf\n\ +\n\ + xor %ebp, %ebp\n\ + ret\n"); + +/* Set up the stack for THREAD, such that it appears as if + START_ROUTINE and ARG were passed to the new thread's entry-point. + Return the stack pointer for the new thread. We also take the + opportunity to install THREAD in our utcb. */ +static void * +stack_setup (struct __pthread *thread, + void *(*start_routine)(void *), void *arg, + void (*entry_point)(void *(*)(void *), void *)) +{ + uintptr_t *top; + + /* Calculate top of the new stack. */ + top = (uintptr_t *) ((uintptr_t) thread->stackaddr + thread->stacksize); + + /* Align on 0x10 for MMX operations. */ + top = (uintptr_t) top & ~0xf; + + if (start_routine) + { + /* Set up call frame. */ + *--top = (uintptr_t) arg; /* Argument to START_ROUTINE. */ + *--top = (uintptr_t) start_routine; + *--top = 0; /* Fake return address. */ + *--top = (uintptr_t) entry_point; + } + + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + thread->mcontext.pc = (void *) &_pthread_entry_point; + thread->mcontext.sp = (void *) stack_setup (thread, start_routine, arg, + entry_point); + + if (__pthread_num_threads == 1) + return 0; + + assert (! ADDR_IS_VOID (thread->exception_area[0])); + + struct exception_page *exception_page = thread->exception_area_va; + + /* SP is set to the end of the exception area minus one word, which + is the location of the exception page. */ + exception_page->exception_handler_sp + = (uintptr_t) thread->exception_area_va + EXCEPTION_AREA_SIZE; + exception_page->exception_handler_sp -= sizeof (void *); + * (void **) exception_page->exception_handler_sp = thread->exception_area_va; + + exception_page->exception_handler_ip = (uintptr_t) &exception_handler_entry; + exception_page->exception_handler_end = (uintptr_t) &exception_handler_end; + + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c b/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c new file mode 100644 index 00000000..37ef8215 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c @@ -0,0 +1,213 @@ +/* signal-dispatch-lowlevel.c - ia32 specific signal handling functions. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <pt-internal.h> +#include <sig-internal.h> + +#include <hurd/thread.h> +#include <pthread.h> +#include <stdint.h> +#include <atomic.h> + +extern char _signal_dispatch_entry; +/* - 0(%esp) a pointer to the thread's struct signal_state. + - 4(%esp) a pointer to a siginfo_t. + - 8(%esp) is a pointer to the ss_flags field (or NULL). + - 12(%esp)+4 is the value of the sp when the thread was interrupted (intr_sp) + - 0(intr_sp) is the value of the ip when the thread was interrupted. + - 16(%esp) - 16 byte register save area +*/ +__asm__ ("\n\ + .globl _signal_dispatch_entry\n\ +_signal_dispatch_entry:\n\ + /* Save caller saved registers (16 bytes). */\n\ + mov %eax, 16(%esp)\n\ + mov %ecx, 16+4(%esp)\n\ + mov %edx, 16+8(%esp)\n\ + pushf\n\ + popl %eax\n\ + mov %eax, 16+12(%esp)\n\ +\n\ + /* Reset EFLAGS. */\n\ + cld\n\ + call signal_dispatch\n\ +\n\ + /* Get the original stack and begin restoration. */\n\ + mov 12(%esp), %edx\n\ +\n\ + /* Move the saved registers to the user stack. */\n\ + sub $16, %edx\n\ + /* eax. */\n\ + mov 16+0(%esp), %ecx\n\ + mov %ecx, 0(%edx)\n\ + /* ecx. */\n\ + mov 16+4(%esp), %ecx\n\ + mov %ecx, 4(%edx)\n\ + /* edx. */\n\ + mov 16+8(%esp), %ecx\n\ + mov %ecx, 8(%edx)\n\ + /* eflags. */\n\ + mov 16+12(%esp), %ecx\n\ + mov %ecx, 12(%edx)\n\ +\n\ + /* Get the pointer to the sigaltstack flags. */\n\ + mov 8(%esp), %ecx\n\ +\n\ + /* Restore the user stack. */\n\ + mov %edx, %esp\n\ +\n\ + /* Clear the SA_ONSTACK flag. */\n\ + and %ecx, %ecx\n\ + jz after_clear\n\ + lock; and $~1, 0(%ecx)\n\ +after_clear:\n\ +\n\ + /* Restore eflags, the scratch regs and the original sp and ip. */\n\ + popl %eax\n\ + popl %ecx\n\ + popl %edx\n\ + popf\n\ + ret\n"); + +extern char _signal_dispatch_entry_self; +/* - 0(%esp) is the return address (we ignore it) + - 4(%esp) is the sp to load + + Since we are returning to signal_dispatch_lowlevel's caller, we + also need to restore its frame pointer. */ +__asm__ ("\n\ + .globl _signal_dispatch_entry_self\n\ +_signal_dispatch_entry_self:\n\ + mov 0(%ebp), %ebp\n\ + mov 4(%esp), %esp\n\ + jmp _signal_dispatch_entry\n"); + +void +signal_dispatch_lowlevel (struct signal_state *ss, pthread_t tid, + siginfo_t si) +{ + assert (pthread_mutex_trylock (&ss->lock) == EBUSY); + + struct __pthread *thread = __pthread_getid (tid); + + bool self = tid == pthread_self (); + + uintptr_t intr_sp; + + if (self) + { + /* The return address is just before the first argument. */ + intr_sp = (uintptr_t) &ss - 4; + assert (* (void **) intr_sp == __builtin_return_address (0)); + } + else + { + struct hurd_thread_exregs_in in; + memset (&in, 0, sizeof (in)); + struct hurd_thread_exregs_out out; + + error_t err; + err = rm_thread_exregs (ADDR_VOID, thread->object, + HURD_EXREGS_STOP | HURD_EXREGS_ABORT_IPC + | HURD_EXREGS_GET_REGS, + in, &out); + if (err) + panic ("Failed to modify thread " ADDR_FMT, + ADDR_PRINTF (thread->object)); + + intr_sp = out.sp; + + /* Push the ip on the user stack. */ + intr_sp -= 4; + * (uintptr_t *) intr_sp = out.ip; + } + + bool altstack = false; + uintptr_t sp; + if (! (ss->actions[si.si_signo - 1].sa_flags & SA_ONSTACK) + || (ss->stack.ss_flags & SS_DISABLE) + || (ss->stack.ss_flags & SS_ONSTACK)) + { + assert (! self); + sp = intr_sp; + } + else + { + /* The stack grows down. */ + sp = (uintptr_t) ss->stack.ss_sp + ss->stack.ss_size; + + /* We know intimately that SS_ONSTACK is the least significant + bit. */ + assert (SS_ONSTACK == 1); + atomic_bit_set (&ss->stack.ss_flags, 0); + + altstack = true; + } + + /* Set up the call frame for a call to signal_dispatch_entry. */ + + /* Allocate a siginfo structure on the stack. */ + sp = sp - sizeof (siginfo_t); + siginfo_t *sip = (void *) sp; + /* Copy the user supplied values. */ + *sip = si; + + /* Add space for the 4 caller saved registers. */ + sp -= 4 * sizeof (uintptr_t); + + /* Save the interrupted sp. */ + sp -= 4; + * (uintptr_t *) sp = intr_sp; + + /* Address of the ss_flags. */ + sp -= 4; + if (altstack) + * (uintptr_t *) sp = (uintptr_t) &ss->stack.ss_flags; + else + * (uintptr_t *) sp = 0; + + /* Push the parameters to signal_dispatch. */ + + /* signal info structure. */ + sp -= 4; + * (uintptr_t *) sp = (uintptr_t) sip; + + /* The ss. */ + sp -= 4; + * (uintptr_t *) sp = (uintptr_t) ss; + + pthread_mutex_transfer_np (&ss->lock, tid); + + if (self) + ((void (*) (uintptr_t)) &_signal_dispatch_entry_self) ((uintptr_t) sp); + else + { + struct hurd_thread_exregs_in in; + struct hurd_thread_exregs_out out; + + in.sp = sp; + in.ip = (uintptr_t) &_signal_dispatch_entry; + + rm_thread_exregs (ADDR_VOID, thread->object, + HURD_EXREGS_SET_SP_IP + | HURD_EXREGS_START | HURD_EXREGS_ABORT_IPC, + in, &out); + } +} diff --git a/libpthread/sysdeps/l4/hurd/powerpc/pt-machdep.c b/libpthread/sysdeps/l4/hurd/powerpc/pt-machdep.c new file mode 100644 index 00000000..754d203e --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/powerpc/pt-machdep.c @@ -0,0 +1,20 @@ +/* Machine dependent pthreads code. Hurd/PowerPC 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. + + The GNU C Library is distributed in the hope that 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. */ + +/* Nothing to do. */ diff --git a/libpthread/sysdeps/l4/hurd/powerpc/pt-setup.c b/libpthread/sysdeps/l4/hurd/powerpc/pt-setup.c new file mode 100644 index 00000000..d3cf4ec3 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/powerpc/pt-setup.c @@ -0,0 +1,93 @@ +/* Setup thread stack. Hurd/PowerPC 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. + + The GNU C Library is distributed in the hope that 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 <l4.h> + +#include <pt-internal.h> + +/* Arguments is passed in registers on the PowerPC. But the + exchange registers syscall only allows us to set the PC and the + stack pointer so we put the entry point and start function on + the stack. */ +struct start_info +{ + void (*entry_point) (void *(*)(void *), void *); + void *(*start_routine) (void *); + void *arg; +}; + +void first_entry_1 (void); + +/* Stage 1 entry function. The start_info structure is inlined on the + stack. Put values into registers and call entry function. */ +asm (" ;\ +first_entry_1: ;\ + lwz 0, 0(1) ;\ + lwz 3, 4(1) ;\ + lwz 4, 8(1) ;\ + mtctr 0 ;\ + bctrl ;\ +"); + +/* Set up the stack for THREAD, such that it appears as if + START_ROUTINE and ARG were passed to the new thread's entry-point. + Return the stack pointer for the new thread. We also take the + opportunity to install THREAD in our utcb. */ +static void * +stack_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + l4_word_t *top; + + /* Calculate top of the new stack. */ + top = (l4_word_t *) ((l4_word_t) thread->stackaddr + thread->stacksize); + + /* Initial stack frame. */ + top[-4] = 0; + top = top - 4; + + if (start_routine) + { + struct start_info *info = ((struct start_info *) top) - 1; + + info->entry_point = entry_point; + info->start_routine = start_routine; + info->arg = arg; + return (void *) info; + } + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + thread->mcontext.pc = first_entry_1; + thread->mcontext.sp = stack_setup (thread, entry_point, + start_routine, arg); + + if (l4_same_threads (thread->threadid, l4_myself ())) + l4_set_user_defined_handle ((l4_word_t) thread); + else + l4_set_user_defined_handle_of (thread->threadid, + (l4_word_t) thread); + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-block.c b/libpthread/sysdeps/l4/hurd/pt-block.c new file mode 100644 index 00000000..2315b1c4 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-block.c @@ -0,0 +1,30 @@ +/* Block a thread. Viengoos version. + Copyright (C) 2008 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 <pt-internal.h> + +#include <hurd/stddef.h> +#include <hurd/futex.h> + +/* Block THREAD. */ +void +__pthread_block (struct __pthread *thread) +{ + futex_wait (&thread->threadid, thread->threadid); +} diff --git a/libpthread/sysdeps/l4/hurd/pt-kill.c b/libpthread/sysdeps/l4/hurd/pt-kill.c new file mode 100644 index 00000000..c72e82f4 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-kill.c @@ -0,0 +1,3 @@ +/* The generic version is good enough for us, however, the generic + Hurd on Mach version supplies a specialized version */ +#include "../generic/pt-kill.c" diff --git a/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c b/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c new file mode 100644 index 00000000..f2f07233 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c @@ -0,0 +1,39 @@ +/* Set a thread's activity activity. Viengoos version. + Copyright (C) 2008 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 <pt-internal.h> + +#include <hurd/addr.h> +#include <hurd/thread.h> + +int +pthread_setactivity_np (addr_t activity) +{ + struct __pthread *self = _pthread_self (); + + struct hurd_thread_exregs_in in; + in.activity = activity; + + struct hurd_thread_exregs_out out; + int err = rm_thread_exregs (ADDR_VOID, self->object, + HURD_EXREGS_SET_ACTIVITY, + in, &out); + + return err; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sigstate-destroy.c b/libpthread/sysdeps/l4/hurd/pt-sigstate-destroy.c new file mode 100644 index 00000000..997a0369 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sigstate-destroy.c @@ -0,0 +1,28 @@ +/* Destroy the signal state. Hurd on L4 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. */ + +#include <pthread.h> + +#include <pt-internal.h> + +void +__pthread_sigstate_destroy (struct __pthread *thread) +{ + /* Nothing to do. */ +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sigstate-init.c b/libpthread/sysdeps/l4/hurd/pt-sigstate-init.c new file mode 100644 index 00000000..4c40fdb3 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sigstate-init.c @@ -0,0 +1,44 @@ +/* Initialize the signal state. Hurd on L4 version. + Copyright (C) 2003, 2008 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 <pthread.h> + +#include <pt-internal.h> +#include <sig-internal.h> + +error_t +__pthread_sigstate_init (struct __pthread *thread) +{ + struct signal_state *ss = &thread->ss; + + memset (ss, 0, sizeof (*ss)); + + ss->stack.ss_flags = SS_DISABLE; + + int signo; + for (signo = 1; signo < NSIG; ++signo) + { + sigemptyset (&ss->actions[signo - 1].sa_mask); + ss->actions[signo - 1].sa_flags = SA_RESTART; + ss->actions[signo - 1].sa_handler = SIG_DFL; + ss->lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; + } + + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sigstate.c b/libpthread/sysdeps/l4/hurd/pt-sigstate.c new file mode 100644 index 00000000..66dd08cf --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sigstate.c @@ -0,0 +1,81 @@ +/* Set a thread's signal state. Hurd on L4 version. + Copyright (C) 2002, 2005, 2008 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 <pthread.h> +#include <assert.h> +#include <signal.h> + +#include <pt-internal.h> + +error_t +__pthread_sigstate (struct __pthread *thread, int how, + const sigset_t *set, sigset_t *oset, + int clear_pending) +{ + struct signal_state *ss = &thread->ss; + pthread_mutex_lock (&ss->lock); + + if (oset) + *oset = ss->blocked; + + if (set) + { + /* Mask out SIGKILL and SIGSTOP. */ + sigset_t s = *set; + sigdelset (&s, SIGKILL); + sigdelset (&s, SIGSTOP); + + switch (how) + { + case SIG_BLOCK: + ss->blocked |= s; + break; + case SIG_UNBLOCK: + ss->blocked &= ~s; + break; + case SIG_SETMASK: + ss->blocked = s; + break; + default: + errno = EINVAL; + pthread_mutex_unlock (&ss->lock); + return -1; + } + } + + if (clear_pending) + sigemptyset (&ss->pending); + + /* A "signal shall remain pending until it is unblocked" (2.4.1). + + "If there are any pending unblocked signals after the call to + sigprocmask(), at least one of those signals shall be delivered + before the call to sigprocmask() returns." + (pthread_sigmask). */ + sigset_t extant = ~ss->blocked & ss->pending; + if (! extant) + extant = ~ss->blocked & process_pending; + + pthread_mutex_unlock (&ss->lock); + + if (extant) + raise (l4_lsb64 (extant)); + + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-startup.c b/libpthread/sysdeps/l4/hurd/pt-startup.c new file mode 100644 index 00000000..b6461de7 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-startup.c @@ -0,0 +1,30 @@ +/* Thread initialization. Hurd/L4 version. + Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <l4.h> +#include <pt-internal.h> + +#include <hurd/exceptions.h> + +void +__pthread_startup (void) +{ + struct __pthread *pthread = _pthread_self (); + pthread->threadid = l4_myself (); +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sysdep.c b/libpthread/sysdeps/l4/hurd/pt-sysdep.c new file mode 100644 index 00000000..c23364c7 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sysdep.c @@ -0,0 +1,61 @@ +/* System dependent pthreads code. Hurd version. + Copyright (C) 2000, 2008 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 <assert.h> +#include <stddef.h> +#include <stdint.h> + +#include <pt-internal.h> + +int +sched_yield (void) +{ + l4_yield (); + return 0; +} + +/* Forward. */ +static void init_routine (void (*) (void *), void *) + __attribute__ ((noreturn)); + +/* OK, the name of this variable isn't really appropriate, but I don't + want to change it yet. */ +void (*_pthread_init_routine)(void (*) (void *), void *) = &init_routine; + +/* This function is called from the Hurd-specific startup code. It + should return a new stack pointer for the main thread. The caller + will switch to this new stack before doing anything serious. */ +static void +init_routine (void (*entry) (void *), void *arg) +{ + /* Initialize the library. */ + __pthread_initialize (); + + struct __pthread *thread; + int err; + + /* Create the pthread structure for the main thread (i.e. us). */ + err = __pthread_create_internal (&thread, 0, + (void *(*)(void *)) entry, arg); + assert_perror (err); + + /* Switch stacks. */ + l4_start_sp_ip (l4_myself (), thread->mcontext.sp, + thread->mcontext.pc); +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sysdep.h b/libpthread/sysdeps/l4/hurd/pt-sysdep.h new file mode 100644 index 00000000..08bcd143 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sysdep.h @@ -0,0 +1,61 @@ +/* Internal definitions for pthreads library. + Copyright (C) 2000, 2002, 2005, 2007, 2008 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. */ + +#ifndef _PT_SYSDEP_H +#define _PT_SYSDEP_H 1 + +#include <l4.h> +#include <hurd/storage.h> +#include <sys/mman.h> + +/* XXX */ +#define _POSIX_THREAD_THREADS_MAX 64 + +/* The default stack size: 2MB. */ +#define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) + +#include <hurd/exceptions.h> + +#define EXCEPTION_AREA_SIZE EXCEPTION_STACK_SIZE +#define EXCEPTION_AREA_SIZE_LOG2 EXCEPTION_STACK_SIZE_LOG2 +/* The exception page is the first object. */ +#define EXCEPTION_PAGE 0 + +#define PTHREAD_SYSDEP_MEMBERS \ + addr_t object; \ + l4_thread_id_t threadid; \ + addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE]; \ + void *exception_area_va; \ + l4_word_t my_errno; + +extern inline struct __pthread * +__attribute__((__always_inline__)) +_pthread_self (void) +{ + return (struct __pthread *) l4_user_defined_handle (); +} + +extern inline void +__attribute__((__always_inline__)) +__pthread_stack_dealloc (void *stackaddr, size_t stacksize) +{ + munmap (stackaddr, stacksize); +} + +#endif /* pt-sysdep.h */ diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c b/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c new file mode 100644 index 00000000..ada7b3b8 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c @@ -0,0 +1,95 @@ +/* Allocate kernel thread. Viengoos version. + Copyright (C) 2007, 2008 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 <assert.h> +#include <errno.h> +#include <string.h> + +#include <hurd/startup.h> +#include <hurd/storage.h> +#include <hurd/as.h> +#include <hurd/addr.h> + +#include <pt-internal.h> + +extern struct hurd_startup_data *__hurd_startup_data; + +extern addr_t meta_data_activity; + +int +__pthread_thread_alloc (struct __pthread *thread) +{ + /* The main thread is already running of course. */ + if (__pthread_num_threads == 1) + { + thread->object = __hurd_startup_data->thread; + thread->threadid = l4_myself (); + return 0; + } + else + { + addr_t exception_area = as_alloc (EXCEPTION_AREA_SIZE_LOG2, 1, true); + + thread->exception_area_va + = ADDR_TO_PTR (addr_extend (exception_area, + 0, EXCEPTION_AREA_SIZE_LOG2)); + + int i; + for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++) + { + addr_t slot = addr_chop (PTR_TO_ADDR (thread->exception_area_va + + i * PAGESIZE), + PAGESIZE_LOG2); + as_ensure (slot); + + struct storage storage = storage_alloc (ADDR_VOID, cap_page, + STORAGE_LONG_LIVED, + OBJECT_POLICY_DEFAULT, + slot); + if (ADDR_IS_VOID (storage.addr)) + { + int j; + for (j = 0; j < i; j ++) + storage_free (thread->exception_area[j], false); + as_free (exception_area, false); + return EAGAIN; + } + + thread->exception_area[i] = storage.addr; + } + + struct storage storage; + storage = storage_alloc (meta_data_activity, cap_thread, + /* Threads are rarely shortly lived. */ + STORAGE_MEDIUM_LIVED, OBJECT_POLICY_DEFAULT, + ADDR_VOID); + if (ADDR_IS_VOID (storage.addr)) + { + int j; + for (j = 0; j < EXCEPTION_AREA_SIZE / PAGESIZE; j ++) + storage_free (thread->exception_area[j], false); + as_free (exception_area, false); + return EAGAIN; + } + + thread->object = storage.addr; + } + + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-halt.c b/libpthread/sysdeps/l4/hurd/pt-thread-halt.c new file mode 100644 index 00000000..98fefaab --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-thread-halt.c @@ -0,0 +1,104 @@ +/* Deallocate the kernel thread resources. Viengoos version. + Copyright (C) 2007, 2008 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 <assert.h> +#include <errno.h> + +#include <pt-internal.h> + +#include <hurd/exceptions.h> +#include <hurd/mutex.h> +#include <hurd/as.h> +#include <hurd/addr.h> + +/* If we try to deallocate our self, we will end up causing a + deadlock. Thus, when a thread tries to free itself, we add it + here. The next thread to free a thread will free it. */ +ss_mutex_t saved_object_lock; +static addr_t saved_object; + +void +__pthread_thread_halt (struct __pthread *thread, int need_dealloc) +{ + /* We may deallocate THREAD. First save any data we need. */ + + addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE]; + memcpy (exception_area, thread->exception_area, + sizeof (thread->exception_area)); + memset (thread->exception_area, 0, sizeof (thread->exception_area)); + + void *va = thread->exception_area_va; + + addr_t object = thread->object; + l4_thread_id_t tid = thread->threadid; + + if (need_dealloc) + __pthread_dealloc (thread); + + /* The THREAD data structure is no longer valid. */ + thread = NULL; + + /* Deallocate any saved object. */ + ss_mutex_lock (&saved_object_lock); + if (! ADDR_IS_VOID (saved_object)) + { + storage_free (saved_object, false); + saved_object = ADDR_VOID; + } + ss_mutex_unlock (&saved_object_lock); + + /* Free the exception area. */ + + /* Clean up the exception page. */ + exception_page_cleanup + (ADDR_TO_PTR (addr_extend (exception_area[EXCEPTION_PAGE], + 0, PAGESIZE_LOG2))); + + /* Free the storage. */ + int i; + for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++) + { + assert (! ADDR_IS_VOID (exception_area[i])); + storage_free (exception_area[i], false); + } + + /* And the address space. */ + as_free (addr_chop (PTR_TO_ADDR (va), EXCEPTION_AREA_SIZE_LOG2), false); + + if (tid == l4_myself ()) + /* If we try to storage_free (storage.addr), we will freeze in the + middle. That's no good. We set SAVED_OBJECT to our thread + object and the next thread in will free us. */ + { + ss_mutex_lock (&saved_object_lock); + saved_object = object; + ss_mutex_unlock (&saved_object_lock); + } + else + storage_free (object, false); + + if (tid == l4_myself ()) + { + l4_send_timeout (l4_myself (), L4_NEVER); + panic ("Failed to stop thread %x.%x!", + l4_thread_no (l4_myself ()), l4_version (l4_myself ())); + } + else + thread_stop (object); +} diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-start.c b/libpthread/sysdeps/l4/hurd/pt-thread-start.c new file mode 100644 index 00000000..9db399ce --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-thread-start.c @@ -0,0 +1,70 @@ +/* Start thread. L4 version. + Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <assert.h> +#include <errno.h> +#include <string.h> +#include <hurd/thread.h> +#include <hurd/exceptions.h> + +#include <pt-internal.h> + +int +__pthread_thread_start (struct __pthread *thread) +{ + error_t err; + + if (__pthread_num_threads == 1) + /* The main thread is already running of course. */ + { + assert (__pthread_total == 1); + assert (l4_is_thread_equal (l4_myself (), thread->threadid)); + l4_set_user_defined_handle ((l4_word_t) thread); + } + else + { + struct hurd_thread_exregs_in in; + struct hurd_thread_exregs_out out; + + in.aspace = ADDR (0, 0); + in.aspace_cap_properties = CAP_PROPERTIES_VOID; + in.aspace_cap_properties_flags = CAP_COPY_COPY_SOURCE_GUARD; + + in.activity = ADDR_VOID; + + in.exception_page = addr_chop (PTR_TO_ADDR (thread->exception_area_va), + PAGESIZE_LOG2); + + in.sp = (l4_word_t) thread->mcontext.sp; + in.ip = (l4_word_t) thread->mcontext.pc; + + in.user_handle = (l4_word_t) thread; + err = rm_thread_exregs (ADDR_VOID, thread->object, + HURD_EXREGS_SET_ASPACE + | HURD_EXREGS_SET_ACTIVITY + | HURD_EXREGS_SET_EXCEPTION_PAGE + | HURD_EXREGS_SET_SP_IP + | HURD_EXREGS_SET_USER_HANDLE + | HURD_EXREGS_START + | HURD_EXREGS_ABORT_IPC, + in, &out); + assert (err == 0); + } + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-wakeup.c b/libpthread/sysdeps/l4/hurd/pt-wakeup.c new file mode 100644 index 00000000..e568a6f9 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-wakeup.c @@ -0,0 +1,46 @@ +/* Wakeup a thread. Viengoos version. + Copyright (C) 2008 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 <pt-internal.h> + +#include <hurd/stddef.h> +#include <hurd/futex.h> +#include <stdint.h> + +/* Wakeup THREAD. */ +void +__pthread_wakeup (struct __pthread *thread) +{ + /* We need to loop here as the blocked thread may not yet be + blocked! Here's what happens when a thread blocks: it registers + itself as blocked, drops the relevant lock and then actually + blocks (via __pthread_block). This means that after dropping the + lock and before blocking, it may be interrupted and another + thread may try to wake it. */ + long ret; + do + { + ret = futex_wake (&thread->threadid, INT_MAX); + assertx (ret <= 1, "tid: %x, ret: %d", thread->threadid, ret); + + if (ret == 0) + l4_thread_switch (thread->threadid); + } + while (ret == 0); +} diff --git a/libpthread/sysdeps/l4/hurd/sig-sysdep.h b/libpthread/sysdeps/l4/hurd/sig-sysdep.h new file mode 100644 index 00000000..33e13857 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/sig-sysdep.h @@ -0,0 +1,69 @@ +/* sig-sysdep.h - Hurd system specific header file. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <l4.h> +#include <string.h> + +struct utcb +{ + l4_word_t saved_sender; + l4_word_t saved_receiver; + l4_word_t saved_timeout; + l4_word_t saved_error_code; + l4_word_t saved_flags; + l4_word_t saved_br0; + l4_msg_t saved_message; +}; + +static inline void +utcb_state_save (struct utcb *buffer) +{ + l4_word_t *utcb = _L4_utcb (); + + buffer->saved_sender = utcb[_L4_UTCB_SENDER]; + buffer->saved_receiver = utcb[_L4_UTCB_RECEIVER]; + buffer->saved_timeout = utcb[_L4_UTCB_TIMEOUT]; + buffer->saved_error_code = utcb[_L4_UTCB_ERROR_CODE]; + buffer->saved_flags = utcb[_L4_UTCB_FLAGS]; + buffer->saved_br0 = utcb[_L4_UTCB_BR0]; + memcpy (&buffer->saved_message, + utcb, L4_NUM_MRS * sizeof (l4_word_t)); +} + +static inline void +utcb_state_restore (struct utcb *buffer) +{ + l4_word_t *utcb = _L4_utcb (); + + utcb[_L4_UTCB_SENDER] = buffer->saved_sender; + utcb[_L4_UTCB_RECEIVER] = buffer->saved_receiver; + utcb[_L4_UTCB_TIMEOUT] = buffer->saved_timeout; + utcb[_L4_UTCB_ERROR_CODE] = buffer->saved_error_code; + utcb[_L4_UTCB_FLAGS] = buffer->saved_flags; + utcb[_L4_UTCB_BR0] = buffer->saved_br0; + memcpy (utcb, &buffer->saved_message, + L4_NUM_MRS * sizeof (l4_word_t)); +} + +#define SIGNAL_DISPATCH_ENTRY \ + struct utcb buffer; utcb_state_save (&buffer); + +#define SIGNAL_DISPATCH_EXIT \ + utcb_state_restore (&buffer); diff --git a/libpthread/sysdeps/l4/hurd/sigprocmask.c b/libpthread/sysdeps/l4/hurd/sigprocmask.c new file mode 100644 index 00000000..a38b3795 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/sigprocmask.c @@ -0,0 +1,41 @@ +/* sigprocmask.c - Generic sigprocmask implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <pt-internal.h> +#include <sig-internal.h> + +int +sigprocmask (int how, const sigset_t *restrict set, sigset_t *restrict old) +{ + struct __pthread *thread = _pthread_self (); + if (! thread) + /* Library is initializing. */ + { + assert (__pthread_num_threads == 1); + + /* We should get the default mask from the startup data structure. */ + if (old) + *old = 0; + + return 0; + } + + return pthread_sigmask (how, set, old); +} diff --git a/libpthread/sysdeps/l4/pt-block.c b/libpthread/sysdeps/l4/pt-block.c new file mode 100644 index 00000000..69e1d358 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-block.c @@ -0,0 +1,47 @@ +/* Block a thread. L4 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. */ + +#include <l4.h> + +#include <pt-internal.h> + +#include <hurd/stddef.h> + +/* Block THREAD. */ +void +__pthread_block (struct __pthread *thread) +{ + debug (5, "%x.%x/%x blocking", + l4_thread_no (thread->threadid), l4_version (thread->threadid), + thread->threadid); + + l4_accept (L4_UNTYPED_WORDS_ACCEPTOR); + l4_msg_tag_t tag = l4_receive (l4_anythread); + if (l4_ipc_failed (tag)) + { + debug (1, "%x.%x failed to block: %d, offset: %x", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + (l4_error_code () >> 1) & 0x7, + l4_error_code () >> 4); + assert (! l4_ipc_failed (tag)); + } + else + debug (5, "%x.%x unblocked", + l4_thread_no (thread->threadid), l4_version (thread->threadid)); +} diff --git a/libpthread/sysdeps/l4/pt-docancel.c b/libpthread/sysdeps/l4/pt-docancel.c new file mode 100644 index 00000000..a3965d0d --- /dev/null +++ b/libpthread/sysdeps/l4/pt-docancel.c @@ -0,0 +1,42 @@ +/* Cancel a thread. + Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <pthread.h> + +#include <pt-internal.h> + +static void +call_exit (void) +{ + pthread_exit (0); +} + +int +__pthread_do_cancel (struct __pthread *p) +{ + assert (p->cancel_pending == 1); + assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); + + if (l4_is_thread_equal (l4_myself (), p->threadid)) + call_exit (); + else + l4_start_sp_ip (p->threadid, (l4_word_t) p->mcontext.sp, + (l4_word_t) call_exit); + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-pool-np.c b/libpthread/sysdeps/l4/pt-pool-np.c new file mode 100644 index 00000000..e83022ba --- /dev/null +++ b/libpthread/sysdeps/l4/pt-pool-np.c @@ -0,0 +1,54 @@ +/* Thread pool for L4 threads. + Copyright (C) 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <pt-internal.h> +#include <l4/thread.h> + +static pthread_mutex_t pool_lock = PTHREAD_MUTEX_INITIALIZER; + +_L4_thread_id_t pool_list = l4_nilthread; + +/* Add the thread TID to the pthread kernel thread pool. */ +int +pthread_pool_add_np (l4_thread_id_t tid) +{ + __pthread_mutex_lock (&pool_lock); + /* FIXME: Do error checking. */ + l4_set_user_defined_handle_of (tid, pool_list); + pool_list = tid; + __pthread_mutex_unlock (&pool_lock); + + return 0; +} + + +/* Get the first thread from the pool. */ +l4_thread_id_t +pthread_pool_get_np (void) +{ + _L4_thread_id_t tid; + + __pthread_mutex_lock (&pool_lock); + /* FIXME: Do error checking. */ + tid = pool_list; + if (tid != l4_nilthread) + pool_list = l4_user_defined_handle_of (tid); + __pthread_mutex_unlock (&pool_lock); + return tid; +} diff --git a/libpthread/sysdeps/l4/pt-spin.c b/libpthread/sysdeps/l4/pt-spin.c new file mode 100644 index 00000000..b6978b0c --- /dev/null +++ b/libpthread/sysdeps/l4/pt-spin.c @@ -0,0 +1,63 @@ +/* Spin locks. L4 version. + Copyright (C) 2000, 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 <l4.h> + +#include <pthread.h> +#include <sched.h> + +/* The default for single processor machines; don't spin, it's + pointless. */ +#ifndef __PTHREAD_SPIN_COUNT +# define __PTHREAD_SPIN_COUNT 1 +#endif + +/* The number of times to spin while trying to lock a spin lock object + before yielding the processor. */ +int __pthread_spin_count = __PTHREAD_SPIN_COUNT; + + +/* Lock the spin lock object LOCK. If the lock is held by another + thread spin until it becomes available. */ +int +_pthread_spin_lock (__pthread_spinlock_t *lock) +{ + l4_time_t timeout; + int i; + + /* Start with a small timeout of 2 microseconds, then back off + exponentially. */ + timeout = l4_time_period (2); + + while (1) + { + for (i = 0; i < __pthread_spin_count; i++) + { + if (__pthread_spin_trylock (lock) == 0) + return 0; + } + l4_sleep (timeout); + + timeout = l4_time_mul2 (timeout); + if (timeout == L4_NEVER) + timeout = L4_TIME_PERIOD_MAX; + } +} + +weak_alias (_pthread_spin_lock, pthread_spin_lock); diff --git a/libpthread/sysdeps/l4/pt-stack-alloc.c b/libpthread/sysdeps/l4/pt-stack-alloc.c new file mode 100644 index 00000000..b7ec12b4 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-stack-alloc.c @@ -0,0 +1,43 @@ +/* Allocate a new stack. L4 Hurd version. + Copyright (C) 2000, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <l4.h> +#include <errno.h> + +#include <pt-internal.h> + +#include <sys/mman.h> + +/* Allocate a new stack of size STACKSIZE. If successful, store the + address of the newly allocated stack in *STACKADDR and return 0. + Otherwise return an error code (EINVAL for an invalid stack size, + EAGAIN if the system lacked the necessary resources to allocate a + new stack). */ +int +__pthread_stack_alloc (void **stackaddr, size_t stacksize) +{ + void *buffer = mmap (0, stacksize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buffer == MAP_FAILED) + return EAGAIN; + + *stackaddr = buffer; + + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-thread-alloc.c b/libpthread/sysdeps/l4/pt-thread-alloc.c new file mode 100644 index 00000000..ec69afb5 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-thread-alloc.c @@ -0,0 +1,43 @@ +/* Allocate kernel thread. L4 version. + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <assert.h> +#include <errno.h> +#include <string.h> + +#include <pt-internal.h> + +int +__pthread_thread_alloc (struct __pthread *thread) +{ + error_t err; + + /* The main thread is already running of course. */ + if (__pthread_num_threads == 1) + thread->threadid = l4_myself (); + else + { + thread->threadid = pthread_pool_get_np (); + if (thread->threadid != l4_nilthread) + return 0; + + return EAGAIN; + } + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-thread-dealloc.c b/libpthread/sysdeps/l4/pt-thread-dealloc.c new file mode 100644 index 00000000..c09e4860 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-thread-dealloc.c @@ -0,0 +1,32 @@ +/* Deallocate the kernel thread resources. L4 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 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 <assert.h> +#include <errno.h> +#include <l4.h> + +#include <pt-internal.h> + +/* Deallocate any kernel resources associated with THREAD except don't + halt the thread itself. On return, the thread will be marked as + dead and __pthread_halt will be called. */ +void +__pthread_thread_dealloc (struct __pthread *thread) +{ +} diff --git a/libpthread/sysdeps/l4/pt-thread-halt.c b/libpthread/sysdeps/l4/pt-thread-halt.c new file mode 100644 index 00000000..aa2bf43d --- /dev/null +++ b/libpthread/sysdeps/l4/pt-thread-halt.c @@ -0,0 +1,45 @@ +/* Deallocate the kernel thread resources. L4version. + 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 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 <assert.h> +#include <errno.h> + +#include <pt-internal.h> + +/* Deallocate the kernel thread resources associated with THREAD. */ +void +__pthread_thread_halt (struct __pthread *thread, int need_dealloc) +{ + l4_thread_id_t tid = thread->threadid; + + if (need_dealloc) + __pthread_dealloc (thread); + + /* There is potential race here: once if TID is the current thread, + then once we add TID to the pool, someone can reallocate it + before we call stop. However, to start the thread, the caller + atomically starts and sets the sp and ip, thus, if the stop has + not yet executed at that point, it won't. */ + + if (tid != l4_myself ()) + l4_stop (tid); + pthread_pool_add_np (tid); + if (tid == l4_myself ()) + l4_stop (tid); +} diff --git a/libpthread/sysdeps/l4/pt-thread-start.c b/libpthread/sysdeps/l4/pt-thread-start.c new file mode 100644 index 00000000..144c58bb --- /dev/null +++ b/libpthread/sysdeps/l4/pt-thread-start.c @@ -0,0 +1,40 @@ +/* Start thread. L4 version. + Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <assert.h> +#include <errno.h> +#include <string.h> + +#include <pt-internal.h> + +/* Start THREAD. Get the kernel thread scheduled and running. */ +int +__pthread_thread_start (struct __pthread *thread) +{ + if (__pthread_num_threads == 1) + /* The main thread is already running of course. */ + { + assert (__pthread_total == 1); + assert (l4_is_thread_equal (l4_myself (), thread->threadid)); + } + else + l4_start_sp_ip (thread->threadid, (l4_word_t) thread->mcontext.sp, + (l4_word_t) thread->mcontext.pc); + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-timedblock.c b/libpthread/sysdeps/l4/pt-timedblock.c new file mode 100644 index 00000000..ce7972bd --- /dev/null +++ b/libpthread/sysdeps/l4/pt-timedblock.c @@ -0,0 +1,35 @@ +/* Block a thread with a timeout. L4 version. + Copyright (C) 2000,02 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 <assert.h> +#include <errno.h> +#include <time.h> +#include <sys/time.h> + +#include <pt-internal.h> + +/* Block THREAD. */ +error_t +__pthread_timedblock (struct __pthread *thread, + const struct timespec *abstime) +{ +#warning Need gettimeofday to implement properly. + __pthread_block (thread); + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-wakeup.c b/libpthread/sysdeps/l4/pt-wakeup.c new file mode 100644 index 00000000..de378465 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-wakeup.c @@ -0,0 +1,54 @@ +/* Wakeup a thread. L4 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. */ + +#include <l4.h> + +#include <pt-internal.h> + +#include <hurd/stddef.h> + +/* Wakeup THREAD. */ +void +__pthread_wakeup (struct __pthread *thread) +{ + debug (5, "%x.%x/%x waking %x.%x/%x", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), l4_myself (), + l4_thread_no (thread->threadid), l4_version (thread->threadid), + thread->threadid); + + /* Signal the waiter. */ + l4_msg_t msg; + l4_msg_clear (msg); + l4_msg_set_untyped_words (msg, 0); + l4_msg_load (msg); + + l4_msg_tag_t tag = l4_send (thread->threadid); + if (l4_ipc_failed (tag)) + { + int err = l4_error_code (); + debug (1, "%x.%x failed to wake %x.%x: %s (%d)", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + l4_thread_no (thread->threadid), l4_version (thread->threadid), + l4_strerror (err), err); + } + else + debug (5, "%x.%x woke %x.%x", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + l4_thread_no (thread->threadid), l4_version (thread->threadid)); +} diff --git a/libpthread/sysdeps/mach/bits/spin-lock-inline.h b/libpthread/sysdeps/mach/bits/spin-lock-inline.h new file mode 100644 index 00000000..f9f7c299 --- /dev/null +++ b/libpthread/sysdeps/mach/bits/spin-lock-inline.h @@ -0,0 +1,90 @@ +/* Definitions of user-visible names for spin locks. + Copyright (C) 1994, 1997, 2002, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SPIN_LOCK_INLINE_H +#define _BITS_SPIN_LOCK_INLINE_H 1 + +#include <features.h> +#include <bits/spin-lock.h> +#include <machine-lock.h> /* This does all the work. */ + +__BEGIN_DECLS + +#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES + +# ifndef __EBUSY +# include <errno.h> +# define __EBUSY EBUSY +# endif + +# ifndef __PT_SPIN_INLINE +# define __PT_SPIN_INLINE __extern_inline +# endif + +__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_destroy (__pthread_spinlock_t *__lock) +{ + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, + int __pshared); + +__PT_SPIN_INLINE int +__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) +{ + *__lock = __PTHREAD_SPIN_LOCK_INITIALIZER; + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_trylock (__pthread_spinlock_t *__lock) +{ + return __spin_try_lock (__lock) ? 0 : __EBUSY; +} + +__extern_inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +__extern_inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__lock); + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_unlock (__pthread_spinlock_t *__lock) +{ + __spin_unlock (__lock); + return 0; +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/libpthread/sysdeps/mach/bits/spin-lock.h b/libpthread/sysdeps/mach/bits/spin-lock.h new file mode 100644 index 00000000..537dac9d --- /dev/null +++ b/libpthread/sysdeps/mach/bits/spin-lock.h @@ -0,0 +1,38 @@ +/* Definitions of user-visible names for spin locks. + Copyright (C) 1994, 1997, 2002, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SPIN_LOCK_H +#define _BITS_SPIN_LOCK_H 1 + +#include <features.h> +#include <machine-lock.h> /* This does all the work. */ + +__BEGIN_DECLS + +/* The type of a spin lock object. */ +typedef __spin_lock_t __pthread_spinlock_t; + +/* Initializer for a spin lock object. */ +#ifndef __PTHREAD_SPIN_LOCK_INITIALIZER +#error __PTHREAD_SPIN_LOCK_INITIALIZER undefined: should be defined by <lock-intern.h>. +#endif + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/libpthread/sysdeps/mach/hurd/ia32/pt-machdep.c b/libpthread/sysdeps/mach/hurd/ia32/pt-machdep.c new file mode 100644 index 00000000..face46c5 --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/ia32/pt-machdep.c @@ -0,0 +1,54 @@ +/* Machine dependent pthreads code. Hurd/i386 version. + Copyright (C) 2000,02 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 <mach.h> +#include <mach/i386/thread_status.h> +#include <mach/thread_status.h> + +int +__thread_set_pcsp (thread_t thread, + int set_ip, void *ip, + int set_sp, void *sp) +{ + error_t err; + struct i386_thread_state state; + mach_msg_type_number_t state_count; + + state_count = i386_THREAD_STATE_COUNT; + + err = __thread_get_state (thread, i386_THREAD_STATE, + (thread_state_t) &state, &state_count); + if (err) + return err; + + if (set_sp) + state.uesp = (unsigned int) sp; + if (set_ip) + state.eip = (unsigned int) ip; + + err = __thread_set_state (thread, i386_THREAD_STATE, + (thread_state_t) &state, + i386_THREAD_STATE_COUNT); + if (err) + return err; + + return 0; +} diff --git a/libpthread/sysdeps/mach/hurd/ia32/pt-setup.c b/libpthread/sysdeps/mach/hurd/ia32/pt-setup.c new file mode 100644 index 00000000..ba438d6a --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/ia32/pt-setup.c @@ -0,0 +1,105 @@ +/* Setup thread stack. Hurd/i386 version. + Copyright (C) 2000, 2002, 2005, 2008 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 <stdint.h> +#include <assert.h> +#include <mach.h> + +#include <pt-internal.h> + +/* The stack layout used on the i386 is: + + ----------------- + | ARG | + ----------------- + | START_ROUTINE | + ----------------- + | 0 | + ----------------- + | | + | Fast TSD | + | | + ----------------- + + We need to reserve __hurd_threadvar_max `unsigned long int's' of + (fast) thread-specific data (TSD) for the Hurd. */ + +/* Set up the stack for THREAD, such that it appears as if + START_ROUTINE and ARG were passed to the new thread's entry-point. + Return the stack pointer for the new thread. */ +static void * +stack_setup (struct __pthread *thread, + void *(*start_routine)(void *), void *arg) +{ + error_t err; + uintptr_t *bottom, *top; + + /* Calculate the top of the new stack. */ + bottom = thread->stackaddr; + top = (uintptr_t *) ((uintptr_t) bottom + thread->stacksize); + + /* Next, make room for the TSDs. */ + top -= __hurd_threadvar_max; + + /* Save the self pointer. */ + top[_HURD_THREADVAR_THREAD] = (uintptr_t) thread; + + if (start_routine) + { + /* And then the call frame. */ + top -= 2; + top = (uintptr_t) top & ~0xf; + top[1] = (uintptr_t) arg; /* Argument to START_ROUTINE. */ + top[0] = (uintptr_t) start_routine; + *--top = 0; /* Fake return address. */ + } + + if (thread->guardsize) + { + err = __vm_protect (__mach_task_self (), (vm_address_t) bottom, + thread->guardsize, 0, 0); + assert_perror (err); + } + + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + error_t err; + mach_port_t ktid; + + thread->mcontext.pc = entry_point; + thread->mcontext.sp = stack_setup (thread, start_routine, arg); + + ktid = __mach_thread_self (); + if (thread->kernel_thread != ktid) + { + err = __thread_set_pcsp (thread->kernel_thread, + 1, thread->mcontext.pc, + 1, thread->mcontext.sp); + assert_perror (err); + } + __mach_port_deallocate (__mach_task_self (), ktid); + + return 0; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-attr-setstackaddr.c b/libpthread/sysdeps/mach/hurd/pt-attr-setstackaddr.c new file mode 100644 index 00000000..1225ed5b --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-attr-setstackaddr.c @@ -0,0 +1,35 @@ +/* pthread_attr_setstackaddr. Hurd on Mach 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +/* We use fixed sized stacks which require proper alignment. */ +#define __pthread_stacksize __pthread_default_attr.stacksize + +int +pthread_attr_setstackaddr (pthread_attr_t *attr, + void *stackaddr) +{ + if ((long) stackaddr & (__pthread_stacksize - 1)) + return EINVAL; + + attr->stackaddr = stackaddr; + return 0; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-attr-setstacksize.c b/libpthread/sysdeps/mach/hurd/pt-attr-setstacksize.c new file mode 100644 index 00000000..6471c0a3 --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-attr-setstacksize.c @@ -0,0 +1,35 @@ +/* pthread_attr_setstacksize. Hurd on Mach 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. */ + +#include <pthread.h> +#include <pt-internal.h> + +/* We use fixed sized stacks which require proper alignment. */ +#define __pthread_stacksize __pthread_default_attr.stacksize + +int +pthread_attr_setstacksize (pthread_attr_t *attr, + size_t stacksize) +{ + if (stacksize != __pthread_stacksize) + return EINVAL; + + attr->stacksize = stacksize; + return 0; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-docancel.c b/libpthread/sysdeps/mach/hurd/pt-docancel.c new file mode 100644 index 00000000..b81a5c70 --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-docancel.c @@ -0,0 +1,64 @@ +/* Cancel a thread. + Copyright (C) 2002, 2008 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 <pthread.h> + +#include <pt-internal.h> + +static void +call_exit (void) +{ + pthread_exit (0); +} + +int +__pthread_do_cancel (struct __pthread *p) +{ + mach_port_t ktid; + int me; + + assert (p->cancel_pending == 1); + assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); + + ktid = __mach_thread_self (); + me = p->kernel_thread == ktid; + __mach_port_deallocate (__mach_task_self (), ktid); + + if (me) + call_exit (); + else + { + error_t err; + + err = __thread_suspend (p->kernel_thread); + assert_perror (err); + + err = __thread_abort (p->kernel_thread); + assert_perror (err); + + err = __thread_set_pcsp (p->kernel_thread, + 1, (void *) call_exit, 0, 0); + assert_perror (err); + + err = __thread_resume (p->kernel_thread); + assert_perror (err); + } + + return 0; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-sigstate-destroy.c b/libpthread/sysdeps/mach/hurd/pt-sigstate-destroy.c new file mode 100644 index 00000000..8e56c5cf --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-sigstate-destroy.c @@ -0,0 +1,28 @@ +/* Destroy the signal state. Hurd on Mach 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. */ + +#include <pthread.h> + +#include <pt-internal.h> + +void +__pthread_sigstate_destroy (struct __pthread *thread) +{ + /* Nothing to do. */ +} diff --git a/libpthread/sysdeps/mach/hurd/pt-sigstate-init.c b/libpthread/sysdeps/mach/hurd/pt-sigstate-init.c new file mode 100644 index 00000000..da5a9455 --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-sigstate-init.c @@ -0,0 +1,37 @@ +/* Initialize the signal state. Hurd on Mach 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. */ + +#include <pthread.h> +#include <hurd/threadvar.h> + +#include <pt-internal.h> + +error_t +__pthread_sigstate_init (struct __pthread *thread) +{ + void **location = + (void *) __hurd_threadvar_location_from_sp (_HURD_THREADVAR_SIGSTATE, + thread->stackaddr); + + /* The real initialization happens internally in glibc the first + time that _hurd_thead_sigstate is called. */ + *location = 0; + + return 0; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-sigstate.c b/libpthread/sysdeps/mach/hurd/pt-sigstate.c new file mode 100644 index 00000000..68c79c5b --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-sigstate.c @@ -0,0 +1,69 @@ +/* Set a thread's signal state. Hurd on Mach 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. */ + +#include <pthread.h> +#include <assert.h> +#include <signal.h> +#include <hurd/signal.h> + +#include <pt-internal.h> + +error_t +__pthread_sigstate (struct __pthread *thread, int how, + const sigset_t *set, sigset_t *oset, + int clear_pending) +{ + error_t err = 0; + struct hurd_sigstate *ss; + + ss = _hurd_thread_sigstate (thread->kernel_thread); + assert (ss); + + __pthread_spin_lock (&ss->lock); + + if (oset) + *oset = ss->blocked; + + if (set) + switch (how) + { + case SIG_BLOCK: + ss->blocked |= *set; + break; + + case SIG_SETMASK: + ss->blocked = *set; + break; + + case SIG_UNBLOCK: + ss->blocked &= ~*set; + break; + + default: + err = EINVAL; + break; + } + + if (! err && clear_pending) + __sigemptyset (&ss->pending); + + __pthread_spin_unlock (&ss->lock); + + return err; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-sysdep.c b/libpthread/sysdeps/mach/hurd/pt-sysdep.c new file mode 100644 index 00000000..5e070067 --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-sysdep.c @@ -0,0 +1,72 @@ +/* System dependent pthreads code. Hurd version. + Copyright (C) 2000, 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 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 <assert.h> +#include <stddef.h> +#include <stdint.h> + +#include <mach.h> +#include <mach/mig_support.h> + +#include <hurd/threadvar.h> + +#include <pt-internal.h> + +/* Forward. */ +static void *init_routine (void); + +/* OK, the name of this variable isn't really appropriate, but I don't + want to change it yet. */ +void *(*_cthread_init_routine)(void) = &init_routine; + +/* This function is called from the Hurd-specific startup code. It + should return a new stack pointer for the main thread. The caller + will switch to this new stack before doing anything serious. */ +static void * +init_routine (void) +{ + struct __pthread *thread; + int err; + + /* Initialize the library. */ + __pthread_initialize (); + + /* Create the pthread structure for the main thread (i.e. us). */ + err = __pthread_create_internal (&thread, 0, 0, 0); + assert_perror (err); + + ((void **) (__hurd_threadvar_stack_offset))[_HURD_THREADVAR_THREAD] + = thread; + + /* Decrease the number of threads, to take into account that the + signal thread (which will be created by the glibc startup code + when we return from here) shouldn't be seen as a user thread. */ + __pthread_total--; + + /* Make MiG code thread aware. */ + __mig_init (thread->stackaddr); + + /* Make sure we can find the per-thread variables. */ + __hurd_threadvar_stack_mask = ~(__pthread_default_attr.stacksize - 1); + __hurd_threadvar_stack_offset + = (__pthread_default_attr.stacksize + - __hurd_threadvar_max * sizeof (uintptr_t)); + + return thread->mcontext.sp; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-sysdep.h b/libpthread/sysdeps/mach/hurd/pt-sysdep.h new file mode 100644 index 00000000..f14a1366 --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-sysdep.h @@ -0,0 +1,70 @@ +/* Internal defenitions for pthreads library. + Copyright (C) 2000, 2002, 2008 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. */ + +#ifndef _PT_SYSDEP_H +#define _PT_SYSDEP_H 1 + +#include <mach.h> + +#include <hurd/threadvar.h> + +/* XXX */ +#define _POSIX_THREAD_THREADS_MAX 64 + +/* The default stack size. */ +#define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) + +#define PTHREAD_SYSDEP_MEMBERS \ + thread_t kernel_thread; \ + mach_msg_header_t wakeupmsg; \ + int have_kernel_resources; + +#define _HURD_THREADVAR_THREAD _HURD_THREADVAR_DYNAMIC_USER + +#define _pthread_self() \ + ({ \ + struct __pthread *thread; \ + \ + assert (__pthread_threads); \ + thread = *(struct __pthread **) \ + __hurd_threadvar_location (_HURD_THREADVAR_THREAD); \ + \ + assert (thread); \ + assert (({ mach_port_t ktid = __mach_thread_self (); \ + int ok = thread->kernel_thread == ktid; \ + __mach_port_deallocate (__mach_task_self (), ktid);\ + ok; })); \ + thread; \ + }) + +extern inline void +__attribute__((__always_inline__)) +__pthread_stack_dealloc (void *stackaddr, size_t stacksize) +{ + __vm_deallocate (__mach_task_self (), (vm_offset_t) stackaddr, stacksize); +} + +/* Change thread THREAD's program counter to PC if SET_PC is true and + its stack pointer to SP if SET_IP is true. */ +extern int __thread_set_pcsp (thread_t thread, + int set_pc, void *pc, + int set_sp, void *sp); + + +#endif /* pt-sysdep.h */ diff --git a/libpthread/sysdeps/mach/pt-block.c b/libpthread/sysdeps/mach/pt-block.c new file mode 100644 index 00000000..a947b27c --- /dev/null +++ b/libpthread/sysdeps/mach/pt-block.c @@ -0,0 +1,39 @@ +/* Block a thread. Mach version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <assert.h> +#include <errno.h> + +#include <mach.h> +#include <mach/message.h> + +#include <pt-internal.h> + +/* Block THREAD. */ +void +__pthread_block (struct __pthread *thread) +{ + mach_msg_header_t msg; + error_t err; + + err = __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof msg, + thread->wakeupmsg.msgh_remote_port, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + assert_perror (err); +} diff --git a/libpthread/sysdeps/mach/pt-spin.c b/libpthread/sysdeps/mach/pt-spin.c new file mode 100644 index 00000000..d9a2a32a --- /dev/null +++ b/libpthread/sysdeps/mach/pt-spin.c @@ -0,0 +1,36 @@ +/* Spin locks. Mach version. + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <pthread.h> +#include <machine-lock.h> + +/* In glibc. */ +extern void __spin_lock_solid (__pthread_spinlock_t *lock); + +/* Lock the spin lock object LOCK. If the lock is held by another + thread spin until it becomes available. */ +int +_pthread_spin_lock (__pthread_spinlock_t *lock) +{ + __spin_lock_solid (lock); + return 0; +} + +weak_alias (_pthread_spin_lock, pthread_spin_lock); +weak_alias (_pthread_spin_lock, __pthread_spin_lock); diff --git a/libpthread/sysdeps/mach/pt-stack-alloc.c b/libpthread/sysdeps/mach/pt-stack-alloc.c new file mode 100644 index 00000000..0956fc7d --- /dev/null +++ b/libpthread/sysdeps/mach/pt-stack-alloc.c @@ -0,0 +1,74 @@ +/* Allocate a new stack. Mach version. + Copyright (C) 2000,02 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 <mach.h> +#include <mach/machine/vm_param.h> + +#include <pt-internal.h> + +#define __pthread_stacksize __pthread_default_attr.stacksize + +/* The next address to use for stack allocation. */ +static vm_address_t next_stack_base = VM_MIN_ADDRESS; + + +/* Allocate a new stack of size STACKSIZE. If successful, store the + address of the newly allocated stack in *STACKADDR and return 0. + Otherwise return an error code (EINVAL for an invalid stack size, + EAGAIN if the system lacked the necessary resources to allocate a + new stack). */ +int +__pthread_stack_alloc (void **stackaddr, size_t stacksize) +{ + vm_offset_t base; + int i = 0; + + if (stacksize != __pthread_stacksize) + return EINVAL; + + get_stack: + i ++; + for (base = next_stack_base; + base < VM_MAX_ADDRESS + && __vm_allocate (__mach_task_self (), &base, + __pthread_stacksize, FALSE) != KERN_SUCCESS; + base += __pthread_stacksize) + ; + + if (base >= VM_MAX_ADDRESS) + { + if (i == 1) + { + next_stack_base = VM_MIN_ADDRESS; + goto get_stack; + } + else + return EAGAIN; + } + + if (base >= VM_MAX_ADDRESS) + return EAGAIN; + + next_stack_base = base + __pthread_stacksize; + + (*stackaddr) = (void *) base; + return 0; +} diff --git a/libpthread/sysdeps/mach/pt-thread-alloc.c b/libpthread/sysdeps/mach/pt-thread-alloc.c new file mode 100644 index 00000000..3d7c0465 --- /dev/null +++ b/libpthread/sysdeps/mach/pt-thread-alloc.c @@ -0,0 +1,106 @@ +/* Start thread. Mach version. + Copyright (C) 2000, 2002, 2005, 2008 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 <assert.h> +#include <errno.h> +#include <string.h> + +#include <mach.h> + +#include <pt-internal.h> + +/* Prepare a wakeup message. */ +static error_t +create_wakeupmsg (struct __pthread *thread) +{ + kern_return_t err; + + /* Build wakeup message. */ + thread->wakeupmsg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); + thread->wakeupmsg.msgh_size = 0; + + err = __mach_port_allocate (__mach_task_self (), MACH_PORT_RIGHT_RECEIVE, + &thread->wakeupmsg.msgh_remote_port); + if (err) + return EAGAIN; + + thread->wakeupmsg.msgh_local_port = MACH_PORT_NULL; + thread->wakeupmsg.msgh_seqno = 0; + thread->wakeupmsg.msgh_id = 0; + + err = __mach_port_insert_right (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port, + thread->wakeupmsg.msgh_remote_port, + MACH_MSG_TYPE_MAKE_SEND); + if (err) + { + __mach_port_destroy (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); + return EAGAIN; + } + + return 0; +} + +/* Allocate any resouces for THREAD. The new kernel thread should not + be eligible to be scheduled. */ +int +__pthread_thread_alloc (struct __pthread *thread) +{ + if (thread->have_kernel_resources) + return 0; + + error_t err; + + err = create_wakeupmsg (thread); + if (err) + return err; + + /* If there are no pthreads in the system then the pthread library + is bootstrapping and the main thread must create initialize + itself. The thread itself is already running, it just has not + pthread context. We want to reuse what it already has (including + the kernel thread), however, we must determine which thread is + the main thread. + + We cannot test if __pthread_total is one as we later decrement + before creating the signal thread. Currently, we check if + __pthread_num_threads--the number of allocated thread + structures--is one. __pthread_alloc has already been called in + __pthread_create_internal for us. This predicate could be improved, + however, it is sufficient for now. */ + if (__pthread_num_threads == 1) + { + assert (__pthread_total == 0); + thread->kernel_thread = __mach_thread_self (); + /* We implicitly hold a reference drop the one that we just + acquired. */ + __mach_port_deallocate (__mach_task_self (), thread->kernel_thread); + } + else + { + err = __thread_create (__mach_task_self (), &thread->kernel_thread); + if (err) + return EAGAIN; + } + + thread->have_kernel_resources = 1; + + return 0; +} diff --git a/libpthread/sysdeps/mach/pt-thread-dealloc.c b/libpthread/sysdeps/mach/pt-thread-dealloc.c new file mode 100644 index 00000000..55d8c4d5 --- /dev/null +++ b/libpthread/sysdeps/mach/pt-thread-dealloc.c @@ -0,0 +1,41 @@ +/* Deallocate the kernel thread resources. Mach 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 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 <assert.h> +#include <errno.h> +#include <mach.h> + +#include <pt-internal.h> + +/* Deallocate any kernel resources associated with THREAD except don't + halt the thread itself. On return, the thread will be marked as + dead and __pthread_halt will be called. */ +void +__pthread_thread_dealloc (struct __pthread *thread) +{ + /* Why no assert? Easy. When Mach kills a task, it starts by + invalidating the task port and then terminating the threads one + by one. But while it is terminating them, they are still + eligible to be scheduled. Imagine we have two threads, one calls + exit, one calls pthread_exit. The second one may run this after + the mask port can been destroyed thus gratuitously triggering the + assert. */ + __mach_port_destroy (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); +} diff --git a/libpthread/sysdeps/mach/pt-thread-halt.c b/libpthread/sysdeps/mach/pt-thread-halt.c new file mode 100644 index 00000000..973cde1e --- /dev/null +++ b/libpthread/sysdeps/mach/pt-thread-halt.c @@ -0,0 +1,37 @@ +/* Deallocate the kernel thread resources. Mach version. + Copyright (C) 2000, 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 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 <assert.h> +#include <errno.h> +#include <mach.h> + +#include <pt-internal.h> + +/* Stop the kernel thread associated with THREAD. If NEED_DEALLOC is + true, the function must call __pthread_dealloc on THREAD. + + NB: The thread executing this function may be the thread which is + being halted, thus the last action should be halting the thread + itself. */ +void +__pthread_thread_halt (struct __pthread *thread) +{ + error_t err = __thread_terminate (thread->kernel_thread); + assert_perror (err); +} diff --git a/libpthread/sysdeps/mach/pt-thread-start.c b/libpthread/sysdeps/mach/pt-thread-start.c new file mode 100644 index 00000000..11b017ff --- /dev/null +++ b/libpthread/sysdeps/mach/pt-thread-start.c @@ -0,0 +1,49 @@ +/* Start thread. Mach version. + Copyright (C) 2000,02 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 <assert.h> +#include <errno.h> +#include <mach.h> + +#include <pt-internal.h> + +/* Start THREAD. Get the kernel thread scheduled and running. */ +int +__pthread_thread_start (struct __pthread *thread) +{ + error_t err; + + if (__pthread_num_threads == 1) + { + /* The main thread is already running: do nothing. */ + assert (__pthread_total == 1); + assert (({ mach_port_t ktid = __mach_thread_self (); + int ok = thread->kernel_thread == ktid; + __mach_port_deallocate (__mach_task_self (), + thread->kernel_thread); + ok; })); + } + else + { + err = __thread_resume (thread->kernel_thread); + assert_perror (err); + } + + return 0; +} diff --git a/libpthread/sysdeps/mach/pt-timedblock.c b/libpthread/sysdeps/mach/pt-timedblock.c new file mode 100644 index 00000000..6f547265 --- /dev/null +++ b/libpthread/sysdeps/mach/pt-timedblock.c @@ -0,0 +1,68 @@ +/* Block a thread with a timeout. Mach version. + Copyright (C) 2000, 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 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 <assert.h> +#include <errno.h> +#include <time.h> +#include <sys/time.h> + +#include <mach.h> +#include <mach/message.h> + +#include <pt-internal.h> + +/* Block THREAD. */ +error_t +__pthread_timedblock (struct __pthread *thread, + const struct timespec *abstime) +{ + error_t err; + mach_msg_header_t msg; + mach_msg_timeout_t timeout; + struct timeval now; + + /* We have an absolute time and now we have to convert it to a + relative time. Arg. */ + + err = gettimeofday(&now, NULL); + assert (! err); + + if (now.tv_sec > abstime->tv_sec + || (now.tv_sec == abstime->tv_sec + && now.tv_usec > ((abstime->tv_nsec + 999) / 1000))) + return ETIMEDOUT; + + timeout = (abstime->tv_sec - now.tv_sec) * 1000; + + if (((abstime->tv_nsec + 999) / 1000) >= now.tv_usec) + timeout += (((abstime->tv_nsec + 999) / 1000) - now.tv_usec + 999) / 1000; + else + /* Need to do a carry. */ + timeout -= (now.tv_usec + 999) / 1000 - + ((abstime->tv_nsec + 999999) / 1000000); + + err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, + sizeof msg, thread->wakeupmsg.msgh_remote_port, + timeout, MACH_PORT_NULL); + if (err == EMACH_RCV_TIMED_OUT) + return ETIMEDOUT; + + assert_perror (err); + return 0; +} diff --git a/libpthread/sysdeps/mach/pt-wakeup.c b/libpthread/sysdeps/mach/pt-wakeup.c new file mode 100644 index 00000000..4920d102 --- /dev/null +++ b/libpthread/sysdeps/mach/pt-wakeup.c @@ -0,0 +1,38 @@ +/* Wakeup a thread. Mach version. + Copyright (C) 2000, 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. */ + +#include <assert.h> +#include <errno.h> + +#include <mach.h> +#include <mach/message.h> + +#include <pt-internal.h> + +/* Wakeup THREAD. */ +void +__pthread_wakeup (struct __pthread *thread) +{ + error_t err; + + err = __mach_msg (&thread->wakeupmsg, MACH_SEND_MSG, + sizeof (thread->wakeupmsg), 0, MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + assert_perror (err); +} diff --git a/libpthread/sysdeps/posix/pt-spin.c b/libpthread/sysdeps/posix/pt-spin.c new file mode 100644 index 00000000..cb809c64 --- /dev/null +++ b/libpthread/sysdeps/posix/pt-spin.c @@ -0,0 +1,54 @@ +/* Spin locks. + Copyright (C) 2000, 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 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 <pthread.h> +#include <sched.h> + +/* The default for single processor machines; don't spin, it's + pointless. */ +#ifndef __PTHREAD_SPIN_COUNT +# define __PTHREAD_SPIN_COUNT 1 +#endif + +/* The number of times to spin while trying to lock a spin lock object + before yielding the processor. */ +int __pthread_spin_count = __PTHREAD_SPIN_COUNT; + + +/* Lock the spin lock object LOCK. If the lock is held by another + thread spin until it becomes available. */ +int +_pthread_spin_lock (__pthread_spinlock_t *lock) +{ + int i; + + while (1) + { + for (i = 0; i < __pthread_spin_count; i++) + { + if (__pthread_spin_trylock (lock) == 0) + return 0; + } + + __sched_yield (); + } +} + +weak_alias (_pthread_spin_lock, pthread_spin_lock); +weak_alias (_pthread_spin_lock, __pthread_spin_lock); diff --git a/libpthread/sysdeps/powerpc/bits/machine-lock.h b/libpthread/sysdeps/powerpc/bits/machine-lock.h new file mode 100644 index 00000000..cba6b0a6 --- /dev/null +++ b/libpthread/sysdeps/powerpc/bits/machine-lock.h @@ -0,0 +1,78 @@ +/* Machine-specific definition for spin locks. PowerPC version. + Copyright (C) 1994,97,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MACHINE_LOCK_H +#define _MACHINE_LOCK_H + +/* The type of a spin lock variable. */ + +typedef __volatile long int __spin_lock_t; + +/* Value to initialize `__spin_lock_t' variables to. */ + +#define __SPIN_LOCK_INITIALIZER 0L + + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +/* Unlock LOCK. */ + +_EXTERN_INLINE void +__spin_unlock (__spin_lock_t *__lock) +{ + long int __locked; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__locked) : "r" (__lock), "r" (0) : "cr0"); +} + +/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */ + +_EXTERN_INLINE int +__spin_try_lock (register __spin_lock_t *__lock) +{ + long int __rtn; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__rtn) : "r" (__lock), "r" (1) : "cr0"); + return !__rtn; +} + +/* Return nonzero if LOCK is locked. */ + +_EXTERN_INLINE int +__spin_lock_locked (__spin_lock_t *__lock) +{ + long int __rtn; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %0,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__rtn) : "r" (__lock) : "cr0"); + return __rtn; +} + + +#endif /* machine-lock.h */ diff --git a/libpthread/sysdeps/powerpc/bits/memory.h b/libpthread/sysdeps/powerpc/bits/memory.h new file mode 100644 index 00000000..96624c3e --- /dev/null +++ b/libpthread/sysdeps/powerpc/bits/memory.h @@ -0,0 +1,36 @@ +/* Memory barrier operations. PowerPC 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. + + The GNU C Library is distributed in the hope that 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. */ + +#ifndef _BITS_MEMORY_H +#define _BITS_MEMORY_H 1 + +/* Prevent read and write reordering across this function. */ +inline void +__memory_barrier (void) +{ + asm ("sync" ::: "memory"); +} + +/* Prevent read reordering across this function. */ +#define __memory_read_barrier __memory_barrier + +/* Prevent write reordering across this function. */ +#define __memory_write_barrier __memory_barrier + +#endif diff --git a/libpthread/sysdeps/powerpc/bits/spin-lock.h b/libpthread/sysdeps/powerpc/bits/spin-lock.h new file mode 100644 index 00000000..1dc25710 --- /dev/null +++ b/libpthread/sysdeps/powerpc/bits/spin-lock.h @@ -0,0 +1,108 @@ +/* Machine-specific definitions for spin locks. PowerPC 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. + + The GNU C Library is distributed in the hope that 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. */ + +/* + * Never include this file directly; use <pthread.h> or <cthreads.h> instead. + */ + +#ifndef _BITS_SPIN_LOCK_H +#define _BITS_SPIN_LOCK_H 1 + +#include <features.h> + +__BEGIN_DECLS + +/* The type of a spin lock object. */ +typedef __volatile int __pthread_spinlock_t; + +/* Initializer for a spin lock object. */ +# define __SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) + +#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES + +# ifndef __EBUSY +# include <errno.h> +# define __EBUSY EBUSY +# endif + +# ifndef __PT_SPIN_INLINE +# define __PT_SPIN_INLINE extern __inline +# endif + +__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_destroy (__pthread_spinlock_t *__lock) +{ + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, + int __pshared); + +__PT_SPIN_INLINE int +__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) +{ + *__lock = __SPIN_LOCK_INITIALIZER; + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_trylock (__pthread_spinlock_t *__lock) +{ + long int __rtn; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__rtn) : "r" (__lock), "r" (1) : "cr0"); + return __rtn ? __EBUSY : 0; +} + +extern inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +extern inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__lock); + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_unlock (__pthread_spinlock_t *__lock) +{ + long int __locked; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__locked) : "r" (__lock), "r" (0) : "cr0"); +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/libpthread/sysdeps/powerpc/machine-sp.h b/libpthread/sysdeps/powerpc/machine-sp.h new file mode 100644 index 00000000..aa787c59 --- /dev/null +++ b/libpthread/sysdeps/powerpc/machine-sp.h @@ -0,0 +1,31 @@ +/* Machine-specific function to return the stack pointer. i386 version. + Copyright (C) 1994,97,2001 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 _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#define __thread_stack_pointer() ({ \ + void *__sp__; \ + __asm__ ("mr %0, 1" : "=r" (__sp__)); \ + __sp__; \ +}) + +#endif /* machine-sp.h */ diff --git a/libpthread/sysdeps/powerpc/pt-machdep.h b/libpthread/sysdeps/powerpc/pt-machdep.h new file mode 100644 index 00000000..6d456367 --- /dev/null +++ b/libpthread/sysdeps/powerpc/pt-machdep.h @@ -0,0 +1,29 @@ +/* Machine dependent pthreads internal defenitions. i386 version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU 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. */ + +#ifndef _PT_MACHDEP_H +#define _PT_MACHDEP_H 1 + +struct pthread_mcontext +{ + void *pc; + void *sp; +}; + +#endif /* pt-machdep.h */ diff --git a/libpthread/tests/.cvsignore b/libpthread/tests/.cvsignore new file mode 100644 index 00000000..70845e08 --- /dev/null +++ b/libpthread/tests/.cvsignore @@ -0,0 +1 @@ +Makefile.in diff --git a/libpthread/tests/Makefile b/libpthread/tests/Makefile new file mode 100644 index 00000000..9509c957 --- /dev/null +++ b/libpthread/tests/Makefile @@ -0,0 +1,29 @@ +CFLAGS=-Wall -g + +LDLIBS = -lpthread + +CHECK_SRC := test-1.c test-2.c test-3.c test-6.c test-7.c test-8.c \ + test-9.c test-10.c test-11.c test-12.c test-13.c test-14.c \ + test-15.c test-16.c + +CHECK_OBJS := $(addsuffix .o,$(basename $(notdir $(CHECK_SRC)))) +CHECK_PROGS := $(basename $(notdir $(CHECK_SRC))) \ + $(addsuffix -static, $(basename $(CHECK_SRC))) + +%-static: %.o + $(CC) -static $(CFLAGS) $(LDFLAGS) $< -o $@ $(LDLIBS) + +check: $(CHECK_OBJS) $(CHECK_PROGS) + for i in $(CHECK_PROGS); do \ + echo -n Running $$i...\ ; \ + if ./$$i 2>&1 > $$i.out; \ + then \ + echo Success.; \ + else \ + echo Failure.; \ + fi \ + done + +clean: + rm -f $(CHECK_OBJS) $(CHECK_PROGS) \ + $(addsuffix .out,$(basename $(notdir $(CHECK_PROGS))))
\ No newline at end of file diff --git a/libpthread/tests/test-1.c b/libpthread/tests/test-1.c new file mode 100644 index 00000000..318fd6e9 --- /dev/null +++ b/libpthread/tests/test-1.c @@ -0,0 +1,49 @@ +#define _GNU_SOURCE + +#include <pthread.h> +#include <unistd.h> +#include <error.h> +#include <errno.h> +#include <stdio.h> + +#define THREADS 500 + +void * +foo (void *arg) +{ + pthread_mutex_t *mutex = arg; + pthread_mutex_lock (mutex); + pthread_mutex_unlock (mutex); + return mutex; +} + +int +main (int argc, char **argv) +{ + int i; + error_t err; + pthread_t tid[THREADS]; + pthread_mutex_t mutex[THREADS]; + + for (i = 0; i < THREADS; i ++) + { + pthread_mutex_init (&mutex[i], 0); + pthread_mutex_lock (&mutex[i]); + err = pthread_create (&tid[i], 0, foo, &mutex[i]); + if (err) + error (1, err, "pthread_create"); + sched_yield (); + } + + for (i = THREADS - 1; i >= 0; i --) + { + void *ret; + pthread_mutex_unlock (&mutex[i]); + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + assert (ret == &mutex[i]); + } + + return 0; +} diff --git a/libpthread/tests/test-10.c b/libpthread/tests/test-10.c new file mode 100644 index 00000000..bec05c14 --- /dev/null +++ b/libpthread/tests/test-10.c @@ -0,0 +1,46 @@ +/* Test error checking mutexes. */ + +#define _GNU_SOURCE + +#include <pthread.h> +#include <assert.h> +#include <error.h> +#include <errno.h> + +int +main (int argc, char **argv) +{ + error_t err; + pthread_mutexattr_t mattr; + pthread_mutex_t mutex; + + err = pthread_mutexattr_init (&mattr); + if (err) + error (1, err, "pthread_mutexattr_init"); + + err = pthread_mutexattr_settype (&mattr, PTHREAD_MUTEX_ERRORCHECK); + if (err) + error (1, err, "pthread_mutexattr_settype"); + + err = pthread_mutex_init (&mutex, &mattr); + if (err) + error (1, err, "pthread_mutex_init"); + + err = pthread_mutexattr_destroy (&mattr); + if (err) + error (1, err, "pthread_mutexattr_destroy"); + + err = pthread_mutex_lock (&mutex); + assert (err == 0); + + err = pthread_mutex_lock (&mutex); + assert (err == EDEADLK); + + err = pthread_mutex_unlock (&mutex); + assert (err == 0); + + err = pthread_mutex_unlock (&mutex); + assert (err == EPERM); + + return 0; +} diff --git a/libpthread/tests/test-11.c b/libpthread/tests/test-11.c new file mode 100644 index 00000000..de779a40 --- /dev/null +++ b/libpthread/tests/test-11.c @@ -0,0 +1,143 @@ +/* Test rwlocks. */ + +#define _GNU_SOURCE + +#include <pthread.h> +#include <assert.h> +#include <error.h> +#include <errno.h> + +#define THREADS 1 + +int a; +int b; + +/* Get a read lock and assert that a == b. */ +void * +test1 (void *arg) +{ + error_t err; + pthread_rwlock_t *lock = arg; + int i; + + for (i = 0; i < 200; i ++) + { + err = pthread_rwlock_rdlock (lock); + assert (err == 0); + + assert (a == b); + + sched_yield (); + + assert (a == b); + + err = pthread_rwlock_unlock (lock); + assert (err == 0); + } + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + pthread_rwlockattr_t attr; + pthread_rwlock_t lock; + int pshared; + + int i; + pthread_t tid[THREADS]; + void *ret; + + err = pthread_rwlockattr_init (&attr); + if (err) + error (1, err, "pthread_rwlockattr_init"); + + err = pthread_rwlockattr_getpshared (&attr, &pshared); + if (err) + error (1, err, "pthread_rwlockattr_getpshared"); + + /* Assert the default state as mandated by POSIX. */ + assert (pshared == PTHREAD_PROCESS_PRIVATE); + + err = pthread_rwlockattr_setpshared (&attr, pshared); + if (err) + error (1, err, "pthread_rwlockattr_setpshared"); + + err = pthread_rwlock_init (&lock, &attr); + if (err) + error (1, err, "pthread_rwlock_init"); + + err = pthread_rwlockattr_destroy (&attr); + if (err) + error (1, err, "pthread_rwlockattr_destroy"); + + /* Now test the lock. */ + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, test1, &lock); + if (err) + error (1, err, "pthread_create"); + } + + for (i = 0; i < 10; i ++) + { + sched_yield (); + + /* Get a write lock. */ + pthread_rwlock_wrlock (&lock); + /* Increment a and b giving other threads a chance to run in + between. */ + sched_yield (); + a ++; + sched_yield (); + b ++; + sched_yield (); + /* Unlock. */ + pthread_rwlock_unlock (&lock); + } + + for (i = 0; i < THREADS; i ++) + { + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + } + + /* Read lock it. */ + err = pthread_rwlock_tryrdlock (&lock); + assert (err == 0); + + /* Try to write lock it. It should fail with EBUSY. */ + err = pthread_rwlock_trywrlock (&lock); + assert (err == EBUSY); + + /* Drop the read lock. */ + err = pthread_rwlock_unlock (&lock); + assert (err == 0); + + /* Get a write lock. */ + err = pthread_rwlock_trywrlock (&lock); + assert (err == 0); + + /* Fail trying to acquire another write lock. */ + err = pthread_rwlock_trywrlock (&lock); + assert (err == EBUSY); + + /* Try to get a read lock which should also fail. */ + err = pthread_rwlock_tryrdlock (&lock); + assert (err == EBUSY); + + /* Unlock it. */ + err = pthread_rwlock_unlock (&lock); + assert (err == 0); + + + err = pthread_rwlock_destroy (&lock); + if (err) + error (1, err, "pthread_rwlock_destroy"); + + return 0; +} diff --git a/libpthread/tests/test-12.c b/libpthread/tests/test-12.c new file mode 100644 index 00000000..2b784908 --- /dev/null +++ b/libpthread/tests/test-12.c @@ -0,0 +1,29 @@ +/* Test concurrency level. */ + +#define _GNU_SOURCE + +#include <pthread.h> +#include <assert.h> +#include <error.h> +#include <errno.h> + +int +main (int argc, char **argv) +{ + int i; + int err; + + i = pthread_getconcurrency (); + assert (i == 0); + + err = pthread_setconcurrency (-1); + assert (err == EINVAL); + + err = pthread_setconcurrency (4); + assert (err == 0); + + i = pthread_getconcurrency (); + assert (i == 4); + + return 0; +} diff --git a/libpthread/tests/test-13.c b/libpthread/tests/test-13.c new file mode 100644 index 00000000..13b09051 --- /dev/null +++ b/libpthread/tests/test-13.c @@ -0,0 +1,66 @@ +/* Test condition attributes and pthread_cond_timedwait. */ + +#define _GNU_SOURCE + +#include <pthread.h> +#include <stdio.h> +#include <assert.h> +#include <error.h> +#include <errno.h> +#include <sys/time.h> + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_condattr_t attr; + pthread_cond_t cond; + struct timespec ts; + pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + struct timeval before, after; + int diff; + + err = pthread_condattr_init (&attr); + if (err) + error (1, err, "pthread_condattr_init"); + + err = pthread_condattr_getpshared (&attr, &i); + if (err) + error (1, err, "pthread_condattr_getpshared"); + assert (i == PTHREAD_PROCESS_PRIVATE); + + err = pthread_condattr_setpshared (&attr, PTHREAD_PROCESS_PRIVATE); + assert (err == 0); + + err = pthread_cond_init (&cond, &attr); + if (err) + error (1, err, "pthread_cond_init"); + + err = pthread_condattr_destroy (&attr); + if (err) + error (1, err, "pthread_condattr_destroy"); + + gettimeofday (&before, 0); + ts.tv_sec = before.tv_sec + 1; + ts.tv_nsec = before.tv_usec * 1000; + + printf ("Starting wait @ %d\n", (int) before.tv_sec); + + pthread_mutex_lock (&m); + err = pthread_cond_timedwait (&cond, &m, &ts); + + gettimeofday (&after, 0); + + printf ("End wait @ %d (err = %d)\n", (int) after.tv_sec, err); + + assert (err == ETIMEDOUT); + + diff = after.tv_sec * 1000000 + after.tv_usec + - before.tv_sec * 1000000 - before.tv_usec; + + if (diff < 900000 || diff > 1100000) + error (1, EGRATUITOUS, "pthread_cond_timedwait waited %d us", diff); + + return 0; +} diff --git a/libpthread/tests/test-14.c b/libpthread/tests/test-14.c new file mode 100644 index 00000000..b1dbfa66 --- /dev/null +++ b/libpthread/tests/test-14.c @@ -0,0 +1,44 @@ +/* Test pthread_mutex_timedlock. */ + +#define _GNU_SOURCE + +#include <pthread.h> +#include <stdio.h> +#include <assert.h> +#include <error.h> +#include <errno.h> +#include <sys/time.h> + +int +main (int argc, char **argv) +{ + error_t err; + struct timespec ts; + pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + struct timeval before, after; + int diff; + + gettimeofday (&before, 0); + ts.tv_sec = before.tv_sec + 1; + ts.tv_nsec = before.tv_usec * 1000; + + printf ("Starting wait @ %d\n", (int) before.tv_sec); + + pthread_mutex_lock (&m); + /* A default mutex shall dead lock if locked twice. As such we do + not need spawn a second thread. */ + err = pthread_mutex_timedlock (&m, &ts); + assert (err == ETIMEDOUT); + + gettimeofday (&after, 0); + + printf ("End wait @ %d\n", (int) after.tv_sec); + + diff = after.tv_sec * 1000000 + after.tv_usec + - before.tv_sec * 1000000 - before.tv_usec; + + if (diff < 900000 || diff > 1100000) + error (1, EGRATUITOUS, "pthread_mutex_timedlock waited %d us", diff); + + return 0; +} diff --git a/libpthread/tests/test-15.c b/libpthread/tests/test-15.c new file mode 100644 index 00000000..173f8b6b --- /dev/null +++ b/libpthread/tests/test-15.c @@ -0,0 +1,87 @@ +/* Test pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock. */ + +#define _GNU_SOURCE + +#include <pthread.h> +#include <stdio.h> +#include <assert.h> +#include <error.h> +#include <errno.h> +#include <sys/time.h> + +#define THREADS 10 + +pthread_rwlock_t rwlock; + +void * +test (void *arg) +{ + error_t err; + int foo = (int) arg; + struct timespec ts; + struct timeval before, after; + int diff; + + gettimeofday (&before, 0); + ts.tv_sec = before.tv_sec + 1; + ts.tv_nsec = before.tv_usec * 1000; + + printf ("Thread %d starting wait @ %d\n", pthread_self (), + (int) before.tv_sec); + + if (foo % 2 == 0) + err = pthread_rwlock_timedrdlock (&rwlock, &ts); + else + err = pthread_rwlock_timedwrlock (&rwlock, &ts); + + assert (err == ETIMEDOUT); + + gettimeofday (&after, 0); + + printf ("Thread %d ending wait @ %d\n", pthread_self (), + (int) after.tv_sec); + + diff = after.tv_sec * 1000000 + after.tv_usec + - before.tv_sec * 1000000 - before.tv_usec; + + if (diff < 900000 || diff > 1100000) + error (1, EGRATUITOUS, "pthread_mutex_timedlock waited %d us", diff); + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_t tid[THREADS]; + + err = pthread_rwlock_init (&rwlock, 0); + if (err) + error (1, err, "pthread_rwlock_init"); + + /* Lock it so all the threads will block. */ + err = pthread_rwlock_wrlock (&rwlock); + assert (err == 0); + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, test, (void *) i); + if (err) + error (1, err, "pthread_create"); + } + + for (i = 0; i < THREADS; i ++) + { + void *ret; + + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + } + + return 0; +} diff --git a/libpthread/tests/test-16.c b/libpthread/tests/test-16.c new file mode 100644 index 00000000..b6a52d01 --- /dev/null +++ b/libpthread/tests/test-16.c @@ -0,0 +1,71 @@ +/* Test pthread_kill.c. */ + +#define _GNU_SOURCE + +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <assert.h> +#include <error.h> +#include <errno.h> +#include <hurd/signal.h> + +pthread_t testthread; + +int i; + +void * +test (void *arg) +{ + error_t err; + + printf ("test: %d\n", pthread_self ()); + + err = pthread_kill (pthread_self (), SIGINFO); + if (err) + error (1, err, "pthread_kill"); + + /* To avoid using condition variables in a signal handler. */ + while (i == 0) + sched_yield (); + + return 0; +} + +static void +handler (int sig, siginfo_t *info, void *context) +{ + assert (pthread_equal (pthread_self (), testthread)); + printf ("handler: %d\n", pthread_self ()); + i = 1; +} + +int +main (int argc, char **argv) +{ + error_t err; + struct sigaction sa; + void *ret; + + printf ("main: %d\n", pthread_self ()); + + sa.sa_handler = handler; + sa.sa_mask = 0; + sa.sa_flags = 0; + + err = sigaction (SIGINFO, &sa, 0); + if (err) + error (1, err, "sigaction"); + + err = pthread_create (&testthread, 0, test, 0); + if (err) + error (1, err, "pthread_create"); + + err = pthread_join (testthread, &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + + return 0; +} diff --git a/libpthread/tests/test-2.c b/libpthread/tests/test-2.c new file mode 100644 index 00000000..701462e8 --- /dev/null +++ b/libpthread/tests/test-2.c @@ -0,0 +1,39 @@ +/* Test detachability. */ +#define _GNU_SOURCE + +#include <pthread.h> +#include <assert.h> +#include <error.h> +#include <errno.h> +#include <unistd.h> + +void * +thread (void *arg) +{ + while (1) + sched_yield (); +} + +int +main (int argc, char **argv) +{ + int err; + pthread_t tid; + void *ret; + + err = pthread_create (&tid, 0, thread, 0); + if (err) + error (1, err, "pthread_create"); + + err = pthread_detach (tid); + if (err) + error (1, err, "pthread_detach"); + + err = pthread_detach (tid); + assert (err == EINVAL); + + err = pthread_join (tid, &ret); + assert (err == EINVAL); + + return 0; +} diff --git a/libpthread/tests/test-3.c b/libpthread/tests/test-3.c new file mode 100644 index 00000000..7db2e43f --- /dev/null +++ b/libpthread/tests/test-3.c @@ -0,0 +1,55 @@ +/* Test the thread attribute get and set methods. */ + +#define _GNU_SOURCE + +#include <pthread.h> +#include <sched.h> +#include <assert.h> +#include <errno.h> + +int +main (int argc, char *argv[]) +{ + error_t err; + pthread_attr_t attr; + + int i; + struct sched_param sp; + void *p; + size_t sz; + + err = pthread_attr_init (&attr); + assert_perror (err); + + err = pthread_attr_destroy (&attr); + assert_perror (err); + + err = pthread_attr_init (&attr); + assert_perror (err); + +#define TEST1(foo, rv, v) \ + err = pthread_attr_get##foo (&attr, rv); \ + assert_perror (err); \ + \ + err = pthread_attr_set##foo (&attr, v); \ + assert_perror (err); + +#define TEST(foo, rv, v) TEST1(foo, rv, v) + + TEST(inheritsched, &i, i); + TEST(schedparam, &sp, &sp); + TEST(schedpolicy, &i, i); + TEST(scope, &i, i); + TEST(stackaddr, &p, p); + TEST(detachstate, &i, i); + TEST(guardsize, &sz, sz); + TEST(stacksize, &sz, sz); + + err = pthread_attr_getstack (&attr, &p, &sz); + assert_perror (err); + + err = pthread_attr_setstack (&attr, p, sz); + assert_perror (err); + + return 0; +} diff --git a/libpthread/tests/test-4.c b/libpthread/tests/test-4.c new file mode 100644 index 00000000..de9c8fe4 --- /dev/null +++ b/libpthread/tests/test-4.c @@ -0,0 +1,86 @@ +/* Test the stack guard. */ + +#define _GNU_SOURCE + +#include <pthread.h> +#include <assert.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <stdio.h> + +size_t stacksize; + +void * +thr (void *arg) +{ + int i; + char *foo; + + foo = alloca (3 * stacksize / 4); + for (i = 0; i < sizeof foo; i ++) + foo[i] = -1; + + return (void *) 1; +} + +int +main (int argc, char *argv[]) +{ + error_t err; + pid_t child; + + child = fork (); + switch (child) + { + case -1: + error (1, errno, "fork"); + break; + + case 0: + { + pthread_attr_t attr; + pthread_t tid; + void *ret; + + err = pthread_attr_init (&attr); + assert_perror (err); + + err = pthread_attr_getstacksize (&attr, &stacksize); + assert_perror (err); + + err = pthread_attr_setguardsize (&attr, stacksize / 2); + if (err == ENOTSUP) + { + printf ("Stack guard attribute not supported.\n"); + return 1; + } + assert_perror (err); + + err = pthread_create (&tid, &attr, thr, 0); + assert_perror (err); + + err = pthread_attr_destroy (&attr); + assert_perror (err); + + err = pthread_join (tid, &ret); + /* Should never be successful. */ + printf ("Thread did not segfault!?!\n"); + assert_perror (err); + return 0; + } + + default: + { + pid_t pid; + int status; + + pid = waitpid (child, &status, 0); + printf ("pid = %d; child = %d; status = %d\n", pid, child, status); + assert (pid == child); + assert (status != 0); + } + } + + return 0; +} diff --git a/libpthread/tests/test-5.c b/libpthread/tests/test-5.c new file mode 100644 index 00000000..0f5000b2 --- /dev/null +++ b/libpthread/tests/test-5.c @@ -0,0 +1,75 @@ +/* Test signals. */ + +#define _GNU_SOURCE + +#include <pthread.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <error.h> +#include <assert.h> +#include <sys/resource.h> +#include <sys/wait.h> + +void * +thr (void *arg) +{ + * (int *)0 = 0; + return 0; +} + +int foobar; + +int +main (int argc, char *argv[]) +{ + error_t err; + pid_t child; + + struct rlimit limit; + + limit.rlim_cur = 0; + limit.rlim_max = 0; + + err = setrlimit (RLIMIT_CORE, &limit); + if (err) + error (1, err, "setrlimit"); + + child = fork (); + switch (child) + { + case -1: + error (1, errno, "fork"); + break; + + case 0: + { + pthread_t tid; + void *ret; + + err = pthread_create (&tid, 0, thr, 0); + if (err) + error (1, err, "pthread_create"); + + err = pthread_join (tid, &ret); + assert_perror (err); + + /* Should have never returned. Our parent expects us to fail + thus we succeed and indicate the error. */ + return 0; + } + + default: + { + pid_t pid; + int status; + + pid = waitpid (child, &status, 0); + printf ("pid = %d; child = %d; status = %d\n", pid, child, status); + assert (pid == child); + assert (status != 0); + } + } + + return 0; +} diff --git a/libpthread/tests/test-6.c b/libpthread/tests/test-6.c new file mode 100644 index 00000000..98aa8ba7 --- /dev/null +++ b/libpthread/tests/test-6.c @@ -0,0 +1,95 @@ +#define _GNU_SOURCE + +#include <pthread.h> +#include <stdio.h> +#include <error.h> +#include <errno.h> + +#define THREADS 500 +#define WAITS 3 + +void * +dowait (void *arg) +{ + pthread_barrier_t *barrier = arg; + int ret; + + ret = pthread_barrier_wait (barrier); + printf ("%d ", pthread_self ()); + return (void *) ret; +} + +int +main (int argc, char **argv) +{ + pthread_barrierattr_t attr; + pthread_barrier_t barrier; + + int i, j; + error_t err; + pthread_t tid[THREADS]; + + int havesyncs; + + err = pthread_barrierattr_init (&attr); + if (err) + error (1, err, "pthread_barrierattr_init"); + + err = pthread_barrierattr_getpshared (&attr, &i); + if (err) + error (1, err, "pthread_barrierattr_getpshared"); + assert (i == PTHREAD_PROCESS_PRIVATE || i == PTHREAD_PROCESS_SHARED); + + err = pthread_barrierattr_setpshared (&attr, PTHREAD_PROCESS_PRIVATE); + if (err) + error (1, err, "pthread_barrierattr_setpshared"); + + err = pthread_barrier_init (&barrier, &attr, THREADS + 1); + if (err) + error (1, err, "pthread_barrier_init"); + + for (j = 0; j < WAITS; j ++) + { + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, dowait, &barrier); + if (err) + error (1, err, "pthread_create (%d)", i); + } + + printf ("Manager will now call pthread_barrier_wait.\n"); + + havesyncs + = pthread_barrier_wait (&barrier) == PTHREAD_BARRIER_SERIAL_THREAD + ? 1 : 0; + + for (i = THREADS - 1; i >= 0; i --) + { + void *ret; + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + switch ((int) ret) + { + case 0: + break; + + case PTHREAD_BARRIER_SERIAL_THREAD: + havesyncs ++; + break; + + default: + assert (! "Unknown value returned from pthread_barrier_wait."); + break; + } + } + + printf ("\n"); + + assert (havesyncs == 1); + } + + return 0; +} diff --git a/libpthread/tests/test-7.c b/libpthread/tests/test-7.c new file mode 100644 index 00000000..bd97acfa --- /dev/null +++ b/libpthread/tests/test-7.c @@ -0,0 +1,66 @@ +#define _GNU_SOURCE + +#include <pthread.h> +#include <stdio.h> +#include <error.h> +#include <errno.h> + +#define THREADS 10 +#define KEYS 400 + +pthread_key_t key[KEYS]; + +void * +thr (void *arg) +{ + error_t err; + int i; + + for (i = 0; i < KEYS; i ++) + { + printf ("pthread_getspecific(%d).\n", key[i]); + assert (pthread_getspecific (key[i]) == NULL); + printf ("pthread_setspecific(%d, %d).\n", key[i], pthread_self ()); + err = pthread_setspecific (key[i], (void *) pthread_self ()); + printf ("pthread_setspecific(%d, %d) => %d.\n", key[i], pthread_self (), err); + assert_perror (err); + } + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_t tid[THREADS]; + + void des (void *val) + { + assert ((pthread_t) val == pthread_self ()); + } + + for (i = 0; i < KEYS; i ++) + err = pthread_key_create (&key[i], des); + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, thr, 0); + if (err) + error (1, err, "pthread_create (%d)", i); + } + + for (i = 0; i < THREADS; i ++) + { + void *ret; + + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + } + + return 0; +} diff --git a/libpthread/tests/test-8.c b/libpthread/tests/test-8.c new file mode 100644 index 00000000..85a7f8f6 --- /dev/null +++ b/libpthread/tests/test-8.c @@ -0,0 +1,60 @@ +#define _GNU_SOURCE + +#include <pthread.h> +#include <assert.h> +#include <error.h> +#include <errno.h> + +#define THREADS 10 + +pthread_once_t inc_var_once = PTHREAD_ONCE_INIT; +int var; + +void +inc_var (void) +{ + var ++; +} + +void * +thr (void *arg) +{ + int i; + + for (i = 0; i < 500; i ++) + pthread_once (&inc_var_once, inc_var); + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_t tid[THREADS]; + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, thr, 0); + if (err) + error (1, err, "pthread_create (%d)", i); + } + + assert (thr (0) == 0); + + for (i = 0; i < THREADS; i ++) + { + void *ret; + + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + } + + assert (var == 1); + + return 0; +} diff --git a/libpthread/tests/test-9.c b/libpthread/tests/test-9.c new file mode 100644 index 00000000..82051570 --- /dev/null +++ b/libpthread/tests/test-9.c @@ -0,0 +1,88 @@ +/* Test recursive mutexes. */ + +#define _GNU_SOURCE + +#include <pthread.h> +#include <assert.h> +#include <error.h> +#include <errno.h> + +#define THREADS 10 + +int foo; + +void * +thr (void *arg) +{ + int i; + + pthread_mutex_lock (arg); + + foo = pthread_self (); + + for (i = 0; i < 500; i ++) + pthread_mutex_lock (arg); + for (i = 0; i < 500; i ++) + pthread_mutex_unlock (arg); + + assert (foo == pthread_self ()); + + pthread_mutex_unlock (arg); + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_t tid[THREADS]; + pthread_mutexattr_t mattr; + pthread_mutex_t mutex; + + err = pthread_mutexattr_init (&mattr); + if (err) + error (1, err, "pthread_mutexattr_init"); + + err = pthread_mutexattr_settype (&mattr, PTHREAD_MUTEX_RECURSIVE); + if (err) + error (1, err, "pthread_mutexattr_settype"); + + err = pthread_mutex_init (&mutex, &mattr); + if (err) + error (1, err, "pthread_mutex_init"); + + err = pthread_mutexattr_destroy (&mattr); + if (err) + error (1, err, "pthread_mutexattr_destroy"); + + pthread_mutex_lock (&mutex); + pthread_mutex_lock (&mutex); + pthread_mutex_unlock (&mutex); + pthread_mutex_unlock (&mutex); + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, thr, &mutex); + if (err) + error (1, err, "pthread_create (%d)", i); + } + + for (i = 0; i < THREADS; i ++) + { + void *ret; + + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + } + + err = pthread_mutex_destroy (&mutex); + if (err) + error (1, err, "pthread_mutex_destroy"); + + return 0; +} |