thread: detect spinlocks that are not initialized
If spdk_spin_lock() is called on an uninitialized spinlock, it will deadlock. This commit detects whether a lock is initialized and aborts instead of deadlocking. Signed-off-by: Mike Gerdts <mgerdts@nvidia.com> Change-Id: Ie7497633091edd4127c06ca0530e9a1dff530d1b Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16002 Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
4077eff3ae
commit
80ab43ae97
@ -905,6 +905,8 @@ struct spdk_spinlock {
|
|||||||
pthread_spinlock_t spinlock;
|
pthread_spinlock_t spinlock;
|
||||||
struct spdk_thread *thread;
|
struct spdk_thread *thread;
|
||||||
struct spdk_spinlock_internal *internal;
|
struct spdk_spinlock_internal *internal;
|
||||||
|
bool initialized;
|
||||||
|
bool destroyed;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -185,6 +185,11 @@ enum spin_error {
|
|||||||
* deadlock when another SPDK thread on the same pthread tries to take that lock.
|
* deadlock when another SPDK thread on the same pthread tries to take that lock.
|
||||||
*/
|
*/
|
||||||
SPIN_ERR_HOLD_DURING_SWITCH,
|
SPIN_ERR_HOLD_DURING_SWITCH,
|
||||||
|
/* Trying to use a lock that was destroyed (but not re-initialized) */
|
||||||
|
SPIN_ERR_DESTROYED,
|
||||||
|
/* Trying to use a lock that is not initialized */
|
||||||
|
SPIN_ERR_NOT_INITIALIZED,
|
||||||
|
|
||||||
/* Must be last, not an actual error code */
|
/* Must be last, not an actual error code */
|
||||||
SPIN_ERR_LAST
|
SPIN_ERR_LAST
|
||||||
};
|
};
|
||||||
@ -198,6 +203,8 @@ static const char *spin_error_strings[] = {
|
|||||||
[SPIN_ERR_LOCK_HELD] = "Destroying a held spinlock",
|
[SPIN_ERR_LOCK_HELD] = "Destroying a held spinlock",
|
||||||
[SPIN_ERR_LOCK_COUNT] = "Lock count is invalid",
|
[SPIN_ERR_LOCK_COUNT] = "Lock count is invalid",
|
||||||
[SPIN_ERR_HOLD_DURING_SWITCH] = "Lock(s) held while SPDK thread going off CPU",
|
[SPIN_ERR_HOLD_DURING_SWITCH] = "Lock(s) held while SPDK thread going off CPU",
|
||||||
|
[SPIN_ERR_DESTROYED] = "Lock has been destroyed",
|
||||||
|
[SPIN_ERR_NOT_INITIALIZED] = "Lock has not been initialized",
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SPIN_ERROR_STRING(err) (err < 0 || err >= SPDK_COUNTOF(spin_error_strings)) \
|
#define SPIN_ERROR_STRING(err) (err < 0 || err >= SPDK_COUNTOF(spin_error_strings)) \
|
||||||
@ -2971,6 +2978,7 @@ spdk_spin_init(struct spdk_spinlock *sspin)
|
|||||||
SPIN_ASSERT_LOG_STACKS(rc == 0, SPIN_ERR_PTHREAD, sspin);
|
SPIN_ASSERT_LOG_STACKS(rc == 0, SPIN_ERR_PTHREAD, sspin);
|
||||||
sspin_init_internal(sspin);
|
sspin_init_internal(sspin);
|
||||||
SSPIN_GET_STACK(sspin, init);
|
SSPIN_GET_STACK(sspin, init);
|
||||||
|
sspin->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2978,12 +2986,16 @@ spdk_spin_destroy(struct spdk_spinlock *sspin)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
SPIN_ASSERT_LOG_STACKS(!sspin->destroyed, SPIN_ERR_DESTROYED, sspin);
|
||||||
|
SPIN_ASSERT_LOG_STACKS(sspin->initialized, SPIN_ERR_NOT_INITIALIZED, sspin);
|
||||||
SPIN_ASSERT_LOG_STACKS(sspin->thread == NULL, SPIN_ERR_LOCK_HELD, sspin);
|
SPIN_ASSERT_LOG_STACKS(sspin->thread == NULL, SPIN_ERR_LOCK_HELD, sspin);
|
||||||
|
|
||||||
rc = pthread_spin_destroy(&sspin->spinlock);
|
rc = pthread_spin_destroy(&sspin->spinlock);
|
||||||
SPIN_ASSERT_LOG_STACKS(rc == 0, SPIN_ERR_PTHREAD, sspin);
|
SPIN_ASSERT_LOG_STACKS(rc == 0, SPIN_ERR_PTHREAD, sspin);
|
||||||
|
|
||||||
sspin_fini_internal(sspin);
|
sspin_fini_internal(sspin);
|
||||||
|
sspin->initialized = false;
|
||||||
|
sspin->destroyed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2992,6 +3004,8 @@ spdk_spin_lock(struct spdk_spinlock *sspin)
|
|||||||
struct spdk_thread *thread = spdk_get_thread();
|
struct spdk_thread *thread = spdk_get_thread();
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
SPIN_ASSERT_LOG_STACKS(!sspin->destroyed, SPIN_ERR_DESTROYED, sspin);
|
||||||
|
SPIN_ASSERT_LOG_STACKS(sspin->initialized, SPIN_ERR_NOT_INITIALIZED, sspin);
|
||||||
SPIN_ASSERT_LOG_STACKS(thread != NULL, SPIN_ERR_NOT_SPDK_THREAD, sspin);
|
SPIN_ASSERT_LOG_STACKS(thread != NULL, SPIN_ERR_NOT_SPDK_THREAD, sspin);
|
||||||
SPIN_ASSERT_LOG_STACKS(thread != sspin->thread, SPIN_ERR_DEADLOCK, sspin);
|
SPIN_ASSERT_LOG_STACKS(thread != sspin->thread, SPIN_ERR_DEADLOCK, sspin);
|
||||||
|
|
||||||
@ -3010,6 +3024,8 @@ spdk_spin_unlock(struct spdk_spinlock *sspin)
|
|||||||
struct spdk_thread *thread = spdk_get_thread();
|
struct spdk_thread *thread = spdk_get_thread();
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
SPIN_ASSERT_LOG_STACKS(!sspin->destroyed, SPIN_ERR_DESTROYED, sspin);
|
||||||
|
SPIN_ASSERT_LOG_STACKS(sspin->initialized, SPIN_ERR_NOT_INITIALIZED, sspin);
|
||||||
SPIN_ASSERT_LOG_STACKS(thread != NULL, SPIN_ERR_NOT_SPDK_THREAD, sspin);
|
SPIN_ASSERT_LOG_STACKS(thread != NULL, SPIN_ERR_NOT_SPDK_THREAD, sspin);
|
||||||
SPIN_ASSERT_LOG_STACKS(thread == sspin->thread, SPIN_ERR_WRONG_THREAD, sspin);
|
SPIN_ASSERT_LOG_STACKS(thread == sspin->thread, SPIN_ERR_WRONG_THREAD, sspin);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user