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 #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 #ifndef MHD_NO_THREAD_NAMES 68 # if defined(MHD_USE_POSIX_THREADS) 69 # if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \ 70 defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD) || \ 71 defined(HAVE_PTHREAD_SETNAME_NP_DARWIN) || \ 72 defined(HAVE_PTHREAD_SETNAME_NP_NETBSD) || \ 73 defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) || \ 74 defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI) 75 # define MHD_USE_THREAD_NAME_ 76 # endif /* HAVE_PTHREAD_SETNAME_NP */ 77 # elif defined(MHD_USE_W32_THREADS) 78 # ifdef _MSC_FULL_VER 79 /* Thread names only available with VC compiler */ 80 # define MHD_USE_THREAD_NAME_ 81 # endif /* _MSC_FULL_VER */ 82 # endif 83 #endif 84 85 #if defined(MHD_USE_POSIX_THREADS) 86 typedef pthread_t MHD_thread_handle_; 87 #elif defined(MHD_USE_W32_THREADS) 88 typedef HANDLE MHD_thread_handle_; 89 #endif 90 91 #if defined(MHD_USE_POSIX_THREADS) 92 # define MHD_THRD_RTRN_TYPE_ void* 93 # define MHD_THRD_CALL_SPEC_ 94 #elif defined(MHD_USE_W32_THREADS) 95 # define MHD_THRD_RTRN_TYPE_ unsigned 96 # define MHD_THRD_CALL_SPEC_ __stdcall 97 #endif 98 99 #if defined(MHD_USE_POSIX_THREADS) 100 typedef pthread_t MHD_thread_ID_; 101 #elif defined(MHD_USE_W32_THREADS) 102 typedef DWORD MHD_thread_ID_; 103 #endif 104 105 /* Depending on implementation, pthread_create() MAY set thread ID into 106 * provided pointer and after it start thread OR start thread and after 107 * it set thread ID. In the latter case, to avoid data races, additional 108 * pthread_self() call is required in thread routine. If some platform 109 * is known for setting thread ID BEFORE starting thread macro 110 * MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD could be defined 111 * to save some resources. */ 112 /* * handle - must be valid when other thread knows that particular thread 113 is started. 114 * ID - must be valid when code is executed inside thread */ 115 #if defined(MHD_USE_POSIX_THREADS) 116 # ifdef MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 117 union _MHD_thread_handle_ID_ 118 { 119 MHD_thread_handle_ handle; /**< To be used in other threads */ 120 MHD_thread_ID_ ID; /**< To be used in thread itself */ 121 }; 122 typedef union _MHD_thread_handle_ID_ MHD_thread_handle_ID_; 123 # else /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ 124 struct _MHD_thread_handle_ID_ 125 { 126 MHD_thread_handle_ handle; /**< To be used in other threads */ 127 MHD_thread_ID_ ID; /**< To be used in thread itself */ 128 }; 129 typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_; 130 # endif /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ 131 #elif defined(MHD_USE_W32_THREADS) 132 struct _MHD_thread_handle_ID_ 133 { 134 MHD_thread_handle_ handle; /**< To be used in other threads */ 135 MHD_thread_ID_ ID; /**< To be used in thread itself */ 136 }; 137 typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_; 138 #endif 139 140 #if defined(MHD_USE_POSIX_THREADS) 141 /** 142 * Wait until specified thread is ended and free thread handle on success. 143 * @param thread handle to watch 144 * @return nonzero on success, zero otherwise 145 */ 146 #define MHD_join_thread_(thread) (! pthread_join ((thread), NULL)) 147 #elif defined(MHD_USE_W32_THREADS) 148 /** 149 * Wait until specified thread is ended and free thread handle on success. 150 * @param thread handle to watch 151 * @return nonzero on success, zero otherwise 152 */ 153 #define MHD_join_thread_(thread) \ 154 ( (WAIT_OBJECT_0 == WaitForSingleObject ( (thread), INFINITE)) ? \ 155 (CloseHandle ( (thread)), ! 0) : 0 ) 156 #endif 157 158 #if defined(MHD_USE_POSIX_THREADS) 159 /** 160 * Check whether provided thread ID match current thread. 161 * @param ID thread ID to match 162 * @return nonzero on match, zero otherwise 163 */ 164 #define MHD_thread_ID_match_current_(pid) \ 165 (pthread_equal ((pid).ID, pthread_self ())) 166 #elif defined(MHD_USE_W32_THREADS) 167 /** 168 * Check whether provided thread ID match current thread. 169 * @param ID thread ID to match 170 * @return nonzero on match, zero otherwise 171 */ 172 #define MHD_thread_ID_match_current_(pid) (GetCurrentThreadId () == (pid).ID) 173 #endif 174 175 #if defined(MHD_USE_POSIX_THREADS) 176 # ifdef MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 177 /** 178 * Initialise thread ID. 179 * @param thread_handle_ID_ptr pointer to thread handle-ID 180 */ 181 #define MHD_thread_init_(thread_handle_ID_ptr) (void) 0 182 # else /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ 183 /** 184 * Initialise thread ID. 185 * @param thread_handle_ID_ptr pointer to thread handle-ID 186 */ 187 #define MHD_thread_init_(thread_handle_ID_ptr) ((thread_handle_ID_ptr)->ID = \ 188 pthread_self ()) 189 # endif /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ 190 #elif defined(MHD_USE_W32_THREADS) 191 /** 192 * Initialise thread ID. 193 * @param thread_handle_ID_ptr pointer to thread handle-ID 194 */ 195 #define MHD_thread_init_(thread_handle_ID_ptr) ((thread_handle_ID_ptr)->ID = \ 196 GetCurrentThreadId ()) 197 #endif 198 199 /** 200 * Signature of main function for a thread. 201 * 202 * @param cls closure argument for the function 203 * @return termination code from the thread 204 */ 205 typedef MHD_THRD_RTRN_TYPE_ 206 (MHD_THRD_CALL_SPEC_ *MHD_THREAD_START_ROUTINE_)(void *cls); 207 208 209 /** 210 * Create a thread and set the attributes according to our options. 211 * 212 * If thread is created, thread handle must be freed by MHD_join_thread_(). 213 * 214 * @param thread handle to initialize 215 * @param stack_size size of stack for new thread, 0 for default 216 * @param start_routine main function of thread 217 * @param arg argument for start_routine 218 * @return non-zero on success; zero otherwise 219 */ 220 int 221 MHD_create_thread_ (MHD_thread_handle_ID_ *thread, 222 size_t stack_size, 223 MHD_THREAD_START_ROUTINE_ start_routine, 224 void *arg); 225 226 #ifndef MHD_USE_THREAD_NAME_ 227 #define MHD_create_named_thread_(t,n,s,r,a) MHD_create_thread_ ((t),(s),(r),(a)) 228 #else /* MHD_USE_THREAD_NAME_ */ 229 /** 230 * Create a named thread and set the attributes according to our options. 231 * 232 * @param thread handle to initialize 233 * @param thread_name name for new thread 234 * @param stack_size size of stack for new thread, 0 for default 235 * @param start_routine main function of thread 236 * @param arg argument for start_routine 237 * @return non-zero on success; zero otherwise 238 */ 239 int 240 MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread, 241 const char *thread_name, 242 size_t stack_size, 243 MHD_THREAD_START_ROUTINE_ start_routine, 244 void *arg); 245 246 #endif /* MHD_USE_THREAD_NAME_ */ 247 248 #endif /* ! MHD_THREADS_H */ 249