From aebb4aaa0d071e0a750223437dcb479a5b1eae33 Mon Sep 17 00:00:00 2001
From: Joshua Colp <jcolp@digium.com>
Date: Thu, 2 Nov 2006 16:28:13 +0000
Subject: [PATCH] I'm crazy so I will add this... pthread rwlock wrappers,
 along with autoconf stuff that detects the presence of the initializer and
 the ability to set the kind of lock (in our case we rather like writer
 preferred locks so writer starvation doesn't occur... but on something like
 Darwin we don't get that)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@46935 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 configure                        | 175 ++++++++++++++++++++++++++++++-
 configure.ac                     |   3 +
 include/asterisk/autoconfig.h.in |  12 +++
 include/asterisk/lock.h          |  64 +++++++++++
 4 files changed, 253 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index bd863f7101..d93af0c344 100755
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.ac Revision: 46846 .
+# From configure.ac Revision: 46848 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.60a.
 #
@@ -14158,6 +14158,179 @@ fi
 done
 
 
+
+    if test "x${PBX_PTHREAD_RWLOCK_INITIALIZER}" != "x1" -a "${USE_PTHREAD_RWLOCK_INITIALIZER}" != "no"; then
+	{ echo "$as_me:$LINENO: checking for PTHREAD_RWLOCK_INITIALIZER in pthread.h" >&5
+echo $ECHO_N "checking for PTHREAD_RWLOCK_INITIALIZER in pthread.h... $ECHO_C" >&6; }
+	saved_cppflags="${CPPFLAGS}"
+	if test "x${PTHREAD_RWLOCK_INITIALIZER_DIR}" != "x"; then
+	    PTHREAD_RWLOCK_INITIALIZER_INCLUDE= "-I${PTHREAD_RWLOCK_INITIALIZER_DIR}/include"
+	fi
+	CPPFLAGS="${CPPFLAGS} ${PTHREAD_RWLOCK_INITIALIZER_INCLUDE}"
+
+	cat >conftest.$ac_ext <<_ACEOF
+ /* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <pthread.h>
+int
+main ()
+{
+int foo = PTHREAD_RWLOCK_INITIALIZER;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+     { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+		PBX_PTHREAD_RWLOCK_INITIALIZER=1
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTHREAD_RWLOCK_INITIALIZER 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTHREAD_RWLOCK_INITIALIZER_VERSION
+_ACEOF
+
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+	CPPFLAGS="${saved_cppflags}"
+    fi
+
+
+    if test "x${PBX_PTHREAD_RWLOCK_PREFER_WRITER_NP}" != "x1" -a "${USE_PTHREAD_RWLOCK_PREFER_WRITER_NP}" != "no"; then
+	{ echo "$as_me:$LINENO: checking for PTHREAD_RWLOCK_PREFER_WRITER_NP in pthread.h" >&5
+echo $ECHO_N "checking for PTHREAD_RWLOCK_PREFER_WRITER_NP in pthread.h... $ECHO_C" >&6; }
+	saved_cppflags="${CPPFLAGS}"
+	if test "x${PTHREAD_RWLOCK_PREFER_WRITER_NP_DIR}" != "x"; then
+	    PTHREAD_RWLOCK_PREFER_WRITER_NP_INCLUDE= "-I${PTHREAD_RWLOCK_PREFER_WRITER_NP_DIR}/include"
+	fi
+	CPPFLAGS="${CPPFLAGS} ${PTHREAD_RWLOCK_PREFER_WRITER_NP_INCLUDE}"
+
+	cat >conftest.$ac_ext <<_ACEOF
+ /* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <pthread.h>
+int
+main ()
+{
+int foo = PTHREAD_RWLOCK_PREFER_WRITER_NP;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+     { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+		PBX_PTHREAD_RWLOCK_PREFER_WRITER_NP=1
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP_VERSION
+_ACEOF
+
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+	CPPFLAGS="${saved_cppflags}"
+    fi
+
+
 { echo "$as_me:$LINENO: checking for compiler atomic operations" >&5
 echo $ECHO_N "checking for compiler atomic operations... $ECHO_C" >&6; }
 cat >conftest.$ac_ext <<_ACEOF
diff --git a/configure.ac b/configure.ac
index 106049d618..33875dc513 100644
--- a/configure.ac
+++ b/configure.ac
@@ -267,6 +267,9 @@ AC_CHECK_FUNCS([funopen fopencookie])
 # some systems already have gethostbyname_r so we don't need to build ours in main/utils.c
 AC_CHECK_FUNCS([gethostbyname_r])
 
+AST_C_DEFINE_CHECK([PTHREAD_RWLOCK_INITIALIZER], [PTHREAD_RWLOCK_INITIALIZER], [pthread.h])
+AST_C_DEFINE_CHECK([PTHREAD_RWLOCK_PREFER_WRITER_NP], [PTHREAD_RWLOCK_PREFER_WRITER_NP], [pthread.h])
+
 AC_MSG_CHECKING(for compiler atomic operations)
 AC_LINK_IFELSE(
 AC_LANG_PROGRAM([], [int foo1; int foo2 = __sync_fetch_and_add(&foo1, 1);]),
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index 81e008a2fa..8bec1372ca 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -316,6 +316,18 @@
 /* Define to indicate the ${PRI_DESCRIP} library version */
 #undef HAVE_PRI_VERSION
 
+/* Define if your system has the PTHREAD_RWLOCK_INITIALIZER headers. */
+#undef HAVE_PTHREAD_RWLOCK_INITIALIZER
+
+/* Define PTHREAD_RWLOCK_INITIALIZER headers version */
+#undef HAVE_PTHREAD_RWLOCK_INITIALIZER_VERSION
+
+/* Define if your system has the PTHREAD_RWLOCK_PREFER_WRITER_NP headers. */
+#undef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
+
+/* Define PTHREAD_RWLOCK_PREFER_WRITER_NP headers version */
+#undef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP_VERSION
+
 /* Define to 1 if the system has the type `ptrdiff_t'. */
 #undef HAVE_PTRDIFF_T
 
diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h
index bcd2fdabef..b329fc1038 100644
--- a/include/asterisk/lock.h
+++ b/include/asterisk/lock.h
@@ -614,6 +614,70 @@ static void  __attribute__ ((destructor)) fini_##mutex(void) \
 #define pthread_create __use_ast_pthread_create_instead__
 #endif
 
+typedef pthread_rwlock_t ast_rwlock_t;
+
+static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
+{
+	pthread_rwlockattr_t attr;
+
+	pthread_rwlockattr_init(&attr);
+
+#ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
+	pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
+#endif
+
+	return pthread_rwlock_init(prwlock, &attr);
+}
+
+static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
+{
+	return pthread_rwlock_destroy(prwlock);
+}
+
+static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
+{
+	return pthread_rwlock_unlock(prwlock);
+}
+
+static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
+{
+	return pthread_rwlock_rdlock(prwlock);
+}
+
+static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
+{
+	return pthread_rwlock_tryrdlock(prwlock);
+}
+
+static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
+{
+	return pthread_rwlock_wrlock(prwlock);
+}
+
+static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
+{
+	return pthread_rwlock_trywrlock(prwlock);
+}
+
+/* Statically declared read/write locks */
+
+#ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER
+#define __AST_RWLOCK_DEFINE(scope, rwlock) \
+static void  __attribute__ ((constructor)) init_##rwlock(void) \
+{ \
+        ast_rwlock_init(&rwlock); \
+} \
+static void  __attribute__ ((destructor)) fini_##rwlock(void) \
+{ \
+        ast_mutex_destroy(&rwlock); \
+}
+#else
+#define __AST_RWLOCK_DEFINE(scope, rwlock) \
+        scope ast_rwlock_t rwlock = AST_RWLOCK_INIT_VALUE
+#endif
+
+#define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock)
+
 /*
  * Initial support for atomic instructions.
  * For platforms that have it, use the native cpu instruction to
-- 
GitLab