libmicrohttpd2

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

mhd_locks.h (10856B)


      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-2026 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 #    define mhd_MUTEX_IMPLEMENTED       1
     68 #    include <pthread.h>
     69 #    include "sys_null_macro.h"
     70 #  endif
     71 
     72 #  if !defined(mhd_MUTEX_IMPLEMENTED) && defined(mhd_THREADS_KIND_W32)
     73 #    include "sys_w32_ver.h"
     74 /* Define MHD_NO_W32_SRWLOCKS_MUTEX to force use critical section on W32 */
     75 #    if _WIN32_WINNT >= 0x0600 /* Vista or later */ && \
     76   !defined(MHD_NO_W32_SRWLOCKS_MUTEX)
     77 #      include "mhd_locksrw.h"
     78 #      if defined(mhd_LOCKRW_KIND_W32_SRW) && !defined(mhd_LOCKRW_KIND_MUTEX)
     79 /**
     80  * The mutex is W32 SRW lock
     81  */
     82 #        define mhd_MUTEX_KIND_W32_SRW  1
     83 #        define mhd_MUTEX_KIND_LOCKRW   1
     84 #        define mhd_MUTEX_IMPLEMENTED   1
     85 #      endif
     86 #    endif
     87 #    ifndef mhd_MUTEX_IMPLEMENTED
     88 /**
     89  * The mutex is W32 Critical Section
     90  */
     91 #      define mhd_MUTEX_KIND_W32_CS     1
     92 #      define mhd_MUTEX_IMPLEMENTED     1
     93 #      if 0 /* _WIN32_WINNT >= 0x0602 */ /* Win8 or later */
     94 /* This include does not work as _ARM_ or _AMD64_ macros
     95            are missing */
     96 #        include <synchapi.h>
     97 #      else
     98 #        include <windows.h>
     99 #      endif
    100 #    endif
    101 #  endif
    102 
    103 #  ifndef mhd_MUTEX_IMPLEMENTED
    104 #    include "mhd_locksrw.h"
    105 #    if defined(mhd_LOCKRW_IMPLEMENTED) && !defined(mhd_LOCKRW_KIND_MUTEX)
    106 /**
    107  * The mutex is RW-lock
    108  */
    109 #      define mhd_MUTEX_KIND_LOCKRW   1
    110 #      define mhd_MUTEX_IMPLEMENTED   1
    111 #    endif
    112 #  endif
    113 
    114 #  ifndef mhd_MUTEX_IMPLEMENTED
    115 #    error No base mutex API is available.
    116 #  endif
    117 
    118 /* Sanity check */
    119 #  ifdef mhd_MUTEX_KIND_PTHREAD
    120 #    ifndef mhd_MUTEX_HAS_ONE_IMPLEMENTATION
    121 #      define mhd_MUTEX_HAS_ONE_IMPLEMENTATION  1
    122 #    else
    123 #      error Multiple mutex implementations are enabled simultaneously
    124 #    endif
    125 #  endif
    126 #  ifdef mhd_MUTEX_KIND_LOCKRW
    127 #    ifndef mhd_MUTEX_HAS_ONE_IMPLEMENTATION
    128 #      define mhd_MUTEX_HAS_ONE_IMPLEMENTATION  1
    129 #    else
    130 #      error Multiple mutex implementations are enabled simultaneously
    131 #    endif
    132 #  endif
    133 #  ifdef mhd_MUTEX_KIND_W32_CS
    134 #    ifndef mhd_MUTEX_HAS_ONE_IMPLEMENTATION
    135 #      define mhd_MUTEX_HAS_ONE_IMPLEMENTATION  1
    136 #    else
    137 #      error Multiple mutex implementations are enabled simultaneously
    138 #    endif
    139 #  endif
    140 #  ifndef mhd_MUTEX_HAS_ONE_IMPLEMENTATION
    141 #    error Not all mutex kinds were checked
    142 #  endif
    143 #  undef mhd_MUTEX_HAS_ONE_IMPLEMENTATION
    144 
    145 #  include "mhd_panic.h"
    146 
    147 #  if defined(mhd_MUTEX_KIND_PTHREAD)
    148 typedef pthread_mutex_t mhd_mutex;
    149 #  elif defined(mhd_MUTEX_KIND_W32_CS)
    150 typedef CRITICAL_SECTION mhd_mutex;
    151 #  elif defined(mhd_MUTEX_KIND_LOCKRW)
    152 typedef mhd_lockrw mhd_mutex;
    153 #  endif
    154 
    155 /**
    156  * Initialise a new mutex.
    157  * @param pmutex the pointer to the mutex
    158  * @return nonzero on success, zero otherwise
    159  */
    160 #  if defined(mhd_MUTEX_KIND_PTHREAD)
    161 #    define mhd_mutex_init(pmutex) (0 == pthread_mutex_init((pmutex), NULL))
    162 #  elif defined(mhd_MUTEX_KIND_W32_CS)
    163 #    if _WIN32_WINNT < 0x0600
    164 /* Before Vista */
    165 #      define mhd_mutex_init(pmutex) \
    166               (InitializeCriticalSectionAndSpinCount((pmutex), 0))
    167 #    else
    168 /* The function always succeed starting from Vista */
    169 #      define mhd_mutex_init(pmutex) \
    170               (((void) InitializeCriticalSection(pmutex)), ! 0)
    171 #    endif
    172 #  elif defined(mhd_MUTEX_KIND_LOCKRW)
    173 #    define mhd_mutex_init(pmutex) mhd_lockrw_init((pmutex))
    174 #  else
    175 #    error Mutex implementation is missing
    176 #  endif
    177 
    178 /**
    179  * Initialise a new mutex for short locks.
    180  *
    181  * Initialised mutex is optimised for locks held only for very short period of
    182  * time. It should be used when only a single or just a few variables are
    183  * modified under the lock.
    184  *
    185  * @param pmutex the pointer to the mutex
    186  * @return nonzero on success, zero otherwise
    187  */
    188 #  ifdef mhd_MUTEX_KIND_W32_CS
    189 #    if _WIN32_WINNT < 0x0600
    190 /* Before Vista */
    191 #      define mhd_mutex_init_short(pmutex) \
    192               (InitializeCriticalSectionAndSpinCount((pmutex), 128))
    193 #    else
    194 /* The function always succeed starting from Vista */
    195 #      define mhd_mutex_init_short(pmutex) \
    196          ((void) InitializeCriticalSectionAndSpinCount((pmutex), 128), ! 0)
    197 #    endif
    198 #  endif
    199 
    200 #  ifndef mhd_mutex_init_short
    201 #    define mhd_mutex_init_short(pmutex) mhd_mutex_init ((pmutex))
    202 #  endif
    203 
    204 /**
    205  * The value to statically initialise mutex
    206  */
    207 #  if defined(mhd_MUTEX_KIND_PTHREAD)
    208 #    if !defined(NDEBUG) && defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)
    209 #      define mhd_MUTEX_INITIALISER_STAT \
    210               PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
    211 #    elif defined(PTHREAD_MUTEX_INITIALIZER)
    212 #      define mhd_MUTEX_INITIALISER_STAT       PTHREAD_MUTEX_INITIALIZER
    213 #    endif
    214 #  elif defined(mhd_MUTEX_KIND_LOCKRW)
    215 #    if defined(mhd_LOCKRW_INITIALISER_STAT)
    216 #      define mhd_MUTEX_INITIALISER_STAT       mhd_LOCKRW_INITIALISER_STAT
    217 #    endif
    218 #  endif
    219 
    220 #  ifdef mhd_MUTEX_INITIALISER_STAT
    221 /**
    222  *  Define static mutex and statically initialise it.
    223  */
    224 #    define mhd_MUTEX_STATIC_DEFN_INIT(m) \
    225             static mhd_mutex m = mhd_MUTEX_INITIALISER_STAT
    226 #  endif
    227 
    228 /**
    229  * Destroy previously initialised mutex.
    230  * @param pmutex the pointer to the mutex
    231  * @return nonzero on success, zero otherwise
    232  */
    233 #  if defined(mhd_MUTEX_KIND_PTHREAD)
    234 #    define mhd_mutex_destroy(pmutex) (0 == pthread_mutex_destroy((pmutex)))
    235 #  elif defined(mhd_MUTEX_KIND_W32_CS)
    236 #    define mhd_mutex_destroy(pmutex) (DeleteCriticalSection((pmutex)), ! 0)
    237 #  elif defined(mhd_MUTEX_KIND_LOCKRW)
    238 #    define mhd_mutex_destroy(pmutex) mhd_lockrw_destroy((pmutex))
    239 #  else
    240 #    error Mutex implementation is missing
    241 #  endif
    242 
    243 
    244 /**
    245  * Acquire a lock on previously initialised mutex.
    246  * If the mutex was already locked by other thread, function blocks until
    247  * the mutex becomes available.
    248  * @param pmutex the pointer to the mutex
    249  * @return nonzero on success, zero otherwise
    250  */
    251 #  if defined(mhd_MUTEX_KIND_PTHREAD)
    252 #    define mhd_mutex_lock(pmutex) (0 == pthread_mutex_lock((pmutex)))
    253 #  elif defined(mhd_MUTEX_KIND_W32_CS)
    254 #    define mhd_mutex_lock(pmutex) (EnterCriticalSection((pmutex)), ! 0)
    255 #  elif defined(mhd_MUTEX_KIND_LOCKRW)
    256 #    define mhd_mutex_lock(pmutex) mhd_lockrw_w_lock((pmutex))
    257 #  else
    258 #    error Mutex implementation is missing
    259 #  endif
    260 
    261 /**
    262  * Unlock previously locked mutex.
    263  * @param pmutex the pointer to the mutex
    264  * @return nonzero on success, zero otherwise
    265  */
    266 #  if defined(mhd_MUTEX_KIND_PTHREAD)
    267 #    define mhd_mutex_unlock(pmutex) (0 == pthread_mutex_unlock((pmutex)))
    268 #  elif defined(mhd_MUTEX_KIND_W32_CS)
    269 #    define mhd_mutex_unlock(pmutex) (LeaveCriticalSection((pmutex)), ! 0)
    270 #  elif defined(mhd_MUTEX_KIND_LOCKRW)
    271 #    define mhd_mutex_unlock(pmutex) mhd_lockrw_w_unlock((pmutex))
    272 #  else
    273 #    error Mutex implementation is missing
    274 #  endif
    275 
    276 /**
    277  * Destroy previously initialised mutex and abort execution if error is
    278  * detected.
    279  * @param pmutex the pointer to the mutex
    280  */
    281 #  define mhd_mutex_destroy_chk(pmutex) do {        \
    282             if (! mhd_mutex_destroy((pmutex)))       \
    283               MHD_PANIC ("Failed to destroy mutex."); \
    284           } while (0)
    285 
    286 /**
    287  * Acquire a lock on previously initialised mutex.
    288  * If the mutex was already locked by other thread, function blocks until
    289  * the mutex becomes available.
    290  * If error is detected, execution is aborted.
    291  * @param pmutex the pointer to the mutex
    292  */
    293 #  define mhd_mutex_lock_chk(pmutex) do {        \
    294             if (! mhd_mutex_lock((pmutex)))       \
    295               MHD_PANIC ("Failed to lock mutex."); \
    296           } while (0)
    297 
    298 /**
    299  * Unlock previously locked mutex.
    300  * If error is detected, execution is aborted.
    301  * @param pmutex the pointer to the mutex
    302  */
    303 #  define mhd_mutex_unlock_chk(pmutex) do {        \
    304             if (! mhd_mutex_unlock((pmutex)))       \
    305               MHD_PANIC ("Failed to unlock mutex."); \
    306           } while (0)
    307 
    308 #else  /* ! MHD_SUPPORT_THREADS */
    309 
    310 #  define mhd_mutex_init(ignored) (! 0)
    311 #  define mhd_mutex_init_short(ignored) (! 0)
    312 #  define mhd_MUTEX_INITIALISER_STAT /* empty */
    313 #  define mhd_MUTEX_STATIC_DEFN_INIT(ignored) /* nothing */
    314 #  define mhd_mutex_destroy(ignored) (! 0)
    315 #  define mhd_mutex_destroy_chk(ignored) ((void) 0)
    316 #  define mhd_mutex_lock(ignored) (! 0)
    317 #  define mhd_mutex_lock_chk(ignored) ((void) 0)
    318 #  define mhd_mutex_unlock(ignored) (! 0)
    319 #  define mhd_mutex_unlock_chk(ignored) ((void) 0)
    320 
    321 #endif /* ! MHD_SUPPORT_THREADS */
    322 
    323 #endif /* ! MHD_LOCKS_H */