libmicrohttpd2

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

commit ca7bb5368b5bd849ba7cfaac530d563e39a47674
parent 9432fca1252e37c192047a831a244392efa955be
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date:   Thu,  6 Aug 2026 18:36:54 +0200

Implemented RW-locks abstraction

Diffstat:
Mconfigure.ac | 42++++++++++++++++++++++++++++++++++++++++++
Msrc/include/microhttpd2.h | 2+-
Msrc/include/microhttpd2_preamble.h.in | 2+-
Msrc/mhd2/Makefile.am | 2+-
Msrc/mhd2/mhd_locks.h | 59+++++++++++++++++++++++++++++++++++++----------------------
Asrc/mhd2/mhd_locksrw.h | 359+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 441 insertions(+), 25 deletions(-)

diff --git a/configure.ac b/configure.ac @@ -2547,6 +2547,48 @@ AX_PTHREAD( ]], [AC_DEFINE([[HAVE_PTHREAD_SIGMASK]],[[1]],[Define to 1 if you have the pthread_sigmask(3) function.])] ) + MHD_CHECK_LINK_RUN([[fo][r pthread RW-locks]],[[mhd_cv_pthread_rwlocks]], + [mhd_cv_pthread_rwlocks="assuming yes"], + [ + AC_LANG_SOURCE([[ +#include <pthread.h> +#if defined(HAVE_STDDEF_H) +# include <stddef.h> /* NULL */ +#elif defined(HAVE_STDLIB_H) +# include <stdlib.h> /* should provide NULL */ +#else +# include <stdio.h> /* should provide NULL */ +#endif + +int main(void) +{ + pthread_rwlock_t pthrwl; + int res; + int res_d; + res = pthread_rwlock_init (&pthrwl, NULL); + if (0 != res) + return res; + res = pthread_rwlock_rdlock (&pthrwl); + if (0 == res) + { + res = pthread_rwlock_unlock (&pthrwl); + if (0 != res) + return res; /* The lock is still held, it cannot be destroyed */ + res = pthread_rwlock_wrlock (&pthrwl); + if (0 == res) + { + res = pthread_rwlock_unlock (&pthrwl); + if (0 != res) + return res; /* The lock is still held, it cannot be destroyed */ + } + } + res_d = pthread_rwlock_destroy (&pthrwl); + return (0 == res) ? res_d : res; +} + ]]) + ], + [AC_DEFINE([[HAVE_PTHREAD_RWLOCKS]],[[1]],[Define to 1 if you have pthread RW-locks functionality.])] + ) CC="$SAVE_CC" AS_UNSET([SAVE_CC]) CFLAGS="${CFLAGS_ac} ${user_CFLAGS}" diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h @@ -1094,7 +1094,7 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode MHD_SC_LISTEN_PORT_INTROSPECTION_UNKNOWN_AF = 50081 , /** - * Failed to initialise mutex. + * Failed to initialise mutex or RW-lock. */ MHD_SC_MUTEX_INIT_FAILURE = 50085 , diff --git a/src/include/microhttpd2_preamble.h.in b/src/include/microhttpd2_preamble.h.in @@ -1094,7 +1094,7 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode MHD_SC_LISTEN_PORT_INTROSPECTION_UNKNOWN_AF = 50081 , /** - * Failed to initialise mutex. + * Failed to initialise mutex or RW-lock. */ MHD_SC_MUTEX_INIT_FAILURE = 50085 , diff --git a/src/mhd2/Makefile.am b/src/mhd2/Makefile.am @@ -59,7 +59,7 @@ libmicrohttpd2_la_SOURCES = \ mhd_dlinked_list.h \ mhd_conn_socket.h mhd_connection.h \ mhd_stream.h \ - mhd_locks.h \ + mhd_locks.h mhd_locksrw.h \ mhd_itc.c mhd_itc.h mhd_itc_types.h \ mhd_mono_clock.c mhd_mono_clock.h \ mempool_funcs.c mempool_funcs.h mempool_types.h \ diff --git a/src/mhd2/mhd_locks.h b/src/mhd2/mhd_locks.h @@ -74,11 +74,15 @@ /* Define MHD_NO_W32_SRWLOCKS_MUTEX to force use critical section on W32 */ # if _WIN32_WINNT >= 0x0600 /* Vista or later */ && \ !defined(MHD_NO_W32_SRWLOCKS_MUTEX) +# include "mhd_locksrw.h" +# if defined(mhd_LOCKRW_KIND_W32_SRW) && !defined(mhd_LOCKRW_KIND_MUTEX) /** * The mutex is W32 SRW lock */ -# define mhd_MUTEX_KIND_W32_SRW 1 -# define mhd_MUTEX_IMPLEMENTED 1 +# define mhd_MUTEX_KIND_W32_SRW 1 +# define mhd_MUTEX_KIND_LOCKRW 1 +# define mhd_MUTEX_IMPLEMENTED 1 +# endif # endif # ifndef mhd_MUTEX_IMPLEMENTED /** @@ -86,13 +90,24 @@ */ # define mhd_MUTEX_KIND_W32_CS 1 # define mhd_MUTEX_IMPLEMENTED 1 -# endif -# if 0 /* _WIN32_WINNT >= 0x0602 */ /* Win8 or later */ +# if 0 /* _WIN32_WINNT >= 0x0602 */ /* Win8 or later */ /* This include does not work as _ARM_ or _AMD64_ macros - are missing */ -# include <synchapi.h> -# else -# include <windows.h> + are missing */ +# include <synchapi.h> +# else +# include <windows.h> +# endif +# endif +# endif + +# ifndef mhd_MUTEX_IMPLEMENTED +# include "mhd_locksrw.h" +# if defined(mhd_LOCKRW_IMPLEMENTED) && !defined(mhd_LOCKRW_KIND_MUTEX) +/** + * The mutex is RW-lock + */ +# define mhd_MUTEX_KIND_LOCKRW 1 +# define mhd_MUTEX_IMPLEMENTED 1 # endif # endif @@ -108,7 +123,7 @@ # error Multiple mutex implementations are enabled simultaneously # endif # endif -# ifdef mhd_MUTEX_KIND_W32_SRW +# ifdef mhd_MUTEX_KIND_LOCKRW # ifndef mhd_MUTEX_HAS_ONE_IMPLEMENTATION # define mhd_MUTEX_HAS_ONE_IMPLEMENTATION 1 # else @@ -131,10 +146,10 @@ # if defined(mhd_MUTEX_KIND_PTHREAD) typedef pthread_mutex_t mhd_mutex; -# elif defined(mhd_MUTEX_KIND_W32_SRW) -typedef SRWLOCK mhd_mutex; # elif defined(mhd_MUTEX_KIND_W32_CS) typedef CRITICAL_SECTION mhd_mutex; +# elif defined(mhd_MUTEX_KIND_LOCKRW) +typedef mhd_lockrw mhd_mutex; # endif /** @@ -144,8 +159,6 @@ typedef CRITICAL_SECTION mhd_mutex; */ # if defined(mhd_MUTEX_KIND_PTHREAD) # define mhd_mutex_init(pmutex) (0 == pthread_mutex_init((pmutex), NULL)) -# elif defined(mhd_MUTEX_KIND_W32_SRW) -# define mhd_mutex_init(pmutex) (InitializeSRWLock((pmutex)), ! 0) # elif defined(mhd_MUTEX_KIND_W32_CS) # if _WIN32_WINNT < 0x0600 /* Before Vista */ @@ -156,6 +169,8 @@ typedef CRITICAL_SECTION mhd_mutex; # define mhd_mutex_init(pmutex) \ (((void) InitializeCriticalSection(pmutex)), ! 0) # endif +# elif defined(mhd_MUTEX_KIND_LOCKRW) +# define mhd_mutex_init(pmutex) mhd_lockrw_init((pmutex)) # else # error Mutex implementation is missing # endif @@ -196,9 +211,9 @@ typedef CRITICAL_SECTION mhd_mutex; # elif defined(PTHREAD_MUTEX_INITIALIZER) # define mhd_MUTEX_INITIALISER_STAT PTHREAD_MUTEX_INITIALIZER # endif -# elif defined(mhd_MUTEX_KIND_W32_SRW) -# if defined(SRWLOCK_INIT) -# define mhd_MUTEX_INITIALISER_STAT SRWLOCK_INIT +# elif defined(mhd_MUTEX_KIND_LOCKRW) +# if defined(mhd_LOCKRW_INITIALISER_STAT) +# define mhd_MUTEX_INITIALISER_STAT mhd_LOCKRW_INITIALISER_STAT # endif # endif @@ -217,10 +232,10 @@ typedef CRITICAL_SECTION mhd_mutex; */ # if defined(mhd_MUTEX_KIND_PTHREAD) # define mhd_mutex_destroy(pmutex) (0 == pthread_mutex_destroy((pmutex))) -# elif defined(mhd_MUTEX_KIND_W32_SRW) -# define mhd_mutex_destroy(pmutex) ((void) (pmutex), ! 0) # elif defined(mhd_MUTEX_KIND_W32_CS) # define mhd_mutex_destroy(pmutex) (DeleteCriticalSection((pmutex)), ! 0) +# elif defined(mhd_MUTEX_KIND_LOCKRW) +# define mhd_mutex_destroy(pmutex) mhd_lockrw_destroy((pmutex)) # else # error Mutex implementation is missing # endif @@ -235,10 +250,10 @@ typedef CRITICAL_SECTION mhd_mutex; */ # if defined(mhd_MUTEX_KIND_PTHREAD) # define mhd_mutex_lock(pmutex) (0 == pthread_mutex_lock((pmutex))) -# elif defined(mhd_MUTEX_KIND_W32_SRW) -# define mhd_mutex_lock(pmutex) (AcquireSRWLockExclusive((pmutex)), ! 0) # elif defined(mhd_MUTEX_KIND_W32_CS) # define mhd_mutex_lock(pmutex) (EnterCriticalSection((pmutex)), ! 0) +# elif defined(mhd_MUTEX_KIND_LOCKRW) +# define mhd_mutex_lock(pmutex) mhd_lockrw_w_lock((pmutex)) # else # error Mutex implementation is missing # endif @@ -250,10 +265,10 @@ typedef CRITICAL_SECTION mhd_mutex; */ # if defined(mhd_MUTEX_KIND_PTHREAD) # define mhd_mutex_unlock(pmutex) (0 == pthread_mutex_unlock((pmutex))) -# elif defined(mhd_MUTEX_KIND_W32_SRW) -# define mhd_mutex_unlock(pmutex) (ReleaseSRWLockExclusive((pmutex)), ! 0) # elif defined(mhd_MUTEX_KIND_W32_CS) # define mhd_mutex_unlock(pmutex) (LeaveCriticalSection((pmutex)), ! 0) +# elif defined(mhd_MUTEX_KIND_LOCKRW) +# define mhd_mutex_unlock(pmutex) mhd_lockrw_w_unlock((pmutex)) # else # error Mutex implementation is missing # endif diff --git a/src/mhd2/mhd_locksrw.h b/src/mhd2/mhd_locksrw.h @@ -0,0 +1,359 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ +/* + This file is part of GNU libmicrohttpd. + Copyright (C) 2026 Evgeny Grin (Karlson2k) + + GNU libmicrohttpd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + GNU libmicrohttpd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + Alternatively, you can redistribute GNU libmicrohttpd and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version, together + with the eCos exception, as follows: + + As a special exception, if other files instantiate templates or + use macros or inline functions from this file, or you compile this + file and link it with other works to produce a work based on this + file, this file does not by itself cause the resulting work to be + covered by the GNU General Public License. However the source code + for this file must still be made available in accordance with + section (3) of the GNU General Public License v2. + + This exception does not invalidate any other reasons why a work + based on this file might be covered by the GNU General Public + License. + + You should have received copies of the GNU Lesser General Public + License and the GNU General Public License along with this library; + if not, see <https://www.gnu.org/licenses/>. +*/ + +/** + * @file src/mhd2/mhd_locksrw.h + * @brief Header for platform-independent RW-locks abstraction + * @author Karlson2k (Evgeny Grin) + * + * Provides basic abstraction for read-write locks. + * On some platforms read-only lock can be implemented as full lock. + * Any functions can be implemented as macro unless explicitly marked + * otherwise. + * Any function argument can be skipped in macro, so avoid + * variable modification in function parameters. + * + * @warning Unlike pthread functions, most of functions return + * nonzero on success. + */ + +#ifndef MHD_LOCKSRW_H +#define MHD_LOCKSRW_H 1 + +#include "mhd_sys_options.h" + +#ifdef MHD_SUPPORT_THREADS + +# if defined(mhd_THREADS_KIND_POSIX) && defined(HAVE_PTHREAD_RWLOCKS) +/** + * The RW-lock is pthreads RW-lock + */ +# define mhd_LOCKRW_KIND_PTHREAD 1 +# define mhd_LOCKRW_NATIVE 1 +# define mhd_LOCKRW_IMPLEMENTED 1 +# include <pthread.h> +# include "sys_null_macro.h" +# endif + +# if !defined(mhd_LOCKRW_IMPLEMENTED) && defined(mhd_THREADS_KIND_W32) +# include "sys_w32_ver.h" +# if _WIN32_WINNT >= 0x0600 /* Vista or later */ +/** + * The RW-lock is W32 SRW lock + */ +# define mhd_LOCKRW_KIND_W32_SRW 1 +# define mhd_LOCKRW_NATIVE 1 +# define mhd_LOCKRW_IMPLEMENTED 1 +# if 0 /* _WIN32_WINNT >= 0x0602 */ /* Win8 or later */ + /* This include does not work as _ARM_ or _AMD64_ macros + are missing */ +# include <synchapi.h> +# else +# include <windows.h> +# endif +# endif +# endif + +# if !defined(mhd_LOCKRW_IMPLEMENTED) +# include "mhd_locks.h" +# if defined(mhd_MUTEX_IMPLEMENTED) && !defined(mhd_MUTEX_KIND_LOCKRW) +/** + * The RW-lock is dumb mutex without shared read-lock support + */ +# define mhd_LOCKRW_KIND_MUTEX 1 +# define mhd_LOCKRW_DUMB 1 +# define mhd_LOCKRW_IMPLEMENTED 1 +# endif +# endif + +# if !defined(mhd_LOCKRW_IMPLEMENTED) +# error No base RW-locks API is available. +# endif + +/* Sanity check */ +# ifdef mhd_LOCKRW_KIND_PTHREAD +# ifndef mhd_LOCKRW_HAS_ONE_IMPLEMENTATION +# define mhd_LOCKRW_HAS_ONE_IMPLEMENTATION 1 +# else +# error Multiple RW-locks implementations are enabled simultaneously +# endif +# endif +# ifdef mhd_LOCKRW_KIND_W32_SRW +# ifndef mhd_LOCKRW_HAS_ONE_IMPLEMENTATION +# define mhd_LOCKRW_HAS_ONE_IMPLEMENTATION 1 +# else +# error Multiple RW-locks implementations are enabled simultaneously +# endif +# endif +# ifdef mhd_LOCKRW_KIND_MUTEX +# ifndef mhd_LOCKRW_HAS_ONE_IMPLEMENTATION +# define mhd_LOCKRW_HAS_ONE_IMPLEMENTATION 1 +# else +# error Multiple RW-locks implementations are enabled simultaneously +# endif +# endif +# ifndef mhd_LOCKRW_HAS_ONE_IMPLEMENTATION +# error Not all RW-locks kinds were checked +# endif +# undef mhd_LOCKRW_HAS_ONE_IMPLEMENTATION + +# include "mhd_panic.h" + +# if defined(mhd_LOCKRW_KIND_PTHREAD) +typedef pthread_rwlock_t mhd_lockrw; +# elif defined(mhd_LOCKRW_KIND_W32_SRW) +typedef SRWLOCK mhd_lockrw; +# elif defined(mhd_LOCKRW_KIND_MUTEX) +typedef mhd_mutex mhd_lockrw; +# else +# error RW-locks implementation is missing +# endif + +/** + * Initialise a new rw-lock. + * @param plock the pointer to the rw-lock + * @return nonzero on success, zero otherwise + */ +# if defined(mhd_LOCKRW_KIND_PTHREAD) +# define mhd_lockrw_init(plock) (0 == pthread_rwlock_init ((plock), NULL)) +# elif defined(mhd_LOCKRW_KIND_W32_SRW) +# define mhd_lockrw_init(plock) (InitializeSRWLock ((plock)), ! 0) +# elif defined(mhd_LOCKRW_KIND_MUTEX) +# define mhd_lockrw_init(plock) mhd_mutex_init((plock)) +# else +# error RW-locks implementation is missing +# endif + +/** + * The value to statically initialise rw-lock + */ +# if defined(mhd_LOCKRW_KIND_PTHREAD) +# if defined(PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP) +# define mhd_LOCKRW_INITIALISER_STAT \ + PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP +# elif defined(PTHREAD_RWLOCK_INITIALIZER) +# define mhd_LOCKRW_INITIALISER_STAT PTHREAD_RWLOCK_INITIALIZER +# elif defined(PTHREAD_RWLOCK_INITIALIZER_NP) +# define mhd_LOCKRW_INITIALISER_STAT PTHREAD_RWLOCK_INITIALIZER_NP +# endif +# elif defined(mhd_LOCKRW_KIND_W32_SRW) +# if defined(SRWLOCK_INIT) +# define mhd_LOCKRW_INITIALISER_STAT SRWLOCK_INIT +# endif +# elif defined(mhd_LOCKRW_KIND_MUTEX) +# if defined(mhd_MUTEX_INITIALISER_STAT) +# define mhd_LOCKRW_INITIALISER_STAT mhd_MUTEX_INITIALISER_STAT +# endif +# endif + +# ifdef mhd_LOCKRW_INITIALISER_STAT +/** + * Define static rw-lock and statically initialise it. + */ +# define mhd_LOCKRW_STATIC_DEFN_INIT(l) \ + static mhd_lockrw l = mhd_LOCKRW_INITIALISER_STAT +# endif + +/** + * Destroy previously initialised rw-lock. + * @param plock the pointer to the rw-lock + * @return nonzero on success, zero otherwise + */ +# if defined(mhd_LOCKRW_KIND_PTHREAD) +# define mhd_lockrw_destroy(plock) (0 == pthread_rwlock_destroy((plock))) +# elif defined(mhd_LOCKRW_KIND_W32_SRW) +# define mhd_lockrw_destroy(plock) ((void) (plock), ! 0) +# elif defined(mhd_LOCKRW_KIND_MUTEX) +# define mhd_lockrw_destroy(plock) mhd_mutex_destroy((plock)) +# else +# error RW-locks implementation is missing +# endif + + +/** + * Acquire a read lock on previously initialised rw-lock. + * If the write-lock was already locked by other thread, function blocks until + * the rw-lock becomes available. + * Behaviour is undefined if write or read lock has been already locked by + * the same thread. + * @param plock the pointer to the rw-lock + * @return nonzero on success, zero otherwise + */ +# if defined(mhd_LOCKRW_KIND_PTHREAD) +# define mhd_lockrw_r_lock(plock) (0 == pthread_rwlock_rdlock((plock))) +# elif defined(mhd_LOCKRW_KIND_W32_SRW) +# define mhd_lockrw_r_lock(plock) (AcquireSRWLockShared((plock)), ! 0) +# elif defined(mhd_LOCKRW_KIND_MUTEX) +# define mhd_lockrw_r_lock(plock) mhd_mutex_lock((plock)) +# else +# error RW-locks implementation is missing +# endif + + +/** + * Unlock previously read-locked rw-lock. + * Behaviour is undefined if rw-lock has not been read-locked. + * @param plock the pointer to the rw-lock + * @return nonzero on success, zero otherwise + */ +# if defined(mhd_LOCKRW_KIND_PTHREAD) +# define mhd_lockrw_r_unlock(plock) (0 == pthread_rwlock_unlock((plock))) +# elif defined(mhd_LOCKRW_KIND_W32_SRW) +# define mhd_lockrw_r_unlock(plock) (ReleaseSRWLockShared((plock)), ! 0) +# elif defined(mhd_LOCKRW_KIND_MUTEX) +# define mhd_lockrw_r_unlock(plock) mhd_mutex_unlock((plock)) +# else +# error RW-locks implementation is missing +# endif + + +/** + * Acquire a write lock on previously initialised rw-lock. + * If the rw-lock was already locked by other thread, function blocks until + * the rw-lock becomes available. + * Behaviour is undefined if write or read lock has been already locked by + * the same thread. + * @param plock the pointer to the rw-lock + * @return nonzero on success, zero otherwise + */ +# if defined(mhd_LOCKRW_KIND_PTHREAD) +# define mhd_lockrw_w_lock(plock) (0 == pthread_rwlock_wrlock((plock))) +# elif defined(mhd_LOCKRW_KIND_W32_SRW) +# define mhd_lockrw_w_lock(plock) (AcquireSRWLockExclusive((plock)), ! 0) +# elif defined(mhd_LOCKRW_KIND_MUTEX) +# define mhd_lockrw_w_lock(plock) mhd_mutex_lock((plock)) +# else +# error RW-locks implementation is missing +# endif + + +/** + * Unlock previously write-locked rw-lock. + * Behaviour is undefined if rw-lock has not been write-locked. + * @param plock the pointer to the rw-lock + * @return nonzero on success, zero otherwise + */ +# if defined(mhd_LOCKRW_KIND_PTHREAD) +# define mhd_lockrw_w_unlock(plock) (0 == pthread_rwlock_unlock((plock))) +# elif defined(mhd_LOCKRW_KIND_W32_SRW) +# define mhd_lockrw_w_unlock(plock) (ReleaseSRWLockExclusive((plock)), ! 0) +# elif defined(mhd_LOCKRW_KIND_MUTEX) +# define mhd_lockrw_w_unlock(plock) mhd_mutex_unlock((plock)) +# else +# error RW-locks implementation is missing +# endif + +/** + * Destroy previously initialised rw-lock and abort execution if error is + * detected. + * @param plock the pointer to the rw-lock + */ +# define mhd_lockrw_destroy_chk(plock) do { \ + if (! mhd_lockrw_destroy((plock))) \ + MHD_PANIC ("Failed to destroy rw-lock."); \ + } while (0) + +/** + * Acquire a read lock on previously initialised rw-lock. + * If the write-lock was already locked by other thread, function blocks until + * the rw-lock becomes available. + * If error is detected, execution is aborted. + * Behaviour is undefined if write or read lock has been already locked by + * the same thread. + * @param plock the pointer to the rw-lock + */ +# define mhd_lockrw_r_lock_chk(plock) do { \ + if (! mhd_lockrw_r_lock((plock))) \ + MHD_PANIC ("Failed to read-lock rw-lock."); \ + } while (0) + +/** + * Unlock previously read-locked rw-lock. + * If error is detected, execution is aborted. + * Behaviour is undefined if rw-lock has not been read-locked. + * @param plock the pointer to the rw-lock + */ +# define mhd_lockrw_r_unlock_chk(plock) do { \ + if (! mhd_lockrw_r_unlock((plock))) \ + MHD_PANIC ("Failed to read-unlock rw-lock."); \ + } while (0) + +/** + * Acquire a write lock on previously initialised rw-lock. + * If the rw-lock was already locked by other thread, function blocks until + * the rw-lock becomes available. + * If error is detected, execution is aborted. + * Behaviour is undefined if write or read lock has been already locked by + * the same thread. + * @param plock the pointer to the rw-lock + */ +# define mhd_lockrw_w_lock_chk(plock) do { \ + if (! mhd_lockrw_w_lock((plock))) \ + MHD_PANIC ("Failed to write-lock rw-lock."); \ + } while (0) + +/** + * Unlock previously write-locked rw-lock. + * If error is detected, execution is aborted. + * Behaviour is undefined if rw-lock has not been write-locked. + * @param plock the pointer to the rw-lock + */ +# define mhd_lockrw_w_unlock_chk(plock) do { \ + if (! mhd_lockrw_w_unlock((plock))) \ + MHD_PANIC ("Failed to write-unlock rw-lock."); \ + } while (0) + +#else /* ! MHD_SUPPORT_THREADS */ + +# define mhd_lockrw_init(ignored) (! 0) +# define mhd_LOCKRW_INITIALISER_STAT /* empty */ +# define mhd_LOCKRW_STATIC_DEFN_INIT(ignored) /* nothing */ +# define mhd_lockrw_destroy(ignored) (! 0) +# define mhd_lockrw_destroy_chk(ignored) ((void) 0) +# define mhd_lockrw_r_lock(ignored) (! 0) +# define mhd_lockrw_r_lock_chk(ignored) ((void) 0) +# define mhd_lockrw_r_unlock(ignored) (! 0) +# define mhd_lockrw_r_unlock_chk(ignored) ((void) 0) +# define mhd_lockrw_w_lock(ignored) (! 0) +# define mhd_lockrw_w_lock_chk(ignored) ((void) 0) +# define mhd_lockrw_w_unlock(ignored) (! 0) +# define mhd_lockrw_w_unlock_chk(ignored) ((void) 0) + +#endif /* ! MHD_SUPPORT_THREADS */ + +#endif /* ! MHD_LOCKSRW_H */