Pthreads: Difference between revisions

No edit summary
 
(3 intermediate revisions by the same user not shown)
Line 7: Line 7:
* The Triforce of POSIX Thread stacks:
* The Triforce of POSIX Thread stacks:
** If you aren't allocating a stack fit to your thread, you will one day smash that stack.
** If you aren't allocating a stack fit to your thread, you will one day smash that stack.
** If you're using your stack, you should probably heap-allocate or use TLS.
** If you're using your stack, you should probably heap-allocate or use [[TLS]].
** Recursion's all fun and games until your recurse on through to the other side.
** Recursion's all fun and games until your recurse on through to the other side.
** Yes, this all applies to an unthreaded program (especially an embedded one), with a critical difference -- memory management is process-based, causing noisy failures in the unthreaded case. Meanwhile, a POSIX thread will happily push a frame down right over his buddy's DTV/TLS in NPTL (see [http://www.redhat.com/whitepapers/developer/POSIX_Linux_Threading.pdf NPTL], "Memory Allocation"). Have a good time debugging that, champ!
** Yes, this all applies to an unthreaded program (especially an embedded one), with a critical difference -- memory management is process-based, causing noisy failures in the unthreaded case. Meanwhile, a POSIX thread will happily push a frame down right over his buddy's DTV/[[TLS]] in NPTL (see [http://www.redhat.com/whitepapers/developer/POSIX_Linux_Threading.pdf NPTL], "Memory Allocation"). Have a good time debugging that, champ!
* Failure to check every return, especially pthread_mutex_destroy(), is cause for [http://en.wikipedia.org/wiki/Tuol_Sleng_Genocide_Museum#The_Security_Regulations many many lashes of electric wire].
* Failure to check every return, especially pthread_mutex_destroy(), is cause for [http://en.wikipedia.org/wiki/Tuol_Sleng_Genocide_Museum#The_Security_Regulations many many lashes of electric wire].
* Those who fail to designate an alternate signal stack will one day wish they had.
* Those who fail to designate an alternate signal stack will one day wish they had.
Line 20: Line 20:
* Before trying to solve an issue with POSIX thread scheduling parameters, see if you can't just drink some hydrochloric acid.
* Before trying to solve an issue with POSIX thread scheduling parameters, see if you can't just drink some hydrochloric acid.
* No, you shouldn't be using the [http://www.mjmwired.net/kernel/Documentation/volatile-considered-harmful.txt volatile keyword].
* No, you shouldn't be using the [http://www.mjmwired.net/kernel/Documentation/volatile-considered-harmful.txt volatile keyword].
==Condition variable clocks==
By default, <tt>pthread_cond_timedwait()</tt> uses <tt>CLOCK_REALTIME</tt>, with all its attendant problems. You probably want it to use <tt>CLOCK_MONOTONIC</tt>. This can be effected on some implementations using <tt>pthread_condattr_setclock()</tt>. The new function <tt>pthread_cond_clockwait()</tt> has been [https://www.austingroupbugs.net/view.php?id=1216 proposed], but not yet accepted into the POSIX standard. Note that C++'s <tt>std::condition_variable</tt> also [https://reviews.llvm.org/D65339 suffers] from this braindamage.


==Pthreads signal model==
==Pthreads signal model==
POSIX threads specify that all threads within a process share a PID, and that each has its own, distinct thread id. PIDs have the integer type <tt>pid_t</tt>, and only positive PIDs can define actual processes. TIDs have the opaque type <tt>pthread_t</tt>; they cannot be ordered, but can be compared for equality.
POSIX threads specify that all threads within a process share a PID, and that each has its own, distinct thread id. PIDs have the integer type <tt>pid_t</tt>, and only positive PIDs can define actual processes. TIDs have the opaque type <tt>pthread_t</tt>; they cannot be ordered, but can be compared for equality.


Other processes can direct signals only to a PID, not the thread IDs within another process (TIDs of a given process have no meaning outside that process). Within the process, signals can be directed to particular TIDs. Use of <tt>raise(s)</tt> in a threaded program is equivalent to <tt>pthread_kill(pthread_self(),s)</tt>.
Other processes can direct signals only to a PID, not the thread IDs within another process (TIDs of a given process have no meaning outside that process). Within the process, signals can be directed to particular TIDs. Use of <tt>raise(s)</tt> in a threaded program is equivalent to <tt>pthread_kill(pthread_self(), s)</tt>.


Signal dispositions (handlers) are per-process. Signal masks are per-thread, and inherited upon thread creation (<tt>sigprocmask()</tt> is undefined in threaded programs; <tt>pthread_sigmask()</tt> must be used). Alternate signal stacks descriptors are per-thread, and inherited upon thread creation.
Signal dispositions (handlers) are per-process. Signal masks are per-thread, and inherited upon thread creation (<tt>sigprocmask()</tt> is undefined in threaded programs; <tt>pthread_sigmask()</tt> must be used). Alternate signal stacks descriptors are per-thread, and inherited upon thread creation.
Line 168: Line 171:
* the [[LinuxThreads]] port (devel/linuxthreads; this does NOT require emulators/linux-base*)
* the [[LinuxThreads]] port (devel/linuxthreads; this does NOT require emulators/linux-base*)
all threaded code muse use the reentrant version of the gcc builtin libs; this is done via -lgcc_r (-pthread should set this up). In addition, use -llthread to link against [[LinuxThreads]].
all threaded code muse use the reentrant version of the gcc builtin libs; this is done via -lgcc_r (-pthread should set this up). In addition, use -llthread to link against [[LinuxThreads]].
==Use with [[autotools]]==
The <tt>AX_PTHREAD</tt> [http://www.gnu.org/software/autoconf-archive/ax_pthread.html macro] from the Autoconf Archive is canonical, defining <tt>PTHREAD_LIBS</tt>, <tt>PTHREAD_CFLAGS</tt>, and <tt>PTHREAD_CC</tt>.