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