mhd_locks.h (10529B)
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_locks.h 41 * @brief Header for platform-independent locks abstraction 42 * @author Karlson2k (Evgeny Grin) 43 * @author Christian Grothoff 44 * 45 * Provides basic abstraction for locks/mutex. 46 * Any functions can be implemented as macro on some platforms 47 * unless explicitly marked otherwise. 48 * Any function argument can be skipped in macro, so avoid 49 * variable modification in function parameters. 50 * 51 * @warning Unlike pthread functions, most of functions return 52 * nonzero on success. 53 */ 54 55 #ifndef MHD_LOCKS_H 56 #define MHD_LOCKS_H 1 57 58 #include "mhd_sys_options.h" 59 60 #ifdef MHD_SUPPORT_THREADS 61 62 #if defined(HAVE_PTHREAD_H) && defined(mhd_THREADS_KIND_POSIX) 63 /** 64 * The mutex is POSIX Threads' mutex 65 */ 66 # define mhd_MUTEX_KIND_PTHREAD 1 67 # include <pthread.h> 68 # include "sys_null_macro.h" 69 #elif defined(mhd_THREADS_KIND_W32) 70 # include "sys_w32_ver.h" 71 # if _WIN32_WINNT >= 0x0600 /* Vista or later */ && \ 72 ! defined (MHD_NO_W32_SRWLOCKS) 73 /** 74 * The mutex is W32 SRW lock 75 */ 76 # define mhd_MUTEX_KIND_W32_SRW 1 77 # else 78 /** 79 * The mutex is W32 Critical Section 80 */ 81 # define mhd_MUTEX_KIND_W32_CS 1 82 # endif 83 # if 0 /* _WIN32_WINNT >= 0x0602 */ /* Win8 or later */ 84 /* This include does not work as _ARM_ or _AMD64_ macros 85 are missing */ 86 # include <synchapi.h> 87 # else 88 # include <windows.h> 89 # endif 90 #else 91 #error No base mutex API is available. 92 #endif 93 94 #include "mhd_panic.h" 95 96 #if defined(mhd_MUTEX_KIND_PTHREAD) 97 typedef pthread_mutex_t mhd_mutex; 98 #elif defined(mhd_MUTEX_KIND_W32_SRW) 99 typedef SRWLOCK mhd_mutex; 100 #elif defined(mhd_MUTEX_KIND_W32_CS) 101 typedef CRITICAL_SECTION mhd_mutex; 102 #endif 103 104 #if defined(mhd_MUTEX_KIND_PTHREAD) 105 /** 106 * Initialise a new mutex. 107 * @param pmutex the pointer to the mutex 108 * @return nonzero on success, zero otherwise 109 */ 110 # define mhd_mutex_init(pmutex) (0 == pthread_mutex_init ((pmutex), NULL)) 111 #elif defined(mhd_MUTEX_KIND_W32_SRW) 112 /** 113 * Initialise a new mutex. 114 * @param pmutex the pointer to the mutex 115 * @return always nonzero (success) 116 */ 117 # define mhd_mutex_init(pmutex) (InitializeSRWLock ((pmutex)), ! 0) 118 #elif defined(mhd_MUTEX_KIND_W32_CS) 119 # if _WIN32_WINNT < 0x0600 120 /* Before Vista */ 121 /** 122 * Initialise a new mutex. 123 * @param pmutex the pointer to the mutex 124 * @return nonzero on success, zero otherwise 125 */ 126 # define mhd_mutex_init(pmutex) \ 127 (InitializeCriticalSectionAndSpinCount ((pmutex), 0)) 128 # else 129 /* The function always succeed starting from Vista */ 130 /** 131 * Initialise a new mutex. 132 * @param pmutex the pointer to the mutex 133 * @return nonzero on success, zero otherwise 134 */ 135 # define mhd_mutex_init(pmutex) \ 136 (((void) InitializeCriticalSection (pmutex)), ! 0) 137 # endif 138 #endif 139 140 #ifdef mhd_MUTEX_KIND_W32_CS 141 # if _WIN32_WINNT < 0x0600 142 /* Before Vista */ 143 /** 144 * Initialise a new mutex for short locks. 145 * 146 * Initialised mutex is optimised for locks held only for very short period of 147 * time. It should be used when only a single or just a few variables are 148 * modified under the lock. 149 * 150 * @param pmutex the pointer to the mutex 151 * @return nonzero on success, zero otherwise 152 */ 153 # define mhd_mutex_init_short(pmutex) \ 154 (InitializeCriticalSectionAndSpinCount ((pmutex), 128)) 155 # else 156 /* The function always succeed starting from Vista */ 157 /** 158 * Initialise a new mutex for short locks. 159 * 160 * Initialised mutex is optimised for locks held only for very short period of 161 * time. It should be used when only a single or just a few variables are 162 * modified under the lock. 163 * 164 * @param pmutex the pointer to the mutex 165 * @return nonzero on success, zero otherwise 166 */ 167 # define mhd_mutex_init_short(pmutex) \ 168 ((void) InitializeCriticalSectionAndSpinCount ((pmutex), 128), ! 0) 169 # endif 170 #endif 171 172 #ifndef mhd_mutex_init_short 173 # define mhd_mutex_init_short(pmutex) mhd_mutex_init ((pmutex)) 174 #endif 175 176 #if defined(mhd_MUTEX_KIND_PTHREAD) 177 # if defined(PTHREAD_MUTEX_INITIALIZER) 178 /** 179 * The value to statically initialise mutex 180 */ 181 # define mhd_MUTEX_INITIALISER_STAT PTHREAD_MUTEX_INITIALIZER 182 # endif /* PTHREAD_MUTEX_INITIALIZER */ 183 #elif defined(mhd_MUTEX_KIND_W32_SRW) 184 # if defined(SRWLOCK_INIT) 185 /** 186 * The value to statically initialise mutex 187 */ 188 # define mhd_MUTEX_INITIALISER_STAT SRWLOCK_INIT 189 # endif 190 #endif 191 192 #ifdef mhd_MUTEX_INITIALISER_STAT 193 /** 194 * Define static mutex and statically initialise it. 195 */ 196 # define mhd_MUTEX_STATIC_DEFN_INIT(m) \ 197 static mhd_mutex m = mhd_MUTEX_INITIALISER_STAT 198 #endif 199 200 #if defined(mhd_MUTEX_KIND_PTHREAD) 201 /** 202 * Destroy previously initialised mutex. 203 * @param pmutex the pointer to the mutex 204 * @return nonzero on success, zero otherwise 205 */ 206 # define mhd_mutex_destroy(pmutex) (0 == pthread_mutex_destroy ((pmutex))) 207 #elif defined(mhd_MUTEX_KIND_W32_SRW) 208 /** 209 * Destroy (no-op) previously initialised mutex. 210 * @param pmutex the pointer to the mutex 211 * @return always nonzero (success) 212 */ 213 # define mhd_mutex_destroy(pmutex) ((void) (pmutex), ! 0) 214 #elif defined(mhd_MUTEX_KIND_W32_CS) 215 /** 216 * Destroy previously initialised mutex. 217 * @param pmutex the pointer to the mutex 218 * @return always nonzero (success) 219 */ 220 # define mhd_mutex_destroy(pmutex) (DeleteCriticalSection ((pmutex)), ! 0) 221 #endif 222 223 224 #if defined(mhd_MUTEX_KIND_PTHREAD) 225 /** 226 * Acquire a lock on previously initialised mutex. 227 * If the mutex was already locked by other thread, function blocks until 228 * the mutex becomes available. 229 * @param pmutex the pointer to the mutex 230 * @return nonzero on success, zero otherwise 231 */ 232 # define mhd_mutex_lock(pmutex) (0 == pthread_mutex_lock ((pmutex))) 233 #elif defined(mhd_MUTEX_KIND_W32_SRW) 234 /** 235 * Acquire a lock on previously initialised mutex. 236 * If the mutex was already locked by other thread, function blocks until 237 * the mutex becomes available. 238 * @param pmutex the pointer to the mutex 239 * @return always nonzero (success) 240 */ 241 # define mhd_mutex_lock(pmutex) (AcquireSRWLockExclusive ((pmutex)), ! 0) 242 #elif defined(mhd_MUTEX_KIND_W32_CS) 243 /** 244 * Acquire a lock on previously initialised mutex. 245 * If the mutex was already locked by other thread, function blocks until 246 * the mutex becomes available. 247 * @param pmutex the pointer to the mutex 248 * @return always nonzero (success) 249 */ 250 # define mhd_mutex_lock(pmutex) (EnterCriticalSection ((pmutex)), ! 0) 251 #endif 252 253 #if defined(mhd_MUTEX_KIND_PTHREAD) 254 /** 255 * Unlock previously locked mutex. 256 * @param pmutex the pointer to the mutex 257 * @return nonzero on success, zero otherwise 258 */ 259 # define mhd_mutex_unlock(pmutex) (0 == pthread_mutex_unlock ((pmutex))) 260 #elif defined(mhd_MUTEX_KIND_W32_SRW) 261 /** 262 * Acquire a lock on previously initialised mutex. 263 * If the mutex was already locked by other thread, function blocks until 264 * the mutex becomes available. 265 * @param pmutex the pointer to the mutex 266 * @return always nonzero (success) 267 */ 268 # define mhd_mutex_unlock(pmutex) (ReleaseSRWLockExclusive ((pmutex)), ! 0) 269 #elif defined(mhd_MUTEX_KIND_W32_CS) 270 /** 271 * Unlock previously initialised and locked mutex. 272 * @param pmutex pointer to mutex 273 * @return always nonzero (success) 274 */ 275 # define mhd_mutex_unlock(pmutex) (LeaveCriticalSection ((pmutex)), ! 0) 276 #endif 277 278 /** 279 * Destroy previously initialised mutex and abort execution if error is 280 * detected. 281 * @param pmutex the pointer to the mutex 282 */ 283 #define mhd_mutex_destroy_chk(pmutex) do { \ 284 if (! mhd_mutex_destroy (pmutex)) \ 285 MHD_PANIC ("Failed to destroy mutex.\n"); \ 286 } while (0) 287 288 /** 289 * Acquire a lock on previously initialised mutex. 290 * If the mutex was already locked by other thread, function blocks until 291 * the mutex becomes available. 292 * If error is detected, execution is aborted. 293 * @param pmutex the pointer to the mutex 294 */ 295 #define mhd_mutex_lock_chk(pmutex) do { \ 296 if (! mhd_mutex_lock (pmutex)) \ 297 MHD_PANIC ("Failed to lock mutex.\n"); \ 298 } while (0) 299 300 /** 301 * Unlock previously locked mutex. 302 * If error is detected, execution is aborted. 303 * @param pmutex the pointer to the mutex 304 */ 305 #define mhd_mutex_unlock_chk(pmutex) do { \ 306 if (! mhd_mutex_unlock (pmutex)) \ 307 MHD_PANIC ("Failed to unlock mutex.\n"); \ 308 } while (0) 309 310 #else /* ! MHD_SUPPORT_THREADS */ 311 312 # define mhd_mutex_init(ignored) (! 0) 313 # define mhd_mutex_init_short(ignored) (! 0) 314 # define mhd_MUTEX_INITIALISER_STAT /* empty */ 315 # define mhd_MUTEX_STATIC_DEFN_INIT(ignored) /* nothing */ 316 # define mhd_mutex_destroy(ignored) (! 0) 317 # define mhd_mutex_destroy_chk(ignored) ((void) 0) 318 # define mhd_mutex_lock(ignored) (! 0) 319 # define mhd_mutex_lock_chk(ignored) ((void) 0) 320 # define mhd_mutex_unlock(ignored) (! 0) 321 # define mhd_mutex_unlock_chk(ignored) ((void) 0) 322 323 #endif /* ! MHD_SUPPORT_THREADS */ 324 325 #endif /* ! MHD_LOCKS_H */