From 107899cefaeebe693f8025e9c0d88784facd2236 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Wed, 27 Feb 2008 04:53:45 +0000 Subject: [PATCH 1/1] windows-dnlc-20080226 LICENSE MIT Remove race conditions in the statistics code by switching to Interlocked functions. Speed up cm_dnlcEnter() by searching first with a read lock and then switching to a write lock if not found. Add HKLM\SOFTWARE\OpenAFS\Client registry values "UseDNLC" and "Debug"DNLC". I suspect with the B+tree code that the DNLC is unnecessary overhead but leave it on by default for now. --- src/WINNT/afsd/cm_dnlc.c | 74 +++++++++++++++++++++++++++++++++++++----------- src/WINNT/afsd/cm_dnlc.h | 6 ++-- 2 files changed, 61 insertions(+), 19 deletions(-) diff --git a/src/WINNT/afsd/cm_dnlc.c b/src/WINNT/afsd/cm_dnlc.c index c6a98d4..b0e7338 100644 --- a/src/WINNT/afsd/cm_dnlc.c +++ b/src/WINNT/afsd/cm_dnlc.c @@ -24,6 +24,7 @@ #include #include #include "afsd.h" +#include osi_rwlock_t cm_dnlcLock; @@ -111,6 +112,7 @@ cm_dnlcEnter ( cm_scache_t *adp, unsigned int key, skey, new=0; char *ts = aname; int safety; + int writeLocked = 0; if (!cm_useDnlc) return ; @@ -127,9 +129,9 @@ cm_dnlcEnter ( cm_scache_t *adp, return ; skey = key & (NHSIZE -1); - lock_ObtainWrite(&cm_dnlcLock); - dnlcstats.enters++; - + InterlockedIncrement(&dnlcstats.enters); + lock_ObtainRead(&cm_dnlcLock); + retry: for (tnc = cm_data.nameHash[skey], safety=0; tnc; tnc = tnc->next, safety++ ) if ((tnc->dirp == adp) && (!strcmp(tnc->name, aname))) break; /* preexisting entry */ @@ -140,8 +142,11 @@ cm_dnlcEnter ( cm_scache_t *adp, } else if (safety > NCSIZE) { - dnlcstats.cycles++; - lock_ReleaseWrite(&cm_dnlcLock); + InterlockedIncrement(&dnlcstats.cycles); + if (writeLocked) + lock_ReleaseWrite(&cm_dnlcLock); + else + lock_ReleaseRead(&cm_dnlcLock); if ( cm_debugDnlc ) osi_Log0(afsd_logp, "DNLC cycle"); @@ -151,6 +156,12 @@ cm_dnlcEnter ( cm_scache_t *adp, if ( !tnc ) { + if ( !writeLocked ) { + lock_ReleaseRead(&cm_dnlcLock); + lock_ObtainWrite(&cm_dnlcLock); + writeLocked = 1; + goto retry; + } new = 1; /* entry does not exist, we are creating a new entry*/ tnc = GetMeAnEntry(); } @@ -165,7 +176,10 @@ cm_dnlcEnter ( cm_scache_t *adp, InsertEntry(tnc); } - lock_ReleaseWrite(&cm_dnlcLock); + if (writeLocked) + lock_ReleaseWrite(&cm_dnlcLock); + else + lock_ReleaseRead(&cm_dnlcLock); if ( !tnc) cm_dnlcPurge(); @@ -186,18 +200,23 @@ cm_dnlcLookup (cm_scache_t *adp, cm_lookupSearch_t* sp) if (!cm_useDnlc) return NULL; + if ( cm_debugDnlc ) osi_Log2(afsd_logp, "cm_dnlcLookup dir %x name %s", adp, osi_LogSaveString(afsd_logp,aname)); dnlcHash( ts, key ); /* leaves ts pointing at the NULL */ - if (ts - aname >= CM_AFSNCNAMESIZE) + + if (ts - aname >= CM_AFSNCNAMESIZE) { + InterlockedIncrement(&dnlcstats.lookups); + InterlockedIncrement(&dnlcstats.misses); return NULL; + } skey = key & (NHSIZE -1); lock_ObtainRead(&cm_dnlcLock); - dnlcstats.lookups++; /* Is a dnlcread lock sufficient? */ + InterlockedIncrement(&dnlcstats.lookups); ts = 0; tnc_begin = cm_data.nameHash[skey]; @@ -256,7 +275,7 @@ cm_dnlcLookup (cm_scache_t *adp, cm_lookupSearch_t* sp) } else if (tnc->next == tnc_begin || safety > NCSIZE) { - dnlcstats.cycles++; + InterlockedIncrement(&dnlcstats.cycles); lock_ReleaseRead(&cm_dnlcLock); if ( cm_debugDnlc ) @@ -274,7 +293,7 @@ cm_dnlcLookup (cm_scache_t *adp, cm_lookupSearch_t* sp) } if (!tvc) - dnlcstats.misses++; /* Is a dnlcread lock sufficient? */ + InterlockedIncrement(&dnlcstats.misses); else { sp->found = 1; @@ -339,7 +358,7 @@ cm_dnlcRemove (cm_scache_t *adp, char *aname) skey = key & (NHSIZE -1); lock_ObtainWrite(&cm_dnlcLock); - dnlcstats.removes++; + InterlockedIncrement(&dnlcstats.removes); for (tnc = cm_data.nameHash[skey], safety=0; tnc; safety++) { @@ -363,7 +382,7 @@ cm_dnlcRemove (cm_scache_t *adp, char *aname) tnc = tnc->next; if ( safety > NCSIZE ) { - dnlcstats.cycles++; + InterlockedIncrement(&dnlcstats.cycles); lock_ReleaseWrite(&cm_dnlcLock); if ( cm_debugDnlc ) @@ -395,7 +414,7 @@ cm_dnlcPurgedp (cm_scache_t *adp) osi_Log1(afsd_logp, "cm_dnlcPurgedp dir %x", adp); lock_ObtainWrite(&cm_dnlcLock); - dnlcstats.purgeds++; + InterlockedIncrement(&dnlcstats.purgeds); for (i=0; i