diff options
| author | Ulrich Drepper <drepper@redhat.com> | 2004-12-22 20:10:10 +0000 |
|---|---|---|
| committer | Ulrich Drepper <drepper@redhat.com> | 2004-12-22 20:10:10 +0000 |
| commit | a334319f6530564d22e775935d9c91663623a1b4 (patch) | |
| tree | b5877475619e4c938e98757d518bb1e9cbead751 /linuxthreads/FAQ.html | |
| parent | 0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (diff) | |
| download | glibc-a334319f6530564d22e775935d9c91663623a1b4.tar.xz glibc-a334319f6530564d22e775935d9c91663623a1b4.zip | |
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
Diffstat (limited to 'linuxthreads/FAQ.html')
| -rw-r--r-- | linuxthreads/FAQ.html | 1039 |
1 files changed, 1039 insertions, 0 deletions
diff --git a/linuxthreads/FAQ.html b/linuxthreads/FAQ.html new file mode 100644 index 0000000000..21be33ec4c --- /dev/null +++ b/linuxthreads/FAQ.html @@ -0,0 +1,1039 @@ +<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, |
