From e94168acd89dba4faef5e43f970633a781e8cba2 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 16 May 2023 22:21:24 +0000 Subject: Import wiredtiger: d310d6330ea5b23835d9eb231f65bb9f91bdef21 from branch mongodb-master ref: 2a63f4a39c..d310d6330e for: 7.1.0-rc0 WT-11066 Add mechanisms for checking whether a session holds a spinlock --- src/third_party/wiredtiger/dist/s_funcs.list | 2 + src/third_party/wiredtiger/dist/s_string.ok | 1 + src/third_party/wiredtiger/import.data | 2 +- src/third_party/wiredtiger/src/include/extern.h | 5 ++ src/third_party/wiredtiger/src/include/mutex.h | 3 +- .../wiredtiger/src/include/mutex_inline.h | 70 +++++++++++++++++++++- src/third_party/wiredtiger/src/include/session.h | 6 ++ 7 files changed, 84 insertions(+), 5 deletions(-) diff --git a/src/third_party/wiredtiger/dist/s_funcs.list b/src/third_party/wiredtiger/dist/s_funcs.list index 1b831580e27..7ac890052d6 100644 --- a/src/third_party/wiredtiger/dist/s_funcs.list +++ b/src/third_party/wiredtiger/dist/s_funcs.list @@ -31,6 +31,8 @@ __wt_nlpo2 __wt_nlpo2_round __wt_print_huffman_code __wt_session_breakpoint +__wt_spin_locked +__wt_spin_unlock_if_owned __wt_stat_join_aggregate __wt_stat_join_clear_all __wt_strcat diff --git a/src/third_party/wiredtiger/dist/s_string.ok b/src/third_party/wiredtiger/dist/s_string.ok index b6dd3317d7c..cdfa81cadef 100644 --- a/src/third_party/wiredtiger/dist/s_string.ok +++ b/src/third_party/wiredtiger/dist/s_string.ok @@ -329,6 +329,7 @@ SDK SIMD SLVG SMT +SPINLOCK SSHH SSq STR diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index cef97e34740..426b41c6c48 100644 --- a/src/third_party/wiredtiger/import.data +++ b/src/third_party/wiredtiger/import.data @@ -2,5 +2,5 @@ "vendor": "wiredtiger", "github": "wiredtiger/wiredtiger.git", "branch": "mongodb-master", - "commit": "2a63f4a39c3a74467005c2c7423823f22f5af394" + "commit": "d310d6330ea5b23835d9eb231f65bb9f91bdef21" } diff --git a/src/third_party/wiredtiger/src/include/extern.h b/src/third_party/wiredtiger/src/include/extern.h index 4fa14f94f2a..19e55c1feee 100644 --- a/src/third_party/wiredtiger/src/include/extern.h +++ b/src/third_party/wiredtiger/src/include/extern.h @@ -2085,6 +2085,10 @@ static inline bool __wt_row_leaf_value_is_encoded(WT_ROW *rip) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); static inline bool __wt_session_can_wait(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); +static inline bool __wt_spin_locked(WT_SESSION_IMPL *session, WT_SPINLOCK *t) + WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); +static inline bool __wt_spin_owned(WT_SESSION_IMPL *session, WT_SPINLOCK *t) + WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); static inline bool __wt_split_descent_race(WT_SESSION_IMPL *session, WT_REF *ref, WT_PAGE_INDEX *saved_pindex) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); static inline bool __wt_txn_tw_start_visible(WT_SESSION_IMPL *session, WT_TIME_WINDOW *tw) @@ -2480,6 +2484,7 @@ static inline void __wt_spin_destroy(WT_SESSION_IMPL *session, WT_SPINLOCK *t); static inline void __wt_spin_lock(WT_SESSION_IMPL *session, WT_SPINLOCK *t); static inline void __wt_spin_lock_track(WT_SESSION_IMPL *session, WT_SPINLOCK *t); static inline void __wt_spin_unlock(WT_SESSION_IMPL *session, WT_SPINLOCK *t); +static inline void __wt_spin_unlock_if_owned(WT_SESSION_IMPL *session, WT_SPINLOCK *t); static inline void __wt_struct_size_adjust(WT_SESSION_IMPL *session, size_t *sizep); static inline void __wt_timing_stress(WT_SESSION_IMPL *session, u_int flag, struct timespec *tsp); static inline void __wt_timing_stress_sleep_random(WT_SESSION_IMPL *session); diff --git a/src/third_party/wiredtiger/src/include/mutex.h b/src/third_party/wiredtiger/src/include/mutex.h index 43eb7b2376a..143de6ce6f9 100644 --- a/src/third_party/wiredtiger/src/include/mutex.h +++ b/src/third_party/wiredtiger/src/include/mutex.h @@ -108,7 +108,8 @@ struct __wt_spinlock { #error Unknown spinlock type #endif - const char *name; /* Mutex name */ + const char *name; /* Mutex name */ + uint32_t session_id; /* The session ID */ /* * We track acquisitions and time spent waiting for some locks. For performance reasons and to diff --git a/src/third_party/wiredtiger/src/include/mutex_inline.h b/src/third_party/wiredtiger/src/include/mutex_inline.h index 8fab4d84628..3b6405bb442 100644 --- a/src/third_party/wiredtiger/src/include/mutex_inline.h +++ b/src/third_party/wiredtiger/src/include/mutex_inline.h @@ -13,6 +13,13 @@ * the spin lock are expected to complete in a small number of instructions. */ +/* + * WT_SPIN_SESSION_ID_SAFE -- + * Get the session ID. We need this because there are a few calls to lock and unlock where the + * session parameter is actually NULL. + */ +#define WT_SPIN_SESSION_ID_SAFE(session) ((session) != NULL ? (session)->id : WT_SESSION_ID_NULL) + /* * __spin_init_internal -- * Initialize the WT portion of a spinlock. @@ -21,6 +28,7 @@ static inline void __spin_init_internal(WT_SPINLOCK *t, const char *name) { t->name = name; + t->session_id = WT_SESSION_ID_INVALID; t->stat_count_off = t->stat_app_usecs_off = t->stat_int_usecs_off = -1; t->stat_session_usecs_off = -1; t->initialized = 1; @@ -68,7 +76,11 @@ __wt_spin_trylock(WT_SESSION_IMPL *session, WT_SPINLOCK *t) { WT_UNUSED(session); - return (!__atomic_test_and_set(&t->lock, __ATOMIC_ACQUIRE) ? 0 : EBUSY); + if (!__atomic_test_and_set(&t->lock, __ATOMIC_ACQUIRE)) { + t->session_id = WT_SPIN_SESSION_ID_SAFE(session); + return (0); + } else + return (EBUSY); } /* @@ -88,6 +100,8 @@ __wt_spin_lock(WT_SESSION_IMPL *session, WT_SPINLOCK *t) if (t->lock) __wt_yield(); } + + t->session_id = WT_SPIN_SESSION_ID_SAFE(session); } /* @@ -99,6 +113,7 @@ __wt_spin_unlock(WT_SESSION_IMPL *session, WT_SPINLOCK *t) { WT_UNUSED(session); + t->session_id = WT_SESSION_ID_INVALID; __atomic_clear(&t->lock, __ATOMIC_RELEASE); } @@ -154,9 +169,13 @@ __wt_spin_destroy(WT_SESSION_IMPL *session, WT_SPINLOCK *t) static inline int __wt_spin_trylock(WT_SESSION_IMPL *session, WT_SPINLOCK *t) { + WT_DECL_RET; WT_UNUSED(session); - return (pthread_mutex_trylock(&t->lock)); + ret = pthread_mutex_trylock(&t->lock); + if (ret == 0) + t->session_id = WT_SPIN_SESSION_ID_SAFE(session); + return (ret); } /* @@ -170,6 +189,7 @@ __wt_spin_lock(WT_SESSION_IMPL *session, WT_SPINLOCK *t) if ((ret = pthread_mutex_lock(&t->lock)) != 0) WT_IGNORE_RET(__wt_panic(session, ret, "pthread_mutex_lock: %s", t->name)); + t->session_id = WT_SPIN_SESSION_ID_SAFE(session); } #endif @@ -182,6 +202,7 @@ __wt_spin_unlock(WT_SESSION_IMPL *session, WT_SPINLOCK *t) { WT_DECL_RET; + t->session_id = WT_SESSION_ID_INVALID; if ((ret = pthread_mutex_unlock(&t->lock)) != 0) WT_IGNORE_RET(__wt_panic(session, ret, "pthread_mutex_unlock: %s", t->name)); } @@ -233,7 +254,10 @@ __wt_spin_trylock(WT_SESSION_IMPL *session, WT_SPINLOCK *t) WT_UNUSED(session); BOOL b = TryEnterCriticalSection(&t->lock); - return (b == 0 ? EBUSY : 0); + if (b == 0) + return (EBUSY); + t->session_id = WT_SPIN_SESSION_ID_SAFE(session); + return (0); } /* @@ -246,6 +270,7 @@ __wt_spin_lock(WT_SESSION_IMPL *session, WT_SPINLOCK *t) WT_UNUSED(session); EnterCriticalSection(&t->lock); + t->session_id = WT_SPIN_SESSION_ID_SAFE(session); } /* @@ -257,6 +282,7 @@ __wt_spin_unlock(WT_SESSION_IMPL *session, WT_SPINLOCK *t) { WT_UNUSED(session); + t->session_id = WT_SESSION_ID_INVALID; LeaveCriticalSection(&t->lock); } @@ -266,6 +292,44 @@ __wt_spin_unlock(WT_SESSION_IMPL *session, WT_SPINLOCK *t) #endif +/* + * __wt_spin_locked -- + * Check whether the spinlock is locked, irrespective of which session locked it. + */ +static inline bool +__wt_spin_locked(WT_SESSION_IMPL *session, WT_SPINLOCK *t) +{ + WT_UNUSED(session); + return (t->session_id != WT_SESSION_ID_INVALID); +} + +/* + * __wt_spin_owned -- + * Check whether the session owns the spinlock. + */ +static inline bool +__wt_spin_owned(WT_SESSION_IMPL *session, WT_SPINLOCK *t) +{ + return (t->session_id == WT_SPIN_SESSION_ID_SAFE(session)); +} + +/* + * __wt_spin_unlock_if_owned -- + * Unlock the spinlock only if it is acquired by the specified session. + */ +static inline void +__wt_spin_unlock_if_owned(WT_SESSION_IMPL *session, WT_SPINLOCK *t) +{ + if (__wt_spin_owned(session, t)) + __wt_spin_unlock(session, t); +} + +/* + * WT_ASSERT_SPINLOCK_OWNED -- + * Assert that the session owns the spinlock. + */ +#define WT_ASSERT_SPINLOCK_OWNED(session, t) WT_ASSERT((session), __wt_spin_owned((session), (t))); + /* * WT_SPIN_INIT_TRACKED -- * Spinlock initialization, with tracking. diff --git a/src/third_party/wiredtiger/src/include/session.h b/src/third_party/wiredtiger/src/include/session.h index 43a336eb214..f9a49ae7030 100644 --- a/src/third_party/wiredtiger/src/include/session.h +++ b/src/third_party/wiredtiger/src/include/session.h @@ -53,6 +53,12 @@ typedef TAILQ_HEAD(__wt_cursor_list, __wt_cursor) WT_CURSOR_LIST; /* Maximum number of buckets to visit during a regular cursor sweep. */ #define WT_SESSION_CURSOR_SWEEP_MAX 64 +/* Invalid session ID. */ +#define WT_SESSION_ID_INVALID 0xffffffff + +/* A fake session ID for when we need to refer to a session that is actually NULL. */ +#define WT_SESSION_ID_NULL 0xfffffffe + /* * WT_SESSION_IMPL -- * Implementation of WT_SESSION. -- cgit v1.2.1