diff options
Diffstat (limited to 'libpthread/linuxthreads')
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><pthread.h></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><pthread.h></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><stdio.h></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><errno.h></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><errno.h></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, ¶m); -  __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)) | 
