diff --git a/src/WINNT/afsd/cm_buf.c b/src/WINNT/afsd/cm_buf.c index bf2f43b3bb..3b0d35b88e 100644 --- a/src/WINNT/afsd/cm_buf.c +++ b/src/WINNT/afsd/cm_buf.c @@ -130,10 +130,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)) { @@ -145,10 +143,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 be961d5e8b..1305a87b0f 100644 --- a/src/WINNT/afsd/cm_dir.c +++ b/src/WINNT/afsd/cm_dir.c @@ -1032,8 +1032,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 829f6a85c3..c47cd5750b 100644 --- a/src/WINNT/afsd/cm_dnlc.c +++ b/src/WINNT/afsd/cm_dnlc.c @@ -159,8 +159,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 4aacaffd77..06b256ed62 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -4740,10 +4740,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 8def9d0331..22e780e913 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 fff810df8b..09e6f2b181 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 5fd2d73a81..2fa6ee48ac 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 3c4e43f2c1..e9ced17509 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 @@ -86,12 +86,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 801fccf378..a56af66ec8 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 34692a8009..0526144020 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;