libmicrohttpd2

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

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 */