1 /* 2 This file is part of libmicrohttpd 3 Copyright (C) 2016 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 21 /** 22 * @file microhttpd/mhd_threads.h 23 * @brief Header for platform-independent threads abstraction 24 * @author Karlson2k (Evgeny Grin) 25 * 26 * Provides basic abstraction for threads. 27 * Any functions can be implemented as macro on some platforms 28 * unless explicitly marked otherwise. 29 * Any function argument can be skipped in macro, so avoid 30 * variable modification in function parameters. 31 * 32 * @warning Unlike pthread functions, most of functions return 33 * nonzero on success. 34 */ 35 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 #else /* ! HAVE_STDDEF_H */ 43 # include <stdlib.h> /* for size_t */ 44 #endif /* ! HAVE_STDDEF_H */ 45 46 #if defined(MHD_USE_POSIX_THREADS) 47 # undef HAVE_CONFIG_H 48 # include <pthread.h> 49 # define HAVE_CONFIG_H 1 50 #elif defined(MHD_USE_W32_THREADS) 51 # ifndef WIN32_LEAN_AND_MEAN 52 # define WIN32_LEAN_AND_MEAN 1 53 # endif /* !WIN32_LEAN_AND_MEAN */ 54 # include <windows.h> 55 #else 56 # error No threading API is available. 57 #endif 58 59 #ifndef MHD_NO_THREAD_NAMES 60 # if defined(MHD_USE_POSIX_THREADS) 61 # if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \ 62 defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD) || \ 63 defined(HAVE_PTHREAD_SETNAME_NP_DARWIN) || \ 64 defined(HAVE_PTHREAD_SETNAME_NP_NETBSD) || \ 65 defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) || \ 66 defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI) 67 # define MHD_USE_THREAD_NAME_ 68 # endif /* HAVE_PTHREAD_SETNAME_NP */ 69 # elif defined(MHD_USE_W32_THREADS) 70 # ifdef _MSC_FULL_VER 71 /* Thread names only available with VC compiler */ 72 # define MHD_USE_THREAD_NAME_ 73 # endif /* _MSC_FULL_VER */ 74 # endif 75 #endif 76 77 #if defined(MHD_USE_POSIX_THREADS) 78 typedef pthread_t MHD_thread_handle_; 79 #elif defined(MHD_USE_W32_THREADS) 80 typedef HANDLE MHD_thread_handle_; 81 #endif 82 83 #if defined(MHD_USE_POSIX_THREADS) 84 # define MHD_THRD_RTRN_TYPE_ void* 85 # define MHD_THRD_CALL_SPEC_ 86 #elif defined(MHD_USE_W32_THREADS) 87 # define MHD_THRD_RTRN_TYPE_ unsigned 88 # define MHD_THRD_CALL_SPEC_ __stdcall 89 #endif 90 91 #if defined(MHD_USE_POSIX_THREADS) 92 typedef pthread_t MHD_thread_ID_; 93 #elif defined(MHD_USE_W32_THREADS) 94 typedef DWORD MHD_thread_ID_; 95 #endif 96 97 /* Depending on implementation, pthread_create() MAY set thread ID into 98 * provided pointer and after it start thread OR start thread and after 99 * if set thread ID. In latter case, to avoid data races, additional 100 * pthread_self() call is required in thread routine. Is some platform 101 * is known for setting thread ID BEFORE starting thread macro 102 * MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD could be defined 103 * to save some resources. */ 104 #if defined(MHD_USE_POSIX_THREADS) 105 # ifdef MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 106 union _MHD_thread_handle_ID_ 107 { 108 MHD_thread_handle_ handle; /**< To be used in other threads */ 109 MHD_thread_ID_ ID; /**< To be used in thread itself */ 110 }; 111 typedef union _MHD_thread_handle_ID_ MHD_thread_handle_ID_; 112 # else /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ 113 struct _MHD_thread_handle_ID_ 114 { 115 MHD_thread_handle_ handle; /**< To be used in other threads */ 116 MHD_thread_ID_ ID; /**< To be used in thread itself */ 117 }; 118 typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_; 119 # endif /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ 120 #elif defined(MHD_USE_W32_THREADS) 121 struct _MHD_thread_handle_ID_ 122 { 123 MHD_thread_handle_ handle; /**< To be used in other threads */ 124 MHD_thread_ID_ ID; /**< To be used in thread itself */ 125 }; 126 typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_; 127 #endif 128 129 #if defined(MHD_USE_POSIX_THREADS) 130 /** 131 * Wait until specified thread is ended and free thread handle on success. 132 * @param thread handle to watch 133 * @return nonzero on success, zero otherwise 134 */ 135 #define MHD_join_thread_(thread) (! pthread_join ((thread), NULL)) 136 #elif defined(MHD_USE_W32_THREADS) 137 /** 138 * Wait until specified thread is ended and free thread handle on success. 139 * @param thread handle to watch 140 * @return nonzero on success, zero otherwise 141 */ 142 #define MHD_join_thread_(thread) (WAIT_OBJECT_0 == WaitForSingleObject ( \ 143 (thread), INFINITE) ? (CloseHandle ( \ 144 (thread)), ! 0) : \ 145 0) 146 #endif 147 148 #if defined(MHD_USE_POSIX_THREADS) 149 /** 150 * Check whether provided thread ID match current thread. 151 * @param ID thread ID to match 152 * @return nonzero on match, zero otherwise 153 */ 154 #define MHD_thread_ID_match_current_(ID) (pthread_equal ((ID), pthread_self ())) 155 #elif defined(MHD_USE_W32_THREADS) 156 /** 157 * Check whether provided thread ID match current thread. 158 * @param ID thread ID to match 159 * @return nonzero on match, zero otherwise 160 */ 161 #define MHD_thread_ID_match_current_(ID) (GetCurrentThreadId () == (ID)) 162 #endif 163 164 #if defined(MHD_USE_POSIX_THREADS) 165 # ifdef MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 166 /** 167 * Initialise thread ID. 168 * @param thread_handle_ID_ptr pointer to thread handle-ID 169 */ 170 #define MHD_thread_init_(thread_handle_ID_ptr) (void) 0 171 # else /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ 172 /** 173 * Initialise thread ID. 174 * @param thread_handle_ID_ptr pointer to thread handle-ID 175 */ 176 #define MHD_thread_init_(thread_handle_ID_ptr) ((thread_handle_ID_ptr)->ID = \ 177 pthread_self ()) 178 # endif /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ 179 #elif defined(MHD_USE_W32_THREADS) 180 /** 181 * Initialise thread ID. 182 * @param thread_handle_ID_ptr pointer to thread handle-ID 183 */ 184 #define MHD_thread_init_(thread_handle_ID_ptr) ((thread_handle_ID_ptr)->ID = \ 185 GetCurrentThreadId ()) 186 #endif 187 188 /** 189 * Signature of main function for a thread. 190 * 191 * @param cls closure argument for the function 192 * @return termination code from the thread 193 */ 194 typedef MHD_THRD_RTRN_TYPE_ 195 (MHD_THRD_CALL_SPEC_ *MHD_THREAD_START_ROUTINE_)(void *cls); 196 197 198 /** 199 * Create a thread and set the attributes according to our options. 200 * 201 * If thread is created, thread handle must be freed by MHD_join_thread_(). 202 * 203 * @param thread handle to initialize 204 * @param stack_size size of stack for new thread, 0 for default 205 * @param start_routine main function of thread 206 * @param arg argument for start_routine 207 * @return non-zero on success; zero otherwise 208 */ 209 int 210 MHD_create_thread_ (MHD_thread_handle_ID_ *thread, 211 size_t stack_size, 212 MHD_THREAD_START_ROUTINE_ start_routine, 213 void *arg); 214 215 #ifndef MHD_USE_THREAD_NAME_ 216 #define MHD_create_named_thread_(t,n,s,r,a) MHD_create_thread_ ((t),(s),(r),(a)) 217 #else /* MHD_USE_THREAD_NAME_ */ 218 /** 219 * Create a named thread and set the attributes according to our options. 220 * 221 * @param thread handle to initialize 222 * @param thread_name name for new thread 223 * @param stack_size size of stack for new thread, 0 for default 224 * @param start_routine main function of thread 225 * @param arg argument for start_routine 226 * @return non-zero on success; zero otherwise 227 */ 228 int 229 MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread, 230 const char *thread_name, 231 size_t stack_size, 232 MHD_THREAD_START_ROUTINE_ start_routine, 233 void *arg); 234 235 #endif /* MHD_USE_THREAD_NAME_ */ 236 237 #endif /* ! MHD_THREADS_H */ 238