GNU libmicrohttpd  1.0.1
mhd_threads.h
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2016-2023 Karlson2k (Evgeny Grin)
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
20 
36 #ifndef MHD_THREADS_H
37 #define MHD_THREADS_H 1
38 
39 #include "mhd_options.h"
40 #ifdef HAVE_STDDEF_H
41 # include <stddef.h> /* for size_t */
42 #elif defined(HAVE_STDLIB_H)
43 # include <stdlib.h> /* for size_t */
44 #else /* ! HAVE_STDLIB_H */
45 # include <stdio.h> /* for size_t */
46 #endif /* ! HAVE_STDLIB_H */
47 
48 #if defined(MHD_USE_POSIX_THREADS)
49 # undef HAVE_CONFIG_H
50 # include <pthread.h>
51 # define HAVE_CONFIG_H 1
52 # ifndef MHD_USE_THREADS
53 # define MHD_USE_THREADS 1
54 # endif
55 #elif defined(MHD_USE_W32_THREADS)
56 # ifndef WIN32_LEAN_AND_MEAN
57 # define WIN32_LEAN_AND_MEAN 1
58 # endif /* !WIN32_LEAN_AND_MEAN */
59 # include <windows.h>
60 # ifndef MHD_USE_THREADS
61 # define MHD_USE_THREADS 1
62 # endif
63 #else
64 # error No threading API is available.
65 #endif
66 
67 #ifdef HAVE_STDBOOL_H
68 # include <stdbool.h>
69 #endif /* HAVE_STDBOOL_H */
70 
71 #if defined(MHD_USE_POSIX_THREADS) && defined(MHD_USE_W32_THREADS)
72 # error Both MHD_USE_POSIX_THREADS and MHD_USE_W32_THREADS are defined
73 #endif /* MHD_USE_POSIX_THREADS && MHD_USE_W32_THREADS */
74 
75 #ifndef MHD_NO_THREAD_NAMES
76 # if defined(MHD_USE_POSIX_THREADS)
77 # if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \
78  defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD) || \
79  defined(HAVE_PTHREAD_SETNAME_NP_DARWIN) || \
80  defined(HAVE_PTHREAD_SETNAME_NP_NETBSD) || \
81  defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) || \
82  defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI)
83 # define MHD_USE_THREAD_NAME_
84 # endif /* HAVE_PTHREAD_SETNAME_NP */
85 # elif defined(MHD_USE_W32_THREADS)
86 # ifdef _MSC_FULL_VER
87 /* Thread names only available with VC compiler */
88 # define MHD_USE_THREAD_NAME_
89 # endif /* _MSC_FULL_VER */
90 # endif
91 #endif
92 
93 /* ** Thread handle - used to control the thread ** */
94 
95 #if defined(MHD_USE_POSIX_THREADS)
101 # define MHD_join_thread_(native_handle) \
102  (! pthread_join ((native_handle), NULL))
103 #elif defined(MHD_USE_W32_THREADS)
109 # define MHD_join_thread_(native_handle) \
110  ( (WAIT_OBJECT_0 == WaitForSingleObject ( (native_handle), INFINITE)) ? \
111  (CloseHandle ( (native_handle)), ! 0) : 0 )
112 #endif
113 
114 #if defined(MHD_USE_POSIX_THREADS)
118 typedef pthread_t MHD_thread_handle_native_;
119 #elif defined(MHD_USE_W32_THREADS)
123 typedef HANDLE MHD_thread_handle_native_;
124 #endif
125 
126 #if defined(MHD_USE_POSIX_THREADS)
127 # if defined(__gnu_linux__) || \
128  (defined(__linux__) && defined(__GLIBC__))
129 /* The next part of code is disabled because it relies on undocumented
130  behaviour.
131  It could be enabled for neglectable performance and size improvements. */
132 # if 0 /* Disabled code */
136 # define MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ \
137  ((MHD_thread_handle_native_) 0)
138 # endif /* Disabled code */
139 # endif /* __gnu_linux__ || (__linux__ && __GLIBC__) */
140 #elif defined(MHD_USE_W32_THREADS)
144 # define MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ \
145  ((MHD_thread_handle_native_) NULL)
146 #endif /* MHD_USE_W32_THREADS */
147 
148 #if ! defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_)
153 {
154  bool valid;
155  MHD_thread_handle_native_ native;
156 };
161 
165 # define MHD_thread_handle_set_invalid_(handle_ptr) \
166  ((handle_ptr)->valid = false)
171 # define MHD_thread_handle_set_native_(handle_ptr,native_val) \
172  ((handle_ptr)->valid = true, (handle_ptr)->native = native_val)
176 # define MHD_thread_handle_is_valid_(handle_var) \
177  ((handle_var).valid)
181 # define MHD_thread_handle_get_native_(handle_var) \
182  ((handle_var).native)
183 #else /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */
187 typedef MHD_thread_handle_native_ MHD_thread_handle_;
188 
192 # define MHD_thread_handle_set_invalid_(handle_ptr) \
193  ((*(handle_ptr)) = MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_)
198 # define MHD_thread_handle_set_native_(handle_ptr,native_val) \
199  ((*(handle_ptr)) = native_val)
203 # define MHD_thread_handle_is_valid_(handle_var) \
204  (MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ != handle_var)
208 # define MHD_thread_handle_get_native_(handle_var) \
209  (handle_var)
215 # define MHD_thread_handle_get_native_ptr_(handle_ptr) \
216  (handle_ptr)
217 #endif /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */
218 
219 
220 /* ** Thread ID - used to check threads match ** */
221 
222 #if defined(MHD_USE_POSIX_THREADS)
226 typedef pthread_t MHD_thread_ID_native_;
227 
231 # define MHD_thread_ID_native_current_ pthread_self
232 
237 # define MHD_thread_ID_native_equal_(id1,id2) \
238  (pthread_equal(id1,id2))
239 #elif defined(MHD_USE_W32_THREADS)
243 typedef DWORD MHD_thread_ID_native_;
244 
248 # define MHD_thread_ID_native_current_ GetCurrentThreadId
249 
254 # define MHD_thread_ID_native_equal_(id1,id2) \
255  ((id1) == (id2))
256 #endif
257 
263 #define MHD_thread_ID_native_is_current_thread_(id) \
264  MHD_thread_ID_native_equal_(id, MHD_thread_ID_native_current_())
265 
266 
267 #if defined(MHD_USE_POSIX_THREADS)
268 # if defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_)
272 # define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \
273  MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_
274 # endif /* MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ */
275 #elif defined(MHD_USE_W32_THREADS)
279  # define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \
280  ((MHD_thread_ID_native_) 0)
281 #endif /* MHD_USE_W32_THREADS */
282 
283 #if ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
288 {
289  bool valid;
290  MHD_thread_ID_native_ native;
291 };
296 
300 # define MHD_thread_ID_set_invalid_(ID_ptr) \
301  ((ID_ptr)->valid = false)
306 # define MHD_thread_ID_set_native_(ID_ptr,native_val) \
307  ((ID_ptr)->valid = true, (ID_ptr)->native = native_val)
311 # define MHD_thread_ID_is_valid_(ID_var) \
312  ((ID_var).valid)
316 # define MHD_thread_ID_get_native_(ID_var) \
317  ((ID_var).native)
321 # define MHD_thread_ID_is_current_thread_(ID_var) \
322  (MHD_thread_ID_is_valid_(ID_var) && \
323  MHD_thread_ID_native_is_current_thread_((ID_var).native))
324 #else /* MHD_THREAD_ID_NATIVE_INVALID_ */
328 typedef MHD_thread_ID_native_ MHD_thread_ID_;
329 
333 # define MHD_thread_ID_set_invalid_(ID_ptr) \
334  ((*(ID_ptr)) = MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
339 # define MHD_thread_ID_set_native_(ID_ptr,native_val) \
340  ((*(ID_ptr)) = native_val)
344 # define MHD_thread_ID_is_valid_(ID_var) \
345  (MHD_THREAD_ID_NATIVE_VALUE_INVALID_ != ID_var)
349 # define MHD_thread_ID_get_native_(ID_var) \
350  (ID_var)
354 # define MHD_thread_ID_is_current_thread_(ID_var) \
355  MHD_thread_ID_native_is_current_thread_(ID_var)
356 #endif /* MHD_THREAD_ID_NATIVE_INVALID_ */
357 
361 # define MHD_thread_ID_set_current_thread_(ID_ptr) \
362  MHD_thread_ID_set_native_(ID_ptr,MHD_thread_ID_native_current_())
363 
364 
365 #if defined(MHD_USE_POSIX_THREADS)
366 # if defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \
367  ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
368 # error \
369  MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined
370 # elif ! defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \
371  defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
372 # error \
373  MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined
374 # endif
375 #endif /* MHD_USE_POSIX_THREADS */
376 
377 /* When staring a new thread, the kernel (and thread implementation) may
378  * pause the calling (initial) thread and start the new thread.
379  * If thread identifier is assigned to variable in the initial thread then
380  * the value of the identifier variable will be undefined in the new thread
381  * until the initial thread continue processing.
382  * However, it is also possible that the new thread created, but not executed
383  * for some time while the initial thread continue execution. In this case any
384  * variable assigned in the new thread will be undefined for some time until
385  * they really processed by the new thread.
386  * To avoid data races, a special structure MHD_thread_handle_ID_ is used.
387  * The "handle" is assigned by calling (initial) thread and should be always
388  * defined when checked in the initial thread.
389  * The "ID" is assigned by the new thread and should be always defined when
390  * checked inside the new thread.
391  */
392 /* Depending on implementation, pthread_create() MAY set thread ID into
393  * provided pointer and after it start thread OR start thread and after
394  * it set thread ID. In the latter case, to avoid data races, additional
395  * pthread_self() call is required in thread routine. If some platform
396  * is known for setting thread ID BEFORE starting thread macro
397  * MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD could be defined
398  * to save some resources. */
399 /* #define MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 1 */
400 
401 /* * handle - must be valid when other thread knows that particular thread
402  is started.
403  * ID - must be valid when code is executed inside thread */
404 #if defined(MHD_USE_POSIX_THREADS) && \
405  defined(MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD) && \
406  defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \
407  defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) && \
408  defined(MHD_thread_handle_get_native_ptr_)
410 {
413 };
415 # define MHD_THREAD_HANDLE_ID_IS_UNION 1
416 #else /* !MHD_USE_POSIX_THREADS
417  || !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
418  || !MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_
419  || !MHD_THREAD_ID_NATIVE_VALUE_INVALID_
420  || !MHD_thread_handle_get_native_ptr_ */
422 {
425 };
427 #endif /* !MHD_USE_POSIX_THREADS
428  || !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
429  || !MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_
430  || !MHD_THREAD_ID_NATIVE_VALUE_INVALID_
431  || !MHD_thread_handle_get_native_ptr_ */
432 
436 #define MHD_thread_handle_ID_set_invalid_(hndl_id_ptr) \
437  (MHD_thread_handle_set_invalid_(&((hndl_id_ptr)->handle)), \
438  MHD_thread_ID_set_invalid_(&((hndl_id_ptr)->ID)))
439 
444 #define MHD_thread_handle_ID_is_valid_handle_(hndl_id) \
445  MHD_thread_handle_is_valid_((hndl_id).handle)
446 
451 #define MHD_thread_handle_ID_set_native_handle_(hndl_id_ptr,native_val) \
452  MHD_thread_handle_set_native_(&((hndl_id_ptr)->handle),native_val)
453 
454 #if defined(MHD_thread_handle_get_native_ptr_)
460 # define MHD_thread_handle_ID_get_native_handle_ptr_(hndl_id_ptr) \
461  MHD_thread_handle_get_native_ptr_(&((hndl_id_ptr)->handle))
462 #endif /* MHD_thread_handle_get_native_ptr_ */
463 
467 #define MHD_thread_handle_ID_get_native_handle_(hndl_id) \
468  MHD_thread_handle_get_native_((hndl_id).handle)
469 
474 #define MHD_thread_handle_ID_is_valid_ID_(hndl_id) \
475  MHD_thread_ID_is_valid_((hndl_id).ID)
476 
477 #if defined(MHD_THREAD_HANDLE_ID_IS_UNION)
478 # if defined(MHD_USE_W32_THREADS)
479 # error MHD_thread_handle_ID_ cannot be a union with W32 threads
480 # endif /* MHD_USE_W32_THREADS */
484 # define MHD_thread_handle_ID_set_current_thread_ID_(hndl_id_ptr) (void) 0
485 #else /* ! MHD_THREAD_HANDLE_ID_IS_UNION */
489 # define MHD_thread_handle_ID_set_current_thread_ID_(hndl_id_ptr) \
490  MHD_thread_ID_set_current_thread_(&((hndl_id_ptr)->ID))
491 #endif /* ! MHD_THREAD_HANDLE_ID_IS_UNION */
492 
498 #define MHD_thread_handle_ID_is_current_thread_(hndl_id) \
499  MHD_thread_ID_is_current_thread_((hndl_id).ID)
500 
506 #define MHD_thread_handle_ID_join_thread_(hndl_id) \
507  MHD_join_thread_(MHD_thread_handle_ID_get_native_handle_(hndl_id))
508 
509 #if defined(MHD_USE_POSIX_THREADS)
510 # define MHD_THRD_RTRN_TYPE_ void*
511 # define MHD_THRD_CALL_SPEC_
512 #elif defined(MHD_USE_W32_THREADS)
513 # define MHD_THRD_RTRN_TYPE_ unsigned
514 # define MHD_THRD_CALL_SPEC_ __stdcall
515 #endif
516 
523 typedef MHD_THRD_RTRN_TYPE_
524 (MHD_THRD_CALL_SPEC_ *MHD_THREAD_START_ROUTINE_)(void *cls);
525 
526 
538 int
540  size_t stack_size,
541  MHD_THREAD_START_ROUTINE_ start_routine,
542  void *arg);
543 
544 #ifndef MHD_USE_THREAD_NAME_
545 #define MHD_create_named_thread_(t,n,s,r,a) MHD_create_thread_ ((t),(s),(r),(a))
546 #else /* MHD_USE_THREAD_NAME_ */
557 int
559  const char *thread_name,
560  size_t stack_size,
561  MHD_THREAD_START_ROUTINE_ start_routine,
562  void *arg);
563 
564 #endif /* MHD_USE_THREAD_NAME_ */
565 
566 #endif /* ! MHD_THREADS_H */
int MHD_create_thread_(MHD_thread_handle_ID_ *thread, size_t stack_size, MHD_THREAD_START_ROUTINE_ start_routine, void *arg)
Definition: mhd_threads.c:180
MHD_THRD_RTRN_TYPE_(MHD_THRD_CALL_SPEC_ * MHD_THREAD_START_ROUTINE_)(void *cls)
Definition: mhd_threads.h:195
additional automatic macros for MHD_config.h
struct MHD_thread_handle_struct_ MHD_thread_handle_
Definition: mhd_threads.h:160
struct MHD_thread_ID_struct_ MHD_thread_ID_
Definition: mhd_threads.h:295
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:545
MHD_thread_ID_native_ native
Definition: mhd_threads.h:290
MHD_thread_handle_native_ native
Definition: mhd_threads.h:155
MHD_thread_ID_ ID
Definition: mhd_threads.h:424
MHD_thread_handle_ handle
Definition: mhd_threads.h:423