aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorJason Evans <jasone@canonware.com>2016-10-31 11:45:41 -0700
committerJason Evans <jasone@canonware.com>2016-10-31 11:51:39 -0700
commit4752a54eebe1945d1cf9eeecaccbca3ed743f240 (patch)
treeb15965e20d59862faf63403173e9f32a0c43ad05 /include
parent1d57c03e331ec9763ba55476a53aa1716f1bc8e1 (diff)
downloadjemalloc-4752a54eebe1945d1cf9eeecaccbca3ed743f240.tar.gz
Refactor witness_unlock() to fix undefined test behavior.
This resolves #396.
Diffstat (limited to 'include')
-rw-r--r--include/jemalloc/internal/private_symbols.txt1
-rw-r--r--include/jemalloc/internal/witness.h39
2 files changed, 29 insertions, 11 deletions
diff --git a/include/jemalloc/internal/private_symbols.txt b/include/jemalloc/internal/private_symbols.txt
index 6221179..09ff832 100644
--- a/include/jemalloc/internal/private_symbols.txt
+++ b/include/jemalloc/internal/private_symbols.txt
@@ -607,6 +607,7 @@ witness_lock
witness_lock_error
witness_lockless_error
witness_not_owner_error
+witness_owner
witness_owner_error
witness_postfork_child
witness_postfork_parent
diff --git a/include/jemalloc/internal/witness.h b/include/jemalloc/internal/witness.h
index d78dca2..cdf15d7 100644
--- a/include/jemalloc/internal/witness.h
+++ b/include/jemalloc/internal/witness.h
@@ -108,6 +108,7 @@ void witness_postfork_child(tsd_t *tsd);
#ifdef JEMALLOC_H_INLINES
#ifndef JEMALLOC_ENABLE_INLINE
+bool witness_owner(tsd_t *tsd, const witness_t *witness);
void witness_assert_owner(tsdn_t *tsdn, const witness_t *witness);
void witness_assert_not_owner(tsdn_t *tsdn, const witness_t *witness);
void witness_assert_lockless(tsdn_t *tsdn);
@@ -116,12 +117,25 @@ void witness_unlock(tsdn_t *tsdn, witness_t *witness);
#endif
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))
+JEMALLOC_INLINE bool
+witness_owner(tsd_t *tsd, const witness_t *witness)
+{
+ witness_list_t *witnesses;
+ witness_t *w;
+
+ witnesses = tsd_witnessesp_get(tsd);
+ ql_foreach(w, witnesses, link) {
+ if (w == witness)
+ return (true);
+ }
+
+ return (false);
+}
+
JEMALLOC_INLINE void
witness_assert_owner(tsdn_t *tsdn, const witness_t *witness)
{
tsd_t *tsd;
- witness_list_t *witnesses;
- witness_t *w;
if (!config_debug)
return;
@@ -132,11 +146,8 @@ witness_assert_owner(tsdn_t *tsdn, const witness_t *witness)
if (witness->rank == WITNESS_RANK_OMIT)
return;
- witnesses = tsd_witnessesp_get(tsd);
- ql_foreach(w, witnesses, link) {
- if (w == witness)
- return;
- }
+ if (witness_owner(tsd, witness))
+ return;
witness_owner_error(witness);
}
@@ -238,10 +249,16 @@ witness_unlock(tsdn_t *tsdn, witness_t *witness)
if (witness->rank == WITNESS_RANK_OMIT)
return;
- witness_assert_owner(tsdn, witness);
-
- witnesses = tsd_witnessesp_get(tsd);
- ql_remove(witnesses, witness, link);
+ /*
+ * Check whether owner before removal, rather than relying on
+ * witness_assert_owner() to abort, so that unit tests can test this
+ * function's failure mode without causing undefined behavior.
+ */
+ if (witness_owner(tsd, witness)) {
+ witnesses = tsd_witnessesp_get(tsd);
+ ql_remove(witnesses, witness, link);
+ } else
+ witness_assert_owner(tsdn, witness);
}
#endif