From: Jeffrey Altman Date: Wed, 27 Feb 2008 17:03:30 +0000 (+0000) Subject: windows-osi-convertRToW-and-logging-optimizations-20080227 X-Git-Tag: BP-openafs-windows-kdfs-ifs~70 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=72687c02b6ee5ff3029937b0278733b252f14550;p=packages%2Fo%2Fopenafs.git windows-osi-convertRToW-and-logging-optimizations-20080227 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. --- diff --git a/src/WINNT/afsd/cm_buf.c b/src/WINNT/afsd/cm_buf.c index a067b8be0..eecbb1007 100644 --- a/src/WINNT/afsd/cm_buf.c +++ b/src/WINNT/afsd/cm_buf.c @@ -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); } } diff --git a/src/WINNT/afsd/cm_dir.c b/src/WINNT/afsd/cm_dir.c index d501255eb..11ad9a182 100644 --- a/src/WINNT/afsd/cm_dir.c +++ b/src/WINNT/afsd/cm_dir.c @@ -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) { diff --git a/src/WINNT/afsd/cm_dnlc.c b/src/WINNT/afsd/cm_dnlc.c index b0e733862..fce669432 100644 --- a/src/WINNT/afsd/cm_dnlc.c +++ b/src/WINNT/afsd/cm_dnlc.c @@ -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; } diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index f8879f913..8c13ee197 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -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); diff --git a/src/WINNT/client_osi/libosi.def b/src/WINNT/client_osi/libosi.def index 8def9d033..22e780e91 100644 --- a/src/WINNT/client_osi/libosi.def +++ b/src/WINNT/client_osi/libosi.def @@ -70,3 +70,4 @@ EXPORTS osi_LogEvent @63 osi_HexifyString @64 osi_QRemoveHT @65 + lock_ConvertRToW @66 diff --git a/src/WINNT/client_osi/osibasel.c b/src/WINNT/client_osi/osibasel.c index fff810df8..09e6f2b18 100644 --- a/src/WINNT/client_osi/osibasel.c +++ b/src/WINNT/client_osi/osibasel.c @@ -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); diff --git a/src/WINNT/client_osi/osibasel.h b/src/WINNT/client_osi/osibasel.h index 5fd2d73a8..2fa6ee48a 100644 --- a/src/WINNT/client_osi/osibasel.h +++ b/src/WINNT/client_osi/osibasel.h @@ -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 *); diff --git a/src/WINNT/client_osi/osilog.h b/src/WINNT/client_osi/osilog.h index 8677da357..3ee612f0a 100644 --- a/src/WINNT/client_osi/osilog.h +++ b/src/WINNT/client_osi/osilog.h @@ -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];\ diff --git a/src/WINNT/client_osi/osiltype.h b/src/WINNT/client_osi/osiltype.h index 801fccf37..a56af66ec 100644 --- a/src/WINNT/client_osi/osiltype.h +++ b/src/WINNT/client_osi/osiltype.h @@ -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; diff --git a/src/WINNT/client_osi/osistatl.c b/src/WINNT/client_osi/osistatl.c index 34692a800..052614402 100644 --- a/src/WINNT/client_osi/osistatl.c +++ b/src/WINNT/client_osi/osistatl.c @@ -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;