From a44537d8c7dc62493634dc9a774c97d2eb6892a9 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sat, 30 Aug 2008 15:05:14 +0000 Subject: [PATCH] DEVEL15-windows-lock-order-validation-20080830 LICENSE MIT Add osi_SetLockOrderValidation(int) to permit lock order validation to be turned on and off. Must be executed before the first lock is obtained. (cherry picked from commit a36596f10ff4d87d75a808cabe4e0e5ec661c5df) --- src/WINNT/client_osi/libosi.def | 1 + src/WINNT/client_osi/osibasel.c | 126 +++++++++++++++++++------------- 2 files changed, 76 insertions(+), 51 deletions(-) diff --git a/src/WINNT/client_osi/libosi.def b/src/WINNT/client_osi/libosi.def index 555d22fc9..bbb229ed5 100644 --- a/src/WINNT/client_osi/libosi.def +++ b/src/WINNT/client_osi/libosi.def @@ -72,3 +72,4 @@ EXPORTS osi_QRemoveHT @65 lock_ConvertRToW @66 osi_LogSaveStringW @67 + osi_SetLockOrderValidation @68 diff --git a/src/WINNT/client_osi/osibasel.c b/src/WINNT/client_osi/osibasel.c index 41a52ada0..1779f976e 100644 --- a/src/WINNT/client_osi/osibasel.c +++ b/src/WINNT/client_osi/osibasel.c @@ -25,6 +25,7 @@ static long atomicIndexCounter = 0; /* Thread local storage index for lock tracking */ static DWORD tls_LockRefH = 0; static DWORD tls_LockRefT = 0; +static BOOLEAN lockOrderValidation = 0; void osi_BaseInit(void) { @@ -40,6 +41,11 @@ void osi_BaseInit(void) osi_panic("TlsAlloc(tls_LockRefT) failure", __FILE__, __LINE__); } +void osi_SetLockOrderValidation(int on) +{ + lockOrderValidation = (BOOLEAN)on; +} + osi_lock_ref_t *lock_GetLockRef(void * lockp, char type) { osi_lock_ref_t * lockRefp = (osi_lock_ref_t *)malloc(sizeof(osi_lock_ref_t)); @@ -126,11 +132,13 @@ void lock_ObtainWrite(osi_rwlock_t *lockp) return; } - lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); - lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); + if (lockOrderValidation) { + lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); + lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); - if (lockp->level != 0) - lock_VerifyOrderRW(lockRefH, lockRefT, lockp); + if (lockp->level != 0) + lock_VerifyOrderRW(lockRefH, lockRefT, lockp); + } /* otherwise we're the fast base type */ csp = &osi_baseAtomicCS[lockp->atomicIndex]; @@ -153,10 +161,12 @@ void lock_ObtainWrite(osi_rwlock_t *lockp) LeaveCriticalSection(csp); - lockRefp = lock_GetLockRef(lockp, OSI_LOCK_RW); - osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q); - TlsSetValue(tls_LockRefH, lockRefH); - TlsSetValue(tls_LockRefT, lockRefT); + if (lockOrderValidation) { + lockRefp = lock_GetLockRef(lockp, OSI_LOCK_RW); + osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q); + TlsSetValue(tls_LockRefH, lockRefH); + TlsSetValue(tls_LockRefT, lockRefT); + } } void lock_ObtainRead(osi_rwlock_t *lockp) @@ -172,11 +182,13 @@ void lock_ObtainRead(osi_rwlock_t *lockp) return; } - lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); - lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); + if (lockOrderValidation) { + lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); + lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); - if (lockp->level != 0) - lock_VerifyOrderRW(lockRefH, lockRefT, lockp); + if (lockp->level != 0) + lock_VerifyOrderRW(lockRefH, lockRefT, lockp); + } /* otherwise we're the fast base type */ csp = &osi_baseAtomicCS[lockp->atomicIndex]; @@ -196,10 +208,12 @@ void lock_ObtainRead(osi_rwlock_t *lockp) LeaveCriticalSection(csp); - lockRefp = lock_GetLockRef(lockp, OSI_LOCK_RW); - osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q); - TlsSetValue(tls_LockRefH, lockRefH); - TlsSetValue(tls_LockRefT, lockRefT); + if (lockOrderValidation) { + lockRefp = lock_GetLockRef(lockp, OSI_LOCK_RW); + osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q); + TlsSetValue(tls_LockRefH, lockRefH); + TlsSetValue(tls_LockRefT, lockRefT); + } } void lock_ReleaseRead(osi_rwlock_t *lockp) @@ -215,7 +229,7 @@ void lock_ReleaseRead(osi_rwlock_t *lockp) return; } - if (lockp->level != 0) { + if (lockOrderValidation && lockp->level != 0) { int found = 0; lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); @@ -263,7 +277,7 @@ void lock_ReleaseWrite(osi_rwlock_t *lockp) return; } - if (lockp->level != 0) { + if (lockOrderValidation && lockp->level != 0) { int found = 0; lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); @@ -379,11 +393,13 @@ void lock_ObtainMutex(struct osi_mutex *lockp) return; } - lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); - lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); + if (lockOrderValidation) { + lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); + lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); - if (lockp->level != 0) - lock_VerifyOrderMX(lockRefH, lockRefT, lockp); + if (lockp->level != 0) + lock_VerifyOrderMX(lockRefH, lockRefT, lockp); + } /* otherwise we're the fast base type */ csp = &osi_baseAtomicCS[lockp->atomicIndex]; @@ -403,10 +419,12 @@ void lock_ObtainMutex(struct osi_mutex *lockp) lockp->tid = thrd_Current(); LeaveCriticalSection(csp); - lockRefp = lock_GetLockRef(lockp, OSI_LOCK_MUTEX); - osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q); - TlsSetValue(tls_LockRefH, lockRefH); - TlsSetValue(tls_LockRefT, lockRefT); + if (lockOrderValidation) { + lockRefp = lock_GetLockRef(lockp, OSI_LOCK_MUTEX); + osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q); + TlsSetValue(tls_LockRefH, lockRefH); + TlsSetValue(tls_LockRefT, lockRefT); + } } void lock_ReleaseMutex(struct osi_mutex *lockp) @@ -422,7 +440,7 @@ void lock_ReleaseMutex(struct osi_mutex *lockp) return; } - if (lockp->level != 0) { + if (lockOrderValidation && lockp->level != 0) { int found = 0; lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); @@ -470,13 +488,15 @@ int lock_TryRead(struct osi_rwlock *lockp) if (i >= 0 && i < OSI_NLOCKTYPES) return (osi_lockOps[i]->TryReadProc)(lockp); - lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); - lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); + if (lockOrderValidation) { + lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); + lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); - if (lockp->level != 0) { - for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) { - if (lockRefp->type == OSI_LOCK_RW) { - osi_assertx(lockRefp->rw != lockp, "RW Lock already held"); + if (lockp->level != 0) { + for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) { + if (lockRefp->type == OSI_LOCK_RW) { + osi_assertx(lockRefp->rw != lockp, "RW Lock already held"); + } } } } @@ -497,7 +517,7 @@ int lock_TryRead(struct osi_rwlock *lockp) LeaveCriticalSection(csp); - if (i) { + if (lockOrderValidation && i) { lockRefp = lock_GetLockRef(lockp, OSI_LOCK_RW); osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q); TlsSetValue(tls_LockRefH, lockRefH); @@ -519,13 +539,15 @@ int lock_TryWrite(struct osi_rwlock *lockp) if (i >= 0 && i < OSI_NLOCKTYPES) return (osi_lockOps[i]->TryWriteProc)(lockp); - lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); - lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); + if (lockOrderValidation) { + lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); + lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); - if (lockp->level != 0) { - for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) { - if (lockRefp->type == OSI_LOCK_RW) { - osi_assertx(lockRefp->rw != lockp, "RW Lock already held"); + if (lockp->level != 0) { + for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) { + if (lockRefp->type == OSI_LOCK_RW) { + osi_assertx(lockRefp->rw != lockp, "RW Lock already held"); + } } } } @@ -550,7 +572,7 @@ int lock_TryWrite(struct osi_rwlock *lockp) LeaveCriticalSection(csp); - if (i) { + if (lockOrderValidation && i) { lockRefp = lock_GetLockRef(lockp, OSI_LOCK_RW); osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q); TlsSetValue(tls_LockRefH, lockRefH); @@ -571,13 +593,15 @@ int lock_TryMutex(struct osi_mutex *lockp) { if (i >= 0 && i < OSI_NLOCKTYPES) return (osi_lockOps[i]->TryMutexProc)(lockp); - lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); - lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); + if (lockOrderValidation) { + lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); + lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); - if (lockp->level != 0) { - for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) { - if (lockRefp->type == OSI_LOCK_MUTEX) { - osi_assertx(lockRefp->mx != lockp, "Mutex already held"); + if (lockp->level != 0) { + for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) { + if (lockRefp->type == OSI_LOCK_MUTEX) { + osi_assertx(lockRefp->mx != lockp, "Mutex already held"); + } } } } @@ -601,7 +625,7 @@ int lock_TryMutex(struct osi_mutex *lockp) { LeaveCriticalSection(csp); - if (i) { + if (lockOrderValidation && i) { lockRefp = lock_GetLockRef(lockp, OSI_LOCK_MUTEX); osi_QAddH(&lockRefH, &lockRefT, &lockRefp->q); TlsSetValue(tls_LockRefH, lockRefH); @@ -623,7 +647,7 @@ void osi_SleepR(LONG_PTR sleepVal, struct osi_rwlock *lockp) return; } - if (lockp->level != 0) { + if (lockOrderValidation && lockp->level != 0) { lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); @@ -669,7 +693,7 @@ void osi_SleepW(LONG_PTR sleepVal, struct osi_rwlock *lockp) return; } - if (lockp->level != 0) { + if (lockOrderValidation && lockp->level != 0) { lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); @@ -713,7 +737,7 @@ void osi_SleepM(LONG_PTR sleepVal, struct osi_mutex *lockp) return; } - if (lockp->level != 0) { + if (lockOrderValidation && lockp->level != 0) { lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH); lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT); -- 2.39.5