From 64fbffbbaaeeb6185eba84bccd2f981bee23710d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Thu, 16 Aug 2018 15:03:42 +0200 Subject: [PATCH 1/3] Use simple pthread_rwlock in place of our custom adaptive rwlock --- config.h.in | 3 ++ configure | 15 +++++--- configure.ac | 6 +-- lib/isc/include/isc/rwlock.h | 11 ++++++ lib/isc/rwlock.c | 74 ++++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 10 deletions(-) diff --git a/config.h.in b/config.h.in index 4f40e31458..cf742bc31c 100644 --- a/config.h.in +++ b/config.h.in @@ -309,6 +309,9 @@ /* Have PTHREAD_PRIO_INHERIT. */ #undef HAVE_PTHREAD_PRIO_INHERIT +/* Define to 1 if you have the `pthread_rwlock_rdlock' function. */ +#undef HAVE_PTHREAD_RWLOCK_RDLOCK + /* Define to 1 if you have the `pthread_setaffinity_np' function. */ #undef HAVE_PTHREAD_SETAFFINITY_NP diff --git a/configure b/configure index 09167c62f4..24cca62c9c 100755 --- a/configure +++ b/configure @@ -15615,12 +15615,17 @@ $as_echo "no" >&6; } esac -# -# If PIC is disabled, shared libraries must also be -# -if test "$pic_mode" = "no"; then : - enable_shared="no" +for ac_func in pthread_rwlock_rdlock +do : + ac_fn_c_check_func "$LINENO" "pthread_rwlock_rdlock" "ac_cv_func_pthread_rwlock_rdlock" +if test "x$ac_cv_func_pthread_rwlock_rdlock" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PTHREAD_RWLOCK_RDLOCK 1 +_ACEOF + fi +done + CRYPTO=OpenSSL diff --git a/configure.ac b/configure.ac index 1e20f1724e..272706314e 100644 --- a/configure.ac +++ b/configure.ac @@ -733,11 +733,7 @@ case $use_libtool in esac AC_SUBST(INSTALL_LIBRARY) -# -# If PIC is disabled, shared libraries must also be -# -AS_IF([test "$pic_mode" = "no"], - [enable_shared="no"]) +AC_CHECK_FUNCS([pthread_rwlock_rdlock]) CRYPTO=OpenSSL diff --git a/lib/isc/include/isc/rwlock.h b/lib/isc/include/isc/rwlock.h index ed1ff66312..50d06d72d0 100644 --- a/lib/isc/include/isc/rwlock.h +++ b/lib/isc/include/isc/rwlock.h @@ -14,6 +14,7 @@ #define ISC_RWLOCK_H 1 #include +#include /*! \file isc/rwlock.h */ @@ -31,6 +32,14 @@ typedef enum { isc_rwlocktype_write } isc_rwlocktype_t; +#if HAVE_PTHREAD_RWLOCK_RDLOCK + +struct isc_rwlock { + pthread_rwlock_t rwlock; +}; + +#else /* HAVE_PTHREAD_RWLOCK_RDLOCK */ + struct isc_rwlock { /* Unlocked. */ unsigned int magic; @@ -68,6 +77,8 @@ struct isc_rwlock { }; +#endif /* HAVE_PTHREAD_RWLOCK_RDLOCK */ + isc_result_t isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, unsigned int write_quota); diff --git a/lib/isc/rwlock.c b/lib/isc/rwlock.c index 1071fecc07..2619619d1b 100644 --- a/lib/isc/rwlock.c +++ b/lib/isc/rwlock.c @@ -27,6 +27,78 @@ #include #include +#if HAVE_PTHREAD_RWLOCK_RDLOCK + +#include +#include + +isc_result_t +isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, + unsigned int write_quota) +{ + UNUSED(read_quota); + UNUSED(write_quota); + REQUIRE(pthread_rwlock_init(&rwl->rwlock, NULL) == 0); + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { + switch (type) { + case isc_rwlocktype_read: REQUIRE(pthread_rwlock_rdlock(&rwl->rwlock) == 0); break; + case isc_rwlocktype_write: REQUIRE(pthread_rwlock_wrlock(&rwl->rwlock) == 0); break; + default: INSIST(0); + } + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { + int ret = 0; + switch (type) { + case isc_rwlocktype_read: + ret = pthread_rwlock_tryrdlock(&rwl->rwlock); + break; + case isc_rwlocktype_write: + ret = pthread_rwlock_trywrlock(&rwl->rwlock); + break; + default: INSIST(0); + } + + switch (ret) { + case 0: return (ISC_R_SUCCESS); + case EBUSY: return (ISC_R_LOCKBUSY); + case EAGAIN: return (ISC_R_LOCKBUSY); + default: INSIST(0); ISC_UNREACHABLE(); + } +} + + +isc_result_t +isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { + UNUSED(type); + REQUIRE(pthread_rwlock_unlock(&rwl->rwlock) == 0); + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_rwlock_tryupgrade(isc_rwlock_t *rwl) { + return (ISC_R_LOCKBUSY); +} + +void +isc_rwlock_downgrade(isc_rwlock_t *rwl) { + isc_rwlock_unlock(rwl, isc_rwlocktype_write); + isc_rwlock_lock(rwl, isc_rwlocktype_read); +} + +void +isc_rwlock_destroy(isc_rwlock_t *rwl) { + pthread_rwlock_destroy(&rwl->rwlock); +} + +#else + #define RWLOCK_MAGIC ISC_MAGIC('R', 'W', 'L', 'k') #define VALID_RWLOCK(rwl) ISC_MAGIC_VALID(rwl, RWLOCK_MAGIC) @@ -549,3 +621,5 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { return (ISC_R_SUCCESS); } + +#endif /* HAVE_PTHREAD_RWLOCK_RDLOCK */ From 4501f646eecd49bda19862187d4f550218bdaf8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Thu, 22 Nov 2018 11:42:12 +0100 Subject: [PATCH 2/3] Implement isc_rwlock_downgrade using pthreads and single atomic_bool --- lib/isc/include/isc/rwlock.h | 1 + lib/isc/rwlock.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/isc/include/isc/rwlock.h b/lib/isc/include/isc/rwlock.h index 50d06d72d0..5551c1b623 100644 --- a/lib/isc/include/isc/rwlock.h +++ b/lib/isc/include/isc/rwlock.h @@ -36,6 +36,7 @@ typedef enum { struct isc_rwlock { pthread_rwlock_t rwlock; + atomic_bool downgrade; }; #else /* HAVE_PTHREAD_RWLOCK_RDLOCK */ diff --git a/lib/isc/rwlock.c b/lib/isc/rwlock.c index 2619619d1b..7d5e14ea4e 100644 --- a/lib/isc/rwlock.c +++ b/lib/isc/rwlock.c @@ -39,15 +39,32 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, UNUSED(read_quota); UNUSED(write_quota); REQUIRE(pthread_rwlock_init(&rwl->rwlock, NULL) == 0); + atomic_init(&rwl->downgrade, false); return (ISC_R_SUCCESS); } isc_result_t isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { switch (type) { - case isc_rwlocktype_read: REQUIRE(pthread_rwlock_rdlock(&rwl->rwlock) == 0); break; - case isc_rwlocktype_write: REQUIRE(pthread_rwlock_wrlock(&rwl->rwlock) == 0); break; - default: INSIST(0); + case isc_rwlocktype_read: + REQUIRE(pthread_rwlock_rdlock(&rwl->rwlock) == 0); + break; + case isc_rwlocktype_write: + while (true) { + REQUIRE(pthread_rwlock_wrlock(&rwl->rwlock) == 0); + /* Unlock if in middle of downgrade operation */ + if (atomic_load_release(&rwl->downgrade)) { + REQUIRE(pthread_rwlock_unlock(&rwl->rwlock) + == 0); + while (atomic_load(&rwl->downgrade)); + continue; + } + break; + } + break; + default: + INSIST(0); + ISC_UNREACHABLE(); } return (ISC_R_SUCCESS); } @@ -61,6 +78,10 @@ isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { break; case isc_rwlocktype_write: ret = pthread_rwlock_trywrlock(&rwl->rwlock); + if ((ret == 0) && atomic_load(&rwl->downgrade)) { + isc_rwlock_unlock(rwl, type); + return (ISC_R_LOCKBUSY); + } break; default: INSIST(0); } @@ -88,8 +109,10 @@ isc_rwlock_tryupgrade(isc_rwlock_t *rwl) { void isc_rwlock_downgrade(isc_rwlock_t *rwl) { + atomic_store_acquire(&rwl->downgrade, true); isc_rwlock_unlock(rwl, isc_rwlocktype_write); isc_rwlock_lock(rwl, isc_rwlocktype_read); + atomic_store_acquire(&rwl->downgrade, false); } void From 02bbf1e2b95878931309153633577ecf4f1c4de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Fri, 25 Jan 2019 12:29:52 +0100 Subject: [PATCH 3/3] Add --enable-pthread-rwlock option --- config.h.in | 3 +++ configure | 24 +++++++++++++++++++++++- configure.ac | 14 +++++++++++++- lib/isc/include/isc/rwlock.h | 6 +++--- lib/isc/rwlock.c | 4 ++-- 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/config.h.in b/config.h.in index cf742bc31c..817fd003e5 100644 --- a/config.h.in +++ b/config.h.in @@ -556,6 +556,9 @@ /* define if PKCS11 is used for Public-Key Cryptography */ #undef USE_PKCS11 +/* Define if you want to use pthread rwlock implementation */ +#undef USE_PTHREAD_RWLOCK + /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE diff --git a/configure b/configure index 24cca62c9c..425bb6a44c 100755 --- a/configure +++ b/configure @@ -900,6 +900,7 @@ enable_devpoll with_geoip with_locktype with_libtool +enable_pthread_rwlock with_openssl enable_fips_mode with_cc_alg @@ -1599,6 +1600,8 @@ Optional Features: --enable-kqueue use BSD kqueue when available [default=yes] --enable-epoll use Linux epoll when available [default=auto] --enable-devpoll use /dev/poll when available [default=yes] + --enable-pthread-rwlock use pthread rwlock instead of internal rwlock + implementation (EXPERIMENTAL) --enable-fips-mode enable FIPS mode in OpenSSL library [default=no] --enable-native-pkcs11 use native PKCS11 for public-key crypto [default=no] --enable-backtrace log stack backtrace on abort [default=yes] @@ -15615,7 +15618,19 @@ $as_echo "no" >&6; } esac -for ac_func in pthread_rwlock_rdlock +# +# Do we want to use pthread rwlock? (useful for ThreadSanitizer) +# +# Check whether --enable-pthread_rwlock was given. +if test "${enable_pthread_rwlock+set}" = set; then : + enableval=$enable_pthread_rwlock; +else + enable_pthread_rwlock=no +fi + + +if test "$enable_pthread_rwlock" = "yes"; then : + for ac_func in pthread_rwlock_rdlock do : ac_fn_c_check_func "$LINENO" "pthread_rwlock_rdlock" "ac_cv_func_pthread_rwlock_rdlock" if test "x$ac_cv_func_pthread_rwlock_rdlock" = xyes; then : @@ -15623,10 +15638,17 @@ if test "x$ac_cv_func_pthread_rwlock_rdlock" = xyes; then : #define HAVE_PTHREAD_RWLOCK_RDLOCK 1 _ACEOF +else + as_fn_error $? "pthread_rwlock_rdlock requested but not found" "$LINENO" 5 fi done +$as_echo "#define USE_PTHREAD_RWLOCK 1" >>confdefs.h + + +fi + CRYPTO=OpenSSL # diff --git a/configure.ac b/configure.ac index 272706314e..7064846004 100644 --- a/configure.ac +++ b/configure.ac @@ -733,7 +733,19 @@ case $use_libtool in esac AC_SUBST(INSTALL_LIBRARY) -AC_CHECK_FUNCS([pthread_rwlock_rdlock]) +# +# Do we want to use pthread rwlock? (useful for ThreadSanitizer) +# +AC_ARG_ENABLE([pthread_rwlock], + [AS_HELP_STRING([--enable-pthread-rwlock], + [use pthread rwlock instead of internal rwlock implementation (EXPERIMENTAL)])], + [], [enable_pthread_rwlock=no]) + +AS_IF([test "$enable_pthread_rwlock" = "yes"], + [AC_CHECK_FUNCS([pthread_rwlock_rdlock], [], + [AC_MSG_ERROR([pthread_rwlock_rdlock requested but not found])]) + AC_DEFINE([USE_PTHREAD_RWLOCK],[1],[Define if you want to use pthread rwlock implementation]) + ]) CRYPTO=OpenSSL diff --git a/lib/isc/include/isc/rwlock.h b/lib/isc/include/isc/rwlock.h index 5551c1b623..d1a4545339 100644 --- a/lib/isc/include/isc/rwlock.h +++ b/lib/isc/include/isc/rwlock.h @@ -32,14 +32,14 @@ typedef enum { isc_rwlocktype_write } isc_rwlocktype_t; -#if HAVE_PTHREAD_RWLOCK_RDLOCK +#if USE_PTHREAD_RWLOCK struct isc_rwlock { pthread_rwlock_t rwlock; atomic_bool downgrade; }; -#else /* HAVE_PTHREAD_RWLOCK_RDLOCK */ +#else /* USE_PTHREAD_RWLOCK */ struct isc_rwlock { /* Unlocked. */ @@ -78,7 +78,7 @@ struct isc_rwlock { }; -#endif /* HAVE_PTHREAD_RWLOCK_RDLOCK */ +#endif /* USE_PTHREAD_RWLOCK */ isc_result_t isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, diff --git a/lib/isc/rwlock.c b/lib/isc/rwlock.c index 7d5e14ea4e..d756d663ab 100644 --- a/lib/isc/rwlock.c +++ b/lib/isc/rwlock.c @@ -27,7 +27,7 @@ #include #include -#if HAVE_PTHREAD_RWLOCK_RDLOCK +#if USE_PTHREAD_RWLOCK #include #include @@ -645,4 +645,4 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { return (ISC_R_SUCCESS); } -#endif /* HAVE_PTHREAD_RWLOCK_RDLOCK */ +#endif /* USE_PTHREAD_RWLOCK */