libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

mhd_threads.h (20558B)


      1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
      2 /*
      3   This file is part of GNU libmicrohttpd.
      4   Copyright (C) 2016-2025 Evgeny Grin (Karlson2k)
      5 
      6   GNU libmicrohttpd is free software; you can redistribute it and/or
      7   modify it under the terms of the GNU Lesser General Public
      8   License as published by the Free Software Foundation; either
      9   version 2.1 of the License, or (at your option) any later version.
     10 
     11   GNU libmicrohttpd is distributed in the hope that it will be useful,
     12   but WITHOUT ANY WARRANTY; without even the implied warranty of
     13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14   Lesser General Public License for more details.
     15 
     16   Alternatively, you can redistribute GNU libmicrohttpd and/or
     17   modify it under the terms of the GNU General Public License as
     18   published by the Free Software Foundation; either version 2 of
     19   the License, or (at your option) any later version, together
     20   with the eCos exception, as follows:
     21 
     22     As a special exception, if other files instantiate templates or
     23     use macros or inline functions from this file, or you compile this
     24     file and link it with other works to produce a work based on this
     25     file, this file does not by itself cause the resulting work to be
     26     covered by the GNU General Public License. However the source code
     27     for this file must still be made available in accordance with
     28     section (3) of the GNU General Public License v2.
     29 
     30     This exception does not invalidate any other reasons why a work
     31     based on this file might be covered by the GNU General Public
     32     License.
     33 
     34   You should have received copies of the GNU Lesser General Public
     35   License and the GNU General Public License along with this library;
     36   if not, see <https://www.gnu.org/licenses/>.
     37 */
     38 
     39 /**
     40  * @file src/mhd2/mhd_threads.h
     41  * @brief  Header for platform-independent threads abstraction
     42  * @author Karlson2k (Evgeny Grin)
     43  *
     44  * Provides basic abstraction for threads.
     45  * Any functions can be implemented as macro on some platforms
     46  * unless explicitly marked otherwise.
     47  * Any function argument can be skipped in macro, so avoid
     48  * variable modification in function parameters.
     49  *
     50  * @warning Unlike pthread functions, most of functions return
     51  *          nonzero on success.
     52  */
     53 
     54 #ifndef MHD_THREADS_H
     55 #define MHD_THREADS_H 1
     56 
     57 #include "mhd_sys_options.h"
     58 
     59 #ifndef MHD_SUPPORT_THREADS
     60 #  error Threads support disabled by configure.
     61 #endif
     62 
     63 #if defined(mhd_THREADS_KIND_POSIX)
     64 #  include <pthread.h>
     65 #  ifndef MHD_SUPPORT_THREADS
     66 #    define MHD_SUPPORT_THREADS 1
     67 #  endif
     68 #elif defined(mhd_THREADS_KIND_W32)
     69 #  include <windows.h>
     70 #  ifndef MHD_SUPPORT_THREADS
     71 #    define MHD_SUPPORT_THREADS 1
     72 #  endif
     73 #else
     74 #  error No threading API is available.
     75 #endif
     76 
     77 #include "sys_bool_type.h"
     78 #include "sys_base_types.h"
     79 #include "sys_thread_entry_type.h"
     80 
     81 #if defined(mhd_THREADS_KIND_POSIX) && defined(mhd_THREADS_KIND_W32)
     82 #  error Both mhd_THREADS_KIND_POSIX and mhd_THREADS_KIND_W32 are defined
     83 #endif /* mhd_THREADS_KIND_POSIX && mhd_THREADS_KIND_W32 */
     84 
     85 #ifndef MHD_NO_THREAD_NAMES
     86 #  if defined(mhd_THREADS_KIND_POSIX)
     87 #    if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \
     88   defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD) || \
     89   defined(HAVE_PTHREAD_SETNAME_NP_DARWIN) || \
     90   defined(HAVE_PTHREAD_SETNAME_NP_NETBSD) || \
     91   defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) || \
     92   defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI)
     93 #      define mhd_USE_THREAD_NAME
     94 #    endif /* HAVE_PTHREAD_SETNAME_NP */
     95 #  elif defined(mhd_THREADS_KIND_W32)
     96 #    ifdef _MSC_FULL_VER
     97 /* Thread names only available with VC compiler */
     98 #      define mhd_USE_THREAD_NAME
     99 #    endif /* _MSC_FULL_VER */
    100 #  endif
    101 #endif
    102 
    103 /* ** Thread handle - used to control the thread ** */
    104 
    105 #if defined(mhd_THREADS_KIND_POSIX)
    106 /**
    107  * The native type to control the thread from other threads
    108  */
    109 typedef pthread_t mhd_thread_handle_native;
    110 #elif defined(mhd_THREADS_KIND_W32)
    111 /**
    112  * The native type to control the thread from other threads
    113  */
    114 typedef HANDLE mhd_thread_handle_native;
    115 #endif
    116 
    117 #if defined(mhd_THREADS_KIND_POSIX)
    118 #  if defined(__gnu_linux__) || \
    119   (defined(__linux__) && defined(__GLIBC__))
    120 /* The next part of code is disabled because it relies on undocumented
    121    behaviour (while the thread ID cannot be zero with GNU C Library, it is
    122    not specified anywhere officially).
    123    It could be enabled for neglectable performance and size improvements. */
    124 #  if 0 /* Disabled code */
    125 /**
    126  * The native invalid value for native thread handle
    127  */
    128 #    define mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID \
    129         ((mhd_thread_handle_native) 0)
    130 #  endif /* Disabled code */
    131 #  endif /* __gnu_linux__ || (__linux__ && __GLIBC__) */
    132 #elif defined(mhd_THREADS_KIND_W32)
    133 /* On W32 the invalid value for thread handle is described directly in
    134   the official documentation. */
    135 /**
    136  * The native invalid value for native thread handle
    137  */
    138 #  define mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID \
    139         ((mhd_thread_handle_native) NULL)
    140 #endif /* mhd_THREADS_KIND_W32 */
    141 
    142 #if defined(mhd_THREADS_KIND_POSIX)
    143 /**
    144  * Wait until specified thread is ended and free the thread handle on success.
    145  * @param native_handle the handle to watch
    146  * @return nonzero on success, zero otherwise
    147  */
    148 #  define mhd_join_thread(native_handle) \
    149         (! pthread_join ((native_handle), NULL))
    150 #elif defined(mhd_THREADS_KIND_W32)
    151 /**
    152  * Wait until specified thread is ended and the free thread handle on success.
    153  * @param native_handle the handle to watch
    154  * @return nonzero on success, zero otherwise
    155  */
    156 #  define mhd_join_thread(native_handle) \
    157         ( (WAIT_OBJECT_0 == WaitForSingleObject ( (native_handle), INFINITE)) ? \
    158           (CloseHandle ( (native_handle)), ! 0) : 0)
    159 #endif
    160 
    161 #if ! defined(mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID)
    162 /**
    163  * Structure with thread handle and validity flag
    164  */
    165 struct mhd_thread_handle_struct
    166 {
    167   bool valid;                       /**< true if native handle is set */
    168   mhd_thread_handle_native native; /**< the native thread handle */
    169 };
    170 /**
    171  * Type with thread handle that can be set to invalid value
    172  */
    173 typedef struct mhd_thread_handle_struct mhd_thread_handle;
    174 
    175 /**
    176  * Set variable pointed by @a handle_ptr to invalid (unset) value
    177  */
    178 #  define mhd_thread_handle_set_invalid(handle_ptr) \
    179         ((handle_ptr)->valid = false)
    180 /**
    181  * Set the native handle in the variable pointed by the @a handle_ptr
    182  * to the @a native_val value
    183  */
    184 #  define mhd_thread_handle_set_native(handle_ptr,native_val) \
    185         ((handle_ptr)->valid = true, (handle_ptr)->native = native_val)
    186 /**
    187  * Check whether the native handle value is set in the @a handle_var variable
    188  */
    189 #  define mhd_thread_handle_is_valid(handle_var) \
    190         ((handle_var).valid)
    191 /**
    192  * Get the native handle value from the @a handle_var variable
    193  */
    194 #  define mhd_thread_handle_get_native(handle_var) \
    195         ((handle_var).native)
    196 #else  /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */
    197 /**
    198  * Type with thread handle that can be set to invalid value
    199  */
    200 typedef mhd_thread_handle_native mhd_thread_handle;
    201 
    202 /**
    203  * Set the variable pointed by the @a handle_ptr to the invalid (unset) value
    204  */
    205 #  define mhd_thread_handle_set_invalid(handle_ptr) \
    206         ((*(handle_ptr)) = mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID)
    207 /**
    208  * Set the native handle in the variable pointed by the @a handle_ptr
    209  * to the @a native_val value
    210  */
    211 #  define mhd_thread_handle_set_native(handle_ptr,native_val) \
    212         ((*(handle_ptr)) = (native_val))
    213 /**
    214  * Check whether the native handle value is set in the @a handle_var variable
    215  */
    216 #  define mhd_thread_handle_is_valid(handle_var) \
    217         (mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID != (handle_var))
    218 /**
    219  * Get the native handle value from the @a handle_var variable
    220  */
    221 #  define mhd_thread_handle_get_native(handle_var) \
    222         (handle_var)
    223 /**
    224  * Get the pointer to the native handle stored the variable pointed by
    225  * the @a handle_ptr pointer
    226  * @note This macro could be not available if direct manipulation of
    227  *       the native handle is not possible
    228  */
    229 #  define mhd_thread_handle_get_native_ptr(handle_ptr) \
    230         (handle_ptr)
    231 #endif /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */
    232 
    233 
    234 /* ** Thread ID - used to check threads match ** */
    235 
    236 #if defined(mhd_THREADS_KIND_POSIX)
    237 /**
    238  * The native type used to check whether the current thread matches
    239  * the expected thread
    240  */
    241 typedef pthread_t mhd_thread_ID_native;
    242 
    243 /**
    244  * Function to get the current thread native ID.
    245  */
    246 #  define mhd_thread_ID_native_current pthread_self
    247 
    248 /**
    249  * Check whether two native thread IDs are equal.
    250  * @return non-zero if equal, zero if not equal
    251  */
    252 #  define mhd_thread_ID_native_equal(id1,id2) \
    253         (pthread_equal ((id1),(id2)))
    254 #elif defined(mhd_THREADS_KIND_W32)
    255 /**
    256  * The native type used to check whether the current thread matches
    257  * the expected thread
    258  */
    259 typedef DWORD mhd_thread_ID_native;
    260 
    261 /**
    262  * Function to get the current thread native ID.
    263  */
    264 #  define mhd_thread_ID_native_current GetCurrentThreadId
    265 
    266 /**
    267  * Check whether two native thread IDs are equal.
    268  * @return non-zero if equal, zero if not equal
    269  */
    270 #  define mhd_thread_ID_native_equal(id1,id2) \
    271         ((id1) == (id2))
    272 #endif
    273 
    274 /**
    275  * Check whether the specified thread ID matches current thread.
    276  * @param id the thread ID to match
    277  * @return nonzero on match, zero otherwise
    278  */
    279 #define mhd_thread_ID_native_is_current_thread(id) \
    280         mhd_thread_ID_native_equal ((id), mhd_thread_ID_native_current ())
    281 
    282 
    283 #if defined(mhd_THREADS_KIND_POSIX)
    284 #  if defined(mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID)
    285 /**
    286  * The native invalid value for native thread ID
    287  */
    288 #    define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \
    289         mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID
    290 #  endif /* mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID */
    291 #elif defined(mhd_THREADS_KIND_W32)
    292 /**
    293  * The native invalid value for native thread ID
    294  */
    295  #  define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \
    296          ((mhd_thread_ID_native) 0)
    297 #endif /* mhd_THREADS_KIND_W32 */
    298 
    299 #if ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
    300 /**
    301  * Structure with thread id and validity flag
    302  */
    303 struct mhd_thread_ID_struct
    304 {
    305   bool valid;                   /**< true if native ID is set */
    306   mhd_thread_ID_native native; /**< the native thread ID */
    307 };
    308 /**
    309  * Type with thread ID that can be set to the invalid value
    310  */
    311 typedef struct mhd_thread_ID_struct mhd_thread_ID;
    312 
    313 /**
    314  * Set variable pointed by the @a ID_ptr to the invalid (unset) value
    315  */
    316 #  define mhd_thread_ID_set_invalid(ID_ptr) \
    317         ((ID_ptr)->valid = false)
    318 /**
    319  * Set the native ID in the variable pointed by the @a ID_ptr
    320  * to the @a native_val value
    321  */
    322 #  define mhd_thread_ID_set_native(ID_ptr,native_val) \
    323         ((ID_ptr)->valid = true, (ID_ptr)->native = (native_val))
    324 /**
    325  * Check whether the native ID value is set in the @a ID_var variable
    326  */
    327 #  define mhd_thread_ID_is_valid(ID_var) \
    328         ((ID_var).valid)
    329 /**
    330  * Get the native ID value from the @a ID_var variable
    331  */
    332 #  define mhd_thread_ID_get_native(ID_var) \
    333         ((ID_var).native)
    334 /**
    335  * Check whether the @a ID_var variable is equal current thread
    336  */
    337 #  define mhd_thread_ID_is_current_thread(ID_var) \
    338         (mhd_thread_ID_is_valid (ID_var) && \
    339          mhd_thread_ID_native_is_current_thread ((ID_var).native))
    340 #else  /* MHD_THREAD_ID_NATIVE_INVALID_ */
    341 /**
    342  * Type with thread ID that can be set to the invalid value
    343  */
    344 typedef mhd_thread_ID_native mhd_thread_ID;
    345 
    346 /**
    347  * Set variable pointed by the @a ID_ptr to the invalid (unset) value
    348  */
    349 #  define mhd_thread_ID_set_invalid(ID_ptr) \
    350         ((*(ID_ptr)) = MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
    351 /**
    352  * Set the native ID in the variable pointed by the @a ID_ptr
    353  * to the @a native_val value
    354  */
    355 #  define mhd_thread_ID_set_native(ID_ptr,native_val) \
    356         ((*(ID_ptr)) = (native_val))
    357 /**
    358  * Check whether the native ID value is set in the @a ID_var variable
    359  */
    360 #  define mhd_thread_ID_is_valid(ID_var) \
    361         (MHD_THREAD_ID_NATIVE_VALUE_INVALID_ != (ID_var))
    362 /**
    363  * Get the native ID value from the @a ID_var variable
    364  */
    365 #  define mhd_thread_ID_get_native(ID_var) \
    366         (ID_var)
    367 /**
    368  * Check whether the @a ID_var variable is equal current thread
    369  */
    370 #  define mhd_thread_ID_is_current_thread(ID_var) \
    371         mhd_thread_ID_native_is_current_thread (ID_var)
    372 #endif /* MHD_THREAD_ID_NATIVE_INVALID_ */
    373 
    374 /**
    375  * Set current thread ID in the variable pointed by the @a ID_ptr
    376  */
    377 #  define mhd_thread_ID_set_current_thread(ID_ptr) \
    378         mhd_thread_ID_set_native ((ID_ptr),mhd_thread_ID_native_current ())
    379 
    380 
    381 #if defined(mhd_THREADS_KIND_POSIX)
    382 #  if defined(mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID) && \
    383   ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
    384 #    error \
    385   MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined
    386 #  elif ! defined(mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID) && \
    387   defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
    388 #    error \
    389   MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined
    390 #  endif
    391 #endif /* mhd_THREADS_KIND_POSIX */
    392 
    393 /* When staring a new thread, the kernel (and thread implementation) may
    394  * pause the calling (initial) thread and start the new thread.
    395  * If thread identifier is assigned to variable in the initial thread then
    396  * the value of the identifier variable will be undefined in the new thread
    397  * until the initial thread continue processing.
    398  * However, it is also possible that the new thread created, but not executed
    399  * for some time while the initial thread continue execution. In this case any
    400  * variable assigned in the new thread will be undefined for some time until
    401  * they really processed by the new thread.
    402  * To avoid data races, a special structure mhd_thread_handle_ID is used.
    403  * The "handle" is assigned by calling (initial) thread and should be always
    404  * defined when checked in the initial thread.
    405  * The "ID" is assigned by the new thread and should be always defined when
    406  * checked inside the new thread.
    407  */
    408 /* Depending on implementation, pthread_create() MAY set thread ID into
    409  * provided pointer and after it start thread OR start thread and after
    410  * it set thread ID. In the latter case, to avoid data races, additional
    411  * pthread_self() call is required in thread routine. If some platform
    412  * is known for setting thread ID BEFORE starting thread macro
    413  * MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD could be defined
    414  * to save some resources. */
    415 
    416 /* #define MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 1 */
    417 
    418 /* * handle - must be valid when other thread knows that particular thread
    419      is started.
    420    * ID     - must be valid when code is executed inside thread */
    421 #if defined(mhd_THREADS_KIND_POSIX) && \
    422   defined(MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD) && \
    423   defined(mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID) && \
    424   defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) && \
    425   defined(mhd_thread_handle_get_native_ptr)
    426 union mhd_thread_handle_ID_
    427 {
    428   mhd_thread_handle handle;    /**< To be used in other threads */
    429   mhd_thread_ID ID;            /**< To be used in the thread itself */
    430 };
    431 typedef union mhd_thread_handle_ID_ mhd_thread_handle_ID;
    432 #  define MHD_THREAD_HANDLE_ID_IS_UNION 1
    433 #else  /* !mhd_THREADS_KIND_POSIX
    434           || !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
    435           || !mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID
    436           || !MHD_THREAD_ID_NATIVE_VALUE_INVALID_
    437           || !mhd_thread_handle_get_native_ptr */
    438 struct mhd_thread_handle_ID_
    439 {
    440   mhd_thread_handle handle;    /**< To be used in other threads */
    441   mhd_thread_ID ID;            /**< To be used in the thread itself */
    442 };
    443 typedef struct mhd_thread_handle_ID_ mhd_thread_handle_ID;
    444 #endif /* !mhd_THREADS_KIND_POSIX
    445           || !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
    446           || !mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID
    447           || !MHD_THREAD_ID_NATIVE_VALUE_INVALID_
    448           || !mhd_thread_handle_get_native_ptr */
    449 
    450 /**
    451  * Set the mhd_thread_handle_ID to the invalid value
    452  */
    453 #define mhd_thread_handle_ID_set_invalid(hndl_id_ptr) \
    454         (mhd_thread_handle_set_invalid (&((hndl_id_ptr)->handle)), \
    455          mhd_thread_ID_set_invalid (&((hndl_id_ptr)->ID)))
    456 
    457 /**
    458  * Check whether the thread handle is valid.
    459  * To be used in threads other then the thread specified by the @a hndl_id.
    460  */
    461 #define mhd_thread_handle_ID_is_valid_handle(hndl_id) \
    462         mhd_thread_handle_is_valid ((hndl_id).handle)
    463 
    464 /**
    465  * Set the native handle in the variable pointed by the @a hndl_id_ptr
    466  * to the @a native_val value
    467  */
    468 #define mhd_thread_handle_ID_set_native_handle(hndl_id_ptr,native_val) \
    469         mhd_thread_handle_set_native (&((hndl_id_ptr)->handle),native_val)
    470 
    471 #if defined(mhd_thread_handle_get_native_ptr)
    472 /**
    473  * Get the pointer to the native handle stored the variable pointed by
    474  * the @a hndl_id_ptr
    475  * @note This macro could not available if direct manipulation of
    476  *       the native handle is not possible
    477  */
    478 #  define mhd_thread_handle_ID_get_native_handle_ptr(hndl_id_ptr) \
    479         mhd_thread_handle_get_native_ptr (&((hndl_id_ptr)->handle))
    480 #endif /* mhd_thread_handle_get_native_ptr */
    481 
    482 /**
    483  * Get the native thread handle from the mhd_thread_handle_ID variable.
    484  */
    485 #define mhd_thread_handle_ID_get_native_handle(hndl_id) \
    486         mhd_thread_handle_get_native ((hndl_id).handle)
    487 
    488 /**
    489  * Check whether the thread ID is valid.
    490  * To be used in the thread itself.
    491  */
    492 #define mhd_thread_handle_ID_is_valid_ID(hndl_id) \
    493         mhd_thread_ID_is_valid ((hndl_id).ID)
    494 
    495 #if defined(MHD_THREAD_HANDLE_ID_IS_UNION)
    496 #  if defined(mhd_THREADS_KIND_W32)
    497 #    error mhd_thread_handle_ID cannot be a union with W32 threads
    498 #  endif /* mhd_THREADS_KIND_W32 */
    499 /**
    500  * Set current thread ID in the variable pointed by the @a hndl_id_ptr
    501  */
    502 #  define mhd_thread_handle_ID_set_current_thread_ID(hndl_id_ptr) (void) 0
    503 #else  /* ! MHD_THREAD_HANDLE_ID_IS_UNION */
    504 /**
    505  * Set current thread ID in the variable pointed by the @a hndl_id_ptr
    506  */
    507 #  define mhd_thread_handle_ID_set_current_thread_ID(hndl_id_ptr) \
    508         mhd_thread_ID_set_current_thread (&((hndl_id_ptr)->ID))
    509 #endif /* ! MHD_THREAD_HANDLE_ID_IS_UNION */
    510 
    511 /**
    512  * Check whether provided thread ID matches current thread.
    513  * @param ID thread ID to match
    514  * @return nonzero on match, zero otherwise
    515  */
    516 #define mhd_thread_handle_ID_is_current_thread(hndl_id) \
    517         mhd_thread_ID_is_current_thread ((hndl_id).ID)
    518 
    519 /**
    520  * Wait until specified thread is ended and free thread handle on success.
    521  * @param hndl_id_ handle with ID to watch
    522  * @return nonzero on success, zero otherwise
    523  */
    524 #define mhd_thread_handle_ID_join_thread(hndl_id) \
    525         mhd_join_thread (mhd_thread_handle_ID_get_native_handle (hndl_id))
    526 
    527 
    528 /**
    529  * Create a thread and set the attributes according to our options.
    530  *
    531  * If thread is created, thread handle must be freed by mhd_join_thread().
    532  *
    533  * @param handle_id     handle to initialise
    534  * @param stack_size    size of stack for new thread, 0 for default
    535  * @param start_routine main function of thread
    536  * @param arg argument  for start_routine
    537  * @return non-zero on success; zero otherwise (with errno set)
    538  */
    539 bool
    540 mhd_create_thread (mhd_thread_handle_ID *handle_id,
    541                    size_t stack_size,
    542                    mhd_THREAD_START_ROUTINE start_routine,
    543                    void *arg);
    544 
    545 #ifndef mhd_USE_THREAD_NAME
    546 #define mhd_create_named_thread(t,n,s,r,a) mhd_create_thread ((t),(s),(r),(a))
    547 #else  /* mhd_USE_THREAD_NAME */
    548 /**
    549  * Create a named thread and set the attributes according to our options.
    550  *
    551  * @param handle_id     handle to initialise
    552  * @param thread_name   name for new thread
    553  * @param stack_size    size of stack for new thread, 0 for default
    554  * @param start_routine main function of thread
    555  * @param arg argument  for start_routine
    556  * @return non-zero on success; zero otherwise
    557  */
    558 bool
    559 mhd_create_named_thread (mhd_thread_handle_ID *handle_id,
    560                          const char *thread_name,
    561                          size_t stack_size,
    562                          mhd_THREAD_START_ROUTINE start_routine,
    563                          void *arg);
    564 
    565 #endif /* mhd_USE_THREAD_NAME */
    566 
    567 #if ! defined(mhd_SEND_SPIPE_SUPPRESS_NEEDED)
    568 #  define mhd_thread_block_sigpipe() ((void) 0)
    569 #else
    570 #  ifdef HAVE_PTHREAD_SIGMASK
    571 /**
    572  * Block a SIGPIPE signal in the current thread
    573  *
    574  * @return 'true' on success,
    575  *         'false' otherwise
    576  */
    577 MHD_INTERNAL bool
    578 mhd_thread_block_sigpipe (void);
    579 
    580 /**
    581  * Indicates that function #mhd_thread_block_sigpipe() is available
    582  */
    583 #    define mhd_HAVE_MHD_THREAD_BLOCK_SIGPIPE   1
    584 #  endif
    585 #endif
    586 #endif /* ! MHD_THREADS_H */