Author: kotkov
Date: Thu Feb 5 16:46:55 2015
New Revision: 1657623
URL: http://svn.apache.org/r1657623
Log:
Tune the conditional compilation related to us using two different types
of locks (apr_thread_mutex_t and apr_thread_rwlock_t) in the membuffer cache.
Instead of having nested #if's for APR_HAS_THREADS and USE_SIMPLE_MUTEX,
make every possible code path explicit and ensure that they don't intersect.
We cannot really get rid of the conditional compilation, because using an
apr_thread_mutex_t under Windows is a workaround for poor APR read-write lock
performance and possible race condition (see [1,2]).
However, what we can do here is avoid merging the conditionally compiled
statements and ensure that only required fields of the struct svn_membuffer_t
are compiled in the corresponding #if statements. This patch gets rid of the
'allow_blocking_writes' field initialization when we do not have a read-write
lock, and also prevents a preprocessor from outputting code with multiple
return statements, e.g.:
static svn_error_t *
read_lock_cache(svn_membuffer_t * cache)
{
return svn_mutex__lock(cache->lock);
return SVN_NO_ERROR;
}
[1] http://svn.haxx.se/dev/archive-2014-12/0112.shtml
(Message-ID:
<CABw-3Yfs4ydsEZj6Y7yL=HK_zas6-9=xpZ=EwS+JaC=7hul...@mail.gmail.com>)
[2] https://issues.apache.org/bugzilla/show_bug.cgi?id=45455
* subversion/libsvn_subr/cache-membuffer.c
(struct svn_membuffer_t): Replace the nested #if's with two explicit
conditions. Compile out the 'allow_blocking_writes' field when we favor
apr_thread_mutex_t over apr_thread_rwlock_t, as it is not being used on
the corresponding code paths.
(read_lock_cache, write_lock_cache, force_write_lock_cache, unlock_cache):
Replace the nested #if's with explicit #if-elif-else conditions.
(svn_cache__membuffer_cache_create): Same here, but without an #else, as
with !APR_HAS_THREADS we don't have locks to initialize.
Modified:
subversion/trunk/subversion/libsvn_subr/cache-membuffer.c
Modified: subversion/trunk/subversion/libsvn_subr/cache-membuffer.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cache-membuffer.c?rev=1657623&r1=1657622&r2=1657623&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cache-membuffer.c Thu Feb 5
16:46:55 2015
@@ -587,16 +587,15 @@ struct svn_membuffer_t
*/
apr_uint64_t total_hits;
-#if APR_HAS_THREADS
+#if (APR_HAS_THREADS && USE_SIMPLE_MUTEX)
/* A lock for intra-process synchronization to the cache, or NULL if
* the cache's creator doesn't feel the cache needs to be
* thread-safe.
*/
-# if USE_SIMPLE_MUTEX
svn_mutex__t *lock;
-# else
+#elif (APR_HAS_THREADS && !USE_SIMPLE_MUTEX)
+ /* Same for read-write lock. */
apr_thread_rwlock_t *lock;
-# endif
/* If set, write access will wait until they get exclusive access.
* Otherwise, they will become no-ops if the segment is currently
@@ -619,19 +618,20 @@ struct svn_membuffer_t
static svn_error_t *
read_lock_cache(svn_membuffer_t *cache)
{
-#if APR_HAS_THREADS
-# if USE_SIMPLE_MUTEX
+#if (APR_HAS_THREADS && USE_SIMPLE_MUTEX)
return svn_mutex__lock(cache->lock);
-# else
+#elif (APR_HAS_THREADS && !USE_SIMPLE_MUTEX)
if (cache->lock)
{
apr_status_t status = apr_thread_rwlock_rdlock(cache->lock);
if (status)
return svn_error_wrap_apr(status, _("Can't lock cache mutex"));
}
-# endif
-#endif
+
return SVN_NO_ERROR;
+#else
+ return SVN_NO_ERROR;
+#endif
}
/* If locking is supported for CACHE, acquire a write lock for it.
@@ -639,13 +639,9 @@ read_lock_cache(svn_membuffer_t *cache)
static svn_error_t *
write_lock_cache(svn_membuffer_t *cache, svn_boolean_t *success)
{
-#if APR_HAS_THREADS
-# if USE_SIMPLE_MUTEX
-
+#if (APR_HAS_THREADS && USE_SIMPLE_MUTEX)
return svn_mutex__lock(cache->lock);
-
-# else
-
+#elif (APR_HAS_THREADS && !USE_SIMPLE_MUTEX)
if (cache->lock)
{
apr_status_t status;
@@ -668,9 +664,10 @@ write_lock_cache(svn_membuffer_t *cache,
_("Can't write-lock cache mutex"));
}
-# endif
-#endif
return SVN_NO_ERROR;
+#else
+ return SVN_NO_ERROR;
+#endif
}
/* If locking is supported for CACHE, acquire an unconditional write lock
@@ -679,21 +676,18 @@ write_lock_cache(svn_membuffer_t *cache,
static svn_error_t *
force_write_lock_cache(svn_membuffer_t *cache)
{
-#if APR_HAS_THREADS
-# if USE_SIMPLE_MUTEX
-
+#if (APR_HAS_THREADS && USE_SIMPLE_MUTEX)
return svn_mutex__lock(cache->lock);
-
-# else
-
+#elif (APR_HAS_THREADS && !USE_SIMPLE_MUTEX)
apr_status_t status = apr_thread_rwlock_wrlock(cache->lock);
if (status)
return svn_error_wrap_apr(status,
_("Can't write-lock cache mutex"));
-# endif
-#endif
return SVN_NO_ERROR;
+#else
+ return SVN_NO_ERROR;
+#endif
}
/* If locking is supported for CACHE, release the current lock
@@ -702,13 +696,9 @@ force_write_lock_cache(svn_membuffer_t *
static svn_error_t *
unlock_cache(svn_membuffer_t *cache, svn_error_t *err)
{
-#if APR_HAS_THREADS
-# if USE_SIMPLE_MUTEX
-
+#if (APR_HAS_THREADS && USE_SIMPLE_MUTEX)
return svn_mutex__unlock(cache->lock, err);
-
-# else
-
+#elif (APR_HAS_THREADS && !USE_SIMPLE_MUTEX)
if (cache->lock)
{
apr_status_t status = apr_thread_rwlock_unlock(cache->lock);
@@ -719,9 +709,10 @@ unlock_cache(svn_membuffer_t *cache, svn
return svn_error_wrap_apr(status, _("Can't unlock cache mutex"));
}
-# endif
-#endif
return err;
+#else
+ return err;
+#endif
}
/* If supported, guard the execution of EXPR with a read lock to cache.
@@ -1797,17 +1788,14 @@ svn_cache__membuffer_cache_create(svn_me
return svn_error_wrap_apr(APR_ENOMEM, "OOM");
}
-#if APR_HAS_THREADS
+#if (APR_HAS_THREADS && USE_SIMPLE_MUTEX)
/* A lock for intra-process synchronization to the cache, or NULL if
* the cache's creator doesn't feel the cache needs to be
* thread-safe.
*/
-# if USE_SIMPLE_MUTEX
-
SVN_ERR(svn_mutex__init(&c[seg].lock, thread_safe, pool));
-
-# else
-
+#elif (APR_HAS_THREADS && !USE_SIMPLE_MUTEX)
+ /* Same for read-write lock. */
c[seg].lock = NULL;
if (thread_safe)
{
@@ -1817,8 +1805,6 @@ svn_cache__membuffer_cache_create(svn_me
return svn_error_wrap_apr(status, _("Can't create cache mutex"));
}
-# endif
-
/* Select the behavior of write operations.
*/
c[seg].allow_blocking_writes = allow_blocking_writes;