summaryrefslogtreecommitdiff
path: root/libpthread/linuxthreads
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2005-11-15 03:13:04 +0000
committerMike Frysinger <vapier@gentoo.org>2005-11-15 03:13:04 +0000
commita9f5aa1cc96fc2c71f19a9c3e9dcbee0e78f83ca (patch)
tree2c5d251bdfd06d0a76cec9fc507b1873b4bbbdad /libpthread/linuxthreads
parentfd6dde5a19092be5bb1990dadd5c595d2ed0b3aa (diff)
rename current stable linuxthreads to linuxthreads.old to prepare for import of latest glibc version
Diffstat (limited to 'libpthread/linuxthreads')
-rw-r--r--libpthread/linuxthreads/Changes85
-rw-r--r--libpthread/linuxthreads/FAQ.html1039
-rw-r--r--libpthread/linuxthreads/LICENSE501
-rw-r--r--libpthread/linuxthreads/Makefile15
-rw-r--r--libpthread/linuxthreads/Makefile.in62
-rw-r--r--libpthread/linuxthreads/README166
-rw-r--r--libpthread/linuxthreads/attr.c214
-rw-r--r--libpthread/linuxthreads/cancel.c184
-rw-r--r--libpthread/linuxthreads/condvar.c296
-rw-r--r--libpthread/linuxthreads/debug.h56
-rw-r--r--libpthread/linuxthreads/errno.c37
-rw-r--r--libpthread/linuxthreads/events.c37
-rw-r--r--libpthread/linuxthreads/internals.h518
-rw-r--r--libpthread/linuxthreads/join.c221
-rw-r--r--libpthread/linuxthreads/linuxthreads.texi1627
-rw-r--r--libpthread/linuxthreads/locale.c58
-rw-r--r--libpthread/linuxthreads/lockfile.c39
-rw-r--r--libpthread/linuxthreads/manager.c905
-rw-r--r--libpthread/linuxthreads/mutex.c356
-rw-r--r--libpthread/linuxthreads/oldsemaphore.c235
-rw-r--r--libpthread/linuxthreads/pt-machine.c22
-rw-r--r--libpthread/linuxthreads/ptfork.c126
-rw-r--r--libpthread/linuxthreads/pthread.c1044
-rw-r--r--libpthread/linuxthreads/pthread.c-OLDEXAMPLE121
-rw-r--r--libpthread/linuxthreads/ptlongjmp.c55
-rw-r--r--libpthread/linuxthreads/queue.h61
-rw-r--r--libpthread/linuxthreads/restart.h50
-rw-r--r--libpthread/linuxthreads/rwlock.c486
-rw-r--r--libpthread/linuxthreads/semaphore.c308
-rw-r--r--libpthread/linuxthreads/semaphore.h87
-rw-r--r--libpthread/linuxthreads/signals.c248
-rw-r--r--libpthread/linuxthreads/specific.c204
-rw-r--r--libpthread/linuxthreads/spinlock.c723
-rw-r--r--libpthread/linuxthreads/spinlock.h218
-rw-r--r--libpthread/linuxthreads/sysdeps/alpha/pt-machine.h128
-rw-r--r--libpthread/linuxthreads/sysdeps/arm/pt-machine.h70
-rw-r--r--libpthread/linuxthreads/sysdeps/bfin/pt-machine.h57
-rw-r--r--libpthread/linuxthreads/sysdeps/cris/pt-machine.h58
-rw-r--r--libpthread/linuxthreads/sysdeps/frv/pt-machine.h68
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/pt-machine.h158
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/tls.h185
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/useldt.h307
-rw-r--r--libpthread/linuxthreads/sysdeps/m68k/pt-machine.h76
-rw-r--r--libpthread/linuxthreads/sysdeps/mips/pt-machine.h110
-rw-r--r--libpthread/linuxthreads/sysdeps/nios/pt-machine.h67
-rw-r--r--libpthread/linuxthreads/sysdeps/nios2/pt-machine.h58
-rw-r--r--libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h103
-rw-r--r--libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h328
-rw-r--r--libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h66
-rw-r--r--libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h142
-rw-r--r--libpthread/linuxthreads/sysdeps/pthread/pthread.h705
-rw-r--r--libpthread/linuxthreads/sysdeps/pthread/tls.h81
-rw-r--r--libpthread/linuxthreads/sysdeps/sh/pt-machine.h81
-rw-r--r--libpthread/linuxthreads/sysdeps/sh/tls.h117
-rw-r--r--libpthread/linuxthreads/sysdeps/sh64/Makefile.arch26
-rw-r--r--libpthread/linuxthreads/sysdeps/sh64/pt-machine.c47
-rw-r--r--libpthread/linuxthreads/sysdeps/sh64/pt-machine.h36
-rw-r--r--libpthread/linuxthreads/sysdeps/sparc/pt-machine.h8
-rw-r--r--libpthread/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h83
-rw-r--r--libpthread/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h105
-rw-r--r--libpthread/linuxthreads/sysdeps/v850/pt-machine.h46
-rw-r--r--libpthread/linuxthreads/sysdeps/x86_64/pt-machine.h86
-rw-r--r--libpthread/linuxthreads/sysdeps/x86_64/tls.h134
-rw-r--r--libpthread/linuxthreads/wrapsyscall.c220
64 files changed, 0 insertions, 14160 deletions
diff --git a/libpthread/linuxthreads/Changes b/libpthread/linuxthreads/Changes
deleted file mode 100644
index b213f36c5..000000000
--- a/libpthread/linuxthreads/Changes
+++ /dev/null
@@ -1,85 +0,0 @@
-Release 0.9:
-- more ports (SH, IA-64, s390)
-- many bug fixes
-- timed sync object wait functions
-- barrier implementation
-- spinlocks implementation
-- thread register on x86
-- variable stack size and position on some platforms
-
-Release 0.8:
-(ehmm, forgot to update, don't know anymore)
-
-Release 0.7:
-- Destructors for thread-specific data now conform to the POSIX semantics
- (call destructors again if non-NULL TSD remains after a round of
- destruction).
-- Implemented thread-specific data as a sparse array, allows more TSD keys
- and smaller thread descriptors (Ulrich Drepper).
-- Added "error checking" mutexes.
-- Protect against multiple sigwait() on the same signals.
-- Simplified implementation of semaphores when compare_and_swap is
- not available.
-- Fixed bug in fork() where stdin was closed if fork() was called before
- the first pthread_create().
-- Fixed bug in the gethostby*_r functions (bad result if null bytes
- in addresses).
-- Typos in manual pages corrected.
-- First cut at a PowerPC port (not working yet, runs into problems
- with gcc and with the C library).
-
-Release 0.6:
-- Validation of thread identifiers: no more crashes when operating on
- a thread that has exited (based on Pavel Krauz's ideas).
-- Added fallback implementation of semaphores for the 386 and the
- Sparc.
-- Fixed a bug in signal handling causing false restarts of suspended
- threads.
-- Fixed a bug in realtime scheduling causing all threads to have
- default scheduling on Ix86 with libc5.
-- With realtime scheduling, unlocking a mutex now restarts the
- highest priority thread waiting on the mutex, not the
- first-suspended thread (Richard Neitzel).
-- Timing a process now returns cumulative times for all threads, not
- just times for the initial thread (suggested by Wolfram Gloger).
-- Cleaned up name space (internal defs prefixed by __, weak aliases
- for non-portable extensions).
-- MIPS port (contributed by Ralf Baechle).
-
-Release 0.5:
-- Signal-safe semaphores a la POSIX 1003.1b added.
-- Locking bug in pthread_mutex_trylock over recursive mutexes fixed.
-- Race conditions in thread cancellation fixed.
-- Sparc port (contributed by Miguel de Icaza).
-- Support for getpwnam_r and getpwuid_r.
-- Added pthread_kill_other_threads_np to be used in conjunction with
- exec*().
-
-Release 0.4:
-- Manual pages for all functions.
-- Synchronization bug causing accumulation of zombie processes fixed.
-- Race condition in pthread_cond_timedwait fixed.
-- Recursive mutexes are back by popular demand.
-- Partial support for realtime scheduling (initiated by Richard Neitzel).
-- pthread.h cleaned up a lot: now C++ compatible, added missing "const"
- qualifiers, added short documentation, put to GNU libc standards
- for name space pollution (Ulrich Drepper).
-- Motorola 68k port (contributed by Andreas Schwab).
-- Interaction with fork(2) cleaned up a lot.
-
-Release 0.3:
-- Thread creation and reclaimation now performed by a centralized
- "thread manager" thread.
-- Removed recursive mutexes to make regular mutexes more efficient.
-- Now available as a shared library (contributed by Richard Henderson).
-- Alpha port (contributed by Richard Henderson).
-- Fixed many small discrepancies with Posix 1003.1c.
-- Put under the LGPL instead of the GPL.
-
-Release 0.2:
-- Reentrant libc functions (adapted from libc 5.3.9 by Peeter Joot)
-- pthread_cond_wait did not reacquire the mutex correctly on return
-- More efficient pthread_cond_broadcast
-
-Release 0.1:
-- First public release
diff --git a/libpthread/linuxthreads/FAQ.html b/libpthread/linuxthreads/FAQ.html
deleted file mode 100644
index 21be33ec4..000000000
--- a/libpthread/linuxthreads/FAQ.html
+++ /dev/null
@@ -1,1039 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>LinuxThreads Frequently Asked Questions</TITLE>
-</HEAD>
-<BODY>
-<H1 ALIGN=center>LinuxThreads Frequently Asked Questions <BR>
- (with answers)</H1>
-<H2 ALIGN=center>[For LinuxThreads version 0.8]</H2>
-
-<HR><P>
-
-<A HREF="#A">A. The big picture</A><BR>
-<A HREF="#B">B. Getting more information</A><BR>
-<A HREF="#C">C. Issues related to the C library</A><BR>
-<A HREF="#D">D. Problems, weird behaviors, potential bugs</A><BR>
-<A HREF="#E">E. Missing functions, wrong types, etc</A><BR>
-<A HREF="#F">F. C++ issues</A><BR>
-<A HREF="#G">G. Debugging LinuxThreads programs</A><BR>
-<A HREF="#H">H. Compiling multithreaded code; errno madness</A><BR>
-<A HREF="#I">I. X-Windows and other libraries</A><BR>
-<A HREF="#J">J. Signals and threads</A><BR>
-<A HREF="#K">K. Internals of LinuxThreads</A><P>
-
-<HR>
-<P>
-
-<H2><A NAME="A">A. The big picture</A></H2>
-
-<H4><A NAME="A.1">A.1: What is LinuxThreads?</A></H4>
-
-LinuxThreads is a Linux library for multi-threaded programming.
-It implements the Posix 1003.1c API (Application Programming
-Interface) for threads. It runs on any Linux system with kernel 2.0.0
-or more recent, and a suitable C library (see section <A HREF="C">C</A>).
-<P>
-
-<H4><A NAME="A.2">A.2: What are threads?</A></H4>
-
-A thread is a sequential flow of control through a program.
-Multi-threaded programming is, thus, a form of parallel programming
-where several threads of control are executing concurrently in the
-program. All threads execute in the same memory space, and can
-therefore work concurrently on shared data.<P>
-
-Multi-threaded programming differs from Unix-style multi-processing in
-that all threads share the same memory space (and a few other system
-resources, such as file descriptors), instead of running in their own
-memory space as is the case with Unix processes.<P>
-
-Threads are useful for two reasons. First, they allow a program to
-exploit multi-processor machines: the threads can run in parallel on
-several processors, allowing a single program to divide its work
-between several processors, thus running faster than a single-threaded
-program, which runs on only one processor at a time. Second, some
-programs are best expressed as several threads of control that
-communicate together, rather than as one big monolithic sequential
-program. Examples include server programs, overlapping asynchronous
-I/O, and graphical user interfaces.<P>
-
-<H4><A NAME="A.3">A.3: What is POSIX 1003.1c?</A></H4>
-
-It's an API for multi-threaded programming standardized by IEEE as
-part of the POSIX standards. Most Unix vendors have endorsed the
-POSIX 1003.1c standard. Implementations of the 1003.1c API are
-already available under Sun Solaris 2.5, Digital Unix 4.0,
-Silicon Graphics IRIX 6, and should soon be available from other
-vendors such as IBM and HP. More generally, the 1003.1c API is
-replacing relatively quickly the proprietary threads library that were
-developed previously under Unix, such as Mach cthreads, Solaris
-threads, and IRIX sprocs. Thus, multithreaded programs using the
-1003.1c API are likely to run unchanged on a wide variety of Unix
-platforms.<P>
-
-<H4><A NAME="A.4">A.4: What is the status of LinuxThreads?</A></H4>
-
-LinuxThreads implements almost all of Posix 1003.1c, as well as a few
-extensions. The only part of LinuxThreads that does not conform yet
-to Posix is signal handling (see section <A HREF="#J">J</A>). Apart
-from the signal stuff, all the Posix 1003.1c base functionality,
-as well as a number of optional extensions, are provided and conform
-to the standard (to the best of my knowledge).
-The signal stuff is hard to get right, at least without special kernel
-support, and while I'm definitely looking at ways to implement the
-Posix behavior for signals, this might take a long time before it's
-completed.<P>
-
-<H4><A NAME="A.5">A.5: How stable is LinuxThreads?</A></H4>
-
-The basic functionality (thread creation and termination, mutexes,
-conditions, semaphores) is very stable. Several industrial-strength
-programs, such as the AOL multithreaded Web server, use LinuxThreads
-and seem quite happy about it. There used to be some rough edges in
-the LinuxThreads / C library interface with libc 5, but glibc 2
-fixes all of those problems and is now the standard C library on major
-Linux distributions (see section <A HREF="#C">C</A>). <P>
-
-<HR>
-<P>
-
-<H2><A NAME="B">B. Getting more information</A></H2>
-
-<H4><A NAME="B.1">B.1: What are good books and other sources of
-information on POSIX threads?</A></H4>
-
-The FAQ for comp.programming.threads lists several books:
-<A HREF="http://www.serpentine.com/~bos/threads-faq/">http://www.serpentine.com/~bos/threads-faq/</A>.<P>
-
-There are also some online tutorials. Follow the links from the
-LinuxThreads web page:
-<A HREF="http://pauillac.inria.fr/~xleroy/linuxthreads">http://pauillac.inria.fr/~xleroy/linuxthreads</A>.<P>
-
-<H4><A NAME="B.2">B.2: I'd like to be informed of future developments on
-LinuxThreads. Is there a mailing list for this purpose?</A></H4>
-
-I post LinuxThreads-related announcements on the newsgroup
-<A HREF="news:comp.os.linux.announce">comp.os.linux.announce</A>,
-and also on the mailing list
-<code>linux-threads@magenet.com</code>.
-You can subscribe to the latter by writing
-<A HREF="mailto:majordomo@magenet.com">majordomo@magenet.com</A>.<P>
-
-<H4><A NAME="B.3">B.3: What are good places for discussing
-LinuxThreads?</A></H4>
-
-For questions about programming with POSIX threads in general, use
-the newsgroup
-<A HREF="news:comp.programming.threads">comp.programming.threads</A>.
-Be sure you read the
-<A HREF="http://www.serpentine.com/~bos/threads-faq/">FAQ</A>
-for this group before you post.<P>
-
-For Linux-specific questions, use
-<A
-HREF="news:comp.os.linux.development.apps">comp.os.linux.development.apps</A>
-and <A
-HREF="news:comp.os.linux.development.kernel">comp.os.linux.development.kernel</A>.
-The latter is especially appropriate for questions relative to the
-interface between the kernel and LinuxThreads.<P>
-
-<H4><A NAME="B.4">B.4: How should I report a possible bug in
-LinuxThreads?</A></H4>
-
-If you're using glibc 2, the best way by far is to use the
-<code>glibcbug</code> script to mail a bug report to the glibc
-maintainers. <P>
-
-If you're using an older libc, or don't have the <code>glibcbug</code>
-script on your machine, then e-mail me directly
-(<code>Xavier.Leroy@inria.fr</code>). <P>
-
-In both cases, before sending the bug report, make sure that it is not
-addressed already in this FAQ. Also, try to send a short program that
-reproduces the weird behavior you observed. <P>
-
-<H4><A NAME="B.5">B.5: I'd like to read the POSIX 1003.1c standard. Is
-it available online?</A></H4>
-
-Unfortunately, no. POSIX standards are copyrighted by IEEE, and
-IEEE does not distribute them freely. You can buy paper copies from
-IEEE, but the price is fairly high ($120 or so). If you disagree with
-this policy and you're an IEEE member, be sure to let them know.<P>
-
-On the other hand, you probably don't want to read the standard. It's
-very hard to read, written in standard-ese, and targeted to
-implementors who already know threads inside-out. A good book on
-POSIX threads provides the same information in a much more readable form.
-I can personally recommend Dave Butenhof's book, <CITE>Programming
-with POSIX threads</CITE> (Addison-Wesley). Butenhof was part of the
-POSIX committee and also designed the Digital Unix implementations of
-POSIX threads, and it shows.<P>
-
-Another good source of information is the X/Open Group Single Unix
-specification which is available both
-<A HREF="http://www.rdg.opengroup.org/onlinepubs/7908799/index.html">on-line</A>
-and as a
-<A HREF="http://www.UNIX-systems.org/gosolo2/">book and CD/ROM</A>.
-That specification includes pretty much all the POSIX standards,
-including 1003.1c, with some extensions and clarifications.<P>
-
-<HR>
-<P>
-
-<H2><A NAME="C">C. Issues related to the C library</A></H2>
-
-<H4><A NAME="C.1">C.1: Which version of the C library should I use
-with LinuxThreads?</A></H4>
-
-The best choice by far is glibc 2, a.k.a. libc 6. It offers very good
-support for multi-threading, and LinuxThreads has been closely
-integrated with glibc 2. The glibc 2 distribution contains the
-sources of a specially adapted version of LinuxThreads.<P>
-
-glibc 2 comes preinstalled as the default C library on several Linux
-distributions, such as RedHat 5 and up, and Debian 2.
-Those distributions include the version of LinuxThreads matching
-glibc 2.<P>
-
-<H4><A NAME="C.2">C.2: My system has libc 5 preinstalled, not glibc
-2. Can I still use LinuxThreads?</H4>
-
-Yes, but you're likely to run into some problems, as libc 5 only
-offers minimal support for threads and contains some bugs that affect
-multithreaded programs. <P>
-
-The versions of libc 5 that work best with LinuxThreads are
-libc 5.2.18 on the one hand, and libc 5.4.12 or later on the other hand.
-Avoid 5.3.12 and 5.4.7: these have problems with the per-thread errno
-variable. <P>
-
-<H4><A NAME="C.3">C.3: So, should I switch to glibc 2, or stay with a
-recent libc 5?</A></H4>
-
-I'd recommend you switch to glibc 2. Even for single-threaded
-programs, glibc 2 is more solid and more standard-conformant than libc
-5. And the shortcomings of libc 5 almost preclude any serious
-multi-threaded programming.<P>
-
-Switching an already installed
-system from libc 5 to glibc 2 is not completely straightforward.
-See the <A HREF="http://sunsite.unc.edu/LDP/HOWTO/Glibc2-HOWTO.html">Glibc2
-HOWTO</A> for more information. Much easier is (re-)installing a
-Linux distribution based on glibc 2, such as RedHat 6.<P>
-
-<H4><A NAME="C.4">C.4: Where can I find glibc 2 and the version of
-LinuxThreads that goes with it?</A></H4>
-
-On <code>prep.ai.mit.edu</code> and its many, many mirrors around the world.
-See <A
-HREF="http://www.gnu.org/order/ftp.html">http://www.gnu.org/order/ftp.html</A>
-for a list of mirrors.<P>
-
-<H4><A NAME="C.5">C.5: Where can I find libc 5 and the version of
-LinuxThreads that goes with it?</A></H4>
-
-For libc 5, see <A HREF="ftp://sunsite.unc.edu/pub/Linux/devel/GCC/"><code>ftp://sunsite.unc.edu/pub/Linux/devel/GCC/</code></A>.<P>
-
-For the libc 5 version of LinuxThreads, see
-<A HREF="ftp://ftp.inria.fr/INRIA/Projects/cristal/Xavier.Leroy/linuxthreads/">ftp://ftp.inria.fr/INRIA/Projects/cristal/Xavier.Leroy/linuxthreads/</A>.<P>
-
-<H4><A NAME="C.6">C.6: How can I recompile the glibc 2 version of the
-LinuxThreads sources?</A></H4>
-
-You must transfer the whole glibc sources, then drop the LinuxThreads
-sources in the <code>linuxthreads/</code> subdirectory, then recompile
-glibc as a whole. There are now too many inter-dependencies between
-LinuxThreads and glibc 2 to allow separate re-compilation of LinuxThreads.
-<P>
-
-<H4><A NAME="C.7">C.7: What is the correspondence between LinuxThreads
-version numbers, libc version numbers, and RedHat version
-numbers?</A></H4>
-
-Here is a summary. (Information on Linux distributions other than
-RedHat are welcome.)<P>
-
-<TABLE>
-<TR><TD>LinuxThreads </TD> <TD>C library</TD> <TD>RedHat</TD></TR>
-<TR><TD>0.7, 0.71 (for libc 5)</TD> <TD>libc 5.x</TD> <TD>RH 4.2</TD></TR>
-<TR><TD>0.7, 0.71 (for glibc 2)</TD> <TD>glibc 2.0.x</TD> <TD>RH 5.x</TD></TR>
-<TR><TD>0.8</TD> <TD>glibc 2.1.1</TD> <TD>RH 6.0</TD></TR>
-<TR><TD>0.8</TD> <TD>glibc 2.1.2</TD> <TD>not yet released</TD></TR>
-</TABLE>
-<P>
-
-<HR>
-<P>
-
-<H2><A NAME="D">D. Problems, weird behaviors, potential bugs</A></H2>
-
-<H4><A NAME="D.1">D.1: When I compile LinuxThreads, I run into problems in
-file <code>libc_r/dirent.c</code></A></H4>
-
-You probably mean:
-<PRE>
- libc_r/dirent.c:94: structure has no member named `dd_lock'
-</PRE>
-I haven't actually seen this problem, but several users reported it.
-My understanding is that something is wrong in the include files of
-your Linux installation (<code>/usr/include/*</code>). Make sure
-you're using a supported version of the libc 5 library. (See question <A
-HREF="#C.2">C.2</A>).<P>
-
-<H4><A NAME="D.2">D.2: When I compile LinuxThreads, I run into problems with
-<CODE>/usr/include/sched.h</CODE>: there are several occurrences of
-<CODE>_p</CODE> that the C compiler does not understand</A></H4>
-
-Yes, <CODE>/usr/include/sched.h</CODE> that comes with libc 5.3.12 is broken.
-Replace it with the <code>sched.h</code> file contained in the
-LinuxThreads distribution. But really you should not be using libc
-5.3.12 with LinuxThreads! (See question <A HREF="#C.2">C.1</A>.)<P>
-
-<H4><A NAME="D.3">D.3: My program does <CODE>fdopen()</CODE> on a file
-descriptor opened on a pipe. When I link it with LinuxThreads,
-<CODE>fdopen()</CODE> always returns NULL!</A></H4>
-
-You're using one of the buggy versions of libc (5.3.12, 5.4.7., etc).
-See question <A HREF="#C.1">C.1</A> above.<P>
-
-<H4><A NAME="D.4">D.4: My program creates a lot of threads, and after
-a while <CODE>pthread_create()</CODE> no longer returns!</A></H4>
-
-This is known bug in the version of LinuxThreads that comes with glibc
-2.1.1. An upgrade to 2.1.2 is recommended. <P>
-
-<H4><A NAME="D.5">D.5: When I'm running a program that creates N
-threads, <code>top</code> or <code>ps</code>
-display N+2 processes that are running my program. What do all these
-processes correspond to?</A></H4>
-
-Due to the general "one process per thread" model, there's one process
-for the initial thread and N processes for the threads it created
-using <CODE>pthread_create</CODE>. That leaves one process
-unaccounted for. That extra process corresponds to the "thread
-manager" thread, a thread created internally by LinuxThreads to handle
-thread creation and thread termination. This extra thread is asleep
-most of the time.
-
-<H4><A NAME="D.6">D.6: Scheduling seems to be very unfair when there
-is strong contention on a mutex: instead of giving the mutex to each
-thread in turn, it seems that it's almost always the same thread that
-gets the mutex. Isn't this completely broken behavior?</A></H4>
-
-That behavior has mostly disappeared in recent releases of
-LinuxThreads (version 0.8 and up). It was fairly common in older
-releases, though.
-
-What happens in LinuxThreads 0.7 and before is the following: when a
-thread unlocks a mutex, all other threads that were waiting on the
-mutex are sent a signal which makes them runnable. However, the
-kernel scheduler may or may not restart them immediately. If the
-thread that unlocked the mutex tries to lock it again immediately
-afterwards, it is likely that it will succeed, because the threads
-haven't yet restarted. This results in an apparently very unfair
-behavior, when the same thread repeatedly locks and unlocks the mutex,
-while other threads can't lock the mutex.<P>
-
-In LinuxThreads 0.8 and up, <code>pthread_unlock</code> restarts only
-one waiting thread, and pre-assign the mutex to that thread. Hence,
-if the thread that unlocked the mutex tries to lock it again
-immediately, it will block until other waiting threads have had a
-chance to lock and unlock the mutex. This results in much fairer
-scheduling.<P>
-
-Notice however that even the old "unfair" behavior is perfectly
-acceptable with respect to the POSIX standard: for the default
-scheduling policy, POSIX makes no guarantees of fairness, such as "the
-thread waiting for the mutex for the longest time always acquires it
-first". Properly written multithreaded code avoids that kind of heavy
-contention on mutexes, and does not run into fairness problems. If
-you need scheduling guarantees, you should consider using the
-real-time scheduling policies <code>SCHED_RR</code> and
-<code>SCHED_FIFO</code>, which have precisely defined scheduling
-behaviors. <P>
-
-<H4><A NAME="D.7">D.7: I have a simple test program with two threads
-that do nothing but <CODE>printf()</CODE> in tight loops, and from the
-printout it seems that only one thread is running, the other doesn't
-print anything!</A></H4>
-
-Again, this behavior is characteristic of old releases of LinuxThreads
-(0.7 and before); more recent versions (0.8 and up) should not exhibit
-this behavior.<P>
-
-The reason for this behavior is explained in
-question <A HREF="#D.6">D.6</A> above: <CODE>printf()</CODE> performs
-locking on <CODE>stdout</CODE>, and thus your two threads contend very
-heavily for the mutex associated with <CODE>stdout</CODE>. But if you
-do some real work between two calls to <CODE>printf()</CODE>, you'll
-see that scheduling becomes much smoother.<P>
-
-<H4><A NAME="D.8">D.8: I've looked at <code>&lt;pthread.h&gt;</code>
-and there seems to be a gross error in the <code>pthread_cleanup_push</code>
-macro: it opens a block with <code>{</code> but does not close it!
-Surely you forgot a <code>}</code> at the end of the macro, right?
-</A></H4>
-
-Nope. That's the way it should be. The closing brace is provided by
-the <code>pthread_cleanup_pop</code> macro. The POSIX standard
-requires <code>pthread_cleanup_push</code> and
-<code>pthread_cleanup_pop</code> to be used in matching pairs, at the
-same level of brace nesting. This allows
-<code>pthread_cleanup_push</code> to open a block in order to
-stack-allocate some data structure, and
-<code>pthread_cleanup_pop</code> to close that block. It's ugly, but
-it's the standard way of implementing cleanup handlers.<P>
-
-<H4><A NAME="D.9">D.9: I tried to use real-time threads and my program
-loops like crazy and freezes the whole machine!</A></H4>
-
-Versions of LinuxThreads prior to 0.8 are susceptible to ``livelocks''
-(one thread loops, consuming 100% of the CPU time) in conjunction with
-real-time scheduling. Since real-time threads and processes have
-higher priority than normal Linux processes, all other processes on
-the machine, including the shell, the X server, etc, cannot run and
-the machine appears frozen.<P>
-
-The problem is fixed in LinuxThreads 0.8.<P>
-
-<H4><A NAME="D.10">D.10: My application needs to create thousands of
-threads, or maybe even more. Can I do this with
-LinuxThreads?</A></H4>
-
-No. You're going to run into several hard limits:
-<UL>
-<LI>Each thread, from the kernel's standpoint, is one process. Stock
-Linux kernels are limited to at most 512 processes for the super-user,
-and half this number for regular users. This can be changed by
-changing <code>NR_TASKS</code> in <code>include/linux/tasks.h</code>
-and recompiling the kernel. On the x86 processors at least,
-architectural constraints seem to limit <code>NR_TASKS</code> to 4090
-at most.
-<LI>LinuxThreads contains a table of all active threads. This table
-has room for 1024 threads at most. To increase this limit, you must
-change <code>PTHREAD_THREADS_MAX</code> in the LinuxThreads sources
-and recompile.
-<LI>By default, each thread reserves 2M of virtual memory space for
-its stack. This space is just reserved; actual memory is allocated
-for the stack on demand. But still, on a 32-bit processor, the total
-virtual memory space available for the stacks is on the order of 1G,
-meaning that more than 500 threads will have a hard time fitting in.
-You can overcome this limitation by moving to a 64-bit platform, or by
-allocating smaller stacks yourself using the <code>setstackaddr</code>
-attribute.
-<LI>Finally, the Linux kernel contains many algorithms that run in
-time proportional to the number of process table entries. Increasing
-this number drastically will slow down the kernel operations
-noticeably.
-</UL>
-(Other POSIX threads libraries have similar limitations, by the way.)
-For all those reasons, you'd better restructure your application so
-that it doesn't need more than, say, 100 threads. For instance,
-in the case of a multithreaded server, instead of creating a new
-thread for each connection, maintain a fixed-size pool of worker
-threads that pick incoming connection requests from a queue.<P>
-
-<HR>
-<P>
-
-<H2><A NAME="E">E. Missing functions, wrong types, etc</A></H2>
-
-<H4><A NAME="E.1">E.1: Where is <CODE>pthread_yield()</CODE> ? How
-comes LinuxThreads does not implement it?</A></H4>
-
-Because it's not part of the (final) POSIX 1003.1c standard.
-Several drafts of the standard contained <CODE>pthread_yield()</CODE>,
-but then the POSIX guys discovered it was redundant with
-<CODE>sched_yield()</CODE> and dropped it. So, just use
-<CODE>sched_yield()</CODE> instead.
-
-<H4><A NAME="E.2">E.2: I've found some type errors in
-<code>&lt;pthread.h&gt;</code>.
-For instance, the second argument to <CODE>pthread_create()</CODE>
-should be a <CODE>pthread_attr_t</CODE>, not a
-<CODE>pthread_attr_t *</CODE>. Also, didn't you forget to declare
-<CODE>pthread_attr_default</CODE>?</A></H4>
-
-No, I didn't. What you're describing is draft 4 of the POSIX
-standard, which is used in OSF DCE threads. LinuxThreads conforms to the
-final standard. Even though the functions have the same names as in
-draft 4 and DCE, their calling conventions are slightly different. In
-particular, attributes are passed by reference, not by value, and
-default attributes are denoted by the NULL pointer. Since draft 4/DCE
-will eventually disappear, you'd better port your program to use the
-standard interface.<P>
-
-<H4><A NAME="E.3">E.3: I'm porting an application from Solaris and I
-have to rename all thread functions from <code>thr_blah</code> to
-<CODE>pthread_blah</CODE>. This is very annoying. Why did you change
-all the function names?</A></H4>
-
-POSIX did it. The <code>thr_*</code> functions correspond to Solaris
-threads, an older thread interface that you'll find only under
-Solaris. The <CODE>pthread_*</CODE> functions correspond to POSIX
-threads, an international standard available for many, many platforms.
-Even Solaris 2.5 and later support the POSIX threads interface. So,
-do yourself a favor and rewrite your code to use POSIX threads: this
-way, it will run unchanged under Linux, Solaris, and quite a lot of
-other platforms.<P>
-
-<H4><A NAME="E.4">E.4: How can I suspend and resume a thread from
-another thread? Solaris has the <CODE>thr_suspend()</CODE> and
-<CODE>thr_resume()</CODE> functions to do that; why don't you?</A></H4>
-
-The POSIX standard provides <B>no</B> mechanism by which a thread A can
-suspend the execution of another thread B, without cooperation from B.
-The only way to implement a suspend/restart mechanism is to have B
-check periodically some global variable for a suspend request
-and then suspend itself on a condition variable, which another thread
-can signal later to restart B.<P>
-
-Notice that <CODE>thr_suspend()</CODE> is inherently dangerous and
-prone to race conditions. For one thing, there is no control on where
-the target thread stops: it can very well be stopped in the middle of
-a critical section, while holding mutexes. Also, there is no
-guarantee on when the target thread will actually stop. For these
-reasons, you'd be much better off using mutexes and conditions
-instead. The only situations that really require the ability to
-suspend a thread are debuggers and some kind of garbage collectors.<P>
-
-If you really must suspend a thread in LinuxThreads, you can send it a
-<CODE>SIGSTOP</CODE> signal with <CODE>pthread_kill</CODE>. Send
-<CODE>SIGCONT</CODE> for restarting it.
-Beware, this is specific to LinuxThreads and entirely non-portable.
-Indeed, a truly conforming POSIX threads implementation will stop all
-threads when one thread receives the <CODE>SIGSTOP</CODE> signal!
-One day, LinuxThreads will implement that behavior, and the
-non-portable hack with <CODE>SIGSTOP</CODE> won't work anymore.<P>
-
-<H4><A NAME="E.5">E.5: Does LinuxThreads implement
-<CODE>pthread_attr_setstacksize()</CODE> and
-<CODE>pthread_attr_setstackaddr()</CODE>?</A></H4>
-
-These optional functions are provided in recent versions of
-LinuxThreads (0.8 and up). Earlier releases did not provide these
-optional components of the POSIX standard.<P>
-
-Even if <CODE>pthread_attr_setstacksize()</CODE> and
-<CODE>pthread_attr_setstackaddr()</CODE> are now provided, we still
-recommend that you do not use them unless you really have strong
-reasons for doing so. The default stack allocation strategy for
-LinuxThreads is nearly optimal: stacks start small (4k) and
-automatically grow on demand to a fairly large limit (2M).
-Moreover, there is no portable way to estimate the stack requirements
-of a thread, so setting the stack size yourself makes your program
-less reliable and non-portable.<P>
-
-<H4><A NAME="E.6">E.6: LinuxThreads does not support the
-<CODE>PTHREAD_SCOPE_PROCESS</CODE> value of the "contentionscope"
-attribute. Why? </A></H4>
-
-With a "one-to-one" model, as in LinuxThreads (one kernel execution
-context per thread), there is only one scheduler for all processes and
-all threads on the system. So, there is no way to obtain the behavior of
-<CODE>PTHREAD_SCOPE_PROCESS</CODE>.
-
-<H4><A NAME="E.7">E.7: LinuxThreads does not implement process-shared
-mutexes, conditions, and semaphores. Why?</A></H4>
-
-This is another optional component of the POSIX standard. Portable
-applications should test <CODE>_POSIX_THREAD_PROCESS_SHARED</CODE>
-before using this facility.
-<P>
-The goal of this extension is to allow different processes (with
-different address spaces) to synchronize through mutexes, conditions
-or semaphores allocated in shared memory (either SVR4 shared memory
-segments or <CODE>mmap()</CODE>ed files).
-<P>
-The reason why this does not work in LinuxThreads is that mutexes,
-conditions, and semaphores are not self-contained: their waiting
-queues contain pointers to linked lists of thread descriptors, and
-these pointers are meaningful only in one address space.
-<P>
-Matt Messier and I spent a significant amount of time trying to design a
-suitable mechanism for sharing waiting queues between processes. We
-came up with several solutions that combined two of the following
-three desirable features, but none that combines all three:
-<UL>
-<LI>allow sharing between processes having different UIDs
-<LI>supports cancellation
-<LI>supports <CODE>pthread_cond_timedwait</CODE>
-</UL>
-We concluded that kernel support is required to share mutexes,
-conditions and semaphores between processes. That's one place where
-Linus Torvalds's intuition that "all we need in the kernel is
-<CODE>clone()</CODE>" fails.
-<P>
-Until suitable kernel support is available, you'd better use
-traditional interprocess communications to synchronize different
-processes: System V semaphores and message queues, or pipes, or sockets.
-<P>
-
-<HR>
-<P>
-
-<H2><A NAME="F">F. C++ issues</A></H2>
-
-<H4><A NAME="F.1">F.1: Are there C++ wrappers for LinuxThreads?</A></H4>
-
-Douglas Schmidt's ACE library contains, among a lot of other
-things, C++ wrappers for LinuxThreads and quite a number of other
-thread libraries. Check out
-<A HREF="http://www.cs.wustl.edu/~schmidt/ACE.html">http://www.cs.wustl.edu/~schmidt/ACE.html</A><P>
-
-<H4><A NAME="F.2">F.2: I'm trying to use LinuxThreads from a C++
-program, and the compiler complains about the third argument to
-<CODE>pthread_create()</CODE> !</A></H4>
-
-You're probably trying to pass a class member function or some
-other C++ thing as third argument to <CODE>pthread_create()</CODE>.
-Recall that <CODE>pthread_create()</CODE> is a C function, and it must
-be passed a C function as third argument.<P>
-
-<H4><A NAME="F.3">F.3: I'm trying to use LinuxThreads in conjunction
-with libg++, and I'm having all sorts of trouble.</A></H4>
-
->From what I understand, thread support in libg++ is completely broken,
-especially with respect to locking of iostreams. H.J.Lu wrote:
-<BLOCKQUOTE>
-If you want to use thread, I can only suggest egcs and glibc. You
-can find egcs at
-<A HREF="http://www.cygnus.com/egcs">http://www.cygnus.com/egcs</A>.
-egcs has libsdtc++, which is MT safe under glibc 2. If you really
-want to use the libg++, I have a libg++ add-on for egcs.
-</BLOCKQUOTE>
-<HR>
-<P>
-
-<H2><A NAME="G">G. Debugging LinuxThreads programs</A></H2>
-
-<H4><A NAME="G.1">G.1: Can I debug LinuxThreads program using gdb?</A></H4>
-
-Yes, but not with the stock gdb 4.17. You need a specially patched
-version of gdb 4.17 developed by Eric Paire and colleages at The Open
-Group, Grenoble. The patches against gdb 4.17 are available at
-<A HREF="http://www.gr.opengroup.org/java/jdk/linux/debug.htm"><code>http://www.gr.opengroup.org/java/jdk/linux/debug.htm</code></A>.
-Precompiled binaries of the patched gdb are available in RedHat's RPM
-format at <A
-HREF="http://odin.appliedtheory.com/"><code>http://odin.appliedtheory.com/</code></A>.<P>
-
-Some Linux distributions provide an already-patched version of gdb;
-others don't. For instance, the gdb in RedHat 5.2 is thread-aware,
-but apparently not the one in RedHat 6.0. Just ask (politely) the
-makers of your Linux distributions to please make sure that they apply
-the correct patches to gdb.<P>
-
-<H4><A NAME="G.2">G.2: Does it work with post-mortem debugging?</A></H4>
-
-Not very well. Generally, the core file does not correspond to the
-thread that crashed. The reason is that the kernel will not dump core
-for a process that shares its memory with other processes, such as the
-other threads of your program. So, the thread that crashes silently
-disappears without generating a core file. Then, all other threads of
-your program die on the same signal that killed the crashing thread.
-(This is required behavior according to the POSIX standard.) The last
-one that dies is no longer sharing its memory with anyone else, so the
-kernel generates a core file for that thread. Unfortunately, that's
-not the thread you are interested in.
-
-<H4><A NAME="G.3">G.3: Any other ways to debug multithreaded programs, then?</A></H4>
-
-Assertions and <CODE>printf()</CODE> are your best friends. Try to debug
-sequential parts in a single-threaded program first. Then, put
-<CODE>printf()</CODE> statements all over the place to get execution traces.
-Also, check invariants often with the <CODE>assert()</CODE> macro. In truth,
-there is no other effective way (save for a full formal proof of your
-program) to track down concurrency bugs. Debuggers are not really
-effective for subtle concurrency problems, because they disrupt
-program execution too much.<P>
-
-<HR>
-<P>
-
-<H2><A NAME="H">H. Compiling multithreaded code; errno madness</A></H2>
-
-<H4><A NAME="H.1">H.1: You say all multithreaded code must be compiled
-with <CODE>_REENTRANT</CODE> defined. What difference does it make?</A></H4>
-
-It affects include files in three ways:
-<UL>
-<LI> The include files define prototypes for the reentrant variants of
-some of the standard library functions,
-e.g. <CODE>gethostbyname_r()</CODE> as a reentrant equivalent to
-<CODE>gethostbyname()</CODE>.<P>
-
-<LI> If <CODE>_REENTRANT</CODE> is defined, some
-<code>&lt;stdio.h&gt;</code> functions are no longer defined as macros,
-e.g. <CODE>getc()</CODE> and <CODE>putc()</CODE>. In a multithreaded
-program, stdio functions require additional locking, which the macros
-don't perform, so we must call functions instead.<P>
-
-<LI> More importantly, <code>&lt;errno.h&gt;</code> redefines errno when
-<CODE>_REENTRANT</CODE> is
-defined, so that errno refers to the thread-specific errno location
-rather than the global errno variable. This is achieved by the
-following <code>#define</code> in <code>&lt;errno.h&gt;</code>:
-<PRE>
- #define errno (*(__errno_location()))
-</PRE>
-which causes each reference to errno to call the
-<CODE>__errno_location()</CODE> function for obtaining the location
-where error codes are stored. libc provides a default definition of
-<CODE>__errno_location()</CODE> that always returns
-<code>&errno</code> (the address of the global errno variable). Thus,
-for programs not linked with LinuxThreads, defining
-<CODE>_REENTRANT</CODE> makes no difference w.r.t. errno processing.
-But LinuxThreads redefines <CODE>__errno_location()</CODE> to return a
-location in the thread descriptor reserved for holding the current
-value of errno for the calling thread. Thus, each thread operates on
-a different errno location.
-</UL>
-<P>
-
-<H4><A NAME="H.2">H.2: Why is it so important that each thread has its
-own errno variable? </A></H4>
-
-If all threads were to store error codes in the same, global errno
-variable, then the value of errno after a system call or library
-function returns would be unpredictable: between the time a system
-call stores its error code in the global errno and your code inspects
-errno to see which error occurred, another thread might have stored
-another error code in the same errno location. <P>
-
-<H4><A NAME="H.3">H.3: What happens if I link LinuxThreads with code
-not compiled with <CODE>-D_REENTRANT</CODE>?</A></H4>
-
-Lots of trouble. If the code uses <CODE>getc()</CODE> or
-<CODE>putc()</CODE>, it will perform I/O without proper interlocking
-of the stdio buffers; this can cause lost output, duplicate output, or
-just crash other stdio functions. If the code consults errno, it will
-get back the wrong error code. The following code fragment is a
-typical example:
-<PRE>
- do {
- r = read(fd, buf, n);
- if (r == -1) {
- if (errno == EINTR) /* an error we can handle */
- continue;
- else { /* other errors are fatal */
- perror("read failed");
- exit(100);
- }
- }
- } while (...);
-</PRE>
-Assume this code is not compiled with <CODE>-D_REENTRANT</CODE>, and
-linked with LinuxThreads. At run-time, <CODE>read()</CODE> is
-interrupted. Since the C library was compiled with
-<CODE>-D_REENTRANT</CODE>, <CODE>read()</CODE> stores its error code
-in the location pointed to by <CODE>__errno_location()</CODE>, which
-is the thread-local errno variable. Then, the code above sees that
-<CODE>read()</CODE> returns -1 and looks up errno. Since
-<CODE>_REENTRANT</CODE> is not defined, the reference to errno
-accesses the global errno variable, which is most likely 0. Hence the
-code concludes that it cannot handle the error and stops.<P>
-
-<H4><A NAME="H.4">H.4: With LinuxThreads, I can no longer use the signals
-<code>SIGUSR1</code> and <code>SIGUSR2</code> in my programs! Why? </A></H4>
-
-The short answer is: because the Linux kernel you're using does not
-support realtime signals. <P>
-
-LinuxThreads needs two signals for its internal operation.
-One is used to suspend and restart threads blocked on mutex, condition
-or semaphore operations. The other is used for thread
-cancellation.<P>
-
-On ``old'' kernels (2.0 and early 2.1 kernels), there are only 32
-signals available and the kernel reserves all of them but two:
-<code>SIGUSR1</code> and <code>SIGUSR2</code>. So, LinuxThreads has
-no choice but use those two signals.<P>
-
-On recent kernels (2.2 and up), more than 32 signals are provided in
-the form of realtime signals. When run on one of those kernels,
-LinuxThreads uses two reserved realtime signals for its internal
-operation, thus leaving <code>SIGUSR1</code> and <code>SIGUSR2</code>
-free for user code. (This works only with glibc, not with libc 5.) <P>
-
-<H4><A NAME="H.5">H.5: Is the stack of one thread visible from the
-other threads? Can I pass a pointer into my stack to other threads?
-</A></H4>
-
-Yes, you can -- if you're very careful. The stacks are indeed visible
-from all threads in the system. Some non-POSIX thread libraries seem
-to map the stacks for all threads at the same virtual addresses and
-change the memory mapping when they switch from one thread to
-another. But this is not the case for LinuxThreads, as it would make
-context switching between threads more expensive, and at any rate
-might not conform to the POSIX standard.<P>
-
-So, you can take the address of an "auto" variable and pass it to
-other threads via shared data structures. However, you need to make
-absolutely sure that the function doing this will not return as long
-as other threads need to access this address. It's the usual mistake
-of returning the address of an "auto" variable, only made much worse
-because of concurrency. It's much, much safer to systematically
-heap-allocate all shared data structures. <P>
-
-<HR>
-<P>
-
-<H2><A NAME="I">I. X-Windows and other libraries</A></H2>
-
-<H4><A NAME="I.1">I.1: My program uses both Xlib and LinuxThreads.
-It stops very early with an "Xlib: unknown 0 error" message. What
-does this mean? </A></H4>
-
-That's a prime example of the errno problem described in question <A
-HREF="#H.2">H.2</A>. The binaries for Xlib you're using have not been
-compiled with <CODE>-D_REENTRANT</CODE>. It happens Xlib contains a
-piece of code very much like the one in question <A
-HREF="#H.2">H.2</A>. So, your Xlib fetches the error code from the
-wrong errno location and concludes that an error it cannot handle
-occurred.<P>
-
-<H4><A NAME="I.2">I.2: So, what can I do to build a multithreaded X
-Windows client? </A></H4>
-
-The best solution is to use X libraries that have been compiled with
-multithreading options set. Linux distributions that come with glibc
-2 as the main C library generally provide thread-safe X libraries.
-At least, that seems to be the case for RedHat 5 and later.<P>
-
-You can try to recompile yourself the X libraries with multithreading
-options set. They contain optional support for multithreading; it's
-just that the binaries provided by your Linux distribution were built
-without this support. See the file <code>README.Xfree3.3</code> in
-the LinuxThreads distribution for patches and info on how to compile
-thread-safe X libraries from the Xfree3.3 distribution. The Xfree3.3
-sources are readily available in most Linux distributions, e.g. as a
-source RPM for RedHat. Be warned, however, that X Windows is a huge
-system, and recompiling even just the libraries takes a lot of time
-and disk space.<P>
-
-Another, less involving solution is to call X functions only from the
-main thread of your program. Even if all threads have their own errno
-location, the main thread uses the global errno variable for its errno
-location. Thus, code not compiled with <code>-D_REENTRANT</code>
-still "sees" the right error values if it executes in the main thread
-only. <P>
-
-<H4><A NAME="I.2">This is a lot of work. Don't you have precompiled
-thread-safe X libraries that you could distribute?</A></H4>
-
-No, I don't. Sorry. But consider installing a Linux distribution
-that comes with thread-safe X libraries, such as RedHat 6.<P>
-
-<H4><A NAME="I.3">I.3: Can I use library FOO in a multithreaded
-program?</A></H4>
-
-Most libraries cannot be used "as is" in a multithreaded program.
-For one thing, they are not necessarily thread-safe: calling
-simultaneously two functions of the library from two threads might not
-work, due to internal use of global variables and the like. Second,
-the libraries must have been compiled with <CODE>-D_REENTRANT</CODE> to avoid
-the errno problems explained in question <A HREF="#H.2">H.2</A>.
-<P>
-
-<H4><A NAME="I.4">I.4: What if I make sure that only one thread calls
-functions in these libraries?</A></H4>
-
-This avoids problems with the library not being thread-safe. But
-you're still vulnerable to errno problems. At the very least, a
-recompile of the library with <CODE>-D_REENTRANT</CODE> is needed.
-<P>
-
-<H4><A NAME="I.5">I.5: What if I make sure that only the main thread
-calls functions in these libraries?</A></H4>
-
-That might actually work. As explained in question <A HREF="#I.1">I.1</A>,
-the main thread uses the global errno variable, and can therefore
-execute code not compiled with <CODE>-D_REENTRANT</CODE>.<P>
-
-<H4><A NAME="I.6">I.6: SVGAlib doesn't work with LinuxThreads. Why?
-</A></H4>
-
-Because both LinuxThreads and SVGAlib use the signals
-<code>SIGUSR1</code> and <code>SIGUSR2</code>. See question <A
-HREF="#H.4">H.4</A>.
-<P>
-
-
-<HR>
-<P>
-
-<H2><A NAME="J">J. Signals and threads</A></H2>
-
-<H4><A NAME="J.1">J.1: When it comes to signals, what is shared
-between threads and what isn't?</A></H4>
-
-Signal handlers are shared between all threads: when a thread calls
-<CODE>sigaction()</CODE>, it sets how the signal is handled not only
-for itself, but for all other threads in the program as well.<P>
-
-On the other hand, signal masks are per-thread: each thread chooses
-which signals it blocks independently of others. At thread creation
-time, the newly created thread inherits the signal mask of the thread
-calling <CODE>pthread_create()</CODE>. But afterwards, the new thread
-can modify its signal mask independently of its creator thread.<P>
-
-<H4><A NAME="J.2">J.2: When I send a <CODE>SIGKILL</CODE> to a
-particular thread using <CODE>pthread_kill</CODE>, all my threads are
-killed!</A></H4>
-
-That's how it should be. The POSIX standard mandates that all threads
-should terminate when the process (i.e. the collection of all threads
-running the program) receives a signal whose effect is to
-terminate the process (such as <CODE>SIGKILL</CODE> or <CODE>SIGINT</CODE>
-when no handler is installed on that signal). This behavior makes a
-lot of sense: when you type "ctrl-C" at the keyboard, or when a thread
-crashes on a division by zero or a segmentation fault, you really want
-all threads to stop immediately, not just the one that caused the
-segmentation violation or that got the <CODE>SIGINT</CODE> signal.
-(This assumes default behavior for those signals; see question
-<A HREF="#J.3">J.3</A> if you install handlers for those signals.)<P>
-
-If you're trying to terminate a thread without bringing the whole
-process down, use <code>pthread_cancel()</code>.<P>
-
-<H4><A NAME="J.3">J.3: I've installed a handler on a signal. Which
-thread executes the handler when the signal is received?</A></H4>
-
-If the signal is generated by a thread during its execution (e.g. a
-thread executes a division by zero and thus generates a
-<CODE>SIGFPE</CODE> signal), then the handler is executed by that
-thread. This also applies to signals generated by
-<CODE>raise()</CODE>.<P>
-
-If the signal is sent to a particular thread using
-<CODE>pthread_kill()</CODE>, then that thread executes the handler.<P>
-
-If the signal is sent via <CODE>kill()</CODE> or the tty interface
-(e.g. by pressing ctrl-C), then the POSIX specs say that the handler
-is executed by any thread in the process that does not currently block
-the signal. In other terms, POSIX considers that the signal is sent
-to the process (the collection of all threads) as a whole, and any
-thread that is not blocking this signal can then handle it.<P>
-
-The latter case is where LinuxThreads departs from the POSIX specs.
-In LinuxThreads, there is no real notion of ``the process as a whole'':
-in the kernel, each thread is really a distinct process with a
-distinct PID, and signals sent to the PID of a thread can only be
-handled by that thread. As long as no thread is blocking the signal,
-the behavior conforms to the standard: one (unspecified) thread of the
-program handles the signal. But if the thread to which PID the signal
-is sent blocks the signal, and some other thread does not block the
-signal, then LinuxThreads will simply queue in
-that thread and execute the handler only when that thread unblocks
-the signal, instead of executing the handler immediately in the other
-thread that does not block the signal.<P>
-
-This is to be viewed as a LinuxThreads bug, but I currently don't see
-any way to implement the POSIX behavior without kernel support.<P>
-
-<H4><A NAME="J.3">J.3: How shall I go about mixing signals and threads
-in my program? </A></H4>
-
-The less you mix them, the better. Notice that all
-<CODE>pthread_*</CODE> functions are not async-signal safe, meaning
-that you should not call them from signal handlers. This
-recommendation is not to be taken lightly: your program can deadlock
-if you call a <CODE>pthread_*</CODE> function from a signal handler!
-<P>
-
-The only sensible things you can do from a signal handler is set a
-global flag, or call <CODE>sem_post</CODE> on a semaphore, to record
-the delivery of the signal. The remainder of the program can then
-either poll the global flag, or use <CODE>sem_wait()</CODE> and
-<CODE>sem_trywait()</CODE> on the semaphore.<P>
-
-Another option is to do nothing in the signal handler, and dedicate
-one thread (preferably the initial thread) to wait synchronously for
-signals, using <CODE>sigwait()</CODE>, and send messages to the other
-threads accordingly.
-
-<H4><A NAME="J.4">J.4: When one thread is blocked in
-<CODE>sigwait()</CODE>, other threads no longer receive the signals
-<CODE>sigwait()</CODE> is waiting for! What happens? </A></H4>
-
-It's an unfortunate consequence of how LinuxThreads implements
-<CODE>sigwait()</CODE>. Basically, it installs signal handlers on all
-signals waited for, in order to record which signal was received.
-Since signal handlers are shared with the other threads, this
-temporarily deactivates any signal handlers you might have previously
-installed on these signals.<P>
-
-Though surprising, this behavior actually seems to conform to the
-POSIX standard. According to POSIX, <CODE>sigwait()</CODE> is
-guaranteed to work as expected only if all other threads in the
-program block the signals waited for (otherwise, the signals could be
-delivered to other threads than the one doing <CODE>sigwait()</CODE>,
-which would make <CODE>sigwait()</CODE> useless). In this particular
-case, the problem described in this question does not appear.<P>
-
-One day, <CODE>sigwait()</CODE> will be implemented in the kernel,
-along with others POSIX 1003.1b extensions, and <CODE>sigwait()</CODE>
-will have a more natural behavior (as well as better performances).<P>
-
-<HR>
-<P>
-
-<H2><A NAME="K">K. Internals of LinuxThreads</A></H2>
-
-<H4><A NAME="K.1">K.1: What is the implementation model for
-LinuxThreads?</A></H4>
-
-LinuxThreads follows the so-called "one-to-one" model: each thread is
-actually a separate process in the kernel. The kernel scheduler takes
-care of scheduling the threads, just like it schedules regular
-processes. The threads are created with the Linux
-<code>clone()</code> system call, which is a generalization of
-<code>fork()</code> allowing the new process to share the memory
-space, file descriptors, and signal handlers of the parent.<P>
-
-Advantages of the "one-to-one" model include:
-<UL>
-<LI> minimal overhead on CPU-intensive multiprocessing (with
-about one thread per processor);
-<LI> minimal overhead on I/O operations;
-<LI> a simple and robust implementation (the kernel scheduler does
-most of the hard work for us).
-</UL>
-The main disadvantage is more expensive context switches on mutex and
-condition operations, which must go through the kernel. This is
-mitigated by the fact that context switches in the Linux kernel are
-pretty efficient.<P>
-
-<H4><A NAME="K.2">K.2: Have you considered other implementation
-models?</A></H4>
-
-There are basically two other models. The "many-to-one" model
-relies on a user-level scheduler that context-switches between the
-threads entirely in user code; viewed from the kernel, there is only
-one process running. This model is completely out of the question for
-me, since it does not take advantage of multiprocessors, and require
-unholy magic to handle blocking I/O operations properly. There are
-several user-level thread libraries available for Linux, but I found
-all of them deficient in functionality, performance, and/or robustness.
-<P>
-
-The "many-to-many" model combines both kernel-level and user-level
-scheduling: several kernel-level threads run concurrently, each
-executing a user-level scheduler that selects between user threads.
-Most commercial Unix systems (Solaris, Digital Unix, IRIX) implement
-POSIX threads this way. This model combines the advantages of both
-the "many-to-one" and the "one-to-one" model, and is attractive
-because it avoids the worst-case behaviors of both models --
-especially on kernels where context switches are expensive, such as
-Digital Unix. Unfortunately, it is pretty complex to implement, and
-requires kernel support which Linux does not provide. Linus Torvalds
-and other Linux kernel developers have always been pushing the
-"one-to-one" model in the name of overall simplicity, and are doing a
-pretty good job of making kernel-level context switches between
-threads efficient. LinuxThreads is just following the general
-direction they set.<P>
-
-<HR>
-<ADDRESS>Xavier.Leroy@inria.fr</ADDRESS>
-</BODY>
-</HTML>
diff --git a/libpthread/linuxthreads/LICENSE b/libpthread/linuxthreads/LICENSE
deleted file mode 100644
index 7bcca6050..000000000
--- a/libpthread/linuxthreads/LICENSE
+++ /dev/null
@@ -1,501 +0,0 @@
-GNU LIBRARY GENERAL PUBLIC LICENSE
-**********************************
-
- Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
- 59 Temple Place -- Suite 330, Boston, MA 02111-1307, USA
-
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- [This is the first released version of the library GPL. It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
-Preamble
-========
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it. You can use it for
-your libraries, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it in
-new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the library, or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
- Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library. If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software. To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License, which was designed for utility
-programs. This license, the GNU Library General Public License,
-applies to certain designated libraries. This license is quite
-different from the ordinary one; be sure to read it in full, and don't
-assume that anything in it is the same as in the ordinary license.
-
- The reason we have a separate public license for some libraries is
-that they blur the distinction we usually make between modifying or
-adding to a program and simply using it. Linking a program with a
-library, without changing the library, is in some sense simply using
-the library, and is analogous to running a utility program or
-application program. However, in a textual and legal sense, the linked
-executable is a combined work, a derivative of the original library,
-and the ordinary General Public License treats it as such.
-
- Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries. We
-concluded that weaker conditions might promote sharing better.
-
- However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves. This Library General Public License is intended
-to permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them. (We have not seen how to
-achieve this as regards changes in header files, but we have achieved
-it as regards changes in the actual functions of the Library.) The
-hope is that this will lead to faster development of free libraries.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, while the latter only
-works together with the library.
-
- Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library which
- contains a notice placed by the copyright holder or other
- authorized party saying it may be distributed under the terms of
- this Library General Public License (also called "this License").
- Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
- prepared so as to be conveniently linked with application programs
- (which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
- which has been distributed under these terms. A "work based on the
- Library" means either the Library or any derivative work under
- copyright law: that is to say, a work containing the Library or a
- portion of it, either verbatim or with modifications and/or
- translated straightforwardly into another language. (Hereinafter,
- translation is included without limitation in the term
- "modification".)
-
- "Source code" for a work means the preferred form of the work for
- making modifications to it. For a library, complete source code
- means all the source code for all modules it contains, plus any
- associated interface definition files, plus the scripts used to
- control compilation and installation of the library.
-
- Activities other than copying, distribution and modification are
- not covered by this License; they are outside its scope. The act
- of running a program using the Library is not restricted, and
- output from such a program is covered only if its contents
- constitute a work based on the Library (independent of the use of
- the Library in a tool for writing it). Whether that is true
- depends on what the Library does and what the program that uses
- the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
- complete source code as you receive it, in any medium, provided
- that you conspicuously and appropriately publish on each copy an
- appropriate copyright notice and disclaimer of warranty; keep
- intact all the notices that refer to this License and to the
- absence of any warranty; and distribute a copy of this License
- along with the Library.
-
- You may charge a fee for the physical act of transferring a copy,
- and you may at your option offer warranty protection in exchange
- for a fee.
-
- 2. You may modify your copy or copies of the Library or any portion
- of it, thus forming a work based on the Library, and copy and
- distribute such modifications or work under the terms of Section 1
- above, provided that you also meet all of these conditions:
-
- a. The modified work must itself be a software library.
-
- b. You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c. You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d. If a facility in the modified Library refers to a function or
- a table of data to be supplied by an application program that
- uses the facility, other than as an argument passed when the
- facility is invoked, then you must make a good faith effort
- to ensure that, in the event an application does not supply
- such function or table, the facility still operates, and
- performs whatever part of its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots
- has a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function
- must be optional: if the application does not supply it, the
- square root function must still compute square roots.)
-
- These requirements apply to the modified work as a whole. If
- identifiable sections of that work are not derived from the
- Library, and can be reasonably considered independent and separate
- works in themselves, then this License, and its terms, do not
- apply to those sections when you distribute them as separate
- works. But when you distribute the same sections as part of a
- whole which is a work based on the Library, the distribution of
- the whole must be on the terms of this License, whose permissions
- for other licensees extend to the entire whole, and thus to each
- and every part regardless of who wrote it.
-
- Thus, it is not the intent of this section to claim rights or
- contest your rights to work written entirely by you; rather, the
- intent is to exercise the right to control the distribution of
- derivative or collective works based on the Library.
-
- In addition, mere aggregation of another work not based on the
- Library with the Library (or with a work based on the Library) on
- a volume of a storage or distribution medium does not bring the
- other work under the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
- License instead of this License to a given copy of the Library.
- To do this, you must alter all the notices that refer to this
- License, so that they refer to the ordinary GNU General Public
- License, version 2, instead of to this License. (If a newer
- version than version 2 of the ordinary GNU General Public License
- has appeared, then you can specify that version instead if you
- wish.) Do not make any other change in these notices.
-
- Once this change is made in a given copy, it is irreversible for
- that copy, so the ordinary GNU General Public License applies to
- all subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
- the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
- derivative of it, under Section 2) in object code or executable
- form under the terms of Sections 1 and 2 above provided that you
- accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software
- interchange.
-
- If distribution of object code is made by offering access to copy
- from a designated place, then offering equivalent access to copy
- the source code from the same place satisfies the requirement to
- distribute the source code, even though third parties are not
- compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
- Library, but is designed to work with the Library by being
- compiled or linked with it, is called a "work that uses the
- Library". Such a work, in isolation, is not a derivative work of
- the Library, and therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
- creates an executable that is a derivative of the Library (because
- it contains portions of the Library), rather than a "work that
- uses the library". The executable is therefore covered by this
- License. Section 6 states terms for distribution of such
- executables.
-
- When a "work that uses the Library" uses material from a header
- file that is part of the Library, the object code for the work may
- be a derivative work of the Library even though the source code is
- not. Whether this is true is especially significant if the work
- can be linked without the Library, or if the work is itself a
- library. The threshold for this to be true is not precisely
- defined by law.
-
- If such an object file uses only numerical parameters, data
- structure layouts and accessors, and small macros and small inline
- functions (ten lines or less in length), then the use of the object
- file is unrestricted, regardless of whether it is legally a
- derivative work. (Executables containing this object code plus
- portions of the Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
- distribute the object code for the work under the terms of Section
- 6. Any executables containing that work also fall under Section 6,
- whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also compile or
- link a "work that uses the Library" with the Library to produce a
- work containing portions of the Library, and distribute that work
- under terms of your choice, provided that the terms permit
- modification of the work for the customer's own use and reverse
- engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
- Library is used in it and that the Library and its use are covered
- by this License. You must supply a copy of this License. If the
- work during execution displays copyright notices, you must include
- the copyright notice for the Library among them, as well as a
- reference directing the user to the copy of this License. Also,
- you must do one of these things:
-
- a. Accompany the work with the complete corresponding
- machine-readable source code for the Library including
- whatever changes were used in the work (which must be
- distributed under Sections 1 and 2 above); and, if the work
- is an executable linked with the Library, with the complete
- machine-readable "work that uses the Library", as object code
- and/or source code, so that the user can modify the Library
- and then relink to produce a modified executable containing
- the modified Library. (It is understood that the user who
- changes the contents of definitions files in the Library will
- not necessarily be able to recompile the application to use
- the modified definitions.)
-
- b. Accompany the work with a written offer, valid for at least
- three years, to give the same user the materials specified in
- Subsection 6a, above, for a charge no more than the cost of
- performing this distribution.
-
- c. If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the
- above specified materials from the same place.
-
- d. Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
- Library" must include any data and utility programs needed for
- reproducing the executable from it. However, as a special
- exception, the source code distributed need not include anything
- that is normally distributed (in either source or binary form)
- with the major components (compiler, kernel, and so on) of the
- operating system on which the executable runs, unless that
- component itself accompanies the executable.
-
- It may happen that this requirement contradicts the license
- restrictions of other proprietary libraries that do not normally
- accompany the operating system. Such a contradiction means you
- cannot use both them and the Library together in an executable
- that you distribute.
-
- 7. You may place library facilities that are a work based on the
- Library side-by-side in a single library together with other
- library facilities not covered by this License, and distribute
- such a combined library, provided that the separate distribution
- of the work based on the Library and of the other library
- facilities is otherwise permitted, and provided that you do these
- two things:
-
- a. Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b. Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same
- work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute the
- Library except as expressly provided under this License. Any
- attempt otherwise to copy, modify, sublicense, link with, or
- distribute the Library is void, and will automatically terminate
- your rights under this License. However, parties who have
- received copies, or rights, from you under this License will not
- have their licenses terminated so long as such parties remain in
- full compliance.
-
- 9. You are not required to accept this License, since you have not
- signed it. However, nothing else grants you permission to modify
- or distribute the Library or its derivative works. These actions
- are prohibited by law if you do not accept this License.
- Therefore, by modifying or distributing the Library (or any work
- based on the Library), you indicate your acceptance of this
- License to do so, and all its terms and conditions for copying,
- distributing or modifying the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
- Library), the recipient automatically receives a license from the
- original licensor to copy, distribute, link with or modify the
- Library subject to these terms and conditions. You may not impose
- any further restrictions on the recipients' exercise of the rights
- granted herein. You are not responsible for enforcing compliance
- by third parties to this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
- infringement or for any other reason (not limited to patent
- issues), conditions are imposed on you (whether by court order,
- agreement or otherwise) that contradict the conditions of this
- License, they do not excuse you from the conditions of this
- License. If you cannot distribute so as to satisfy simultaneously
- your obligations under this License and any other pertinent
- obligations, then as a consequence you may not distribute the
- Library at all. For example, if a patent license would not permit
- royalty-free redistribution of the Library by all those who
- receive copies directly or indirectly through you, then the only
- way you could satisfy both it and this License would be to refrain
- entirely from distribution of the Library.
-
- If any portion of this section is held invalid or unenforceable
- under any particular circumstance, the balance of the section is
- intended to apply, and the section as a whole is intended to apply
- in other circumstances.
-
- It is not the purpose of this section to induce you to infringe any
- patents or other property right claims or to contest validity of
- any such claims; this section has the sole purpose of protecting
- the integrity of the free software distribution system which is
- implemented by public license practices. Many people have made
- generous contributions to the wide range of software distributed
- through that system in reliance on consistent application of that
- system; it is up to the author/donor to decide if he or she is
- willing to distribute software through any other system and a
- licensee cannot impose that choice.
-
- This section is intended to make thoroughly clear what is believed
- to be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
- certain countries either by patents or by copyrighted interfaces,
- the original copyright holder who places the Library under this
- License may add an explicit geographical distribution limitation
- excluding those countries, so that distribution is permitted only
- in or among countries not thus excluded. In such case, this
- License incorporates the limitation as if written in the body of
- this License.
-
- 13. The Free Software Foundation may publish revised and/or new
- versions of the Library General Public License from time to time.
- Such new versions will be similar in spirit to the present version,
- but may differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
- Library specifies a version number of this License which applies
- to it and "any later version", you have the option of following
- the terms and conditions either of that version or of any later
- version published by the Free Software Foundation. If the Library
- does not specify a license version number, you may choose any
- version ever published by the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
- programs whose distribution conditions are incompatible with these,
- write to the author to ask for permission. For software which is
- copyrighted by the Free Software Foundation, write to the Free
- Software Foundation; we sometimes make exceptions for this. Our
- decision will be guided by the two goals of preserving the free
- status of all derivatives of our free software and of promoting
- the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
- WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE
- LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
- HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT
- WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT
- NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
- QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE
- LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
- SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
- WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY
- MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
- LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
- INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
- INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF
- DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
- OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY
- OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
-How to Apply These Terms to Your New Libraries
-==============================================
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of
-the ordinary General Public License).
-
- To apply these terms, attach the following notices to the library.
-It is safest to attach them to the start of each source file to most
-effectively convey the exclusion of warranty; and each file should have
-at least the "copyright" line and a pointer to where the full notice is
-found.
-
- ONE LINE TO GIVE THE LIBRARY'S NAME AND AN IDEA OF WHAT IT DOES.
- Copyright (C) YEAR NAME OF AUTHOR
-
- This 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.
-
- This library is distributed in the hope that 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 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.
-
- Also add information on how to contact you by electronic and paper
-mail.
-
- You should also get your employer (if you work as a programmer) or
-your school, if any, to sign a "copyright disclaimer" for the library,
-if necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the library
- `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- SIGNATURE OF TY COON, 1 April 1990
- Ty Coon, President of Vice
-
- That's all there is to it!
-
diff --git a/libpthread/linuxthreads/Makefile b/libpthread/linuxthreads/Makefile
deleted file mode 100644
index f92f205a5..000000000
--- a/libpthread/linuxthreads/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# Makefile for uClibc
-#
-# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
-#
-# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
-#
-
-TOPDIR=../../
-
-top_srcdir=$(TOPDIR)
-top_builddir=../../
-include $(top_builddir)Rules.mak
-all: libs
-include Makefile.in
-include $(top_srcdir)Makerules
diff --git a/libpthread/linuxthreads/Makefile.in b/libpthread/linuxthreads/Makefile.in
deleted file mode 100644
index 4804a73c2..000000000
--- a/libpthread/linuxthreads/Makefile.in
+++ /dev/null
@@ -1,62 +0,0 @@
-# Makefile for uClibc
-#
-# Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
-# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
-#
-# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
-#
-
-CFLAGS+=$(SSP_ALL_CFLAGS)
-
-# This stuff will not compile without at least -O1
-CFLAGS:=$(CFLAGS:-O0=-O1)
-
-LDFLAGS:=$(LDFLAGS_NOSTRIP)
-
-ifeq ($(UCLIBC_CTOR_DTOR),y)
-SHARED_START_FILES:=$(top_builddir)lib/crti.o $(LIBGCC_DIR)crtbeginS.o
-SHARED_END_FILES:=$(LIBGCC_DIR)crtendS.o $(top_builddir)lib/crtn.o
-endif
-
-ifeq ($(PTHREADS_DEBUG_SUPPORT),y)
-STRIP_FLAGS:=-X --strip-debug -R .note -R .comment
-endif
-
-DOMULTI=n
-
-LIB_NAME:=libpthread
-
-libpthread_DIR:=$(top_srcdir)libpthread/linuxthreads
-libpthread_OUT:=$(top_builddir)libpthread/linuxthreads
-
-ARCH_CFLAGS:=$(CFLAGS)
--include $(libpthread_DIR)/sysdeps/$(TARGET_ARCH)/Makefile.arch
-CFLAGS:=$(ARCH_CFLAGS)
-
-libpthread_SRC:=$(wildcard $(libpthread_DIR)/*.c)
-ifneq ($(UCLIBC_HAS_XLOCALE),y)
-libpthread_SRC:=$(filter-out $(libpthread_DIR)/locale.c,$(libpthread_SRC))
-endif
-
-ifneq ($(DOMULTI),n)
-libpthread_NO_MULTI:=manager.c pt-machine.c
-libpthread_SRC:=$(filter-out $(patsubst %.c,$(libpthread_DIR)/%.c,$(libpthread_NO_MULTI)),$(libpthread_SRC))
-endif
-
-# remove generic sources, if arch specific version is present
-ifneq ($(strip $(libpthread_ARCH_SRC)),)
-libpthread_SRC:=$(filter-out $(patsubst %.c,$(libpthread_DIR)/%.c,$(notdir $(libpthread_ARCH_SRC))),$(libpthread_SRC))
-endif
-
-libpthread_OBJ:=$(patsubst $(libpthread_DIR)/%.c,$(libpthread_OUT)/%.o,$(libpthread_SRC))
-
-libpthread-a-$(UCLIBC_HAS_THREADS)+=$(libpthread_OBJ)
-libpthread-so-$(UCLIBC_HAS_THREADS)+=$(libpthread_OBJ:.o=.os)
-
-libpthread-multi-$(UCLIBC_HAS_THREADS)+=$(libpthread_SRC)
-libpthread-nomulti-$(UCLIBC_HAS_THREADS)+=$(patsubst %.c,$(libpthread_OUT)/%.o,$(libpthread_NO_MULTI))
-
-objclean-y+=libpthread_clean
-
-lib-a-$(UCLIBC_HAS_THREADS)+=$(top_builddir)lib/libpthread.a
-lib-so-$(UCLIBC_HAS_THREADS)+=$(top_builddir)lib/libpthread.so
diff --git a/libpthread/linuxthreads/README b/libpthread/linuxthreads/README
deleted file mode 100644
index 955bd59e7..000000000
--- a/libpthread/linuxthreads/README
+++ /dev/null
@@ -1,166 +0,0 @@
- Linuxthreads - POSIX 1003.1c kernel threads for Linux
-
- Copyright 1996, 1997 Xavier Leroy (Xavier.Leroy@inria.fr)
-
-
-DESCRIPTION:
-
-This is release 0.7 (late beta) of LinuxThreads, a BiCapitalized
-implementation of the Posix 1003.1c "pthread" interface for Linux.
-
-LinuxThreads provides kernel-level threads: each thread is a separate
-Unix process, sharing its address space with the other threads through
-the new system call clone(). Scheduling between threads is handled by
-the kernel scheduler, just like scheduling between Unix processes.
-
-
-REQUIREMENTS:
-
-- Linux version 2.0 and up (requires the new clone() system call
- and the new realtime scheduler).
-
-- For Intel platforms: libc 5.2.18 or later is required.
- 5.2.18 or 5.4.12 or later are recommended;
- 5.3.12 and 5.4.7 have problems (see the FAQ.html file for more info).
-
-- Also supports glibc 2 (a.k.a. libc 6), which actually comes with
- a specially-adapted version of this library.
-
-- Currently supports Intel, Alpha, Sparc, Motorola 68k, ARM and MIPS
- platforms.
-
-- Multiprocessors are supported.
-
-
-INSTALLATION:
-
-- Edit the Makefile, set the variables in the "Configuration" section.
-
-- Do "make".
-
-- Do "make install".
-
-
-USING LINUXTHREADS:
-
- gcc -D_REENTRANT ... -lpthread
-
-A complete set of manual pages is included. Also see the subdirectory
-Examples/ for some sample programs.
-
-
-STATUS:
-
-- All functions in the Posix 1003.1c base interface implemented.
- Also supports priority scheduling.
-
-- For users of libc 5 (H.J.Lu's libc), a number of C library functions
- are reimplemented or wrapped to make them thread-safe, including:
- * malloc functions
- * stdio functions (define _REENTRANT before including <stdio.h>)
- * per-thread errno variable (define _REENTRANT before including <errno.h>)
- * directory reading functions (opendir(), etc)
- * sleep()
- * gmtime(), localtime()
-
- New library functions provided:
- * flockfile(), funlockfile(), ftrylockfile()
- * reentrant versions of network database functions (gethostbyname_r(), etc)
- and password functions (getpwnam_r(), etc).
-
-- libc 6 (glibc 2) provides much better thread support than libc 5,
- and comes with a specially-adapted version of LinuxThreads.
- For serious multithreaded programming, you should consider switching
- to glibc 2. It is available from ftp.gnu.org:/pub/gnu and its mirrors.
-
-
-WARNING:
-
-Many existing libraries are not compatible with LinuxThreads,
-either because they are not inherently thread-safe, or because they
-have not been compiled with the -D_REENTRANT. For more info, see the
-FAQ.html file in this directory.
-
-A prime example of the latter is Xlib. If you link it with
-LinuxThreads, you'll probably get an "unknown 0 error" very
-early. This is just a consequence of the Xlib binaries using the
-global variable "errno" to fetch error codes, while LinuxThreads and
-the C library use the per-thread "errno" location.
-
-See the file README.Xfree3.3 for info on how to compile the Xfree 3.3
-libraries to make them compatible with LinuxThreads.
-
-
-KNOWN BUGS AND LIMITATIONS:
-
-- Threads share pretty much everything they should share according
- to the standard: memory space, file descriptors, signal handlers,
- current working directory, etc. One thing that they do not share
- is their pid's and parent pid's. According to the standard, they
- should have the same, but that's one thing we cannot achieve
- in this implementation (until the CLONE_PID flag to clone() becomes
- usable).
-
-- The current implementation uses the two signals SIGUSR1 and SIGUSR2,
- so user-level code cannot employ them. Ideally, there should be two
- signals reserved for this library. One signal is used for restarting
- threads blocked on mutexes or conditions; the other is for thread
- cancellation.
-
- *** This is not anymore true when the application runs on a kernel
- newer than approximately 2.1.60.
-
-- The stacks for the threads are allocated high in the memory space,
- below the stack of the initial process, and spaced 2M apart.
- Stacks are allocated with the "grow on demand" flag, so they don't
- use much virtual space initially (4k, currently), but can grow
- up to 2M if needed.
-
- Reserving such a large address space for each thread means that,
- on a 32-bit architecture, no more than about 1000 threads can
- coexist (assuming a 2Gb address space for user processes),
- but this is reasonable, since each thread uses up one entry in the
- kernel's process table, which is usually limited to 512 processes.
-
- Another potential problem of the "grow on demand" scheme is that
- nothing prevents the user from mmap'ing something in the 2M address
- window reserved for a thread stack, possibly causing later extensions of
- that stack to fail. Mapping at fixed addresses should be avoided
- when using this library.
-
-- Signal handling does not fully conform to the Posix standard,
- due to the fact that threads are here distinct processes that can be
- sent signals individually, so there's no notion of sending a signal
- to "the" process (the collection of all threads).
- More precisely, here is a summary of the standard requirements
- and how they are met by the implementation:
-
- 1- Synchronous signals (generated by the thread execution, e.g. SIGFPE)
- are delivered to the thread that raised them.
- (OK.)
-
- 2- A fatal asynchronous signal terminates all threads in the process.
- (OK. The thread manager notices when a thread dies on a signal
- and kills all other threads with the same signal.)
-
- 3- An asynchronous signal will be delivered to one of the threads
- of the program which does not block the signal (it is unspecified
- which).
- (No, the signal is delivered to the thread it's been sent to,
- based on the pid of the thread. If that thread is currently
- blocking the signal, the signal remains pending.)
-
- 4- The signal will be delivered to at most one thread.
- (OK, except for signals generated from the terminal or sent to
- the process group, which will be delivered to all threads.)
-
-- The current implementation of the MIPS support assumes a MIPS ISA II
- processor or better. These processors support atomic operations by
- ll/sc instructions. Older R2000/R3000 series processors are not
- supported yet; support for these will have higher overhead.
-
-- The current implementation of the ARM support assumes that the SWP
- (atomic swap register with memory) instruction is available. This is
- the case for all processors except for the ARM1 and ARM2. On StrongARM,
- the SWP instruction does not bypass the cache, so multi-processor support
- will be more troublesome.
diff --git a/libpthread/linuxthreads/attr.c b/libpthread/linuxthreads/attr.c
deleted file mode 100644
index 4432a04d1..000000000
--- a/libpthread/linuxthreads/attr.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* changed for uClibc */
-#define __sched_get_priority_min sched_get_priority_min
-#define __sched_get_priority_max sched_get_priority_max
-
-/* Handling of thread attributes */
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include "pthread.h"
-#include "internals.h"
-
-extern int __getpagesize(void);
-
-/* NOTE: With uClibc I don't think we need this versioning stuff.
- * Therefore, define the function pthread_attr_init() here using
- * a strong symbol. */
-
-//int __pthread_attr_init_2_1(pthread_attr_t *attr)
-int pthread_attr_init(pthread_attr_t *attr)
-{
- size_t ps = __getpagesize ();
-
- attr->__detachstate = PTHREAD_CREATE_JOINABLE;
- attr->__schedpolicy = SCHED_OTHER;
- attr->__schedparam.sched_priority = 0;
- attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
- attr->__scope = PTHREAD_SCOPE_SYSTEM;
- attr->__guardsize = ps;
- attr->__stackaddr = NULL;
- attr->__stackaddr_set = 0;
- attr->__stacksize = STACK_SIZE - ps;
- return 0;
-}
-
-/* uClibc: leave out this for now. */
-#if DO_PTHREAD_VERSIONING_WITH_UCLIBC
-#if defined __HAVE_ELF__ && defined __PIC__ && defined DO_VERSIONING
-default_symbol_version (__pthread_attr_init_2_1, pthread_attr_init, GLIBC_2.1);
-
-int __pthread_attr_init_2_0(pthread_attr_t *attr)
-{
- attr->__detachstate = PTHREAD_CREATE_JOINABLE;
- attr->__schedpolicy = SCHED_OTHER;
- attr->__schedparam.sched_priority = 0;
- attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
- attr->__scope = PTHREAD_SCOPE_SYSTEM;
- return 0;
-}
-symbol_version (__pthread_attr_init_2_0, pthread_attr_init, GLIBC_2.0);
-#else
-strong_alias (__pthread_attr_init_2_1, pthread_attr_init)
-#endif
-#endif /* DO_PTHREAD_VERSIONING_WITH_UCLIBC */
-
-int pthread_attr_destroy(pthread_attr_t *attr)
-{
- return 0;
-}
-
-int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
-{
- if (detachstate < PTHREAD_CREATE_JOINABLE ||
- detachstate > PTHREAD_CREATE_DETACHED)
- return EINVAL;
- attr->__detachstate = detachstate;
- return 0;
-}
-
-int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
-{
- *detachstate = attr->__detachstate;
- return 0;
-}
-
-int pthread_attr_setschedparam(pthread_attr_t *attr,
- const struct sched_param *param)
-{
- int max_prio = __sched_get_priority_max(attr->__schedpolicy);
- int min_prio = __sched_get_priority_min(attr->__schedpolicy);
-
- if (param->sched_priority < min_prio || param->sched_priority > max_prio)
- return EINVAL;
- memcpy (&attr->__schedparam, param, sizeof (struct sched_param));
- return 0;
-}
-
-int pthread_attr_getschedparam(const pthread_attr_t *attr,
- struct sched_param *param)
-{
- memcpy (param, &attr->__schedparam, sizeof (struct sched_param));
- return 0;
-}
-
-int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
-{
- if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
- return EINVAL;
- attr->__schedpolicy = policy;
- return 0;
-}
-
-int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
-{
- *policy = attr->__schedpolicy;
- return 0;
-}
-
-int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
-{
- if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED)
- return EINVAL;
- attr->__inheritsched = inherit;
- return 0;
-}
-
-int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
-{
- *inherit = attr->__inheritsched;
- return 0;
-}
-
-int pthread_attr_setscope(pthread_attr_t *attr, int scope)
-{
- switch (scope) {
- case PTHREAD_SCOPE_SYSTEM:
- attr->__scope = scope;
- return 0;
- case PTHREAD_SCOPE_PROCESS:
- return ENOTSUP;
- default:
- return EINVAL;
- }
-}
-
-int pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
-{
- *scope = attr->__scope;
- return 0;
-}
-
-int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
-{
- size_t ps = __getpagesize ();
-
- /* First round up the guard size. */
- guardsize = roundup (guardsize, ps);
-
- /* The guard size must not be larger than the stack itself */
- if (guardsize >= attr->__stacksize) return EINVAL;
-
- attr->__guardsize = guardsize;
-
- return 0;
-}
-weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize)
-
-int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
-{
- *guardsize = attr->__guardsize;
- return 0;
-}
-weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize)
-
-int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
-{
- attr->__stackaddr = stackaddr;
- attr->__stackaddr_set = 1;
- return 0;
-}
-weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
-
-int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
-{
- /* XXX This function has a stupid definition. The standard specifies
- no error value but what is if no stack address was set? We simply
- return the value we have in the member. */
- *stackaddr = attr->__stackaddr;
- return 0;
-}
-weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr)
-
-int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
-{
- /* We don't accept value smaller than PTHREAD_STACK_MIN. */
- if (stacksize < PTHREAD_STACK_MIN)
- return EINVAL;
-
- attr->__stacksize = stacksize;
- return 0;
-}
-weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
-
-int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
-{
- *stacksize = attr->__stacksize;
- return 0;
-}
-weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
diff --git a/libpthread/linuxthreads/cancel.c b/libpthread/linuxthreads/cancel.c
deleted file mode 100644
index 1356348a7..000000000
--- a/libpthread/linuxthreads/cancel.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Thread cancellation */
-
-#define __FORCE_GLIBC
-#include <features.h>
-#include <errno.h>
-#include "pthread.h"
-#include "internals.h"
-#include "spinlock.h"
-#include "restart.h"
-#ifdef __UCLIBC_HAS_RPC__
-#include <rpc/rpc.h>
-extern void __rpc_thread_destroy(void);
-#endif
-
-
-int pthread_setcancelstate(int state, int * oldstate)
-{
- pthread_descr self = thread_self();
- if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE)
- return EINVAL;
- if (oldstate != NULL) *oldstate = THREAD_GETMEM(self, p_cancelstate);
- THREAD_SETMEM(self, p_cancelstate, state);
- if (THREAD_GETMEM(self, p_canceled) &&
- THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE &&
- THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
- pthread_exit(PTHREAD_CANCELED);
- return 0;
-}
-
-int pthread_setcanceltype(int type, int * oldtype)
-{
- pthread_descr self = thread_self();
- if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS)
- return EINVAL;
- if (oldtype != NULL) *oldtype = THREAD_GETMEM(self, p_canceltype);
- THREAD_SETMEM(self, p_canceltype, type);
- if (THREAD_GETMEM(self, p_canceled) &&
- THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE &&
- THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
- pthread_exit(PTHREAD_CANCELED);
- return 0;
-}
-
-int pthread_cancel(pthread_t thread)
-{
- pthread_handle handle = thread_handle(thread);
- int pid;
- int dorestart = 0;
- pthread_descr th;
- pthread_extricate_if *pextricate;
-
- __pthread_lock(&handle->h_lock, NULL);
- if (invalid_handle(handle, thread)) {
- __pthread_unlock(&handle->h_lock);
- return ESRCH;
- }
-
- th = handle->h_descr;
-
- if (th->p_canceled) {
- __pthread_unlock(&handle->h_lock);
- return 0;
- }
-
- pextricate = th->p_extricate;
- th->p_canceled = 1;
- pid = th->p_pid;
-
- /* If the thread has registered an extrication interface, then
- invoke the interface. If it returns 1, then we succeeded in
- dequeuing the thread from whatever waiting object it was enqueued
- with. In that case, it is our responsibility to wake it up.
- And also to set the p_woken_by_cancel flag so the woken thread
- can tell that it was woken by cancellation. */
-
- if (pextricate != NULL) {
- dorestart = pextricate->pu_extricate_func(pextricate->pu_object, th);
- th->p_woken_by_cancel = dorestart;
- }
-
- __pthread_unlock(&handle->h_lock);
-
- /* If the thread has suspended or is about to, then we unblock it by
- issuing a restart, instead of a cancel signal. Otherwise we send
- the cancel signal to unblock the thread from a cancellation point,
- or to initiate asynchronous cancellation. The restart is needed so
- we have proper accounting of restarts; suspend decrements the thread's
- resume count, and restart() increments it. This also means that suspend's
- handling of the cancel signal is obsolete. */
-
- if (dorestart)
- restart(th);
- else
- kill(pid, __pthread_sig_cancel);
-
- return 0;
-}
-
-void pthread_testcancel(void)
-{
- pthread_descr self = thread_self();
- if (THREAD_GETMEM(self, p_canceled)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)
- pthread_exit(PTHREAD_CANCELED);
-}
-
-void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer,
- void (*routine)(void *), void * arg)
-{
- pthread_descr self = thread_self();
- buffer->__routine = routine;
- buffer->__arg = arg;
- buffer->__prev = THREAD_GETMEM(self, p_cleanup);
- THREAD_SETMEM(self, p_cleanup, buffer);
-}
-
-void _pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer,
- int execute)
-{
- pthread_descr self = thread_self();
- if (execute) buffer->__routine(buffer->__arg);
- THREAD_SETMEM(self, p_cleanup, buffer->__prev);
-}
-
-void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer,
- void (*routine)(void *), void * arg)
-{
- pthread_descr self = thread_self();
- buffer->__routine = routine;
- buffer->__arg = arg;
- buffer->__canceltype = THREAD_GETMEM(self, p_canceltype);
- buffer->__prev = THREAD_GETMEM(self, p_cleanup);
- THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED);
- THREAD_SETMEM(self, p_cleanup, buffer);
-}
-
-void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer,
- int execute)
-{
- pthread_descr self = thread_self();
- if (execute) buffer->__routine(buffer->__arg);
- THREAD_SETMEM(self, p_cleanup, buffer->__prev);
- THREAD_SETMEM(self, p_canceltype, buffer->__canceltype);
- if (THREAD_GETMEM(self, p_canceled) &&
- THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE &&
- THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
- pthread_exit(PTHREAD_CANCELED);
-}
-
-void __pthread_perform_cleanup(void)
-{
- pthread_descr self = thread_self();
- struct _pthread_cleanup_buffer * c;
- for (c = THREAD_GETMEM(self, p_cleanup); c != NULL; c = c->__prev)
- c->__routine(c->__arg);
-
-#ifdef __UCLIBC_HAS_RPC__
- /* And the TSD which needs special help. */
- if (THREAD_GETMEM(self, p_libc_specific[_LIBC_TSD_KEY_RPC_VARS]) != NULL)
- __rpc_thread_destroy ();
-#endif
-}
-
-#ifndef __PIC__
-/* We need a hook to force the cancelation wrappers to be linked in when
- static libpthread is used. */
-extern const int __pthread_provide_wrappers;
-static const int * const __pthread_require_wrappers =
- &__pthread_provide_wrappers;
-#endif
diff --git a/libpthread/linuxthreads/condvar.c b/libpthread/linuxthreads/condvar.c
deleted file mode 100644
index f9c46a331..000000000
--- a/libpthread/linuxthreads/condvar.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* and Pavel Krauz (krauz@fsid.cvut.cz). */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Condition variables */
-
-#include <errno.h>
-#include <sched.h>
-#include <stddef.h>
-#include <sys/time.h>
-#include "pthread.h"
-#include "internals.h"
-#include "spinlock.h"
-#include "queue.h"
-#include "restart.h"
-
-int pthread_cond_init(pthread_cond_t *cond,
- const pthread_condattr_t *cond_attr)
-{
- __pthread_init_lock(&cond->__c_lock);
- cond->__c_waiting = NULL;
- return 0;
-}
-
-int pthread_cond_destroy(pthread_cond_t *cond)
-{
- if (cond->__c_waiting != NULL) return EBUSY;
- return 0;
-}
-
-/* Function called by pthread_cancel to remove the thread from
- waiting on a condition variable queue. */
-
-static int cond_extricate_func(void *obj, pthread_descr th)
-{
- volatile pthread_descr self = thread_self();
- pthread_cond_t *cond = obj;
- int did_remove = 0;
-
- __pthread_lock(&cond->__c_lock, self);
- did_remove = remove_from_queue(&cond->__c_waiting, th);
- __pthread_unlock(&cond->__c_lock);
-
- return did_remove;
-}
-
-int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
-{
- volatile pthread_descr self = thread_self();
- pthread_extricate_if extr;
- int already_canceled = 0;
- int spurious_wakeup_count;
-
- /* Check whether the mutex is locked and owned by this thread. */
- if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
- && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
- && mutex->__m_owner != self)
- return EINVAL;
-
- /* Set up extrication interface */
- extr.pu_object = cond;
- extr.pu_extricate_func = cond_extricate_func;
-
- /* Register extrication interface */
- THREAD_SETMEM(self, p_condvar_avail, 0);
- __pthread_set_own_extricate_if(self, &extr);
-
- /* Atomically enqueue thread for waiting, but only if it is not
- canceled. If the thread is canceled, then it will fall through the
- suspend call below, and then call pthread_exit without
- having to worry about whether it is still on the condition variable queue.
- This depends on pthread_cancel setting p_canceled before calling the
- extricate function. */
-
- __pthread_lock(&cond->__c_lock, self);
- if (!(THREAD_GETMEM(self, p_canceled)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
- enqueue(&cond->__c_waiting, self);
- else
- already_canceled = 1;
- __pthread_unlock(&cond->__c_lock);
-
- if (already_canceled) {
- __pthread_set_own_extricate_if(self, 0);
- pthread_exit(PTHREAD_CANCELED);
- }
-
- pthread_mutex_unlock(mutex);
-
- spurious_wakeup_count = 0;
- while (1)
- {
- suspend(self);
- if (THREAD_GETMEM(self, p_condvar_avail) == 0
- && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
- || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
- {
- /* Count resumes that don't belong to us. */
- spurious_wakeup_count++;
- continue;
- }
- break;
- }
-
- __pthread_set_own_extricate_if(self, 0);
-
- /* Check for cancellation again, to provide correct cancellation
- point behavior */
-
- if (THREAD_GETMEM(self, p_woken_by_cancel)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
- THREAD_SETMEM(self, p_woken_by_cancel, 0);
- pthread_mutex_lock(mutex);
- pthread_exit(PTHREAD_CANCELED);
- }
-
- /* Put back any resumes we caught that don't belong to us. */
- while (spurious_wakeup_count--)
- restart(self);
-
- pthread_mutex_lock(mutex);
- return 0;
-}
-
-static int
-pthread_cond_timedwait_relative(pthread_cond_t *cond,
- pthread_mutex_t *mutex,
- const struct timespec * abstime)
-{
- volatile pthread_descr self = thread_self();
- int already_canceled = 0;
- pthread_extricate_if extr;
- int spurious_wakeup_count;
-
- /* Check whether the mutex is locked and owned by this thread. */
- if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
- && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
- && mutex->__m_owner != self)
- return EINVAL;
-
- /* Set up extrication interface */
- extr.pu_object = cond;
- extr.pu_extricate_func = cond_extricate_func;
-
- /* Register extrication interface */
- THREAD_SETMEM(self, p_condvar_avail, 0);
- __pthread_set_own_extricate_if(self, &extr);
-
- /* Enqueue to wait on the condition and check for cancellation. */
- __pthread_lock(&cond->__c_lock, self);
- if (!(THREAD_GETMEM(self, p_canceled)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
- enqueue(&cond->__c_waiting, self);
- else
- already_canceled = 1;
- __pthread_unlock(&cond->__c_lock);
-
- if (already_canceled) {
- __pthread_set_own_extricate_if(self, 0);
- pthread_exit(PTHREAD_CANCELED);
- }
-
- pthread_mutex_unlock(mutex);
-
- spurious_wakeup_count = 0;
- while (1)
- {
- if (!timedsuspend(self, abstime)) {
- int was_on_queue;
-
- /* __pthread_lock will queue back any spurious restarts that
- may happen to it. */
-
- __pthread_lock(&cond->__c_lock, self);
- was_on_queue = remove_from_queue(&cond->__c_waiting, self);
- __pthread_unlock(&cond->__c_lock);
-
- if (was_on_queue) {
- __pthread_set_own_extricate_if(self, 0);
- pthread_mutex_lock(mutex);
- return ETIMEDOUT;
- }
-
- /* Eat the outstanding restart() from the signaller */
- suspend(self);
- }
-
- if (THREAD_GETMEM(self, p_condvar_avail) == 0
- && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
- || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
- {
- /* Count resumes that don't belong to us. */
- spurious_wakeup_count++;
- continue;
- }
- break;
- }
-
- __pthread_set_own_extricate_if(self, 0);
-
- /* The remaining logic is the same as in other cancellable waits,
- such as pthread_join sem_wait or pthread_cond wait. */
-
- if (THREAD_GETMEM(self, p_woken_by_cancel)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
- THREAD_SETMEM(self, p_woken_by_cancel, 0);
- pthread_mutex_lock(mutex);
- pthread_exit(PTHREAD_CANCELED);
- }
-
- /* Put back any resumes we caught that don't belong to us. */
- while (spurious_wakeup_count--)
- restart(self);
-
- pthread_mutex_lock(mutex);
- return 0;
-}
-
-int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
- const struct timespec * abstime)
-{
- /* Indirect call through pointer! */
- return pthread_cond_timedwait_relative(cond, mutex, abstime);
-}
-
-int pthread_cond_signal(pthread_cond_t *cond)
-{
- pthread_descr th;
-
- __pthread_lock(&cond->__c_lock, NULL);
- th = dequeue(&cond->__c_waiting);
- __pthread_unlock(&cond->__c_lock);
- if (th != NULL) {
- th->p_condvar_avail = 1;
- WRITE_MEMORY_BARRIER();
- restart(th);
- }
- return 0;
-}
-
-int pthread_cond_broadcast(pthread_cond_t *cond)
-{
- pthread_descr tosignal, th;
-
- __pthread_lock(&cond->__c_lock, NULL);
- /* Copy the current state of the waiting queue and empty it */
- tosignal = cond->__c_waiting;
- cond->__c_waiting = NULL;
- __pthread_unlock(&cond->__c_lock);
- /* Now signal each process in the queue */
- while ((th = dequeue(&tosignal)) != NULL) {
- th->p_condvar_avail = 1;
- WRITE_MEMORY_BARRIER();
- restart(th);
- }
- return 0;
-}
-
-int pthread_condattr_init(pthread_condattr_t *attr)
-{
- return 0;
-}
-
-int pthread_condattr_destroy(pthread_condattr_t *attr)
-{
- return 0;
-}
-
-int pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
-{
- *pshared = PTHREAD_PROCESS_PRIVATE;
- return 0;
-}
-
-int pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared)
-{
- if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
- return EINVAL;
-
- /* For now it is not possible to shared a conditional variable. */
- if (pshared != PTHREAD_PROCESS_PRIVATE)
- return ENOSYS;
-
- return 0;
-}
diff --git a/libpthread/linuxthreads/debug.h b/libpthread/linuxthreads/debug.h
deleted file mode 100644
index a2ac5113a..000000000
--- a/libpthread/linuxthreads/debug.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/****************************************************************************
-**
-** NAME:
-** debug.h
-**
-** DESCRIPTION:
-** This header file defines the debug macros used in pthreads. To turn
-** debugging on, add -DDEBUG_PT to CFLAGS. It was added to the original
-** distribution of linuxthreads.
-**
-** This program is free software; you can redistribute it and/or
-** modify it under the terms of the GNU Library General Public License
-** as published by the Free Software Foundation; either version 2
-** of the License, or (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU Library General Public License for more details.
-**
-****************************************************************************/
-
-#ifndef _PT_DEBUG_H
-#define _PT_DEBUG_H
-
-#include <features.h>
-
-#ifdef __DODEBUG_PT__
-# define DEBUG_PT
-#endif
-
-/* include asserts for now */
-#define DO_ASSERT
-
-/* define the PDEBUG macro here */
-#undef PDEBUG
-#ifdef DEBUG_PT
-# define PDEBUG(fmt, args...) __pthread_message("%s: " fmt, __FUNCTION__, ## args)
-#else
-# define PDEBUG(fmt, args...) /* debug switched off */
-#endif
-
-/* nothing; placeholder to disable a PDEBUG message but don't delete it */
-#undef PDEBUGG
-#define PDEBUGG(fmt, args...)
-
-/* Define ASSERT to stop/warn. Should be void in production code */
-#undef ASSERT
-#ifdef DO_ASSERT
-# define ASSERT(x) if (!(x)) fprintf(stderr, "pt: assertion failed in %s:%i.\n",\
- __FILE__, __LINE__)
-#else
-# define ASSERT(x)
-#endif
-
-#endif /* _PT_DEBUG_H */
diff --git a/libpthread/linuxthreads/errno.c b/libpthread/linuxthreads/errno.c
deleted file mode 100644
index f5778f98a..000000000
--- a/libpthread/linuxthreads/errno.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Define the location of errno for the remainder of the C library */
-
-#define __FORCE_GLIBC
-#include <features.h>
-#include <errno.h>
-#include <netdb.h>
-#include "pthread.h"
-#include "internals.h"
-#include <stdio.h>
-
-int *
-__errno_location (void)
-{
- pthread_descr self = thread_self();
- return THREAD_GETMEM (self, p_errnop);
-}
-
-int *
-__h_errno_location (void)
-{
- pthread_descr self = thread_self();
- return THREAD_GETMEM (self, p_h_errnop);
-}
diff --git a/libpthread/linuxthreads/events.c b/libpthread/linuxthreads/events.c
deleted file mode 100644
index a4bf1f898..000000000
--- a/libpthread/linuxthreads/events.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Event functions used while debugging.
- Copyright (C) 1999 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* The functions contained here do nothing, they just return. */
-
-#include "internals.h"
-
-void
-__linuxthreads_create_event (void)
-{
-}
-
-void
-__linuxthreads_death_event (void)
-{
-}
-
-void
-__linuxthreads_reap_event (void)
-{
-}
diff --git a/libpthread/linuxthreads/internals.h b/libpthread/linuxthreads/internals.h
deleted file mode 100644
index 50a4d2d59..000000000
--- a/libpthread/linuxthreads/internals.h
+++ /dev/null
@@ -1,518 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-#ifndef _INTERNALS_H
-#define _INTERNALS_H 1
-
-/* Internal data structures */
-
-/* Includes */
-
-#include <bits/libc-tsd.h> /* for _LIBC_TSD_KEY_N */
-#include <limits.h>
-#include <setjmp.h>
-#include <signal.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include "pt-machine.h"
-#include "semaphore.h"
-#include "../linuxthreads_db/thread_dbP.h"
-#ifdef __UCLIBC_HAS_XLOCALE__
-#include <bits/uClibc_locale.h>
-#endif /* __UCLIBC_HAS_XLOCALE__ */
-
-/* Use a funky version in a probably vein attempt at preventing gdb
- * from dlopen()'ing glibc's libthread_db library... */
-#define STRINGIFY(s) STRINGIFY2 (s)
-#define STRINGIFY2(s) #s
-#define VERSION STRINGIFY(__UCLIBC_MAJOR__) "." STRINGIFY(__UCLIBC_MINOR__) "." STRINGIFY(__UCLIBC_SUBLEVEL__)
-
-#ifndef THREAD_GETMEM
-# define THREAD_GETMEM(descr, member) descr->member
-#endif
-#ifndef THREAD_GETMEM_NC
-# define THREAD_GETMEM_NC(descr, member) descr->member
-#endif
-#ifndef THREAD_SETMEM
-# define THREAD_SETMEM(descr, member, value) descr->member = (value)
-#endif
-#ifndef THREAD_SETMEM_NC
-# define THREAD_SETMEM_NC(descr, member, value) descr->member = (value)
-#endif
-
-/* Arguments passed to thread creation routine */
-
-struct pthread_start_args {
- void * (*start_routine)(void *); /* function to run */
- void * arg; /* its argument */
- sigset_t mask; /* initial signal mask for thread */
- int schedpolicy; /* initial scheduling policy (if any) */
- struct sched_param schedparam; /* initial scheduling parameters (if any) */
-};
-
-
-/* We keep thread specific data in a special data structure, a two-level
- array. The top-level array contains pointers to dynamically allocated
- arrays of a certain number of data pointers. So we can implement a
- sparse array. Each dynamic second-level array has
- PTHREAD_KEY_2NDLEVEL_SIZE
- entries. This value shouldn't be too large. */
-#define PTHREAD_KEY_2NDLEVEL_SIZE 32
-
-/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE
- keys in each subarray. */
-#define PTHREAD_KEY_1STLEVEL_SIZE \
- ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \
- / PTHREAD_KEY_2NDLEVEL_SIZE)
-
-typedef void (*destr_function)(void *);
-
-struct pthread_key_struct {
- int in_use; /* already allocated? */
- destr_function destr; /* destruction routine */
-};
-
-
-#define PTHREAD_START_ARGS_INITIALIZER { NULL, NULL, {{0, }}, 0, { 0 } }
-
-/* The type of thread descriptors */
-
-typedef struct _pthread_descr_struct * pthread_descr;
-
-/* Callback interface for removing the thread from waiting on an
- object if it is cancelled while waiting or about to wait.
- This hold a pointer to the object, and a pointer to a function
- which ``extricates'' the thread from its enqueued state.
- The function takes two arguments: pointer to the wait object,
- and a pointer to the thread. It returns 1 if an extrication
- actually occured, and hence the thread must also be signalled.
- It returns 0 if the thread had already been extricated. */
-
-typedef struct _pthread_extricate_struct {
- void *pu_object;
- int (*pu_extricate_func)(void *, pthread_descr);
-} pthread_extricate_if;
-
-/* Atomic counter made possible by compare_and_swap */
-
-struct pthread_atomic {
- long p_count;
- int p_spinlock;
-};
-
-/* Context info for read write locks. The pthread_rwlock_info structure
- is information about a lock that has been read-locked by the thread
- in whose list this structure appears. The pthread_rwlock_context
- is embedded in the thread context and contains a pointer to the
- head of the list of lock info structures, as well as a count of
- read locks that are untracked, because no info structure could be
- allocated for them. */
-
-struct _pthread_rwlock_t;
-
-typedef struct _pthread_rwlock_info {
- struct _pthread_rwlock_info *pr_next;
- struct _pthread_rwlock_t *pr_lock;
- int pr_lock_count;
-} pthread_readlock_info;
-
-struct _pthread_descr_struct {
- pthread_descr p_nextlive, p_prevlive;
- /* Double chaining of active threads */
- pthread_descr p_nextwaiting; /* Next element in the queue holding the thr */
- pthread_descr p_nextlock; /* can be on a queue and waiting on a lock */
- pthread_t p_tid; /* Thread identifier */
- int p_pid; /* PID of Unix process */
- int p_priority; /* Thread priority (== 0 if not realtime) */
- struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */
- int p_signal; /* last signal received */
- sigjmp_buf * p_signal_jmp; /* where to siglongjmp on a signal or NULL */
- sigjmp_buf * p_cancel_jmp; /* where to siglongjmp on a cancel or NULL */
- char p_terminated; /* true if terminated e.g. by pthread_exit */
- char p_detached; /* true if detached */
- char p_exited; /* true if the assoc. process terminated */
- void * p_retval; /* placeholder for return value */
- int p_retcode; /* placeholder for return code */
- pthread_descr p_joining; /* thread joining on that thread or NULL */
- struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */
- char p_cancelstate; /* cancellation state */
- char p_canceltype; /* cancellation type (deferred/async) */
- char p_canceled; /* cancellation request pending */
- int * p_errnop; /* pointer to used errno variable */
- int p_errno; /* error returned by last system call */
- int * p_h_errnop; /* pointer to used h_errno variable */
- int p_h_errno; /* error returned by last netdb function */
- char * p_in_sighandler; /* stack address of sighandler, or NULL */
- char p_sigwaiting; /* true if a sigwait() is in progress */
- struct pthread_start_args p_start_args; /* arguments for thread creation */
- void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */
- void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */
- int p_userstack; /* nonzero if the user provided the stack */
- void *p_guardaddr; /* address of guard area or NULL */
- size_t p_guardsize; /* size of guard area */
- pthread_descr p_self; /* Pointer to this structure */
- int p_nr; /* Index of descriptor in __pthread_handles */
- int p_report_events; /* Nonzero if events must be reported. */
- td_eventbuf_t p_eventbuf; /* Data for event. */
- struct pthread_atomic p_resume_count; /* number of times restart() was
- called on thread */
- char p_woken_by_cancel; /* cancellation performed wakeup */
- char p_condvar_avail; /* flag if conditional variable became avail */
- char p_sem_avail; /* flag if semaphore became available */
- pthread_extricate_if *p_extricate; /* See above */
- pthread_readlock_info *p_readlock_list; /* List of readlock info structs */
- pthread_readlock_info *p_readlock_free; /* Free list of structs */
- int p_untracked_readlock_count; /* Readlocks not tracked by list */
- /* New elements must be added at the end. */
-#ifdef __UCLIBC_HAS_XLOCALE__
- __locale_t locale; /* thread-specific locale from uselocale() only! */
-#endif /* __UCLIBC_HAS_XLOCALE__ */
-} __attribute__ ((aligned(32))); /* We need to align the structure so that
- doubles are aligned properly. This is 8
- bytes on MIPS and 16 bytes on MIPS64.
- 32 bytes might give better cache
- utilization. */
-
-/* The type of thread handles. */
-
-typedef struct pthread_handle_struct * pthread_handle;
-
-struct pthread_handle_struct {
- struct _pthread_fastlock h_lock; /* Fast lock for sychronized access */
- pthread_descr h_descr; /* Thread descriptor or NULL if invalid */
- char * h_bottom; /* Lowest address in the stack thread */
-};
-
-/* The type of messages sent to the thread manager thread */
-
-struct pthread_request {
- pthread_descr req_thread; /* Thread doing the request */
- enum { /* Request kind */
- REQ_CREATE, REQ_FREE, REQ_PROCESS_EXIT, REQ_MAIN_THREAD_EXIT,
- REQ_POST, REQ_DEBUG, REQ_KICK
- } req_kind;
- union { /* Arguments for request */
- struct { /* For REQ_CREATE: */
- const pthread_attr_t * attr; /* thread attributes */
- void * (*fn)(void *); /* start function */
- void * arg; /* argument to start function */
- sigset_t mask; /* signal mask */
- } create;
- struct { /* For REQ_FREE: */
- pthread_t thread_id; /* identifier of thread to free */
- } free;
- struct { /* For REQ_PROCESS_EXIT: */
- int code; /* exit status */
- } exit;
- void * post; /* For REQ_POST: the semaphore */
- } req_args;
-};
-
-
-/* Signals used for suspend/restart and for cancellation notification. */
-
-extern int __pthread_sig_restart;
-extern int __pthread_sig_cancel;
-
-/* Signal used for interfacing with gdb */
-
-extern int __pthread_sig_debug;
-
-/* Global array of thread handles, used for validating a thread id
- and retrieving the corresponding thread descriptor. Also used for
- mapping the available stack segments. */
-
-extern struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX];
-
-/* Descriptor of the initial thread */
-
-extern struct _pthread_descr_struct __pthread_initial_thread;
-
-/* Descriptor of the manager thread */
-
-extern struct _pthread_descr_struct __pthread_manager_thread;
-
-/* Descriptor of the main thread */
-
-extern pthread_descr __pthread_main_thread;
-
-/* Limit between the stack of the initial thread (above) and the
- stacks of other threads (below). Aligned on a STACK_SIZE boundary.
- Initially 0, meaning that the current thread is (by definition)
- the initial thread. */
-
-/* For non-MMU systems also remember to stack top of the initial thread.
- * This is adapted when other stacks are malloc'ed since we don't know
- * the bounds a-priori. -StS */
-
-extern char *__pthread_initial_thread_bos;
-#ifndef __ARCH_HAS_MMU__
-extern char *__pthread_initial_thread_tos;
-#define NOMMU_INITIAL_THREAD_BOUNDS(tos,bos) \
- if ((tos)>=__pthread_initial_thread_bos \
- && (bos)<__pthread_initial_thread_tos) \
- __pthread_initial_thread_bos = (tos)+1
-#else
-#define NOMMU_INITIAL_THREAD_BOUNDS(tos,bos) /* empty */
-#endif /* __ARCH_HAS_MMU__ */
-
-
-/* Indicate whether at least one thread has a user-defined stack (if 1),
- or all threads have stacks supplied by LinuxThreads (if 0). */
-
-extern int __pthread_nonstandard_stacks;
-
-/* File descriptor for sending requests to the thread manager.
- Initially -1, meaning that __pthread_initialize_manager must be called. */
-
-extern int __pthread_manager_request;
-
-/* Other end of the pipe for sending requests to the thread manager. */
-
-extern int __pthread_manager_reader;
-
-/* Limits of the thread manager stack. */
-
-extern char *__pthread_manager_thread_bos;
-extern char *__pthread_manager_thread_tos;
-
-/* Pending request for a process-wide exit */
-
-extern int __pthread_exit_requested, __pthread_exit_code;
-
-/* Set to 1 by gdb if we're debugging */
-
-extern volatile int __pthread_threads_debug;
-
-/* Globally enabled events. */
-extern volatile td_thr_events_t __pthread_threads_events;
-
-/* Pointer to descriptor of thread with last event. */
-extern volatile pthread_descr __pthread_last_event;
-
-/* Return the handle corresponding to a thread id */
-
-static inline pthread_handle thread_handle(pthread_t id)
-{
- return &__pthread_handles[id % PTHREAD_THREADS_MAX];
-}
-
-/* Validate a thread handle. Must have acquired h->h_spinlock before. */
-
-static inline int invalid_handle(pthread_handle h, pthread_t id)
-{
- return h->h_descr == NULL || h->h_descr->p_tid != id;
-}
-
-/* Fill in defaults left unspecified by pt-machine.h. */
-
-/* The page size we can get from the system. This should likely not be
- changed by the machine file but, you never know. */
-extern size_t __pagesize;
-#include <bits/uClibc_page.h>
-#ifndef PAGE_SIZE
-#define PAGE_SIZE (sysconf (_SC_PAGESIZE))
-#endif
-
-/* The max size of the thread stack segments. If the default
- THREAD_SELF implementation is used, this must be a power of two and
- a multiple of PAGE_SIZE. */
-#ifndef STACK_SIZE
-#ifdef __ARCH_HAS_MMU__
-#define STACK_SIZE (2 * 1024 * 1024)
-#else
-#define STACK_SIZE (4 * __pagesize)
-#endif
-#endif
-
-/* The initial size of the thread stack. Must be a multiple of PAGE_SIZE. */
-#ifndef INITIAL_STACK_SIZE
-#define INITIAL_STACK_SIZE (4 * __pagesize)
-#endif
-
-/* Size of the thread manager stack. The "- 32" avoids wasting space
- with some malloc() implementations. */
-#ifndef THREAD_MANAGER_STACK_SIZE
-#define THREAD_MANAGER_STACK_SIZE (2 * __pagesize - 32)
-#endif
-
-/* The base of the "array" of thread stacks. The array will grow down from
- here. Defaults to the calculated bottom of the initial application
- stack. */
-#ifndef THREAD_STACK_START_ADDRESS
-#define THREAD_STACK_START_ADDRESS __pthread_initial_thread_bos
-#endif
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#ifndef CURRENT_STACK_FRAME
-#define CURRENT_STACK_FRAME ({ char __csf; &__csf; })
-#endif
-
-/* If MEMORY_BARRIER isn't defined in pt-machine.h, assume the
- architecture doesn't need a memory barrier instruction (e.g. Intel
- x86). Still we need the compiler to respect the barrier and emit
- all outstanding operations which modify memory. Some architectures
- distinguish between full, read and write barriers. */
-#ifndef MEMORY_BARRIER
-#define MEMORY_BARRIER() asm ("" : : : "memory")
-#endif
-#ifndef READ_MEMORY_BARRIER
-#define READ_MEMORY_BARRIER() MEMORY_BARRIER()
-#endif
-#ifndef WRITE_MEMORY_BARRIER
-#define WRITE_MEMORY_BARRIER() MEMORY_BARRIER()
-#endif
-
-/* Recover thread descriptor for the current thread */
-
-extern pthread_descr __pthread_find_self (void) __attribute__ ((const));
-
-static inline pthread_descr thread_self (void) __attribute__ ((const));
-static inline pthread_descr thread_self (void)
-{
-#ifdef THREAD_SELF
- return THREAD_SELF;
-#else
- char *sp = CURRENT_STACK_FRAME;
-#ifdef __ARCH_HAS_MMU__
- if (sp >= __pthread_initial_thread_bos)
- return &__pthread_initial_thread;
- else if (sp >= __pthread_manager_thread_bos
- && sp < __pthread_manager_thread_tos)
- return &__pthread_manager_thread;
- else if (__pthread_nonstandard_stacks)
- return __pthread_find_self();
- else
- return (pthread_descr)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1;
-#else
- /* For non-MMU we need to be more careful about the initial thread stack.
- * We refine the initial thread stack bounds dynamically as we allocate
- * the other stack frame such that it doesn't overlap with them. Then
- * we can be sure to pick the right thread according to the current SP */
-
- /* Since we allow other stack frames to be above or below, we need to
- * treat this case special. When pthread_initialize() wasn't called yet,
- * only the initial thread is there. */
- if (__pthread_initial_thread_bos == NULL) {
- return &__pthread_initial_thread;
- }
- else if (sp >= __pthread_initial_thread_bos
- && sp < __pthread_initial_thread_tos) {
- return &__pthread_initial_thread;
- }
- else if (sp >= __pthread_manager_thread_bos
- && sp < __pthread_manager_thread_tos) {
- return &__pthread_manager_thread;
- }
- else {
- return __pthread_find_self();
- }
-#endif /* __ARCH_HAS_MMU__ */
-#endif
-}
-
-/* Max number of times we must spin on a spinlock calling sched_yield().
- After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */
-
-#ifndef MAX_SPIN_COUNT
-#define MAX_SPIN_COUNT 50
-#endif
-
-/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock
- after MAX_SPIN_COUNT iterations of sched_yield().
- With the 2.0 and 2.1 kernels, this MUST BE > 2ms.
- (Otherwise the kernel does busy-waiting for realtime threads,
- giving other threads no chance to run.) */
-
-#ifndef SPIN_SLEEP_DURATION
-#define SPIN_SLEEP_DURATION 2000001
-#endif
-
-/* Debugging */
-
-#ifdef DEBUG
-#include <assert.h>
-#define ASSERT assert
-#define MSG __pthread_message
-#else
-#define ASSERT(x)
-#define MSG(msg,arg...)
-#endif
-
-/* Internal global functions */
-
-void __pthread_destroy_specifics(void);
-void __pthread_perform_cleanup(void);
-int __pthread_initialize_manager(void);
-void __pthread_message(char * fmt, ...);
-int __pthread_manager(void *reqfd);
-int __pthread_manager_event(void *reqfd);
-void __pthread_manager_sighandler(int sig);
-void __pthread_reset_main_thread(void);
-void __fresetlockfiles(void);
-void __pthread_manager_adjust_prio(int thread_prio);
-void __pthread_initialize_minimal (void);
-
-extern int __pthread_attr_setguardsize __P ((pthread_attr_t *__attr,
- size_t __guardsize));
-extern int __pthread_attr_getguardsize __P ((__const pthread_attr_t *__attr,
- size_t *__guardsize));
-extern int __pthread_attr_setstackaddr __P ((pthread_attr_t *__attr,
- void *__stackaddr));
-extern int __pthread_attr_getstackaddr __P ((__const pthread_attr_t *__attr,
- void **__stackaddr));
-extern int __pthread_attr_setstacksize __P ((pthread_attr_t *__attr,
- size_t __stacksize));
-extern int __pthread_attr_getstacksize __P ((__const pthread_attr_t *__attr,
- size_t *__stacksize));
-extern int __pthread_getconcurrency __P ((void));
-extern int __pthread_setconcurrency __P ((int __level));
-extern int __pthread_mutexattr_gettype __P ((__const pthread_mutexattr_t *__attr,
- int *__kind));
-extern void __pthread_kill_other_threads_np __P ((void));
-
-extern void __pthread_restart_old(pthread_descr th);
-extern void __pthread_suspend_old(pthread_descr self);
-extern int __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abs);
-
-extern void __pthread_restart_new(pthread_descr th);
-extern void __pthread_suspend_new(pthread_descr self);
-extern int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abs);
-
-extern void __pthread_wait_for_restart_signal(pthread_descr self);
-
-/* Global pointers to old or new suspend functions */
-
-extern void (*__pthread_restart)(pthread_descr);
-extern void (*__pthread_suspend)(pthread_descr);
-
-/* Prototypes for the function without cancelation support when the
- normal version has it. */
-extern int __libc_close (int fd);
-extern int __libc_nanosleep (const struct timespec *requested_time,
- struct timespec *remaining);
-extern ssize_t __libc_read (int fd, void *buf, size_t count);
-extern pid_t __libc_waitpid (pid_t pid, int *stat_loc, int options);
-extern ssize_t __libc_write (int fd, const void *buf, size_t count);
-
-/* Prototypes for some of the new semaphore functions. */
-extern int __new_sem_post (sem_t * sem);
-
-/* The functions called the signal events. */
-extern void __linuxthreads_create_event (void);
-extern void __linuxthreads_death_event (void);
-extern void __linuxthreads_reap_event (void);
-
-#endif /* internals.h */
diff --git a/libpthread/linuxthreads/join.c b/libpthread/linuxthreads/join.c
deleted file mode 100644
index 5aeec6a20..000000000
--- a/libpthread/linuxthreads/join.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Thread termination and joining */
-
-#include <features.h>
-#define __USE_GNU
-#include <errno.h>
-#include <sched.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include "pthread.h"
-#include "internals.h"
-#include "spinlock.h"
-#include "restart.h"
-#include "debug.h" /* PDEBUG, added by StS */
-
-void pthread_exit(void * retval)
-{
- pthread_descr self = thread_self();
- pthread_descr joining;
- struct pthread_request request;
- PDEBUG("self=%p, pid=%d\n", self, self->p_pid);
-
- /* Reset the cancellation flag to avoid looping if the cleanup handlers
- contain cancellation points */
- THREAD_SETMEM(self, p_canceled, 0);
- /* Call cleanup functions and destroy the thread-specific data */
- __pthread_perform_cleanup();
- __pthread_destroy_specifics();
- /* Store return value */
- __pthread_lock(THREAD_GETMEM(self, p_lock), self);
- THREAD_SETMEM(self, p_retval, retval);
- /* See whether we have to signal the death. */
- if (THREAD_GETMEM(self, p_report_events))
- {
- /* See whether TD_DEATH is in any of the mask. */
- int idx = __td_eventword (TD_DEATH);
- uint32_t mask = __td_eventmask (TD_DEATH);
-
- if ((mask & (__pthread_threads_events.event_bits[idx]
- | THREAD_GETMEM_NC(self,
- p_eventbuf.eventmask).event_bits[idx]))
- != 0)
- {
- /* Yep, we have to signal the death. */
- THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH);
- THREAD_SETMEM(self, p_eventbuf.eventdata, self);
- __pthread_last_event = self;
-
- /* Now call the function to signal the event. */
- __linuxthreads_death_event();
- }
- }
- /* Say that we've terminated */
- THREAD_SETMEM(self, p_terminated, 1);
- /* See if someone is joining on us */
- joining = THREAD_GETMEM(self, p_joining);
- PDEBUG("joining = %p, pid=%d\n", joining, joining->p_pid);
- __pthread_unlock(THREAD_GETMEM(self, p_lock));
- /* Restart joining thread if any */
- if (joining != NULL) restart(joining);
- /* If this is the initial thread, block until all threads have terminated.
- If another thread calls exit, we'll be terminated from our signal
- handler. */
- if (self == __pthread_main_thread && __pthread_manager_request >= 0) {
- request.req_thread = self;
- request.req_kind = REQ_MAIN_THREAD_EXIT;
- TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
- (char *)&request, sizeof(request)));
- suspend(self);
- /* Main thread flushes stdio streams and runs atexit functions.
- * It also calls a handler within LinuxThreads which sends a process exit
- * request to the thread manager. */
- exit(0);
- }
- /* Exit the process (but don't flush stdio streams, and don't run
- atexit functions). */
- _exit(0);
-}
-
-/* Function called by pthread_cancel to remove the thread from
- waiting on a condition variable queue. */
-
-static int join_extricate_func(void *obj, pthread_descr th)
-{
- volatile pthread_descr self = thread_self();
- pthread_handle handle = obj;
- pthread_descr jo;
- int did_remove = 0;
-
- __pthread_lock(&handle->h_lock, self);
- jo = handle->h_descr;
- did_remove = jo->p_joining != NULL;
- jo->p_joining = NULL;
- __pthread_unlock(&handle->h_lock);
-
- return did_remove;
-}
-
-int pthread_join(pthread_t thread_id, void ** thread_return)
-{
- volatile pthread_descr self = thread_self();
- struct pthread_request request;
- pthread_handle handle = thread_handle(thread_id);
- pthread_descr th;
- pthread_extricate_if extr;
- int already_canceled = 0;
- PDEBUG("\n");
-
- /* Set up extrication interface */
- extr.pu_object = handle;
- extr.pu_extricate_func = join_extricate_func;
-
- __pthread_lock(&handle->h_lock, self);
- if (invalid_handle(handle, thread_id)) {
- __pthread_unlock(&handle->h_lock);
- return ESRCH;
- }
- th = handle->h_descr;
- if (th == self) {
- __pthread_unlock(&handle->h_lock);
- return EDEADLK;
- }
- /* If detached or already joined, error */
- if (th->p_detached || th->p_joining != NULL) {
- __pthread_unlock(&handle->h_lock);
- return EINVAL;
- }
- /* If not terminated yet, suspend ourselves. */
- if (! th->p_terminated) {
- /* Register extrication interface */
- __pthread_set_own_extricate_if(self, &extr);
- if (!(THREAD_GETMEM(self, p_canceled)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
- th->p_joining = self;
- else
- already_canceled = 1;
- __pthread_unlock(&handle->h_lock);
-
- if (already_canceled) {
- __pthread_set_own_extricate_if(self, 0);
- pthread_exit(PTHREAD_CANCELED);
- }
-
- PDEBUG("before suspend\n");
- suspend(self);
- PDEBUG("after suspend\n");
- /* Deregister extrication interface */
- __pthread_set_own_extricate_if(self, 0);
-
- /* This is a cancellation point */
- if (THREAD_GETMEM(self, p_woken_by_cancel)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
- THREAD_SETMEM(self, p_woken_by_cancel, 0);
- pthread_exit(PTHREAD_CANCELED);
- }
- __pthread_lock(&handle->h_lock, self);
- }
- /* Get return value */
- if (thread_return != NULL) *thread_return = th->p_retval;
- __pthread_unlock(&handle->h_lock);
- /* Send notification to thread manager */
- if (__pthread_manager_request >= 0) {
- request.req_thread = self;
- request.req_kind = REQ_FREE;
- request.req_args.free.thread_id = thread_id;
- TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
- (char *) &request, sizeof(request)));
- }
- return 0;
-}
-
-int pthread_detach(pthread_t thread_id)
-{
- int terminated;
- struct pthread_request request;
- pthread_handle handle = thread_handle(thread_id);
- pthread_descr th;
-
- __pthread_lock(&handle->h_lock, NULL);
- if (invalid_handle(handle, thread_id)) {
- __pthread_unlock(&handle->h_lock);
- return ESRCH;
- }
- th = handle->h_descr;
- /* If already detached, error */
- if (th->p_detached) {
- __pthread_unlock(&handle->h_lock);
- return EINVAL;
- }
- /* If already joining, don't do anything. */
- if (th->p_joining != NULL) {
- __pthread_unlock(&handle->h_lock);
- return 0;
- }
- /* Mark as detached */
- th->p_detached = 1;
- terminated = th->p_terminated;
- __pthread_unlock(&handle->h_lock);
- /* If already terminated, notify thread manager to reclaim resources */
- if (terminated && __pthread_manager_request >= 0) {
- request.req_thread = thread_self();
- request.req_kind = REQ_FREE;
- request.req_args.free.thread_id = thread_id;
- TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
- (char *) &request, sizeof(request)));
- }
- return 0;
-}
diff --git a/libpthread/linuxthreads/linuxthreads.texi b/libpthread/linuxthreads/linuxthreads.texi
deleted file mode 100644
index 795fb7097..000000000
--- a/libpthread/linuxthreads/linuxthreads.texi
+++ /dev/null
@@ -1,1627 +0,0 @@
-@node POSIX Threads
-@c @node POSIX Threads, , Top, Top
-@chapter POSIX Threads
-@c %MENU% The standard threads library
-
-@c This chapter needs more work bigtime. -zw
-
-This chapter describes the pthreads (POSIX threads) library. This
-library provides support functions for multithreaded programs: thread
-primitives, synchronization objects, and so forth. It also implements
-POSIX 1003.1b semaphores (not to be confused with System V semaphores).
-
-The threads operations (@samp{pthread_*}) do not use @var{errno}.
-Instead they return an error code directly. The semaphore operations do
-use @var{errno}.
-
-@menu
-* Basic Thread Operations:: Creating, terminating, and waiting for threads.
-* Thread Attributes:: Tuning thread scheduling.
-* Cancellation:: Stopping a thread before it's done.
-* Cleanup Handlers:: Deallocating resources when a thread is
- canceled.
-* Mutexes:: One way to synchronize threads.
-* Condition Variables:: Another way.
-* POSIX Semaphores:: And a third way.
-* Thread-Specific Data:: Variables with different values in
- different threads.
-* Threads and Signal Handling:: Why you should avoid mixing the two, and
- how to do it if you must.
-* Threads and Fork:: Interactions between threads and the
- @code{fork} function.
-* Streams and Fork:: Interactions between stdio streams and
- @code{fork}.
-* Miscellaneous Thread Functions:: A grab bag of utility routines.
-@end menu
-
-@node Basic Thread Operations
-@section Basic Thread Operations
-
-These functions are the thread equivalents of @code{fork}, @code{exit},
-and @code{wait}.
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_create (pthread_t * @var{thread}, pthread_attr_t * @var{attr}, void * (*@var{start_routine})(void *), void * @var{arg})
-@code{pthread_create} creates a new thread of control that executes
-concurrently with the calling thread. The new thread calls the
-function @var{start_routine}, passing it @var{arg} as first argument. The
-new thread terminates either explicitly, by calling @code{pthread_exit},
-or implicitly, by returning from the @var{start_routine} function. The
-latter case is equivalent to calling @code{pthread_exit} with the result
-returned by @var{start_routine} as exit code.
-
-The @var{attr} argument specifies thread attributes to be applied to the
-new thread. @xref{Thread Attributes}, for details. The @var{attr}
-argument can also be @code{NULL}, in which case default attributes are
-used: the created thread is joinable (not detached) and has an ordinary
-(not realtime) scheduling policy.
-
-On success, the identifier of the newly created thread is stored in the
-location pointed by the @var{thread} argument, and a 0 is returned. On
-error, a non-zero error code is returned.
-
-This function may return the following errors:
-@table @code
-@item EAGAIN
-Not enough system resources to create a process for the new thread,
-or more than @code{PTHREAD_THREADS_MAX} threads are already active.
-@end table
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun void pthread_exit (void *@var{retval})
-@code{pthread_exit} terminates the execution of the calling thread. All
-cleanup handlers (@pxref{Cleanup Handlers}) that have been set for the
-calling thread with @code{pthread_cleanup_push} are executed in reverse
-order (the most recently pushed handler is executed first). Finalization
-functions for thread-specific data are then called for all keys that
-have non-@code{NULL} values associated with them in the calling thread
-(@pxref{Thread-Specific Data}). Finally, execution of the calling
-thread is stopped.
-
-The @var{retval} argument is the return value of the thread. It can be
-retrieved from another thread using @code{pthread_join}.
-
-The @code{pthread_exit} function never returns.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_cancel (pthread_t @var{thread})
-
-@code{pthread_cancel} sends a cancellation request to the thread denoted
-by the @var{thread} argument. If there is no such thread,
-@code{pthread_cancel} fails and returns @code{ESRCH}. Otherwise it
-returns 0. @xref{Cancellation}, for details.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_join (pthread_t @var{th}, void **thread_@var{return})
-@code{pthread_join} suspends the execution of the calling thread until
-the thread identified by @var{th} terminates, either by calling
-@code{pthread_exit} or by being canceled.
-
-If @var{thread_return} is not @code{NULL}, the return value of @var{th}
-is stored in the location pointed to by @var{thread_return}. The return
-value of @var{th} is either the argument it gave to @code{pthread_exit},
-or @code{PTHREAD_CANCELED} if @var{th} was canceled.
-
-The joined thread @code{th} must be in the joinable state: it must not
-have been detached using @code{pthread_detach} or the
-@code{PTHREAD_CREATE_DETACHED} attribute to @code{pthread_create}.
-
-When a joinable thread terminates, its memory resources (thread
-descriptor and stack) are not deallocated until another thread performs
-@code{pthread_join} on it. Therefore, @code{pthread_join} must be called
-once for each joinable thread created to avoid memory leaks.
-
-At most one thread can wait for the termination of a given
-thread. Calling @code{pthread_join} on a thread @var{th} on which
-another thread is already waiting for termination returns an error.
-
-@code{pthread_join} is a cancellation point. If a thread is canceled
-while suspended in @code{pthread_join}, the thread execution resumes
-immediately and the cancellation is executed without waiting for the
-@var{th} thread to terminate. If cancellation occurs during
-@code{pthread_join}, the @var{th} thread remains not joined.
-
-On success, the return value of @var{th} is stored in the location
-pointed to by @var{thread_return}, and 0 is returned. On error, one of
-the following values is returned:
-@table @code
-@item ESRCH
-No thread could be found corresponding to that specified by @var{th}.
-@item EINVAL
-The @var{th} thread has been detached, or another thread is already
-waiting on termination of @var{th}.
-@item EDEADLK
-The @var{th} argument refers to the calling thread.
-@end table
-@end deftypefun
-
-@node Thread Attributes
-@section Thread Attributes
-
-@comment pthread.h
-@comment POSIX
-
-Threads have a number of attributes that may be set at creation time.
-This is done by filling a thread attribute object @var{attr} of type
-@code{pthread_attr_t}, then passing it as second argument to
-@code{pthread_create}. Passing @code{NULL} is equivalent to passing a
-thread attribute object with all attributes set to their default values.
-
-Attribute objects are consulted only when creating a new thread. The
-same attribute object can be used for creating several threads.
-Modifying an attribute object after a call to @code{pthread_create} does
-not change the attributes of the thread previously created.
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_attr_init (pthread_attr_t *@var{attr})
-@code{pthread_attr_init} initializes the thread attribute object
-@var{attr} and fills it with default values for the attributes. (The
-default values are listed below for each attribute.)
-
-Each attribute @var{attrname} (see below for a list of all attributes)
-can be individually set using the function
-@code{pthread_attr_set@var{attrname}} and retrieved using the function
-@code{pthread_attr_get@var{attrname}}.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_attr_destroy (pthread_attr_t *@var{attr})
-@code{pthread_attr_destroy} destroys the attribute object pointed to by
-@var{attr} releasing any resources associated with it. @var{attr} is
-left in an undefined state, and you must not use it again in a call to
-any pthreads function until it has been reinitialized.
-@end deftypefun
-
-@findex pthread_attr_setdetachstate
-@findex pthread_attr_setguardsize
-@findex pthread_attr_setinheritsched
-@findex pthread_attr_setschedparam
-@findex pthread_attr_setschedpolicy
-@findex pthread_attr_setscope
-@findex pthread_attr_setstack
-@findex pthread_attr_setstackaddr
-@findex pthread_attr_setstacksize
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_attr_setattr (pthread_attr_t *@var{obj}, int @var{value})
-Set attribute @var{attr} to @var{value} in the attribute object pointed
-to by @var{obj}. See below for a list of possible attributes and the
-values they can take.
-
-On success, these functions return 0. If @var{value} is not meaningful
-for the @var{attr} being modified, they will return the error code
-@code{EINVAL}. Some of the functions have other failure modes; see
-below.
-@end deftypefun
-
-@findex pthread_attr_getdetachstate
-@findex pthread_attr_getguardsize
-@findex pthread_attr_getinheritsched
-@findex pthread_attr_getschedparam
-@findex pthread_attr_getschedpolicy
-@findex pthread_attr_getscope
-@findex pthread_attr_getstack
-@findex pthread_attr_getstackaddr
-@findex pthread_attr_getstacksize
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_attr_getattr (const pthread_attr_t *@var{obj}, int *@var{value})
-Store the current setting of @var{attr} in @var{obj} into the variable
-pointed to by @var{value}.
-
-These functions always return 0.
-@end deftypefun
-
-The following thread attributes are supported:
-@table @samp
-@item detachstate
-Choose whether the thread is created in the joinable state (value
-@code{PTHREAD_CREATE_JOINABLE}) or in the detached state
-(@code{PTHREAD_CREATE_DETACHED}). The default is
-@code{PTHREAD_CREATE_JOINABLE}.
-
-In the joinable state, another thread can synchronize on the thread
-termination and recover its termination code using @code{pthread_join},
-but some of the thread resources are kept allocated after the thread
-terminates, and reclaimed only when another thread performs
-@code{pthread_join} on that thread.
-
-In the detached state, the thread resources are immediately freed when
-it terminates, but @code{pthread_join} cannot be used to synchronize on
-the thread termination.
-
-A thread created in the joinable state can later be put in the detached
-thread using @code{pthread_detach}.
-
-@item schedpolicy
-Select the scheduling policy for the thread: one of @code{SCHED_OTHER}
-(regular, non-realtime scheduling), @code{SCHED_RR} (realtime,
-round-robin) or @code{SCHED_FIFO} (realtime, first-in first-out).
-The default is @code{SCHED_OTHER}.
-@c Not doc'd in our manual: FIXME.
-@c See @code{sched_setpolicy} for more information on scheduling policies.
-
-The realtime scheduling policies @code{SCHED_RR} and @code{SCHED_FIFO}
-are available only to processes with superuser privileges.
-@code{pthread_attr_setschedparam} will fail and return @code{ENOTSUP} if
-you try to set a realtime policy when you are unprivileged.
-
-The scheduling policy of a thread can be changed after creation with
-@code{pthread_setschedparam}.
-
-@item schedparam
-Change the scheduling parameter (the scheduling priority)
-for the thread. The default is 0.
-
-This attribute is not significant if the scheduling policy is
-@code{SCHED_OTHER}; it only matters for the realtime policies
-@code{SCHED_RR} and @code{SCHED_FIFO}.
-
-The scheduling priority of a thread can be changed after creation with
-@code{pthread_setschedparam}.
-
-@item inheritsched
-Choose whether the scheduling policy and scheduling parameter for the
-newly created thread are determined by the values of the
-@var{schedpolicy} and @var{schedparam} attributes (value
-@code{PTHREAD_EXPLICIT_SCHED}) or are inherited from the parent thread
-(value @code{PTHREAD_INHERIT_SCHED}). The default is
-@code{PTHREAD_EXPLICIT_SCHED}.
-
-@item scope
-Choose the scheduling contention scope for the created thread. The
-default is @code{PTHREAD_SCOPE_SYSTEM}, meaning that the threads contend
-for CPU time with all processes running on the machine. In particular,
-thread priorities are interpreted relative to the priorities of all
-other processes on the machine. The other possibility,
-@code{PTHREAD_SCOPE_PROCESS}, means that scheduling contention occurs
-only between the threads of the running process: thread priorities are
-interpreted relative to the priorities of the other threads of the
-process, regardless of the priorities of other processes.
-
-@code{PTHREAD_SCOPE_PROCESS} is not supported in LinuxThreads. If you
-try to set the scope to this value, @code{pthread_attr_setscope} will
-fail and return @code{ENOTSUP}.
-
-@item stackaddr
-Provide an address for an application managed stack. The size of the
-stack must be at least @code{PTHREAD_STACK_MIN}.
-
-@item stacksize
-Change the size of the stack created for the thread. The value defines
-the minimum stack size, in bytes.
-
-If the value exceeds the system's maximum stack size, or is smaller
-than @code{PTHREAD_STACK_MIN}, @code{pthread_attr_setstacksize} will
-fail and return @code{EINVAL}.
-
-@item stack
-Provide both the address and size of an application managed stack to
-use for the new thread. The base of the memory area is @var{stackaddr}
-with the size of the memory area, @var{stacksize}, measured in bytes.
-
-If the value of @var{stacksize} is less than @code{PTHREAD_STACK_MIN},
-or greater than the system's maximum stack size, or if the value of
-@var{stackaddr} lacks the proper alignment, @code{pthread_attr_setstack}
-will fail and return @code{EINVAL}.
-
-@item guardsize
-Change the minimum size in bytes of the guard area for the thread's
-stack. The default size is a single page. If this value is set, it
-will be rounded up to the nearest page size. If the value is set to 0,
-a guard area will not be created for this thread. The space allocated
-for the guard area is used to catch stack overflow. Therefore, when
-allocating large structures on the stack, a larger guard area may be
-required to catch a stack overflow.
-
-If the caller is managing their own stacks (if the @code{stackaddr}
-attribute has been set), then the @code{guardsize} attribute is ignored.
-
-If the value exceeds the @code{stacksize}, @code{pthread_atrr_setguardsize}
-will fail and return @code{EINVAL}.
-@end table
-
-@node Cancellation
-@section Cancellation
-
-Cancellation is the mechanism by which a thread can terminate the
-execution of another thread. More precisely, a thread can send a
-cancellation request to another thread. Depending on its settings, the
-target thread can then either ignore the request, honor it immediately,
-or defer it till it reaches a cancellation point. When threads are
-first created by @code{pthread_create}, they always defer cancellation
-requests.
-
-When a thread eventually honors a cancellation request, it behaves as if
-@code{pthread_exit(PTHREAD_CANCELED)} was called. All cleanup handlers
-are executed in reverse order, finalization functions for
-thread-specific data are called, and finally the thread stops executing.
-If the canceled thread was joinable, the return value
-@code{PTHREAD_CANCELED} is provided to whichever thread calls
-@var{pthread_join} on it. See @code{pthread_exit} for more information.
-
-Cancellation points are the points where the thread checks for pending
-cancellation requests and performs them. The POSIX threads functions
-@code{pthread_join}, @code{pthread_cond_wait},
-@code{pthread_cond_timedwait}, @code{pthread_testcancel},
-@code{sem_wait}, and @code{sigwait} are cancellation points. In
-addition, these system calls are cancellation points:
-
-@multitable @columnfractions .33 .33 .33
-@item @t{accept} @tab @t{open} @tab @t{sendmsg}
-@item @t{close} @tab @t{pause} @tab @t{sendto}
-@item @t{connect} @tab @t{read} @tab @t{system}
-@item @t{fcntl} @tab @t{recv} @tab @t{tcdrain}
-@item @t{fsync} @tab @t{recvfrom} @tab @t{wait}
-@item @t{lseek} @tab @t{recvmsg} @tab @t{waitpid}
-@item @t{msync} @tab @t{send} @tab @t{write}
-@item @t{nanosleep}
-@end multitable
-
-@noindent
-All library functions that call these functions (such as
-@code{printf}) are also cancellation points.
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_setcancelstate (int @var{state}, int *@var{oldstate})
-@code{pthread_setcancelstate} changes the cancellation state for the
-calling thread -- that is, whether cancellation requests are ignored or
-not. The @var{state} argument is the new cancellation state: either
-@code{PTHREAD_CANCEL_ENABLE} to enable cancellation, or
-@code{PTHREAD_CANCEL_DISABLE} to disable cancellation (cancellation
-requests are ignored).
-
-If @var{oldstate} is not @code{NULL}, the previous cancellation state is
-stored in the location pointed to by @var{oldstate}, and can thus be
-restored later by another call to @code{pthread_setcancelstate}.
-
-If the @var{state} argument is not @code{PTHREAD_CANCEL_ENABLE} or
-@code{PTHREAD_CANCEL_DISABLE}, @code{pthread_setcancelstate} fails and
-returns @code{EINVAL}. Otherwise it returns 0.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_setcanceltype (int @var{type}, int *@var{oldtype})
-@code{pthread_setcanceltype} changes the type of responses to
-cancellation requests for the calling thread: asynchronous (immediate)
-or deferred. The @var{type} argument is the new cancellation type:
-either @code{PTHREAD_CANCEL_ASYNCHRONOUS} to cancel the calling thread
-as soon as the cancellation request is received, or
-@code{PTHREAD_CANCEL_DEFERRED} to keep the cancellation request pending
-until the next cancellation point. If @var{oldtype} is not @code{NULL},
-the previous cancellation state is stored in the location pointed to by
-@var{oldtype}, and can thus be restored later by another call to
-@code{pthread_setcanceltype}.
-
-If the @var{type} argument is not @code{PTHREAD_CANCEL_DEFERRED} or
-@code{PTHREAD_CANCEL_ASYNCHRONOUS}, @code{pthread_setcanceltype} fails
-and returns @code{EINVAL}. Otherwise it returns 0.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun void pthread_testcancel (@var{void})
-@code{pthread_testcancel} does nothing except testing for pending
-cancellation and executing it. Its purpose is to introduce explicit
-checks for cancellation in long sequences of code that do not call
-cancellation point functions otherwise.
-@end deftypefun
-
-@node Cleanup Handlers
-@section Cleanup Handlers
-
-Cleanup handlers are functions that get called when a thread terminates,
-either by calling @code{pthread_exit} or because of
-cancellation. Cleanup handlers are installed and removed following a
-stack-like discipline.
-
-The purpose of cleanup handlers is to free the resources that a thread
-may hold at the time it terminates. In particular, if a thread exits or
-is canceled while it owns a locked mutex, the mutex will remain locked
-forever and prevent other threads from executing normally. The best way
-to avoid this is, just before locking the mutex, to install a cleanup
-handler whose effect is to unlock the mutex. Cleanup handlers can be
-used similarly to free blocks allocated with @code{malloc} or close file
-descriptors on thread termination.
-
-Here is how to lock a mutex @var{mut} in such a way that it will be
-unlocked if the thread is canceled while @var{mut} is locked:
-
-@smallexample
-pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
-pthread_mutex_lock(&mut);
-/* do some work */
-pthread_mutex_unlock(&mut);
-pthread_cleanup_pop(0);
-@end smallexample
-
-Equivalently, the last two lines can be replaced by
-
-@smallexample
-pthread_cleanup_pop(1);
-@end smallexample
-
-Notice that the code above is safe only in deferred cancellation mode
-(see @code{pthread_setcanceltype}). In asynchronous cancellation mode, a
-cancellation can occur between @code{pthread_cleanup_push} and
-@code{pthread_mutex_lock}, or between @code{pthread_mutex_unlock} and
-@code{pthread_cleanup_pop}, resulting in both cases in the thread trying
-to unlock a mutex not locked by the current thread. This is the main
-reason why asynchronous cancellation is difficult to use.
-
-If the code above must also work in asynchronous cancellation mode,
-then it must switch to deferred mode for locking and unlocking the
-mutex:
-
-@smallexample
-pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
-pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
-pthread_mutex_lock(&mut);
-/* do some work */
-pthread_cleanup_pop(1);
-pthread_setcanceltype(oldtype, NULL);
-@end smallexample
-
-The code above can be rewritten in a more compact and efficient way,
-using the non-portable functions @code{pthread_cleanup_push_defer_np}
-and @code{pthread_cleanup_pop_restore_np}:
-
-@smallexample
-pthread_cleanup_push_defer_np(pthread_mutex_unlock, (void *) &mut);
-pthread_mutex_lock(&mut);
-/* do some work */
-pthread_cleanup_pop_restore_np(1);
-@end smallexample
-
-@comment pthread.h
-@comment POSIX
-@deftypefun void pthread_cleanup_push (void (*@var{routine}) (void *), void *@var{arg})
-
-@code{pthread_cleanup_push} installs the @var{routine} function with
-argument @var{arg} as a cleanup handler. From this point on to the
-matching @code{pthread_cleanup_pop}, the function @var{routine} will be
-called with arguments @var{arg} when the thread terminates, either
-through @code{pthread_exit} or by cancellation. If several cleanup
-handlers are active at that point, they are called in LIFO order: the
-most recently installed handler is called first.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun void pthread_cleanup_pop (int @var{execute})
-@code{pthread_cleanup_pop} removes the most recently installed cleanup
-handler. If the @var{execute} argument is not 0, it also executes the
-handler, by calling the @var{routine} function with arguments
-@var{arg}. If the @var{execute} argument is 0, the handler is only
-removed but not executed.
-@end deftypefun
-
-Matching pairs of @code{pthread_cleanup_push} and
-@code{pthread_cleanup_pop} must occur in the same function, at the same
-level of block nesting. Actually, @code{pthread_cleanup_push} and
-@code{pthread_cleanup_pop} are macros, and the expansion of
-@code{pthread_cleanup_push} introduces an open brace @code{@{} with the
-matching closing brace @code{@}} being introduced by the expansion of the
-matching @code{pthread_cleanup_pop}.
-
-@comment pthread.h
-@comment GNU
-@deftypefun void pthread_cleanup_push_defer_np (void (*@var{routine}) (void *), void *@var{arg})
-@code{pthread_cleanup_push_defer_np} is a non-portable extension that
-combines @code{pthread_cleanup_push} and @code{pthread_setcanceltype}.
-It pushes a cleanup handler just as @code{pthread_cleanup_push} does,
-but also saves the current cancellation type and sets it to deferred
-cancellation. This ensures that the cleanup mechanism is effective even
-if the thread was initially in asynchronous cancellation mode.
-@end deftypefun
-
-@comment pthread.h
-@comment GNU
-@deftypefun void pthread_cleanup_pop_restore_np (int @var{execute})
-@code{pthread_cleanup_pop_restore_np} pops a cleanup handler introduced
-by @code{pthread_cleanup_push_defer_np}, and restores the cancellation
-type to its value at the time @code{pthread_cleanup_push_defer_np} was
-called.
-@end deftypefun
-
-@code{pthread_cleanup_push_defer_np} and
-@code{pthread_cleanup_pop_restore_np} must occur in matching pairs, at
-the same level of block nesting.
-
-The sequence
-
-@smallexample
-pthread_cleanup_push_defer_np(routine, arg);
-...
-pthread_cleanup_pop_restore_np(execute);
-@end smallexample
-
-@noindent
-is functionally equivalent to (but more compact and efficient than)
-
-@smallexample
-@{
- int oldtype;
- pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
- pthread_cleanup_push(routine, arg);
- ...
- pthread_cleanup_pop(execute);
- pthread_setcanceltype(oldtype, NULL);
-@}
-@end smallexample
-
-
-@node Mutexes
-@section Mutexes
-
-A mutex is a MUTual EXclusion device, and is useful for protecting
-shared data structures from concurrent modifications, and implementing
-critical sections and monitors.
-
-A mutex has two possible states: unlocked (not owned by any thread),
-and locked (owned by one thread). A mutex can never be owned by two
-different threads simultaneously. A thread attempting to lock a mutex
-that is already locked by another thread is suspended until the owning
-thread unlocks the mutex first.
-
-None of the mutex functions is a cancellation point, not even
-@code{pthread_mutex_lock}, in spite of the fact that it can suspend a
-thread for arbitrary durations. This way, the status of mutexes at
-cancellation points is predictable, allowing cancellation handlers to
-unlock precisely those mutexes that need to be unlocked before the
-thread stops executing. Consequently, threads using deferred
-cancellation should never hold a mutex for extended periods of time.
-
-It is not safe to call mutex functions from a signal handler. In
-particular, calling @code{pthread_mutex_lock} or
-@code{pthread_mutex_unlock} from a signal handler may deadlock the
-calling thread.
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_mutex_init (pthread_mutex_t *@var{mutex}, const pthread_mutexattr_t *@var{mutexattr})
-
-@code{pthread_mutex_init} initializes the mutex object pointed to by
-@var{mutex} according to the mutex attributes specified in @var{mutexattr}.
-If @var{mutexattr} is @code{NULL}, default attributes are used instead.
-
-The LinuxThreads implementation supports only one mutex attribute,
-the @var{mutex type}, which is either ``fast'', ``recursive'', or
-``error checking''. The type of a mutex determines whether
-it can be locked again by a thread that already owns it.
-The default type is ``fast''.
-
-Variables of type @code{pthread_mutex_t} can also be initialized
-statically, using the constants @code{PTHREAD_MUTEX_INITIALIZER} (for
-timed mutexes), @code{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} (for
-recursive mutexes), @code{PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP}
-(for fast mutexes(, and @code{PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP}
-(for error checking mutexes).
-
-@code{pthread_mutex_init} always returns 0.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_mutex_lock (pthread_mutex_t *mutex))
-@code{pthread_mutex_lock} locks the given mutex. If the mutex is
-currently unlocked, it becomes locked and owned by the calling thread,
-and @code{pthread_mutex_lock} returns immediately. If the mutex is
-already locked by another thread, @code{pthread_mutex_lock} suspends the
-calling thread until the mutex is unlocked.
-
-If the mutex is already locked by the calling thread, the behavior of
-@code{pthread_mutex_lock} depends on the type of the mutex. If the mutex
-is of the ``fast'' type, the calling thread is suspended. It will
-remain suspended forever, because no other thread can unlock the mutex.
-If the mutex is of the ``error checking'' type, @code{pthread_mutex_lock}
-returns immediately with the error code @code{EDEADLK}. If the mutex is
-of the ``recursive'' type, @code{pthread_mutex_lock} succeeds and
-returns immediately, recording the number of times the calling thread
-has locked the mutex. An equal number of @code{pthread_mutex_unlock}
-operations must be performed before the mutex returns to the unlocked
-state.
-@c This doesn't discuss PTHREAD_MUTEX_TIMED_NP mutex attributes. FIXME
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_mutex_trylock (pthread_mutex_t *@var{mutex})
-@code{pthread_mutex_trylock} behaves identically to
-@code{pthread_mutex_lock}, except that it does not block the calling
-thread if the mutex is already locked by another thread (or by the
-calling thread in the case of a ``fast'' mutex). Instead,
-@code{pthread_mutex_trylock} returns immediately with the error code
-@code{EBUSY}.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_mutex_timedlock (pthread_mutex_t *@var{mutex}, const struct timespec *@var{abstime})
-The @code{pthread_mutex_timedlock} is similar to the
-@code{pthread_mutex_lock} function but instead of blocking for in
-indefinite time if the mutex is locked by another thread, it returns
-when the time specified in @var{abstime} is reached.
-
-This function can only be used on standard (``timed'') and ``error
-checking'' mutexes. It behaves just like @code{pthread_mutex_lock} for
-all other types.
-
-If the mutex is successfully locked, the function returns zero. If the
-time specified in @var{abstime} is reached without the mutex being locked,
-@code{ETIMEDOUT} is returned.
-
-This function was introduced in the POSIX.1d revision of the POSIX standard.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_mutex_unlock (pthread_mutex_t *@var{mutex})
-@code{pthread_mutex_unlock} unlocks the given mutex. The mutex is
-assumed to be locked and owned by the calling thread on entrance to
-@code{pthread_mutex_unlock}. If the mutex is of the ``fast'' type,
-@code{pthread_mutex_unlock} always returns it to the unlocked state. If
-it is of the ``recursive'' type, it decrements the locking count of the
-mutex (number of @code{pthread_mutex_lock} operations performed on it by
-the calling thread), and only when this count reaches zero is the mutex
-actually unlocked.
-
-On ``error checking'' mutexes, @code{pthread_mutex_unlock} actually
-checks at run-time that the mutex is locked on entrance, and that it was
-locked by the same thread that is now calling
-@code{pthread_mutex_unlock}. If these conditions are not met,
-@code{pthread_mutex_unlock} returns @code{EPERM}, and the mutex remains
-unchanged. ``Fast'' and ``recursive'' mutexes perform no such checks,
-thus allowing a locked mutex to be unlocked by a thread other than its
-owner. This is non-portable behavior and must not be relied upon.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_mutex_destroy (pthread_mutex_t *@var{mutex})
-@code{pthread_mutex_destroy} destroys a mutex object, freeing the
-resources it might hold. The mutex must be unlocked on entrance. In the
-LinuxThreads implementation, no resources are associated with mutex
-objects, thus @code{pthread_mutex_destroy} actually does nothing except
-checking that the mutex is unlocked.
-
-If the mutex is locked by some thread, @code{pthread_mutex_destroy}
-returns @code{EBUSY}. Otherwise it returns 0.
-@end deftypefun
-
-If any of the above functions (except @code{pthread_mutex_init})
-is applied to an uninitialized mutex, they will simply return
-@code{EINVAL} and do nothing.
-
-A shared global variable @var{x} can be protected by a mutex as follows:
-
-@smallexample
-int x;
-pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
-@end smallexample
-
-All accesses and modifications to @var{x} should be bracketed by calls to
-@code{pthread_mutex_lock} and @code{pthread_mutex_unlock} as follows:
-
-@smallexample
-pthread_mutex_lock(&mut);
-/* operate on x */
-pthread_mutex_unlock(&mut);
-@end smallexample
-
-Mutex attributes can be specified at mutex creation time, by passing a
-mutex attribute object as second argument to @code{pthread_mutex_init}.
-Passing @code{NULL} is equivalent to passing a mutex attribute object
-with all attributes set to their default values.
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_mutexattr_init (pthread_mutexattr_t *@var{attr})
-@code{pthread_mutexattr_init} initializes the mutex attribute object
-@var{attr} and fills it with default values for the attributes.
-
-This function always returns 0.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_mutexattr_destroy (pthread_mutexattr_t *@var{attr})
-@code{pthread_mutexattr_destroy} destroys a mutex attribute object,
-which must not be reused until it is
-reinitialized. @code{pthread_mutexattr_destroy} does nothing in the
-LinuxThreads implementation.
-
-This function always returns 0.
-@end deftypefun
-
-LinuxThreads supports only one mutex attribute: the mutex type, which is
-either @code{PTHREAD_MUTEX_ADAPTIVE_NP} for ``fast'' mutexes,
-@code{PTHREAD_MUTEX_RECURSIVE_NP} for ``recursive'' mutexes,
-@code{PTHREAD_MUTEX_TIMED_NP} for ``timed'' mutexes, or
-@code{PTHREAD_MUTEX_ERRORCHECK_NP} for ``error checking'' mutexes. As
-the @code{NP} suffix indicates, this is a non-portable extension to the
-POSIX standard and should not be employed in portable programs.
-
-The mutex type determines what happens if a thread attempts to lock a
-mutex it already owns with @code{pthread_mutex_lock}. If the mutex is of
-the ``fast'' type, @code{pthread_mutex_lock} simply suspends the calling
-thread forever. If the mutex is of the ``error checking'' type,
-@code{pthread_mutex_lock} returns immediately with the error code
-@code{EDEADLK}. If the mutex is of the ``recursive'' type, the call to
-@code{pthread_mutex_lock} returns immediately with a success return
-code. The number of times the thread owning the mutex has locked it is
-recorded in the mutex. The owning thread must call
-@code{pthread_mutex_unlock} the same number of times before the mutex
-returns to the unlocked state.
-
-The default mutex type is ``timed'', that is, @code{PTHREAD_MUTEX_TIMED_NP}.
-@c This doesn't describe how a ``timed'' mutex behaves. FIXME
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_mutexattr_settype (pthread_mutexattr_t *@var{attr}, int @var{type})
-@code{pthread_mutexattr_settype} sets the mutex type attribute in
-@var{attr} to the value specified by @var{type}.
-
-If @var{type} is not @code{PTHREAD_MUTEX_ADAPTIVE_NP},
-@code{PTHREAD_MUTEX_RECURSIVE_NP}, @code{PTHREAD_MUTEX_TIMED_NP}, or
-@code{PTHREAD_MUTEX_ERRORCHECK_NP}, this function will return
-@code{EINVAL} and leave @var{attr} unchanged.
-
-The standard Unix98 identifiers @code{PTHREAD_MUTEX_DEFAULT},
-@code{PTHREAD_MUTEX_NORMAL}, @code{PTHREAD_MUTEX_RECURSIVE},
-and @code{PTHREAD_MUTEX_ERRORCHECK} are also permitted.
-
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_mutexattr_gettype (const pthread_mutexattr_t *@var{attr}, int *@var{type})
-@code{pthread_mutexattr_gettype} retrieves the current value of the
-mutex type attribute in @var{attr} and stores it in the location pointed
-to by @var{type}.
-
-This function always returns 0.
-@end deftypefun
-
-@node Condition Variables
-@section Condition Variables
-
-A condition (short for ``condition variable'') is a synchronization
-device that allows threads to suspend execution until some predicate on
-shared data is satisfied. The basic operations on conditions are: signal
-the condition (when the predicate becomes true), and wait for the
-condition, suspending the thread execution until another thread signals
-the condition.
-
-A condition variable must always be associated with a mutex, to avoid
-the race condition where a thread prepares to wait on a condition
-variable and another thread signals the condition just before the first
-thread actually waits on it.
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_cond_init (pthread_cond_t *@var{cond}, pthread_condattr_t *cond_@var{attr})
-
-@code{pthread_cond_init} initializes the condition variable @var{cond},
-using the condition attributes specified in @var{cond_attr}, or default
-attributes if @var{cond_attr} is @code{NULL}. The LinuxThreads
-implementation supports no attributes for conditions, hence the
-@var{cond_attr} parameter is actually ignored.
-
-Variables of type @code{pthread_cond_t} can also be initialized
-statically, using the constant @code{PTHREAD_COND_INITIALIZER}.
-
-This function always returns 0.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_cond_signal (pthread_cond_t *@var{cond})
-@code{pthread_cond_signal} restarts one of the threads that are waiting
-on the condition variable @var{cond}. If no threads are waiting on
-@var{cond}, nothing happens. If several threads are waiting on
-@var{cond}, exactly one is restarted, but it is not specified which.
-
-This function always returns 0.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_cond_broadcast (pthread_cond_t *@var{cond})
-@code{pthread_cond_broadcast} restarts all the threads that are waiting
-on the condition variable @var{cond}. Nothing happens if no threads are
-waiting on @var{cond}.
-
-This function always returns 0.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_cond_wait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex})
-@code{pthread_cond_wait} atomically unlocks the @var{mutex} (as per
-@code{pthread_unlock_mutex}) and waits for the condition variable
-@var{cond} to be signaled. The thread execution is suspended and does
-not consume any CPU time until the condition variable is signaled. The
-@var{mutex} must be locked by the calling thread on entrance to
-@code{pthread_cond_wait}. Before returning to the calling thread,
-@code{pthread_cond_wait} re-acquires @var{mutex} (as per
-@code{pthread_lock_mutex}).
-
-Unlocking the mutex and suspending on the condition variable is done
-atomically. Thus, if all threads always acquire the mutex before
-signaling the condition, this guarantees that the condition cannot be
-signaled (and thus ignored) between the time a thread locks the mutex
-and the time it waits on the condition variable.
-
-This function always returns 0.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_cond_timedwait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex}, const struct timespec *@var{abstime})
-@code{pthread_cond_timedwait} atomically unlocks @var{mutex} and waits
-on @var{cond}, as @code{pthread_cond_wait} does, but it also bounds the
-duration of the wait. If @var{cond} has not been signaled before time
-@var{abstime}, the mutex @var{mutex} is re-acquired and
-@code{pthread_cond_timedwait} returns the error code @code{ETIMEDOUT}.
-The wait can also be interrupted by a signal; in that case
-@code{pthread_cond_timedwait} returns @code{EINTR}.
-
-The @var{abstime} parameter specifies an absolute time, with the same
-origin as @code{time} and @code{gettimeofday}: an @var{abstime} of 0
-corresponds to 00:00:00 GMT, January 1, 1970.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_cond_destroy (pthread_cond_t *@var{cond})
-@code{pthread_cond_destroy} destroys the condition variable @var{cond},
-freeing the resources it might hold. If any threads are waiting on the
-condition variable, @code{pthread_cond_destroy} leaves @var{cond}
-untouched and returns @code{EBUSY}. Otherwise it returns 0, and
-@var{cond} must not be used again until it is reinitialized.
-
-In the LinuxThreads implementation, no resources are associated with
-condition variables, so @code{pthread_cond_destroy} actually does
-nothing.
-@end deftypefun
-
-@code{pthread_cond_wait} and @code{pthread_cond_timedwait} are
-cancellation points. If a thread is canceled while suspended in one of
-these functions, the thread immediately resumes execution, relocks the
-mutex specified by @var{mutex}, and finally executes the cancellation.
-Consequently, cleanup handlers are assured that @var{mutex} is locked
-when they are called.
-
-It is not safe to call the condition variable functions from a signal
-handler. In particular, calling @code{pthread_cond_signal} or
-@code{pthread_cond_broadcast} from a signal handler may deadlock the
-calling thread.
-
-Consider two shared variables @var{x} and @var{y}, protected by the
-mutex @var{mut}, and a condition variable @var{cond} that is to be
-signaled whenever @var{x} becomes greater than @var{y}.
-
-@smallexample
-int x,y;
-pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
-pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
-@end smallexample
-
-Waiting until @var{x} is greater than @var{y} is performed as follows:
-
-@smallexample
-pthread_mutex_lock(&mut);
-while (x <= y) @{
- pthread_cond_wait(&cond, &mut);
-@}
-/* operate on x and y */
-pthread_mutex_unlock(&mut);
-@end smallexample
-
-Modifications on @var{x} and @var{y} that may cause @var{x} to become greater than
-@var{y} should signal the condition if needed:
-
-@smallexample
-pthread_mutex_lock(&mut);
-/* modify x and y */
-if (x > y) pthread_cond_broadcast(&cond);
-pthread_mutex_unlock(&mut);
-@end smallexample
-
-If it can be proved that at most one waiting thread needs to be waken
-up (for instance, if there are only two threads communicating through
-@var{x} and @var{y}), @code{pthread_cond_signal} can be used as a slightly more
-efficient alternative to @code{pthread_cond_broadcast}. In doubt, use
-@code{pthread_cond_broadcast}.
-
-To wait for @var{x} to becomes greater than @var{y} with a timeout of 5
-seconds, do:
-
-@smallexample
-struct timeval now;
-struct timespec timeout;
-int retcode;
-
-pthread_mutex_lock(&mut);
-gettimeofday(&now);
-timeout.tv_sec = now.tv_sec + 5;
-timeout.tv_nsec = now.tv_usec * 1000;
-retcode = 0;
-while (x <= y && retcode != ETIMEDOUT) @{
- retcode = pthread_cond_timedwait(&cond, &mut, &timeout);
-@}
-if (retcode == ETIMEDOUT) @{
- /* timeout occurred */
-@} else @{
- /* operate on x and y */
-@}
-pthread_mutex_unlock(&mut);
-@end smallexample
-
-Condition attributes can be specified at condition creation time, by
-passing a condition attribute object as second argument to
-@code{pthread_cond_init}. Passing @code{NULL} is equivalent to passing
-a condition attribute object with all attributes set to their default
-values.
-
-The LinuxThreads implementation supports no attributes for
-conditions. The functions on condition attributes are included only for
-compliance with the POSIX standard.
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_condattr_init (pthread_condattr_t *@var{attr})
-@deftypefunx int pthread_condattr_destroy (pthread_condattr_t *@var{attr})
-@code{pthread_condattr_init} initializes the condition attribute object
-@var{attr} and fills it with default values for the attributes.
-@code{pthread_condattr_destroy} destroys the condition attribute object
-@var{attr}.
-
-Both functions do nothing in the LinuxThreads implementation.
-
-@code{pthread_condattr_init} and @code{pthread_condattr_destroy} always
-return 0.
-@end deftypefun
-
-@node POSIX Semaphores
-@section POSIX Semaphores
-
-@vindex SEM_VALUE_MAX
-Semaphores are counters for resources shared between threads. The
-basic operations on semaphores are: increment the counter atomically,
-and wait until the counter is non-null and decrement it atomically.
-
-Semaphores have a maximum value past which they cannot be incremented.
-The macro @code{SEM_VALUE_MAX} is defined to be this maximum value. In
-the GNU C library, @code{SEM_VALUE_MAX} is equal to @code{INT_MAX}
-(@pxref{Range of Type}), but it may be much smaller on other systems.
-
-The pthreads library implements POSIX 1003.1b semaphores. These should
-not be confused with System V semaphores (@code{ipc}, @code{semctl} and
-@code{semop}).
-@c !!! SysV IPC is not doc'd at all in our manual
-
-All the semaphore functions and macros are defined in @file{semaphore.h}.
-
-@comment semaphore.h
-@comment POSIX
-@deftypefun int sem_init (sem_t *@var{sem}, int @var{pshared}, unsigned int @var{value})
-@code{sem_init} initializes the semaphore object pointed to by
-@var{sem}. The count associated with the semaphore is set initially to
-@var{value}. The @var{pshared} argument indicates whether the semaphore
-is local to the current process (@var{pshared} is zero) or is to be
-shared between several processes (@var{pshared} is not zero).
-
-On success @code{sem_init} returns 0. On failure it returns -1 and sets
-@var{errno} to one of the following values:
-
-@table @code
-@item EINVAL
-@var{value} exceeds the maximal counter value @code{SEM_VALUE_MAX}
-
-@item ENOSYS
-@var{pshared} is not zero. LinuxThreads currently does not support
-process-shared semaphores. (This will eventually change.)
-@end table
-@end deftypefun
-
-@comment semaphore.h
-@comment POSIX
-@deftypefun int sem_destroy (sem_t * @var{sem})
-@code{sem_destroy} destroys a semaphore object, freeing the resources it
-might hold. If any threads are waiting on the semaphore when
-@code{sem_destroy} is called, it fails and sets @var{errno} to
-@code{EBUSY}.
-
-In the LinuxThreads implementation, no resources are associated with
-semaphore objects, thus @code{sem_destroy} actually does nothing except
-checking that no thread is waiting on the semaphore. This will change
-when process-shared semaphores are implemented.
-@end deftypefun
-
-@comment semaphore.h
-@comment POSIX
-@deftypefun int sem_wait (sem_t * @var{sem})
-@code{sem_wait} suspends the calling thread until the semaphore pointed
-to by @var{sem} has non-zero count. It then atomically decreases the
-semaphore count.
-
-@code{sem_wait} is a cancellation point. It always returns 0.
-@end deftypefun
-
-@comment semaphore.h
-@comment POSIX
-@deftypefun int sem_trywait (sem_t * @var{sem})
-@code{sem_trywait} is a non-blocking variant of @code{sem_wait}. If the
-semaphore pointed to by @var{sem} has non-zero count, the count is
-atomically decreased and @code{sem_trywait} immediately returns 0. If
-the semaphore count is zero, @code{sem_trywait} immediately returns -1
-and sets errno to @code{EAGAIN}.
-@end deftypefun
-
-@comment semaphore.h
-@comment POSIX
-@deftypefun int sem_post (sem_t * @var{sem})
-@code{sem_post} atomically increases the count of the semaphore pointed to
-by @var{sem}. This function never blocks.
-
-@c !!! This para appears not to agree with the code.
-On processors supporting atomic compare-and-swap (Intel 486, Pentium and
-later, Alpha, PowerPC, MIPS II, Motorola 68k, Ultrasparc), the
-@code{sem_post} function is can safely be called from signal handlers.
-This is the only thread synchronization function provided by POSIX
-threads that is async-signal safe. On the Intel 386 and earlier Sparc
-chips, the current LinuxThreads implementation of @code{sem_post} is not
-async-signal safe, because the hardware does not support the required
-atomic operations.
-
-@code{sem_post} always succeeds and returns 0, unless the semaphore
-count would exceed @code{SEM_VALUE_MAX} after being incremented. In
-that case @code{sem_post} returns -1 and sets @var{errno} to
-@code{EINVAL}. The semaphore count is left unchanged.
-@end deftypefun
-
-@comment semaphore.h
-@comment POSIX
-@deftypefun int sem_getvalue (sem_t * @var{sem}, int * @var{sval})
-@code{sem_getvalue} stores in the location pointed to by @var{sval} the
-current count of the semaphore @var{sem}. It always returns 0.
-@end deftypefun
-
-@node Thread-Specific Data
-@section Thread-Specific Data
-
-Programs often need global or static variables that have different
-values in different threads. Since threads share one memory space, this
-cannot be achieved with regular variables. Thread-specific data is the
-POSIX threads answer to this need.
-
-Each thread possesses a private memory block, the thread-specific data
-area, or TSD area for short. This area is indexed by TSD keys. The TSD
-area associates values of type @code{void *} to TSD keys. TSD keys are
-common to all threads, but the value associated with a given TSD key can
-be different in each thread.
-
-For concreteness, the TSD areas can be viewed as arrays of @code{void *}
-pointers, TSD keys as integer indices into these arrays, and the value
-of a TSD key as the value of the corresponding array element in the
-calling thread.
-
-When a thread is created, its TSD area initially associates @code{NULL}
-with all keys.
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_key_create (pthread_key_t *@var{key}, void (*destr_function) (void *))
-@code{pthread_key_create} allocates a new TSD key. The key is stored in
-the location pointed to by @var{key}. There is a limit of
-@code{PTHREAD_KEYS_MAX} on the number of keys allocated at a given
-time. The value initially associated with the returned key is
-@code{NULL} in all currently executing threads.
-
-The @var{destr_function} argument, if not @code{NULL}, specifies a
-destructor function associated with the key. When a thread terminates
-via @code{pthread_exit} or by cancellation, @var{destr_function} is
-called on the value associated with the key in that thread. The
-@var{destr_function} is not called if a key is deleted with
-@code{pthread_key_delete} or a value is changed with
-@code{pthread_setspecific}. The order in which destructor functions are
-called at thread termination time is unspecified.
-
-Before the destructor function is called, the @code{NULL} value is
-associated with the key in the current thread. A destructor function
-might, however, re-associate non-@code{NULL} values to that key or some
-other key. To deal with this, if after all the destructors have been
-called for all non-@code{NULL} values, there are still some
-non-@code{NULL} values with associated destructors, then the process is
-repeated. The LinuxThreads implementation stops the process after
-@code{PTHREAD_DESTRUCTOR_ITERATIONS} iterations, even if some
-non-@code{NULL} values with associated descriptors remain. Other
-implementations may loop indefinitely.
-
-@code{pthread_key_create} returns 0 unless @code{PTHREAD_KEYS_MAX} keys
-have already been allocated, in which case it fails and returns
-@code{EAGAIN}.
-@end deftypefun
-
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_key_delete (pthread_key_t @var{key})
-@code{pthread_key_delete} deallocates a TSD key. It does not check
-whether non-@code{NULL} values are associated with that key in the
-currently executing threads, nor call the destructor function associated
-with the key.
-
-If there is no such key @var{key}, it returns @code{EINVAL}. Otherwise
-it returns 0.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_setspecific (pthread_key_t @var{key}, const void *@var{pointer})
-@code{pthread_setspecific} changes the value associated with @var{key}
-in the calling thread, storing the given @var{pointer} instead.
-
-If there is no such key @var{key}, it returns @code{EINVAL}. Otherwise
-it returns 0.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun {void *} pthread_getspecific (pthread_key_t @var{key})
-@code{pthread_getspecific} returns the value currently associated with
-@var{key} in the calling thread.
-
-If there is no such key @var{key}, it returns @code{NULL}.
-@end deftypefun
-
-The following code fragment allocates a thread-specific array of 100
-characters, with automatic reclaimation at thread exit:
-
-@smallexample
-/* Key for the thread-specific buffer */
-static pthread_key_t buffer_key;
-
-/* Once-only initialisation of the key */
-static pthread_once_t buffer_key_once = PTHREAD_ONCE_INIT;
-
-/* Allocate the thread-specific buffer */
-void buffer_alloc(void)
-@{
- pthread_once(&buffer_key_once, buffer_key_alloc);
- pthread_setspecific(buffer_key, malloc(100));
-@}
-
-/* Return the thread-specific buffer */
-char * get_buffer(void)
-@{
- return (char *) pthread_getspecific(buffer_key);
-@}
-
-/* Allocate the key */
-static void buffer_key_alloc()
-@{
- pthread_key_create(&buffer_key, buffer_destroy);
-@}
-
-/* Free the thread-specific buffer */
-static void buffer_destroy(void * buf)
-@{
- free(buf);
-@}
-@end smallexample
-
-@node Threads and Signal Handling
-@section Threads and Signal Handling
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_sigmask (int @var{how}, const sigset_t *@var{newmask}, sigset_t *@var{oldmask})
-@code{pthread_sigmask} changes the signal mask for the calling thread as
-described by the @var{how} and @var{newmask} arguments. If @var{oldmask}
-is not @code{NULL}, the previous signal mask is stored in the location
-pointed to by @var{oldmask}.
-
-The meaning of the @var{how} and @var{newmask} arguments is the same as
-for @code{sigprocmask}. If @var{how} is @code{SIG_SETMASK}, the signal
-mask is set to @var{newmask}. If @var{how} is @code{SIG_BLOCK}, the
-signals specified to @var{newmask} are added to the current signal mask.
-If @var{how} is @code{SIG_UNBLOCK}, the signals specified to
-@var{newmask} are removed from the current signal mask.
-
-Recall that signal masks are set on a per-thread basis, but signal
-actions and signal handlers, as set with @code{sigaction}, are shared
-between all threads.
-
-The @code{pthread_sigmask} function returns 0 on success, and one of the
-following error codes on error:
-@table @code
-@item EINVAL
-@var{how} is not one of @code{SIG_SETMASK}, @code{SIG_BLOCK}, or @code{SIG_UNBLOCK}
-
-@item EFAULT
-@var{newmask} or @var{oldmask} point to invalid addresses
-@end table
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_kill (pthread_t @var{thread}, int @var{signo})
-@code{pthread_kill} sends signal number @var{signo} to the thread
-@var{thread}. The signal is delivered and handled as described in
-@ref{Signal Handling}.
-
-@code{pthread_kill} returns 0 on success, one of the following error codes
-on error:
-@table @code
-@item EINVAL
-@var{signo} is not a valid signal number
-
-@item ESRCH
-The thread @var{thread} does not exist (e.g. it has already terminated)
-@end table
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int sigwait (const sigset_t *@var{set}, int *@var{sig})
-@code{sigwait} suspends the calling thread until one of the signals in
-@var{set} is delivered to the calling thread. It then stores the number
-of the signal received in the location pointed to by @var{sig} and
-returns. The signals in @var{set} must be blocked and not ignored on
-entrance to @code{sigwait}. If the delivered signal has a signal handler
-function attached, that function is @emph{not} called.
-
-@code{sigwait} is a cancellation point. It always returns 0.
-@end deftypefun
-
-For @code{sigwait} to work reliably, the signals being waited for must be
-blocked in all threads, not only in the calling thread, since
-otherwise the POSIX semantics for signal delivery do not guarantee
-that it's the thread doing the @code{sigwait} that will receive the signal.
-The best way to achieve this is block those signals before any threads
-are created, and never unblock them in the program other than by
-calling @code{sigwait}.
-
-Signal handling in LinuxThreads departs significantly from the POSIX
-standard. According to the standard, ``asynchronous'' (external) signals
-are addressed to the whole process (the collection of all threads),
-which then delivers them to one particular thread. The thread that
-actually receives the signal is any thread that does not currently block
-the signal.
-
-In LinuxThreads, each thread is actually a kernel process with its own
-PID, so external signals are always directed to one particular thread.
-If, for instance, another thread is blocked in @code{sigwait} on that
-signal, it will not be restarted.
-
-The LinuxThreads implementation of @code{sigwait} installs dummy signal
-handlers for the signals in @var{set} for the duration of the
-wait. Since signal handlers are shared between all threads, other
-threads must not attach their own signal handlers to these signals, or
-alternatively they should all block these signals (which is recommended
-anyway).
-
-@node Threads and Fork
-@section Threads and Fork
-
-It's not intuitively obvious what should happen when a multi-threaded POSIX
-process calls @code{fork}. Not only are the semantics tricky, but you may
-need to write code that does the right thing at fork time even if that code
-doesn't use the @code{fork} function. Moreover, you need to be aware of
-interaction between @code{fork} and some library features like
-@code{pthread_once} and stdio streams.
-
-When @code{fork} is called by one of the threads of a process, it creates a new
-process which is copy of the calling process. Effectively, in addition to
-copying certain system objects, the function takes a snapshot of the memory
-areas of the parent process, and creates identical areas in the child.
-To make matters more complicated, with threads it's possible for two or more
-threads to concurrently call fork to create two or more child processes.
-
-The child process has a copy of the address space of the parent, but it does
-not inherit any of its threads. Execution of the child process is carried out
-by a new thread which returns from @code{fork} function with a return value of
-zero; it is the only thread in the child process. Because threads are not
-inherited across fork, issues arise. At the time of the call to @code{fork},
-threads in the parent process other than the one calling @code{fork} may have
-been executing critical regions of code. As a result, the child process may
-get a copy of objects that are not in a well-defined state. This potential
-problem affects all components of the program.
-
-Any program component which will continue being used in a child process must
-correctly handle its state during @code{fork}. For this purpose, the POSIX
-interface provides the special function @code{pthread_atfork} for installing
-pointers to handler functions which are called from within @code{fork}.
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_atfork (void (*@var{prepare})(void), void (*@var{parent})(void), void (*@var{child})(void))
-
-@code{pthread_atfork} registers handler functions to be called just
-before and just after a new process is created with @code{fork}. The
-@var{prepare} handler will be called from the parent process, just
-before the new process is created. The @var{parent} handler will be
-called from the parent process, just before @code{fork} returns. The
-@var{child} handler will be called from the child process, just before
-@code{fork} returns.
-
-@code{pthread_atfork} returns 0 on success and a non-zero error code on
-error.
-
-One or more of the three handlers @var{prepare}, @var{parent} and
-@var{child} can be given as @code{NULL}, meaning that no handler needs
-to be called at the corresponding point.
-
-@code{pthread_atfork} can be called several times to install several
-sets of handlers. At @code{fork} time, the @var{prepare} handlers are
-called in LIFO order (last added with @code{pthread_atfork}, first
-called before @code{fork}), while the @var{parent} and @var{child}
-handlers are called in FIFO order (first added, first called).
-
-If there is insufficient memory available to register the handlers,
-@code{pthread_atfork} fails and returns @code{ENOMEM}. Otherwise it
-returns 0.
-
-The functions @code{fork} and @code{pthread_atfork} must not be regarded as
-reentrant from the context of the handlers. That is to say, if a
-@code{pthread_atfork} handler invoked from within @code{fork} calls
-@code{pthread_atfork} or @code{fork}, the behavior is undefined.
-
-Registering a triplet of handlers is an atomic operation with respect to fork.
-If new handlers are registered at about the same time as a fork occurs, either
-all three handlers will be called, or none of them will be called.
-
-The handlers are inherited by the child process, and there is no
-way to remove them, short of using @code{exec} to load a new
-pocess image.
-
-@end deftypefun
-
-To understand the purpose of @code{pthread_atfork}, recall that
-@code{fork} duplicates the whole memory space, including mutexes in
-their current locking state, but only the calling thread: other threads
-are not running in the child process. The mutexes are not usable after
-the @code{fork} and must be initialized with @code{pthread_mutex_init}
-in the child process. This is a limitation of the current
-implementation and might or might not be present in future versions.
-
-To avoid this, install handlers with @code{pthread_atfork} as follows: have the
-@var{prepare} handler lock the mutexes (in locking order), and the
-@var{parent} handler unlock the mutexes. The @var{child} handler should reset
-the mutexes using @code{pthread_mutex_init}, as well as any other
-synchronization objects such as condition variables.
-
-Locking the global mutexes before the fork ensures that all other threads are
-locked out of the critical regions of code protected by those mutexes. Thus
-when @code{fork} takes a snapshot of the parent's address space, that snapshot
-will copy valid, stable data. Resetting the synchronization objects in the
-child process will ensure they are properly cleansed of any artifacts from the
-threading subsystem of the parent process. For example, a mutex may inherit
-a wait queue of threads waiting for the lock; this wait queue makes no sense
-in the child process. Initializing the mutex takes care of this.
-
-@node Streams and Fork
-@section Streams and Fork
-
-The GNU standard I/O library has an internal mutex which guards the internal
-linked list of all standard C FILE objects. This mutex is properly taken care
-of during @code{fork} so that the child receives an intact copy of the list.
-This allows the @code{fopen} function, and related stream-creating functions,
-to work correctly in the child process, since these functions need to insert
-into the list.
-
-However, the individual stream locks are not completely taken care of. Thus
-unless the multithreaded application takes special precautions in its use of
-@code{fork}, the child process might not be able to safely use the streams that
-it inherited from the parent. In general, for any given open stream in the
-parent that is to be used by the child process, the application must ensure
-that that stream is not in use by another thread when @code{fork} is called.
-Otherwise an inconsistent copy of the stream object be produced. An easy way to
-ensure this is to use @code{flockfile} to lock the stream prior to calling
-@code{fork} and then unlock it with @code{funlockfile} inside the parent
-process, provided that the parent's threads properly honor these locks.
-Nothing special needs to be done in the child process, since the library
-internally resets all stream locks.
-
-Note that the stream locks are not shared between the parent and child.
-For example, even if you ensure that, say, the stream @code{stdout} is properly
-treated and can be safely used in the child, the stream locks do not provide
-an exclusion mechanism between the parent and child. If both processes write
-to @code{stdout}, strangely interleaved output may result regardless of
-the explicit use of @code{flockfile} or implicit locks.
-
-Also note that these provisions are a GNU extension; other systems might not
-provide any way for streams to be used in the child of a multithreaded process.
-POSIX requires that such a child process confines itself to calling only
-asynchronous safe functions, which excludes much of the library, including
-standard I/O.
-
-@node Miscellaneous Thread Functions
-@section Miscellaneous Thread Functions
-
-@comment pthread.h
-@comment POSIX
-@deftypefun {pthread_t} pthread_self (@var{void})
-@code{pthread_self} returns the thread identifier for the calling thread.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_equal (pthread_t thread1, pthread_t thread2)
-@code{pthread_equal} determines if two thread identifiers refer to the same
-thread.
-
-A non-zero value is returned if @var{thread1} and @var{thread2} refer to
-the same thread. Otherwise, 0 is returned.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_detach (pthread_t @var{th})
-@code{pthread_detach} puts the thread @var{th} in the detached
-state. This guarantees that the memory resources consumed by @var{th}
-will be freed immediately when @var{th} terminates. However, this
-prevents other threads from synchronizing on the termination of @var{th}
-using @code{pthread_join}.
-
-A thread can be created initially in the detached state, using the
-@code{detachstate} attribute to @code{pthread_create}. In contrast,
-@code{pthread_detach} applies to threads created in the joinable state,
-and which need to be put in the detached state later.
-
-After @code{pthread_detach} completes, subsequent attempts to perform
-@code{pthread_join} on @var{th} will fail. If another thread is already
-joining the thread @var{th} at the time @code{pthread_detach} is called,
-@code{pthread_detach} does nothing and leaves @var{th} in the joinable
-state.
-
-On success, 0 is returned. On error, one of the following codes is
-returned:
-@table @code
-@item ESRCH
-No thread could be found corresponding to that specified by @var{th}
-@item EINVAL
-The thread @var{th} is already in the detached state
-@end table
-@end deftypefun
-
-@comment pthread.h
-@comment GNU
-@deftypefun void pthread_kill_other_threads_np (@var{void})
-@code{pthread_kill_other_threads_np} is a non-portable LinuxThreads extension.
-It causes all threads in the program to terminate immediately, except
-the calling thread which proceeds normally. It is intended to be
-called just before a thread calls one of the @code{exec} functions,
-e.g. @code{execve}.
-
-Termination of the other threads is not performed through
-@code{pthread_cancel} and completely bypasses the cancellation
-mechanism. Hence, the current settings for cancellation state and
-cancellation type are ignored, and the cleanup handlers are not
-executed in the terminated threads.
-
-According to POSIX 1003.1c, a successful @code{exec*} in one of the
-threads should automatically terminate all other threads in the program.
-This behavior is not yet implemented in LinuxThreads. Calling
-@code{pthread_kill_other_threads_np} before @code{exec*} achieves much
-of the same behavior, except that if @code{exec*} ultimately fails, then
-all other threads are already killed.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_once (pthread_once_t *once_@var{control}, void (*@var{init_routine}) (void))
-
-The purpose of @code{pthread_once} is to ensure that a piece of
-initialization code is executed at most once. The @var{once_control}
-argument points to a static or extern variable statically initialized
-to @code{PTHREAD_ONCE_INIT}.
-
-The first time @code{pthread_once} is called with a given
-@var{once_control} argument, it calls @var{init_routine} with no
-argument and changes the value of the @var{once_control} variable to
-record that initialization has been performed. Subsequent calls to
-@code{pthread_once} with the same @code{once_control} argument do
-nothing.
-
-If a thread is cancelled while executing @var{init_routine}
-the state of the @var{once_control} variable is reset so that
-a future call to @code{pthread_once} will call the routine again.
-
-If the process forks while one or more threads are executing
-@code{pthread_once} initialization routines, the states of their respective
-@var{once_control} variables will appear to be reset in the child process so
-that if the child calls @code{pthread_once}, the routines will be executed.
-
-@code{pthread_once} always returns 0.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_setschedparam (pthread_t target_@var{thread}, int @var{policy}, const struct sched_param *@var{param})
-
-@code{pthread_setschedparam} sets the scheduling parameters for the
-thread @var{target_thread} as indicated by @var{policy} and
-@var{param}. @var{policy} can be either @code{SCHED_OTHER} (regular,
-non-realtime scheduling), @code{SCHED_RR} (realtime, round-robin) or
-@code{SCHED_FIFO} (realtime, first-in first-out). @var{param} specifies
-the scheduling priority for the two realtime policies. See
-@code{sched_setpolicy} for more information on scheduling policies.
-
-The realtime scheduling policies @code{SCHED_RR} and @code{SCHED_FIFO}
-are available only to processes with superuser privileges.
-
-On success, @code{pthread_setschedparam} returns 0. On error it returns
-one of the following codes:
-@table @code
-@item EINVAL
-@var{policy} is not one of @code{SCHED_OTHER}, @code{SCHED_RR},
-@code{SCHED_FIFO}, or the priority value specified by @var{param} is not
-valid for the specified policy
-
-@item EPERM
-Realtime scheduling was requested but the calling process does not have
-sufficient privileges.
-
-@item ESRCH
-The @var{target_thread} is invalid or has already terminated
-
-@item EFAULT
-@var{param} points outside the process memory space
-@end table
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_getschedparam (pthread_t target_@var{thread}, int *@var{policy}, struct sched_param *@var{param})
-
-@code{pthread_getschedparam} retrieves the scheduling policy and
-scheduling parameters for the thread @var{target_thread} and stores them
-in the locations pointed to by @var{policy} and @var{param},
-respectively.
-
-@code{pthread_getschedparam} returns 0 on success, or one of the
-following error codes on failure:
-@table @code
-@item ESRCH
-The @var{target_thread} is invalid or has already terminated.
-
-@item EFAULT
-@var{policy} or @var{param} point outside the process memory space.
-
-@end table
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_setconcurrency (int @var{level})
-@code{pthread_setconcurrency} is unused in LinuxThreads due to the lack
-of a mapping of user threads to kernel threads. It exists for source
-compatibility. It does store the value @var{level} so that it can be
-returned by a subsequent call to @code{pthread_getconcurrency}. It takes
-no other action however.
-@end deftypefun
-
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_getconcurrency ()
-@code{pthread_getconcurrency} is unused in LinuxThreads due to the lack
-of a mapping of user threads to kernel threads. It exists for source
-compatibility. However, it will return the value that was set by the
-last call to @code{pthread_setconcurrency}.
-@end deftypefun
diff --git a/libpthread/linuxthreads/locale.c b/libpthread/linuxthreads/locale.c
deleted file mode 100644
index c3ebbc285..000000000
--- a/libpthread/linuxthreads/locale.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Copyright (C) 2003 Manuel Novoa III
- *
- * This 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.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define _GNU_SOURCE
-#include <features.h>
-#include "pthread.h"
-#include "internals.h"
-#include <locale.h>
-#include <assert.h>
-#include <stdlib.h>
-
-extern struct _pthread_descr_struct __pthread_initial_thread;
-
-__locale_t __curlocale(void)
-{
- pthread_descr self = thread_self();
-
-#ifdef NDEBUG
- return THREAD_GETMEM (self, locale);
-#else
- {
- __locale_t r = THREAD_GETMEM (self, locale);
-
- assert(r);
-
- return r;
- }
-#endif
-}
-
-__locale_t __curlocale_set(__locale_t newloc)
-{
- __locale_t oldloc;
- pthread_descr self = thread_self();
-
- oldloc = THREAD_GETMEM (self, locale);
-
- assert(newloc != LC_GLOBAL_LOCALE);
- assert(oldloc);
-
- THREAD_SETMEM (self, locale, newloc);
-
- return oldloc;
-}
diff --git a/libpthread/linuxthreads/lockfile.c b/libpthread/linuxthreads/lockfile.c
deleted file mode 100644
index b0f41c98a..000000000
--- a/libpthread/linuxthreads/lockfile.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* lockfile - Handle locking and unlocking of stream.
- Copyright (C) 1996, 1998, 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; 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 <stdio.h>
-#include <pthread.h>
-
-/* Note: glibc puts flockfile, funlockfile, and ftrylockfile in both
- * libc and libpthread. In uClibc, they are now in libc only. */
-
-void
-__fresetlockfiles (void)
-{
- FILE *fp;
- pthread_mutexattr_t attr;
-
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
-
- for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen)
- pthread_mutex_init(&fp->__lock, &attr);
-
- pthread_mutexattr_destroy(&attr);
-}
diff --git a/libpthread/linuxthreads/manager.c b/libpthread/linuxthreads/manager.c
deleted file mode 100644
index 204344aef..000000000
--- a/libpthread/linuxthreads/manager.c
+++ /dev/null
@@ -1,905 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* The "thread manager" thread: manages creation and termination of threads */
-
-/* mods for uClibc: getpwd and getpagesize are the syscalls */
-#define __getpid getpid
-#define __getpagesize getpagesize
-
-#include <features.h>
-#define __USE_GNU
-#include <errno.h>
-#include <sched.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/poll.h> /* for poll */
-#include <sys/mman.h> /* for mmap */
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/wait.h> /* for waitpid macros */
-
-#include "pthread.h"
-#include "internals.h"
-#include "spinlock.h"
-#include "restart.h"
-#include "semaphore.h"
-#include "debug.h" /* PDEBUG, added by StS */
-
-
-/* poll() is not supported in kernel <= 2.0, therefore is __NR_poll is
- * not available, we assume an old Linux kernel is in use and we will
- * use select() instead. */
-#include <sys/syscall.h>
-#ifndef __NR_poll
-# define USE_SELECT
-#endif
-
-
-/* Array of active threads. Entry 0 is reserved for the initial thread. */
-struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] =
-{ { __LOCK_INITIALIZER, &__pthread_initial_thread, 0},
- { __LOCK_INITIALIZER, &__pthread_manager_thread, 0}, /* All NULLs */ };
-
-/* For debugging purposes put the maximum number of threads in a variable. */
-const int __linuxthreads_pthread_threads_max = PTHREAD_THREADS_MAX;
-
-/* Indicate whether at least one thread has a user-defined stack (if 1),
- or if all threads have stacks supplied by LinuxThreads (if 0). */
-int __pthread_nonstandard_stacks;
-
-/* Number of active entries in __pthread_handles (used by gdb) */
-volatile int __pthread_handles_num = 2;
-
-/* Whether to use debugger additional actions for thread creation
- (set to 1 by gdb) */
-volatile int __pthread_threads_debug;
-
-/* Globally enabled events. */
-volatile td_thr_events_t __pthread_threads_events;
-
-/* Pointer to thread descriptor with last event. */
-volatile pthread_descr __pthread_last_event;
-
-/* Mapping from stack segment to thread descriptor. */
-/* Stack segment numbers are also indices into the __pthread_handles array. */
-/* Stack segment number 0 is reserved for the initial thread. */
-
-static inline pthread_descr thread_segment(int seg)
-{
- return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE)
- - 1;
-}
-
-/* Flag set in signal handler to record child termination */
-
-static volatile int terminated_children = 0;
-
-/* Flag set when the initial thread is blocked on pthread_exit waiting
- for all other threads to terminate */
-
-static int main_thread_exiting = 0;
-
-/* Counter used to generate unique thread identifier.
- Thread identifier is pthread_threads_counter + segment. */
-
-static pthread_t pthread_threads_counter = 0;
-
-/* Forward declarations */
-
-static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
- void * (*start_routine)(void *), void *arg,
- sigset_t *mask, int father_pid,
- int report_events,
- td_thr_events_t *event_maskp);
-static void pthread_handle_free(pthread_t th_id);
-static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode);
-static void pthread_reap_children(void);
-static void pthread_kill_all_threads(int sig, int main_thread_also);
-
-/* The server thread managing requests for thread creation and termination */
-
-int __pthread_manager(void *arg)
-{
- int reqfd = (int) (long int) arg;
-#ifdef USE_SELECT
- struct timeval tv;
- fd_set fd;
-#else
- struct pollfd ufd;
-#endif
- sigset_t manager_mask;
- int n;
- struct pthread_request request;
-
- /* If we have special thread_self processing, initialize it. */
-#ifdef INIT_THREAD_SELF
- INIT_THREAD_SELF(&__pthread_manager_thread, 1);
-#endif
- /* Set the error variable. */
- __pthread_manager_thread.p_errnop = &__pthread_manager_thread.p_errno;
- __pthread_manager_thread.p_h_errnop = &__pthread_manager_thread.p_h_errno;
-
-#ifdef __UCLIBC_HAS_XLOCALE__
- /* Initialize thread's locale to the global locale. */
- __pthread_manager_thread.locale = __global_locale;
-#endif /* __UCLIBC_HAS_XLOCALE__ */
-
- /* Block all signals except __pthread_sig_cancel and SIGTRAP */
- sigfillset(&manager_mask);
- sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */
- sigdelset(&manager_mask, SIGTRAP); /* for debugging purposes */
- if (__pthread_threads_debug && __pthread_sig_debug > 0)
- sigdelset(&manager_mask, __pthread_sig_debug);
- sigprocmask(SIG_SETMASK, &manager_mask, NULL);
- /* Raise our priority to match that of main thread */
- __pthread_manager_adjust_prio(__pthread_main_thread->p_priority);
- /* Synchronize debugging of the thread manager */
- n = TEMP_FAILURE_RETRY(__libc_read(reqfd, (char *)&request,
- sizeof(request)));
- ASSERT(n == sizeof(request) && request.req_kind == REQ_DEBUG);
-#ifndef USE_SELECT
- ufd.fd = reqfd;
- ufd.events = POLLIN;
-#endif
- /* Enter server loop */
- while(1) {
-#ifdef USE_SELECT
- tv.tv_sec = 2;
- tv.tv_usec = 0;
- FD_ZERO (&fd);
- FD_SET (reqfd, &fd);
- n = select (reqfd + 1, &fd, NULL, NULL, &tv);
-#else
- PDEBUG("before poll\n");
- n = poll(&ufd, 1, 2000);
- PDEBUG("after poll\n");
-#endif
- /* Check for termination of the main thread */
- if (getppid() == 1) {
- pthread_kill_all_threads(SIGKILL, 0);
- _exit(0);
- }
- /* Check for dead children */
- if (terminated_children) {
- terminated_children = 0;
- pthread_reap_children();
- }
- /* Read and execute request */
-#ifdef USE_SELECT
- if (n == 1)
-#else
- if (n == 1 && (ufd.revents & POLLIN))
-#endif
- {
-
- PDEBUG("before __libc_read\n");
- n = __libc_read(reqfd, (char *)&request, sizeof(request));
- PDEBUG("after __libc_read, n=%d\n", n);
- ASSERT(n == sizeof(request));
- switch(request.req_kind) {
- case REQ_CREATE:
- PDEBUG("got REQ_CREATE\n");
- request.req_thread->p_retcode =
- pthread_handle_create((pthread_t *) &request.req_thread->p_retval,
- request.req_args.create.attr,
- request.req_args.create.fn,
- request.req_args.create.arg,
- &request.req_args.create.mask,
- request.req_thread->p_pid,
- request.req_thread->p_report_events,
- &request.req_thread->p_eventbuf.eventmask);
- PDEBUG("restarting %d\n", request.req_thread);
- restart(request.req_thread);
- break;
- case REQ_FREE:
- PDEBUG("got REQ_FREE\n");
- pthread_handle_free(request.req_args.free.thread_id);
- break;
- case REQ_PROCESS_EXIT:
- PDEBUG("got REQ_PROCESS_EXIT from %d, exit code = %d\n",
- request.req_thread, request.req_args.exit.code);
- pthread_handle_exit(request.req_thread,
- request.req_args.exit.code);
- break;
- case REQ_MAIN_THREAD_EXIT:
- PDEBUG("got REQ_MAIN_THREAD_EXIT\n");
- main_thread_exiting = 1;
- /* Reap children in case all other threads died and the signal handler
- went off before we set main_thread_exiting to 1, and therefore did
- not do REQ_KICK. */
- pthread_reap_children();
-
- if (__pthread_main_thread->p_nextlive == __pthread_main_thread) {
- restart(__pthread_main_thread);
- /* The main thread will now call exit() which will trigger an
- __on_exit handler, which in turn will send REQ_PROCESS_EXIT
- to the thread manager. In case you are wondering how the
- manager terminates from its loop here. */
- }
- break;
- case REQ_POST:
- PDEBUG("got REQ_POST\n");
- __new_sem_post(request.req_args.post);
- break;
- case REQ_DEBUG:
- PDEBUG("got REQ_DEBUG\n");
- /* Make gdb aware of new thread and gdb will restart the
- new thread when it is ready to handle the new thread. */
- if (__pthread_threads_debug && __pthread_sig_debug > 0) {
- PDEBUG("about to call raise(__pthread_sig_debug)\n");
- raise(__pthread_sig_debug);
- }
- case REQ_KICK:
- /* This is just a prod to get the manager to reap some
- threads right away, avoiding a potential delay at shutdown. */
- break;
- }
- }
- }
-}
-
-int __pthread_manager_event(void *arg)
-{
- /* If we have special thread_self processing, initialize it. */
-#ifdef INIT_THREAD_SELF
- INIT_THREAD_SELF(&__pthread_manager_thread, 1);
-#endif
-
- /* Get the lock the manager will free once all is correctly set up. */
- __pthread_lock (THREAD_GETMEM((&__pthread_manager_thread), p_lock), NULL);
- /* Free it immediately. */
- __pthread_unlock (THREAD_GETMEM((&__pthread_manager_thread), p_lock));
-
- return __pthread_manager(arg);
-}
-
-/* Process creation */
-static int
-__attribute__ ((noreturn))
-pthread_start_thread(void *arg)
-{
- pthread_descr self = (pthread_descr) arg;
- struct pthread_request request;
- void * outcome;
- /* Initialize special thread_self processing, if any. */
-#ifdef INIT_THREAD_SELF
- INIT_THREAD_SELF(self, self->p_nr);
-#endif
- PDEBUG("\n");
- /* Make sure our pid field is initialized, just in case we get there
- before our father has initialized it. */
- THREAD_SETMEM(self, p_pid, __getpid());
- /* Initial signal mask is that of the creating thread. (Otherwise,
- we'd just inherit the mask of the thread manager.) */
- sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL);
- /* Set the scheduling policy and priority for the new thread, if needed */
- if (THREAD_GETMEM(self, p_start_args.schedpolicy) >= 0)
- /* Explicit scheduling attributes were provided: apply them */
- sched_setscheduler(THREAD_GETMEM(self, p_pid),
- THREAD_GETMEM(self, p_start_args.schedpolicy),
- &self->p_start_args.schedparam);
- else if (__pthread_manager_thread.p_priority > 0)
- /* Default scheduling required, but thread manager runs in realtime
- scheduling: switch new thread to SCHED_OTHER policy */
- {
- struct sched_param default_params;
- default_params.sched_priority = 0;
- sched_setscheduler(THREAD_GETMEM(self, p_pid),
- SCHED_OTHER, &default_params);
- }
- /* Make gdb aware of new thread */
- if (__pthread_threads_debug && __pthread_sig_debug > 0) {
- request.req_thread = self;
- request.req_kind = REQ_DEBUG;
- TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
- (char *) &request, sizeof(request)));
- suspend(self);
- }
- /* Run the thread code */
- outcome = self->p_start_args.start_routine(THREAD_GETMEM(self,
- p_start_args.arg));
- /* Exit with the given return value */
- pthread_exit(outcome);
-}
-
-static int
-__attribute__ ((noreturn))
-pthread_start_thread_event(void *arg)
-{
- pthread_descr self = (pthread_descr) arg;
-
-#ifdef INIT_THREAD_SELF
- INIT_THREAD_SELF(self, self->p_nr);
-#endif
- /* Make sure our pid field is initialized, just in case we get there
- before our father has initialized it. */
- THREAD_SETMEM(self, p_pid, __getpid());
- /* Get the lock the manager will free once all is correctly set up. */
- __pthread_lock (THREAD_GETMEM(self, p_lock), NULL);
- /* Free it immediately. */
- __pthread_unlock (THREAD_GETMEM(self, p_lock));
-
- /* Continue with the real function. */
- pthread_start_thread (arg);
-}
-
-static int pthread_allocate_stack(const pthread_attr_t *attr,
- pthread_descr default_new_thread,
- int pagesize,
- pthread_descr * out_new_thread,
- char ** out_new_thread_bottom,
- char ** out_guardaddr,
- size_t * out_guardsize)
-{
- pthread_descr new_thread;
- char * new_thread_bottom;
- char * guardaddr;
- size_t stacksize, guardsize;
-
- if (attr != NULL && attr->__stackaddr_set)
- {
- /* The user provided a stack. */
- new_thread =
- (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1;
- new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize;
- guardaddr = NULL;
- guardsize = 0;
- __pthread_nonstandard_stacks = 1;
- }
- else
- {
-#ifdef __ARCH_HAS_MMU__
- stacksize = STACK_SIZE - pagesize;
- if (attr != NULL)
- stacksize = MIN (stacksize, roundup(attr->__stacksize, pagesize));
- /* Allocate space for stack and thread descriptor at default address */
- new_thread = default_new_thread;
- new_thread_bottom = (char *) (new_thread + 1) - stacksize;
- if (mmap((caddr_t)((char *)(new_thread + 1) - INITIAL_STACK_SIZE),
- INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN,
- -1, 0) == MAP_FAILED)
- /* Bad luck, this segment is already mapped. */
- return -1;
- /* We manage to get a stack. Now see whether we need a guard
- and allocate it if necessary. Notice that the default
- attributes (stack_size = STACK_SIZE - pagesize) do not need
- a guard page, since the RLIMIT_STACK soft limit prevents stacks
- from running into one another. */
- if (stacksize == STACK_SIZE - pagesize)
- {
- /* We don't need a guard page. */
- guardaddr = NULL;
- guardsize = 0;
- }
- else
- {
- /* Put a bad page at the bottom of the stack */
- guardsize = attr->__guardsize;
- guardaddr = (void *)new_thread_bottom - guardsize;
- if (mmap ((caddr_t) guardaddr, guardsize, 0, MAP_FIXED, -1, 0)
- == MAP_FAILED)
- {
- /* We don't make this an error. */
- guardaddr = NULL;
- guardsize = 0;
- }
- }
-#else
- /* We cannot mmap to this huge chunk of stack space when we don't have
- * an MMU. Pretend we are using a user provided stack even if there was
- * none provided by the user. Thus, we get around the mmap and reservation
- * of a huge stack segment. -StS */
-
- stacksize = INITIAL_STACK_SIZE;
- /* The user may want to use a non-default stacksize */
- if (attr != NULL)
- {
- stacksize = attr->__stacksize;
- }
-
- /* malloc a stack - memory from the bottom up */
- if ((new_thread_bottom = malloc(stacksize)) == NULL)
- {
- /* bad luck, we cannot malloc any more */
- return -1 ;
- }
- PDEBUG("malloced chunk: base=%p, size=0x%04x\n", new_thread_bottom, stacksize);
-
- /* Set up the pointers. new_thread marks the TOP of the stack frame and
- * the address of the pthread_descr struct at the same time. Therefore we
- * must account for its size and fit it in the malloc()'ed block. The
- * value of `new_thread' is then passed to clone() as the stack argument.
- *
- * ^ +------------------------+
- * | | pthread_descr struct |
- * | +------------------------+ <- new_thread
- * malloc block | | |
- * | | thread stack |
- * | | |
- * v +------------------------+ <- new_thread_bottom
- *
- * Note: The calculated value of new_thread must be word aligned otherwise
- * the kernel chokes on a non-aligned stack frame. Choose the lower
- * available word boundary.
- */
- new_thread = ((pthread_descr) ((int)(new_thread_bottom + stacksize) & -sizeof(void*))) - 1;
- guardaddr = NULL;
- guardsize = 0;
-
- PDEBUG("thread stack: bos=%p, tos=%p\n", new_thread_bottom, new_thread);
-
- /* check the initial thread stack boundaries so they don't overlap */
- NOMMU_INITIAL_THREAD_BOUNDS((char *) new_thread, (char *) new_thread_bottom);
-
- PDEBUG("initial stack: bos=%p, tos=%p\n", __pthread_initial_thread_bos,
- __pthread_initial_thread_tos);
-
- /* on non-MMU systems we always have non-standard stack frames */
- __pthread_nonstandard_stacks = 1;
-
-#endif /* __ARCH_HAS_MMU__ */
- }
-
- /* Clear the thread data structure. */
- memset (new_thread, '\0', sizeof (*new_thread));
- *out_new_thread = new_thread;
- *out_new_thread_bottom = new_thread_bottom;
- *out_guardaddr = guardaddr;
- *out_guardsize = guardsize;
- return 0;
-}
-
-static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
- void * (*start_routine)(void *), void *arg,
- sigset_t * mask, int father_pid,
- int report_events,
- td_thr_events_t *event_maskp)
-{
- size_t sseg;
- int pid;
- pthread_descr new_thread;
- char * new_thread_bottom;
- pthread_t new_thread_id;
- char *guardaddr = NULL;
- size_t guardsize = 0;
- int pagesize = __getpagesize();
- int saved_errno = 0;
-
- /* First check whether we have to change the policy and if yes, whether
- we can do this. Normally this should be done by examining the
- return value of the sched_setscheduler call in pthread_start_thread
- but this is hard to implement. FIXME */
- if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0)
- return EPERM;
- /* Find a free segment for the thread, and allocate a stack if needed */
- for (sseg = 2; ; sseg++)
- {
- if (sseg >= PTHREAD_THREADS_MAX)
- return EAGAIN;
- if (__pthread_handles[sseg].h_descr != NULL)
- continue;
- if (pthread_allocate_stack(attr, thread_segment(sseg), pagesize,
- &new_thread, &new_thread_bottom,
- &guardaddr, &guardsize) == 0)
- break;
- }
- __pthread_handles_num++;
- /* Allocate new thread identifier */
- pthread_threads_counter += PTHREAD_THREADS_MAX;
- new_thread_id = sseg + pthread_threads_counter;
- /* Initialize the thread descriptor. Elements which have to be
- initialized to zero already have this value. */
- new_thread->p_tid = new_thread_id;
- new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
- new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
- new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
- new_thread->p_errnop = &new_thread->p_errno;
- new_thread->p_h_errnop = &new_thread->p_h_errno;
-#ifdef __UCLIBC_HAS_XLOCALE__
- /* Initialize thread's locale to the global locale. */
- new_thread->locale = __global_locale;
-#endif /* __UCLIBC_HAS_XLOCALE__ */
- new_thread->p_guardaddr = guardaddr;
- new_thread->p_guardsize = guardsize;
- new_thread->p_self = new_thread;
- new_thread->p_nr = sseg;
- /* Initialize the thread handle */
- __pthread_init_lock(&__pthread_handles[sseg].h_lock);
- __pthread_handles[sseg].h_descr = new_thread;
- __pthread_handles[sseg].h_bottom = new_thread_bottom;
- /* Determine scheduling parameters for the thread */
- new_thread->p_start_args.schedpolicy = -1;
- if (attr != NULL) {
- new_thread->p_detached = attr->__detachstate;
- new_thread->p_userstack = attr->__stackaddr_set;
-
- switch(attr->__inheritsched) {
- case PTHREAD_EXPLICIT_SCHED:
- new_thread->p_start_args.schedpolicy = attr->__schedpolicy;
- memcpy (&new_thread->p_start_args.schedparam, &attr->__schedparam,
- sizeof (struct sched_param));
- break;
- case PTHREAD_INHERIT_SCHED:
- new_thread->p_start_args.schedpolicy = sched_getscheduler(father_pid);
- sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
- break;
- }
- new_thread->p_priority =
- new_thread->p_start_args.schedparam.sched_priority;
- }
- /* Finish setting up arguments to pthread_start_thread */
- new_thread->p_start_args.start_routine = start_routine;
- new_thread->p_start_args.arg = arg;
- new_thread->p_start_args.mask = *mask;
- /* Raise priority of thread manager if needed */
- __pthread_manager_adjust_prio(new_thread->p_priority);
- /* Do the cloning. We have to use two different functions depending
- on whether we are debugging or not. */
- pid = 0; /* Note that the thread never can have PID zero. */
-
-
- /* ******************************************************** */
- /* This code was moved from below to cope with running threads
- * on uClinux systems. See comment below...
- * Insert new thread in doubly linked list of active threads */
- new_thread->p_prevlive = __pthread_main_thread;
- new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
- __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
- __pthread_main_thread->p_nextlive = new_thread;
- /* ********************************************************* */
-
- if (report_events)
- {
- /* See whether the TD_CREATE event bit is set in any of the
- masks. */
- int idx = __td_eventword (TD_CREATE);
- uint32_t mask = __td_eventmask (TD_CREATE);
-
- if ((mask & (__pthread_threads_events.event_bits[idx]
- | event_maskp->event_bits[idx])) != 0)
- {
- /* Lock the mutex the child will use now so that it will stop. */
- __pthread_lock(new_thread->p_lock, NULL);
-
- /* We have to report this event. */
- pid = clone(pthread_start_thread_event, (void **) new_thread,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
- __pthread_sig_cancel, new_thread);
-
- saved_errno = errno;
- if (pid != -1)
- {
- /* Now fill in the information about the new thread in
- the newly created thread's data structure. We cannot let
- the new thread do this since we don't know whether it was
- already scheduled when we send the event. */
- new_thread->p_eventbuf.eventdata = new_thread;
- new_thread->p_eventbuf.eventnum = TD_CREATE;
- __pthread_last_event = new_thread;
-
- /* We have to set the PID here since the callback function
- in the debug library will need it and we cannot guarantee
- the child got scheduled before the debugger. */
- new_thread->p_pid = pid;
-
- /* Now call the function which signals the event. */
- __linuxthreads_create_event ();
-
- /* Now restart the thread. */
- __pthread_unlock(new_thread->p_lock);
- }
- }
- }
- if (pid == 0)
- {
- PDEBUG("cloning new_thread = %p\n", new_thread);
- pid = clone(pthread_start_thread, (void **) new_thread,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
- __pthread_sig_cancel, new_thread);
- saved_errno = errno;
- }
- /* Check if cloning succeeded */
- if (pid == -1) {
- /********************************************************
- * Code inserted to remove the thread from our list of active
- * threads in case of failure (needed to cope with uClinux),
- * See comment below. */
- new_thread->p_nextlive->p_prevlive = new_thread->p_prevlive;
- new_thread->p_prevlive->p_nextlive = new_thread->p_nextlive;
- /********************************************************/
-
- /* Free the stack if we allocated it */
- if (attr == NULL || !attr->__stackaddr_set)
- {
-#ifdef __ARCH_HAS_MMU__
- if (new_thread->p_guardsize != 0)
- munmap(new_thread->p_guardaddr, new_thread->p_guardsize);
- munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
- INITIAL_STACK_SIZE);
-#else
- free(new_thread_bottom);
-#endif /* __ARCH_HAS_MMU__ */
- }
- __pthread_handles[sseg].h_descr = NULL;
- __pthread_handles[sseg].h_bottom = NULL;
- __pthread_handles_num--;
- return errno;
- }
- PDEBUG("new thread pid = %d\n", pid);
-
-#if 0
- /* ***********************************************************
- This code has been moved before the call to clone(). In uClinux,
- the use of wait on a semaphore is dependant upon that the child so
- the child must be in the active threads list. This list is used in
- pthread_find_self() to get the pthread_descr of self. So, if the
- child calls sem_wait before this code is executed , it will hang
- forever and initial_thread will instead be posted by a sem_post
- call. */
-
- /* Insert new thread in doubly linked list of active threads */
- new_thread->p_prevlive = __pthread_main_thread;
- new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
- __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
- __pthread_main_thread->p_nextlive = new_thread;
- /************************************************************/
-#endif
-
- /* Set pid field of the new thread, in case we get there before the
- child starts. */
- new_thread->p_pid = pid;
- /* We're all set */
- *thread = new_thread_id;
- return 0;
-}
-
-
-/* Try to free the resources of a thread when requested by pthread_join
- or pthread_detach on a terminated thread. */
-
-static void pthread_free(pthread_descr th)
-{
- pthread_handle handle;
- pthread_readlock_info *iter, *next;
- char *h_bottom_save;
-
- ASSERT(th->p_exited);
- /* Make the handle invalid */
- handle = thread_handle(th->p_tid);
- __pthread_lock(&handle->h_lock, NULL);
- h_bottom_save = handle->h_bottom;
- handle->h_descr = NULL;
- handle->h_bottom = (char *)(-1L);
- __pthread_unlock(&handle->h_lock);
-#ifdef FREE_THREAD_SELF
- FREE_THREAD_SELF(th, th->p_nr);
-#endif
- /* One fewer threads in __pthread_handles */
- __pthread_handles_num--;
-
- /* Destroy read lock list, and list of free read lock structures.
- If the former is not empty, it means the thread exited while
- holding read locks! */
-
- for (iter = th->p_readlock_list; iter != NULL; iter = next)
- {
- next = iter->pr_next;
- free(iter);
- }
-
- for (iter = th->p_readlock_free; iter != NULL; iter = next)
- {
- next = iter->pr_next;
- free(iter);
- }
-
- /* If initial thread, nothing to free */
- if (th == &__pthread_initial_thread) return;
-#ifdef __ARCH_HAS_MMU__
- if (!th->p_userstack)
- {
- /* Free the stack and thread descriptor area */
- if (th->p_guardsize != 0)
- munmap(th->p_guardaddr, th->p_guardsize);
- munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE);
- }
-#else
- /* For non-MMU systems we always malloc the stack, so free it here. -StS */
- if (!th->p_userstack) {
- free(h_bottom_save);
- }
-#endif /* __ARCH_HAS_MMU__ */
-}
-
-/* Handle threads that have exited */
-
-static void pthread_exited(pid_t pid)
-{
- pthread_descr th;
- int detached;
- /* Find thread with that pid */
- for (th = __pthread_main_thread->p_nextlive;
- th != __pthread_main_thread;
- th = th->p_nextlive) {
- if (th->p_pid == pid) {
- /* Remove thread from list of active threads */
- th->p_nextlive->p_prevlive = th->p_prevlive;
- th->p_prevlive->p_nextlive = th->p_nextlive;
- /* Mark thread as exited, and if detached, free its resources */
- __pthread_lock(th->p_lock, NULL);
- th->p_exited = 1;
- /* If we have to signal this event do it now. */
- if (th->p_report_events)
- {
- /* See whether TD_REAP is in any of the mask. */
- int idx = __td_eventword (TD_REAP);
- uint32_t mask = __td_eventmask (TD_REAP);
-
- if ((mask & (__pthread_threads_events.event_bits[idx]
- | th->p_eventbuf.eventmask.event_bits[idx])) != 0)
- {
- /* Yep, we have to signal the reapage. */
- th->p_eventbuf.eventnum = TD_REAP;
- th->p_eventbuf.eventdata = th;
- __pthread_last_event = th;
-
- /* Now call the function to signal the event. */
- __linuxthreads_reap_event();
- }
- }
- detached = th->p_detached;
- __pthread_unlock(th->p_lock);
- if (detached)
- pthread_free(th);
- break;
- }
- }
- /* If all threads have exited and the main thread is pending on a
- pthread_exit, wake up the main thread and terminate ourselves. */
- if (main_thread_exiting &&
- __pthread_main_thread->p_nextlive == __pthread_main_thread) {
- restart(__pthread_main_thread);
- /* Same logic as REQ_MAIN_THREAD_EXIT. */
- }
-}
-
-static void pthread_reap_children(void)
-{
- pid_t pid;
- int status;
- PDEBUG("\n");
-
- while ((pid = __libc_waitpid(-1, &status, WNOHANG | __WCLONE)) > 0) {
- pthread_exited(pid);
- if (WIFSIGNALED(status)) {
- /* If a thread died due to a signal, send the same signal to
- all other threads, including the main thread. */
- pthread_kill_all_threads(WTERMSIG(status), 1);
- _exit(0);
- }
- }
-}
-
-/* Try to free the resources of a thread when requested by pthread_join
- or pthread_detach on a terminated thread. */
-
-static void pthread_handle_free(pthread_t th_id)
-{
- pthread_handle handle = thread_handle(th_id);
- pthread_descr th;
-
- __pthread_lock(&handle->h_lock, NULL);
- if (invalid_handle(handle, th_id)) {
- /* pthread_reap_children has deallocated the thread already,
- nothing needs to be done */
- __pthread_unlock(&handle->h_lock);
- return;
- }
- th = handle->h_descr;
- if (th->p_exited) {
- __pthread_unlock(&handle->h_lock);
- pthread_free(th);
- } else {
- /* The Unix process of the thread is still running.
- Mark the thread as detached so that the thread manager will
- deallocate its resources when the Unix process exits. */
- th->p_detached = 1;
- __pthread_unlock(&handle->h_lock);
- }
-}
-
-/* Send a signal to all running threads */
-
-static void pthread_kill_all_threads(int sig, int main_thread_also)
-{
- pthread_descr th;
- for (th = __pthread_main_thread->p_nextlive;
- th != __pthread_main_thread;
- th = th->p_nextlive) {
- kill(th->p_pid, sig);
- }
- if (main_thread_also) {
- kill(__pthread_main_thread->p_pid, sig);
- }
-}
-
-/* Process-wide exit() */
-
-static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode)
-{
- pthread_descr th;
- __pthread_exit_requested = 1;
- __pthread_exit_code = exitcode;
- /* Send the CANCEL signal to all running threads, including the main
- thread, but excluding the thread from which the exit request originated
- (that thread must complete the exit, e.g. calling atexit functions
- and flushing stdio buffers). */
- for (th = issuing_thread->p_nextlive;
- th != issuing_thread;
- th = th->p_nextlive) {
- kill(th->p_pid, __pthread_sig_cancel);
- }
- /* Now, wait for all these threads, so that they don't become zombies
- and their times are properly added to the thread manager's times. */
- for (th = issuing_thread->p_nextlive;
- th != issuing_thread;
- th = th->p_nextlive) {
- waitpid(th->p_pid, NULL, __WCLONE);
- }
- restart(issuing_thread);
- _exit(0);
-}
-
-/* Handler for __pthread_sig_cancel in thread manager thread */
-
-void __pthread_manager_sighandler(int sig)
-{
- int kick_manager = terminated_children == 0 && main_thread_exiting;
- terminated_children = 1;
-
- /* If the main thread is terminating, kick the thread manager loop
- each time some threads terminate. This eliminates a two second
- shutdown delay caused by the thread manager sleeping in the
- call to __poll(). Instead, the thread manager is kicked into
- action, reaps the outstanding threads and resumes the main thread
- so that it can complete the shutdown. */
-
- if (kick_manager) {
- struct pthread_request request;
- request.req_thread = 0;
- request.req_kind = REQ_KICK;
- TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
- (char *) &request, sizeof(request)));
- }
-}
-
-/* Adjust priority of thread manager so that it always run at a priority
- higher than all threads */
-
-void __pthread_manager_adjust_prio(int thread_prio)
-{
- struct sched_param param;
-
- if (thread_prio <= __pthread_manager_thread.p_priority) return;
- param.sched_priority =
- thread_prio < sched_get_priority_max(SCHED_FIFO)
- ? thread_prio + 1 : thread_prio;
- sched_setscheduler(__pthread_manager_thread.p_pid, SCHED_FIFO, &param);
- __pthread_manager_thread.p_priority = thread_prio;
-}
diff --git a/libpthread/linuxthreads/mutex.c b/libpthread/linuxthreads/mutex.c
deleted file mode 100644
index 7cc344fac..000000000
--- a/libpthread/linuxthreads/mutex.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Mutexes */
-
-#include <errno.h>
-#include <sched.h>
-#include <stddef.h>
-#include <limits.h>
-#include "pthread.h"
-#include "internals.h"
-#include "spinlock.h"
-#include "queue.h"
-#include "restart.h"
-
-int __pthread_mutex_init(pthread_mutex_t * mutex,
- const pthread_mutexattr_t * mutex_attr)
-{
- __pthread_init_lock(&mutex->__m_lock);
- mutex->__m_kind =
- mutex_attr == NULL ? PTHREAD_MUTEX_TIMED_NP : mutex_attr->__mutexkind;
- mutex->__m_count = 0;
- mutex->__m_owner = NULL;
- return 0;
-}
-strong_alias (__pthread_mutex_init, pthread_mutex_init)
-
-int __pthread_mutex_destroy(pthread_mutex_t * mutex)
-{
- switch (mutex->__m_kind) {
- case PTHREAD_MUTEX_ADAPTIVE_NP:
- case PTHREAD_MUTEX_RECURSIVE_NP:
- if ((mutex->__m_lock.__status & 1) != 0)
- return EBUSY;
- return 0;
- case PTHREAD_MUTEX_ERRORCHECK_NP:
- case PTHREAD_MUTEX_TIMED_NP:
- if (mutex->__m_lock.__status != 0)
- return EBUSY;
- return 0;
- default:
- return EINVAL;
- }
-}
-strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy)
-
-int __pthread_mutex_trylock(pthread_mutex_t * mutex)
-{
- pthread_descr self;
- int retcode;
-
- switch(mutex->__m_kind) {
- case PTHREAD_MUTEX_ADAPTIVE_NP:
- retcode = __pthread_trylock(&mutex->__m_lock);
- return retcode;
- case PTHREAD_MUTEX_RECURSIVE_NP:
- self = thread_self();
- if (mutex->__m_owner == self) {
- mutex->__m_count++;
- return 0;
- }
- retcode = __pthread_trylock(&mutex->__m_lock);
- if (retcode == 0) {
- mutex->__m_owner = self;
- mutex->__m_count = 0;
- }
- return retcode;
- case PTHREAD_MUTEX_ERRORCHECK_NP:
- retcode = __pthread_alt_trylock(&mutex->__m_lock);
- if (retcode == 0) {
- mutex->__m_owner = thread_self();
- }
- return retcode;
- case PTHREAD_MUTEX_TIMED_NP:
- retcode = __pthread_alt_trylock(&mutex->__m_lock);
- return retcode;
- default:
- return EINVAL;
- }
-}
-strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock)
-
-int __pthread_mutex_lock(pthread_mutex_t * mutex)
-{
- pthread_descr self;
-
- switch(mutex->__m_kind) {
- case PTHREAD_MUTEX_ADAPTIVE_NP:
- __pthread_lock(&mutex->__m_lock, NULL);
- return 0;
- case PTHREAD_MUTEX_RECURSIVE_NP:
- self = thread_self();
- if (mutex->__m_owner == self) {
- mutex->__m_count++;
- return 0;
- }
- __pthread_lock(&mutex->__m_lock, self);
- mutex->__m_owner = self;
- mutex->__m_count = 0;
- return 0;
- case PTHREAD_MUTEX_ERRORCHECK_NP:
- self = thread_self();
- if (mutex->__m_owner == self) return EDEADLK;
- __pthread_alt_lock(&mutex->__m_lock, self);
- mutex->__m_owner = self;
- return 0;
- case PTHREAD_MUTEX_TIMED_NP:
- __pthread_alt_lock(&mutex->__m_lock, NULL);
- return 0;
- default:
- return EINVAL;
- }
-}
-strong_alias (__pthread_mutex_lock, pthread_mutex_lock)
-
-int __pthread_mutex_timedlock (pthread_mutex_t *mutex,
- const struct timespec *abstime)
-{
- pthread_descr self;
- int res;
-
- if (__builtin_expect (abstime->tv_nsec, 0) < 0
- || __builtin_expect (abstime->tv_nsec, 0) >= 1000000000)
- return EINVAL;
-
- switch(mutex->__m_kind) {
- case PTHREAD_MUTEX_ADAPTIVE_NP:
- __pthread_lock(&mutex->__m_lock, NULL);
- return 0;
- case PTHREAD_MUTEX_RECURSIVE_NP:
- self = thread_self();
- if (mutex->__m_owner == self) {
- mutex->__m_count++;
- return 0;
- }
- __pthread_lock(&mutex->__m_lock, self);
- mutex->__m_owner = self;
- mutex->__m_count = 0;
- return 0;
- case PTHREAD_MUTEX_ERRORCHECK_NP:
- self = thread_self();
- if (mutex->__m_owner == self) return EDEADLK;
- res = __pthread_alt_timedlock(&mutex->__m_lock, self, abstime);
- if (res != 0)
- {
- mutex->__m_owner = self;
- return 0;
- }
- return ETIMEDOUT;
- case PTHREAD_MUTEX_TIMED_NP:
- /* Only this type supports timed out lock. */
- return (__pthread_alt_timedlock(&mutex->__m_lock, NULL, abstime)
- ? 0 : ETIMEDOUT);
- default:
- return EINVAL;
- }
-}
-strong_alias (__pthread_mutex_timedlock, pthread_mutex_timedlock)
-
-int __pthread_mutex_unlock(pthread_mutex_t * mutex)
-{
- switch (mutex->__m_kind) {
- case PTHREAD_MUTEX_ADAPTIVE_NP:
- __pthread_unlock(&mutex->__m_lock);
- return 0;
- case PTHREAD_MUTEX_RECURSIVE_NP:
- if (mutex->__m_owner != thread_self())
- return EPERM;
- if (mutex->__m_count > 0) {
- mutex->__m_count--;
- return 0;
- }
- mutex->__m_owner = NULL;
- __pthread_unlock(&mutex->__m_lock);
- return 0;
- case PTHREAD_MUTEX_ERRORCHECK_NP:
- if (mutex->__m_owner != thread_self() || mutex->__m_lock.__status == 0)
- return EPERM;
- mutex->__m_owner = NULL;
- __pthread_alt_unlock(&mutex->__m_lock);
- return 0;
- case PTHREAD_MUTEX_TIMED_NP:
- __pthread_alt_unlock(&mutex->__m_lock);
- return 0;
- default:
- return EINVAL;
- }
-}
-strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock)
-
-int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
-{
- attr->__mutexkind = PTHREAD_MUTEX_TIMED_NP;
- return 0;
-}
-strong_alias (__pthread_mutexattr_init, pthread_mutexattr_init)
-
-int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
-{
- return 0;
-}
-strong_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
-
-int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind)
-{
- if (kind != PTHREAD_MUTEX_ADAPTIVE_NP
- && kind != PTHREAD_MUTEX_RECURSIVE_NP
- && kind != PTHREAD_MUTEX_ERRORCHECK_NP
- && kind != PTHREAD_MUTEX_TIMED_NP)
- return EINVAL;
- attr->__mutexkind = kind;
- return 0;
-}
-weak_alias (__pthread_mutexattr_settype, pthread_mutexattr_settype)
-strong_alias ( __pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
-weak_alias (__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
-
-int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind)
-{
- *kind = attr->__mutexkind;
- return 0;
-}
-weak_alias (__pthread_mutexattr_gettype, pthread_mutexattr_gettype)
-strong_alias (__pthread_mutexattr_gettype, __pthread_mutexattr_getkind_np)
-weak_alias (__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np)
-
-int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr,
- int *pshared)
-{
- *pshared = PTHREAD_PROCESS_PRIVATE;
- return 0;
-}
-weak_alias (__pthread_mutexattr_getpshared, pthread_mutexattr_getpshared)
-
-int __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared)
-{
- if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
- return EINVAL;
-
- /* For now it is not possible to shared a conditional variable. */
- if (pshared != PTHREAD_PROCESS_PRIVATE)
- return ENOSYS;
-
- return 0;
-}
-weak_alias (__pthread_mutexattr_setpshared, pthread_mutexattr_setpshared)
-
-/* Once-only execution */
-
-static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t once_finished = PTHREAD_COND_INITIALIZER;
-static int fork_generation = 0; /* Child process increments this after fork. */
-
-enum { NEVER = 0, IN_PROGRESS = 1, DONE = 2 };
-
-/* If a thread is canceled while calling the init_routine out of
- pthread once, this handler will reset the once_control variable
- to the NEVER state. */
-
-static void pthread_once_cancelhandler(void *arg)
-{
- pthread_once_t *once_control = arg;
-
- pthread_mutex_lock(&once_masterlock);
- *once_control = NEVER;
- pthread_mutex_unlock(&once_masterlock);
- pthread_cond_broadcast(&once_finished);
-}
-
-int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void))
-{
- /* flag for doing the condition broadcast outside of mutex */
- int state_changed;
-
- /* Test without locking first for speed */
- if (*once_control == DONE) {
- READ_MEMORY_BARRIER();
- return 0;
- }
- /* Lock and test again */
-
- state_changed = 0;
-
- pthread_mutex_lock(&once_masterlock);
-
- /* If this object was left in an IN_PROGRESS state in a parent
- process (indicated by stale generation field), reset it to NEVER. */
- if ((*once_control & 3) == IN_PROGRESS && (*once_control & ~3) != fork_generation)
- *once_control = NEVER;
-
- /* If init_routine is being called from another routine, wait until
- it completes. */
- while ((*once_control & 3) == IN_PROGRESS) {
- pthread_cond_wait(&once_finished, &once_masterlock);
- }
- /* Here *once_control is stable and either NEVER or DONE. */
- if (*once_control == NEVER) {
- *once_control = IN_PROGRESS | fork_generation;
- pthread_mutex_unlock(&once_masterlock);
- pthread_cleanup_push(pthread_once_cancelhandler, once_control);
- init_routine();
- pthread_cleanup_pop(0);
- pthread_mutex_lock(&once_masterlock);
- WRITE_MEMORY_BARRIER();
- *once_control = DONE;
- state_changed = 1;
- }
- pthread_mutex_unlock(&once_masterlock);
-
- if (state_changed)
- pthread_cond_broadcast(&once_finished);
-
- return 0;
-}
-strong_alias (__pthread_once, pthread_once)
-
-/*
- * Handle the state of the pthread_once mechanism across forks. The
- * once_masterlock is acquired in the parent process prior to a fork to ensure
- * that no thread is in the critical region protected by the lock. After the
- * fork, the lock is released. In the child, the lock and the condition
- * variable are simply reset. The child also increments its generation
- * counter which lets pthread_once calls detect stale IN_PROGRESS states
- * and reset them back to NEVER.
- */
-
-void __pthread_once_fork_prepare(void)
-{
- pthread_mutex_lock(&once_masterlock);
-}
-
-void __pthread_once_fork_parent(void)
-{
- pthread_mutex_unlock(&once_masterlock);
-}
-
-void __pthread_once_fork_child(void)
-{
- pthread_mutex_init(&once_masterlock, NULL);
- pthread_cond_init(&once_finished, NULL);
- if (fork_generation <= INT_MAX - 4)
- fork_generation += 4; /* leave least significant two bits zero */
- else
- fork_generation = 0;
-}
diff --git a/libpthread/linuxthreads/oldsemaphore.c b/libpthread/linuxthreads/oldsemaphore.c
deleted file mode 100644
index 3a3b3d186..000000000
--- a/libpthread/linuxthreads/oldsemaphore.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * This file contains the old semaphore code that we need to
- * preserve for glibc-2.0 backwards compatibility. Port to glibc 2.1
- * done by Cristian Gafton.
- */
-
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Semaphores a la POSIX 1003.1b */
-
-#include <errno.h>
-#include "pthread.h"
-#include "internals.h"
-#include "spinlock.h"
-#include "restart.h"
-#include "queue.h"
-
-typedef struct {
- long int sem_status;
- int sem_spinlock;
-} old_sem_t;
-
-/* Maximum value the semaphore can have. */
-#define SEM_VALUE_MAX ((int) ((~0u) >> 1))
-
-static inline int sem_compare_and_swap(old_sem_t *sem, long oldval, long newval)
-{
- return compare_and_swap(&sem->sem_status, oldval, newval, &sem->sem_spinlock);
-}
-
-/* The state of a semaphore is represented by a long int encoding
- either the semaphore count if >= 0 and no thread is waiting on it,
- or the head of the list of threads waiting for the semaphore.
- To distinguish the two cases, we encode the semaphore count N
- as 2N+1, so that it has the lowest bit set.
-
- A sequence of sem_wait operations on a semaphore initialized to N
- result in the following successive states:
- 2N+1, 2N-1, ..., 3, 1, &first_waiting_thread, &second_waiting_thread, ...
-*/
-
-static void sem_restart_list(pthread_descr waiting);
-
-int __old_sem_init(old_sem_t *sem, int pshared, unsigned int value)
-{
- if (value > SEM_VALUE_MAX) {
- errno = EINVAL;
- return -1;
- }
- if (pshared) {
- errno = ENOSYS;
- return -1;
- }
- sem->sem_spinlock = 0;
- sem->sem_status = ((long)value << 1) + 1;
- return 0;
-}
-
-/* Function called by pthread_cancel to remove the thread from
- waiting inside __old_sem_wait. Here we simply unconditionally
- indicate that the thread is to be woken, by returning 1. */
-
-static int old_sem_extricate_func(void *obj, pthread_descr th)
-{
- return 1;
-}
-
-int __old_sem_wait(old_sem_t * sem)
-{
- long oldstatus, newstatus;
- volatile pthread_descr self = thread_self();
- pthread_descr * th;
- pthread_extricate_if extr;
-
- /* Set up extrication interface */
- extr.pu_object = 0;
- extr.pu_extricate_func = old_sem_extricate_func;
-
- while (1) {
- /* Register extrication interface */
- __pthread_set_own_extricate_if(self, &extr);
- do {
- oldstatus = sem->sem_status;
- if ((oldstatus & 1) && (oldstatus != 1))
- newstatus = oldstatus - 2;
- else {
- newstatus = (long) self;
- self->p_nextwaiting = (pthread_descr) oldstatus;
- }
- }
- while (! sem_compare_and_swap(sem, oldstatus, newstatus));
- if (newstatus & 1) {
- /* We got the semaphore. */
- __pthread_set_own_extricate_if(self, 0);
- return 0;
- }
- /* Wait for sem_post or cancellation */
- suspend(self);
- __pthread_set_own_extricate_if(self, 0);
-
- /* This is a cancellation point */
- if (self->p_canceled && self->p_cancelstate == PTHREAD_CANCEL_ENABLE) {
- /* Remove ourselves from the waiting list if we're still on it */
- /* First check if we're at the head of the list. */
- do {
- oldstatus = sem->sem_status;
- if (oldstatus != (long) self) break;
- newstatus = (long) self->p_nextwaiting;
- }
- while (! sem_compare_and_swap(sem, oldstatus, newstatus));
- /* Now, check if we're somewhere in the list.
- There's a race condition with sem_post here, but it does not matter:
- the net result is that at the time pthread_exit is called,
- self is no longer reachable from sem->sem_status. */
- if (oldstatus != (long) self && (oldstatus & 1) == 0) {
- for (th = &(((pthread_descr) oldstatus)->p_nextwaiting);
- *th != NULL && *th != (pthread_descr) 1;
- th = &((*th)->p_nextwaiting)) {
- if (*th == self) {
- *th = self->p_nextwaiting;
- break;
- }
- }
- }
- pthread_exit(PTHREAD_CANCELED);
- }
- }
-}
-
-int __old_sem_trywait(old_sem_t * sem)
-{
- long oldstatus, newstatus;
-
- do {
- oldstatus = sem->sem_status;
- if ((oldstatus & 1) == 0 || (oldstatus == 1)) {
- errno = EAGAIN;
- return -1;
- }
- newstatus = oldstatus - 2;
- }
- while (! sem_compare_and_swap(sem, oldstatus, newstatus));
- return 0;
-}
-
-int __old_sem_post(old_sem_t * sem)
-{
- long oldstatus, newstatus;
-
- do {
- oldstatus = sem->sem_status;
- if ((oldstatus & 1) == 0)
- newstatus = 3;
- else {
- if (oldstatus >= SEM_VALUE_MAX) {
- /* Overflow */
- errno = ERANGE;
- return -1;
- }
- newstatus = oldstatus + 2;
- }
- }
- while (! sem_compare_and_swap(sem, oldstatus, newstatus));
- if ((oldstatus & 1) == 0)
- sem_restart_list((pthread_descr) oldstatus);
- return 0;
-}
-
-int __old_sem_getvalue(old_sem_t * sem, int * sval)
-{
- long status = sem->sem_status;
- if (status & 1)
- *sval = (int)((unsigned long) status >> 1);
- else
- *sval = 0;
- return 0;
-}
-
-int __old_sem_destroy(old_sem_t * sem)
-{
- if ((sem->sem_status & 1) == 0) {
- errno = EBUSY;
- return -1;
- }
- return 0;
-}
-
-/* Auxiliary function for restarting all threads on a waiting list,
- in priority order. */
-
-static void sem_restart_list(pthread_descr waiting)
-{
- pthread_descr th, towake, *p;
-
- /* Sort list of waiting threads by decreasing priority (insertion sort) */
- towake = NULL;
- while (waiting != (pthread_descr) 1) {
- th = waiting;
- waiting = waiting->p_nextwaiting;
- p = &towake;
- while (*p != NULL && th->p_priority < (*p)->p_priority)
- p = &((*p)->p_nextwaiting);
- th->p_nextwaiting = *p;
- *p = th;
- }
- /* Wake up threads in priority order */
- while (towake != NULL) {
- th = towake;
- towake = towake->p_nextwaiting;
- th->p_nextwaiting = NULL;
- restart(th);
- }
-}
-
-#if defined __PIC__ && defined DO_VERSIONING
-symbol_version (__old_sem_init, sem_init, GLIBC_2.0);
-symbol_version (__old_sem_wait, sem_wait, GLIBC_2.0);
-symbol_version (__old_sem_trywait, sem_trywait, GLIBC_2.0);
-symbol_version (__old_sem_post, sem_post, GLIBC_2.0);
-symbol_version (__old_sem_getvalue, sem_getvalue, GLIBC_2.0);
-symbol_version (__old_sem_destroy, sem_destroy, GLIBC_2.0);
-#endif
-
diff --git a/libpthread/linuxthreads/pt-machine.c b/libpthread/linuxthreads/pt-machine.c
deleted file mode 100644
index 438008d5d..000000000
--- a/libpthread/linuxthreads/pt-machine.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* "Instantiation of machine-dependent pthreads inline functions.
- Copyright (C) 1998 Free Software Foundation, Inc.
- This file is part of the 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. */
-
-#define PT_EI
-
-#include <pt-machine.h>
diff --git a/libpthread/linuxthreads/ptfork.c b/libpthread/linuxthreads/ptfork.c
deleted file mode 100644
index eb544f34b..000000000
--- a/libpthread/linuxthreads/ptfork.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* mods for uClibc: removed strong alias and defined funcs properly */
-
-/* The "atfork" stuff */
-
-#include <errno.h>
-
-#ifdef __ARCH_HAS_MMU__
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include "pthread.h"
-#include "internals.h"
-
-struct handler_list {
- void (*handler)(void);
- struct handler_list * next;
-};
-
-static pthread_mutex_t pthread_atfork_lock = PTHREAD_MUTEX_INITIALIZER;
-static struct handler_list * pthread_atfork_prepare = NULL;
-static struct handler_list * pthread_atfork_parent = NULL;
-static struct handler_list * pthread_atfork_child = NULL;
-
-static void pthread_insert_list(struct handler_list ** list,
- void (*handler)(void),
- struct handler_list * newlist,
- int at_end)
-{
- if (handler == NULL) return;
- if (at_end) {
- while(*list != NULL) list = &((*list)->next);
- }
- newlist->handler = handler;
- newlist->next = *list;
- *list = newlist;
-}
-
-struct handler_list_block {
- struct handler_list prepare, parent, child;
-};
-
-int pthread_atfork(void (*prepare)(void),
- void (*parent)(void),
- void (*child)(void))
-{
- struct handler_list_block * block =
- (struct handler_list_block *) malloc(sizeof(struct handler_list_block));
- if (block == NULL) return ENOMEM;
- pthread_mutex_lock(&pthread_atfork_lock);
- /* "prepare" handlers are called in LIFO */
- pthread_insert_list(&pthread_atfork_prepare, prepare, &block->prepare, 0);
- /* "parent" handlers are called in FIFO */
- pthread_insert_list(&pthread_atfork_parent, parent, &block->parent, 1);
- /* "child" handlers are called in FIFO */
- pthread_insert_list(&pthread_atfork_child, child, &block->child, 1);
- pthread_mutex_unlock(&pthread_atfork_lock);
- return 0;
-}
-//strong_alias (__pthread_atfork, pthread_atfork)
-
-static inline void pthread_call_handlers(struct handler_list * list)
-{
- for (/*nothing*/; list != NULL; list = list->next) (list->handler)();
-}
-
-extern int __libc_fork(void);
-
-pid_t __fork(void)
-{
- pid_t pid;
- struct handler_list * prepare, * child, * parent;
-
- pthread_mutex_lock(&pthread_atfork_lock);
- prepare = pthread_atfork_prepare;
- child = pthread_atfork_child;
- parent = pthread_atfork_parent;
- pthread_mutex_unlock(&pthread_atfork_lock);
- pthread_call_handlers(prepare);
- pid = __libc_fork();
- if (pid == 0) {
- __pthread_reset_main_thread();
- __fresetlockfiles();
- pthread_call_handlers(child);
- } else {
- pthread_call_handlers(parent);
- }
- return pid;
-}
-weak_alias (__fork, fork);
-
-pid_t __vfork(void)
-{
- return __fork();
-}
-weak_alias (__vfork, vfork);
-
-#else
-
-/* We can't support pthread_atfork without MMU, since we don't have
- fork(), and we can't offer the correct semantics for vfork(). */
-int pthread_atfork(void (*prepare)(void),
- void (*parent)(void),
- void (*child)(void))
-{
- /* ENOMEM is probably pushing it a little bit.
- Take it as `no *virtual* memory' :-) */
- errno = ENOMEM;
- return -1;
-}
-
-#endif
diff --git a/libpthread/linuxthreads/pthread.c b/libpthread/linuxthreads/pthread.c
deleted file mode 100644
index fed3d8c72..000000000
--- a/libpthread/linuxthreads/pthread.c
+++ /dev/null
@@ -1,1044 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Thread creation, initialization, and basic low-level routines */
-
-#define __FORCE_GLIBC
-#include <features.h>
-#define __USE_GNU
-#include <errno.h>
-#include <netdb.h> /* for h_errno */
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-#include <sys/resource.h>
-#include "pthread.h"
-#include "internals.h"
-#include "spinlock.h"
-#include "restart.h"
-#include "debug.h" /* added to linuxthreads -StS */
-
-
-/* Mods for uClibc: Some includes */
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/syscall.h>
-
-/* mods for uClibc: getpwd and getpagesize are the syscalls */
-#define __getpid getpid
-#define __getpagesize getpagesize
-/* mods for uClibc: __libc_sigaction is not in any standard headers */
-extern int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact);
-
-
-/* These variables are used by the setup code. */
-extern int _errno;
-extern int _h_errno;
-
-
-/* Descriptor of the initial thread */
-
-struct _pthread_descr_struct __pthread_initial_thread = {
- &__pthread_initial_thread, /* pthread_descr p_nextlive */
- &__pthread_initial_thread, /* pthread_descr p_prevlive */
- NULL, /* pthread_descr p_nextwaiting */
- NULL, /* pthread_descr p_nextlock */
- PTHREAD_THREADS_MAX, /* pthread_t p_tid */
- 0, /* int p_pid */
- 0, /* int p_priority */
- &__pthread_handles[0].h_lock, /* struct _pthread_fastlock * p_lock */
- 0, /* int p_signal */
- NULL, /* sigjmp_buf * p_signal_buf */
- NULL, /* sigjmp_buf * p_cancel_buf */
- 0, /* char p_terminated */
- 0, /* char p_detached */
- 0, /* char p_exited */
- NULL, /* void * p_retval */
- 0, /* int p_retval */
- NULL, /* pthread_descr p_joining */
- NULL, /* struct _pthread_cleanup_buffer * p_cleanup */
- 0, /* char p_cancelstate */
- 0, /* char p_canceltype */
- 0, /* char p_canceled */
- &_errno, /* int *p_errnop */
- 0, /* int p_errno */
- &_h_errno, /* int *p_h_errnop */
- 0, /* int p_h_errno */
- NULL, /* char * p_in_sighandler */
- 0, /* char p_sigwaiting */
- PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */
- {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
- {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
- 0, /* int p_userstack */
- NULL, /* void * p_guardaddr */
- 0, /* size_t p_guardsize */
- &__pthread_initial_thread, /* pthread_descr p_self */
- 0, /* Always index 0 */
- 0, /* int p_report_events */
- {{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */
- __ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */
- 0, /* char p_woken_by_cancel */
- 0, /* char p_condvar_avail */
- 0, /* char p_sem_avail */
- NULL, /* struct pthread_extricate_if *p_extricate */
- NULL, /* pthread_readlock_info *p_readlock_list; */
- NULL, /* pthread_readlock_info *p_readlock_free; */
- 0 /* int p_untracked_readlock_count; */
-#ifdef __UCLIBC_HAS_XLOCALE__
- ,
- &__global_locale_data, /* __locale_t locale; */
-#endif /* __UCLIBC_HAS_XLOCALE__ */
-};
-
-/* Descriptor of the manager thread; none of this is used but the error
- variables, the p_pid and p_priority fields,
- and the address for identification. */
-#define manager_thread (&__pthread_manager_thread)
-struct _pthread_descr_struct __pthread_manager_thread = {
- NULL, /* pthread_descr p_nextlive */
- NULL, /* pthread_descr p_prevlive */
- NULL, /* pthread_descr p_nextwaiting */
- NULL, /* pthread_descr p_nextlock */
- 0, /* int p_tid */
- 0, /* int p_pid */
- 0, /* int p_priority */
- &__pthread_handles[1].h_lock, /* struct _pthread_fastlock * p_lock */
- 0, /* int p_signal */
- NULL, /* sigjmp_buf * p_signal_buf */
- NULL, /* sigjmp_buf * p_cancel_buf */
- 0, /* char p_terminated */
- 0, /* char p_detached */
- 0, /* char p_exited */
- NULL, /* void * p_retval */
- 0, /* int p_retval */
- NULL, /* pthread_descr p_joining */
- NULL, /* struct _pthread_cleanup_buffer * p_cleanup */
- 0, /* char p_cancelstate */
- 0, /* char p_canceltype */
- 0, /* char p_canceled */
- &__pthread_manager_thread.p_errno, /* int *p_errnop */
- 0, /* int p_errno */
- NULL, /* int *p_h_errnop */
- 0, /* int p_h_errno */
- NULL, /* char * p_in_sighandler */
- 0, /* char p_sigwaiting */
- PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */
- {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
- {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
- 0, /* int p_userstack */
- NULL, /* void * p_guardaddr */
- 0, /* size_t p_guardsize */
- &__pthread_manager_thread, /* pthread_descr p_self */
- 1, /* Always index 1 */
- 0, /* int p_report_events */
- {{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */
- __ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */
- 0, /* char p_woken_by_cancel */
- 0, /* char p_condvar_avail */
- 0, /* char p_sem_avail */
- NULL, /* struct pthread_extricate_if *p_extricate */
- NULL, /* pthread_readlock_info *p_readlock_list; */
- NULL, /* pthread_readlock_info *p_readlock_free; */
- 0 /* int p_untracked_readlock_count; */
-#ifdef __UCLIBC_HAS_XLOCALE__
- ,
- &__global_locale_data, /* __locale_t locale; */
-#endif /* __UCLIBC_HAS_XLOCALE__ */
-};
-
-/* Pointer to the main thread (the father of the thread manager thread) */
-/* Originally, this is the initial thread, but this changes after fork() */
-
-pthread_descr __pthread_main_thread = &__pthread_initial_thread;
-
-/* Limit between the stack of the initial thread (above) and the
- stacks of other threads (below). Aligned on a STACK_SIZE boundary. */
-
-char *__pthread_initial_thread_bos = NULL;
-
-/* For non-MMU systems also remember to stack top of the initial thread.
- * This is adapted when other stacks are malloc'ed since we don't know
- * the bounds a-priori. -StS */
-
-#ifndef __ARCH_HAS_MMU__
-char *__pthread_initial_thread_tos = NULL;
-#endif /* __ARCH_HAS_MMU__ */
-
-/* File descriptor for sending requests to the thread manager. */
-/* Initially -1, meaning that the thread manager is not running. */
-
-int __pthread_manager_request = -1;
-
-/* Other end of the pipe for sending requests to the thread manager. */
-
-int __pthread_manager_reader;
-
-/* Limits of the thread manager stack */
-
-char *__pthread_manager_thread_bos = NULL;
-char *__pthread_manager_thread_tos = NULL;
-
-/* For process-wide exit() */
-
-int __pthread_exit_requested = 0;
-int __pthread_exit_code = 0;
-
-/* Communicate relevant LinuxThreads constants to gdb */
-
-const int __pthread_threads_max = PTHREAD_THREADS_MAX;
-const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct);
-const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct, h_descr);
-const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct,
- p_pid);
-const int __linuxthreads_pthread_sizeof_descr
- = sizeof(struct _pthread_descr_struct);
-
-const int __linuxthreads_initial_report_events;
-
-const char __linuxthreads_version[] = VERSION;
-
-/* Forward declarations */
-static void pthread_onexit_process(int retcode, void *arg);
-static void pthread_handle_sigcancel(int sig);
-static void pthread_handle_sigrestart(int sig);
-static void pthread_handle_sigdebug(int sig);
-int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime);
-
-/* Signal numbers used for the communication.
- In these variables we keep track of the used variables. If the
- platform does not support any real-time signals we will define the
- values to some unreasonable value which will signal failing of all
- the functions below. */
-#ifndef __NR_rt_sigaction
-static int current_rtmin = -1;
-static int current_rtmax = -1;
-int __pthread_sig_restart = SIGUSR1;
-int __pthread_sig_cancel = SIGUSR2;
-int __pthread_sig_debug;
-#else
-
-#if __SIGRTMAX - __SIGRTMIN >= 3
-static int current_rtmin = __SIGRTMIN + 3;
-static int current_rtmax = __SIGRTMAX;
-int __pthread_sig_restart = __SIGRTMIN;
-int __pthread_sig_cancel = __SIGRTMIN + 1;
-int __pthread_sig_debug = __SIGRTMIN + 2;
-void (*__pthread_restart)(pthread_descr) = __pthread_restart_new;
-void (*__pthread_suspend)(pthread_descr) = __pthread_wait_for_restart_signal;
-int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_new;
-#else
-static int current_rtmin = __SIGRTMIN;
-static int current_rtmax = __SIGRTMAX;
-int __pthread_sig_restart = SIGUSR1;
-int __pthread_sig_cancel = SIGUSR2;
-int __pthread_sig_debug;
-void (*__pthread_restart)(pthread_descr) = __pthread_restart_old;
-void (*__pthread_suspend)(pthread_descr) = __pthread_suspend_old;
-int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_old;
-
-#endif
-
-/* Return number of available real-time signal with highest priority. */
-int __libc_current_sigrtmin (void)
-{
- return current_rtmin;
-}
-
-/* Return number of available real-time signal with lowest priority. */
-int __libc_current_sigrtmax (void)
-{
- return current_rtmax;
-}
-
-/* Allocate real-time signal with highest/lowest available
- priority. Please note that we don't use a lock since we assume
- this function to be called at program start. */
-int __libc_allocate_rtsig (int high)
-{
- if (current_rtmin == -1 || current_rtmin > current_rtmax)
- /* We don't have anymore signal available. */
- return -1;
- return high ? current_rtmin++ : current_rtmax--;
-}
-#endif
-
-/* Initialize the pthread library.
- Initialization is split in two functions:
- - a constructor function that blocks the __pthread_sig_restart signal
- (must do this very early, since the program could capture the signal
- mask with e.g. sigsetjmp before creating the first thread);
- - a regular function called from pthread_create when needed. */
-
-static void pthread_initialize(void) __attribute__((constructor));
-
- /* Do some minimal initialization which has to be done during the
- startup of the C library. */
-void __pthread_initialize_minimal(void)
-{
- /* If we have special thread_self processing, initialize
- * that for the main thread now. */
-#ifdef INIT_THREAD_SELF
- INIT_THREAD_SELF(&__pthread_initial_thread, 0);
-#endif
-}
-
-
-static void pthread_initialize(void)
-{
- struct sigaction sa;
- sigset_t mask;
- struct rlimit limit;
- int max_stack;
-
- /* If already done (e.g. by a constructor called earlier!), bail out */
- if (__pthread_initial_thread_bos != NULL) return;
-#ifdef TEST_FOR_COMPARE_AND_SWAP
- /* Test if compare-and-swap is available */
- __pthread_has_cas = compare_and_swap_is_available();
-#endif
- /* For the initial stack, reserve at least STACK_SIZE bytes of stack
- below the current stack address, and align that on a
- STACK_SIZE boundary. */
- __pthread_initial_thread_bos =
- (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
- /* Update the descriptor for the initial thread. */
- __pthread_initial_thread.p_pid = __getpid();
- /* If we have special thread_self processing, initialize that for the
- main thread now. */
-#ifdef INIT_THREAD_SELF
- INIT_THREAD_SELF(&__pthread_initial_thread, 0);
-#endif
- /* The errno/h_errno variable of the main thread are the global ones. */
- __pthread_initial_thread.p_errnop = &_errno;
- __pthread_initial_thread.p_h_errnop = &_h_errno;
-
-#ifdef __UCLIBC_HAS_XLOCALE__
- /* The locale of the main thread is the current locale in use. */
- __pthread_initial_thread.locale = __curlocale_var;
-#endif /* __UCLIBC_HAS_XLOCALE__ */
-
- { /* uClibc-specific stdio initialization for threads. */
- FILE *fp;
-
- _stdio_user_locking = 0; /* 2 if threading not initialized */
- for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) {
- if (fp->__user_locking != 1) {
- fp->__user_locking = 0;
- }
- }
- }
-
- /* Play with the stack size limit to make sure that no stack ever grows
- beyond STACK_SIZE minus two pages (one page for the thread descriptor
- immediately beyond, and one page to act as a guard page). */
-
-#ifdef __ARCH_HAS_MMU__
- /* We cannot allocate a huge chunk of memory to mmap all thread stacks later
- * on a non-MMU system. Thus, we don't need the rlimit either. -StS */
- getrlimit(RLIMIT_STACK, &limit);
- max_stack = STACK_SIZE - 2 * __getpagesize();
- if (limit.rlim_cur > max_stack) {
- limit.rlim_cur = max_stack;
- setrlimit(RLIMIT_STACK, &limit);
- }
-#else
- /* For non-MMU assume __pthread_initial_thread_tos at upper page boundary, and
- * __pthread_initial_thread_bos at address 0. These bounds are refined as we
- * malloc other stack frames such that they don't overlap. -StS
- */
- __pthread_initial_thread_tos =
- (char *)(((long)CURRENT_STACK_FRAME + __getpagesize()) & ~(__getpagesize() - 1));
- __pthread_initial_thread_bos = (char *) 1; /* set it non-zero so we know we have been here */
- PDEBUG("initial thread stack bounds: bos=%p, tos=%p\n",
- __pthread_initial_thread_bos, __pthread_initial_thread_tos);
-#endif /* __ARCH_HAS_MMU__ */
-
- /* Setup signal handlers for the initial thread.
- Since signal handlers are shared between threads, these settings
- will be inherited by all other threads. */
- sa.sa_handler = pthread_handle_sigrestart;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- __libc_sigaction(__pthread_sig_restart, &sa, NULL);
- sa.sa_handler = pthread_handle_sigcancel;
- sigaddset(&sa.sa_mask, __pthread_sig_restart);
- // sa.sa_flags = 0;
- __libc_sigaction(__pthread_sig_cancel, &sa, NULL);
- if (__pthread_sig_debug > 0) {
- sa.sa_handler = pthread_handle_sigdebug;
- sigemptyset(&sa.sa_mask);
- // sa.sa_flags = 0;
- __libc_sigaction(__pthread_sig_debug, &sa, NULL);
- }
- /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */
- sigemptyset(&mask);
- sigaddset(&mask, __pthread_sig_restart);
- sigprocmask(SIG_BLOCK, &mask, NULL);
- /* And unblock __pthread_sig_cancel if it has been blocked. */
- sigdelset(&mask, __pthread_sig_restart);
- sigaddset(&mask, __pthread_sig_cancel);
- sigprocmask(SIG_UNBLOCK, &mask, NULL);
- /* Register an exit function to kill all other threads. */
- /* Do it early so that user-registered atexit functions are called
- before pthread_onexit_process. */
- on_exit(pthread_onexit_process, NULL);
-}
-
-void __pthread_initialize(void)
-{
- pthread_initialize();
-}
-
-int __pthread_initialize_manager(void)
-{
- int manager_pipe[2];
- int pid;
- int report_events;
- struct pthread_request request;
-
- /* If basic initialization not done yet (e.g. we're called from a
- constructor run before our constructor), do it now */
- if (__pthread_initial_thread_bos == NULL) pthread_initialize();
- /* Setup stack for thread manager */
- __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
- if (__pthread_manager_thread_bos == NULL) return -1;
- __pthread_manager_thread_tos =
- __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;
-
- /* On non-MMU systems we make sure that the initial thread bounds don't overlap
- * with the manager stack frame */
- NOMMU_INITIAL_THREAD_BOUNDS(__pthread_manager_thread_tos,__pthread_manager_thread_bos);
- PDEBUG("manager stack: size=%d, bos=%p, tos=%p\n", THREAD_MANAGER_STACK_SIZE,
- __pthread_manager_thread_bos, __pthread_manager_thread_tos);
-#if 0
- PDEBUG("initial stack: estimate bos=%p, tos=%p\n",
- __pthread_initial_thread_bos, __pthread_initial_thread_tos);
-#endif
-
- /* Setup pipe to communicate with thread manager */
- if (pipe(manager_pipe) == -1) {
- free(__pthread_manager_thread_bos);
- return -1;
- }
- /* Start the thread manager */
- pid = 0;
-#ifdef USE_TLS
- if (__linuxthreads_initial_report_events != 0)
- THREAD_SETMEM (((pthread_descr) NULL), p_report_events,
- __linuxthreads_initial_report_events);
- report_events = THREAD_GETMEM (((pthread_descr) NULL), p_report_events);
-#else
- if (__linuxthreads_initial_report_events != 0)
- __pthread_initial_thread.p_report_events
- = __linuxthreads_initial_report_events;
- report_events = __pthread_initial_thread.p_report_events;
-#endif
- if (__builtin_expect (report_events, 0))
- {
- /* It's a bit more complicated. We have to report the creation of
- the manager thread. */
- int idx = __td_eventword (TD_CREATE);
- uint32_t mask = __td_eventmask (TD_CREATE);
-
- if ((mask & (__pthread_threads_events.event_bits[idx]
- | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]))
- != 0)
- {
-
- __pthread_lock(__pthread_manager_thread.p_lock, NULL);
-
- pid = clone(__pthread_manager_event,
- (void **) __pthread_manager_thread_tos,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
- (void *)(long)manager_pipe[0]);
-
- if (pid != -1)
- {
- /* Now fill in the information about the new thread in
- the newly created thread's data structure. We cannot let
- the new thread do this since we don't know whether it was
- already scheduled when we send the event. */
- __pthread_manager_thread.p_eventbuf.eventdata =
- &__pthread_manager_thread;
- __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE;
- __pthread_last_event = &__pthread_manager_thread;
- __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
- __pthread_manager_thread.p_pid = pid;
-
- /* Now call the function which signals the event. */
- __linuxthreads_create_event ();
- }
- /* Now restart the thread. */
- __pthread_unlock(__pthread_manager_thread.p_lock);
- }
- }
-
- if (pid == 0) {
- pid = clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
- (void *)(long)manager_pipe[0]);
- }
- if (pid == -1) {
- free(__pthread_manager_thread_bos);
- __libc_close(manager_pipe[0]);
- __libc_close(manager_pipe[1]);
- return -1;
- }
- __pthread_manager_request = manager_pipe[1]; /* writing end */
- __pthread_manager_reader = manager_pipe[0]; /* reading end */
- __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
- __pthread_manager_thread.p_pid = pid;
-
- /* Make gdb aware of new thread manager */
- if (__pthread_threads_debug && __pthread_sig_debug > 0)
- {
- raise(__pthread_sig_debug);
- /* We suspend ourself and gdb will wake us up when it is
- ready to handle us. */
- __pthread_wait_for_restart_signal(thread_self());
- }
- /* Synchronize debugging of the thread manager */
- PDEBUG("send REQ_DEBUG to manager thread\n");
- request.req_kind = REQ_DEBUG;
- TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
- (char *) &request, sizeof(request)));
- return 0;
-}
-
-/* Thread creation */
-
-int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
- void * (*start_routine)(void *), void *arg)
-{
- pthread_descr self = thread_self();
- struct pthread_request request;
- if (__pthread_manager_request < 0) {
- if (__pthread_initialize_manager() < 0) return EAGAIN;
- }
- request.req_thread = self;
- request.req_kind = REQ_CREATE;
- request.req_args.create.attr = attr;
- request.req_args.create.fn = start_routine;
- request.req_args.create.arg = arg;
- sigprocmask(SIG_SETMASK, (const sigset_t *) NULL,
- &request.req_args.create.mask);
- PDEBUG("write REQ_CREATE to manager thread\n");
- TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
- (char *) &request, sizeof(request)));
- PDEBUG("before suspend(self)\n");
- suspend(self);
- PDEBUG("after suspend(self)\n");
- if (THREAD_GETMEM(self, p_retcode) == 0)
- *thread = (pthread_t) THREAD_GETMEM(self, p_retval);
- return THREAD_GETMEM(self, p_retcode);
-}
-
-/* Simple operations on thread identifiers */
-
-pthread_t pthread_self(void)
-{
- pthread_descr self = thread_self();
- return THREAD_GETMEM(self, p_tid);
-}
-
-int pthread_equal(pthread_t thread1, pthread_t thread2)
-{
- return thread1 == thread2;
-}
-
-/* Helper function for thread_self in the case of user-provided stacks */
-
-#ifndef THREAD_SELF
-
-pthread_descr __pthread_find_self()
-{
- char * sp = CURRENT_STACK_FRAME;
- pthread_handle h;
-
- /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is
- the manager threads handled specially in thread_self(), so start at 2 */
- h = __pthread_handles + 2;
- while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++;
-
-#ifdef DEBUG_PT
- if (h->h_descr == NULL) {
- printf("*** %s ERROR descriptor is NULL!!!!! ***\n\n", __FUNCTION__);
- _exit(1);
- }
-#endif
-
- return h->h_descr;
-}
-#else
-
-static pthread_descr thread_self_stack(void)
-{
- char *sp = CURRENT_STACK_FRAME;
- pthread_handle h;
-
- if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos)
- return manager_thread;
- h = __pthread_handles + 2;
-# ifdef USE_TLS
- while (h->h_descr == NULL
- || ! (sp <= (char *) h->h_descr->p_stackaddr && sp >= h->h_bottom))
- h++;
-# else
- while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom))
- h++;
-# endif
- return h->h_descr;
-}
-
-#endif
-
-/* Thread scheduling */
-
-int pthread_setschedparam(pthread_t thread, int policy,
- const struct sched_param *param)
-{
- pthread_handle handle = thread_handle(thread);
- pthread_descr th;
-
- __pthread_lock(&handle->h_lock, NULL);
- if (invalid_handle(handle, thread)) {
- __pthread_unlock(&handle->h_lock);
- return ESRCH;
- }
- th = handle->h_descr;
- if (sched_setscheduler(th->p_pid, policy, param) == -1) {
- __pthread_unlock(&handle->h_lock);
- return errno;
- }
- th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority;
- __pthread_unlock(&handle->h_lock);
- if (__pthread_manager_request >= 0)
- __pthread_manager_adjust_prio(th->p_priority);
- return 0;
-}
-
-int pthread_getschedparam(pthread_t thread, int *policy,
- struct sched_param *param)
-{
- pthread_handle handle = thread_handle(thread);
- int pid, pol;
-
- __pthread_lock(&handle->h_lock, NULL);
- if (invalid_handle(handle, thread)) {
- __pthread_unlock(&handle->h_lock);
- return ESRCH;
- }
- pid = handle->h_descr->p_pid;
- __pthread_unlock(&handle->h_lock);
- pol = sched_getscheduler(pid);
- if (pol == -1) return errno;
- if (sched_getparam(pid, param) == -1) return errno;
- *policy = pol;
- return 0;
-}
-
-/* Process-wide exit() request */
-
-static void pthread_onexit_process(int retcode, void *arg)
-{
- struct pthread_request request;
- pthread_descr self = thread_self();
-
- if (__pthread_manager_request >= 0) {
- request.req_thread = self;
- request.req_kind = REQ_PROCESS_EXIT;
- request.req_args.exit.code = retcode;
- TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
- (char *) &request, sizeof(request)));
- suspend(self);
- /* Main thread should accumulate times for thread manager and its
- children, so that timings for main thread account for all threads. */
- if (self == __pthread_main_thread) {
- waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
- /* Since all threads have been asynchronously terminated
- * (possibly holding locks), free cannot be used any more. */
- __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL;
- }
- }
-}
-
-/* The handler for the RESTART signal just records the signal received
- in the thread descriptor, and optionally performs a siglongjmp
- (for pthread_cond_timedwait). */
-
-static void pthread_handle_sigrestart(int sig)
-{
- pthread_descr self = thread_self();
- THREAD_SETMEM(self, p_signal, sig);
- if (THREAD_GETMEM(self, p_signal_jmp) != NULL)
- siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1);
-}
-
-/* The handler for the CANCEL signal checks for cancellation
- (in asynchronous mode), for process-wide exit and exec requests.
- For the thread manager thread, redirect the signal to
- __pthread_manager_sighandler. */
-
-static void pthread_handle_sigcancel(int sig)
-{
- pthread_descr self = thread_self();
- sigjmp_buf * jmpbuf;
-
-
- if (self == &__pthread_manager_thread)
- {
-#ifdef THREAD_SELF
- /* A new thread might get a cancel signal before it is fully
- initialized, so that the thread register might still point to the
- manager thread. Double check that this is really the manager
- thread. */
- pthread_descr real_self = thread_self_stack();
- if (real_self == &__pthread_manager_thread)
- {
- __pthread_manager_sighandler(sig);
- return;
- }
- /* Oops, thread_self() isn't working yet.. */
- self = real_self;
-# ifdef INIT_THREAD_SELF
- INIT_THREAD_SELF(self, self->p_nr);
-# endif
-#else
- __pthread_manager_sighandler(sig);
- return;
-#endif
- }
- if (__builtin_expect (__pthread_exit_requested, 0)) {
- /* Main thread should accumulate times for thread manager and its
- children, so that timings for main thread account for all threads. */
- if (self == __pthread_main_thread) {
-#ifdef USE_TLS
- waitpid(__pthread_manager_thread->p_pid, NULL, __WCLONE);
-#else
- waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
-#endif
- }
- _exit(__pthread_exit_code);
- }
- if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
- if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
- pthread_exit(PTHREAD_CANCELED);
- jmpbuf = THREAD_GETMEM(self, p_cancel_jmp);
- if (jmpbuf != NULL) {
- THREAD_SETMEM(self, p_cancel_jmp, NULL);
- siglongjmp(*jmpbuf, 1);
- }
- }
-}
-
-/* Handler for the DEBUG signal.
- The debugging strategy is as follows:
- On reception of a REQ_DEBUG request (sent by new threads created to
- the thread manager under debugging mode), the thread manager throws
- __pthread_sig_debug to itself. The debugger (if active) intercepts
- this signal, takes into account new threads and continue execution
- of the thread manager by propagating the signal because it doesn't
- know what it is specifically done for. In the current implementation,
- the thread manager simply discards it. */
-
-static void pthread_handle_sigdebug(int sig)
-{
- /* Nothing */
-}
-
-/* Reset the state of the thread machinery after a fork().
- Close the pipe used for requests and set the main thread to the forked
- thread.
- Notice that we can't free the stack segments, as the forked thread
- may hold pointers into them. */
-
-void __pthread_reset_main_thread()
-{
- pthread_descr self = thread_self();
-
- if (__pthread_manager_request != -1) {
- /* Free the thread manager stack */
- free(__pthread_manager_thread_bos);
- __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL;
- /* Close the two ends of the pipe */
- __libc_close(__pthread_manager_request);
- __libc_close(__pthread_manager_reader);
- __pthread_manager_request = __pthread_manager_reader = -1;
- }
-
- /* Update the pid of the main thread */
- THREAD_SETMEM(self, p_pid, __getpid());
- /* Make the forked thread the main thread */
- __pthread_main_thread = self;
- THREAD_SETMEM(self, p_nextlive, self);
- THREAD_SETMEM(self, p_prevlive, self);
- /* Now this thread modifies the global variables. */
- THREAD_SETMEM(self, p_errnop, &_errno);
- THREAD_SETMEM(self, p_h_errnop, &_h_errno);
-}
-
-/* Process-wide exec() request */
-
-void __pthread_kill_other_threads_np(void)
-{
- struct sigaction sa;
- /* Terminate all other threads and thread manager */
- pthread_onexit_process(0, NULL);
- /* Make current thread the main thread in case the calling thread
- changes its mind, does not exec(), and creates new threads instead. */
- __pthread_reset_main_thread();
- /* Reset the signal handlers behaviour for the signals the
- implementation uses since this would be passed to the new
- process. */
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = SIG_DFL;
- __libc_sigaction(__pthread_sig_restart, &sa, NULL);
- __libc_sigaction(__pthread_sig_cancel, &sa, NULL);
- if (__pthread_sig_debug > 0)
- __libc_sigaction(__pthread_sig_debug, &sa, NULL);
-}
-weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
-
-/* Concurrency symbol level. */
-static int current_level;
-
-int __pthread_setconcurrency(int level)
-{
- /* We don't do anything unless we have found a useful interpretation. */
- current_level = level;
- return 0;
-}
-weak_alias (__pthread_setconcurrency, pthread_setconcurrency)
-
-int __pthread_getconcurrency(void)
-{
- return current_level;
-}
-weak_alias (__pthread_getconcurrency, pthread_getconcurrency)
-
-
-/* Primitives for controlling thread execution */
-
-void __pthread_wait_for_restart_signal(pthread_descr self)
-{
- sigset_t mask;
-
- sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */
- sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */
- THREAD_SETMEM(self, p_signal, 0);
- do {
- sigsuspend(&mask); /* Wait for signal */
- } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart);
-
- READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */
-}
-
-#ifndef __NR_rt_sigaction
-/* The _old variants are for 2.0 and early 2.1 kernels which don't have RT
- signals.
- On these kernels, we use SIGUSR1 and SIGUSR2 for restart and cancellation.
- Since the restart signal does not queue, we use an atomic counter to create
- queuing semantics. This is needed to resolve a rare race condition in
- pthread_cond_timedwait_relative. */
-
-void __pthread_restart_old(pthread_descr th)
-{
- if (atomic_increment(&th->p_resume_count) == -1)
- kill(th->p_pid, __pthread_sig_restart);
-}
-
-void __pthread_suspend_old(pthread_descr self)
-{
- if (atomic_decrement(&self->p_resume_count) <= 0)
- __pthread_wait_for_restart_signal(self);
-}
-
-int
-__pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime)
-{
- sigset_t unblock, initial_mask;
- int was_signalled = 0;
- sigjmp_buf jmpbuf;
-
- if (atomic_decrement(&self->p_resume_count) == 0) {
- /* Set up a longjmp handler for the restart signal, unblock
- the signal and sleep. */
-
- if (sigsetjmp(jmpbuf, 1) == 0) {
- THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);
- THREAD_SETMEM(self, p_signal, 0);
- /* Unblock the restart signal */
- sigemptyset(&unblock);
- sigaddset(&unblock, __pthread_sig_restart);
- sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
-
- while (1) {
- struct timeval now;
- struct timespec reltime;
-
- /* Compute a time offset relative to now. */
- __gettimeofday (&now, NULL);
- reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
- reltime.tv_sec = abstime->tv_sec - now.tv_sec;
- if (reltime.tv_nsec < 0) {
- reltime.tv_nsec += 1000000000;
- reltime.tv_sec -= 1;
- }
-
- /* Sleep for the required duration. If woken by a signal,
- resume waiting as required by Single Unix Specification. */
- if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0)
- break;
- }
-
- /* Block the restart signal again */
- sigprocmask(SIG_SETMASK, &initial_mask, NULL);
- was_signalled = 0;
- } else {
- was_signalled = 1;
- }
- THREAD_SETMEM(self, p_signal_jmp, NULL);
- }
-
- /* Now was_signalled is true if we exited the above code
- due to the delivery of a restart signal. In that case,
- we know we have been dequeued and resumed and that the
- resume count is balanced. Otherwise, there are some
- cases to consider. First, try to bump up the resume count
- back to zero. If it goes to 1, it means restart() was
- invoked on this thread. The signal must be consumed
- and the count bumped down and everything is cool. We
- can return a 1 to the caller.
- Otherwise, no restart was delivered yet, so a potential
- race exists; we return a 0 to the caller which must deal
- with this race in an appropriate way; for example by
- atomically removing the thread from consideration for a
- wakeup---if such a thing fails, it means a restart is
- being delivered. */
-
- if (!was_signalled) {
- if (atomic_increment(&self->p_resume_count) != -1) {
- __pthread_wait_for_restart_signal(self);
- atomic_decrement(&self->p_resume_count); /* should be zero now! */
- /* woke spontaneously and consumed restart signal */
- return 1;
- }
- /* woke spontaneously but did not consume restart---caller must resolve */
- return 0;
- }
- /* woken due to restart signal */
- return 1;
-}
-#endif /* __NR_rt_sigaction */
-
-
-#ifdef __NR_rt_sigaction
-void __pthread_restart_new(pthread_descr th)
-{
- /* The barrier is proabably not needed, in which case it still documents
- our assumptions. The intent is to commit previous writes to shared
- memory so the woken thread will have a consistent view. Complementary
- read barriers are present to the suspend functions. */
- WRITE_MEMORY_BARRIER();
- kill(th->p_pid, __pthread_sig_restart);
-}
-
-int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime)
-{
- sigset_t unblock, initial_mask;
- int was_signalled = 0;
- sigjmp_buf jmpbuf;
-
- if (sigsetjmp(jmpbuf, 1) == 0) {
- THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);
- THREAD_SETMEM(self, p_signal, 0);
- /* Unblock the restart signal */
- sigemptyset(&unblock);
- sigaddset(&unblock, __pthread_sig_restart);
- sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
-
- while (1) {
- struct timeval now;
- struct timespec reltime;
-
- /* Compute a time offset relative to now. */
- gettimeofday (&now, NULL);
- reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
- reltime.tv_sec = abstime->tv_sec - now.tv_sec;
- if (reltime.tv_nsec < 0) {
- reltime.tv_nsec += 1000000000;
- reltime.tv_sec -= 1;
- }
-
- /* Sleep for the required duration. If woken by a signal,
- resume waiting as required by Single Unix Specification. */
- if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0)
- break;
- }
-
- /* Block the restart signal again */
- sigprocmask(SIG_SETMASK, &initial_mask, NULL);
- was_signalled = 0;
- } else {
- was_signalled = 1;
- }
- THREAD_SETMEM(self, p_signal_jmp, NULL);
-
- /* Now was_signalled is true if we exited the above code
- due to the delivery of a restart signal. In that case,
- everything is cool. We have been removed from whatever
- we were waiting on by the other thread, and consumed its signal.
-
- Otherwise we this thread woke up spontaneously, or due to a signal other
- than restart. This is an ambiguous case that must be resolved by
- the caller; the thread is still eligible for a restart wakeup
- so there is a race. */
-
- READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */
- return was_signalled;
-}
-#endif
-
-/* Debugging aid */
-
-#ifdef DEBUG_PT
-#include <stdarg.h>
-
-void __pthread_message(char * fmt, ...)
-{
- char buffer[1024];
- va_list args;
- sprintf(buffer, "%05d : ", __getpid());
- va_start(args, fmt);
- vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args);
- va_end(args);
- TEMP_FAILURE_RETRY(__libc_write(2, buffer, strlen(buffer)));
-}
-
-#endif
-
-
-#ifndef __PIC__
-/* We need a hook to force the cancelation wrappers to be linked in when
- static libpthread is used. */
-extern const int __pthread_provide_wrappers;
-static const int *const __pthread_require_wrappers =
- &__pthread_provide_wrappers;
-#endif
diff --git a/libpthread/linuxthreads/pthread.c-OLDEXAMPLE b/libpthread/linuxthreads/pthread.c-OLDEXAMPLE
deleted file mode 100644
index 88b163087..000000000
--- a/libpthread/linuxthreads/pthread.c-OLDEXAMPLE
+++ /dev/null
@@ -1,121 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * A _very_ simple clone based pthread-like implementation
- *
- * Copyright (C) 2001,2002 by Erik Andersen <andersee@debian.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <stdlib.h>
-#include <sched.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <pthread.h>
-
-#define STACKSIZE 8096
-
-#define CSIGNAL 0x000000ff /* signal mask to be sent at exit */
-#define CLONE_VM 0x00000100 /* set if VM shared between processes */
-#define CLONE_FS 0x00000200 /* set if fs info shared between proces ses */
-#define CLONE_FILES 0x00000400 /* set if open files shared between pro cesses */
-#define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */
-
-
-
-/* Lame home-grown clone based threading */
-int pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutex_attr)
-{
- mutex->__m_lock.__spinlock = 1;
- return 0;
-}
-
-int pthread_mutex_lock (pthread_mutex_t *mutex)
-{
- while (mutex->__m_lock.__spinlock == 0) {
- usleep(10000);
- }
- --(mutex->__m_lock.__spinlock);
- return 0;
-}
-
-int pthread_mutex_unlock (pthread_mutex_t *mutex)
-{
- ++(mutex->__m_lock.__spinlock);
- return 0;
-}
-
-int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
-{
- ++(mutex->__m_lock.__spinlock);
- while (cond->__c_lock.__spinlock == 0) {
- usleep(10000);
- }
- --(cond->__c_lock.__spinlock);
- return 0;
-}
-
-int pthread_cond_signal(pthread_cond_t *cond)
-{
- ++(cond->__c_lock.__spinlock);
- return 0;
-}
-
-int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
-{
- cond->__c_lock.__spinlock = 1;
- return 0;
-}
-
-int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void* (*fn)(void *), void *data)
-{
- long retval;
- void **newstack;
- int (*clonefunc)(void *) = (int (*)(void *))(fn);
-
- newstack = (void **) malloc(STACKSIZE);
- if (!newstack)
- return -1;
- newstack = (void **) (STACKSIZE + (char *) newstack);
- *--newstack = data;
- retval = clone(clonefunc, newstack,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD, data);
- if (retval < 0) {
- errno = -retval;
- *thread = 0;
- retval = -1;
- } else {
- *thread = retval;
- retval = 0;
- }
- return retval;
-}
-
-int pthread_join (pthread_t thread, void **thread_return)
-{
- int retval;
- /* Fixme -- wait for thread and get its return value */
- retval = EXIT_SUCCESS;
- if (thread_return)
- (int)*thread_return = retval;
- _exit(retval);
-}
-link_warning(pthread_join, "pthread_join is a stub and does not behave properly");
-
-void pthread_exit (void *retval)
-{
- _exit(*(int *)retval);
-}
diff --git a/libpthread/linuxthreads/ptlongjmp.c b/libpthread/linuxthreads/ptlongjmp.c
deleted file mode 100644
index c0ea8223a..000000000
--- a/libpthread/linuxthreads/ptlongjmp.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Redefine siglongjmp and longjmp so that they interact correctly
- with cleanup handlers */
-
-#include <setjmp.h>
-#include "pthread.h"
-#include "internals.h"
-
-/* These functions are not declared anywhere since they shouldn't be
- used at another place but here. */
-extern void __libc_siglongjmp (sigjmp_buf env, int val)
- __attribute__ ((noreturn));
-extern void __libc_longjmp (sigjmp_buf env, int val)
- __attribute__ ((noreturn));
-
-
-static void pthread_cleanup_upto(__jmp_buf target)
-{
- pthread_descr self = thread_self();
- struct _pthread_cleanup_buffer * c;
-
- for (c = THREAD_GETMEM(self, p_cleanup);
- c != NULL && _JMPBUF_UNWINDS(target, c);
- c = c->__prev)
- c->__routine(c->__arg);
- THREAD_SETMEM(self, p_cleanup, c);
- if (THREAD_GETMEM(self, p_in_sighandler)
- && _JMPBUF_UNWINDS(target, THREAD_GETMEM(self, p_in_sighandler)))
- THREAD_SETMEM(self, p_in_sighandler, NULL);
-}
-
-void siglongjmp(sigjmp_buf env, int val)
-{
- pthread_cleanup_upto(env->__jmpbuf);
- __libc_siglongjmp(env, val);
-}
-
-void longjmp(jmp_buf env, int val)
-{
- pthread_cleanup_upto(env->__jmpbuf);
- __libc_siglongjmp(env, val);
-}
diff --git a/libpthread/linuxthreads/queue.h b/libpthread/linuxthreads/queue.h
deleted file mode 100644
index 28bd75531..000000000
--- a/libpthread/linuxthreads/queue.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Waiting queues */
-
-/* Waiting queues are represented by lists of thread descriptors
- linked through their p_nextwaiting field. The lists are kept
- sorted by decreasing priority, and then decreasing waiting time. */
-
-static inline void enqueue(pthread_descr * q, pthread_descr th)
-{
- int prio = th->p_priority;
- ASSERT(th->p_nextwaiting == NULL);
- for (; *q != NULL; q = &((*q)->p_nextwaiting)) {
- if (prio > (*q)->p_priority) {
- th->p_nextwaiting = *q;
- *q = th;
- return;
- }
- }
- *q = th;
-}
-
-static inline pthread_descr dequeue(pthread_descr * q)
-{
- pthread_descr th;
- th = *q;
- if (th != NULL) {
- *q = th->p_nextwaiting;
- th->p_nextwaiting = NULL;
- }
- return th;
-}
-
-static inline int remove_from_queue(pthread_descr * q, pthread_descr th)
-{
- for (; *q != NULL; q = &((*q)->p_nextwaiting)) {
- if (*q == th) {
- *q = th->p_nextwaiting;
- th->p_nextwaiting = NULL;
- return 1;
- }
- }
- return 0;
-}
-
-static inline int queue_is_empty(pthread_descr * q)
-{
- return *q == NULL;
-}
diff --git a/libpthread/linuxthreads/restart.h b/libpthread/linuxthreads/restart.h
deleted file mode 100644
index 687d92fae..000000000
--- a/libpthread/linuxthreads/restart.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-#include <signal.h>
-#include <sys/syscall.h>
-#define __ASSUME_REALTIME_SIGNALS defined(__NR_rt_sigaction)
-
-/* Primitives for controlling thread execution */
-
-static inline void restart(pthread_descr th)
-{
- /* See pthread.c */
-#if __ASSUME_REALTIME_SIGNALS
- __pthread_restart_new(th);
-#else
- __pthread_restart(th);
-#endif
-}
-
-static inline void suspend(pthread_descr self)
-{
- /* See pthread.c */
-#if __ASSUME_REALTIME_SIGNALS
- __pthread_wait_for_restart_signal(self);
-#else
- __pthread_suspend(self);
-#endif
-}
-
-static inline int timedsuspend(pthread_descr self,
- const struct timespec *abstime)
-{
- /* See pthread.c */
-#if __ASSUME_REALTIME_SIGNALS
- return __pthread_timedsuspend_new(self, abstime);
-#else
- return __pthread_timedsuspend(self, abstime);
-#endif
-}
diff --git a/libpthread/linuxthreads/rwlock.c b/libpthread/linuxthreads/rwlock.c
deleted file mode 100644
index 977fd88af..000000000
--- a/libpthread/linuxthreads/rwlock.c
+++ /dev/null
@@ -1,486 +0,0 @@
-/* Read-write lock implementation.
- Copyright (C) 1998 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Xavier Leroy <Xavier.Leroy@inria.fr>
- and Ulrich Drepper <drepper@cygnus.com>, 1998.
-
- 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 <stdlib.h>
-#include "internals.h"
-#include "queue.h"
-#include "spinlock.h"
-#include "restart.h"
-
-/*
- * Check whether the calling thread already owns one or more read locks on the
- * specified lock. If so, return a pointer to the read lock info structure
- * corresponding to that lock.
- */
-
-static pthread_readlock_info *
-rwlock_is_in_list(pthread_descr self, pthread_rwlock_t *rwlock)
-{
- pthread_readlock_info *info;
-
- for (info = self->p_readlock_list; info != NULL; info = info->pr_next)
- {
- if (info->pr_lock == rwlock)
- return info;
- }
-
- return NULL;
-}
-
-/*
- * Add a new lock to the thread's list of locks for which it has a read lock.
- * A new info node must be allocated for this, which is taken from the thread's
- * free list, or by calling malloc. If malloc fails, a null pointer is
- * returned. Otherwise the lock info structure is initialized and pushed
- * onto the thread's list.
- */
-
-static pthread_readlock_info *
-rwlock_add_to_list(pthread_descr self, pthread_rwlock_t *rwlock)
-{
- pthread_readlock_info *info = self->p_readlock_free;
-
- if (info != NULL)
- self->p_readlock_free = info->pr_next;
- else
- info = malloc(sizeof *info);
-
- if (info == NULL)
- return NULL;
-
- info->pr_lock_count = 1;
- info->pr_lock = rwlock;
- info->pr_next = self->p_readlock_list;
- self->p_readlock_list = info;
-
- return info;
-}
-
-/*
- * If the thread owns a read lock over the given pthread_rwlock_t,
- * and this read lock is tracked in the thread's lock list,
- * this function returns a pointer to the info node in that list.
- * It also decrements the lock count within that node, and if
- * it reaches zero, it removes the node from the list.
- * If nothing is found, it returns a null pointer.
- */
-
-static pthread_readlock_info *
-rwlock_remove_from_list(pthread_descr self, pthread_rwlock_t *rwlock)
-{
- pthread_readlock_info **pinfo;
-
- for (pinfo = &self->p_readlock_list; *pinfo != NULL; pinfo = &(*pinfo)->pr_next)
- {
- if ((*pinfo)->pr_lock == rwlock)
- {
- pthread_readlock_info *info = *pinfo;
- if (--info->pr_lock_count == 0)
- *pinfo = info->pr_next;
- return info;
- }
- }
-
- return NULL;
-}
-
-/*
- * This function checks whether the conditions are right to place a read lock.
- * It returns 1 if so, otherwise zero. The rwlock's internal lock must be
- * locked upon entry.
- */
-
-static int
-rwlock_can_rdlock(pthread_rwlock_t *rwlock, int have_lock_already)
-{
- /* Can't readlock; it is write locked. */
- if (rwlock->__rw_writer != NULL)
- return 0;
-
- /* Lock prefers readers; get it. */
- if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
- return 1;
-
- /* Lock prefers writers, but none are waiting. */
- if (queue_is_empty(&rwlock->__rw_write_waiting))
- return 1;
-
- /* Writers are waiting, but this thread already has a read lock */
- if (have_lock_already)
- return 1;
-
- /* Writers are waiting, and this is a new lock */
- return 0;
-}
-
-/*
- * This function helps support brain-damaged recursive read locking
- * semantics required by Unix 98, while maintaining write priority.
- * This basically determines whether this thread already holds a read lock
- * already. It returns 1 if so, otherwise it returns 0.
- *
- * If the thread has any ``untracked read locks'' then it just assumes
- * that this lock is among them, just to be safe, and returns 1.
- *
- * Also, if it finds the thread's lock in the list, it sets the pointer
- * referenced by pexisting to refer to the list entry.
- *
- * If the thread has no untracked locks, and the lock is not found
- * in its list, then it is added to the list. If this fails,
- * then *pout_of_mem is set to 1.
- */
-
-static int
-rwlock_have_already(pthread_descr *pself, pthread_rwlock_t *rwlock,
- pthread_readlock_info **pexisting, int *pout_of_mem)
-{
- pthread_readlock_info *existing = NULL;
- int out_of_mem = 0, have_lock_already = 0;
- pthread_descr self = *pself;
-
- if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP)
- {
- if (!self)
- self = thread_self();
-
- existing = rwlock_is_in_list(self, rwlock);
-
- if (existing != NULL || self->p_untracked_readlock_count > 0)
- have_lock_already = 1;
- else
- {
- existing = rwlock_add_to_list(self, rwlock);
- if (existing == NULL)
- out_of_mem = 1;
- }
- }
-
- *pout_of_mem = out_of_mem;
- *pexisting = existing;
- *pself = self;
-
- return have_lock_already;
-}
-
-int
-pthread_rwlock_init (pthread_rwlock_t *rwlock,
- const pthread_rwlockattr_t *attr)
-{
- __pthread_init_lock(&rwlock->__rw_lock);
- rwlock->__rw_readers = 0;
- rwlock->__rw_writer = NULL;
- rwlock->__rw_read_waiting = NULL;
- rwlock->__rw_write_waiting = NULL;
-
- if (attr == NULL)
- {
- rwlock->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
- rwlock->__rw_pshared = PTHREAD_PROCESS_PRIVATE;
- }
- else
- {
- rwlock->__rw_kind = attr->__lockkind;
- rwlock->__rw_pshared = attr->__pshared;
- }
-
- return 0;
-}
-
-
-int
-pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
-{
- int readers;
- _pthread_descr writer;
-
- __pthread_lock (&rwlock->__rw_lock, NULL);
- readers = rwlock->__rw_readers;
- writer = rwlock->__rw_writer;
- __pthread_unlock (&rwlock->__rw_lock);
-
- if (readers > 0 || writer != NULL)
- return EBUSY;
-
- return 0;
-}
-
-int
-pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
-{
- pthread_descr self = NULL;
- pthread_readlock_info *existing;
- int out_of_mem, have_lock_already;
-
- have_lock_already = rwlock_have_already(&self, rwlock,
- &existing, &out_of_mem);
-
- for (;;)
- {
- if (self == NULL)
- self = thread_self ();
-
- __pthread_lock (&rwlock->__rw_lock, self);
-
- if (rwlock_can_rdlock(rwlock, have_lock_already))
- break;
-
- enqueue (&rwlock->__rw_read_waiting, self);
- __pthread_unlock (&rwlock->__rw_lock);
- suspend (self); /* This is not a cancellation point */
- }
-
- ++rwlock->__rw_readers;
- __pthread_unlock (&rwlock->__rw_lock);
-
- if (have_lock_already || out_of_mem)
- {
- if (existing != NULL)
- existing->pr_lock_count++;
- else
- self->p_untracked_readlock_count++;
- }
-
- return 0;
-}
-
-int
-pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
-{
- pthread_descr self = thread_self();
- pthread_readlock_info *existing;
- int out_of_mem, have_lock_already;
- int retval = EBUSY;
-
- have_lock_already = rwlock_have_already(&self, rwlock,
- &existing, &out_of_mem);
-
- __pthread_lock (&rwlock->__rw_lock, self);
-
- /* 0 is passed to here instead of have_lock_already.
- This is to meet Single Unix Spec requirements:
- if writers are waiting, pthread_rwlock_tryrdlock
- does not acquire a read lock, even if the caller has
- one or more read locks already. */
-
- if (rwlock_can_rdlock(rwlock, 0))
- {
- ++rwlock->__rw_readers;
- retval = 0;
- }
-
- __pthread_unlock (&rwlock->__rw_lock);
-
- if (retval == 0)
- {
- if (have_lock_already || out_of_mem)
- {
- if (existing != NULL)
- existing->pr_lock_count++;
- else
- self->p_untracked_readlock_count++;
- }
- }
-
- return retval;
-}
-
-
-int
-pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
-{
- pthread_descr self = thread_self ();
-
- while(1)
- {
- __pthread_lock (&rwlock->__rw_lock, self);
- if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL)
- {
- rwlock->__rw_writer = self;
- __pthread_unlock (&rwlock->__rw_lock);
- return 0;
- }
-
- /* Suspend ourselves, then try again */
- enqueue (&rwlock->__rw_write_waiting, self);
- __pthread_unlock (&rwlock->__rw_lock);
- suspend (self); /* This is not a cancellation point */
- }
-}
-
-
-int
-pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
-{
- int result = EBUSY;
-
- __pthread_lock (&rwlock->__rw_lock, NULL);
- if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL)
- {
- rwlock->__rw_writer = thread_self ();
- result = 0;
- }
- __pthread_unlock (&rwlock->__rw_lock);
-
- return result;
-}
-
-
-int
-pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
-{
- pthread_descr torestart;
- pthread_descr th;
-
- __pthread_lock (&rwlock->__rw_lock, NULL);
- if (rwlock->__rw_writer != NULL)
- {
- /* Unlocking a write lock. */
- if (rwlock->__rw_writer != thread_self ())
- {
- __pthread_unlock (&rwlock->__rw_lock);
- return EPERM;
- }
- rwlock->__rw_writer = NULL;
-
- if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP
- || (th = dequeue (&rwlock->__rw_write_waiting)) == NULL)
- {
- /* Restart all waiting readers. */
- torestart = rwlock->__rw_read_waiting;
- rwlock->__rw_read_waiting = NULL;
- __pthread_unlock (&rwlock->__rw_lock);
- while ((th = dequeue (&torestart)) != NULL)
- restart (th);
- }
- else
- {
- /* Restart one waiting writer. */
- __pthread_unlock (&rwlock->__rw_lock);
- restart (th);
- }
- }
- else
- {
- /* Unlocking a read lock. */
- if (rwlock->__rw_readers == 0)
- {
- __pthread_unlock (&rwlock->__rw_lock);
- return EPERM;
- }
-
- --rwlock->__rw_readers;
- if (rwlock->__rw_readers == 0)
- /* Restart one waiting writer, if any. */
- th = dequeue (&rwlock->__rw_write_waiting);
- else
- th = NULL;
-
- __pthread_unlock (&rwlock->__rw_lock);
- if (th != NULL)
- restart (th);
-
- /* Recursive lock fixup */
-
- if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP)
- {
- pthread_descr self = thread_self();
- pthread_readlock_info *victim = rwlock_remove_from_list(self, rwlock);
-
- if (victim != NULL)
- {
- if (victim->pr_lock_count == 0)
- {
- victim->pr_next = self->p_readlock_free;
- self->p_readlock_free = victim;
- }
- }
- else
- {
- if (self->p_untracked_readlock_count > 0)
- self->p_untracked_readlock_count--;
- }
- }
- }
-
- return 0;
-}
-
-
-
-int
-pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
-{
- attr->__lockkind = 0;
- attr->__pshared = 0;
-
- return 0;
-}
-
-
-int
-pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
-{
- return 0;
-}
-
-
-int
-pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared)
-{
- *pshared = attr->__pshared;
- return 0;
-}
-
-
-int
-pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
-{
- if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
- return EINVAL;
-
- attr->__pshared = pshared;
-
- return 0;
-}
-
-
-int
-pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *attr, int *pref)
-{
- *pref = attr->__lockkind;
- return 0;
-}
-
-
-int
-pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref)
-{
- if (pref != PTHREAD_RWLOCK_PREFER_READER_NP
- && pref != PTHREAD_RWLOCK_PREFER_WRITER_NP
- && pref != PTHREAD_RWLOCK_DEFAULT_NP)
- return EINVAL;
-
- attr->__lockkind = pref;
-
- return 0;
-}
diff --git a/libpthread/linuxthreads/semaphore.c b/libpthread/linuxthreads/semaphore.c
deleted file mode 100644
index 5be1f5316..000000000
--- a/libpthread/linuxthreads/semaphore.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Semaphores a la POSIX 1003.1b */
-
-#include <features.h>
-#define __USE_GNU
-#include <errno.h>
-#include "pthread.h"
-#include "semaphore.h"
-#include "internals.h"
-#include "spinlock.h"
-#include "restart.h"
-#include "queue.h"
-
-int __new_sem_init(sem_t *sem, int pshared, unsigned int value)
-{
- if (value > SEM_VALUE_MAX) {
- errno = EINVAL;
- return -1;
- }
- if (pshared) {
- errno = ENOSYS;
- return -1;
- }
- __pthread_init_lock(&sem->__sem_lock);
- sem->__sem_value = value;
- sem->__sem_waiting = NULL;
- return 0;
-}
-
-/* Function called by pthread_cancel to remove the thread from
- waiting inside __new_sem_wait. */
-
-static int new_sem_extricate_func(void *obj, pthread_descr th)
-{
- volatile pthread_descr self = thread_self();
- sem_t *sem = obj;
- int did_remove = 0;
-
- __pthread_lock(&sem->__sem_lock, self);
- did_remove = remove_from_queue(&sem->__sem_waiting, th);
- __pthread_unlock(&sem->__sem_lock);
-
- return did_remove;
-}
-
-int __new_sem_wait(sem_t * sem)
-{
- volatile pthread_descr self = thread_self();
- pthread_extricate_if extr;
- int already_canceled = 0;
- int spurious_wakeup_count;
-
- /* Set up extrication interface */
- extr.pu_object = sem;
- extr.pu_extricate_func = new_sem_extricate_func;
-
- __pthread_lock(&sem->__sem_lock, self);
- if (sem->__sem_value > 0) {
- sem->__sem_value--;
- __pthread_unlock(&sem->__sem_lock);
- return 0;
- }
- /* Register extrication interface */
- THREAD_SETMEM(self, p_sem_avail, 0);
- __pthread_set_own_extricate_if(self, &extr);
- /* Enqueue only if not already cancelled. */
- if (!(THREAD_GETMEM(self, p_canceled)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
- enqueue(&sem->__sem_waiting, self);
- else
- already_canceled = 1;
- __pthread_unlock(&sem->__sem_lock);
-
- if (already_canceled) {
- __pthread_set_own_extricate_if(self, 0);
- pthread_exit(PTHREAD_CANCELED);
- }
-
- /* Wait for sem_post or cancellation, or fall through if already canceled */
- spurious_wakeup_count = 0;
- while (1)
- {
- suspend(self);
- if (THREAD_GETMEM(self, p_sem_avail) == 0
- && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
- || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
- {
- /* Count resumes that don't belong to us. */
- spurious_wakeup_count++;
- continue;
- }
- break;
- }
- __pthread_set_own_extricate_if(self, 0);
-
- /* Terminate only if the wakeup came from cancellation. */
- /* Otherwise ignore cancellation because we got the semaphore. */
-
- if (THREAD_GETMEM(self, p_woken_by_cancel)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
- THREAD_SETMEM(self, p_woken_by_cancel, 0);
- pthread_exit(PTHREAD_CANCELED);
- }
- /* We got the semaphore */
- return 0;
-}
-
-int __new_sem_trywait(sem_t * sem)
-{
- int retval;
-
- __pthread_lock(&sem->__sem_lock, NULL);
- if (sem->__sem_value == 0) {
- errno = EAGAIN;
- retval = -1;
- } else {
- sem->__sem_value--;
- retval = 0;
- }
- __pthread_unlock(&sem->__sem_lock);
- return retval;
-}
-
-int __new_sem_post(sem_t * sem)
-{
- pthread_descr self = thread_self();
- pthread_descr th;
- struct pthread_request request;
-
- if (THREAD_GETMEM(self, p_in_sighandler) == NULL) {
- __pthread_lock(&sem->__sem_lock, self);
- if (sem->__sem_waiting == NULL) {
- if (sem->__sem_value >= SEM_VALUE_MAX) {
- /* Overflow */
- errno = ERANGE;
- __pthread_unlock(&sem->__sem_lock);
- return -1;
- }
- sem->__sem_value++;
- __pthread_unlock(&sem->__sem_lock);
- } else {
- th = dequeue(&sem->__sem_waiting);
- __pthread_unlock(&sem->__sem_lock);
- th->p_sem_avail = 1;
- WRITE_MEMORY_BARRIER();
- restart(th);
- }
- } else {
- /* If we're in signal handler, delegate post operation to
- the thread manager. */
- if (__pthread_manager_request < 0) {
- if (__pthread_initialize_manager() < 0) {
- errno = EAGAIN;
- return -1;
- }
- }
- request.req_kind = REQ_POST;
- request.req_args.post = sem;
- TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
- (char *) &request, sizeof(request)));
- }
- return 0;
-}
-
-int __new_sem_getvalue(sem_t * sem, int * sval)
-{
- *sval = sem->__sem_value;
- return 0;
-}
-
-int __new_sem_destroy(sem_t * sem)
-{
- if (sem->__sem_waiting != NULL) {
- __set_errno (EBUSY);
- return -1;
- }
- return 0;
-}
-
-sem_t *sem_open(const char *name, int oflag, ...)
-{
- __set_errno (ENOSYS);
- return SEM_FAILED;
-}
-
-int sem_close(sem_t *sem)
-{
- __set_errno (ENOSYS);
- return -1;
-}
-
-int sem_unlink(const char *name)
-{
- __set_errno (ENOSYS);
- return -1;
-}
-
-int sem_timedwait(sem_t *sem, const struct timespec *abstime)
-{
- pthread_descr self = thread_self();
- pthread_extricate_if extr;
- int already_canceled = 0;
- int spurious_wakeup_count;
-
- __pthread_lock(&sem->__sem_lock, self);
- if (sem->__sem_value > 0) {
- --sem->__sem_value;
- __pthread_unlock(&sem->__sem_lock);
- return 0;
- }
-
- if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) {
- /* The standard requires that if the function would block and the
- time value is illegal, the function returns with an error. */
- __pthread_unlock(&sem->__sem_lock);
- __set_errno (EINVAL);
- return -1;
- }
-
- /* Set up extrication interface */
- extr.pu_object = sem;
- extr.pu_extricate_func = new_sem_extricate_func;
-
- /* Register extrication interface */
- THREAD_SETMEM(self, p_sem_avail, 0);
- __pthread_set_own_extricate_if(self, &extr);
- /* Enqueue only if not already cancelled. */
- if (!(THREAD_GETMEM(self, p_canceled)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
- enqueue(&sem->__sem_waiting, self);
- else
- already_canceled = 1;
- __pthread_unlock(&sem->__sem_lock);
-
- if (already_canceled) {
- __pthread_set_own_extricate_if(self, 0);
- pthread_exit(PTHREAD_CANCELED);
- }
-
- spurious_wakeup_count = 0;
- while (1)
- {
- if (timedsuspend(self, abstime) == 0) {
- int was_on_queue;
-
- /* __pthread_lock will queue back any spurious restarts that
- may happen to it. */
-
- __pthread_lock(&sem->__sem_lock, self);
- was_on_queue = remove_from_queue(&sem->__sem_waiting, self);
- __pthread_unlock(&sem->__sem_lock);
-
- if (was_on_queue) {
- __pthread_set_own_extricate_if(self, 0);
- __set_errno (ETIMEDOUT);
- return -1;
- }
-
- /* Eat the outstanding restart() from the signaller */
- suspend(self);
- }
-
- if (THREAD_GETMEM(self, p_sem_avail) == 0
- && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
- || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
- {
- /* Count resumes that don't belong to us. */
- spurious_wakeup_count++;
- continue;
- }
- break;
- }
-
- __pthread_set_own_extricate_if(self, 0);
-
- /* Terminate only if the wakeup came from cancellation. */
- /* Otherwise ignore cancellation because we got the semaphore. */
-
- if (THREAD_GETMEM(self, p_woken_by_cancel)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
- THREAD_SETMEM(self, p_woken_by_cancel, 0);
- pthread_exit(PTHREAD_CANCELED);
- }
- /* We got the semaphore */
- return 0;
-}
-
-
-weak_alias (__new_sem_init, sem_init)
-weak_alias (__new_sem_wait, sem_wait)
-weak_alias (__new_sem_trywait, sem_trywait)
-weak_alias (__new_sem_post, sem_post)
-weak_alias (__new_sem_getvalue, sem_getvalue)
-weak_alias (__new_sem_destroy, sem_destroy)
-
diff --git a/libpthread/linuxthreads/semaphore.h b/libpthread/linuxthreads/semaphore.h
deleted file mode 100644
index 7b09ea931..000000000
--- a/libpthread/linuxthreads/semaphore.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-#ifndef _SEMAPHORE_H
-#define _SEMAPHORE_H 1
-
-#include <features.h>
-#include <sys/types.h>
-#ifdef __USE_XOPEN2K
-# define __need_timespec
-# include <time.h>
-#endif
-
-#ifndef _PTHREAD_DESCR_DEFINED
-/* Thread descriptors. Needed for `sem_t' definition. */
-typedef struct _pthread_descr_struct *_pthread_descr;
-# define _PTHREAD_DESCR_DEFINED
-#endif
-
-/* System specific semaphore definition. */
-typedef struct
-{
- struct _pthread_fastlock __sem_lock;
- int __sem_value;
- _pthread_descr __sem_waiting;
-} sem_t;
-
-
-
-/* Value returned if `sem_open' failed. */
-#define SEM_FAILED ((sem_t *) 0)
-
-/* Maximum value the semaphore can have. */
-#define SEM_VALUE_MAX ((int) ((~0u) >> 1))
-
-
-__BEGIN_DECLS
-
-/* Initialize semaphore object SEM to VALUE. If PSHARED then share it
- with other processes. */
-extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) __THROW;
-
-/* Free resources associated with semaphore object SEM. */
-extern int sem_destroy (sem_t *__sem) __THROW;
-
-/* Open a named semaphore NAME with open flaot OFLAG. */
-extern sem_t *sem_open (__const char *__name, int __oflag, ...) __THROW;
-
-/* Close descriptor for named semaphore SEM. */
-extern int sem_close (sem_t *__sem) __THROW;
-
-/* Remove named semaphore NAME. */
-extern int sem_unlink (__const char *__name) __THROW;
-
-/* Wait for SEM being posted. */
-extern int sem_wait (sem_t *__sem);
-
-#ifdef __USE_XOPEN2K
-/* Similar to `sem_wait' but wait only until ABSTIME. */
-extern int sem_timedwait (sem_t *__restrict __sem,
- __const struct timespec *__restrict __abstime);
-#endif
-
-/* Test whether SEM is posted. */
-extern int sem_trywait (sem_t *__sem) __THROW;
-
-/* Post SEM. */
-extern int sem_post (sem_t *__sem) __THROW;
-
-/* Get current value of SEM and store it in *SVAL. */
-extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval)
- __THROW;
-
-__END_DECLS
-
-#endif /* semaphore.h */
diff --git a/libpthread/linuxthreads/signals.c b/libpthread/linuxthreads/signals.c
deleted file mode 100644
index df15b884e..000000000
--- a/libpthread/linuxthreads/signals.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Handling of signals */
-
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include "pthread.h"
-#include "internals.h"
-#include "spinlock.h"
-#include <ucontext.h>
-#include <bits/sigcontextinfo.h>
-
-/* mods for uClibc: __libc_sigaction is not in any standard headers */
-extern int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact);
-
-int pthread_sigmask(int how, const sigset_t * newmask, sigset_t * oldmask)
-{
- sigset_t mask;
-
- if (newmask != NULL) {
- mask = *newmask;
- /* Don't allow __pthread_sig_restart to be unmasked.
- Don't allow __pthread_sig_cancel to be masked. */
- switch(how) {
- case SIG_SETMASK:
- sigaddset(&mask, __pthread_sig_restart);
- sigdelset(&mask, __pthread_sig_cancel);
- if (__pthread_sig_debug > 0)
- sigdelset(&mask, __pthread_sig_debug);
- break;
- case SIG_BLOCK:
- sigdelset(&mask, __pthread_sig_cancel);
- if (__pthread_sig_debug > 0)
- sigdelset(&mask, __pthread_sig_debug);
- break;
- case SIG_UNBLOCK:
- sigdelset(&mask, __pthread_sig_restart);
- break;
- }
- newmask = &mask;
- }
- if (sigprocmask(how, newmask, oldmask) == -1)
- return errno;
- else
- return 0;
-}
-
-int pthread_kill(pthread_t thread, int signo)
-{
- pthread_handle handle = thread_handle(thread);
- int pid;
-
- __pthread_lock(&handle->h_lock, NULL);
- if (invalid_handle(handle, thread)) {
- __pthread_unlock(&handle->h_lock);
- return ESRCH;
- }
- pid = handle->h_descr->p_pid;
- __pthread_unlock(&handle->h_lock);
- if (kill(pid, signo) == -1)
- return errno;
- else
- return 0;
-}
-
-/* User-provided signal handlers */
-typedef void (*arch_sighandler_t) __PMT ((int, SIGCONTEXT));
-static union
-{
- arch_sighandler_t old;
- void (*rt) (int, struct siginfo *, struct ucontext *);
-} sighandler[NSIG];
-
-/* The wrapper around user-provided signal handlers */
-static void pthread_sighandler(int signo, SIGCONTEXT ctx)
-{
- pthread_descr self = thread_self();
- char * in_sighandler;
- /* If we're in a sigwait operation, just record the signal received
- and return without calling the user's handler */
- if (THREAD_GETMEM(self, p_sigwaiting)) {
- THREAD_SETMEM(self, p_sigwaiting, 0);
- THREAD_SETMEM(self, p_signal, signo);
- return;
- }
- /* Record that we're in a signal handler and call the user's
- handler function */
- in_sighandler = THREAD_GETMEM(self, p_in_sighandler);
- if (in_sighandler == NULL)
- THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME);
- sighandler[signo].old(signo, SIGCONTEXT_EXTRA_ARGS ctx);
- if (in_sighandler == NULL)
- THREAD_SETMEM(self, p_in_sighandler, NULL);
-}
-
-/* The same, this time for real-time signals. */
-static void pthread_sighandler_rt(int signo, struct siginfo *si,
- struct ucontext *uc)
-{
- pthread_descr self = thread_self();
- char * in_sighandler;
- /* If we're in a sigwait operation, just record the signal received
- and return without calling the user's handler */
- if (THREAD_GETMEM(self, p_sigwaiting)) {
- THREAD_SETMEM(self, p_sigwaiting, 0);
- THREAD_SETMEM(self, p_signal, signo);
- return;
- }
- /* Record that we're in a signal handler and call the user's
- handler function */
- in_sighandler = THREAD_GETMEM(self, p_in_sighandler);
- if (in_sighandler == NULL)
- THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME);
- sighandler[signo].rt(signo, si, uc);
- if (in_sighandler == NULL)
- THREAD_SETMEM(self, p_in_sighandler, NULL);
-}
-
-/* The wrapper around sigaction. Install our own signal handler
- around the signal. */
-int __sigaction(int sig, const struct sigaction * act,
- struct sigaction * oact)
-{
- struct sigaction newact;
- struct sigaction *newactp;
-
-#ifdef DEBUG_PT
-printf(__FUNCTION__": pthreads wrapper!\n");
-#endif
- if (sig == __pthread_sig_restart ||
- sig == __pthread_sig_cancel ||
- (sig == __pthread_sig_debug && __pthread_sig_debug > 0))
- return EINVAL;
- if (act)
- {
- newact = *act;
- if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL
- && sig > 0 && sig < NSIG)
- {
- if (act->sa_flags & SA_SIGINFO)
- newact.sa_handler = (__sighandler_t) pthread_sighandler_rt;
- else
- newact.sa_handler = (__sighandler_t) pthread_sighandler;
- }
- newactp = &newact;
- }
- else
- newactp = NULL;
- if (__libc_sigaction(sig, newactp, oact) == -1)
- return -1;
-#ifdef DEBUG_PT
-printf(__FUNCTION__": signahdler installed, __sigaction successful\n");
-#endif
- if (sig > 0 && sig < NSIG)
- {
- if (oact != NULL)
- oact->sa_handler = (__sighandler_t) sighandler[sig].old;
- if (act)
- /* For the assignment is does not matter whether it's a normal
- or real-time signal. */
- sighandler[sig].old = (arch_sighandler_t) act->sa_handler;
- }
- return 0;
-}
-strong_alias(__sigaction, sigaction)
-
-/* A signal handler that does nothing */
-static void pthread_null_sighandler(int sig) { }
-
-/* sigwait -- synchronously wait for a signal */
-int sigwait(const sigset_t * set, int * sig)
-{
- volatile pthread_descr self = thread_self();
- sigset_t mask;
- int s;
- sigjmp_buf jmpbuf;
- struct sigaction sa;
-
- /* Get ready to block all signals except those in set
- and the cancellation signal.
- Also check that handlers are installed on all signals in set,
- and if not, install our dummy handler. This is conformant to
- POSIX: "The effect of sigwait() on the signal actions for the
- signals in set is unspecified." */
- sigfillset(&mask);
- sigdelset(&mask, __pthread_sig_cancel);
- for (s = 1; s <= NSIG; s++) {
- if (sigismember(set, s) &&
- s != __pthread_sig_restart &&
- s != __pthread_sig_cancel &&
- s != __pthread_sig_debug) {
- sigdelset(&mask, s);
- if (sighandler[s].old == NULL ||
- sighandler[s].old == (arch_sighandler_t) SIG_DFL ||
- sighandler[s].old == (arch_sighandler_t) SIG_IGN) {
- sa.sa_handler = pthread_null_sighandler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction(s, &sa, NULL);
- }
- }
- }
- /* Test for cancellation */
- if (sigsetjmp(jmpbuf, 1) == 0) {
- THREAD_SETMEM(self, p_cancel_jmp, &jmpbuf);
- if (! (THREAD_GETMEM(self, p_canceled)
- && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) {
- /* Reset the signal count */
- THREAD_SETMEM(self, p_signal, 0);
- /* Say we're in sigwait */
- THREAD_SETMEM(self, p_sigwaiting, 1);
- /* Unblock the signals and wait for them */
- sigsuspend(&mask);
- }
- }
- THREAD_SETMEM(self, p_cancel_jmp, NULL);
- /* The signals are now reblocked. Check for cancellation */
- pthread_testcancel();
- /* We should have self->p_signal != 0 and equal to the signal received */
- *sig = THREAD_GETMEM(self, p_signal);
- return 0;
-}
-
-/* Redefine raise() to send signal to calling thread only,
- as per POSIX 1003.1c */
-int raise (int sig)
-{
- int retcode = pthread_kill(pthread_self(), sig);
- if (retcode == 0)
- return 0;
- else {
- errno = retcode;
- return -1;
- }
-}
diff --git a/libpthread/linuxthreads/specific.c b/libpthread/linuxthreads/specific.c
deleted file mode 100644
index d8b5bb0b3..000000000
--- a/libpthread/linuxthreads/specific.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Thread-specific data */
-
-#include <features.h>
-#define __USE_GNU
-#include <errno.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include "pthread.h"
-#include "internals.h"
-#include "spinlock.h"
-#include "restart.h"
-
-
-/* Table of keys. */
-
-static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] =
- { { 0, NULL } };
-
-/* For debugging purposes put the maximum number of keys in a variable. */
-const int __linuxthreads_pthread_keys_max = PTHREAD_KEYS_MAX;
-const int __linuxthreads_pthread_key_2ndlevel_size = PTHREAD_KEY_2NDLEVEL_SIZE;
-
-/* Mutex to protect access to pthread_keys */
-
-static pthread_mutex_t pthread_keys_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/* Create a new key */
-
-int pthread_key_create(pthread_key_t * key, destr_function destr)
-{
- int i;
-
- pthread_mutex_lock(&pthread_keys_mutex);
- for (i = 0; i < PTHREAD_KEYS_MAX; i++) {
- if (! pthread_keys[i].in_use) {
- /* Mark key in use */
- pthread_keys[i].in_use = 1;
- pthread_keys[i].destr = destr;
- pthread_mutex_unlock(&pthread_keys_mutex);
- *key = i;
- return 0;
- }
- }
- pthread_mutex_unlock(&pthread_keys_mutex);
- return EAGAIN;
-}
-
-/* Delete a key */
-int pthread_key_delete(pthread_key_t key)
-{
- pthread_descr self = thread_self();
-
- pthread_mutex_lock(&pthread_keys_mutex);
- if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) {
- pthread_mutex_unlock(&pthread_keys_mutex);
- return EINVAL;
- }
- pthread_keys[key].in_use = 0;
- pthread_keys[key].destr = NULL;
-
- /* Set the value of the key to NULL in all running threads, so
- that if the key is reallocated later by pthread_key_create, its
- associated values will be NULL in all threads.
- Do nothing if no threads have been created yet. */
- if (__pthread_manager_request != -1)
- {
- pthread_descr th;
- unsigned int idx1st, idx2nd;
-
- idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
- idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
- th = self;
- do {
- /* If the thread already is terminated don't modify the memory. */
- if (!th->p_terminated && th->p_specific[idx1st] != NULL)
- th->p_specific[idx1st][idx2nd] = NULL;
- th = th->p_nextlive;
- } while (th != self);
- }
-
- pthread_mutex_unlock(&pthread_keys_mutex);
- return 0;
-}
-
-/* Set the value of a key */
-
-int pthread_setspecific(pthread_key_t key, const void * pointer)
-{
- pthread_descr self = thread_self();
- unsigned int idx1st, idx2nd;
-
- if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use)
- return EINVAL;
- idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
- idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
- if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL) {
- void *newp = calloc(PTHREAD_KEY_2NDLEVEL_SIZE, sizeof (void *));
- if (newp == NULL)
- return ENOMEM;
- THREAD_SETMEM_NC(self, p_specific[idx1st], newp);
- }
- THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd] = (void *) pointer;
- return 0;
-}
-
-/* Get the value of a key */
-
-void * pthread_getspecific(pthread_key_t key)
-{
- pthread_descr self = thread_self();
- unsigned int idx1st, idx2nd;
-
- if (key >= PTHREAD_KEYS_MAX)
- return NULL;
- idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
- idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
- if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL
- || !pthread_keys[key].in_use)
- return NULL;
- return THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd];
-}
-
-/* Call the destruction routines on all keys */
-
-void __pthread_destroy_specifics()
-{
- pthread_descr self = thread_self();
- int i, j, round, found_nonzero;
- destr_function destr;
- void * data;
-
- for (round = 0, found_nonzero = 1;
- found_nonzero && round < PTHREAD_DESTRUCTOR_ITERATIONS;
- round++) {
- found_nonzero = 0;
- for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++)
- if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL)
- for (j = 0; j < PTHREAD_KEY_2NDLEVEL_SIZE; j++) {
- destr = pthread_keys[i * PTHREAD_KEY_2NDLEVEL_SIZE + j].destr;
- data = THREAD_GETMEM_NC(self, p_specific[i])[j];
- if (destr != NULL && data != NULL) {
- THREAD_GETMEM_NC(self, p_specific[i])[j] = NULL;
- destr(data);
- found_nonzero = 1;
- }
- }
- }
- __pthread_lock(THREAD_GETMEM(self, p_lock), self);
- for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) {
- if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) {
- free(THREAD_GETMEM_NC(self, p_specific[i]));
- THREAD_SETMEM_NC(self, p_specific[i], NULL);
- }
- }
- __pthread_unlock(THREAD_GETMEM(self, p_lock));
-}
-
-
-/* Thread-specific data for libc. */
-#if !(USE_TLS && HAVE___THREAD)
-static int
-libc_internal_tsd_set(enum __libc_tsd_key_t key, const void * pointer)
-{
- pthread_descr self = thread_self();
-
- THREAD_SETMEM_NC(self, p_libc_specific[key], (void *) pointer);
- return 0;
-}
-int (*__libc_internal_tsd_set)(enum __libc_tsd_key_t key, const void * pointer)
- = libc_internal_tsd_set;
-
-static void *
-libc_internal_tsd_get(enum __libc_tsd_key_t key)
-{
- pthread_descr self = thread_self();
-
- return THREAD_GETMEM_NC(self, p_libc_specific[key]);
-}
-void * (*__libc_internal_tsd_get)(enum __libc_tsd_key_t key)
- = libc_internal_tsd_get;
-
-static void ** __attribute__ ((__const__))
-libc_internal_tsd_address (enum __libc_tsd_key_t key)
-{
- pthread_descr self = thread_self();
- return &self->p_libc_specific[key];
-}
-void **(*const __libc_internal_tsd_address) (enum __libc_tsd_key_t key)
- __THROW __attribute__ ((__const__)) = libc_internal_tsd_address;
-#endif
diff --git a/libpthread/linuxthreads/spinlock.c b/libpthread/linuxthreads/spinlock.c
deleted file mode 100644
index cdf45f195..000000000
--- a/libpthread/linuxthreads/spinlock.c
+++ /dev/null
@@ -1,723 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-/* Internal locks */
-
-#define __FORCE_GLIBC
-#include <features.h>
-#include <errno.h>
-#include <sched.h>
-#include <time.h>
-#include <stdlib.h>
-#include <limits.h>
-#include "pthread.h"
-#include "internals.h"
-#include "spinlock.h"
-#include "restart.h"
-
-static void __pthread_acquire(int * spinlock);
-
-static inline void __pthread_release(int * spinlock)
-{
- WRITE_MEMORY_BARRIER();
- *spinlock = __LT_SPINLOCK_INIT;
- __asm __volatile ("" : "=m" (*spinlock) : "m" (*spinlock));
-}
-
-
-/* The status field of a spinlock is a pointer whose least significant
- bit is a locked flag.
-
- Thus the field values have the following meanings:
-
- status == 0: spinlock is free
- status == 1: spinlock is taken; no thread is waiting on it
-
- (status & 1) == 1: spinlock is taken and (status & ~1L) is a
- pointer to the first waiting thread; other
- waiting threads are linked via the p_nextlock
- field.
- (status & 1) == 0: same as above, but spinlock is not taken.
-
- The waiting list is not sorted by priority order.
- Actually, we always insert at top of list (sole insertion mode
- that can be performed without locking).
- For __pthread_unlock, we perform a linear search in the list
- to find the highest-priority, oldest waiting thread.
- This is safe because there are no concurrent __pthread_unlock
- operations -- only the thread that locked the mutex can unlock it. */
-
-
-void internal_function __pthread_lock(struct _pthread_fastlock * lock,
- pthread_descr self)
-{
-#if defined HAS_COMPARE_AND_SWAP
- long oldstatus, newstatus;
- int successful_seizure, spurious_wakeup_count;
- int spin_count;
-#endif
-
-#if defined TEST_FOR_COMPARE_AND_SWAP
- if (!__pthread_has_cas)
-#endif
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- {
- __pthread_acquire(&lock->__spinlock);
- return;
- }
-#endif
-
-#if defined HAS_COMPARE_AND_SWAP
- /* First try it without preparation. Maybe it's a completely
- uncontested lock. */
- if (lock->__status == 0 && __compare_and_swap (&lock->__status, 0, 1))
- return;
-
- spurious_wakeup_count = 0;
- spin_count = 0;
-
- /* On SMP, try spinning to get the lock. */
-#if 0
- if (__pthread_smp_kernel) {
- int max_count = lock->__spinlock * 2 + 10;
-
- if (max_count > MAX_ADAPTIVE_SPIN_COUNT)
- max_count = MAX_ADAPTIVE_SPIN_COUNT;
-
- for (spin_count = 0; spin_count < max_count; spin_count++) {
- if (((oldstatus = lock->__status) & 1) == 0) {
- if(__compare_and_swap(&lock->__status, oldstatus, oldstatus | 1))
- {
- if (spin_count)
- lock->__spinlock += (spin_count - lock->__spinlock) / 8;
- READ_MEMORY_BARRIER();
- return;
- }
- }
-#ifdef BUSY_WAIT_NOP
- BUSY_WAIT_NOP;
-#endif
- __asm __volatile ("" : "=m" (lock->__status) : "m" (lock->__status));
- }
-
- lock->__spinlock += (spin_count - lock->__spinlock) / 8;
- }
-#endif
-
-again:
-
- /* No luck, try once more or suspend. */
-
- do {
- oldstatus = lock->__status;
- successful_seizure = 0;
-
- if ((oldstatus & 1) == 0) {
- newstatus = oldstatus | 1;
- successful_seizure = 1;
- } else {
- if (self == NULL)
- self = thread_self();
- newstatus = (long) self | 1;
- }
-
- if (self != NULL) {
- THREAD_SETMEM(self, p_nextlock, (pthread_descr) (oldstatus));
- /* Make sure the store in p_nextlock completes before performing
- the compare-and-swap */
- MEMORY_BARRIER();
- }
- } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
-
- /* Suspend with guard against spurious wakeup.
- This can happen in pthread_cond_timedwait_relative, when the thread
- wakes up due to timeout and is still on the condvar queue, and then
- locks the queue to remove itself. At that point it may still be on the
- queue, and may be resumed by a condition signal. */
-
- if (!successful_seizure) {
- for (;;) {
- suspend(self);
- if (self->p_nextlock != NULL) {
- /* Count resumes that don't belong to us. */
- spurious_wakeup_count++;
- continue;
- }
- break;
- }
- goto again;
- }
-
- /* Put back any resumes we caught that don't belong to us. */
- while (spurious_wakeup_count--)
- restart(self);
-
- READ_MEMORY_BARRIER();
-#endif
-}
-
-int __pthread_unlock(struct _pthread_fastlock * lock)
-{
-#if defined HAS_COMPARE_AND_SWAP
- long oldstatus;
- pthread_descr thr, * ptr, * maxptr;
- int maxprio;
-#endif
-
-#if defined TEST_FOR_COMPARE_AND_SWAP
- if (!__pthread_has_cas)
-#endif
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- {
- __pthread_release(&lock->__spinlock);
- return 0;
- }
-#endif
-
-#if defined HAS_COMPARE_AND_SWAP
- WRITE_MEMORY_BARRIER();
-
-again:
- while ((oldstatus = lock->__status) == 1) {
- if (__compare_and_swap_with_release_semantics(&lock->__status,
- oldstatus, 0))
- return 0;
- }
-
- /* Find thread in waiting queue with maximal priority */
- ptr = (pthread_descr *) &lock->__status;
- thr = (pthread_descr) (oldstatus & ~1L);
- maxprio = 0;
- maxptr = ptr;
-
- /* Before we iterate over the wait queue, we need to execute
- a read barrier, otherwise we may read stale contents of nodes that may
- just have been inserted by other processors. One read barrier is enough to
- ensure we have a stable list; we don't need one for each pointer chase
- through the list, because we are the owner of the lock; other threads
- can only add nodes at the front; if a front node is consistent,
- the ones behind it must also be. */
-
- READ_MEMORY_BARRIER();
-
- while (thr != 0) {
- if (thr->p_priority >= maxprio) {
- maxptr = ptr;
- maxprio = thr->p_priority;
- }
- ptr = &(thr->p_nextlock);
- thr = (pthread_descr)((long)(thr->p_nextlock) & ~1L);
- }
-
- /* Remove max prio thread from waiting list. */
- if (maxptr == (pthread_descr *) &lock->__status) {
- /* If max prio thread is at head, remove it with compare-and-swap
- to guard against concurrent lock operation. This removal
- also has the side effect of marking the lock as released
- because the new status comes from thr->p_nextlock whose
- least significant bit is clear. */
- thr = (pthread_descr) (oldstatus & ~1L);
- if (! __compare_and_swap_with_release_semantics
- (&lock->__status, oldstatus, (long)(thr->p_nextlock) & ~1L))
- goto again;
- } else {
- /* No risk of concurrent access, remove max prio thread normally.
- But in this case we must also flip the least significant bit
- of the status to mark the lock as released. */
- thr = (pthread_descr)((long)*maxptr & ~1L);
- *maxptr = thr->p_nextlock;
-
- /* Ensure deletion from linked list completes before we
- release the lock. */
- WRITE_MEMORY_BARRIER();
-
- do {
- oldstatus = lock->__status;
- } while (!__compare_and_swap_with_release_semantics(&lock->__status,
- oldstatus, oldstatus & ~1L));
- }
-
- /* Wake up the selected waiting thread. Woken thread can check
- its own p_nextlock field for NULL to detect that it has been removed. No
- barrier is needed here, since restart() and suspend() take
- care of memory synchronization. */
-
- thr->p_nextlock = NULL;
- restart(thr);
-
- return 0;
-#endif
-}
-
-/*
- * Alternate fastlocks do not queue threads directly. Instead, they queue
- * these wait queue node structures. When a timed wait wakes up due to
- * a timeout, it can leave its wait node in the queue (because there
- * is no safe way to remove from the quue). Some other thread will
- * deallocate the abandoned node.
- */
-
-
-struct wait_node {
- struct wait_node *next; /* Next node in null terminated linked list */
- pthread_descr thr; /* The thread waiting with this node */
- int abandoned; /* Atomic flag */
-};
-
-static long wait_node_free_list;
-static int wait_node_free_list_spinlock;
-
-/* Allocate a new node from the head of the free list using an atomic
- operation, or else using malloc if that list is empty. A fundamental
- assumption here is that we can safely access wait_node_free_list->next.
- That's because we never free nodes once we allocate them, so a pointer to a
- node remains valid indefinitely. */
-
-static struct wait_node *wait_node_alloc(void)
-{
- struct wait_node *new_node = 0;
-
- __pthread_acquire(&wait_node_free_list_spinlock);
- if (wait_node_free_list != 0) {
- new_node = (struct wait_node *) wait_node_free_list;
- wait_node_free_list = (long) new_node->next;
- }
- WRITE_MEMORY_BARRIER();
- __pthread_release(&wait_node_free_list_spinlock);
-
- if (new_node == 0)
- return malloc(sizeof *wait_node_alloc());
-
- return new_node;
-}
-
-/* Return a node to the head of the free list using an atomic
- operation. */
-
-static void wait_node_free(struct wait_node *wn)
-{
- __pthread_acquire(&wait_node_free_list_spinlock);
- wn->next = (struct wait_node *) wait_node_free_list;
- wait_node_free_list = (long) wn;
- WRITE_MEMORY_BARRIER();
- __pthread_release(&wait_node_free_list_spinlock);
- return;
-}
-
-#if defined HAS_COMPARE_AND_SWAP
-
-/* Remove a wait node from the specified queue. It is assumed
- that the removal takes place concurrently with only atomic insertions at the
- head of the queue. */
-
-static void wait_node_dequeue(struct wait_node **pp_head,
- struct wait_node **pp_node,
- struct wait_node *p_node)
-{
- /* If the node is being deleted from the head of the
- list, it must be deleted using atomic compare-and-swap.
- Otherwise it can be deleted in the straightforward way. */
-
- if (pp_node == pp_head) {
- /* We don't need a read barrier between these next two loads,
- because it is assumed that the caller has already ensured
- the stability of *p_node with respect to p_node. */
-
- long oldvalue = (long) p_node;
- long newvalue = (long) p_node->next;
-
- if (__compare_and_swap((long *) pp_node, oldvalue, newvalue))
- return;
-
- /* Oops! Compare and swap failed, which means the node is
- no longer first. We delete it using the ordinary method. But we don't
- know the identity of the node which now holds the pointer to the node
- being deleted, so we must search from the beginning. */
-
- for (pp_node = pp_head; p_node != *pp_node; ) {
- pp_node = &(*pp_node)->next;
- READ_MEMORY_BARRIER(); /* Stabilize *pp_node for next iteration. */
- }
- }
-
- *pp_node = p_node->next;
- return;
-}
-
-#endif
-
-void __pthread_alt_lock(struct _pthread_fastlock * lock,
- pthread_descr self)
-{
-#if defined HAS_COMPARE_AND_SWAP
- long oldstatus, newstatus;
-#endif
- struct wait_node wait_node;
-
-#if defined TEST_FOR_COMPARE_AND_SWAP
- if (!__pthread_has_cas)
-#endif
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- {
- int suspend_needed = 0;
- __pthread_acquire(&lock->__spinlock);
-
- if (lock->__status == 0)
- lock->__status = 1;
- else {
- if (self == NULL)
- self = thread_self();
-
- wait_node.abandoned = 0;
- wait_node.next = (struct wait_node *) lock->__status;
- wait_node.thr = self;
- lock->__status = (long) &wait_node;
- suspend_needed = 1;
- }
-
- __pthread_release(&lock->__spinlock);
-
- if (suspend_needed)
- suspend (self);
- return;
- }
-#endif
-
-#if defined HAS_COMPARE_AND_SWAP
- do {
- oldstatus = lock->__status;
- if (oldstatus == 0) {
- newstatus = 1;
- } else {
- if (self == NULL)
- self = thread_self();
- wait_node.thr = self;
- newstatus = (long) &wait_node;
- }
- wait_node.abandoned = 0;
- wait_node.next = (struct wait_node *) oldstatus;
- /* Make sure the store in wait_node.next completes before performing
- the compare-and-swap */
- MEMORY_BARRIER();
- } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
-
- /* Suspend. Note that unlike in __pthread_lock, we don't worry
- here about spurious wakeup. That's because this lock is not
- used in situations where that can happen; the restart can
- only come from the previous lock owner. */
-
- if (oldstatus != 0)
- suspend(self);
-
- READ_MEMORY_BARRIER();
-#endif
-}
-
-/* Timed-out lock operation; returns 0 to indicate timeout. */
-
-int __pthread_alt_timedlock(struct _pthread_fastlock * lock,
- pthread_descr self, const struct timespec *abstime)
-{
- long oldstatus = 0;
-#if defined HAS_COMPARE_AND_SWAP
- long newstatus;
-#endif
- struct wait_node *p_wait_node = wait_node_alloc();
-
- /* Out of memory, just give up and do ordinary lock. */
- if (p_wait_node == 0) {
- __pthread_alt_lock(lock, self);
- return 1;
- }
-
-#if defined TEST_FOR_COMPARE_AND_SWAP
- if (!__pthread_has_cas)
-#endif
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- {
- __pthread_acquire(&lock->__spinlock);
-
- if (lock->__status == 0)
- lock->__status = 1;
- else {
- if (self == NULL)
- self = thread_self();
-
- p_wait_node->abandoned = 0;
- p_wait_node->next = (struct wait_node *) lock->__status;
- p_wait_node->thr = self;
- lock->__status = (long) p_wait_node;
- oldstatus = 1; /* force suspend */
- }
-
- __pthread_release(&lock->__spinlock);
- goto suspend;
- }
-#endif
-
-#if defined HAS_COMPARE_AND_SWAP
- do {
- oldstatus = lock->__status;
- if (oldstatus == 0) {
- newstatus = 1;
- } else {
- if (self == NULL)
- self = thread_self();
- p_wait_node->thr = self;
- newstatus = (long) p_wait_node;
- }
- p_wait_node->abandoned = 0;
- p_wait_node->next = (struct wait_node *) oldstatus;
- /* Make sure the store in wait_node.next completes before performing
- the compare-and-swap */
- MEMORY_BARRIER();
- } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
-#endif
-
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- suspend:
-#endif
-
- /* If we did not get the lock, do a timed suspend. If we wake up due
- to a timeout, then there is a race; the old lock owner may try
- to remove us from the queue. This race is resolved by us and the owner
- doing an atomic testandset() to change the state of the wait node from 0
- to 1. If we succeed, then it's a timeout and we abandon the node in the
- queue. If we fail, it means the owner gave us the lock. */
-
- if (oldstatus != 0) {
- if (timedsuspend(self, abstime) == 0) {
- if (!testandset(&p_wait_node->abandoned))
- return 0; /* Timeout! */
-
- /* Eat oustanding resume from owner, otherwise wait_node_free() below
- will race with owner's wait_node_dequeue(). */
- suspend(self);
- }
- }
-
- wait_node_free(p_wait_node);
-
- READ_MEMORY_BARRIER();
-
- return 1; /* Got the lock! */
-}
-
-void __pthread_alt_unlock(struct _pthread_fastlock *lock)
-{
- struct wait_node *p_node, **pp_node, *p_max_prio, **pp_max_prio;
- struct wait_node ** const pp_head = (struct wait_node **) &lock->__status;
- int maxprio;
-
- WRITE_MEMORY_BARRIER();
-
-#if defined TEST_FOR_COMPARE_AND_SWAP
- if (!__pthread_has_cas)
-#endif
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- {
- __pthread_acquire(&lock->__spinlock);
- }
-#endif
-
- while (1) {
-
- /* If no threads are waiting for this lock, try to just
- atomically release it. */
-#if defined TEST_FOR_COMPARE_AND_SWAP
- if (!__pthread_has_cas)
-#endif
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- {
- if (lock->__status == 0 || lock->__status == 1) {
- lock->__status = 0;
- break;
- }
- }
-#endif
-
-#if defined TEST_FOR_COMPARE_AND_SWAP
- else
-#endif
-
-#if defined HAS_COMPARE_AND_SWAP
- {
- long oldstatus = lock->__status;
- if (oldstatus == 0 || oldstatus == 1) {
- if (__compare_and_swap_with_release_semantics (&lock->__status, oldstatus, 0))
- break;
- else
- continue;
- }
- }
-#endif
-
- /* Process the entire queue of wait nodes. Remove all abandoned
- wait nodes and put them into the global free queue, and
- remember the one unabandoned node which refers to the thread
- having the highest priority. */
-
- pp_max_prio = pp_node = pp_head;
- p_max_prio = p_node = *pp_head;
- maxprio = INT_MIN;
-
- READ_MEMORY_BARRIER(); /* Prevent access to stale data through p_node */
-
- while (p_node != (struct wait_node *) 1) {
- int prio;
-
- if (p_node->abandoned) {
- /* Remove abandoned node. */
-#if defined TEST_FOR_COMPARE_AND_SWAP
- if (!__pthread_has_cas)
-#endif
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- *pp_node = p_node->next;
-#endif
-#if defined TEST_FOR_COMPARE_AND_SWAP
- else
-#endif
-#if defined HAS_COMPARE_AND_SWAP
- wait_node_dequeue(pp_head, pp_node, p_node);
-#endif
- wait_node_free(p_node);
- /* Note that the next assignment may take us to the beginning
- of the queue, to newly inserted nodes, if pp_node == pp_head.
- In that case we need a memory barrier to stabilize the first of
- these new nodes. */
- p_node = *pp_node;
- if (pp_node == pp_head)
- READ_MEMORY_BARRIER(); /* No stale reads through p_node */
- continue;
- } else if ((prio = p_node->thr->p_priority) >= maxprio) {
- /* Otherwise remember it if its thread has a higher or equal priority
- compared to that of any node seen thus far. */
- maxprio = prio;
- pp_max_prio = pp_node;
- p_max_prio = p_node;
- }
-
- /* This canno6 jump backward in the list, so no further read
- barrier is needed. */
- pp_node = &p_node->next;
- p_node = *pp_node;
- }
-
- /* If all threads abandoned, go back to top */
- if (maxprio == INT_MIN)
- continue;
-
- ASSERT (p_max_prio != (struct wait_node *) 1);
-
- /* Now we want to to remove the max priority thread's wait node from
- the list. Before we can do this, we must atomically try to change the
- node's abandon state from zero to nonzero. If we succeed, that means we
- have the node that we will wake up. If we failed, then it means the
- thread timed out and abandoned the node in which case we repeat the
- whole unlock operation. */
-
- if (!testandset(&p_max_prio->abandoned)) {
-#if defined TEST_FOR_COMPARE_AND_SWAP
- if (!__pthread_has_cas)
-#endif
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- *pp_max_prio = p_max_prio->next;
-#endif
-#if defined TEST_FOR_COMPARE_AND_SWAP
- else
-#endif
-#if defined HAS_COMPARE_AND_SWAP
- wait_node_dequeue(pp_head, pp_max_prio, p_max_prio);
-#endif
- restart(p_max_prio->thr);
- break;
- }
- }
-
-#if defined TEST_FOR_COMPARE_AND_SWAP
- if (!__pthread_has_cas)
-#endif
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- {
- __pthread_release(&lock->__spinlock);
- }
-#endif
-}
-
-
-/* Compare-and-swap emulation with a spinlock */
-
-#ifdef TEST_FOR_COMPARE_AND_SWAP
-int __pthread_has_cas = 0;
-#endif
-
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
-
-int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
- int * spinlock)
-{
- int res;
-
- __pthread_acquire(spinlock);
-
- if (*ptr == oldval) {
- *ptr = newval; res = 1;
- } else {
- res = 0;
- }
-
- __pthread_release(spinlock);
-
- return res;
-}
-
-#endif
-
-/* The retry strategy is as follows:
- - We test and set the spinlock MAX_SPIN_COUNT times, calling
- sched_yield() each time. This gives ample opportunity for other
- threads with priority >= our priority to make progress and
- release the spinlock.
- - If a thread with priority < our priority owns the spinlock,
- calling sched_yield() repeatedly is useless, since we're preventing
- the owning thread from making progress and releasing the spinlock.
- So, after MAX_SPIN_LOCK attemps, we suspend the calling thread
- using nanosleep(). This again should give time to the owning thread
- for releasing the spinlock.
- Notice that the nanosleep() interval must not be too small,
- since the kernel does busy-waiting for short intervals in a realtime
- process (!). The smallest duration that guarantees thread
- suspension is currently 2ms.
- - When nanosleep() returns, we try again, doing MAX_SPIN_COUNT
- sched_yield(), then sleeping again if needed. */
-
-static void __pthread_acquire(int * spinlock)
-{
- int cnt = 0;
- struct timespec tm;
-
- READ_MEMORY_BARRIER();
-
- while (testandset(spinlock)) {
- if (cnt < MAX_SPIN_COUNT) {
- sched_yield();
- cnt++;
- } else {
- tm.tv_sec = 0;
- tm.tv_nsec = SPIN_SLEEP_DURATION;
- nanosleep(&tm, NULL);
- cnt = 0;
- }
- }
-}
diff --git a/libpthread/linuxthreads/spinlock.h b/libpthread/linuxthreads/spinlock.h
deleted file mode 100644
index 0ec40c57c..000000000
--- a/libpthread/linuxthreads/spinlock.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-#include <bits/initspin.h>
-
-
-/* There are 2 compare and swap synchronization primitives with
- different semantics:
-
- 1. compare_and_swap, which has acquire semantics (i.e. it
- completes befor subsequent writes.)
- 2. compare_and_swap_with_release_semantics, which has release
- semantics (it completes after previous writes.)
-
- For those platforms on which they are the same. HAS_COMPARE_AND_SWAP
- should be defined. For those platforms on which they are different,
- HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS has to be defined. */
-
-#ifndef HAS_COMPARE_AND_SWAP
-#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
-#define HAS_COMPARE_AND_SWAP
-#endif
-#endif
-
-#if defined(TEST_FOR_COMPARE_AND_SWAP)
-
-extern int __pthread_has_cas;
-extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
- int * spinlock);
-
-static inline int compare_and_swap(long * ptr, long oldval, long newval,
- int * spinlock)
-{
- if (__builtin_expect (__pthread_has_cas, 1))
- return __compare_and_swap(ptr, oldval, newval);
- else
- return __pthread_compare_and_swap(ptr, oldval, newval, spinlock);
-}
-
-#elif defined(HAS_COMPARE_AND_SWAP)
-
-#ifdef IMPLEMENT_TAS_WITH_CAS
-#define testandset(p) !__compare_and_swap((long int *) p, 0, 1)
-#endif
-
-#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
-
-static inline int
-compare_and_swap_with_release_semantics (long * ptr, long oldval,
- long newval, int * spinlock)
-{
- return __compare_and_swap_with_release_semantics (ptr, oldval,
- newval);
-}
-
-#endif
-
-static inline int compare_and_swap(long * ptr, long oldval, long newval,
- int * spinlock)
-{
- return __compare_and_swap(ptr, oldval, newval);
-}
-
-#else
-
-extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
- int * spinlock);
-
-static inline int compare_and_swap(long * ptr, long oldval, long newval,
- int * spinlock)
-{
- return __pthread_compare_and_swap(ptr, oldval, newval, spinlock);
-}
-
-#endif
-
-#ifndef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
-#define compare_and_swap_with_release_semantics compare_and_swap
-#define __compare_and_swap_with_release_semantics __compare_and_swap
-#endif
-
-/* Internal locks */
-
-extern void internal_function __pthread_lock(struct _pthread_fastlock * lock,
- pthread_descr self);
-extern int __pthread_unlock(struct _pthread_fastlock *lock);
-
-static inline void __pthread_init_lock(struct _pthread_fastlock * lock)
-{
- lock->__status = 0;
- lock->__spinlock = __LT_SPINLOCK_INIT;
-}
-
-static inline int __pthread_trylock (struct _pthread_fastlock * lock)
-{
-#if defined TEST_FOR_COMPARE_AND_SWAP
- if (!__pthread_has_cas)
-#endif
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- {
- return (testandset(&lock->__spinlock) ? EBUSY : 0);
- }
-#endif
-
-#if defined HAS_COMPARE_AND_SWAP
- do {
- if (lock->__status != 0) return EBUSY;
- } while(! __compare_and_swap(&lock->__status, 0, 1));
- return 0;
-#endif
-}
-
-/* Variation of internal lock used for pthread_mutex_t, supporting
- timed-out waits. Warning: do not mix these operations with the above ones
- over the same lock object! */
-
-extern void __pthread_alt_lock(struct _pthread_fastlock * lock,
- pthread_descr self);
-
-extern int __pthread_alt_timedlock(struct _pthread_fastlock * lock,
- pthread_descr self, const struct timespec *abstime);
-
-extern void __pthread_alt_unlock(struct _pthread_fastlock *lock);
-
-static inline void __pthread_alt_init_lock(struct _pthread_fastlock * lock)
-{
- lock->__status = 0;
- lock->__spinlock = __LT_SPINLOCK_INIT;
-}
-
-static inline int __pthread_alt_trylock (struct _pthread_fastlock * lock)
-{
-#if defined TEST_FOR_COMPARE_AND_SWAP
- if (!__pthread_has_cas)
-#endif
-#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- {
- int res = EBUSY;
-
- if (testandset(&lock->__spinlock) == 0)
- {
- if (lock->__status == 0)
- {
- lock->__status = 1;
- WRITE_MEMORY_BARRIER();
- res = 0;
- }
- lock->__spinlock = __LT_SPINLOCK_INIT;
- }
- return res;
- }
-#endif
-
-#if defined HAS_COMPARE_AND_SWAP
- do {
- if (lock->__status != 0) return EBUSY;
- } while(! compare_and_swap(&lock->__status, 0, 1, &lock->__spinlock));
- return 0;
-#endif
-}
-
-/* Operations on pthread_atomic, which is defined in internals.h */
-
-static inline long atomic_increment(struct pthread_atomic *pa)
-{
- long oldval;
-
- do {
- oldval = pa->p_count;
- } while (!compare_and_swap(&pa->p_count, oldval, oldval + 1, &pa->p_spinlock));
-
- return oldval;
-}
-
-
-static inline long atomic_decrement(struct pthread_atomic *pa)
-{
- long oldval;
-
- do {
- oldval = pa->p_count;
- } while (!compare_and_swap(&pa->p_count, oldval, oldval - 1, &pa->p_spinlock));
-
- return oldval;
-}
-
-
-static inline void
-__pthread_set_own_extricate_if (pthread_descr self, pthread_extricate_if *peif)
-{
- /* Only store a non-null peif if the thread has cancellation enabled.
- Otherwise pthread_cancel will unconditionally call the extricate handler,
- and restart the thread giving rise to forbidden spurious wakeups. */
- if (peif == NULL
- || THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)
- {
- /* If we are removing the extricate interface, we need to synchronize
- against pthread_cancel so that it does not continue with a pointer
- to a deallocated pthread_extricate_if struct! The thread lock
- is (ab)used for this synchronization purpose. */
- if (peif == NULL)
- __pthread_lock (THREAD_GETMEM(self, p_lock), self);
- THREAD_SETMEM(self, p_extricate, peif);
- if (peif == NULL)
- __pthread_unlock (THREAD_GETMEM(self, p_lock));
- }
-}
diff --git a/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h b/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h
deleted file mode 100644
index 853ac6f04..000000000
--- a/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- Alpha version.
- Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003
- Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson <rth@tamu.edu>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#ifndef _PT_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef PT_EI
-# define PT_EI extern inline __attribute__ ((always_inline))
-#endif
-
-#ifdef __linux__
-# include <asm/pal.h>
-#else
-# include <machine/pal.h>
-#endif
-
-extern long int testandset (int *spinlock);
-extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME stack_pointer
-register char *stack_pointer __asm__("$30");
-
-
-/* Memory barrier; default is to do nothing */
-#define MEMORY_BARRIER() __asm__ __volatile__("mb" : : : "memory")
-/* Write barrier. */
-#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("wmb" : : : "memory")
-
-
-/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
-{
- long int ret, temp;
-
- __asm__ __volatile__(
- "/* Inline spinlock test & set */\n"
- "1:\t"
- "ldl_l %0,%3\n\t"
- "bne %0,2f\n\t"
- "or $31,1,%1\n\t"
- "stl_c %1,%2\n\t"
- "beq %1,1b\n"
- "2:\tmb\n"
- "/* End spinlock test & set */"
- : "=&r"(ret), "=&r"(temp), "=m"(*spinlock)
- : "m"(*spinlock)
- : "memory");
-
- return ret;
-}
-
-
-/* Begin allocating thread stacks at this address. Default is to allocate
- them just below the initial program stack. */
-#define THREAD_STACK_START_ADDRESS 0x40000000000
-
-
-/* Return the thread descriptor for the current thread. */
-#define THREAD_SELF \
-({ \
- register pthread_descr __self __asm__("$0"); \
- __asm__ ("call_pal %1" : "=r"(__self) : "i"(PAL_rduniq)); \
- __self; \
-})
-
-/* Initialize the thread-unique value. */
-#define INIT_THREAD_SELF(descr, nr) \
-{ \
- register pthread_descr __self __asm__("$16") = (descr); \
- __asm__ __volatile__ ("call_pal %1" : : "r"(__self), "i"(PAL_wruniq)); \
-}
-
-
-/* Compare-and-swap for semaphores. */
-
-#define HAS_COMPARE_AND_SWAP
-PT_EI int
-__compare_and_swap (long int *p, long int oldval, long int newval)
-{
- long int ret;
-
- __asm__ __volatile__ (
- "/* Inline compare & swap */\n"
- "1:\t"
- "ldq_l %0,%4\n\t"
- "cmpeq %0,%2,%0\n\t"
- "beq %0,2f\n\t"
- "mov %3,%0\n\t"
- "stq_c %0,%1\n\t"
- "beq %0,1b\n\t"
- "2:\tmb\n"
- "/* End compare & swap */"
- : "=&r"(ret), "=m"(*p)
- : "r"(oldval), "r"(newval), "m"(*p)
- : "memory");
-
- return ret;
-}
-
-/* We want the OS to assign stack addresses. */
-#define FLOATING_STACKS 1
-
-/* Maximum size of the stack if the rlimit is unlimited. */
-#define ARCH_STACK_MAX_SIZE 32*1024*1024
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/arm/pt-machine.h b/libpthread/linuxthreads/sysdeps/arm/pt-machine.h
deleted file mode 100644
index 284567970..000000000
--- a/libpthread/linuxthreads/sysdeps/arm/pt-machine.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- ARM version.
- Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Philip Blundell <philb@gnu.org>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; 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_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef PT_EI
-# define PT_EI extern inline
-#endif
-
-extern long int testandset (int *spinlock);
-extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-
-/* This will not work on ARM1 or ARM2 because SWP is lacking on those
- machines. Unfortunately we have no way to detect this at compile
- time; let's hope nobody tries to use one. */
-
-/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
-{
- register unsigned int ret;
-
-#if defined(__thumb__)
- void *pc;
- __asm__ __volatile__(
- ".align 0\n"
- "\tbx pc\n"
- "\tnop\n"
- "\t.arm\n"
- "\tswp %0, %2, [%3]\n"
- "\torr %1, pc, #1\n"
- "\tbx %1\n"
- "\t.force_thumb"
- : "=r"(ret), "=r"(pc)
- : "0"(1), "r"(spinlock));
-#else
- __asm__ __volatile__("swp %0, %1, [%2]"
- : "=r"(ret)
- : "0"(1), "r"(spinlock));
-#endif
-
- return ret;
-}
-
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME stack_pointer
-register char * stack_pointer __asm__ ("sp");
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/bfin/pt-machine.h b/libpthread/linuxthreads/sysdeps/bfin/pt-machine.h
deleted file mode 100644
index fef16263e..000000000
--- a/libpthread/linuxthreads/sysdeps/bfin/pt-machine.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson <rth@tamu.edu>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#ifndef _PT_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef PT_EI
-# define PT_EI extern inline
-#endif
-
-extern long int testandset (int *spinlock);
-extern int __compare_and_swap (long *, long , long);
-
-/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
-{
- if (*spinlock)
- return 1;
- else
- {
- *spinlock=1;
- return 0;
- }
-}
-
-#define HAS_COMPARE_AND_SWAP
-
-PT_EI int
-__compare_and_swap (long int *p, long int oldval, long int newval)
-{
- if((*p ^ oldval) == 0) {
- *p = newval;
- return 1;
- }
- else
- return 0;
-}
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/cris/pt-machine.h b/libpthread/linuxthreads/sysdeps/cris/pt-machine.h
deleted file mode 100644
index 431da7101..000000000
--- a/libpthread/linuxthreads/sysdeps/cris/pt-machine.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- CRIS version.
- Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#ifndef _PT_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef PT_EI
-# define PT_EI extern inline __attribute__ ((always_inline))
-#endif
-
-extern long int testandset (int *spinlock);
-extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-
-PT_EI long int
-testandset (int *spinlock)
-{
- register unsigned long int ret;
-
- /* Note the use of a dummy output of *spinlock to expose the write. The
- memory barrier is to stop *other* writes being moved past this code. */
- __asm__ __volatile__("clearf\n"
- "0:\n\t"
- "movu.b [%2],%0\n\t"
- "ax\n\t"
- "move.b %3,[%2]\n\t"
- "bwf 0b\n\t"
- "clearf"
- : "=&r" (ret), "=m" (*spinlock)
- : "r" (spinlock), "r" ((int) 1)
- : "memory");
- return ret;
-}
-
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame.
- I don't trust register variables, so let's do this the safe way. */
-#define CURRENT_STACK_FRAME \
- ({ char *sp; __asm__ ("move.d $sp,%0" : "=rm" (sp)); sp; })
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/frv/pt-machine.h b/libpthread/linuxthreads/sysdeps/frv/pt-machine.h
deleted file mode 100644
index 64df5ffdb..000000000
--- a/libpthread/linuxthreads/sysdeps/frv/pt-machine.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- FR-V version.
- Copyright (C) 2004 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Alexandre Oliva <aoliva@redhat.com>
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#ifndef _PT_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef __ASSEMBLER__
-
-#ifndef PT_EI
-# define PT_EI extern inline __attribute__ ((always_inline))
-#endif
-
-/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
-{
- int i = 1;
- asm ("swap%I0 %M0, %1" : "+m"(*(volatile int *)spinlock), "+r"(i));
- return i;
-}
-
-/* We want the OS to assign stack addresses. */
-#define FLOATING_STACKS 1
-
-/* This symbol is defined by the ABI as the stack size requested by
- the main program. */
-extern char __stacksize;
-#define ARCH_STACK_MAX_SIZE ((unsigned long)&__stacksize)
-
-/* Memory barrier; default is to do nothing */
-#define MEMORY_BARRIER() __asm__ __volatile__("membar" : : : "memory")
-/* Write barrier. */
-#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("membar" : : : "memory")
-
-/* Return the thread descriptor for the current thread. */
-register struct _pthread_descr_struct *THREAD_SELF asm ("gr29");
-#define THREAD_SELF THREAD_SELF
-
-/* Initialize the thread-unique value. */
-#define INIT_THREAD_SELF(descr, nr) \
- (THREAD_SELF = descr)
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME stack_pointer
-register char * stack_pointer __asm__ ("sp");
-
-#endif
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/i386/pt-machine.h b/libpthread/linuxthreads/sysdeps/i386/pt-machine.h
deleted file mode 100644
index af1818d7b..000000000
--- a/libpthread/linuxthreads/sysdeps/i386/pt-machine.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- i386 version.
- Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson <rth@tamu.edu>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#ifndef _PT_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef __ASSEMBLER__
-#ifndef PT_EI
-# define PT_EI extern inline __attribute__ ((always_inline))
-#endif
-
-extern long int testandset (int *spinlock);
-extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME __builtin_frame_address (0)
-
-
-/* See if we can optimize for newer cpus... */
-#if defined __GNUC__ && __GNUC__ >= 2 && \
- (defined __i486__ || defined __pentium__ || defined __pentiumpro__ || defined __pentium4__ || \
- defined __athlon__ || defined __k8__)
-
-/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
-{
- long int ret;
-
- __asm__ __volatile__ (
- "xchgl %0, %1"
- : "=r" (ret), "=m" (*spinlock)
- : "0" (1), "m" (*spinlock)
- : "memory");
-
- return ret;
-}
-
-/* Compare-and-swap for semaphores. It's always available on i686. */
-#define HAS_COMPARE_AND_SWAP
-
-PT_EI int
-__compare_and_swap (long int *p, long int oldval, long int newval)
-{
- char ret;
- long int readval;
-
- __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
- : "=q" (ret), "=m" (*p), "=a" (readval)
- : "r" (newval), "m" (*p), "a" (oldval)
- : "memory");
- return ret;
-}
-
-#if __ASSUME_LDT_WORKS > 0
-#include "../useldt.h"
-#endif
-
-/* The P4 and above really want some help to prevent overheating. */
-#define BUSY_WAIT_NOP __asm__ ("rep; nop")
-
-
-#else /* Generic i386 implementation */
-
-
-
-/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
-{
- long int ret;
-
- __asm__ __volatile__(
- "xchgl %0, %1"
- : "=r"(ret), "=m"(*spinlock)
- : "0"(1), "m"(*spinlock)
- : "memory");
-
- return ret;
-}
-
-
-/* Compare-and-swap for semaphores.
- Available on the 486 and above, but not on the 386.
- We test dynamically whether it's available or not. */
-
-#define HAS_COMPARE_AND_SWAP
-#define TEST_FOR_COMPARE_AND_SWAP
-
-PT_EI int
-__compare_and_swap (long int *p, long int oldval, long int newval)
-{
- char ret;
- long int readval;
-
- __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
- : "=q" (ret), "=m" (*p), "=a" (readval)
- : "r" (newval), "m" (*p), "a" (oldval)
- : "memory");
- return ret;
-}
-
-
-PT_EI int
-get_eflags (void)
-{
- int res;
- __asm__ __volatile__ ("pushfl; popl %0" : "=r" (res) : );
- return res;
-}
-
-
-PT_EI void
-set_eflags (int newflags)
-{
- __asm__ __volatile__ ("pushl %0; popfl" : : "r" (newflags) : "cc");
-}
-
-
-PT_EI int
-compare_and_swap_is_available (void)
-{
- int oldflags = get_eflags ();
- int changed;
- /* Flip AC bit in EFLAGS. */
- set_eflags (oldflags ^ 0x40000);
- /* See if bit changed. */
- changed = (get_eflags () ^ oldflags) & 0x40000;
- /* Restore EFLAGS. */
- set_eflags (oldflags);
- /* If the AC flag did not change, it's a 386 and it lacks cmpxchg.
- Otherwise, it's a 486 or above and it has cmpxchg. */
- return changed != 0;
-}
-#endif /* Generic i386 implementation */
-
-#endif /* __ASSEMBLER__ */
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/i386/tls.h b/libpthread/linuxthreads/sysdeps/i386/tls.h
deleted file mode 100644
index e4f007ee3..000000000
--- a/libpthread/linuxthreads/sysdeps/i386/tls.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/* Definition for thread-local data handling. linuxthreads/i386 version.
- Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifndef _TLS_H
-#define _TLS_H
-
-# include <pt-machine.h>
-
-#ifndef __ASSEMBLER__
-# include <stdbool.h>
-# include <stddef.h>
-# include <stdint.h>
-
-/* Type for the dtv. */
-typedef union dtv
-{
- size_t counter;
- void *pointer;
-} dtv_t;
-
-
-typedef struct
-{
- void *tcb; /* Pointer to the TCB. Not necessary the
- thread descriptor used by libpthread. */
- dtv_t *dtv;
- void *self; /* Pointer to the thread descriptor. */
-} tcbhead_t;
-#endif
-
-
-/* We can support TLS only if the floating-stack support is available. */
-#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT
-
-/* Signal that TLS support is available. */
-//# define USE_TLS 1
-
-# ifndef __ASSEMBLER__
-/* Get system call information. */
-# include <sysdep.h>
-
-
-/* Get the thread descriptor definition. */
-# include <linuxthreads/descr.h>
-
-/* This is the size of the initial TCB. */
-# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
-
-/* This is the size of the TCB. */
-# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
-
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
-
-/* The TCB can have any size and the memory following the address the
- thread pointer points to is unspecified. Allocate the TCB there. */
-# define TLS_TCB_AT_TP 1
-
-
-/* Install the dtv pointer. The pointer passed is to the element with
- index -1 which contain the length. */
-# define INSTALL_DTV(descr, dtvp) \
- ((tcbhead_t *) (descr))->dtv = (dtvp) + 1
-
-/* Install new dtv for current thread. */
-# define INSTALL_NEW_DTV(dtv) \
- ({ struct _pthread_descr_struct *__descr; \
- THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); })
-
-/* Return dtv of given thread descriptor. */
-# define GET_DTV(descr) \
- (((tcbhead_t *) (descr))->dtv)
-
-# ifdef __PIC__
-# define TLS_EBX_ARG "r"
-# define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t"
-# else
-# define TLS_EBX_ARG "b"
-# define TLS_LOAD_EBX
-# endif
-
-# define TLS_DO_MODIFY_LDT(descr, nr) \
-({ \
- struct modify_ldt_ldt_s ldt_entry = \
- { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \
- 1, 0, 0, 1, 0, 1, 0 }; \
- int result; \
- asm volatile (TLS_LOAD_EBX \
- "int $0x80\n\t" \
- TLS_LOAD_EBX \
- : "=a" (result) \
- : "0" (__NR_modify_ldt), \
- /* The extra argument with the "m" constraint is necessary \
- to let the compiler know that we are accessing LDT_ENTRY \
- here. */ \
- "m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry), \
- "d" (sizeof (ldt_entry))); \
- __builtin_expect (result, 0) != 0 ? -1 : nr * 8 + 7; \
-})
-
-# define TLS_DO_SET_THREAD_AREA(descr, secondcall) \
-({ \
- struct modify_ldt_ldt_s ldt_entry = \
- { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \
- 1, 0, 0, 1, 0, 1, 0 }; \
- int result; \
- if (secondcall) \
- ldt_entry.entry_number = ({ int _gs; \
- asm ("movw %%gs, %w0" : "=q" (_gs)); \
- (_gs & 0xffff) >> 3; }); \
- asm volatile (TLS_LOAD_EBX \
- "int $0x80\n\t" \
- TLS_LOAD_EBX \
- : "=a" (result), "=m" (ldt_entry.entry_number) \
- : "0" (__NR_set_thread_area), \
- /* The extra argument with the "m" constraint is necessary \
- to let the compiler know that we are accessing LDT_ENTRY \
- here. */ \
- TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry)); \
- __builtin_expect (result, 0) == 0 ? ldt_entry.entry_number * 8 + 3 : -1; \
-})
-
-# ifdef __ASSUME_SET_THREAD_AREA_SYSCALL
-# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
- TLS_DO_SET_THREAD_AREA (descr, firstcall)
-# elif defined __NR_set_thread_area
-# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
- ({ int __seg = TLS_DO_SET_THREAD_AREA (descr, secondcall); \
- __seg == -1 ? TLS_DO_MODIFY_LDT (descr, 0) : __seg; })
-# else
-# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
- TLS_DO_MODIFY_LDT ((descr), 0)
-# endif
-
-/* Code to initially initialize the thread pointer. This might need
- special attention since 'errno' is not yet available and if the
- operation can cause a failure 'errno' must not be touched. */
-# define TLS_INIT_TP(descr, secondcall) \
- ({ \
- void *_descr = (descr); \
- tcbhead_t *head = _descr; \
- int __gs; \
- \
- head->tcb = _descr; \
- /* For now the thread descriptor is at the same address. */ \
- head->self = _descr; \
- \
- __gs = TLS_SETUP_GS_SEGMENT (_descr, secondcall); \
- if (__builtin_expect (__gs, 7) != -1) \
- { \
- asm ("movw %w0, %%gs" : : "q" (__gs)); \
- __gs = 0; \
- } \
- __gs; \
- })
-
-
-/* Return the address of the dtv for the current thread. */
-# define THREAD_DTV() \
- ({ struct _pthread_descr_struct *__descr; \
- THREAD_GETMEM (__descr, p_header.data.dtvp); })
-
-# endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */
-#endif /* __ASSEMBLER__ */
-
-#endif /* tls.h */
diff --git a/libpthread/linuxthreads/sysdeps/i386/useldt.h b/libpthread/linuxthreads/sysdeps/i386/useldt.h
deleted file mode 100644
index 16aee9989..000000000
--- a/libpthread/linuxthreads/sysdeps/i386/useldt.h
+++ /dev/null
@@ -1,307 +0,0 @@
-/* Special definitions for ix86 machine using segment register based
- thread descriptor.
- Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@cygnus.com>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#ifndef __ASSEMBLER__
-#include <stddef.h> /* For offsetof. */
-#include <stdlib.h> /* For abort(). */
-
-
-/* We don't want to include the kernel header. So duplicate the
- information. */
-
-/* Structure passed on `modify_ldt' call. */
-struct modify_ldt_ldt_s
-{
- unsigned int entry_number;
- unsigned long int base_addr;
- unsigned int limit;
- unsigned int seg_32bit:1;
- unsigned int contents:2;
- unsigned int read_exec_only:1;
- unsigned int limit_in_pages:1;
- unsigned int seg_not_present:1;
- unsigned int useable:1;
- unsigned int empty:25;
-};
-
-/* System call to set LDT entry. */
-extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
-
-
-/* Return the thread descriptor for the current thread.
-
- The contained asm must *not* be marked volatile since otherwise
- assignments like
- pthread_descr self = thread_self();
- do not get optimized away. */
-#define THREAD_SELF \
-({ \
- register pthread_descr __self; \
- __asm__ ("movl %%gs:%c1,%0" : "=r" (__self) \
- : "i" (offsetof (struct _pthread_descr_struct, \
- p_header.data.self))); \
- __self; \
-})
-
-
-/* Initialize the thread-unique value. Two possible ways to do it. */
-
-#define DO_MODIFY_LDT(descr, nr) \
-({ \
- struct modify_ldt_ldt_s ldt_entry = \
- { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \
- 1, 0, 0, 1, 0, 1, 0 }; \
- if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0) \
- abort (); \
- asm ("movw %w0, %%gs" : : "q" (nr * 8 + 7)); \
-})
-
-#ifdef __PIC__
-# define USETLS_EBX_ARG "r"
-# define USETLS_LOAD_EBX "xchgl %3, %%ebx\n\t"
-#else
-# define USETLS_EBX_ARG "b"
-# define USETLS_LOAD_EBX
-#endif
-
-/* When using the new set_thread_area call, we don't need to change %gs
- because we inherited the value set up in the main thread by TLS setup.
- We need to extract that value and set up the same segment in this
- thread. */
-#if USE_TLS
-# define DO_SET_THREAD_AREA_REUSE(nr) 1
-#else
-/* Without TLS, we do the initialization of the main thread, where NR == 0. */
-# define DO_SET_THREAD_AREA_REUSE(nr) (!__builtin_constant_p (nr) || (nr))
-#endif
-#define DO_SET_THREAD_AREA(descr, nr) \
-({ \
- int __gs; \
- if (DO_SET_THREAD_AREA_REUSE (nr)) \
- { \
- asm ("movw %%gs, %w0" : "=q" (__gs)); \
- struct modify_ldt_ldt_s ldt_entry = \
- { (__gs & 0xffff) >> 3, \
- (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \
- 1, 0, 0, 1, 0, 1, 0 }; \
- \
- int __result; \
- __asm (USETLS_LOAD_EBX \
- "movl %2, %%eax\n\t" \
- "int $0x80\n\t" \
- USETLS_LOAD_EBX \
- : "&a" (__result) \
- : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area)); \
- if (__result == 0) \
- asm ("movw %w0, %%gs" :: "q" (__gs)); \
- else \
- __gs = -1; \
- } \
- else \
- { \
- struct modify_ldt_ldt_s ldt_entry = \
- { -1, \
- (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \
- 1, 0, 0, 1, 0, 1, 0 }; \
- int __result; \
- __asm (USETLS_LOAD_EBX \
- "movl %2, %%eax\n\t" \
- "int $0x80\n\t" \
- USETLS_LOAD_EBX \
- : "&a" (__result) \
- : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area)); \
- if (__result == 0) \
- { \
- __gs = (ldt_entry.entry_number << 3) + 3; \
- asm ("movw %w0, %%gs" : : "q" (__gs)); \
- } \
- else \
- __gs = -1; \
- } \
- __gs; \
-})
-
-#if defined __ASSUME_SET_THREAD_AREA_SYSCALL
-# define INIT_THREAD_SELF(descr, nr) DO_SET_THREAD_AREA (descr, nr)
-#elif defined __NR_set_thread_area
-# define INIT_THREAD_SELF(descr, nr) \
-({ \
- if (__builtin_expect (__have_no_set_thread_area, 0) \
- || (DO_SET_THREAD_AREA (descr, DO_SET_THREAD_AREA_REUSE (nr)) == -1 \
- && (__have_no_set_thread_area = 1))) \
- DO_MODIFY_LDT (descr, nr); \
-})
-/* Defined in pspinlock.c. */
-extern int __have_no_set_thread_area;
-#else
-# define INIT_THREAD_SELF(descr, nr) DO_MODIFY_LDT (descr, nr)
-#endif
-
-/* Free resources associated with thread descriptor. */
-#ifdef __ASSUME_SET_THREAD_AREA_SYSCALL
-#define FREE_THREAD(descr, nr) do { } while (0)
-#elif defined __NR_set_thread_area
-#define FREE_THREAD(descr, nr) \
-{ \
- int __gs; \
- __asm__ __volatile__ ("movw %%gs, %w0" : "=q" (__gs)); \
- if (__builtin_expect (__gs & 4, 0)) \
- { \
- struct modify_ldt_ldt_s ldt_entry = \
- { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \
- __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \
- } \
-}
-#else
-#define FREE_THREAD(descr, nr) \
-{ \
- struct modify_ldt_ldt_s ldt_entry = \
- { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \
- __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \
-}
-#endif
-
-/* Read member of the thread descriptor directly. */
-#define THREAD_GETMEM(descr, member) \
-({ \
- __typeof__ (descr->member) __value; \
- if (sizeof (__value) == 1) \
- __asm__ __volatile__ ("movb %%gs:%P2,%b0" \
- : "=q" (__value) \
- : "0" (0), \
- "i" (offsetof (struct _pthread_descr_struct, \
- member))); \
- else if (sizeof (__value) == 4) \
- __asm__ __volatile__ ("movl %%gs:%P1,%0" \
- : "=r" (__value) \
- : "i" (offsetof (struct _pthread_descr_struct, \
- member))); \
- else \
- { \
- if (sizeof (__value) != 8) \
- /* There should not be any value with a size other than 1, 4 or 8. */\
- abort (); \
- \
- __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t" \
- "movl %%gs:%P2,%%edx" \
- : "=A" (__value) \
- : "i" (offsetof (struct _pthread_descr_struct, \
- member)), \
- "i" (offsetof (struct _pthread_descr_struct, \
- member) + 4)); \
- } \
- __value; \
-})
-
-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
-#define THREAD_GETMEM_NC(descr, member) \
-({ \
- __typeof__ (descr->member) __value; \
- if (sizeof (__value) == 1) \
- __asm__ __volatile__ ("movb %%gs:(%2),%b0" \
- : "=q" (__value) \
- : "0" (0), \
- "r" (offsetof (struct _pthread_descr_struct, \
- member))); \
- else if (sizeof (__value) == 4) \
- __asm__ __volatile__ ("movl %%gs:(%1),%0" \
- : "=r" (__value) \
- : "r" (offsetof (struct _pthread_descr_struct, \
- member))); \
- else \
- { \
- if (sizeof (__value) != 8) \
- /* There should not be any value with a size other than 1, 4 or 8. */\
- abort (); \
- \
- __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t" \
- "movl %%gs:4(%1),%%edx" \
- : "=&A" (__value) \
- : "r" (offsetof (struct _pthread_descr_struct, \
- member))); \
- } \
- __value; \
-})
-
-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
-#define THREAD_SETMEM(descr, member, value) \
-({ \
- __typeof__ (descr->member) __value = (value); \
- if (sizeof (__value) == 1) \
- __asm__ __volatile__ ("movb %0,%%gs:%P1" : \
- : "q" (__value), \
- "i" (offsetof (struct _pthread_descr_struct, \
- member))); \
- else if (sizeof (__value) == 4) \
- __asm__ __volatile__ ("movl %0,%%gs:%P1" : \
- : "r" (__value), \
- "i" (offsetof (struct _pthread_descr_struct, \
- member))); \
- else \
- { \
- if (sizeof (__value) != 8) \
- /* There should not be any value with a size other than 1, 4 or 8. */\
- abort (); \
- \
- __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n" \
- "movl %%edx,%%gs:%P2" : \
- : "A" (__value), \
- "i" (offsetof (struct _pthread_descr_struct, \
- member)), \
- "i" (offsetof (struct _pthread_descr_struct, \
- member) + 4)); \
- } \
-})
-
-/* Set member of the thread descriptor directly. */
-#define THREAD_SETMEM_NC(descr, member, value) \
-({ \
- __typeof__ (descr->member) __value = (value); \
- if (sizeof (__value) == 1) \
- __asm__ __volatile__ ("movb %0,%%gs:(%1)" : \
- : "q" (__value), \
- "r" (offsetof (struct _pthread_descr_struct, \
- member))); \
- else if (sizeof (__value) == 4) \
- __asm__ __volatile__ ("movl %0,%%gs:(%1)" : \
- : "r" (__value), \
- "r" (offsetof (struct _pthread_descr_struct, \
- member))); \
- else \
- { \
- if (sizeof (__value) != 8) \
- /* There should not be any value with a size other than 1, 4 or 8. */\
- abort (); \
- \
- __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t" \
- "movl %%edx,%%gs:4(%1)" : \
- : "A" (__value), \
- "r" (offsetof (struct _pthread_descr_struct, \
- member))); \
- } \
-})
-#endif
-
-/* We want the OS to assign stack addresses. */
-#define FLOATING_STACKS 1
-
-/* Maximum size of the stack if the rlimit is unlimited. */
-#define ARCH_STACK_MAX_SIZE 8*1024*1024
diff --git a/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h b/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h
deleted file mode 100644
index 4670ae3c4..000000000
--- a/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- m68k version.
- Copyright (C) 1996, 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson <rth@tamu.edu>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#ifndef _PT_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef PT_EI
-# define PT_EI extern inline __attribute__ ((always_inline))
-#endif
-
-extern long int testandset (int *spinlock);
-extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-
-/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
-{
- char ret;
-
- __asm__ __volatile__(
-#if !defined(__mcoldfire__) && !defined(__mcf5200__) && !defined(__m68000)
- "tas %1; sne %0"
-#else
- "bset #7,%1; sne %0"
-#endif
- : "=dm"(ret), "=m"(*spinlock)
- : "m"(*spinlock)
- : "cc");
-
- return ret;
-}
-
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME stack_pointer
-register char * stack_pointer __asm__ ("%sp");
-
-
-/* Compare-and-swap for semaphores. */
-
-#if !defined(__mcoldfire__) && !defined(__mcf5200__) && !defined(__mc68000)
-#define HAS_COMPARE_AND_SWAP
-PT_EI int
-__compare_and_swap (long int *p, long int oldval, long int newval)
-{
- char ret;
- long int readval;
-
- __asm__ __volatile__ ("casl %2, %3, %1; seq %0"
- : "=dm" (ret), "=m" (*p), "=d" (readval)
- : "d" (newval), "m" (*p), "2" (oldval));
-
- return ret;
-}
-#endif
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/mips/pt-machine.h b/libpthread/linuxthreads/sysdeps/mips/pt-machine.h
deleted file mode 100644
index f7efc881d..000000000
--- a/libpthread/linuxthreads/sysdeps/mips/pt-machine.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
-
- Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004
- Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ralf Baechle <ralf@gnu.org>.
- Based on the Alpha version by Richard Henderson <rth@tamu.edu>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#ifndef _PT_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#include <features.h>
-
-/* Copyright (C) 2000, 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Maciej W. Rozycki <macro@ds2.pg.gda.pl>, 2000. */
-static inline int
-_test_and_set (int *p, int v) __THROW
-{
- int r, t;
-
- __asm__ __volatile__
- ("/* Inline test and set */\n"
- "1:\n\t"
- ".set push\n\t"
- ".set mips2\n\t"
- "ll %0,%3\n\t"
- "move %1,%4\n\t"
- "beq %0,%4,2f\n\t"
- "sc %1,%2\n\t"
- ".set pop\n\t"
- "beqz %1,1b\n"
- "2:\n\t"
- "/* End test and set */"
- : "=&r" (r), "=&r" (t), "=m" (*p)
- : "m" (*p), "r" (v)
- : "memory");
-
- return r;
-}
-
-
-#ifndef PT_EI
-# define PT_EI extern inline __attribute__ ((always_inline))
-#endif
-
-extern long int testandset (int *spinlock);
-extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-
-
-/* Spinlock implementation; required. */
-
-PT_EI long int
-testandset (int *spinlock)
-{
- return _test_and_set (spinlock, 1);
-}
-
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME stack_pointer
-register char * stack_pointer __asm__ ("$29");
-
-
-/* Compare-and-swap for semaphores. */
-
-#define HAS_COMPARE_AND_SWAP
-PT_EI int
-__compare_and_swap (long int *p, long int oldval, long int newval)
-{
- long int ret, temp;
-
- __asm__ __volatile__
- ("/* Inline compare & swap */\n"
- "1:\n\t"
- ".set push\n\t"
- ".set mips2\n\t"
- "ll %1,%5\n\t"
- "move %0,$0\n\t"
- "bne %1,%3,2f\n\t"
- "move %0,%4\n\t"
- "sc %0,%2\n\t"
- ".set pop\n\t"
- "beqz %0,1b\n"
- "2:\n\t"
- "/* End compare & swap */"
- : "=&r" (ret), "=&r" (temp), "=m" (*p)
- : "r" (oldval), "r" (newval), "m" (*p)
- : "memory");
-
- return ret;
-}
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/nios/pt-machine.h b/libpthread/linuxthreads/sysdeps/nios/pt-machine.h
deleted file mode 100644
index 5d82b8d16..000000000
--- a/libpthread/linuxthreads/sysdeps/nios/pt-machine.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- ARM version.
- Copyright (C) 1997, 1998 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Philip Blundell <philb@gnu.org>.
-
- 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_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef PT_EI
-# define PT_EI extern inline
-#endif
-
-extern long int testandset (int *spinlock);
-/* Spinlock implementation; required. */
-/* it is weird and dangerous to disable interrupt in userspace, but for nios
- what else we can do before we have a swap like instruction? This is better
- than nothing
- */
-PT_EI long int
-testandset (int *spinlock)
-{
- unsigned int ret;
-
- __asm__ __volatile__("pfx 8\n\t"
- "wrctl %1 ; disable interrupt\n\t"
- "nop\n\t"
- "nop\n\t"
- "ld %0, [%2]\n\t"
- "st [%2], %1\n\t"
- "pfx 9\n\t"
- "wrctl %1 ; enable interrupt\n\t"
- "nop\n\t"
- "nop\n\t"
- : "=&r"(ret)
- : "r"(1), "r"(spinlock)
- : "memory");
-
- return ret;
-}
-
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME stack_pointer
-register char * stack_pointer __asm__ ("%sp");
-
-/* nios needs more because of reg windows */
-#define THREAD_MANAGER_STACK_SIZE (32*1024)
-#define STACK_SIZE (32*1024)
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/nios2/pt-machine.h b/libpthread/linuxthreads/sysdeps/nios2/pt-machine.h
deleted file mode 100644
index 484a77e14..000000000
--- a/libpthread/linuxthreads/sysdeps/nios2/pt-machine.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- nios2 version.
- Copyright (C) 1996, 1998, 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 Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#ifndef _PT_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef PT_EI
-# define PT_EI extern inline
-#endif
-
-extern long int testandset (int *spinlock);
-
-/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
-{
- unsigned int scratch;
- long int ret=-2;
-
- __asm__ __volatile__(
- "rdctl %0, status\n\t"
- "and %0, %0, %1\n\t"
- "wrctl status, %0 #disable interrupts\n\t"
- "ldw %1, 0(%4)\n\t"
- "stw %3, 0(%4)\n\t"
- "ori %0, %0, 1\n\t"
- "wrctl status, %0 #enable interrupts\n\t"
- : "=&r"(scratch), "=r"(ret)
- : "1"(ret), "r"(1), "r"(spinlock)
- : "memory");
-
- return ret;
-}
-
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME stack_pointer
-register char * stack_pointer __asm__ ("%sp");
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h b/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h
deleted file mode 100644
index 9e6543a26..000000000
--- a/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- powerpc version.
- Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor
- User's Manual', by IBM and Motorola. */
-
-#ifndef _PT_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef PT_EI
-# define PT_EI extern inline
-#endif
-
-extern long int testandset (int *spinlock);
-extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-
-/* For multiprocessor systems, we want to ensure all memory accesses
- are completed before we reset a lock. On other systems, we still
- need to make sure that the compiler has flushed everything to memory. */
-#define MEMORY_BARRIER() __asm__ __volatile__ ("sync" : : : "memory")
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME stack_pointer
-register char * stack_pointer __asm__ ("r1");
-
-/* Register r2 (tp) is reserved by the ABI as "thread pointer". */
-struct _pthread_descr_struct;
-register struct _pthread_descr_struct *__thread_self __asm__("r2");
-
-/* Return the thread descriptor for the current thread. */
-#define THREAD_SELF __thread_self
-
-/* Initialize the thread-unique value. */
-#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr))
-
-/* Compare-and-swap for semaphores. */
-/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */
-
-#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
-#define IMPLEMENT_TAS_WITH_CAS
-
-PT_EI int
-__compare_and_swap (long int *p, long int oldval, long int newval)
-{
- int ret;
-
- __asm__ __volatile__ (
- "0: lwarx %0,0,%1 ;"
- " xor. %0,%3,%0;"
- " bne 1f;"
- " stwcx. %2,0,%1;"
- " bne- 0b;"
- "1: "
- : "=&r"(ret)
- : "r"(p), "r"(newval), "r"(oldval)
- : "cr0", "memory");
- /* This version of __compare_and_swap is to be used when acquiring
- a lock, so we don't need to worry about whether other memory
- operations have completed, but we do need to be sure that any loads
- after this point really occur after we have acquired the lock. */
- __asm__ __volatile__ ("isync" : : : "memory");
- return ret == 0;
-}
-
-PT_EI int
-__compare_and_swap_with_release_semantics (long int *p,
- long int oldval, long int newval)
-{
- int ret;
-
- MEMORY_BARRIER ();
- __asm__ __volatile__ (
- "0: lwarx %0,0,%1 ;"
- " xor. %0,%3,%0;"
- " bne 1f;"
- " stwcx. %2,0,%1;"
- " bne- 0b;"
- "1: "
- : "=&r"(ret)
- : "r"(p), "r"(newval), "r"(oldval)
- : "cr0", "memory");
- return ret == 0;
-}
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h b/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h
deleted file mode 100644
index e2b267d32..000000000
--- a/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h
+++ /dev/null
@@ -1,328 +0,0 @@
-/* libc-internal interface for mutex locks. LinuxThreads version.
- Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
- Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#ifndef _BITS_LIBC_LOCK_H
-#define _BITS_LIBC_LOCK_H 1
-
-#include <pthread.h>
-
-/* Mutex type. */
-#if defined(_LIBC) || defined(_IO_MTSAFE_IO)
-typedef pthread_mutex_t __libc_lock_t;
-typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t;
-# ifdef __USE_UNIX98
-typedef pthread_rwlock_t __libc_rwlock_t;
-# else
-typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
-# endif
-#else
-typedef struct __libc_lock_opaque__ __libc_lock_t;
-typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
-typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
-#endif
-
-/* Type for key to thread-specific data. */
-typedef pthread_key_t __libc_key_t;
-
-/* Define a lock variable NAME with storage class CLASS. The lock must be
- initialized with __libc_lock_init before it can be used (or define it
- with __libc_lock_define_initialized, below). Use `extern' for CLASS to
- declare a lock defined in another module. In public structure
- definitions you must use a pointer to the lock structure (i.e., NAME
- begins with a `*'), because its storage size will not be known outside
- of libc. */
-#define __libc_lock_define(CLASS,NAME) \
- CLASS __libc_lock_t NAME;
-#define __libc_rwlock_define(CLASS,NAME) \
- CLASS __libc_rwlock_t NAME;
-#define __libc_lock_define_recursive(CLASS,NAME) \
- CLASS __libc_lock_recursive_t NAME;
-
-/* Define an initialized lock variable NAME with storage class CLASS.
-
- For the C library we take a deeper look at the initializer. For
- this implementation all fields are initialized to zero. Therefore
- we don't initialize the variable which allows putting it into the
- BSS section. (Except on PA-RISC and other odd architectures, where
- initialized locks must be set to one due to the lack of normal
- atomic operations.) */
-
-#if __LT_SPINLOCK_INIT == 0
-# define __libc_lock_define_initialized(CLASS,NAME) \
- CLASS __libc_lock_t NAME;
-#else
-# define __libc_lock_define_initialized(CLASS,NAME) \
- CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-#define __libc_rwlock_define_initialized(CLASS,NAME) \
- CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
-
-/* Define an initialized recursive lock variable NAME with storage
- class CLASS. */
-#define __libc_lock_define_initialized_recursive(CLASS,NAME) \
- CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
-#define _LIBC_LOCK_RECURSIVE_INITIALIZER \
- {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
-
-/* Initialize the named lock variable, leaving it in a consistent, unlocked
- state. */
-#define __libc_lock_init(NAME) \
- (__pthread_mutex_init != NULL ? __pthread_mutex_init (&(NAME), NULL) : 0);
-#define __libc_rwlock_init(NAME) \
- (__pthread_rwlock_init != NULL ? __pthread_rwlock_init (&(NAME), NULL) : 0);
-
-/* Same as last but this time we initialize a recursive mutex. */
-#define __libc_lock_init_recursive(NAME) \
- do { \
- if (__pthread_mutex_init != NULL) \
- { \
- pthread_mutexattr_t __attr; \
- __pthread_mutexattr_init (&__attr); \
- __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \
- __pthread_mutex_init (&(NAME).mutex, &__attr); \
- __pthread_mutexattr_destroy (&__attr); \
- } \
- } while (0);
-
-/* Finalize the named lock variable, which must be locked. It cannot be
- used again until __libc_lock_init is called again on it. This must be
- called on a lock variable before the containing storage is reused. */
-#define __libc_lock_fini(NAME) \
- (__pthread_mutex_destroy != NULL ? __pthread_mutex_destroy (&(NAME)) : 0);
-#define __libc_rwlock_fini(NAME) \
- (__pthread_rwlock_destroy != NULL ? __pthread_rwlock_destroy (&(NAME)) : 0);
-
-/* Finalize recursive named lock. */
-#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex)
-
-/* Lock the named lock variable. */
-#define __libc_lock_lock(NAME) \
- (__pthread_mutex_lock != NULL ? __pthread_mutex_lock (&(NAME)) : 0);
-#define __libc_rwlock_rdlock(NAME) \
- (__pthread_rwlock_rdlock != NULL ? __pthread_rwlock_rdlock (&(NAME)) : 0);
-#define __libc_rwlock_wrlock(NAME) \
- (__pthread_rwlock_wrlock != NULL ? __pthread_rwlock_wrlock (&(NAME)) : 0);
-
-/* Lock the recursive named lock variable. */
-#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex)
-
-/* Try to lock the named lock variable. */
-#define __libc_lock_trylock(NAME) \
- (__pthread_mutex_trylock != NULL ? __pthread_mutex_trylock (&(NAME)) : 0)
-#define __libc_rwlock_tryrdlock(NAME) \
- (__pthread_rwlock_tryrdlock != NULL \
- ? __pthread_rwlock_tryrdlock (&(NAME)) : 0)
-#define __libc_rwlock_trywrlock(NAME) \
- (__pthread_rwlock_trywrlock != NULL \
- ? __pthread_rwlock_trywrlock (&(NAME)) : 0)
-
-/* Try to lock the recursive named lock variable. */
-#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex)
-
-/* Unlock the named lock variable. */
-#define __libc_lock_unlock(NAME) \
- (__pthread_mutex_unlock != NULL ? __pthread_mutex_unlock (&(NAME)) : 0);
-#define __libc_rwlock_unlock(NAME) \
- (__pthread_rwlock_unlock != NULL ? __pthread_rwlock_unlock (&(NAME)) : 0);
-
-/* Unlock the recursive named lock variable. */
-#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex)
-
-
-/* Define once control variable. */
-#if PTHREAD_ONCE_INIT == 0
-/* Special case for static variables where we can avoid the initialization
- if it is zero. */
-# define __libc_once_define(CLASS, NAME) \
- CLASS pthread_once_t NAME
-#else
-# define __libc_once_define(CLASS, NAME) \
- CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
-#endif
-
-/* Call handler iff the first call. */
-#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
- do { \
- if (__pthread_once != NULL) \
- __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \
- else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \
- INIT_FUNCTION (); \
- (ONCE_CONTROL) = !PTHREAD_ONCE_INIT; \
- } \
- } while (0)
-
-
-/* Start critical region with cleanup. */
-#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
- { struct _pthread_cleanup_buffer _buffer; \
- int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \
- if (_avail) { \
- _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \
- }
-
-/* End critical region with cleanup. */
-#define __libc_cleanup_region_end(DOIT) \
- if (_avail) { \
- _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \
- } \
- }
-
-/* Sometimes we have to exit the block in the middle. */
-#define __libc_cleanup_end(DOIT) \
- if (_avail) { \
- _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \
- }
-
-/* Create thread-specific key. */
-#define __libc_key_create(KEY, DESTRUCTOR) \
- (__pthread_key_create != NULL ? __pthread_key_create (KEY, DESTRUCTOR) : 1)
-
-/* Get thread-specific data. */
-#define __libc_getspecific(KEY) \
- (__pthread_getspecific != NULL ? __pthread_getspecific (KEY) : NULL)
-
-/* Set thread-specific data. */
-#define __libc_setspecific(KEY, VALUE) \
- (__pthread_setspecific != NULL ? __pthread_setspecific (KEY, VALUE) : 0)
-
-
-/* Register handlers to execute before and after `fork'. */
-#define __libc_atfork(PREPARE, PARENT, CHILD) \
- (__pthread_atfork != NULL ? __pthread_atfork (PREPARE, PARENT, CHILD) : 0)
-
-/* Functions that are used by this file and are internal to the GNU C
- library. */
-
-extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
- __const pthread_mutexattr_t *__mutex_attr);
-
-extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
-
-extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
-
-extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
-
-extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
-
-extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr);
-
-extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
-
-extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr,
- int __kind);
-
-#ifdef __USE_UNIX98
-extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
- __const pthread_rwlockattr_t *__attr);
-
-extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
-
-extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
-
-extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
-
-extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
-
-extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
-
-extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
-#endif
-
-extern int __pthread_key_create (pthread_key_t *__key,
- void (*__destr_function) (void *));
-
-extern int __pthread_setspecific (pthread_key_t __key,
- __const void *__pointer);
-
-extern void *__pthread_getspecific (pthread_key_t __key);
-
-extern int __pthread_once (pthread_once_t *__once_control,
- void (*__init_routine) (void));
-
-extern int __pthread_atfork (void (*__prepare) (void),
- void (*__parent) (void),
- void (*__child) (void));
-
-
-
-/* Make the pthread functions weak so that we can elide them from
- single-threaded processes. */
-#ifndef __NO_WEAK_PTHREAD_ALIASES
-# ifdef weak_extern
-# if _LIBC
-# include <bp-sym.h>
-# else
-# define BP_SYM (sym) sym
-# endif
-weak_extern (BP_SYM (__pthread_mutex_init))
-weak_extern (BP_SYM (__pthread_mutex_destroy))
-weak_extern (BP_SYM (__pthread_mutex_lock))
-weak_extern (BP_SYM (__pthread_mutex_trylock))
-weak_extern (BP_SYM (__pthread_mutex_unlock))
-weak_extern (BP_SYM (__pthread_mutexattr_init))
-weak_extern (BP_SYM (__pthread_mutexattr_destroy))
-weak_extern (BP_SYM (__pthread_mutexattr_settype))
-weak_extern (BP_SYM (__pthread_rwlock_init))
-weak_extern (BP_SYM (__pthread_rwlock_destroy))
-weak_extern (BP_SYM (__pthread_rwlock_rdlock))
-weak_extern (BP_SYM (__pthread_rwlock_tryrdlock))
-weak_extern (BP_SYM (__pthread_rwlock_wrlock))
-weak_extern (BP_SYM (__pthread_rwlock_trywrlock))
-weak_extern (BP_SYM (__pthread_rwlock_unlock))
-weak_extern (BP_SYM (__pthread_key_create))
-weak_extern (BP_SYM (__pthread_setspecific))
-weak_extern (BP_SYM (__pthread_getspecific))
-weak_extern (BP_SYM (__pthread_once))
-weak_extern (__pthread_initialize)
-weak_extern (__pthread_atfork)
-weak_extern (BP_SYM (_pthread_cleanup_push_defer))
-weak_extern (BP_SYM (_pthread_cleanup_pop_restore))
-# else
-# pragma weak __pthread_mutex_init
-# pragma weak __pthread_mutex_destroy
-# pragma weak __pthread_mutex_lock
-# pragma weak __pthread_mutex_trylock
-# pragma weak __pthread_mutex_unlock
-# pragma weak __pthread_mutexattr_init
-# pragma weak __pthread_mutexattr_destroy
-# pragma weak __pthread_mutexattr_settype
-# pragma weak __pthread_rwlock_destroy
-# pragma weak __pthread_rwlock_rdlock
-# pragma weak __pthread_rwlock_tryrdlock
-# pragma weak __pthread_rwlock_wrlock
-# pragma weak __pthread_rwlock_trywrlock
-# pragma weak __pthread_rwlock_unlock
-# pragma weak __pthread_key_create
-# pragma weak __pthread_setspecific
-# pragma weak __pthread_getspecific
-# pragma weak __pthread_once
-# pragma weak __pthread_initialize
-# pragma weak __pthread_atfork
-# pragma weak _pthread_cleanup_push_defer
-# pragma weak _pthread_cleanup_pop_restore
-# endif
-#endif
-
-/* We need portable names for some functions. E.g., when they are
- used as argument to __libc_cleanup_region_start. */
-#define __libc_mutex_unlock __pthread_mutex_unlock
-
-#endif /* bits/libc-lock.h */
diff --git a/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h b/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h
deleted file mode 100644
index efd0c83be..000000000
--- a/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* libc-internal interface for thread-specific data. LinuxThreads version.
- Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; 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_LIBC_TSD_H
-#define _BITS_LIBC_TSD_H 1
-
-/* Fast thread-specific data internal to libc. */
-enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
- _LIBC_TSD_KEY_DL_ERROR,
- _LIBC_TSD_KEY_RPC_VARS,
- _LIBC_TSD_KEY_LOCALE,
- _LIBC_TSD_KEY_CTYPE_B,
- _LIBC_TSD_KEY_CTYPE_TOLOWER,
- _LIBC_TSD_KEY_CTYPE_TOUPPER,
- _LIBC_TSD_KEY_N };
-
-#include <sys/cdefs.h>
-#include <tls.h>
-
-#if USE_TLS && HAVE___THREAD
-
-/* When __thread works, the generic definition is what we want. */
-# include <sysdeps/generic/bits/libc-tsd.h>
-
-#else
-
-extern void *(*__libc_internal_tsd_get) (enum __libc_tsd_key_t) __THROW;
-extern int (*__libc_internal_tsd_set) (enum __libc_tsd_key_t,
- __const void *) __THROW;
-extern void **(*const __libc_internal_tsd_address) (enum __libc_tsd_key_t)
- __THROW __attribute__ ((__const__));
-
-#define __libc_tsd_address(KEY) \
- (__libc_internal_tsd_address != NULL \
- ? __libc_internal_tsd_address (_LIBC_TSD_KEY_##KEY) \
- : &__libc_tsd_##KEY##_data)
-
-#define __libc_tsd_define(CLASS, KEY) CLASS void *__libc_tsd_##KEY##_data;
-#define __libc_tsd_get(KEY) \
- (__libc_internal_tsd_get != NULL \
- ? __libc_internal_tsd_get (_LIBC_TSD_KEY_##KEY) \
- : __libc_tsd_##KEY##_data)
-#define __libc_tsd_set(KEY, VALUE) \
- (__libc_internal_tsd_set != NULL \
- ? __libc_internal_tsd_set (_LIBC_TSD_KEY_##KEY, (VALUE)) \
- : ((__libc_tsd_##KEY##_data = (VALUE)), 0))
-
-#endif
-
-#endif /* bits/libc-tsd.h */
diff --git a/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h b/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h
deleted file mode 100644
index faec63b06..000000000
--- a/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-#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
-
-#define __need_schedparam
-#include <bits/sched.h>
-
-/* Fast locks (not abstract because mutexes and conditions aren't abstract). */
-struct _pthread_fastlock
-{
- long int __status; /* "Free" or "taken" or head of waiting list */
- int __spinlock; /* Used by compare_and_swap emulation. Also,
- adaptive SMP lock stores spin count here. */
-};
-
-#ifndef _PTHREAD_DESCR_DEFINED
-/* Thread descriptors */
-typedef struct _pthread_descr_struct *_pthread_descr;
-# define _PTHREAD_DESCR_DEFINED
-#endif
-
-
-/* Attributes for threads. */
-typedef struct __pthread_attr_s
-{
- int __detachstate;
- int __schedpolicy;
- struct __sched_param __schedparam;
- int __inheritsched;
- int __scope;
- size_t __guardsize;
- int __stackaddr_set;
- void *__stackaddr;
- size_t __stacksize;
-} pthread_attr_t;
-
-
-/* Conditions (not abstract because of PTHREAD_COND_INITIALIZER */
-typedef struct
-{
- struct _pthread_fastlock __c_lock; /* Protect against concurrent access */
- _pthread_descr __c_waiting; /* Threads waiting on this condition */
-} pthread_cond_t;
-
-
-/* Attribute for conditionally variables. */
-typedef struct
-{
- int __dummy;
-} pthread_condattr_t;
-
-/* Keys for thread-specific data */
-typedef unsigned int pthread_key_t;
-
-
-/* Mutexes (not abstract because of PTHREAD_MUTEX_INITIALIZER). */
-/* (The layout is unnatural to maintain binary compatibility
- with earlier releases of LinuxThreads.) */
-typedef struct
-{
- int __m_reserved; /* Reserved for future use */
- int __m_count; /* Depth of recursive locking */
- _pthread_descr __m_owner; /* Owner thread (if recursive or errcheck) */
- int __m_kind; /* Mutex kind: fast, recursive or errcheck */
- struct _pthread_fastlock __m_lock; /* Underlying fast lock */
-} pthread_mutex_t;
-
-
-/* Attribute for mutex. */
-typedef struct
-{
- int __mutexkind;
-} pthread_mutexattr_t;
-
-
-/* Once-only execution */
-typedef int pthread_once_t;
-
-
-#if defined __USE_UNIX98 || defined __USE_XOPEN2K
-/* Read-write locks. */
-typedef struct _pthread_rwlock_t
-{
- struct _pthread_fastlock __rw_lock; /* Lock to guarantee mutual exclusion */
- int __rw_readers; /* Number of readers */
- _pthread_descr __rw_writer; /* Identity of writer, or NULL if none */
- _pthread_descr __rw_read_waiting; /* Threads waiting for reading */
- _pthread_descr __rw_write_waiting; /* Threads waiting for writing */
- int __rw_kind; /* Reader/Writer preference selection */
- int __rw_pshared; /* Shared between processes or not */
-} pthread_rwlock_t;
-
-
-/* Attribute for read-write locks. */
-typedef struct
-{
- int __lockkind;
- int __pshared;
-} pthread_rwlockattr_t;
-#endif
-
-#ifdef __USE_XOPEN2K
-/* POSIX spinlock data type. */
-typedef volatile int pthread_spinlock_t;
-
-/* POSIX barrier. */
-typedef struct {
- struct _pthread_fastlock __ba_lock; /* Lock to guarantee mutual exclusion */
- int __ba_required; /* Threads needed for completion */
- int __ba_present; /* Threads waiting */
- _pthread_descr __ba_waiting; /* Queue of waiting threads */
-} pthread_barrier_t;
-
-/* barrier attribute */
-typedef struct {
- int __pshared;
-} pthread_barrierattr_t;
-
-#endif
-
-
-/* Thread identifiers */
-typedef unsigned long int pthread_t;
-
-#endif /* bits/pthreadtypes.h */
diff --git a/libpthread/linuxthreads/sysdeps/pthread/pthread.h b/libpthread/linuxthreads/sysdeps/pthread/pthread.h
deleted file mode 100644
index 6613cab88..000000000
--- a/libpthread/linuxthreads/sysdeps/pthread/pthread.h
+++ /dev/null
@@ -1,705 +0,0 @@
-/* Linuxthreads - a simple clone()-based implementation of Posix */
-/* threads for Linux. */
-/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU Library General Public License for more details. */
-
-#ifndef _PTHREAD_H
-#define _PTHREAD_H 1
-
-#include <features.h>
-
-#include <sched.h>
-#include <time.h>
-
-#define __need_sigset_t
-#include <signal.h>
-#include <bits/pthreadtypes.h>
-#include <bits/initspin.h>
-#ifdef _LIBC
-#include <bits/uClibc_pthread.h>
-#endif
-
-
-__BEGIN_DECLS
-
-/* Initializers. */
-
-#define PTHREAD_MUTEX_INITIALIZER \
- {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER}
-#ifdef __USE_GNU
-# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
- {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __LOCK_INITIALIZER}
-# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
- {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __LOCK_INITIALIZER}
-# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
- {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER}
-#endif
-
-#define PTHREAD_COND_INITIALIZER {__LOCK_INITIALIZER, 0}
-
-#if defined __USE_UNIX98 || defined __USE_XOPEN2K
-# define PTHREAD_RWLOCK_INITIALIZER \
- { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \
- PTHREAD_RWLOCK_DEFAULT_NP, PTHREAD_PROCESS_PRIVATE }
-#endif
-#ifdef __USE_GNU
-# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \
- { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \
- PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, PTHREAD_PROCESS_PRIVATE }
-#endif
-
-/* Values for attributes. */
-
-enum
-{
- PTHREAD_CREATE_JOINABLE,
-#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE
- PTHREAD_CREATE_DETACHED
-#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED
-};
-
-enum
-{
- PTHREAD_INHERIT_SCHED,
-#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED
- PTHREAD_EXPLICIT_SCHED
-#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED
-};
-
-enum
-{
- PTHREAD_SCOPE_SYSTEM,
-#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM
- PTHREAD_SCOPE_PROCESS
-#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS
-};
-
-enum
-{
- PTHREAD_MUTEX_ADAPTIVE_NP,
- PTHREAD_MUTEX_RECURSIVE_NP,
- PTHREAD_MUTEX_ERRORCHECK_NP,
- PTHREAD_MUTEX_TIMED_NP
-#ifdef __USE_UNIX98
- ,
- PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_ADAPTIVE_NP,
- PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
- PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
- PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
-#endif
-#ifdef __USE_GNU
- /* For compatibility. */
- , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_ADAPTIVE_NP
-#endif
-};
-
-enum
-{
- PTHREAD_PROCESS_PRIVATE,
-#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE
- PTHREAD_PROCESS_SHARED
-#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED
-};
-
-#if defined __USE_UNIX98 || defined __USE_XOPEN2K
-enum
-{
- PTHREAD_RWLOCK_PREFER_READER_NP,
- PTHREAD_RWLOCK_PREFER_WRITER_NP,
- PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
- PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_WRITER_NP
-};
-#endif /* Unix98 */
-
-#define PTHREAD_ONCE_INIT 0
-
-/* Special constants */
-
-#ifdef __USE_XOPEN2K
-/* -1 is distinct from 0 and all errno constants */
-# define PTHREAD_BARRIER_SERIAL_THREAD -1
-#endif
-
-/* Cleanup buffers */
-
-struct _pthread_cleanup_buffer
-{
- void (*__routine) (void *); /* Function to call. */
- void *__arg; /* Its argument. */
- int __canceltype; /* Saved cancellation type. */
- struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */
-};
-
-/* Cancellation */
-
-enum
-{
- PTHREAD_CANCEL_ENABLE,
-#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE
- PTHREAD_CANCEL_DISABLE
-#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE
-};
-enum
-{
- PTHREAD_CANCEL_DEFERRED,
-#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED
- PTHREAD_CANCEL_ASYNCHRONOUS
-#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS
-};
-#define PTHREAD_CANCELED ((void *) -1)
-
-
-/* Function for handling threads. */
-
-/* Create a thread with given attributes ATTR (or default attributes
- if ATTR is NULL), and call function START_ROUTINE with given
- arguments ARG. */
-extern int pthread_create (pthread_t *__restrict __threadp,
- __const pthread_attr_t *__restrict __attr,
- void *(*__start_routine) (void *),
- void *__restrict __arg) __THROW;
-
-/* Obtain the identifier of the current thread. */
-extern pthread_t pthread_self (void) __THROW;
-
-/* Compare two thread identifiers. */
-extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW;
-
-/* Terminate calling thread. */
-extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__));
-
-/* Make calling thread wait for termination of the thread TH. The
- exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN
- is not NULL. */
-extern int pthread_join (pthread_t __th, void **__thread_return);
-
-/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN.
- The resources of TH will therefore be freed immediately when it
- terminates, instead of waiting for another thread to perform PTHREAD_JOIN
- on it. */
-extern int pthread_detach (pthread_t __th) __THROW;
-
-
-/* Functions for handling attributes. */
-
-/* Initialize thread attribute *ATTR with default attributes
- (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER,
- no user-provided stack). */
-extern int pthread_attr_init (pthread_attr_t *__attr) __THROW;
-
-/* Destroy thread attribute *ATTR. */
-extern int pthread_attr_destroy (pthread_attr_t *__attr) __THROW;
-
-/* Set the `detachstate' attribute in *ATTR according to DETACHSTATE. */
-extern int pthread_attr_setdetachstate (pthread_attr_t *__attr,
- int __detachstate) __THROW;
-
-/* Return in *DETACHSTATE the `detachstate' attribute in *ATTR. */
-extern int pthread_attr_getdetachstate (__const pthread_attr_t *__attr,
- int *__detachstate) __THROW;
-
-/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */
-extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr,
- __const struct sched_param *__restrict
- __param) __THROW;
-
-/* Return in *PARAM the scheduling parameters of *ATTR. */
-extern int pthread_attr_getschedparam (__const pthread_attr_t *__restrict
- __attr,
- struct sched_param *__restrict __param)
- __THROW;
-
-/* Set scheduling policy in *ATTR according to POLICY. */
-extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy)
- __THROW;
-
-/* Return in *POLICY the scheduling policy of *ATTR. */
-extern int pthread_attr_getschedpolicy (__const pthread_attr_t *__restrict
- __attr, int *__restrict __policy)
- __THROW;
-
-/* Set scheduling inheritance mode in *ATTR according to INHERIT. */
-extern int pthread_attr_setinheritsched (pthread_attr_t *__attr,
- int __inherit) __THROW;
-
-/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */
-extern int pthread_attr_getinheritsched (__const pthread_attr_t *__restrict
- __attr, int *__restrict __inherit)
- __THROW;
-
-/* Set scheduling contention scope in *ATTR according to SCOPE. */
-extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope)
- __THROW;
-
-/* Return in *SCOPE the scheduling contention scope of *ATTR. */
-extern int pthread_attr_getscope (__const pthread_attr_t *__restrict __attr,
- int *__restrict __scope) __THROW;
-
-#ifdef __USE_UNIX98
-/* Set the size of the guard area at the bottom of the thread. */
-extern int pthread_attr_setguardsize (pthread_attr_t *__attr,
- size_t __guardsize) __THROW;
-
-/* Get the size of the guard area at the bottom of the thread. */
-extern int pthread_attr_getguardsize (__const pthread_attr_t *__restrict
- __attr, size_t *__restrict __guardsize)
- __THROW;
-#endif
-
-/* Set the starting address of the stack of the thread to be created.
- Depending on whether the stack grows up or down the value must either
- be higher or lower than all the address in the memory block. The
- minimal size of the block must be PTHREAD_STACK_SIZE. */
-extern int pthread_attr_setstackaddr (pthread_attr_t *__attr,
- void *__stackaddr) __THROW;
-
-/* Return the previously set address for the stack. */
-extern int pthread_attr_getstackaddr (__const pthread_attr_t *__restrict
- __attr, void **__restrict __stackaddr)
- __THROW;
-
-#ifdef __USE_XOPEN2K
-/* The following two interfaces are intended to replace the last two. They
- require setting the address as well as the size since only setting the
- address will make the implementation on some architectures impossible. */
-extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr,
- size_t __stacksize) __THROW;
-
-/* Return the previously set address for the stack. */
-extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr,
- void **__restrict __stackaddr,
- size_t *__restrict __stacksize) __THROW;
-#endif
-
-/* Add information about the minimum stack size needed for the thread
- to be started. This size must never be less than PTHREAD_STACK_SIZE
- and must also not exceed the system limits. */
-extern int pthread_attr_setstacksize (pthread_attr_t *__attr,
- size_t __stacksize) __THROW;
-
-/* Return the currently used minimal stack size. */
-extern int pthread_attr_getstacksize (__const pthread_attr_t *__restrict
- __attr, size_t *__restrict __stacksize)
- __THROW;
-
-#if 0
-/* Not yet implemented in uClibc! */
-
-#ifdef __USE_GNU
-/* Initialize thread attribute *ATTR with attributes corresponding to the
- already running thread TH. It shall be called on unitialized ATTR
- and destroyed with pthread_attr_destroy when no longer needed. */
-extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW;
-#endif
-#endif
-
-/* Functions for scheduling control. */
-
-/* Set the scheduling parameters for TARGET_THREAD according to POLICY
- and *PARAM. */
-extern int pthread_setschedparam (pthread_t __target_thread, int __policy,
- __const struct sched_param *__param)
- __THROW;
-
-/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */
-extern int pthread_getschedparam (pthread_t __target_thread,
- int *__restrict __policy,
- struct sched_param *__restrict __param)
- __THROW;
-
-#ifdef __USE_UNIX98
-/* Determine level of concurrency. */
-extern int pthread_getconcurrency (void) __THROW;
-
-/* Set new concurrency level to LEVEL. */
-extern int pthread_setconcurrency (int __level) __THROW;
-#endif
-
-#if 0
-/* Not yet implemented in uClibc! */
-
-#ifdef __USE_GNU
-/* Yield the processor to another thread or process.
- This function is similar to the POSIX `sched_yield' function but
- might be differently implemented in the case of a m-on-n thread
- implementation. */
-extern int pthread_yield (void) __THROW;
-#endif
-#endif
-
-/* Functions for mutex handling. */
-
-/* Initialize MUTEX using attributes in *MUTEX_ATTR, or use the
- default values if later is NULL. */
-extern int pthread_mutex_init (pthread_mutex_t *__restrict __mutex,
- __const pthread_mutexattr_t *__restrict
- __mutex_attr) __THROW;
-
-/* Destroy MUTEX. */
-extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW;
-
-/* Try to lock MUTEX. */
-extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) __THROW;
-
-/* Wait until lock for MUTEX becomes available and lock it. */
-extern int pthread_mutex_lock (pthread_mutex_t *__mutex) __THROW;
-
-#ifdef __USE_XOPEN2K
-/* Wait until lock becomes available, or specified time passes. */
-extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
- __const struct timespec *__restrict
- __abstime) __THROW;
-#endif
-
-/* Unlock MUTEX. */
-extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW;
-
-
-/* Functions for handling mutex attributes. */
-
-/* Initialize mutex attribute object ATTR with default attributes
- (kind is PTHREAD_MUTEX_TIMED_NP). */
-extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) __THROW;
-
-/* Destroy mutex attribute object ATTR. */
-extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) __THROW;
-
-/* Get the process-shared flag of the mutex attribute ATTR. */
-extern int pthread_mutexattr_getpshared (__const pthread_mutexattr_t *
- __restrict __attr,
- int *__restrict __pshared) __THROW;
-
-/* Set the process-shared flag of the mutex attribute ATTR. */
-extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr,
- int __pshared) __THROW;
-
-#ifdef __USE_UNIX98
-/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
- PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
- PTHREAD_MUTEX_DEFAULT). */
-extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
- __THROW;
-
-/* Return in *KIND the mutex kind attribute in *ATTR. */
-extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict
- __attr, int *__restrict __kind) __THROW;
-#endif
-
-
-/* Functions for handling conditional variables. */
-
-/* Initialize condition variable COND using attributes ATTR, or use
- the default values if later is NULL. */
-extern int pthread_cond_init (pthread_cond_t *__restrict __cond,
- __const pthread_condattr_t *__restrict
- __cond_attr) __THROW;
-
-/* Destroy condition variable COND. */
-extern int pthread_cond_destroy (pthread_cond_t *__cond) __THROW;
-
-/* Wake up one thread waiting for condition variable COND. */
-extern int pthread_cond_signal (pthread_cond_t *__cond) __THROW;
-
-/* Wake up all threads waiting for condition variables COND. */
-extern int pthread_cond_broadcast (pthread_cond_t *__cond) __THROW;
-
-/* Wait for condition variable COND to be signaled or broadcast.
- MUTEX is assumed to be locked before. */
-extern int pthread_cond_wait (pthread_cond_t *__restrict __cond,
- pthread_mutex_t *__restrict __mutex);
-
-/* Wait for condition variable COND to be signaled or broadcast until
- ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an
- absolute time specification; zero is the beginning of the epoch
- (00:00:00 GMT, January 1, 1970). */
-extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
- pthread_mutex_t *__restrict __mutex,
- __const struct timespec *__restrict
- __abstime);
-
-/* Functions for handling condition variable attributes. */
-
-/* Initialize condition variable attribute ATTR. */
-extern int pthread_condattr_init (pthread_condattr_t *__attr) __THROW;
-
-/* Destroy condition variable attribute ATTR. */
-extern int pthread_condattr_destroy (pthread_condattr_t *__attr) __THROW;
-
-/* Get the process-shared flag of the condition variable attribute ATTR. */
-extern int pthread_condattr_getpshared (__const pthread_condattr_t *
- __restrict __attr,
- int *__restrict __pshared) __THROW;
-
-/* Set the process-shared flag of the condition variable attribute ATTR. */
-extern int pthread_condattr_setpshared (pthread_condattr_t *__attr,
- int __pshared) __THROW;
-
-
-#if defined __USE_UNIX98 || defined __USE_XOPEN2K
-/* Functions for handling read-write locks. */
-
-/* Initialize read-write lock RWLOCK using attributes ATTR, or use
- the default values if later is NULL. */
-extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock,
- __const pthread_rwlockattr_t *__restrict
- __attr) __THROW;
-
-/* Destroy read-write lock RWLOCK. */
-extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) __THROW;
-
-/* Acquire read lock for RWLOCK. */
-extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) __THROW;
-
-/* Try to acquire read lock for RWLOCK. */
-extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) __THROW;
-
-# ifdef __USE_XOPEN2K
-/* Try to acquire read lock for RWLOCK or return after specfied time. */
-extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
- __const struct timespec *__restrict
- __abstime) __THROW;
-# endif
-
-/* Acquire write lock for RWLOCK. */
-extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) __THROW;
-
-/* Try to acquire write lock for RWLOCK. */
-extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) __THROW;
-
-# ifdef __USE_XOPEN2K
-/* Try to acquire write lock for RWLOCK or return after specfied time. */
-extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
- __const struct timespec *__restrict
- __abstime) __THROW;
-# endif
-
-/* Unlock RWLOCK. */
-extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) __THROW;
-
-
-/* Functions for handling read-write lock attributes. */
-
-/* Initialize attribute object ATTR with default values. */
-extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) __THROW;
-
-/* Destroy attribute object ATTR. */
-extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) __THROW;
-
-/* Return current setting of process-shared attribute of ATTR in PSHARED. */
-extern int pthread_rwlockattr_getpshared (__const pthread_rwlockattr_t *
- __restrict __attr,
- int *__restrict __pshared) __THROW;
-
-/* Set process-shared attribute of ATTR to PSHARED. */
-extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr,
- int __pshared) __THROW;
-
-/* Return current setting of reader/writer preference. */
-extern int pthread_rwlockattr_getkind_np (__const pthread_rwlockattr_t *__attr,
- int *__pref) __THROW;
-
-/* Set reader/write preference. */
-extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr,
- int __pref) __THROW;
-#endif
-
-#if 0
-/* Not yet implemented in uClibc! */
-
-#ifdef __USE_XOPEN2K
-/* The IEEE Std. 1003.1j-2000 introduces functions to implement
- spinlocks. */
-
-/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can
- be shared between different processes. */
-extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared)
- __THROW;
-
-/* Destroy the spinlock LOCK. */
-extern int pthread_spin_destroy (pthread_spinlock_t *__lock) __THROW;
-
-/* Wait until spinlock LOCK is retrieved. */
-extern int pthread_spin_lock (pthread_spinlock_t *__lock) __THROW;
-
-/* Try to lock spinlock LOCK. */
-extern int pthread_spin_trylock (pthread_spinlock_t *__lock) __THROW;
-
-/* Release spinlock LOCK. */
-extern int pthread_spin_unlock (pthread_spinlock_t *__lock) __THROW;
-
-
-/* Barriers are a also a new feature in 1003.1j-2000. */
-
-extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier,
- __const pthread_barrierattr_t *__restrict
- __attr, unsigned int __count) __THROW;
-
-extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) __THROW;
-
-extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) __THROW;
-
-extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) __THROW;
-
-extern int pthread_barrierattr_getpshared (__const pthread_barrierattr_t *
- __restrict __attr,
- int *__restrict __pshared) __THROW;
-
-extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr,
- int __pshared) __THROW;
-
-extern int pthread_barrier_wait (pthread_barrier_t *__barrier) __THROW;
-#endif
-#endif
-
-
-/* Functions for handling thread-specific data. */
-
-/* Create a key value identifying a location in the thread-specific
- data area. Each thread maintains a distinct thread-specific data
- area. DESTR_FUNCTION, if non-NULL, is called with the value
- associated to that key when the key is destroyed.
- DESTR_FUNCTION is not called if the value associated is NULL when
- the key is destroyed. */
-extern int pthread_key_create (pthread_key_t *__key,
- void (*__destr_function) (void *)) __THROW;
-
-/* Destroy KEY. */
-extern int pthread_key_delete (pthread_key_t __key) __THROW;
-
-/* Store POINTER in the thread-specific data slot identified by KEY. */
-extern int pthread_setspecific (pthread_key_t __key,
- __const void *__pointer) __THROW;
-
-/* Return current value of the thread-specific data slot identified by KEY. */
-extern void *pthread_getspecific (pthread_key_t __key) __THROW;
-
-
-/* Functions for handling initialization. */
-
-/* Guarantee that the initialization function INIT_ROUTINE will be called
- only once, even if pthread_once is executed several times with the
- same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or
- extern variable initialized to PTHREAD_ONCE_INIT.
-
- The initialization functions might throw exception which is why
- this function is not marked with __THROW. */
-extern int pthread_once (pthread_once_t *__once_control,
- void (*__init_routine) (void));
-
-
-/* Functions for handling cancellation. */
-
-/* Set cancelability state of current thread to STATE, returning old
- state in *OLDSTATE if OLDSTATE is not NULL. */
-extern int pthread_setcancelstate (int __state, int *__oldstate);
-
-/* Set cancellation state of current thread to TYPE, returning the old
- type in *OLDTYPE if OLDTYPE is not NULL. */
-extern int pthread_setcanceltype (int __type, int *__oldtype);
-
-/* Cancel THREAD immediately or at the next possibility. */
-extern int pthread_cancel (pthread_t __cancelthread);
-
-/* Test for pending cancellation for the current thread and terminate
- the thread as per pthread_exit(PTHREAD_CANCELED) if it has been
- cancelled. */
-extern void pthread_testcancel (void);
-
-
-/* Install a cleanup handler: ROUTINE will be called with arguments ARG
- when the thread is cancelled or calls pthread_exit. ROUTINE will also
- be called with arguments ARG when the matching pthread_cleanup_pop
- is executed with non-zero EXECUTE argument.
- pthread_cleanup_push and pthread_cleanup_pop are macros and must always
- be used in matching pairs at the same nesting level of braces. */
-
-#define pthread_cleanup_push(routine,arg) \
- { struct _pthread_cleanup_buffer _buffer; \
- _pthread_cleanup_push (&_buffer, (routine), (arg));
-
-extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
- void (*__routine) (void *),
- void *__arg) __THROW;
-
-/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
- If EXECUTE is non-zero, the handler function is called. */
-
-#define pthread_cleanup_pop(execute) \
- _pthread_cleanup_pop (&_buffer, (execute)); }
-
-extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
- int __execute) __THROW;
-
-/* Install a cleanup handler as pthread_cleanup_push does, but also
- saves the current cancellation type and set it to deferred cancellation. */
-
-#ifdef __USE_GNU
-# define pthread_cleanup_push_defer_np(routine,arg) \
- { struct _pthread_cleanup_buffer _buffer; \
- _pthread_cleanup_push_defer (&_buffer, (routine), (arg));
-
-extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
- void (*__routine) (void *),
- void *__arg) __THROW;
-
-/* Remove a cleanup handler as pthread_cleanup_pop does, but also
- restores the cancellation type that was in effect when the matching
- pthread_cleanup_push_defer was called. */
-
-# define pthread_cleanup_pop_restore_np(execute) \
- _pthread_cleanup_pop_restore (&_buffer, (execute)); }
-
-extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
- int __execute) __THROW;
-#endif
-
-
-#if 0
-/* Not yet implemented in uClibc! */
-
-#ifdef __USE_XOPEN2K
-/* Get ID of CPU-time clock for thread THREAD_ID. */
-extern int pthread_getcpuclockid (pthread_t __thread_id,
- clockid_t *__clock_id) __THROW;
-#endif
-#endif
-
-
-/* Functions for handling signals. */
-#include <bits/sigthread.h>
-
-
-/* Functions for handling process creation and process execution. */
-
-/* Install handlers to be called when a new process is created with FORK.
- The PREPARE handler is called in the parent process just before performing
- FORK. The PARENT handler is called in the parent process just after FORK.
- The CHILD handler is called in the child process. Each of the three
- handlers can be NULL, meaning that no handler needs to be called at that
- point.
- PTHREAD_ATFORK can be called several times, in which case the PREPARE
- handlers are called in LIFO order (last added with PTHREAD_ATFORK,
- first called before FORK), and the PARENT and CHILD handlers are called
- in FIFO (first added, first called). */
-
-extern int pthread_atfork (void (*__prepare) (void),
- void (*__parent) (void),
- void (*__child) (void)) __THROW;
-
-/* Terminate all threads in the program except the calling process.
- Should be called just before invoking one of the exec*() functions. */
-
-extern void pthread_kill_other_threads_np (void) __THROW;
-
-__END_DECLS
-
-#endif /* pthread.h */
diff --git a/libpthread/linuxthreads/sysdeps/pthread/tls.h b/libpthread/linuxthreads/sysdeps/pthread/tls.h
deleted file mode 100644
index 6a23ec05e..000000000
--- a/libpthread/linuxthreads/sysdeps/pthread/tls.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Definition for thread-local data handling. 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 Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-/* By default no TLS support is available. This is signaled by the
- absence of the symbol USE_TLS. */
-#undef USE_TLS
-
-
-/* An architecture-specific version of this file has to defined a
- number of symbols:
-
- TLS_TCB_AT_TP or TLS_DTV_AT_TP
-
- The presence of one of these symbols signals which variant of
- the TLS ABI is used. There are in the moment two variants
- available:
-
- * the thread pointer points to a thread control block
-
- * the thread pointer points to the dynamic thread vector
-
-
- TLS_TCB_SIZE
-
- This is the size of the thread control block structure. How
- this is actually defined depends on the ABI. The thread control
- block could be internal descriptor of the thread library or
- just a data structure which allows finding the DTV.
-
- TLS_INIT_TCB_SIZE
-
- Similarly, but this value is only used at startup and in the
- dynamic linker itself. There are no threads in use at that time.
-
-
- TLS_TCB_ALIGN
-
- Alignment requirements for the TCB structure.
-
- TLS_INIT_TCB_ALIGN
-
- Similarly, but for the structure used at startup time.
-
-
- INSTALL_DTV(tcb, init_dtv)
-
- This macro must install the given initial DTV into the thread control
- block TCB. The normal runtime functionality must then be able to
- use the value.
-
-
- TLS_INIT_TP(tcb, firstcall)
-
- This macro must initialize the thread pointer to enable normal TLS
- operation. The first parameter is a pointer to the thread control
- block. The second parameter specifies whether this is the first
- call for the TCB. ld.so calls this macro more than once.
-
-
- THREAD_DTV()
-
- This macro returns the address of the DTV of the current thread.
- This normally is done using the the thread register which points
- to the dtv or the TCB (from which the DTV can found).
- */
diff --git a/libpthread/linuxthreads/sysdeps/sh/pt-machine.h b/libpthread/linuxthreads/sysdeps/sh/pt-machine.h
deleted file mode 100644
index 02545e6b4..000000000
--- a/libpthread/linuxthreads/sysdeps/sh/pt-machine.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- SuperH version.
- Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Niibe Yutaka <gniibe@m17n.org>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; 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_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef __ASSEMBLER__
-#ifndef PT_EI
-# define PT_EI extern inline __attribute__ ((always_inline))
-#endif
-
-extern long int testandset (int *spinlock);
-extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-
-/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
-{
- int ret;
-
- __asm__ __volatile__(
- "tas.b @%1\n\t"
- "movt %0"
- : "=r" (ret)
- : "r" (spinlock)
- : "memory", "cc");
-
- return (ret == 0);
-}
-
-/* We want the OS to assign stack addresses. */
-#define FLOATING_STACKS 1
-
-/* Maximum size of the stack if the rlimit is unlimited. */
-#define ARCH_STACK_MAX_SIZE 32*1024*1024
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME stack_pointer
-register char * stack_pointer __asm__ ("r15");
-
-/* Return the thread descriptor for the current thread. */
-struct _pthread_descr_struct;
-#define THREAD_SELF \
- ({ struct _pthread_descr_struct *self; \
- __asm__("stc gbr,%0" : "=r" (self)); self;})
-
-/* Initialize the thread-unique value. */
-#define INIT_THREAD_SELF(descr, nr) \
- ({ __asm__ __volatile__("ldc %0,gbr" : : "r" (descr));})
-
-/* Access to data in the thread descriptor is easy. */
-#define THREAD_GETMEM(descr, member) \
- ((void) sizeof (descr), THREAD_SELF->member)
-#define THREAD_GETMEM_NC(descr, member) \
- ((void) sizeof (descr), THREAD_SELF->member)
-#define THREAD_SETMEM(descr, member, value) \
- ((void) sizeof (descr), THREAD_SELF->member = (value))
-#define THREAD_SETMEM_NC(descr, member, value) \
- ((void) sizeof (descr), THREAD_SELF->member = (value))
-#endif /* __ASSEMBLER__ */
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/sh/tls.h b/libpthread/linuxthreads/sysdeps/sh/tls.h
deleted file mode 100644
index 75326d8e1..000000000
--- a/libpthread/linuxthreads/sysdeps/sh/tls.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Definition for thread-local data handling. linuxthreads/SH version.
- Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifndef _TLS_H
-#define _TLS_H
-
-# include <pt-machine.h>
-
-#ifndef __ASSEMBLER__
-# include <stdbool.h>
-# include <stddef.h>
-# include <stdint.h>
-
-/* Type for the dtv. */
-typedef union dtv
-{
- size_t counter;
- void *pointer;
-} dtv_t;
-
-
-typedef struct
-{
- void *tcb; /* Pointer to the TCB. Not necessary the
- thread descriptor used by libpthread. */
- dtv_t *dtv;
- void *self; /* Pointer to the thread descriptor. */
-} tcbhead_t;
-
-
-/* We can support TLS only if the floating-stack support is available. */
-#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT
-
-/* Get system call information. */
-# include <sysdep.h>
-
-/* Signal that TLS support is available. */
-//# define USE_TLS 1
-
-
-/* Get the thread descriptor definition. */
-# include <linuxthreads/descr.h>
-
-/* This is the size of the initial TCB. */
-# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
-
-/* This is the size of the TCB. */
-# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
-
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
-
-/* The TLS blocks start right after the TCB. */
-# define TLS_DTV_AT_TP 1
-
-
-/* Install the dtv pointer. The pointer passed is to the element with
- index -1 which contain the length. */
-# define INSTALL_DTV(descr, dtvp) \
- ((tcbhead_t *) (descr))->dtv = dtvp + 1
-
-/* Install new dtv for current thread. */
-# define INSTALL_NEW_DTV(dtv) \
- ({ struct _pthread_descr_struct *__descr; \
- THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); })
-
-/* Return dtv of given thread descriptor. */
-# define GET_DTV(descr) \
- (((tcbhead_t *) (descr))->dtv)
-
-/* Code to initially initialize the thread pointer. This might need
- special attention since 'errno' is not yet available and if the
- operation can cause a failure 'errno' must not be touched. */
-# define TLS_INIT_TP(descr, secondcall) \
- ({ \
- void *_descr = (descr); \
- int result; \
- tcbhead_t *head = _descr; \
- \
- head->tcb = _descr; \
- /* For now the thread descriptor is at the same address. */ \
- head->self = _descr; \
- \
- asm ("ldc %0,gbr" : : "r" (_descr)); \
- \
- 0; \
- })
-
-
-/* Return the address of the dtv for the current thread. */
-# define THREAD_DTV() \
- ({ struct _pthread_descr_struct *__descr; \
- THREAD_GETMEM (__descr, p_header.data.dtvp); })
-
-#endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */
-#endif /* __ASSEMBLER__ */
-
-#endif /* tls.h */
diff --git a/libpthread/linuxthreads/sysdeps/sh64/Makefile.arch b/libpthread/linuxthreads/sysdeps/sh64/Makefile.arch
deleted file mode 100644
index 38cd12db6..000000000
--- a/libpthread/linuxthreads/sysdeps/sh64/Makefile.arch
+++ /dev/null
@@ -1,26 +0,0 @@
-# Makefile for uClibc
-#
-# Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
-# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
-#
-# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
-#
-
-# We need to build as SHcompact for tas..
-ARCH_CFLAGS:=$(subst 32media,compact,$(ARCH_CFLAGS))
-
-libpthread_ARCH_DIR:=$(top_srcdir)libpthread/linuxthreads/sysdeps/sh64
-libpthread_ARCH_OUT:=$(top_builddir)libpthread/linuxthreads/sysdeps/sh64
-
-libpthread_ARCH_SRC:=$(wildcard $(libpthread_ARCH_DIR)/*.c)
-libpthread_ARCH_OBJ:=$(patsubst $(libpthread_ARCH_DIR)/%.c,$(libpthread_ARCH_OUT)/%.o,$(libpthread_ARCH_SRC))
-
-libpthread-a-$(UCLIBC_HAS_THREADS)+=$(libpthread_ARCH_OBJ)
-libpthread-so-$(UCLIBC_HAS_THREADS)+=$(libpthread_ARCH_OBJ:.o=.os)
-
-libpthread-multi-$(UCLIBC_HAS_THREADS)+=$(libpthread_ARCH_SRC)
-
-objclean-y+=libpthread_arch_objclean
-
-libpthread_arch_objclean:
- $(RM) $(libpthread_ARCH_OUT)/*.{o,os}
diff --git a/libpthread/linuxthreads/sysdeps/sh64/pt-machine.c b/libpthread/linuxthreads/sysdeps/sh64/pt-machine.c
deleted file mode 100644
index ea4881322..000000000
--- a/libpthread/linuxthreads/sysdeps/sh64/pt-machine.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Cloned for uClibc by Paul Mundt, December 2003 */
-/* Modified by SuperH, Inc. September 2003 */
-
-/* Machine-dependent pthreads configuration and inline functions.
- SH5 version.
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Niibe Yutaka <gniibe@m17n.org>.
-
- 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-machine.h"
-
-/* Spinlock implementation; required. */
-
-/* The SH5 does not have a suitable test-and-set instruction (SWAP only
- operates on an aligned quad word). So we use the SH4 version instead.
- This must be seperately compiled in SHcompact mode, so it cannot be
- inline. */
-
-long int testandset (int *spinlock)
-{
- int ret;
-
- __asm__ __volatile__(
- "tas.b @%1\n\t"
- "movt %0"
- : "=r" (ret)
- : "r" (spinlock)
- : "memory", "cc");
-
- return (ret == 0);
-}
-
diff --git a/libpthread/linuxthreads/sysdeps/sh64/pt-machine.h b/libpthread/linuxthreads/sysdeps/sh64/pt-machine.h
deleted file mode 100644
index 8269a4cb3..000000000
--- a/libpthread/linuxthreads/sysdeps/sh64/pt-machine.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Cloned for uClibc by Paul Mundt, December 2003 */
-/* Modified by SuperH, Inc. September 2003 */
-
-/* Machine-dependent pthreads configuration and inline functions.
- SuperH version.
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Niibe Yutaka <gniibe@m17n.org>.
-
- 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_EI
-# define PT_EI extern inline
-#endif
-
-/* Spinlock implementation; required. */
-extern long int testandset (int *spinlock);
-
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME stack_pointer
-register char * stack_pointer __asm__ ("r15");
diff --git a/libpthread/linuxthreads/sysdeps/sparc/pt-machine.h b/libpthread/linuxthreads/sysdeps/sparc/pt-machine.h
deleted file mode 100644
index ab90810f1..000000000
--- a/libpthread/linuxthreads/sysdeps/sparc/pt-machine.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <features.h>
-#include <bits/wordsize.h>
-
-#if __WORDSIZE == 32
-# include "sparc32/pt-machine.h"
-#else
-# include "sparc64/pt-machine.h"
-#endif
diff --git a/libpthread/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h b/libpthread/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h
deleted file mode 100644
index 322a52051..000000000
--- a/libpthread/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- sparc version.
- Copyright (C) 1996-1998, 2000-2003 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson <rth@tamu.edu>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#ifndef _PT_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef PT_EI
-# define PT_EI extern inline __attribute__ ((always_inline))
-#endif
-
-extern long int testandset (int *spinlock);
-extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-
-/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
-{
- int ret;
-
- __asm__ __volatile__("ldstub %1,%0"
- : "=r"(ret), "=m"(*spinlock)
- : "m"(*spinlock));
-
- return ret;
-}
-
-
-/* Memory barrier; default is to do nothing */
-#define MEMORY_BARRIER() __asm__ __volatile__("stbar" : : : "memory")
-
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME (stack_pointer + (2 * 64))
-register char *stack_pointer __asm__("%sp");
-
-
-/* Registers %g6 and %g7 are reserved by the ABI for "system use".
- %g7 is specified in the TLS ABI as thread pointer -- we do the same. */
-struct _pthread_descr_struct;
-register struct _pthread_descr_struct *__thread_self __asm__("%g7");
-
-/* Return the thread descriptor for the current thread. */
-#define THREAD_SELF __thread_self
-
-/* Initialize the thread-unique value. */
-#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr))
-
-/* Access to data in the thread descriptor is easy. */
-#define THREAD_GETMEM(descr, member) \
- ((void) sizeof (descr), THREAD_SELF->member)
-#define THREAD_GETMEM_NC(descr, member) \
- ((void) sizeof (descr), THREAD_SELF->member)
-#define THREAD_SETMEM(descr, member, value) \
- ((void) sizeof (descr), THREAD_SELF->member = (value))
-#define THREAD_SETMEM_NC(descr, member, value) \
- ((void) sizeof (descr), THREAD_SELF->member = (value))
-
-/* We want the OS to assign stack addresses. */
-#define FLOATING_STACKS 1
-
-/* Maximum size of the stack if the rlimit is unlimited. */
-#define ARCH_STACK_MAX_SIZE 8*1024*1024
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h b/libpthread/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h
deleted file mode 100644
index f65c13be1..000000000
--- a/libpthread/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- Sparc v9 version.
- Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson <rth@tamu.edu>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#ifndef _PT_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef PT_EI
-# define PT_EI extern inline __attribute__ ((always_inline))
-#endif
-
-extern long int testandset (int *spinlock);
-extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-
-/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
-{
- int ret;
-
- __asm__ __volatile__("ldstub %1,%0"
- : "=r" (ret), "=m" (*spinlock) : "m" (*spinlock));
-
- return ret;
-}
-
-
-/* Memory barrier; default is to do nothing */
-#define MEMORY_BARRIER() \
- __asm__ __volatile__("membar #LoadLoad | #LoadStore | #StoreLoad | #StoreStore" : : : "memory")
-/* Read barrier. */
-#define READ_MEMORY_BARRIER() \
- __asm__ __volatile__("membar #LoadLoad | #LoadStore" : : : "memory")
-/* Write barrier. */
-#define WRITE_MEMORY_BARRIER() \
- __asm__ __volatile__("membar #StoreLoad | #StoreStore" : : : "memory")
-
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME (stack_pointer + (2 * 128))
-register char *stack_pointer __asm__ ("%sp");
-
-
-/* Registers %g6 and %g7 are reserved by the ABI for "system use". The
- TLS ABI specifies %g7 as the thread pointer. */
-struct _pthread_descr_struct;
-register struct _pthread_descr_struct *__thread_self __asm__ ("%g7");
-
-/* Return the thread descriptor for the current thread. */
-#define THREAD_SELF __thread_self
-
-/* Initialize the thread-unique value. */
-#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr))
-
-
-/* Compare-and-swap for semaphores. */
-
-#define HAS_COMPARE_AND_SWAP
-PT_EI int
-__compare_and_swap (long int *p, long int oldval, long int newval)
-{
- long int readval;
-
- __asm__ __volatile__ ("casx [%4], %2, %0"
- : "=r"(readval), "=m"(*p)
- : "r"(oldval), "m"(*p), "r"(p), "0"(newval));
- MEMORY_BARRIER();
- return readval == oldval;
-}
-
-/* Access to data in the thread descriptor is easy. */
-#define THREAD_GETMEM(descr, member) \
- ((void) sizeof (descr), THREAD_SELF->member)
-#define THREAD_GETMEM_NC(descr, member) \
- ((void) sizeof (descr), THREAD_SELF->member)
-#define THREAD_SETMEM(descr, member, value) \
- ((void) sizeof (descr), THREAD_SELF->member = (value))
-#define THREAD_SETMEM_NC(descr, member, value) \
- ((void) sizeof (descr), THREAD_SELF->member = (value))
-
-/* We want the OS to assign stack addresses. */
-#define FLOATING_STACKS 1
-
-/* Maximum size of the stack if the rlimit is unlimited. */
-#define ARCH_STACK_MAX_SIZE 32*1024*1024
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/v850/pt-machine.h b/libpthread/linuxthreads/sysdeps/v850/pt-machine.h
deleted file mode 100644
index fb41c41e9..000000000
--- a/libpthread/linuxthreads/sysdeps/v850/pt-machine.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * sysdeps/v850/pt-machine.h -- v850-specific pthread definitions
- *
- * Copyright (C) 2002 NEC Electronics Corporation
- * Copyright (C) 2002 Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU Lesser
- * General Public License. See the file COPYING.LIB in the main
- * directory of this archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef PT_EI
-# define PT_EI extern inline
-#endif
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#define CURRENT_STACK_FRAME __stack_pointer
-register char *__stack_pointer __asm__ ("sp");
-
-#define HAS_COMPARE_AND_SWAP
-
-/* Atomically: If *PTR == OLD, set *PTR to NEW and return true,
- otherwise do nothing and return false. */
-PT_EI int
-__compare_and_swap (long *ptr, long old, long new)
-{
- unsigned long psw;
-
- /* disable interrupts */
- __asm__ __volatile__ ("stsr psw, %0; di" : "=&r" (psw));
-
- if (likely (*ptr == old))
- {
- *ptr = new;
- __asm__ __volatile__ ("ldsr %0, psw" :: "r" (psw)); /* re-enable */
- return 1;
- }
- else
- {
- __asm__ __volatile__ ("ldsr %0, psw" :: "r" (psw)); /* re-enable */
- return 0;
- }
-}
diff --git a/libpthread/linuxthreads/sysdeps/x86_64/pt-machine.h b/libpthread/linuxthreads/sysdeps/x86_64/pt-machine.h
deleted file mode 100644
index 8a2d1a762..000000000
--- a/libpthread/linuxthreads/sysdeps/x86_64/pt-machine.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Machine-dependent pthreads configuration and inline functions.
- x86-64 version.
- Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifndef _PT_MACHINE_H
-#define _PT_MACHINE_H 1
-
-#ifndef __ASSEMBLER__
-# include <stddef.h> /* For offsetof. */
-# include <stdlib.h> /* For abort(). */
-# include <asm/prctl.h>
-
-
-# ifndef PT_EI
-# define PT_EI extern inline __attribute__ ((always_inline))
-# endif
-
-extern long int testandset (int *spinlock);
-extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-# define CURRENT_STACK_FRAME stack_pointer
-register char * stack_pointer __asm__ ("%rsp") __attribute_used__;
-
-
-/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
-{
- long int ret;
-
- __asm__ __volatile__ (
- "xchgl %k0, %1"
- : "=r"(ret), "=m"(*spinlock)
- : "0"(1), "m"(*spinlock)
- : "memory");
-
- return ret;
-}
-
-
-/* Compare-and-swap for semaphores. */
-# define HAS_COMPARE_AND_SWAP
-
-PT_EI int
-__compare_and_swap (long int *p, long int oldval, long int newval)
-{
- char ret;
- long int readval;
-
- __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0"
- : "=q" (ret), "=m" (*p), "=a" (readval)
- : "r" (newval), "m" (*p), "a" (oldval)
- : "memory");
- return ret;
-}
-
-#endif /* !__ASSEMBLER__ */
-
-/* We want the OS to assign stack addresses. */
-#define FLOATING_STACKS 1
-
-/* Maximum size of the stack if the rlimit is unlimited. */
-#define ARCH_STACK_MAX_SIZE 32*1024*1024
-
-/* The ia32e really want some help to prevent overheating. */
-#define BUSY_WAIT_NOP __asm__ ("rep; nop")
-
-#endif /* pt-machine.h */
diff --git a/libpthread/linuxthreads/sysdeps/x86_64/tls.h b/libpthread/linuxthreads/sysdeps/x86_64/tls.h
deleted file mode 100644
index d67275c10..000000000
--- a/libpthread/linuxthreads/sysdeps/x86_64/tls.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Definitions for thread-local data handling. linuxthreads/x86-64 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 Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifndef _TLS_H
-#define _TLS_H
-
-#ifndef __ASSEMBLER__
-
-# include <pt-machine.h>
-# include <stdbool.h>
-# include <stddef.h>
-
-/* Type for the dtv. */
-typedef union dtv
-{
- size_t counter;
- struct
- {
- void *val;
- bool is_static;
- } pointer;
-} dtv_t;
-
-
-typedef struct
-{
- void *tcb; /* Pointer to the TCB. Not necessary the
- thread descriptor used by libpthread. */
- dtv_t *dtv;
- void *self; /* Pointer to the thread descriptor. */
- int multiple_threads;
-} tcbhead_t;
-
-#else /* __ASSEMBLER__ */
-# include <tcb-offsets.h>
-#endif
-
-
-#ifdef HAVE_TLS_SUPPORT
-
-/* Signal that TLS support is available. */
-# define USE_TLS 1
-
-# ifndef __ASSEMBLER__
-/* Get system call information. */
-# include <sysdep.h>
-
-/* Get the thread descriptor definition. */
-# include <linuxthreads/descr.h>
-
-/* This is the size of the initial TCB. */
-# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
-
-/* This is the size of the TCB. */
-# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
-
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
-
-/* The TCB can have any size and the memory following the address the
- thread pointer points to is unspecified. Allocate the TCB there. */
-# define TLS_TCB_AT_TP 1
-
-
-/* Install the dtv pointer. The pointer passed is to the element with
- index -1 which contain the length. */
-# define INSTALL_DTV(descr, dtvp) \
- ((tcbhead_t *) (descr))->dtv = (dtvp) + 1
-
-/* Install new dtv for current thread. */
-# define INSTALL_NEW_DTV(dtv) \
- ({ struct _pthread_descr_struct *__descr; \
- THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); })
-
-/* Return dtv of given thread descriptor. */
-# define GET_DTV(descr) \
- (((tcbhead_t *) (descr))->dtv)
-
-/* Code to initially initialize the thread pointer. This might need
- special attention since 'errno' is not yet available and if the
- operation can cause a failure 'errno' must not be touched. */
-# define TLS_INIT_TP(descr, secondcall) \
- ({ \
- void *_descr = (descr); \
- tcbhead_t *head = _descr; \
- long int _result; \
- \
- head->tcb = _descr; \
- /* For now the thread descriptor is at the same address. */ \
- head->self = _descr; \
- \
- asm volatile ("syscall" \
- : "=a" (_result) \
- : "0" ((unsigned long int) __NR_arch_prctl), \
- "D" ((unsigned long int) ARCH_SET_FS), \
- "S" (_descr) \
- : "memory", "cc", "r11", "cx"); \
- \
- _result ? "cannot set %fs base address for thread-local storage" : 0; \
- })
-
-/* Indicate that dynamic linker shouldn't try to initialize TLS even
- when no PT_TLS segments are found in the program and libraries
- it is linked against. */
-# define TLS_INIT_TP_EXPENSIVE 1
-
-/* Return the address of the dtv for the current thread. */
-# define THREAD_DTV() \
- ({ struct _pthread_descr_struct *__descr; \
- THREAD_GETMEM (__descr, p_header.data.dtvp); })
-
-# endif /* HAVE_TLS_SUPPORT */
-#endif /* __ASSEMBLER__ */
-
-#endif /* tls.h */
diff --git a/libpthread/linuxthreads/wrapsyscall.c b/libpthread/linuxthreads/wrapsyscall.c
deleted file mode 100644
index 6b8a00bb5..000000000
--- a/libpthread/linuxthreads/wrapsyscall.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/* Wrapper arpund system calls to provide cancelation points.
- Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
-
- 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. */
-
-#define __FORCE_GLIBC
-#include <features.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <termios.h>
-#include <sys/resource.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/syscall.h>
-
-
-#ifndef __PIC__
-/* We need a hook to force this file to be linked in when static
- libpthread is used. */
-const int __pthread_provide_wrappers = 0;
-#endif
-
-
-#define CANCELABLE_SYSCALL(res_type, name, param_list, params) \
-res_type __libc_##name param_list; \
-res_type \
-__attribute__ ((weak)) \
-name param_list \
-{ \
- res_type result; \
- int oldtype; \
- pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \
- result = __libc_##name params; \
- pthread_setcanceltype (oldtype, NULL); \
- return result; \
-}
-
-#define CANCELABLE_SYSCALL_VA(res_type, name, param_list, params, last_arg) \
-res_type __libc_##name param_list; \
-res_type \
-__attribute__ ((weak)) \
-name param_list \
-{ \
- res_type result; \
- int oldtype; \
- va_list ap; \
- pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \
- va_start (ap, last_arg); \
- result = __libc_##name params; \
- va_end (ap); \
- pthread_setcanceltype (oldtype, NULL); \
- return result; \
-}
-
-
-/* close(2). */
-CANCELABLE_SYSCALL (int, close, (int fd), (fd))
-
-
-/* fcntl(2). */
-CANCELABLE_SYSCALL_VA (int, fcntl, (int fd, int cmd, ...),
- (fd, cmd, va_arg (ap, long int)), cmd)
-
-
-/* fsync(2). */
-CANCELABLE_SYSCALL (int, fsync, (int fd), (fd))
-
-
-/* lseek(2). */
-CANCELABLE_SYSCALL (off_t, lseek, (int fd, off_t offset, int whence),
- (fd, offset, whence))
-
-#ifdef __UCLIBC_HAS_LFS__
-/* lseek64(2). */
-CANCELABLE_SYSCALL (off64_t, lseek64, (int fd, off64_t offset, int whence),
- (fd, offset, whence))
-#endif
-
-/* msync(2). */
-CANCELABLE_SYSCALL (int, msync, (__ptr_t addr, size_t length, int flags),
- (addr, length, flags))
-
-
-/* nanosleep(2). */
-CANCELABLE_SYSCALL (int, nanosleep, (const struct timespec *requested_time,
- struct timespec *remaining),
- (requested_time, remaining))
-
-
-/* open(2). */
-CANCELABLE_SYSCALL_VA (int, open, (const char *pathname, int flags, ...),
- (pathname, flags, va_arg (ap, mode_t)), flags)
-
-
-#ifdef __UCLIBC_HAS_LFS__
-/* open64(3). */
-CANCELABLE_SYSCALL_VA (int, open64, (const char *pathname, int flags, ...),
- (pathname, flags, va_arg (ap, mode_t)), flags)
-#endif
-
-/* pause(2). */
-CANCELABLE_SYSCALL (int, pause, (void), ())
-
-
-/* Enable this if enabling these in syscalls.c */
-/* pread(3). */
-CANCELABLE_SYSCALL (ssize_t, pread, (int fd, void *buf, size_t count,
- off_t offset),
- (fd, buf, count, offset))
-
-
-#if defined __UCLIBC_HAS_LFS__ && defined __NR_pread64
-/* pread64(3). */
-CANCELABLE_SYSCALL (ssize_t, pread64, (int fd, void *buf, size_t count,
- off64_t offset),
- (fd, buf, count, offset))
-#endif
-
-/* pwrite(3). */
-CANCELABLE_SYSCALL (ssize_t, pwrite, (int fd, const void *buf, size_t n,
- off_t offset),
- (fd, buf, n, offset))
-
-
-#if defined __UCLIBC_HAS_LFS__ && defined __NR_pwrited64
-/* pwrite64(3). */
-CANCELABLE_SYSCALL (ssize_t, pwrite64, (int fd, const void *buf, size_t n,
- off64_t offset),
- (fd, buf, n, offset))
-#endif
-
-/* read(2). */
-CANCELABLE_SYSCALL (ssize_t, read, (int fd, void *buf, size_t count),
- (fd, buf, count))
-
-
-/* system(3). */
-CANCELABLE_SYSCALL (int, system, (const char *line), (line))
-
-
-/* tcdrain(2). */
-CANCELABLE_SYSCALL (int, tcdrain, (int fd), (fd))
-
-
-/* wait(2). */
-CANCELABLE_SYSCALL (__pid_t, wait, (__WAIT_STATUS_DEFN stat_loc), (stat_loc))
-
-
-/* waitpid(2). */
-CANCELABLE_SYSCALL (__pid_t, waitpid, (__pid_t pid, int *stat_loc,
- int options),
- (pid, stat_loc, options))
-
-
-/* write(2). */
-CANCELABLE_SYSCALL (ssize_t, write, (int fd, const void *buf, size_t n),
- (fd, buf, n))
-
-
-/* The following system calls are thread cancellation points specified
- in XNS. */
-
-/* accept(2). */
-CANCELABLE_SYSCALL (int, accept, (int fd, __SOCKADDR_ARG addr,
- socklen_t *addr_len),
- (fd, addr, addr_len))
-
-/* connect(2). */
-CANCELABLE_SYSCALL (int, connect, (int fd, __CONST_SOCKADDR_ARG addr,
- socklen_t len),
- (fd, addr, len))
-
-/* recv(2). */
-CANCELABLE_SYSCALL (ssize_t, recv, (int fd, __ptr_t buf, size_t n, int flags),
- (fd, buf, n, flags))
-
-/* recvfrom(2). */
-CANCELABLE_SYSCALL (ssize_t, recvfrom, (int fd, __ptr_t buf, size_t n, int flags,
- __SOCKADDR_ARG addr, socklen_t *addr_len),
- (fd, buf, n, flags, addr, addr_len))
-
-/* recvmsg(2). */
-CANCELABLE_SYSCALL (ssize_t, recvmsg, (int fd, struct msghdr *message, int flags),
- (fd, message, flags))
-
-/* send(2). */
-CANCELABLE_SYSCALL (ssize_t, send, (int fd, const __ptr_t buf, size_t n,
- int flags),
- (fd, buf, n, flags))
-
-/* sendmsg(2). */
-CANCELABLE_SYSCALL (ssize_t, sendmsg, (int fd, const struct msghdr *message,
- int flags),
- (fd, message, flags))
-
-/* sendto(2). */
-CANCELABLE_SYSCALL (ssize_t, sendto, (int fd, const __ptr_t buf, size_t n,
- int flags, __CONST_SOCKADDR_ARG addr,
- socklen_t addr_len),
- (fd, buf, n, flags, addr, addr_len))