yield: Implement for OS/2 kLIBC.
[gnulib.git] / doc / multithread.texi
blob9b1bc2e174dc6dacc086428d82f8ffcec7d5e9ac
1 @node Multithreading
2 @chapter Multithreading
4 Multithreading is a programming paradigm.  In a multithreaded program,
5 multiple threads execute concurrently (or quasi concurrently) at different
6 places in the program.
8 There are three motivations for using multithreading in a program:
9 @itemize @bullet
10 @item
11 Exploiting CPU hardware with multiple execution units.  Nowadays, many CPUs
12 have 2 to 8 execution cores in a single chip.  Additionally, often multiple
13 CPU chips are combined in a single package.  Thus, some CPU packages support
14 64 or 96 simultaneous threads of execution.
15 @item
16 Simplifying program architecture.  When a program has to read from different
17 file descriptors, network sockets, or event channels at the same time, the
18 classical single-threaded architecture is to have a main loop which uses
19 @code{select} or @code{poll} on all the descriptors and then dispatches
20 according to from which descriptor input arrived.  In a multi-threaded
21 program, you allocate one thread for each descriptor, and these threads can
22 be programmed and managed independently.
23 @item
24 Offloading work from signal handlers.  A signal handler is not allowed to
25 call @code{malloc}; therefore you are very limited in what you can do in
26 a signal handler.  But a signal handler can notify a thread, and the thread
27 can then do the appropriate processing, as complex as it needs to be.
28 @end itemize
30 A multithreading API offers
31 @itemize @bullet
32 @item
33 Primitives for creating threads, for waiting until threads are terminated,
34 and for reaping their results.
35 @item
36 Primitives through which different threads can operate on the same data or
37 use some data structures for communicating between the threads.  These are
38 called ``mutexes'' or ``locks''.
39 @item
40 Primitives for executing a certain (initialization) code at most once.
41 @item
42 Primitives for notifying one or more other threads.  These are called wait
43 queues or ``condition variables''.
44 @item
45 Primitives for allowing different threads to have different values for a
46 variable.  Such a variable is said to reside in ``thread-local storage'' or
47 ``thread-specific storage''.
48 @item
49 Primitives for relinquishing control for some time and letting other threads
50 go.
51 @end itemize
53 Note: Programs that achieve multithreading through OpenMP (cf. the gnulib
54 module @samp{openmp}) don't create and manage their threads themselves.
55 Nevertheless, they need to use mutexes/locks in many cases.
57 @menu
58 * Multithreading APIs::
59 * Choosing a multithreading API::
60 * POSIX multithreading::
61 * ISO C multithreading::
62 * Gnulib multithreading::
63 * Multithreading Optimizations::
64 @end menu
66 @node Multithreading APIs
67 @section The three multithreading APIs
69 Three multithreading APIs are available to Gnulib users:
70 @itemize @bullet
71 @item
72 POSIX multithreading,
73 @item
74 ISO C multithreading,
75 @item
76 Gnulib multithreading.
77 @end itemize
79 They are supported on all platforms that have multithreading in one form or
80 the other.  Currently, these are all platforms supported by Gnulib, except
81 for Minix.
83 The main differences are:
84 @itemize @bullet
85 @item
86 The exit code of a thread is a pointer in the POSIX and Gnulib APIs, but
87 only an @code{int} in the ISO C API.
88 @item
89 The POSIX API has additional facilities for detaching threads, setting the
90 priority of a thread, assigning a thread to a certain set of processors,
91 and much more.
92 @item
93 In the POSIX and ISO C APIs, most functions have a return code, and you
94 are supposed to check the return code; even locking and unlocking a lock
95 can fail.  In the Gnulib API, many functions don't have a return code; if
96 they cannot complete, the program aborts.  This sounds harsh, but such
97 aborts have not been reported in 12 years.
98 @item
99 In the ISO C API, the initialization of a statically allocated lock is
100 clumsy: You have to initialize it through a once-only function.
101 @end itemize
103 @node Choosing a multithreading API
104 @section Choosing the right multithreading API
106 Here are guidelines for determining which multithreading API is best for
107 your code.
109 In programs that use advanced POSIX APIs, such as spin locks,
110 detached threads (@code{pthread_detach}),
111 signal blocking (@code{pthread_sigmask}),
112 priorities (@code{pthread_setschedparam}),
113 processor affinity (@code{pthread_setaffinity_np}), it is best to use
114 the POSIX API.  This is because you cannot convert an ISO C @code{thrd_t}
115 or a Gnulib @code{gl_thread_t} to a POSIX @code{pthread_t}.
117 In code that is shared with glibc, it is best to use the POSIX API as well.
119 In libraries, it is best to use the Gnulib API.  This is because it gives
120 the person who builds the library an option
121 @samp{--enable-threads=@{isoc,posix,windows@}}, that determines on which
122 native multithreading API of the platform to rely.  In other words, with
123 this choice, you can minimize the amount of glue code that your library
124 needs to contain.
126 In the other cases, the POSIX API and the Gnulib API are equally well suited.
128 The ISO C API is never the best choice, as of this writing (2020).
130 @node POSIX multithreading
131 @section The POSIX multithreading API
133 The POSIX multithreading API is documented in POSIX
134 @url{https://pubs.opengroup.org/onlinepubs/9699919799/}.
136 To make use of POSIX multithreading, even on platforms that don't support it
137 natively (most prominently, native Windows), use the following Gnulib modules:
138 @multitable @columnfractions .75 .25
139 @headitem Purpose @tab Module
140 @item For thread creation and management:@tie{} @tab @code{pthread-thread}
141 @item For simple and recursive locks:@tie{} @tab @code{pthread-mutex}
142 @item For read-write locks:@tie{} @tab @code{pthread-rwlock}
143 @item For once-only execution:@tie{} @tab @code{pthread-once}
144 @item For ``condition variables'' (wait queues):@tie{} @tab @code{pthread-cond}
145 @item For thread-local storage:@tie{} @tab @code{pthread-tss}
146 @item For relinquishing control:@tie{} @tab @code{sched_yield}
147 @item For spin locks:@tie{} @tab @code{pthread-spin}
148 @end multitable
150 There is also a convenience module named @code{pthread} which depends on all
151 of these (except @code{sched_yield}); so you don't need to enumerate these
152 modules one by one.
154 @node ISO C multithreading
155 @section The ISO C multithreading API
157 The ISO C multithreading API is documented in ISO C 11
158 @url{http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf}.
160 To make use of ISO C multithreading, even on platforms that don't support it
161 or have severe bugs, use the following Gnulib modules:
162 @multitable @columnfractions .85 .15
163 @headitem Purpose @tab Module
164 @item For thread creation and management:@tie{} @tab @code{thrd}
165 @item For simple locks, recursive locks, and read-write locks:@tie{}
166       @tab @code{mtx}
167 @item For once-only execution:@tie{} @tab @code{mtx}
168 @item For ``condition variables'' (wait queues):@tie{} @tab @code{cnd}
169 @item For thread-local storage:@tie{} @tab @code{tss}
170 @end multitable
172 There is also a convenience module named @code{threads} which depends on all
173 of these; so you don't need to enumerate these modules one by one.
175 @node Gnulib multithreading
176 @section The Gnulib multithreading API
178 The Gnulib multithreading API is documented in the respective include files:
179 @itemize
180 @item
181 @code{<glthread/thread.h>}
182 @item
183 @code{<glthread/lock.h>}
184 @item
185 @code{<glthread/cond.h>}
186 @item
187 @code{<glthread/tls.h>}
188 @item
189 @code{<glthread/yield.h>}
190 @end itemize
192 To make use of Gnulib multithreading, use the following Gnulib modules:
193 @multitable @columnfractions .85 .15
194 @headitem Purpose @tab Module
195 @item For thread creation and management:@tie{} @tab @code{thread}
196 @item For simple locks, recursive locks, and read-write locks:@tie{}
197       @tab @code{lock}
198 @item For once-only execution:@tie{} @tab @code{lock}
199 @item For ``condition variables'' (wait queues):@tie{} @tab @code{cond}
200 @item For thread-local storage:@tie{} @tab @code{tls}
201 @item For relinquishing control:@tie{} @tab @code{yield}
202 @end multitable
204 The Gnulib multithreading supports a configure option
205 @samp{--enable-threads=@{isoc,posix,windows@}}, that chooses the underlying
206 thread implementation.  Currently (2020):
207 @itemize @bullet
208 @item
209 @code{--enable-threads=posix} is supported and is the best choice on all
210 platforms except for native Windows.  It may also work, to a limited extent,
211 on mingw with the @code{winpthreads} library, but is not recommended there.
212 @item
213 @code{--enable-threads=windows} is supported and is the best choice on
214 native Windows platforms (mingw and MSVC).
215 @item
216 @code{--enable-threads=isoc} is supported on all platforms that have the
217 ISO C multithreading API.  However, @code{--enable-threads=posix} is always
218 a better choice.
219 @end itemize
221 @node Multithreading Optimizations
222 @section Optimizations of multithreaded code
224 Despite all the optimizations of multithreading primitives that have been
225 implemented over the years --- from
226 @url{https://en.wikipedia.org/wiki/Compare-and-swap,
227 atomic operations in hardware},
228 over @url{https://en.wikipedia.org/wiki/Futex, futexes} and
229 @url{https://www.efficios.com/blog/2019/02/08/linux-restartable-sequences/,
230 restartable sequences}
231 in the Linux kernel, to lock elision
232 @url{https://lwn.net/Articles/534758/, [1]}
233 @url{https://www.gnu.org/software/libc/manual/html_node/Elision-Tunables.html,
234 [2]})
235 --- single-threaded programs can still profit performance-wise from the
236 assertion that they are single-threaded.
238 Gnulib defines four facilities that help optimizing for the single-threaded
239 case.
241 @itemize @bullet
242 @item
243 The Gnulib multithreading API, when used on glibc @leq{} 2.32 and *BSD systems,
244 uses weak symbols to detect whether the program is linked with
245 @code{libpthread}.  If not, the program has no way to create additional
246 threads and must therefore be single-threaded.  This optimization applies
247 to all the Gnulib multithreading API (locks, thread-local storage, and more).
248 @item
249 The @code{thread-optim} module, on glibc @geq{} 2.32 systems, allows your code
250 to skip locking between threads (regardless which of the three multithreading
251 APIs you use).  You need extra code for this: include the
252 @code{"thread-optim.h"} header file, and use the macro @code{gl_multithreaded}
253 like this:
254 @smallexample
255 bool mt = gl_multithreaded ();
256 if (mt) gl_lock_lock (some_lock);
258 if (mt) gl_lock_unlock (some_lock);
259 @end smallexample
260 @item
261 The @code{unlocked-io} module is applicable only if all the programs in your
262 package are single-threaded.  It optimizes the operations on @code{FILE}
263 streams.  You need extra code for this: include the @code{"unlocked-io.h"}
264 header file.  Some Gnulib modules that do operations on @code{FILE} streams
265 have these preparations already included.
266 @item
267 You may define the C macro @code{GNULIB_WCHAR_SINGLE}, if all the programs in
268 your package are single-threaded and won't change the locale after it has
269 been initialized.  This macro optimizes the functions @code{mbrtowc} and
270 @code{wcwidth}.
271 @end itemize