Windows: record history of read lock threads
[openafs.git] / src / WINNT / client_osi / osistatl.c
index 405acc3..d11f5d7 100644 (file)
@@ -1,7 +1,7 @@
-/* 
+/*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
@@ -78,7 +78,7 @@ static void lock_ObtainWriteStat(osi_rwlock_t *lockp)
                lockp->waiters++;
                if (!ap) ap = osi_QueueActiveInfo(&realp->qi,
                        OSI_ACTIVEFLAGS_WRITER | OSI_ACTIVEFLAGS_WAITER);
-                osi_TWait(&realp->turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
+                osi_TWait(&realp->turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, lockp->tid, csp);
                lockp->waiters--;
                osi_assert((lockp->flags & OSI_LOCKFLAG_EXCL) && lockp->readers == 0);
        }
@@ -93,7 +93,7 @@ static void lock_ObtainWriteStat(osi_rwlock_t *lockp)
        if (ap) {
                /* remove from queue and turn time to incremental time */
                osi_RemoveActiveInfo(&realp->qi, ap);
-               
+
                /* add in increment to statistics */
                realp->writeBlockedCount++;
                realp->writeBlockedTime = LargeIntegerAdd(realp->writeBlockedTime,
@@ -123,7 +123,7 @@ static void lock_ObtainReadStat(osi_rwlock_t *lockp)
                lockp->waiters++;
                if (!ap) ap = osi_QueueActiveInfo(&realp->qi,
                        OSI_ACTIVEFLAGS_WAITER | OSI_ACTIVEFLAGS_READER);
-               osi_TWait(&realp->turn, OSI_SLEEPINFO_W4READ, &lockp->readers, csp);
+               osi_TWait(&realp->turn, OSI_SLEEPINFO_W4READ, &lockp->readers, lockp->tid, csp);
                 lockp->waiters--;
                 osi_assert(!(lockp->flags & OSI_LOCKFLAG_EXCL) && lockp->readers > 0);
        }
@@ -162,7 +162,7 @@ static void lock_ReleaseReadStat(osi_rwlock_t *lockp)
        realp->readLockedCount++;
        realp->readLockedTime = LargeIntegerAdd(realp->readLockedTime, ap->startTime);
        osi_FreeActiveInfo(ap);
-       
+
        if (--lockp->readers == 0 && !osi_TEmpty(&realp->turn)) {
                osi_TSignalForMLs(&realp->turn, 0, csp);
        }
@@ -191,11 +191,11 @@ static void lock_ConvertWToRStat(osi_rwlock_t *lockp)
        realp->writeLockedCount++;
        realp->writeLockedTime = LargeIntegerAdd(realp->writeLockedTime, ap->startTime);
        osi_FreeActiveInfo(ap);
-        
+
         /* and obtain the read lock */
        lockp->readers++;
        osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_READER);
-       
+
        lockp->flags &= ~OSI_LOCKFLAG_EXCL;
        if (!osi_TEmpty(&realp->turn)) {
                osi_TSignalForMLs(&realp->turn, 1, csp);
@@ -206,6 +206,56 @@ static void lock_ConvertWToRStat(osi_rwlock_t *lockp)
        }
 }
 
+static void lock_ConvertRToWStat(osi_rwlock_t *lockp)
+{
+       osi_activeInfo_t *ap;
+       osi_rwlockStat_t *realp;
+        CRITICAL_SECTION *csp;
+
+       realp = (osi_rwlockStat_t *)lockp->d.privateDatap;
+
+       /* otherwise we're the fast base type */
+       csp = &osi_statAtomicCS[lockp->atomicIndex];
+        EnterCriticalSection(csp);
+
+       osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
+       ap = osi_FindActiveInfo(&realp->qi);
+       osi_assert(ap !=NULL);
+       osi_RemoveActiveInfo(&realp->qi, ap);
+        realp->readLockedCount++;
+        realp->readLockedTime = LargeIntegerAdd(realp->readLockedTime, ap->startTime);
+        osi_FreeActiveInfo(ap);
+
+        if (--lockp->readers == 0) {
+            /* and obtain the write lock */
+            lockp->readers--;
+            lockp->flags |= OSI_LOCKFLAG_EXCL;
+        } else {
+            lockp->waiters++;
+            ap = osi_QueueActiveInfo(&realp->qi,
+                                     OSI_ACTIVEFLAGS_WRITER | OSI_ACTIVEFLAGS_WAITER);
+            osi_TWait(&realp->turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, lockp->tid, csp);
+            lockp->waiters--;
+            osi_assert((lockp->flags & OSI_LOCKFLAG_EXCL) && lockp->readers == 0);
+
+            /*  we have some timer info about the last sleep operation
+             * that we should merge in under the spin lock.
+             */
+
+            /* remove from queue and turn time to incremental time */
+            osi_RemoveActiveInfo(&realp->qi, ap);
+
+            /* add in increment to statistics */
+            realp->writeBlockedCount++;
+            realp->writeBlockedTime = LargeIntegerAdd(realp->writeBlockedTime,
+                                                   ap->startTime);
+            osi_FreeActiveInfo(ap);
+        }
+
+        osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_WRITER);
+        LeaveCriticalSection(csp);
+}
+
 static void lock_ReleaseWriteStat(osi_rwlock_t *lockp)
 {
        osi_activeInfo_t *ap;
@@ -225,7 +275,7 @@ static void lock_ReleaseWriteStat(osi_rwlock_t *lockp)
        realp->writeLockedCount++;
        realp->writeLockedTime = LargeIntegerAdd(realp->writeLockedTime, ap->startTime);
        osi_FreeActiveInfo(ap);
-       
+
        lockp->flags &= ~OSI_LOCKFLAG_EXCL;
        if (!osi_TEmpty(&realp->turn)) {
                osi_TSignalForMLs(&realp->turn, 0, csp);
@@ -252,7 +302,7 @@ static void lock_ObtainMutexStat(struct osi_mutex *lockp)
        if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
                lockp->waiters++;
                ap = osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_WAITER);
-               osi_TWait(&realp->turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
+               osi_TWait(&realp->turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, &lockp->tid, csp);
                lockp->waiters--;
                 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
        }
@@ -287,7 +337,7 @@ static void lock_ReleaseMutexStat(struct osi_mutex *lockp)
         EnterCriticalSection(csp);
 
        osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
-       
+
        ap = osi_FindActiveInfo(&realp->qi);
        osi_assert(ap != NULL);
        osi_RemoveActiveInfo(&realp->qi, ap);
@@ -308,7 +358,7 @@ static void lock_ReleaseMutexStat(struct osi_mutex *lockp)
 static int lock_TryReadStat(struct osi_rwlock *lockp)
 {
        long i;
-       osi_rwlockStat_t *realp; 
+       osi_rwlockStat_t *realp;
         CRITICAL_SECTION *csp;
 
        realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
@@ -444,7 +494,7 @@ static int lock_TryMutexStat(struct osi_mutex *lockp) {
        return i;
 }
 
-static void osi_SleepRStat(long sleepVal, struct osi_rwlock *lockp)
+static void osi_SleepRStat(LONG_PTR sleepVal, struct osi_rwlock *lockp)
 {
        osi_rwlockStat_t *realp;
        osi_activeInfo_t *ap;
@@ -457,7 +507,7 @@ static void osi_SleepRStat(long sleepVal, struct osi_rwlock *lockp)
         EnterCriticalSection(csp);
 
        osi_assert(lockp->readers > 0);
-       
+
        if (--lockp->readers == 0 && !osi_TEmpty(&realp->turn)) {
                osi_TSignalForMLs(&realp->turn, 0, NULL);
        }
@@ -474,7 +524,7 @@ static void osi_SleepRStat(long sleepVal, struct osi_rwlock *lockp)
        osi_SleepSpin(sleepVal, csp);
 }
 
-static void osi_SleepWStat(long sleepVal, struct osi_rwlock *lockp)
+static void osi_SleepWStat(LONG_PTR sleepVal, struct osi_rwlock *lockp)
 {
        osi_activeInfo_t *ap;
        osi_rwlockStat_t *realp;
@@ -487,7 +537,7 @@ static void osi_SleepWStat(long sleepVal, struct osi_rwlock *lockp)
         EnterCriticalSection(csp);
 
        osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
-       
+
        lockp->flags &= ~OSI_LOCKFLAG_EXCL;
        if (!osi_TEmpty(&realp->turn)) {
                osi_TSignalForMLs(&realp->turn, 0, NULL);
@@ -505,7 +555,7 @@ static void osi_SleepWStat(long sleepVal, struct osi_rwlock *lockp)
        osi_SleepSpin(sleepVal, csp);
 }
 
-static void osi_SleepMStat(long sleepVal, struct osi_mutex *lockp)
+static void osi_SleepMStat(LONG_PTR sleepVal, struct osi_mutex *lockp)
 {
        osi_mutexStat_t *realp;
        osi_activeInfo_t *ap;
@@ -518,7 +568,7 @@ static void osi_SleepMStat(long sleepVal, struct osi_mutex *lockp)
         EnterCriticalSection(csp);
 
        osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
-       
+
        lockp->flags &= ~OSI_LOCKFLAG_EXCL;
        if (!osi_TEmpty(&realp->turn)) {
                osi_TSignalForMLs(&realp->turn, 0, NULL);
@@ -560,10 +610,10 @@ static void lock_DecrRWLockStat(osi_rwlockStat_t *rwp)
 static void lock_FinalizeMutexStat(osi_mutex_t *lockp)
 {
        osi_mutexStat_t *realp;
-       
+
        /* pull out the real pointer */
        realp = (osi_mutexStat_t *) lockp->d.privateDatap;
-       
+
        /* remove from the queues, and free */
        EnterCriticalSection(&osi_statFDCS);
        if (realp->refCount <= 0) {
@@ -577,10 +627,10 @@ static void lock_FinalizeMutexStat(osi_mutex_t *lockp)
 static void lock_FinalizeRWLockStat(osi_rwlock_t *lockp)
 {
        osi_rwlockStat_t *realp;
-       
+
        /* pull out the real pointer */
        realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
-       
+
        /* remove from the queues, and free */
        EnterCriticalSection(&osi_statFDCS);
        if (realp->refCount <= 0) {
@@ -591,10 +641,10 @@ static void lock_FinalizeRWLockStat(osi_rwlock_t *lockp)
        LeaveCriticalSection(&osi_statFDCS);
 }
 
-void lock_InitializeRWLockStat(osi_rwlock_t *lockp, char *namep)
+void lock_InitializeRWLockStat(osi_rwlock_t *lockp, char *namep, unsigned short level)
 {
        osi_rwlockStat_t *realp;
-       
+
        realp = (osi_rwlockStat_t *) malloc(sizeof(*realp));
        lockp->d.privateDatap = (void *) realp;
        lockp->type = osi_statType;
@@ -610,10 +660,10 @@ void lock_InitializeRWLockStat(osi_rwlock_t *lockp, char *namep)
        LeaveCriticalSection(&osi_statFDCS);
 }
 
-void lock_InitializeMutexStat(osi_mutex_t *lockp, char *namep)
+void lock_InitializeMutexStat(osi_mutex_t *lockp, char *namep, unsigned short level)
 {
        osi_mutexStat_t *realp;
-       
+
        realp = (osi_mutexStat_t *) malloc(sizeof(*realp));
        lockp->d.privateDatap = (void *) realp;
        lockp->type = osi_statType;
@@ -740,6 +790,7 @@ static osi_lockOps_t osi_statOps = {
        lock_FinalizeMutexStat,
        lock_FinalizeRWLockStat,
         lock_ConvertWToRStat,
+        lock_ConvertRToWStat,
        lock_GetRWLockStateStat,
         lock_GetMutexStateStat
 };
@@ -798,7 +849,7 @@ long osi_StatFDGetInfo(osi_fd_t *ifdp, osi_remGetInfoParms_t *parmsp)
 
                memset((void *) parmsp, 0, sizeof(*parmsp));
                backMutexp = mp->qi.backp;
-               parmsp->idata[0] = (long) backMutexp;
+               parmsp->idata[0] = (LONG_PTR)backMutexp;
                parmsp->idata[1] = (backMutexp->flags & OSI_LOCKFLAG_EXCL)? 1 : 0;
                /* reader count [2] is 0 */
                parmsp->idata[3] = (backMutexp->waiters > 0)? 1 : 0;
@@ -816,7 +867,7 @@ long osi_StatFDGetInfo(osi_fd_t *ifdp, osi_remGetInfoParms_t *parmsp)
 
                memset((void *) parmsp, 0, sizeof(*parmsp));
                 backRWLockp = rwp->qi.backp;
-               parmsp->idata[0] = (long) backRWLockp;
+               parmsp->idata[0] = (LONG_PTR)backRWLockp;
                parmsp->idata[1] = (backRWLockp->flags & OSI_LOCKFLAG_EXCL)? 1 : 0;
                parmsp->idata[2] = backRWLockp->readers;
                parmsp->idata[3] = (backRWLockp->waiters > 0)? 1 : 0;