mirror of
https://git.openafs.org/openafs.git
synced 2025-01-19 15:30:14 +00:00
Windows: record history of read lock threads
Maintance an array of up to 32 reader threads that have acquired a rwlock. Use it for debugging when things go bad. Change-Id: I2e2e781ff355f1452e991898dfb5b91c47db9e34 Reviewed-on: http://gerrit.openafs.org/5411 Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Jeffrey Altman <jaltman@openafs.org> Tested-by: Jeffrey Altman <jaltman@openafs.org>
This commit is contained in:
parent
1de4561529
commit
c9d655b9a6
@ -177,17 +177,14 @@ void lock_ObtainWrite(osi_rwlock_t *lockp)
|
||||
if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL) ||
|
||||
(lockp->readers > 0)) {
|
||||
lockp->waiters++;
|
||||
osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
|
||||
osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, lockp->tid, csp);
|
||||
lockp->waiters--;
|
||||
osi_assert(lockp->readers == 0 && (lockp->flags & OSI_LOCKFLAG_EXCL));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* if we're here, all clear to set the lock */
|
||||
lockp->flags |= OSI_LOCKFLAG_EXCL;
|
||||
lockp->tid[0] = thrd_Current();
|
||||
}
|
||||
|
||||
lockp->tid = thrd_Current();
|
||||
|
||||
LeaveCriticalSection(csp);
|
||||
|
||||
if (lockOrderValidation) {
|
||||
@ -204,6 +201,7 @@ void lock_ObtainRead(osi_rwlock_t *lockp)
|
||||
CRITICAL_SECTION *csp;
|
||||
osi_queue_t * lockRefH, *lockRefT;
|
||||
osi_lock_ref_t *lockRefp;
|
||||
DWORD tid = thrd_Current();
|
||||
|
||||
if ((i=lockp->type) != 0) {
|
||||
if (i >= 0 && i < OSI_NLOCKTYPES)
|
||||
@ -223,18 +221,21 @@ void lock_ObtainRead(osi_rwlock_t *lockp)
|
||||
csp = &osi_baseAtomicCS[lockp->atomicIndex];
|
||||
EnterCriticalSection(csp);
|
||||
|
||||
for ( i=0; i < lockp->readers; i++ ) {
|
||||
osi_assertx(lockp->tid[i] != tid, "OSI_RWLOCK_READHELD");
|
||||
}
|
||||
|
||||
/* here we have the fast lock, so see if we can obtain the real lock */
|
||||
if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
|
||||
lockp->waiters++;
|
||||
osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4READ, &lockp->readers, csp);
|
||||
osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4READ, &lockp->readers, lockp->tid, csp);
|
||||
lockp->waiters--;
|
||||
osi_assert(!(lockp->flags & OSI_LOCKFLAG_EXCL) && lockp->readers > 0);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* if we're here, all clear to set the lock */
|
||||
lockp->readers++;
|
||||
if (++lockp->readers <= OSI_RWLOCK_THREADS)
|
||||
lockp->tid[lockp->readers-1] = tid;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(csp);
|
||||
|
||||
if (lockOrderValidation) {
|
||||
@ -251,6 +252,7 @@ void lock_ReleaseRead(osi_rwlock_t *lockp)
|
||||
CRITICAL_SECTION *csp;
|
||||
osi_queue_t * lockRefH, *lockRefT;
|
||||
osi_lock_ref_t *lockRefp;
|
||||
DWORD tid = thrd_Current();
|
||||
|
||||
if ((i = lockp->type) != 0) {
|
||||
if (i >= 0 && i < OSI_NLOCKTYPES)
|
||||
@ -283,6 +285,15 @@ void lock_ReleaseRead(osi_rwlock_t *lockp)
|
||||
|
||||
osi_assertx(lockp->readers > 0, "read lock not held");
|
||||
|
||||
for ( i=0; i < lockp->readers; i++) {
|
||||
if ( lockp->tid[i] == tid ) {
|
||||
for ( ; i < lockp->readers - 1; i++)
|
||||
lockp->tid[i] = lockp->tid[i+1];
|
||||
lockp->tid[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* releasing a read lock can allow readers or writers */
|
||||
if (--lockp->readers == 0 && !osi_TEmpty(&lockp->d.turn)) {
|
||||
osi_TSignalForMLs(&lockp->d.turn, 0, csp);
|
||||
@ -330,9 +341,9 @@ void lock_ReleaseWrite(osi_rwlock_t *lockp)
|
||||
EnterCriticalSection(csp);
|
||||
|
||||
osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "write lock not held");
|
||||
osi_assertx(lockp->tid == thrd_Current(), "write lock not held by current thread");
|
||||
osi_assertx(lockp->tid[0] == thrd_Current(), "write lock not held by current thread");
|
||||
|
||||
lockp->tid = 0;
|
||||
lockp->tid[0] = 0;
|
||||
|
||||
lockp->flags &= ~OSI_LOCKFLAG_EXCL;
|
||||
if (!osi_TEmpty(&lockp->d.turn)) {
|
||||
@ -360,14 +371,12 @@ void lock_ConvertWToR(osi_rwlock_t *lockp)
|
||||
EnterCriticalSection(csp);
|
||||
|
||||
osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "write lock not held");
|
||||
osi_assertx(lockp->tid == thrd_Current(), "write lock not held by current thread");
|
||||
osi_assertx(lockp->tid[0] == thrd_Current(), "write lock not held by current thread");
|
||||
|
||||
/* convert write lock to read lock */
|
||||
lockp->flags &= ~OSI_LOCKFLAG_EXCL;
|
||||
lockp->readers++;
|
||||
|
||||
lockp->tid = 0;
|
||||
|
||||
if (!osi_TEmpty(&lockp->d.turn)) {
|
||||
osi_TSignalForMLs(&lockp->d.turn, /* still have readers */ 1, csp);
|
||||
}
|
||||
@ -381,6 +390,7 @@ void lock_ConvertRToW(osi_rwlock_t *lockp)
|
||||
{
|
||||
long i;
|
||||
CRITICAL_SECTION *csp;
|
||||
DWORD tid = thrd_Current();
|
||||
|
||||
if ((i = lockp->type) != 0) {
|
||||
if (i >= 0 && i < OSI_NLOCKTYPES)
|
||||
@ -395,17 +405,26 @@ void lock_ConvertRToW(osi_rwlock_t *lockp)
|
||||
osi_assertx(!(lockp->flags & OSI_LOCKFLAG_EXCL), "write lock held");
|
||||
osi_assertx(lockp->readers > 0, "read lock not held");
|
||||
|
||||
for ( i=0; i < lockp->readers; i++) {
|
||||
if ( lockp->tid[i] == tid ) {
|
||||
for ( ; i < lockp->readers - 1; i++)
|
||||
lockp->tid[i] = lockp->tid[i+1];
|
||||
lockp->tid[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (--lockp->readers == 0) {
|
||||
/* convert read lock to write lock */
|
||||
lockp->flags |= OSI_LOCKFLAG_EXCL;
|
||||
lockp->tid[0] = tid;
|
||||
} else {
|
||||
lockp->waiters++;
|
||||
osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
|
||||
osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, lockp->tid, csp);
|
||||
lockp->waiters--;
|
||||
osi_assert(lockp->readers == 0 && (lockp->flags & OSI_LOCKFLAG_EXCL));
|
||||
}
|
||||
|
||||
lockp->tid = thrd_Current();
|
||||
LeaveCriticalSection(csp);
|
||||
}
|
||||
|
||||
@ -437,15 +456,14 @@ void lock_ObtainMutex(struct osi_mutex *lockp)
|
||||
/* here we have the fast lock, so see if we can obtain the real lock */
|
||||
if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
|
||||
lockp->waiters++;
|
||||
osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
|
||||
osi_TWait(&lockp->d.turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, &lockp->tid, csp);
|
||||
lockp->waiters--;
|
||||
osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* if we're here, all clear to set the lock */
|
||||
lockp->flags |= OSI_LOCKFLAG_EXCL;
|
||||
lockp->tid = thrd_Current();
|
||||
}
|
||||
lockp->tid = thrd_Current();
|
||||
LeaveCriticalSection(csp);
|
||||
|
||||
if (lockOrderValidation) {
|
||||
@ -540,7 +558,8 @@ int lock_TryRead(struct osi_rwlock *lockp)
|
||||
}
|
||||
else {
|
||||
/* if we're here, all clear to set the lock */
|
||||
lockp->readers++;
|
||||
if (++lockp->readers < OSI_RWLOCK_THREADS)
|
||||
lockp->tid[lockp->readers-1] = thrd_Current();
|
||||
i = 1;
|
||||
}
|
||||
|
||||
@ -593,12 +612,10 @@ int lock_TryWrite(struct osi_rwlock *lockp)
|
||||
else {
|
||||
/* if we're here, all clear to set the lock */
|
||||
lockp->flags |= OSI_LOCKFLAG_EXCL;
|
||||
lockp->tid[0] = thrd_Current();
|
||||
i = 1;
|
||||
}
|
||||
|
||||
if (i)
|
||||
lockp->tid = thrd_Current();
|
||||
|
||||
LeaveCriticalSection(csp);
|
||||
|
||||
if (lockOrderValidation && i) {
|
||||
@ -646,12 +663,10 @@ int lock_TryMutex(struct osi_mutex *lockp) {
|
||||
else {
|
||||
/* if we're here, all clear to set the lock */
|
||||
lockp->flags |= OSI_LOCKFLAG_EXCL;
|
||||
lockp->tid = thrd_Current();
|
||||
i = 1;
|
||||
}
|
||||
|
||||
if (i)
|
||||
lockp->tid = thrd_Current();
|
||||
|
||||
LeaveCriticalSection(csp);
|
||||
|
||||
if (lockOrderValidation && i) {
|
||||
@ -669,6 +684,7 @@ void osi_SleepR(LONG_PTR sleepVal, struct osi_rwlock *lockp)
|
||||
CRITICAL_SECTION *csp;
|
||||
osi_queue_t * lockRefH, *lockRefT;
|
||||
osi_lock_ref_t *lockRefp;
|
||||
DWORD tid = thrd_Current();
|
||||
|
||||
if ((i = lockp->type) != 0) {
|
||||
if (i >= 0 && i < OSI_NLOCKTYPES)
|
||||
@ -698,6 +714,15 @@ void osi_SleepR(LONG_PTR sleepVal, struct osi_rwlock *lockp)
|
||||
|
||||
osi_assertx(lockp->readers > 0, "osi_SleepR: not held");
|
||||
|
||||
for ( i=0; i < lockp->readers; i++) {
|
||||
if ( lockp->tid[i] == tid ) {
|
||||
for ( ; i < lockp->readers - 1; i++)
|
||||
lockp->tid[i] = lockp->tid[i+1];
|
||||
lockp->tid[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX better to get the list of things to wakeup from TSignalForMLs, and
|
||||
* then do the wakeup after SleepSpin releases the low-level mutex.
|
||||
*/
|
||||
@ -715,6 +740,7 @@ void osi_SleepW(LONG_PTR sleepVal, struct osi_rwlock *lockp)
|
||||
CRITICAL_SECTION *csp;
|
||||
osi_queue_t * lockRefH, *lockRefT;
|
||||
osi_lock_ref_t *lockRefp;
|
||||
DWORD tid = thrd_Current();
|
||||
|
||||
if ((i = lockp->type) != 0) {
|
||||
if (i >= 0 && i < OSI_NLOCKTYPES)
|
||||
@ -745,6 +771,7 @@ void osi_SleepW(LONG_PTR sleepVal, struct osi_rwlock *lockp)
|
||||
osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "osi_SleepW: not held");
|
||||
|
||||
lockp->flags &= ~OSI_LOCKFLAG_EXCL;
|
||||
lockp->tid[0] = 0;
|
||||
if (!osi_TEmpty(&lockp->d.turn)) {
|
||||
osi_TSignalForMLs(&lockp->d.turn, 0, NULL);
|
||||
}
|
||||
@ -789,6 +816,7 @@ void osi_SleepM(LONG_PTR sleepVal, struct osi_mutex *lockp)
|
||||
osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "osi_SleepM not held");
|
||||
|
||||
lockp->flags &= ~OSI_LOCKFLAG_EXCL;
|
||||
lockp->tid = 0;
|
||||
if (!osi_TEmpty(&lockp->d.turn)) {
|
||||
osi_TSignalForMLs(&lockp->d.turn, 0, NULL);
|
||||
}
|
||||
@ -850,11 +878,8 @@ void lock_InitializeRWLock(osi_rwlock_t *mp, char *namep, unsigned short level)
|
||||
/* otherwise we have the base case, which requires no special
|
||||
* initialization.
|
||||
*/
|
||||
mp->type = 0;
|
||||
mp->flags = 0;
|
||||
memset(mp, 0, sizeof(osi_rwlock_t));
|
||||
mp->atomicIndex = (unsigned short)(InterlockedIncrement(&atomicIndexCounter) % OSI_MUTEXHASHSIZE);
|
||||
mp->readers = 0;
|
||||
mp->tid = 0;
|
||||
mp->level = level;
|
||||
osi_TInit(&mp->d.turn);
|
||||
return;
|
||||
|
@ -53,11 +53,14 @@ typedef struct osi_mutex {
|
||||
*
|
||||
* This type of lock has N readers or one writer.
|
||||
*/
|
||||
|
||||
#define OSI_RWLOCK_THREADS 32
|
||||
|
||||
typedef struct osi_rwlock {
|
||||
char type; /* for all types; type 0 uses atomic count */
|
||||
char flags; /* flags for base type */
|
||||
unsigned short atomicIndex; /* index into hash table for low-level sync */
|
||||
DWORD tid; /* writer's tid */
|
||||
DWORD tid[OSI_RWLOCK_THREADS]; /* writer's tid */
|
||||
unsigned short waiters; /* waiters */
|
||||
unsigned short readers; /* readers */
|
||||
union {
|
||||
@ -149,10 +152,10 @@ extern void osi_SetLockOrderValidation(int);
|
||||
|
||||
#define lock_AssertRead(x) osi_assertx(lock_GetRWLockState(x) & OSI_RWLOCK_READHELD, "!OSI_RWLOCK_READHELD")
|
||||
|
||||
#define lock_AssertWrite(x) osi_assertx(lock_GetRWLockState(x) & OSI_RWLOCK_WRITEHELD, "!OSI_RWLOCK_WRITEHELD")
|
||||
#define lock_AssertWrite(x) osi_assertx((lock_GetRWLockState(x) & OSI_RWLOCK_WRITEHELD) && ((x)->tid[0] == thrd_Current()), "!OSI_RWLOCK_WRITEHELD")
|
||||
|
||||
#define lock_AssertAny(x) osi_assertx(lock_GetRWLockState(x) != 0, "!(OSI_RWLOCK_READHELD | OSI_RWLOCK_WRITEHELD)")
|
||||
|
||||
#define lock_AssertMutex(x) osi_assertx(lock_GetMutexState(x) & OSI_MUTEX_HELD, "!OSI_MUTEX_HELD")
|
||||
#define lock_AssertMutex(x) osi_assertx((lock_GetMutexState(x) & OSI_MUTEX_HELD) && ((x)->tid == thrd_Current()), "!OSI_MUTEX_HELD")
|
||||
|
||||
#endif /* OPENAFS_WINNT_CLIENT_OSI_OSIBASEL_H */
|
||||
|
@ -125,63 +125,63 @@ void osi_FreeSleepInfo(osi_sleepInfo_t *ap)
|
||||
/* allocate a new sleep structure from the free list */
|
||||
osi_sleepInfo_t *osi_AllocSleepInfo()
|
||||
{
|
||||
osi_sleepInfo_t *ap;
|
||||
osi_sleepInfo_t *ap;
|
||||
|
||||
EnterCriticalSection(&osi_sleepInfoAllocCS);
|
||||
if (!(ap = osi_sleepInfoFreeListp)) {
|
||||
ap = (osi_sleepInfo_t *) malloc(sizeof(osi_sleepInfo_t));
|
||||
ap->sema = CreateSemaphore(NULL, 0, 65536, (char *) 0);
|
||||
osi_sleepInfoAllocs++;
|
||||
}
|
||||
else {
|
||||
osi_sleepInfoFreeListp = (osi_sleepInfo_t *) ap->q.nextp;
|
||||
osi_sleepInfoCount--;
|
||||
}
|
||||
ap->tid = GetCurrentThreadId();
|
||||
ap->states = 0; /* not signalled yet */
|
||||
LeaveCriticalSection(&osi_sleepInfoAllocCS);
|
||||
EnterCriticalSection(&osi_sleepInfoAllocCS);
|
||||
if (!(ap = osi_sleepInfoFreeListp)) {
|
||||
ap = (osi_sleepInfo_t *) malloc(sizeof(osi_sleepInfo_t));
|
||||
ap->sema = CreateSemaphore(NULL, 0, 65536, (char *) 0);
|
||||
osi_sleepInfoAllocs++;
|
||||
}
|
||||
else {
|
||||
osi_sleepInfoFreeListp = (osi_sleepInfo_t *) ap->q.nextp;
|
||||
osi_sleepInfoCount--;
|
||||
}
|
||||
ap->tid = GetCurrentThreadId();
|
||||
ap->states = 0; /* not signalled yet */
|
||||
LeaveCriticalSection(&osi_sleepInfoAllocCS);
|
||||
|
||||
return ap;
|
||||
return ap;
|
||||
}
|
||||
|
||||
int osi_Once(osi_once_t *argp)
|
||||
{
|
||||
long i;
|
||||
long i;
|
||||
|
||||
while ((i=InterlockedExchange(&argp->atomic, 1)) != 0) {
|
||||
Sleep(0);
|
||||
}
|
||||
while ((i=InterlockedExchange(&argp->atomic, 1)) != 0) {
|
||||
Sleep(0);
|
||||
}
|
||||
|
||||
if (argp->done == 0) {
|
||||
argp->done = 1;
|
||||
return 1;
|
||||
}
|
||||
if (argp->done == 0) {
|
||||
argp->done = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* otherwise we've already been initialized, so clear lock and return */
|
||||
InterlockedExchange(&argp->atomic, 0);
|
||||
return 0;
|
||||
/* otherwise we've already been initialized, so clear lock and return */
|
||||
InterlockedExchange(&argp->atomic, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void osi_EndOnce(osi_once_t *argp)
|
||||
{
|
||||
InterlockedExchange(&argp->atomic, 0);
|
||||
InterlockedExchange(&argp->atomic, 0);
|
||||
}
|
||||
|
||||
int osi_TestOnce(osi_once_t *argp)
|
||||
{
|
||||
long localDone;
|
||||
long i;
|
||||
long localDone;
|
||||
long i;
|
||||
|
||||
while ((i=InterlockedExchange(&argp->atomic, 1)) != 0) {
|
||||
Sleep(0);
|
||||
}
|
||||
while ((i=InterlockedExchange(&argp->atomic, 1)) != 0) {
|
||||
Sleep(0);
|
||||
}
|
||||
|
||||
localDone = argp->done;
|
||||
localDone = argp->done;
|
||||
|
||||
/* drop interlock */
|
||||
InterlockedExchange(&argp->atomic, 0);
|
||||
/* drop interlock */
|
||||
InterlockedExchange(&argp->atomic, 0);
|
||||
|
||||
return (localDone? 0 : 1);
|
||||
return (localDone? 0 : 1);
|
||||
}
|
||||
|
||||
/* Initialize the package, should be called while single-threaded.
|
||||
@ -190,74 +190,75 @@ int osi_TestOnce(osi_once_t *argp)
|
||||
*/
|
||||
void osi_Init(void)
|
||||
{
|
||||
int i;
|
||||
static osi_once_t once;
|
||||
unsigned long remainder; /* for division output */
|
||||
osi_fdType_t *typep;
|
||||
SYSTEMTIME sysTime;
|
||||
FILETIME fileTime;
|
||||
osi_hyper_t bootTime;
|
||||
int i;
|
||||
static osi_once_t once;
|
||||
unsigned long remainder; /* for division output */
|
||||
osi_fdType_t *typep;
|
||||
SYSTEMTIME sysTime;
|
||||
FILETIME fileTime;
|
||||
osi_hyper_t bootTime;
|
||||
|
||||
/* check to see if already initialized; if so, claim success */
|
||||
if (!osi_Once(&once)) return;
|
||||
/* check to see if already initialized; if so, claim success */
|
||||
if (!osi_Once(&once))
|
||||
return;
|
||||
|
||||
/* setup boot time values */
|
||||
GetSystemTime(&sysTime);
|
||||
SystemTimeToFileTime(&sysTime, &fileTime);
|
||||
/* setup boot time values */
|
||||
GetSystemTime(&sysTime);
|
||||
SystemTimeToFileTime(&sysTime, &fileTime);
|
||||
|
||||
/* change the base of the time so it won't be negative for a long time */
|
||||
fileTime.dwHighDateTime -= 28000000;
|
||||
/* change the base of the time so it won't be negative for a long time */
|
||||
fileTime.dwHighDateTime -= 28000000;
|
||||
|
||||
bootTime.HighPart = fileTime.dwHighDateTime;
|
||||
bootTime.LowPart = fileTime.dwLowDateTime;
|
||||
/* now, bootTime is in 100 nanosecond units, and we'd really rather
|
||||
* have it in 1 second units, units 10,000,000 times bigger.
|
||||
* So, we divide.
|
||||
*/
|
||||
bootTime = ExtendedLargeIntegerDivide(bootTime, 10000000, &remainder);
|
||||
osi_bootTime = bootTime.LowPart;
|
||||
bootTime.HighPart = fileTime.dwHighDateTime;
|
||||
bootTime.LowPart = fileTime.dwLowDateTime;
|
||||
/* now, bootTime is in 100 nanosecond units, and we'd really rather
|
||||
* have it in 1 second units, units 10,000,000 times bigger.
|
||||
* So, we divide.
|
||||
*/
|
||||
bootTime = ExtendedLargeIntegerDivide(bootTime, 10000000, &remainder);
|
||||
osi_bootTime = bootTime.LowPart;
|
||||
|
||||
/* initialize thread-local storage for sleep Info structures */
|
||||
osi_SleepSlot = TlsAlloc();
|
||||
/* initialize thread-local storage for sleep Info structures */
|
||||
osi_SleepSlot = TlsAlloc();
|
||||
|
||||
/* init FD system */
|
||||
osi_InitFD();
|
||||
/* init FD system */
|
||||
osi_InitFD();
|
||||
|
||||
/* initialize critical regions and semaphores */
|
||||
for(i=0;i<OSI_SLEEPHASHSIZE; i++) {
|
||||
InitializeCriticalSection(&osi_critSec[i]);
|
||||
osi_sleepers[i] = (osi_sleepInfo_t *) NULL;
|
||||
osi_sleepersEnd[i] = (osi_sleepInfo_t *) NULL;
|
||||
}
|
||||
/* initialize critical regions and semaphores */
|
||||
for(i=0;i<OSI_SLEEPHASHSIZE; i++) {
|
||||
InitializeCriticalSection(&osi_critSec[i]);
|
||||
osi_sleepers[i] = (osi_sleepInfo_t *) NULL;
|
||||
osi_sleepersEnd[i] = (osi_sleepInfo_t *) NULL;
|
||||
}
|
||||
|
||||
/* free list CS */
|
||||
InitializeCriticalSection(&osi_sleepInfoAllocCS);
|
||||
/* free list CS */
|
||||
InitializeCriticalSection(&osi_sleepInfoAllocCS);
|
||||
|
||||
/* initialize cookie system */
|
||||
InitializeCriticalSection(&osi_sleepFDCS);
|
||||
/* initialize cookie system */
|
||||
InitializeCriticalSection(&osi_sleepFDCS);
|
||||
|
||||
/* register the FD type */
|
||||
typep = osi_RegisterFDType("sleep", &osi_sleepFDOps, NULL);
|
||||
if (typep) {
|
||||
/* add formatting info */
|
||||
osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 0,
|
||||
"Sleep address", OSI_DBRPC_HEX);
|
||||
osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 1,
|
||||
"Thread ID", 0);
|
||||
osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 2,
|
||||
"States", OSI_DBRPC_HEX);
|
||||
}
|
||||
/* register the FD type */
|
||||
typep = osi_RegisterFDType("sleep", &osi_sleepFDOps, NULL);
|
||||
if (typep) {
|
||||
/* add formatting info */
|
||||
osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 0,
|
||||
"Sleep address", OSI_DBRPC_HEX);
|
||||
osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 1,
|
||||
"Thread ID", 0);
|
||||
osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 2,
|
||||
"States", OSI_DBRPC_HEX);
|
||||
}
|
||||
|
||||
osi_BaseInit();
|
||||
osi_BaseInit();
|
||||
|
||||
osi_StatInit();
|
||||
osi_StatInit();
|
||||
|
||||
osi_InitQueue();
|
||||
osi_InitQueue();
|
||||
|
||||
osi_EndOnce(&once);
|
||||
osi_EndOnce(&once);
|
||||
}
|
||||
|
||||
void osi_TWait(osi_turnstile_t *turnp, int waitFor, void *patchp, CRITICAL_SECTION *releasep)
|
||||
void osi_TWait(osi_turnstile_t *turnp, int waitFor, void *patchp, DWORD *tidp, CRITICAL_SECTION *releasep)
|
||||
{
|
||||
osi_sleepInfo_t *sp;
|
||||
unsigned int code;
|
||||
@ -273,35 +274,36 @@ void osi_TWait(osi_turnstile_t *turnp, int waitFor, void *patchp, CRITICAL_SECTI
|
||||
sp->refCount = 0;
|
||||
sp->waitFor = waitFor;
|
||||
sp->value = (LONG_PTR) patchp;
|
||||
sp->tidp = tidp;
|
||||
osi_QAddT((osi_queue_t **) &turnp->firstp, (osi_queue_t **) &turnp->lastp, &sp->q);
|
||||
if (!turnp->lastp)
|
||||
turnp->lastp = sp;
|
||||
LeaveCriticalSection(releasep);
|
||||
|
||||
/* now wait for the signal */
|
||||
while(1) {
|
||||
/* wait */
|
||||
code = WaitForSingleObject(sp->sema,
|
||||
/* timeout */ INFINITE);
|
||||
/* now wait for the signal */
|
||||
while(1) {
|
||||
/* wait */
|
||||
code = WaitForSingleObject(sp->sema,
|
||||
/* timeout */ INFINITE);
|
||||
|
||||
/* if the reason for the wakeup was that we were signalled,
|
||||
* break out, otherwise try again, since the semaphore count is
|
||||
* decreased only when we get WAIT_OBJECT_0 back.
|
||||
*/
|
||||
if (code == WAIT_OBJECT_0) break;
|
||||
} /* while we're waiting */
|
||||
|
||||
/* we're the only one who should be looking at or changing this
|
||||
* structure after it gets signalled. Sema sp->sema isn't signalled
|
||||
* any longer after we're back from WaitForSingleObject, so we can
|
||||
* free this element directly.
|
||||
/* if the reason for the wakeup was that we were signalled,
|
||||
* break out, otherwise try again, since the semaphore count is
|
||||
* decreased only when we get WAIT_OBJECT_0 back.
|
||||
*/
|
||||
osi_assert(sp->states & OSI_SLEEPINFO_SIGNALLED);
|
||||
if (code == WAIT_OBJECT_0) break;
|
||||
} /* while we're waiting */
|
||||
|
||||
osi_FreeSleepInfo(sp);
|
||||
/* we're the only one who should be looking at or changing this
|
||||
* structure after it gets signalled. Sema sp->sema isn't signalled
|
||||
* any longer after we're back from WaitForSingleObject, so we can
|
||||
* free this element directly.
|
||||
*/
|
||||
osi_assert(sp->states & OSI_SLEEPINFO_SIGNALLED);
|
||||
|
||||
/* reobtain, since caller commonly needs it */
|
||||
EnterCriticalSection(releasep);
|
||||
osi_FreeSleepInfo(sp);
|
||||
|
||||
/* reobtain, since caller commonly needs it */
|
||||
EnterCriticalSection(releasep);
|
||||
}
|
||||
|
||||
/* must be called with a critical section held that guards the turnstile
|
||||
@ -311,29 +313,29 @@ void osi_TWait(osi_turnstile_t *turnp, int waitFor, void *patchp, CRITICAL_SECTI
|
||||
*/
|
||||
void osi_TSignal(osi_turnstile_t *turnp)
|
||||
{
|
||||
osi_sleepInfo_t *sp;
|
||||
osi_sleepInfo_t *sp;
|
||||
|
||||
if (!turnp->lastp)
|
||||
return;
|
||||
if (!turnp->lastp)
|
||||
return;
|
||||
|
||||
sp = turnp->lastp;
|
||||
turnp->lastp = (osi_sleepInfo_t *) osi_QPrev(&sp->q);
|
||||
osi_QRemoveHT((osi_queue_t **) &turnp->firstp, (osi_queue_t **) &turnp->lastp, &sp->q);
|
||||
sp->states |= OSI_SLEEPINFO_SIGNALLED;
|
||||
ReleaseSemaphore(sp->sema, 1, (long *) 0);
|
||||
sp = turnp->lastp;
|
||||
turnp->lastp = (osi_sleepInfo_t *) osi_QPrev(&sp->q);
|
||||
osi_QRemoveHT((osi_queue_t **) &turnp->firstp, (osi_queue_t **) &turnp->lastp, &sp->q);
|
||||
sp->states |= OSI_SLEEPINFO_SIGNALLED;
|
||||
ReleaseSemaphore(sp->sema, 1, (long *) 0);
|
||||
}
|
||||
|
||||
/* like TSignal, only wake *everyone* */
|
||||
void osi_TBroadcast(osi_turnstile_t *turnp)
|
||||
{
|
||||
osi_sleepInfo_t *sp;
|
||||
osi_sleepInfo_t *sp;
|
||||
|
||||
while(sp = turnp->lastp) {
|
||||
turnp->lastp = (osi_sleepInfo_t *) osi_QPrev(&sp->q);
|
||||
osi_QRemoveHT((osi_queue_t **) &turnp->firstp, (osi_queue_t **) &turnp->lastp, &sp->q);
|
||||
sp->states |= OSI_SLEEPINFO_SIGNALLED;
|
||||
ReleaseSemaphore(sp->sema, 1, (long *) 0);
|
||||
} /* while someone's still asleep */
|
||||
while(sp = turnp->lastp) {
|
||||
turnp->lastp = (osi_sleepInfo_t *) osi_QPrev(&sp->q);
|
||||
osi_QRemoveHT((osi_queue_t **) &turnp->firstp, (osi_queue_t **) &turnp->lastp, &sp->q);
|
||||
sp->states |= OSI_SLEEPINFO_SIGNALLED;
|
||||
ReleaseSemaphore(sp->sema, 1, (long *) 0);
|
||||
} /* while someone's still asleep */
|
||||
}
|
||||
|
||||
/* special turnstile signal for mutexes and locks. Wakes up only those who
|
||||
@ -352,64 +354,71 @@ void osi_TBroadcast(osi_turnstile_t *turnp)
|
||||
*/
|
||||
void osi_TSignalForMLs(osi_turnstile_t *turnp, int stillHaveReaders, CRITICAL_SECTION *csp)
|
||||
{
|
||||
osi_sleepInfo_t *tsp; /* a temp */
|
||||
osi_sleepInfo_t *nsp; /* a temp */
|
||||
osi_queue_t *wakeupListp; /* list of dudes to wakeup after dropping lock */
|
||||
int wokeReader;
|
||||
unsigned short *sp;
|
||||
unsigned char *cp;
|
||||
osi_sleepInfo_t *tsp; /* a temp */
|
||||
osi_sleepInfo_t *nsp; /* a temp */
|
||||
osi_queue_t *wakeupListp; /* list of dudes to wakeup after dropping lock */
|
||||
int wokeReader;
|
||||
unsigned short *sp;
|
||||
unsigned char *cp;
|
||||
|
||||
wokeReader = stillHaveReaders;
|
||||
wakeupListp = NULL;
|
||||
while(tsp = turnp->lastp) {
|
||||
/* look at each sleepInfo until we find someone we're not supposed to
|
||||
* wakeup.
|
||||
*/
|
||||
if (tsp->waitFor & OSI_SLEEPINFO_W4WRITE) {
|
||||
if (wokeReader) break;
|
||||
}
|
||||
else wokeReader = 1;
|
||||
wokeReader = stillHaveReaders;
|
||||
wakeupListp = NULL;
|
||||
while(tsp = turnp->lastp) {
|
||||
/* look at each sleepInfo until we find someone we're not supposed to
|
||||
* wakeup.
|
||||
*/
|
||||
if (tsp->waitFor & OSI_SLEEPINFO_W4WRITE) {
|
||||
if (wokeReader)
|
||||
break;
|
||||
}
|
||||
else
|
||||
wokeReader = 1;
|
||||
|
||||
/* otherwise, we will wake this guy. For now, remove from this list
|
||||
* and move to private one, so we can do the wakeup after releasing
|
||||
* the crit sec.
|
||||
*/
|
||||
turnp->lastp = (osi_sleepInfo_t *) osi_QPrev(&tsp->q);
|
||||
osi_QRemoveHT((osi_queue_t **) &turnp->firstp, (osi_queue_t **) &turnp->lastp, &tsp->q);
|
||||
/* otherwise, we will wake this guy. For now, remove from this list
|
||||
* and move to private one, so we can do the wakeup after releasing
|
||||
* the crit sec.
|
||||
*/
|
||||
turnp->lastp = (osi_sleepInfo_t *) osi_QPrev(&tsp->q);
|
||||
osi_QRemoveHT((osi_queue_t **) &turnp->firstp, (osi_queue_t **) &turnp->lastp, &tsp->q);
|
||||
|
||||
/* do the patching required for lock obtaining */
|
||||
if (tsp->waitFor & OSI_SLEEPINFO_W4WRITE) {
|
||||
cp = (void *) tsp->value;
|
||||
(*cp) |= OSI_LOCKFLAG_EXCL;
|
||||
}
|
||||
else if (tsp->waitFor & OSI_SLEEPINFO_W4READ) {
|
||||
sp = (void *) tsp->value;
|
||||
(*sp)++;
|
||||
}
|
||||
|
||||
/* and add to our own list */
|
||||
tsp->q.nextp = wakeupListp;
|
||||
wakeupListp = &tsp->q;
|
||||
|
||||
/* now if we woke a writer, we're done, since it is pointless
|
||||
* to wake more than one writer.
|
||||
*/
|
||||
if (!wokeReader) break;
|
||||
/* do the patching required for lock obtaining */
|
||||
if (tsp->waitFor & OSI_SLEEPINFO_W4WRITE) {
|
||||
cp = (void *) tsp->value;
|
||||
(*cp) |= OSI_LOCKFLAG_EXCL;
|
||||
tsp->tidp[0] = tsp->tid;
|
||||
}
|
||||
else if (tsp->waitFor & OSI_SLEEPINFO_W4READ) {
|
||||
sp = (void *) tsp->value;
|
||||
(*sp)++;
|
||||
if ((*sp) <= OSI_RWLOCK_THREADS)
|
||||
tsp->tidp[(*sp)-1] = tsp->tid;
|
||||
}
|
||||
|
||||
/* hit end, or found someone we're not supposed to wakeup */
|
||||
if (csp) LeaveCriticalSection(csp);
|
||||
/* and add to our own list */
|
||||
tsp->q.nextp = wakeupListp;
|
||||
wakeupListp = &tsp->q;
|
||||
|
||||
/* now if we woke a writer, we're done, since it is pointless
|
||||
* to wake more than one writer.
|
||||
*/
|
||||
if (!wokeReader)
|
||||
break;
|
||||
}
|
||||
|
||||
/* hit end, or found someone we're not supposed to wakeup */
|
||||
if (csp)
|
||||
LeaveCriticalSection(csp);
|
||||
|
||||
/* finally, wakeup everyone we found. Don't free things since the sleeper
|
||||
* will free the sleepInfo structure.
|
||||
*/
|
||||
for(tsp = (osi_sleepInfo_t *) wakeupListp; tsp; tsp = nsp) {
|
||||
/* pull this out first, since *tsp *could* get freed immediately
|
||||
* after the ReleaseSemaphore, if a context swap occurs.
|
||||
*/
|
||||
nsp = (osi_sleepInfo_t *) tsp->q.nextp;
|
||||
tsp->states |= OSI_SLEEPINFO_SIGNALLED;
|
||||
ReleaseSemaphore(tsp->sema, 1, (long *) 0);
|
||||
/* pull this out first, since *tsp *could* get freed immediately
|
||||
* after the ReleaseSemaphore, if a context swap occurs.
|
||||
*/
|
||||
nsp = (osi_sleepInfo_t *) tsp->q.nextp;
|
||||
tsp->states |= OSI_SLEEPINFO_SIGNALLED;
|
||||
ReleaseSemaphore(tsp->sema, 1, (long *) 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -492,39 +501,39 @@ void osi_WakeupSpin(LONG_PTR sleepValue)
|
||||
|
||||
void osi_Sleep(LONG_PTR sleepVal)
|
||||
{
|
||||
CRITICAL_SECTION *csp;
|
||||
CRITICAL_SECTION *csp;
|
||||
|
||||
/* may as well save some code by using SleepSched again */
|
||||
csp = &osi_baseAtomicCS[0];
|
||||
EnterCriticalSection(csp);
|
||||
osi_SleepSpin(sleepVal, csp);
|
||||
/* may as well save some code by using SleepSched again */
|
||||
csp = &osi_baseAtomicCS[0];
|
||||
EnterCriticalSection(csp);
|
||||
osi_SleepSpin(sleepVal, csp);
|
||||
}
|
||||
|
||||
void osi_Wakeup(LONG_PTR sleepVal)
|
||||
{
|
||||
/* how do we do osi_Wakeup on a per-lock package type? */
|
||||
/* how do we do osi_Wakeup on a per-lock package type? */
|
||||
|
||||
osi_WakeupSpin(sleepVal);
|
||||
osi_WakeupSpin(sleepVal);
|
||||
}
|
||||
|
||||
long osi_SleepFDCreate(osi_fdType_t *fdTypep, osi_fd_t **outpp)
|
||||
{
|
||||
osi_sleepFD_t *cp;
|
||||
osi_sleepFD_t *cp;
|
||||
|
||||
cp = (osi_sleepFD_t *)malloc(sizeof(*cp));
|
||||
memset((void *) cp, 0, sizeof(*cp));
|
||||
cp->idx = 0;
|
||||
cp->sip = NULL;
|
||||
cp = (osi_sleepFD_t *)malloc(sizeof(*cp));
|
||||
memset((void *) cp, 0, sizeof(*cp));
|
||||
cp->idx = 0;
|
||||
cp->sip = NULL;
|
||||
|
||||
/* done */
|
||||
*outpp = &cp->fd;
|
||||
return 0;
|
||||
/* done */
|
||||
*outpp = &cp->fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long osi_SleepFDClose(osi_fd_t *cp)
|
||||
{
|
||||
free((void *) cp);
|
||||
return 0;
|
||||
free((void *) cp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* called with osi_sleepFDCS locked; returns with same, so that
|
||||
@ -533,52 +542,55 @@ long osi_SleepFDClose(osi_fd_t *cp)
|
||||
*/
|
||||
void osi_AdvanceSleepFD(osi_sleepFD_t *cp)
|
||||
{
|
||||
int idx; /* index we're dealing with */
|
||||
int oidx; /* index we locked */
|
||||
osi_sleepInfo_t *sip;
|
||||
osi_sleepInfo_t *nsip;
|
||||
int idx; /* index we're dealing with */
|
||||
int oidx; /* index we locked */
|
||||
osi_sleepInfo_t *sip;
|
||||
osi_sleepInfo_t *nsip;
|
||||
|
||||
idx = 0; /* so we go around once safely */
|
||||
sip = NULL;
|
||||
while(idx < OSI_SLEEPHASHSIZE) {
|
||||
/* cp->sip should be held */
|
||||
idx = cp->idx;
|
||||
EnterCriticalSection(&osi_critSec[idx]);
|
||||
oidx = idx; /* remember original index; that's the one we locked */
|
||||
idx = 0; /* so we go around once safely */
|
||||
sip = NULL;
|
||||
while(idx < OSI_SLEEPHASHSIZE) {
|
||||
/* cp->sip should be held */
|
||||
idx = cp->idx;
|
||||
EnterCriticalSection(&osi_critSec[idx]);
|
||||
oidx = idx; /* remember original index; that's the one we locked */
|
||||
|
||||
/* if there's a sleep info structure in the FD, it should be held; it
|
||||
* is the one we just processed, so we want to move on to the next.
|
||||
* If not, then we want to process the chain in the bucket idx points
|
||||
* to.
|
||||
*/
|
||||
if ((sip = cp->sip) == NULL) {
|
||||
sip = osi_sleepers[idx];
|
||||
if (!sip) idx++;
|
||||
else sip->refCount++;
|
||||
}
|
||||
else {
|
||||
/* it is safe to release the current sleep info guy now
|
||||
* since we hold the bucket lock. Pull next guy out first,
|
||||
* since if sip is deleted, Release will move him into
|
||||
* free list.
|
||||
*/
|
||||
nsip = (osi_sleepInfo_t *) sip->q.nextp;
|
||||
osi_ReleaseSleepInfo(sip);
|
||||
sip = nsip;
|
||||
/* if there's a sleep info structure in the FD, it should be held; it
|
||||
* is the one we just processed, so we want to move on to the next.
|
||||
* If not, then we want to process the chain in the bucket idx points
|
||||
* to.
|
||||
*/
|
||||
if ((sip = cp->sip) == NULL) {
|
||||
sip = osi_sleepers[idx];
|
||||
if (!sip) idx++;
|
||||
else sip->refCount++;
|
||||
}
|
||||
else {
|
||||
/* it is safe to release the current sleep info guy now
|
||||
* since we hold the bucket lock. Pull next guy out first,
|
||||
* since if sip is deleted, Release will move him into
|
||||
* free list.
|
||||
*/
|
||||
nsip = (osi_sleepInfo_t *) sip->q.nextp;
|
||||
osi_ReleaseSleepInfo(sip);
|
||||
sip = nsip;
|
||||
|
||||
if (sip) sip->refCount++;
|
||||
else idx++;
|
||||
}
|
||||
cp->idx = idx;
|
||||
cp->sip = sip;
|
||||
LeaveCriticalSection(&osi_critSec[oidx]);
|
||||
if (sip)
|
||||
sip->refCount++;
|
||||
else
|
||||
idx++;
|
||||
}
|
||||
cp->idx = idx;
|
||||
cp->sip = sip;
|
||||
LeaveCriticalSection(&osi_critSec[oidx]);
|
||||
|
||||
/* now, if we advanced to a new sleep info structure, we're
|
||||
* done, otherwise we continue and look at the next hash bucket
|
||||
* until we're out of them.
|
||||
*/
|
||||
if (sip) break;
|
||||
}
|
||||
/* now, if we advanced to a new sleep info structure, we're
|
||||
* done, otherwise we continue and look at the next hash bucket
|
||||
* until we're out of them.
|
||||
*/
|
||||
if (sip)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -620,7 +632,7 @@ long osi_SleepFDGetInfo(osi_fd_t *ifdp, osi_remGetInfoParms_t *parmsp)
|
||||
/* finally, DLL-specific code for NT */
|
||||
BOOL APIENTRY DLLMain(HANDLE inst, DWORD why, char *reserved)
|
||||
{
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* some misc functions for setting hash table sizes */
|
||||
@ -628,48 +640,51 @@ BOOL APIENTRY DLLMain(HANDLE inst, DWORD why, char *reserved)
|
||||
/* return true iff x is prime */
|
||||
int osi_IsPrime(unsigned long x)
|
||||
{
|
||||
unsigned long c;
|
||||
unsigned long c;
|
||||
|
||||
/* even numbers aren't prime */
|
||||
if ((x & 1) == 0 && x != 2) return 0;
|
||||
/* even numbers aren't prime */
|
||||
if ((x & 1) == 0 && x != 2) return 0;
|
||||
|
||||
for(c = 3; c<x; c += 2) {
|
||||
/* see if x is divisible by c */
|
||||
if ((x % c) == 0) return 0; /* yup, it ain't prime */
|
||||
for(c = 3; c<x; c += 2) {
|
||||
/* see if x is divisible by c */
|
||||
if ((x % c) == 0)
|
||||
return 0; /* yup, it ain't prime */
|
||||
|
||||
/* see if we've gone far enough; only have to compute until
|
||||
* square root of x.
|
||||
*/
|
||||
if (c*c > x) return 1;
|
||||
}
|
||||
/* see if we've gone far enough; only have to compute until
|
||||
* square root of x.
|
||||
*/
|
||||
if (c*c > x)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* probably never get here */
|
||||
return 1;
|
||||
/* probably never get here */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* return first prime number less than or equal to x */
|
||||
unsigned long osi_PrimeLessThan(unsigned long x) {
|
||||
unsigned long c;
|
||||
unsigned long c;
|
||||
|
||||
for(c = x; c > 1; c--) {
|
||||
if (osi_IsPrime(c)) return c;
|
||||
}
|
||||
for(c = x; c > 1; c--) {
|
||||
if (osi_IsPrime(c))
|
||||
return c;
|
||||
}
|
||||
|
||||
/* ever reached? */
|
||||
return 1;
|
||||
/* ever reached? */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* return the # of seconds since some fixed date */
|
||||
unsigned long osi_GetBootTime(void)
|
||||
{
|
||||
return osi_bootTime;
|
||||
return osi_bootTime;
|
||||
}
|
||||
|
||||
static int (*notifFunc)(char *, char *, long) = NULL;
|
||||
|
||||
void osi_InitPanic(void *anotifFunc)
|
||||
{
|
||||
notifFunc = anotifFunc;
|
||||
notifFunc = anotifFunc;
|
||||
}
|
||||
|
||||
void osi_panic(char *msgp, char *filep, long line)
|
||||
@ -712,26 +727,26 @@ time_t osi_Time(void)
|
||||
/* get time in seconds since some relatively recent time */
|
||||
void osi_GetTime(long *timesp)
|
||||
{
|
||||
FILETIME fileTime;
|
||||
SYSTEMTIME sysTime;
|
||||
unsigned long remainder;
|
||||
LARGE_INTEGER bootTime;
|
||||
FILETIME fileTime;
|
||||
SYSTEMTIME sysTime;
|
||||
unsigned long remainder;
|
||||
LARGE_INTEGER bootTime;
|
||||
|
||||
/* setup boot time values */
|
||||
GetSystemTime(&sysTime);
|
||||
SystemTimeToFileTime(&sysTime, &fileTime);
|
||||
/* setup boot time values */
|
||||
GetSystemTime(&sysTime);
|
||||
SystemTimeToFileTime(&sysTime, &fileTime);
|
||||
|
||||
/* change the base of the time so it won't be negative for a long time */
|
||||
fileTime.dwHighDateTime -= 28000000;
|
||||
/* change the base of the time so it won't be negative for a long time */
|
||||
fileTime.dwHighDateTime -= 28000000;
|
||||
|
||||
bootTime.HighPart = fileTime.dwHighDateTime;
|
||||
bootTime.LowPart = fileTime.dwLowDateTime;
|
||||
/* now, bootTime is in 100 nanosecond units, and we'd really rather
|
||||
* have it in 1 microsecond units, units 10 times bigger.
|
||||
* So, we divide.
|
||||
*/
|
||||
bootTime = ExtendedLargeIntegerDivide(bootTime, 10, &remainder);
|
||||
bootTime = ExtendedLargeIntegerDivide(bootTime, 1000000, &remainder);
|
||||
timesp[0] = bootTime.LowPart; /* seconds */
|
||||
timesp[1] = remainder; /* microseconds */
|
||||
bootTime.HighPart = fileTime.dwHighDateTime;
|
||||
bootTime.LowPart = fileTime.dwLowDateTime;
|
||||
/* now, bootTime is in 100 nanosecond units, and we'd really rather
|
||||
* have it in 1 microsecond units, units 10 times bigger.
|
||||
* So, we divide.
|
||||
*/
|
||||
bootTime = ExtendedLargeIntegerDivide(bootTime, 10, &remainder);
|
||||
bootTime = ExtendedLargeIntegerDivide(bootTime, 1000000, &remainder);
|
||||
timesp[0] = bootTime.LowPart; /* seconds */
|
||||
timesp[1] = remainder; /* microseconds */
|
||||
}
|
||||
|
@ -25,14 +25,15 @@
|
||||
#define OSI_SLEEPINFO_W4READ 1 /* waiting for a read lock */
|
||||
#define OSI_SLEEPINFO_W4WRITE 2 /* waiting for a write lock */
|
||||
typedef struct osi_sleepInfo {
|
||||
osi_queue_t q;
|
||||
LONG_PTR value; /* sleep value when in a sleep queue, patch addr for turnstiles */
|
||||
size_t tid; /* thread ID of sleeper */
|
||||
EVENT_HANDLE sema; /* semaphore for this entry */
|
||||
unsigned short states; /* states bits */
|
||||
unsigned short idx; /* sleep hash table we're in, if in hash */
|
||||
unsigned short waitFor; /* what are we waiting for; used for bulk wakeups */
|
||||
unsigned long refCount; /* reference count from FDs */
|
||||
osi_queue_t q;
|
||||
LONG_PTR value; /* sleep value when in a sleep queue, patch addr for turnstiles */
|
||||
DWORD *tidp; /* tid history */
|
||||
size_t tid; /* thread ID of sleeper */
|
||||
EVENT_HANDLE sema; /* semaphore for this entry */
|
||||
unsigned short states; /* states bits */
|
||||
unsigned short idx; /* sleep hash table we're in, if in hash */
|
||||
unsigned short waitFor; /* what are we waiting for; used for bulk wakeups */
|
||||
unsigned long refCount; /* reference count from FDs */
|
||||
} osi_sleepInfo_t;
|
||||
|
||||
/* first guy is the most recently added process */
|
||||
@ -144,8 +145,9 @@ void osi_panic(char *, char *, long);
|
||||
|
||||
time_t osi_Time(void);
|
||||
|
||||
extern void osi_TWait(osi_turnstile_t *turnp, int waitFor, void *patchp,
|
||||
Crit_Sec *releasep);
|
||||
extern void osi_TWait(osi_turnstile_t *turnp, int waitFor,
|
||||
void *patchp, DWORD *tidp,
|
||||
Crit_Sec *releasep);
|
||||
|
||||
extern void osi_TSignal(osi_turnstile_t *turnp);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -234,7 +234,7 @@ static void lock_ConvertRToWStat(osi_rwlock_t *lockp)
|
||||
lockp->waiters++;
|
||||
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);
|
||||
|
||||
@ -302,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);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ typedef struct osi_rwlockStat {
|
||||
osi_turnstile_t turn; /* the real turnstile */
|
||||
unsigned long refCount; /* so we can iterate cleanly */
|
||||
short states;
|
||||
DWORD tid;
|
||||
DWORD tid[OSI_RWLOCK_THREADS];
|
||||
|
||||
/* statistics */
|
||||
LARGE_INTEGER writeLockedTime; /* total time held */
|
||||
|
Loading…
Reference in New Issue
Block a user