]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
windows-osi-convertRToW-and-logging-optimizations-20080227
authorJeffrey Altman <jaltman@secure-endpoints.com>
Wed, 27 Feb 2008 17:03:30 +0000 (17:03 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Wed, 27 Feb 2008 17:03:30 +0000 (17:03 +0000)
LICENSE MIT

Add lock_convertRToW which permits a read-lock to be upgraded to a
write lock.  If the caller is the only reader it permits a fast
transition otherwise it adds the caller to the waiters queue.

In the osi_Log macros, check to see if the log is enabled before making
the function call.  This avoids significant function call overhead.

In the cache manager, make use of the above.

src/WINNT/afsd/cm_buf.c
src/WINNT/afsd/cm_dir.c
src/WINNT/afsd/cm_dnlc.c
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/client_osi/libosi.def
src/WINNT/client_osi/osibasel.c
src/WINNT/client_osi/osibasel.h
src/WINNT/client_osi/osilog.h
src/WINNT/client_osi/osiltype.h
src/WINNT/client_osi/osistatl.c

index a067b8be0ad051c5c8fbde1497140d25e84e58f8..eecbb10072d6b7875bbc05294e2e2c5ddd363899 100644 (file)
@@ -128,10 +128,8 @@ void buf_ReleaseLocked(cm_buf_t *bp, afs_uint32 writeLocked)
          * double check that the refCount is actually zero
          * before we remove the buffer from the LRU queue.
          */
-        if (!writeLocked) {
-            lock_ReleaseRead(&buf_globalLock);
-            lock_ObtainWrite(&buf_globalLock);
-        }
+        if (!writeLocked)
+            lock_ConvertRToW(&buf_globalLock);
 
         if (bp->refCount == 0 &&
             !(bp->flags & CM_BUF_INLRU)) {
@@ -143,10 +141,8 @@ void buf_ReleaseLocked(cm_buf_t *bp, afs_uint32 writeLocked)
             bp->flags |= CM_BUF_INLRU;
         }
 
-        if (!writeLocked) {
-            lock_ReleaseWrite(&buf_globalLock);
-            lock_ObtainRead(&buf_globalLock);
-        }
+        if (!writeLocked)
+            lock_ConvertWToR(&buf_globalLock);
     }
 }       
 
index d501255ebb4c83f7c990dd39300e07b5cfd3d616..11ad9a18276ecb910e329ed64ad03d8ee63ef413 100644 (file)
@@ -1030,8 +1030,7 @@ cm_BeginDirOp(cm_scache_t * scp, cm_user_t * userp, cm_req_t * reqp,
                         lock_ReleaseMutex(&scp->mx);
                         mxheld = 0;
                     }
-                    lock_ReleaseRead(&scp->dirlock);
-                    lock_ObtainWrite(&scp->dirlock);
+                    lock_ConvertRToW(&scp->dirlock);
                     haveWrite = 1;
                 }
                 if (!mxheld) {
index b0e733862825e55f70664fedfc1df6c2fa20534a..fce669432fdac3a5522f265b8d606b1afbcb03cb 100644 (file)
@@ -157,8 +157,7 @@ cm_dnlcEnter ( cm_scache_t *adp,
     if ( !tnc )
     {
         if ( !writeLocked ) {
-            lock_ReleaseRead(&cm_dnlcLock);
-            lock_ObtainWrite(&cm_dnlcLock);
+            lock_ConvertRToW(&cm_dnlcLock);
             writeLocked = 1;
             goto retry;
         }
index f8879f9133c0b7c2c5138bb19e78c006f78eae12..8c13ee197ca4ff2728695dfbcafb0e228a76c85b 100644 (file)
@@ -4738,10 +4738,8 @@ long cm_Unlock(cm_scache_t *scp,
         return CM_ERROR_RANGE_NOT_LOCKED;
     }
 
-    lock_ReleaseRead(&cm_scacheLock);
-
     /* discard lock record */
-    lock_ObtainWrite(&cm_scacheLock);
+    lock_ConvertRToW(&cm_scacheLock);
     if (scp->fileLocksT == q)
         scp->fileLocksT = osi_QPrev(q);
     osi_QRemoveHT(&scp->fileLocksH, &scp->fileLocksT, q);
index 8def9d03318d865aa1b14f2a01ccfb22ed774a2c..22e780e91379a14d83e35f67b57caf121501ae66 100644 (file)
@@ -70,3 +70,4 @@ EXPORTS
        osi_LogEvent            @63
         osi_HexifyString        @64
         osi_QRemoveHT           @65
+       lock_ConvertRToW        @66
index fff810df8b4144bad2f0e42d01c316387c75afd4..09e6f2b181de159cb95b78f195bf3fd908807cb9 100644 (file)
@@ -19,6 +19,7 @@
 
 /* atomicity-providing critical sections */
 CRITICAL_SECTION osi_baseAtomicCS[OSI_MUTEXHASHSIZE];
+static long     atomicIndexCounter = 0;
 
 void osi_BaseInit(void)
 {
@@ -179,6 +180,38 @@ void lock_ConvertWToR(osi_rwlock_t *lockp)
        }
 }
 
+void lock_ConvertRToW(osi_rwlock_t *lockp)
+{
+       long i;
+        CRITICAL_SECTION *csp;
+
+       if ((i = lockp->type) != 0) {
+           if (i >= 0 && i < OSI_NLOCKTYPES)
+               (osi_lockOps[i]->ConvertRToWProc)(lockp);
+               return;
+       }
+
+       /* otherwise we're the fast base type */
+       csp = &osi_baseAtomicCS[lockp->atomicIndex];
+        EnterCriticalSection(csp);
+
+       osi_assertx(!(lockp->flags & OSI_LOCKFLAG_EXCL), "write lock held");
+        osi_assertx(lockp->readers > 0, "read lock not held");
+       
+        if (--lockp->readers == 0) {
+            /* convert read lock to write lock */
+            lockp->flags |= OSI_LOCKFLAG_EXCL;
+        } else {
+            lockp->waiters++;
+            osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
+            lockp->waiters--;
+            osi_assert(lockp->readers == 0 && (lockp->flags & OSI_LOCKFLAG_EXCL));
+       }
+
+        lockp->tid = thrd_Current();
+        LeaveCriticalSection(csp);
+}
+
 void lock_ObtainMutex(struct osi_mutex *lockp)
 {
        long i;
@@ -443,7 +476,7 @@ void lock_InitializeMutex(osi_mutex_t *mp, char *namep)
        mp->type = 0;
        mp->flags = 0;
         mp->tid = 0;
-       mp->atomicIndex = osi_MUTEXHASH(mp);
+       mp->atomicIndex = (unsigned short)(InterlockedIncrement(&atomicIndexCounter) % OSI_MUTEXHASHSIZE);
         osi_TInit(&mp->d.turn);
        return;
 }
@@ -463,7 +496,7 @@ void lock_InitializeRWLock(osi_rwlock_t *mp, char *namep)
         */
        mp->type = 0;
        mp->flags = 0;
-       mp->atomicIndex = osi_MUTEXHASH(mp);
+        mp->atomicIndex = (unsigned short)(InterlockedIncrement(&atomicIndexCounter) % OSI_MUTEXHASHSIZE);
        mp->readers = 0;
         mp->tid = 0;
         osi_TInit(&mp->d.turn);
index 5fd2d73a81a383ad5588d6af88ef1b58f1e5187d..2fa6ee48acfd02fa7785954b6f69cc6cea4845d9 100644 (file)
@@ -109,6 +109,8 @@ extern void osi_Init (void);
 
 extern void lock_ConvertWToR(struct osi_rwlock *);
 
+extern void lock_ConvertRToW(struct osi_rwlock *);
+
 /* and stat functions */
 
 extern int lock_GetRWLockState(struct osi_rwlock *);
index 8677da3577c3210e4b0cb488c8edd3d6eec07f64..3ee612f0a3209a0e368a178197e71e42fefe2f3c 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 1998, 1989 Transarc Corporation - All rights reserved
  *
  * (C) COPYRIGHT IBM CORPORATION 1987, 1988
@@ -82,12 +82,12 @@ extern void osi_LogEvent(char *a,char *b,char *c,...);
 extern char *osi_HexifyString(char *s);
 
 /* define macros */
-#define osi_Log0(l,f)          osi_LogAdd((l), (f), 0, 0, 0, 0)
-#define osi_Log1(l,f,a)                osi_LogAdd((l), (f), (size_t) (a), 0, 0, 0)
-#define osi_Log2(l,f,a,b)      osi_LogAdd((l), (f), (size_t) (a), (size_t) (b), 0, 0)
-#define osi_Log3(l,f,a,b,c)    osi_LogAdd((l), (f), (size_t) (a), (size_t) (b), (size_t) (c), 0)
-#define osi_Log4(l,f,a,b,c,d)  osi_LogAdd((l), (f), (size_t) (a), (size_t) (b), (size_t) (c), (size_t) (d))
-#define osi_Log5(l,f,a,b,c,d,e)        osi_LogAdd((l), (f), (size_t) (a), (size_t) (b), (size_t) (c), (size_t) (d), (size_t) (e))
+#define osi_Log0(l,f)          if ((l) && (l)->enabled) osi_LogAdd((l), (f), 0, 0, 0, 0)
+#define osi_Log1(l,f,a)                if ((l) && (l)->enabled) osi_LogAdd((l), (f), (size_t) (a), 0, 0, 0)
+#define osi_Log2(l,f,a,b)      if ((l) && (l)->enabled) osi_LogAdd((l), (f), (size_t) (a), (size_t) (b), 0, 0)
+#define osi_Log3(l,f,a,b,c)    if ((l) && (l)->enabled) osi_LogAdd((l), (f), (size_t) (a), (size_t) (b), (size_t) (c), 0)
+#define osi_Log4(l,f,a,b,c,d)  if ((l) && (l)->enabled) osi_LogAdd((l), (f), (size_t) (a), (size_t) (b), (size_t) (c), (size_t) (d))
+#define osi_Log5(l,f,a,b,c,d,e)        if ((l) && (l)->enabled) osi_LogAdd((l), (f), (size_t) (a), (size_t) (b), (size_t) (c), (size_t) (d), (size_t) (e))
 
 #ifdef DEBUG_VERBOSE
 #define DEBUG_EVENT1(a,b,c) {HANDLE h; char *ptbuf[1],buf[132];\
index 801fccf3783a31c15e89d475ad1092d5ec37aed1..a56af66ec8f027d94d6f7beaa539ae0575e83993 100644 (file)
@@ -35,6 +35,7 @@ typedef struct osi_lockOps {
        void (*FinalizeMutexProc)(struct osi_mutex *);
        void (*FinalizeRWLockProc)(struct osi_rwlock *);
         void (*ConvertWToRProc)(struct osi_rwlock *);
+        void (*ConvertRToWProc)(struct osi_rwlock *);
         int (*GetRWLockState)(struct osi_rwlock *);
         int (*GetMutexState)(struct osi_mutex *);
 } osi_lockOps_t;
index 34692a8009d67faa2071134b31023a526a802005..0526144020ff4ae9bc2604376ecefc2eafeac559 100644 (file)
@@ -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, 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;
@@ -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;
@@ -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;
@@ -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;
@@ -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] = 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] = 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;