Lock object fixes.
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@476 0109f412-320b-0410-ab79-c3e0c5ffbbe6
This commit is contained in:
@@ -5740,6 +5740,11 @@ RCODE FLMAPI f_allocHashTable(
|
||||
FLMUINT uiHashTblSize,
|
||||
FBUCKET ** ppHashTblRV);
|
||||
|
||||
FLMUINT FLMAPI f_strHashBucket(
|
||||
char * pszStr,
|
||||
FBUCKET * pHashTbl,
|
||||
FLMUINT uiNumBuckets);
|
||||
|
||||
/**************************************************************************
|
||||
Desc:
|
||||
**************************************************************************/
|
||||
|
||||
@@ -39,8 +39,8 @@ typedef struct F_LOCK_WAITER
|
||||
FLMINT iPriority;
|
||||
F_TMSTAMP StartTime;
|
||||
F_LOCK_STATS * pLockStats;
|
||||
F_LOCK_WAITER * pNext;
|
||||
F_LOCK_WAITER * pPrev;
|
||||
F_LOCK_WAITER * pNextInList;
|
||||
F_LOCK_WAITER * pPrevInList;
|
||||
F_LOCK_WAITER * pNextByTime;
|
||||
F_LOCK_WAITER * pPrevByTime;
|
||||
} F_LOCK_WAITER;
|
||||
@@ -119,8 +119,10 @@ private:
|
||||
FLMUINT m_uiLockThreadId;
|
||||
FLMUINT m_uiLockTime;
|
||||
FLMUINT m_uiLockCount;
|
||||
F_LOCK_WAITER * m_pFirstLockWaiter;
|
||||
F_LOCK_WAITER * m_pLastLockWaiter;
|
||||
F_LOCK_WAITER * m_pFirstInList;
|
||||
F_LOCK_WAITER * m_pLastInList;
|
||||
F_LOCK_WAITER * m_pFirstToTimeout;
|
||||
F_LOCK_WAITER * m_pLastToTimeout;
|
||||
FLMUINT m_uiNumWaiters;
|
||||
FLMUINT m_uiSharedLockCnt;
|
||||
FLMBOOL m_bExclLock;
|
||||
@@ -171,8 +173,10 @@ F_LockObject::F_LockObject()
|
||||
m_uiLockThreadId = 0;
|
||||
m_uiLockTime = 0;
|
||||
m_uiLockCount = 0;
|
||||
m_pFirstLockWaiter = NULL;
|
||||
m_pLastLockWaiter = NULL;
|
||||
m_pFirstInList = NULL;
|
||||
m_pLastInList = NULL;
|
||||
m_pFirstToTimeout = NULL;
|
||||
m_pLastToTimeout = NULL;
|
||||
m_uiNumWaiters = 0;
|
||||
m_uiSharedLockCnt = 0;
|
||||
m_bExclLock = FALSE;
|
||||
@@ -264,32 +268,28 @@ RCODE F_LockObject::timeoutThread(
|
||||
{
|
||||
RCODE rc = NE_FLM_OK;
|
||||
F_LockObject * pThis = (F_LockObject *)pThread->getParm1();
|
||||
FLMUINT uiLoop;
|
||||
FLMUINT uiCurrTime;
|
||||
F_LOCK_WAITER * pLockWaiter;
|
||||
|
||||
for( ;;)
|
||||
{
|
||||
if( pThread->getShutdownFlag())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( pThis->m_pFirstLockWaiter && pThis->m_pFirstLockWaiter->uiWaitTime)
|
||||
if( pThis->m_pFirstInList && pThis->m_pFirstInList->uiWaitTime)
|
||||
{
|
||||
f_mutexLock( pThis->m_hMutex);
|
||||
uiCurrTime = FLM_GET_TIMER();
|
||||
|
||||
while( pThis->m_pFirstLockWaiter &&
|
||||
pThis->m_pFirstLockWaiter->uiWaitTime &&
|
||||
while( pThis->m_pFirstToTimeout &&
|
||||
pThis->m_pFirstToTimeout->uiWaitTime &&
|
||||
FLM_ELAPSED_TIME( uiCurrTime,
|
||||
pThis->m_pFirstLockWaiter->uiWaitStartTime) >=
|
||||
pThis->m_pFirstLockWaiter->uiWaitTime)
|
||||
pThis->m_pFirstToTimeout->uiWaitStartTime) >=
|
||||
pThis->m_pFirstToTimeout->uiWaitTime)
|
||||
{
|
||||
f_assert( !pThis->m_pFirstLockWaiter->pPrevByTime);
|
||||
f_assert( !pThis->m_pFirstToTimeout->pPrevByTime);
|
||||
|
||||
// Lock waiter has timed out.
|
||||
|
||||
pLockWaiter = pThis->m_pFirstLockWaiter;
|
||||
pLockWaiter = pThis->m_pFirstToTimeout;
|
||||
|
||||
// Remove the waiter from the list
|
||||
|
||||
@@ -303,9 +303,19 @@ RCODE F_LockObject::timeoutThread(
|
||||
|
||||
f_mutexUnlock( pThis->m_hMutex);
|
||||
}
|
||||
|
||||
for( uiLoop = 0; uiLoop < 100; uiLoop++)
|
||||
{
|
||||
if( pThread->getShutdownFlag())
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
f_sleep( 1000);
|
||||
f_sleep( 10);
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
return( rc);
|
||||
}
|
||||
@@ -323,7 +333,7 @@ void FLMAPI F_LockObject::timeoutLockWaiter(
|
||||
f_mutexLock( m_hMutex);
|
||||
uiCurrTime = FLM_GET_TIMER();
|
||||
|
||||
for( pLockWaiter = m_pFirstLockWaiter;
|
||||
for( pLockWaiter = m_pFirstToTimeout;
|
||||
pLockWaiter;
|
||||
pLockWaiter = pNextWaiter)
|
||||
{
|
||||
@@ -356,9 +366,9 @@ void FLMAPI F_LockObject::timeoutAllWaiters( void)
|
||||
|
||||
f_mutexLock( m_hMutex);
|
||||
|
||||
while( m_pFirstLockWaiter)
|
||||
while( m_pFirstInList)
|
||||
{
|
||||
pLockWaiter = m_pFirstLockWaiter;
|
||||
pLockWaiter = m_pFirstInList;
|
||||
removeWaiter( pLockWaiter);
|
||||
*(pLockWaiter->pRc) = RC_SET( NE_FLM_LOCK_REQ_TIMEOUT);
|
||||
f_semSignal( pLockWaiter->hWaitSem);
|
||||
@@ -376,9 +386,22 @@ void F_LockObject::insertWaiter(
|
||||
{
|
||||
F_LOCK_WAITER * pPrevLockWaiter;
|
||||
|
||||
// Link into list of waiters on this object.
|
||||
|
||||
if( (pLockWaiter->pPrevInList = m_pLastInList) != NULL)
|
||||
{
|
||||
pLockWaiter->pPrevInList->pNextInList = pLockWaiter;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pFirstInList = pLockWaiter;
|
||||
}
|
||||
|
||||
m_pLastInList = pLockWaiter;
|
||||
|
||||
// Determine where in the list this lock waiter should go.
|
||||
|
||||
if ((pPrevLockWaiter = m_pFirstLockWaiter) != NULL)
|
||||
if ((pPrevLockWaiter = m_pFirstToTimeout) != NULL)
|
||||
{
|
||||
FLMUINT uiCurrTime = FLM_GET_TIMER();
|
||||
FLMUINT uiElapTime;
|
||||
@@ -436,7 +459,10 @@ void F_LockObject::insertWaiter(
|
||||
else
|
||||
{
|
||||
if (!pPrevLockWaiter->pNextByTime)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pPrevLockWaiter = pPrevLockWaiter->pNextByTime;
|
||||
}
|
||||
}
|
||||
@@ -456,13 +482,15 @@ void F_LockObject::insertWaiter(
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (pLockWaiter->pNextByTime = m_pFirstLockWaiter) != NULL)
|
||||
if( (pLockWaiter->pNextByTime = m_pFirstToTimeout) != NULL)
|
||||
{
|
||||
m_pFirstLockWaiter->pPrevByTime = pLockWaiter;
|
||||
m_pFirstToTimeout->pPrevByTime = pLockWaiter;
|
||||
}
|
||||
|
||||
m_pFirstLockWaiter = pLockWaiter;
|
||||
m_pFirstToTimeout = pLockWaiter;
|
||||
}
|
||||
|
||||
m_uiNumWaiters++;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -482,25 +510,25 @@ void F_LockObject::removeWaiter(
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pFirstLockWaiter = pLockWaiter->pNextByTime;
|
||||
m_pFirstToTimeout = pLockWaiter->pNextByTime;
|
||||
}
|
||||
|
||||
if (pLockWaiter->pNext)
|
||||
if (pLockWaiter->pNextInList)
|
||||
{
|
||||
pLockWaiter->pNext->pPrev = pLockWaiter->pPrev;
|
||||
pLockWaiter->pNextInList->pPrevInList = pLockWaiter->pPrevInList;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pLastLockWaiter = pLockWaiter->pPrev;
|
||||
m_pLastInList = pLockWaiter->pPrevInList;
|
||||
}
|
||||
|
||||
if (pLockWaiter->pPrev)
|
||||
if (pLockWaiter->pPrevInList)
|
||||
{
|
||||
pLockWaiter->pPrev->pNext = pLockWaiter->pNext;
|
||||
pLockWaiter->pPrevInList->pNextInList = pLockWaiter->pNextInList;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pFirstLockWaiter = pLockWaiter->pNext;
|
||||
m_pFirstInList = pLockWaiter->pNextInList;
|
||||
}
|
||||
|
||||
f_assert( m_uiNumWaiters > 0);
|
||||
@@ -526,7 +554,7 @@ RCODE FLMAPI F_LockObject::lock(
|
||||
f_mutexLock( m_hMutex);
|
||||
bMutexLocked = TRUE;
|
||||
|
||||
if (m_pFirstLockWaiter || m_bExclLock || (bExclReq && m_uiSharedLockCnt))
|
||||
if (m_pFirstInList || m_bExclLock || (bExclReq && m_uiSharedLockCnt))
|
||||
{
|
||||
|
||||
// Object is locked by another thread, wait to get lock.
|
||||
@@ -542,20 +570,6 @@ RCODE FLMAPI F_LockObject::lock(
|
||||
f_memset( &LockWait, 0, sizeof( LockWait));
|
||||
LockWait.hWaitSem = hWaitSem;
|
||||
|
||||
// Link into list of waiters on this object.
|
||||
|
||||
if( (LockWait.pPrev = m_pLastLockWaiter) != NULL)
|
||||
{
|
||||
LockWait.pPrev->pNext = &LockWait;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pFirstLockWaiter = &LockWait;
|
||||
}
|
||||
|
||||
m_pLastLockWaiter = &LockWait;
|
||||
m_uiNumWaiters++;
|
||||
|
||||
LockWait.uiThreadId = f_threadId();
|
||||
LockWait.pRc = &rc;
|
||||
|
||||
@@ -704,18 +718,18 @@ RCODE FLMAPI F_LockObject::unlock(
|
||||
|
||||
// See if we need to signal the next set of waiters
|
||||
|
||||
if( m_pFirstLockWaiter && !m_uiSharedLockCnt)
|
||||
if( m_pFirstInList && !m_uiSharedLockCnt)
|
||||
{
|
||||
m_bExclLock = m_pFirstLockWaiter->bExclReq;
|
||||
m_bExclLock = m_pFirstInList->bExclReq;
|
||||
|
||||
while( m_pFirstLockWaiter)
|
||||
while( m_pFirstInList)
|
||||
{
|
||||
if (!m_bExclLock)
|
||||
{
|
||||
m_uiSharedLockCnt++;
|
||||
}
|
||||
|
||||
pLockWaiter = m_pFirstLockWaiter;
|
||||
pLockWaiter = m_pFirstInList;
|
||||
hWaitSem = pLockWaiter->hWaitSem;
|
||||
|
||||
// Unlink the waiter from the list of waiters on this lock object.
|
||||
@@ -723,9 +737,9 @@ RCODE FLMAPI F_LockObject::unlock(
|
||||
// IMPORTANT NOTE: Do NOT signal the semaphore until AFTER
|
||||
// doing this unlinking. This is because F_LOCK_WAITER
|
||||
// structures exist only on the stack of the thread
|
||||
// being signaled. If we tried to assign m_pFirstLockWaiter after
|
||||
// being signaled. If we tried to assign m_pFirstInList after
|
||||
// signaling the semaphore, the F_LOCK_WAITER structure could
|
||||
// disappear and m_pFirstLockWaiter would get garbage.
|
||||
// disappear and m_pFirstInList would get garbage.
|
||||
|
||||
removeWaiter( pLockWaiter);
|
||||
|
||||
@@ -763,7 +777,7 @@ RCODE FLMAPI F_LockObject::unlock(
|
||||
// here.
|
||||
|
||||
if (m_bExclLock ||
|
||||
(m_pFirstLockWaiter && m_pFirstLockWaiter->bExclReq))
|
||||
(m_pFirstInList && m_pFirstInList->bExclReq))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -826,8 +840,8 @@ RCODE FLMAPI F_LockObject::getLockInfo(
|
||||
|
||||
// Get information on pending lock requests.
|
||||
|
||||
pLockWaiter = m_pFirstLockWaiter;
|
||||
for( ; pLockWaiter; pLockWaiter = pLockWaiter->pNext)
|
||||
pLockWaiter = m_pFirstInList;
|
||||
for( ; pLockWaiter; pLockWaiter = pLockWaiter->pNextInList)
|
||||
{
|
||||
|
||||
// Count the number of exclusive and shared waiters.
|
||||
@@ -895,7 +909,7 @@ RCODE FLMAPI F_LockObject::getLockInfo(
|
||||
|
||||
// Output the lock waiters.
|
||||
|
||||
pLockWaiter = m_pFirstLockWaiter;
|
||||
pLockWaiter = m_pFirstInList;
|
||||
while( pLockWaiter && uiCnt)
|
||||
{
|
||||
uiElapTime = FLM_ELAPSED_TIME( uiCurrTime, pLockWaiter->uiWaitStartTime);
|
||||
@@ -907,7 +921,7 @@ RCODE FLMAPI F_LockObject::getLockInfo(
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
pLockWaiter = pLockWaiter->pNext;
|
||||
pLockWaiter = pLockWaiter->pNextInList;
|
||||
uiCnt--;
|
||||
}
|
||||
|
||||
@@ -930,8 +944,8 @@ FLMBOOL FLMAPI F_LockObject::haveHigherPriorityWaiter(
|
||||
|
||||
f_mutexLock( m_hMutex);
|
||||
|
||||
pLockWaiter = m_pFirstLockWaiter;
|
||||
for( ; pLockWaiter; pLockWaiter = pLockWaiter->pNext )
|
||||
pLockWaiter = m_pFirstInList;
|
||||
for( ; pLockWaiter; pLockWaiter = pLockWaiter->pNextInList)
|
||||
{
|
||||
// If we find a waiter with a priority > the specified
|
||||
// priority, we're done.
|
||||
|
||||
@@ -2165,3 +2165,32 @@ Exit:
|
||||
*ppHashTblRV = pHashTbl;
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: This routine determines the hash bucket for a string.
|
||||
****************************************************************************/
|
||||
FLMUINT FLMAPI f_strHashBucket(
|
||||
char * pszStr,
|
||||
FBUCKET * pHashTbl,
|
||||
FLMUINT uiNumBuckets)
|
||||
{
|
||||
FLMUINT uiHashIndex;
|
||||
|
||||
if ((uiHashIndex = (FLMUINT)*pszStr) >= uiNumBuckets)
|
||||
{
|
||||
uiHashIndex -= uiNumBuckets;
|
||||
}
|
||||
|
||||
while (*pszStr)
|
||||
{
|
||||
if ((uiHashIndex =
|
||||
(FLMUINT)((pHashTbl [uiHashIndex].uiHashValue) ^ (FLMUINT)(f_toupper( *pszStr)))) >=
|
||||
uiNumBuckets)
|
||||
{
|
||||
uiHashIndex -= uiNumBuckets;
|
||||
}
|
||||
pszStr++;
|
||||
}
|
||||
|
||||
return( uiHashIndex);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user