2 * Copyright (C) 1998, 1989 Transarc Corporation - All rights reserved
4 * (C) COPYRIGHT IBM CORPORATION 1987, 1988
5 * LICENSED MATERIALS - PROPERTY OF IBM
9 /* Copyright (C) 1994 Cazamar Systems, Inc. */
11 #include <afs/param.h>
21 * 2. osi_activeInfoAllocCS.
22 * 3. individual log critical sections (since we call log pkg).
24 * There are no cases today where both 1 and 2 are locked simultaneously.
27 /* el cheapo watch system */
28 osi_watchProc_t *osi_statWatchProcp; /* proc to call on too-long held locks */
29 void *osi_statWatchRockp; /* with this rock */
30 unsigned long osi_statWatchMS; /* after a lock is held this many MS */
32 /* type index of the statistics gathering lock package */
35 /* log to which to log lock events */
36 osi_log_t *osi_statLogp;
38 /* queue of all rwlock auxiliary structures */
39 osi_queue_t *osi_allRWLocks;
41 /* queue of all mutex auxiliary structures */
42 osi_queue_t *osi_allMutexes;
44 /* free list and mutex for active info structures */
45 osi_activeInfo_t *osi_activeInfoFreeListp;
46 CRITICAL_SECTION osi_activeInfoAllocCS;
48 /* atomicity-providing critical sections */
49 CRITICAL_SECTION osi_statAtomicCS[OSI_MUTEXHASHSIZE];
51 /* lock protecting ref count on locks, osi_allMutexes and osi_RWLocks, and
52 * file descriptor contents
54 CRITICAL_SECTION osi_statFDCS;
56 void osi_SetStatLog(osi_log_t *logp)
58 /* nicer if ref counted */
62 static void lock_ObtainWriteStat(osi_rwlock_t *lockp)
64 osi_rwlockStat_t *realp;
66 CRITICAL_SECTION *csp;
68 realp = (osi_rwlockStat_t *)lockp->d.privateDatap;
71 csp = &osi_statAtomicCS[lockp->atomicIndex];
72 EnterCriticalSection(csp);
74 /* here we have the fast lock, so see if we can obtain the real lock */
75 if ((lockp->waiters > 0) || (lockp->flags & OSI_LOCKFLAG_EXCL)
76 || (lockp->readers > 0)) {
78 if (!ap) ap = osi_QueueActiveInfo(&realp->qi,
79 OSI_ACTIVEFLAGS_WRITER | OSI_ACTIVEFLAGS_WAITER);
80 osi_TWait(&realp->turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
82 osi_assert((lockp->flags & OSI_LOCKFLAG_EXCL) && lockp->readers == 0);
85 /* if we're here, all clear to set the lock */
86 lockp->flags |= OSI_LOCKFLAG_EXCL;
89 /* if we have ap set, we have some timer info about the last sleep operation
90 * that we should merge in under the spin lock.
93 /* remove from queue and turn time to incremental time */
94 osi_RemoveActiveInfo(&realp->qi, ap);
96 /* add in increment to statistics */
97 realp->writeBlockedCount++;
98 realp->writeBlockedTime = LargeIntegerAdd(realp->writeBlockedTime,
100 osi_FreeActiveInfo(ap);
103 osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_WRITER);
104 LeaveCriticalSection(csp);
107 static void lock_ObtainReadStat(osi_rwlock_t *lockp)
109 osi_activeInfo_t *ap;
110 osi_rwlockStat_t *realp;
111 CRITICAL_SECTION *csp;
114 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
116 /* otherwise we're the fast base type */
117 csp = &osi_statAtomicCS[lockp->atomicIndex];
118 EnterCriticalSection(csp);
120 /* here we have the fast lock, so see if we can obtain the real lock */
121 if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
123 if (!ap) ap = osi_QueueActiveInfo(&realp->qi,
124 OSI_ACTIVEFLAGS_WAITER | OSI_ACTIVEFLAGS_READER);
125 osi_TWait(&realp->turn, OSI_SLEEPINFO_W4READ, &lockp->readers, csp);
127 osi_assert(!(lockp->flags & OSI_LOCKFLAG_EXCL) && lockp->readers > 0);
130 /* if we're here, all clear to set the lock */
135 /* have statistics to merge in */
136 osi_RemoveActiveInfo(&realp->qi, ap);
137 realp->readBlockedCount++;
138 realp->readBlockedTime = LargeIntegerAdd(realp->readBlockedTime, ap->startTime);
139 osi_FreeActiveInfo(ap);
142 osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_READER);
143 LeaveCriticalSection(csp);
146 static void lock_ReleaseReadStat(osi_rwlock_t *lockp)
148 osi_activeInfo_t *ap;
149 osi_rwlockStat_t *realp;
150 CRITICAL_SECTION *csp;
152 realp = (osi_rwlockStat_t *)lockp->d.privateDatap;
154 csp = &osi_statAtomicCS[lockp->atomicIndex];
155 EnterCriticalSection(csp);
157 osi_assert(lockp->readers > 0);
158 ap = osi_FindActiveInfo(&realp->qi);
159 osi_assert(ap != NULL);
160 osi_RemoveActiveInfo(&realp->qi, ap);
161 realp->readLockedCount++;
162 realp->readLockedTime = LargeIntegerAdd(realp->readLockedTime, ap->startTime);
163 osi_FreeActiveInfo(ap);
165 if (--lockp->readers == 0 && !osi_TEmpty(&realp->turn)) {
166 osi_TSignalForMLs(&realp->turn, 0, csp);
169 /* and finally release the big lock */
170 LeaveCriticalSection(csp);
174 static void lock_ConvertWToRStat(osi_rwlock_t *lockp)
176 osi_activeInfo_t *ap;
177 osi_rwlockStat_t *realp;
178 CRITICAL_SECTION *csp;
180 realp = (osi_rwlockStat_t *)lockp->d.privateDatap;
182 /* otherwise we're the fast base type */
183 csp = &osi_statAtomicCS[lockp->atomicIndex];
184 EnterCriticalSection(csp);
186 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
187 ap = osi_FindActiveInfo(&realp->qi);
188 osi_assert(ap !=NULL);
189 osi_RemoveActiveInfo(&realp->qi, ap);
190 realp->writeLockedCount++;
191 realp->writeLockedTime = LargeIntegerAdd(realp->writeLockedTime, ap->startTime);
192 osi_FreeActiveInfo(ap);
194 /* and obtain the read lock */
196 osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_READER);
198 lockp->flags &= ~OSI_LOCKFLAG_EXCL;
199 if (!osi_TEmpty(&realp->turn)) {
200 osi_TSignalForMLs(&realp->turn, 1, csp);
203 /* and finally release the big lock */
204 LeaveCriticalSection(csp);
208 static void lock_ReleaseWriteStat(osi_rwlock_t *lockp)
210 osi_activeInfo_t *ap;
211 osi_rwlockStat_t *realp;
212 CRITICAL_SECTION *csp;
214 realp = (osi_rwlockStat_t *)lockp->d.privateDatap;
216 /* otherwise we're the fast base type */
217 csp = &osi_statAtomicCS[lockp->atomicIndex];
218 EnterCriticalSection(csp);
220 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
221 ap = osi_FindActiveInfo(&realp->qi);
222 osi_assert(ap !=NULL);
223 osi_RemoveActiveInfo(&realp->qi, ap);
224 realp->writeLockedCount++;
225 realp->writeLockedTime = LargeIntegerAdd(realp->writeLockedTime, ap->startTime);
226 osi_FreeActiveInfo(ap);
228 lockp->flags &= ~OSI_LOCKFLAG_EXCL;
229 if (!osi_TEmpty(&realp->turn)) {
230 osi_TSignalForMLs(&realp->turn, 0, csp);
233 /* and finally release the big lock */
234 LeaveCriticalSection(csp);
238 static void lock_ObtainMutexStat(struct osi_mutex *lockp)
240 osi_activeInfo_t *ap;
241 osi_mutexStat_t *realp;
242 CRITICAL_SECTION *csp;
245 realp = (osi_mutexStat_t *) lockp->d.privateDatap;
247 csp = &osi_statAtomicCS[lockp->atomicIndex];
248 EnterCriticalSection(csp);
250 /* here we have the fast lock, so see if we can obtain the real lock */
251 if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
253 ap = osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_WAITER);
254 osi_TWait(&realp->turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
256 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
259 /* if we're here, all clear to set the lock */
260 lockp->flags |= OSI_LOCKFLAG_EXCL;
263 /* release the blocking ap */
265 osi_RemoveActiveInfo(&realp->qi, ap);
266 realp->blockedCount++;
267 realp->blockedTime = LargeIntegerAdd(realp->blockedTime, ap->startTime);
268 osi_FreeActiveInfo(ap);
271 /* start tracking this call */
272 osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_WRITER);
274 LeaveCriticalSection(csp);
277 static void lock_ReleaseMutexStat(struct osi_mutex *lockp)
279 osi_activeInfo_t *ap;
280 osi_mutexStat_t *realp;
281 CRITICAL_SECTION *csp;
283 realp = (osi_mutexStat_t *)lockp->d.privateDatap;
285 csp = &osi_statAtomicCS[lockp->atomicIndex];
286 EnterCriticalSection(csp);
288 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
290 ap = osi_FindActiveInfo(&realp->qi);
291 osi_assert(ap != NULL);
292 osi_RemoveActiveInfo(&realp->qi, ap);
293 realp->lockedCount++;
294 realp->lockedTime = LargeIntegerAdd(realp->lockedTime, ap->startTime);
295 osi_FreeActiveInfo(ap);
297 lockp->flags &= ~OSI_LOCKFLAG_EXCL;
298 if (!osi_TEmpty(&realp->turn)) {
299 osi_TSignalForMLs(&realp->turn, 0, csp);
302 /* and finally release the big lock */
303 LeaveCriticalSection(csp);
307 static int lock_TryReadStat(struct osi_rwlock *lockp)
310 osi_rwlockStat_t *realp;
311 CRITICAL_SECTION *csp;
313 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
315 /* otherwise we're the fast base type */
316 csp = &osi_statAtomicCS[lockp->atomicIndex];
317 EnterCriticalSection(csp);
319 /* here we have the fast lock, so see if we can obtain the real lock */
320 if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
324 /* if we're here, all clear to set the lock */
329 /* start tracking lock holding stats */
330 if (i) osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_READER);
332 LeaveCriticalSection(csp);
338 static int lock_TryWriteStat(struct osi_rwlock *lockp)
341 osi_rwlockStat_t *realp;
342 CRITICAL_SECTION *csp;
344 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
346 /* otherwise we're the fast base type */
347 csp = &osi_statAtomicCS[lockp->atomicIndex];
348 EnterCriticalSection(csp);
350 /* here we have the fast lock, so see if we can obtain the real lock */
351 if ((lockp->waiters > 0) || (lockp->flags & OSI_LOCKFLAG_EXCL)
352 || (lockp->readers > 0)) {
356 /* if we're here, all clear to set the lock */
357 lockp->flags |= OSI_LOCKFLAG_EXCL;
361 /* start tracking lock holding stats */
362 if (i) osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_WRITER);
364 LeaveCriticalSection(csp);
370 static int lock_GetRWLockStateStat(struct osi_rwlock *lockp)
373 osi_rwlockStat_t *realp;
374 CRITICAL_SECTION *csp;
376 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
378 /* otherwise we're the fast base type */
379 csp = &osi_statAtomicCS[lockp->atomicIndex];
380 EnterCriticalSection(csp);
383 if (lockp->flags & OSI_LOCKFLAG_EXCL) {
384 i |= OSI_RWLOCK_WRITEHELD;
386 if (lockp->readers) {
387 i |= OSI_RWLOCK_READHELD;
390 LeaveCriticalSection(csp);
396 static int lock_GetMutexStateStat(struct osi_mutex *lockp) {
398 osi_mutexStat_t *realp;
399 CRITICAL_SECTION *csp;
401 realp = (osi_mutexStat_t *) lockp->d.privateDatap;
403 /* otherwise we're the fast base type */
404 csp = &osi_statAtomicCS[lockp->atomicIndex];
405 EnterCriticalSection(csp);
407 /* here we have the fast lock, so see if we can obtain the real lock */
409 if (lockp->flags & OSI_LOCKFLAG_EXCL) {
413 LeaveCriticalSection(csp);
418 static int lock_TryMutexStat(struct osi_mutex *lockp) {
420 osi_mutexStat_t *realp;
421 CRITICAL_SECTION *csp;
423 realp = (osi_mutexStat_t *) lockp->d.privateDatap;
425 /* otherwise we're the fast base type */
426 csp = &osi_statAtomicCS[lockp->atomicIndex];
427 EnterCriticalSection(csp);
429 /* here we have the fast lock, so see if we can obtain the real lock */
430 if ((lockp->waiters > 0) || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
434 /* if we're here, all clear to set the lock */
435 lockp->flags |= OSI_LOCKFLAG_EXCL;
439 if (i) osi_QueueActiveInfo(&realp->qi, 0);
441 LeaveCriticalSection(csp);
446 static void osi_SleepRStat(long sleepVal, struct osi_rwlock *lockp)
448 osi_rwlockStat_t *realp;
449 osi_activeInfo_t *ap;
450 CRITICAL_SECTION *csp;
452 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
454 /* otherwise we're the fast base type */
455 csp = &osi_statAtomicCS[lockp->atomicIndex];
456 EnterCriticalSection(csp);
458 osi_assert(lockp->readers > 0);
460 if (--lockp->readers == 0 && !osi_TEmpty(&realp->turn)) {
461 osi_TSignalForMLs(&realp->turn, 0, NULL);
464 /* now merge in lock hold stats */
465 ap = osi_FindActiveInfo(&realp->qi);
466 osi_assert(ap != NULL);
467 osi_RemoveActiveInfo(&realp->qi, ap);
468 realp->writeLockedCount++;
469 realp->writeLockedTime = LargeIntegerAdd(realp->writeLockedTime, ap->startTime);
470 osi_FreeActiveInfo(ap);
472 /* now call into scheduler to sleep atomically with releasing spin lock */
473 osi_SleepSpin(sleepVal, csp);
476 static void osi_SleepWStat(long sleepVal, struct osi_rwlock *lockp)
478 osi_activeInfo_t *ap;
479 osi_rwlockStat_t *realp;
480 CRITICAL_SECTION *csp;
482 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
484 /* otherwise we're the fast base type */
485 csp = &osi_statAtomicCS[lockp->atomicIndex];
486 EnterCriticalSection(csp);
488 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
490 lockp->flags &= ~OSI_LOCKFLAG_EXCL;
491 if (!osi_TEmpty(&realp->turn)) {
492 osi_TSignalForMLs(&realp->turn, 0, NULL);
495 /* now merge in lock hold stats */
496 ap = osi_FindActiveInfo(&realp->qi);
497 osi_assert(ap != NULL);
498 osi_RemoveActiveInfo(&realp->qi, ap);
499 realp->readLockedCount++;
500 realp->readLockedTime = LargeIntegerAdd(realp->readLockedTime, ap->startTime);
501 osi_FreeActiveInfo(ap);
503 /* and finally release the big lock */
504 osi_SleepSpin(sleepVal, csp);
507 static void osi_SleepMStat(long sleepVal, struct osi_mutex *lockp)
509 osi_mutexStat_t *realp;
510 osi_activeInfo_t *ap;
511 CRITICAL_SECTION *csp;
513 realp = (osi_mutexStat_t *) lockp->d.privateDatap;
515 /* otherwise we're the fast base type */
516 csp = &osi_statAtomicCS[lockp->atomicIndex];
517 EnterCriticalSection(csp);
519 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
521 lockp->flags &= ~OSI_LOCKFLAG_EXCL;
522 if (!osi_TEmpty(&realp->turn)) {
523 osi_TSignalForMLs(&realp->turn, 0, NULL);
526 /* now merge in lock hold stats */
527 ap = osi_FindActiveInfo(&realp->qi);
528 osi_assert(ap != NULL);
529 osi_RemoveActiveInfo(&realp->qi, ap);
530 realp->lockedCount++;
531 realp->lockedTime = LargeIntegerAdd(realp->lockedTime, ap->startTime);
532 osi_FreeActiveInfo(ap);
534 /* and finally release the big lock */
535 osi_SleepSpin(sleepVal, csp);
538 /* this is a function that release a ref count, but we give it a different
539 * name than release to avoid confusion with all of the releases here.
540 * Must be called holding the osi_statFDCS lock.
542 static void lock_DecrMutexStat(osi_mutexStat_t *mp)
544 if (--mp->refCount <= 0 && (mp->states & OSI_STATL_DELETED)) {
545 osi_QRemove(&osi_allMutexes, &mp->q);
550 /* Must be called holding the osi_statFDCS lock. */
551 static void lock_DecrRWLockStat(osi_rwlockStat_t *rwp)
553 if (--rwp->refCount <= 0 && (rwp->states & OSI_STATL_DELETED)) {
554 osi_QRemove(&osi_allRWLocks, &rwp->q);
559 static void lock_FinalizeMutexStat(osi_mutex_t *lockp)
561 osi_mutexStat_t *realp;
563 /* pull out the real pointer */
564 realp = (osi_mutexStat_t *) lockp->d.privateDatap;
566 /* remove from the queues, and free */
567 EnterCriticalSection(&osi_statFDCS);
568 if (realp->refCount <= 0) {
569 osi_QRemove(&osi_allMutexes, &realp->q);
570 free((void *) realp);
572 else realp->states |= OSI_STATL_DELETED;
573 LeaveCriticalSection(&osi_statFDCS);
576 static void lock_FinalizeRWLockStat(osi_rwlock_t *lockp)
578 osi_rwlockStat_t *realp;
580 /* pull out the real pointer */
581 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
583 /* remove from the queues, and free */
584 EnterCriticalSection(&osi_statFDCS);
585 if (realp->refCount <= 0) {
586 osi_QRemove(&osi_allRWLocks, &realp->q);
587 free((void *) realp);
589 else realp->states |= OSI_STATL_DELETED;
590 LeaveCriticalSection(&osi_statFDCS);
593 void lock_InitializeRWLockStat(osi_rwlock_t *lockp, char *namep)
595 osi_rwlockStat_t *realp;
597 realp = (osi_rwlockStat_t *) malloc(sizeof(*realp));
598 lockp->d.privateDatap = (void *) realp;
599 lockp->type = osi_statType;
602 lockp->atomicIndex = osi_MUTEXHASH(lockp);
603 memset(realp, 0, sizeof(*realp));
604 osi_TInit(&realp->turn);
605 realp->qi.namep = namep;
606 realp->qi.backp = lockp;
607 EnterCriticalSection(&osi_statFDCS);
608 osi_QAdd(&osi_allRWLocks, &realp->q);
609 LeaveCriticalSection(&osi_statFDCS);
612 void lock_InitializeMutexStat(osi_mutex_t *lockp, char *namep)
614 osi_mutexStat_t *realp;
616 realp = (osi_mutexStat_t *) malloc(sizeof(*realp));
617 lockp->d.privateDatap = (void *) realp;
618 lockp->type = osi_statType;
620 lockp->atomicIndex = osi_MUTEXHASH(lockp);
621 memset(realp, 0, sizeof(*realp));
622 osi_TInit(&realp->turn);
623 realp->qi.namep = namep;
624 realp->qi.backp = lockp;
625 EnterCriticalSection(&osi_statFDCS);
626 osi_QAdd(&osi_allMutexes, &realp->q);
627 LeaveCriticalSection(&osi_statFDCS);
630 static void osi_FreeActiveInfo(osi_activeInfo_t *ap)
632 EnterCriticalSection(&osi_activeInfoAllocCS);
633 ap->q.nextp = (osi_queue_t *) osi_activeInfoFreeListp;
634 osi_activeInfoFreeListp = ap;
635 LeaveCriticalSection(&osi_activeInfoAllocCS);
638 static osi_activeInfo_t *osi_AllocActiveInfo()
640 osi_activeInfo_t *ap;
642 EnterCriticalSection(&osi_activeInfoAllocCS);
643 if (!(ap = osi_activeInfoFreeListp)) {
644 ap = (osi_activeInfo_t *) malloc(sizeof(osi_activeInfo_t));
647 osi_activeInfoFreeListp = (osi_activeInfo_t *) ap->q.nextp;
649 LeaveCriticalSection(&osi_activeInfoAllocCS);
654 static osi_activeInfo_t *osi_QueueActiveInfo(osi_qiStat_t *qp, int flags)
656 osi_activeInfo_t *ap;
657 osi_queue_t **qpp = (osi_queue_t **) &qp->activeListp;
660 ap = osi_AllocActiveInfo();
662 ap->startTime.LowPart = GetCurrentTime();
663 ap->startTime.HighPart = 0;
664 ap->tid = GetCurrentThreadId();
665 osi_QAdd(qpp, &ap->q);
666 if (osi_statLogp && (flags & OSI_ACTIVEFLAGS_WAITER)) {
667 if (flags & OSI_ACTIVEFLAGS_READER)
669 else if (flags & OSI_ACTIVEFLAGS_WRITER)
670 whatp = "write lock";
671 else whatp = "mutex";
672 osi_Log2(osi_statLogp, "Blocking on %s on %s", whatp, qp->namep);
677 static void osi_RemoveActiveInfo(osi_qiStat_t *qp, osi_activeInfo_t *ap)
680 osi_queue_t **qpp = (osi_queue_t **) &qp->activeListp;
684 now = GetCurrentTime();
685 osi_QRemove(qpp, &ap->q);
687 ap->startTime.LowPart = now - ap->startTime.LowPart;
689 if (osi_statLogp && (flags & OSI_ACTIVEFLAGS_WAITER)) {
690 if (flags & OSI_ACTIVEFLAGS_READER)
692 else if (flags & OSI_ACTIVEFLAGS_WRITER)
693 whatp = "write lock";
694 else whatp = "mutex";
695 osi_Log2(osi_statLogp, "Finally obtained %s on %s", whatp, qp->namep);
698 /* releasing a lock or mutex */
699 if (osi_statWatchProcp && ap->startTime.LowPart > osi_statWatchMS) {
700 (*osi_statWatchProcp)(osi_statWatchRockp, ap->startTime.LowPart,
706 static osi_activeInfo_t *osi_FindActiveInfo(osi_qiStat_t *qp)
709 osi_activeInfo_t *ap;
711 osi_queue_t **qpp = (osi_queue_t **) &qp->activeListp;
714 tid = GetCurrentThreadId();
716 for(tqp = *qpp; tqp; tqp = tqp->nextp) {
717 ap = (osi_activeInfo_t *) tqp;
718 if (ap->tid == tid) break;
724 static osi_lockOps_t osi_statOps = {
726 lock_ObtainWriteStat,
727 lock_ReleaseReadStat,
728 lock_ReleaseWriteStat,
729 lock_ObtainMutexStat,
730 lock_ReleaseMutexStat,
737 lock_InitializeMutexStat,
738 lock_InitializeRWLockStat,
739 lock_FinalizeMutexStat,
740 lock_FinalizeRWLockStat,
741 lock_ConvertWToRStat,
742 lock_GetRWLockStateStat,
743 lock_GetMutexStateStat
746 long osi_StatFDCreate(osi_fdType_t *typep, osi_fd_t **fdpp)
750 osi_rwlockStat_t *rwp;
752 fdp = (osi_statFD_t *) malloc(sizeof(*fdp));
753 EnterCriticalSection(&osi_statFDCS);
754 if (osi_allMutexes) {
755 fdp->curp = osi_allMutexes;
756 mp = (osi_mutexStat_t *) fdp->curp;
760 else if (osi_allRWLocks) {
761 fdp->curp = osi_allRWLocks;
762 rwp = (osi_rwlockStat_t *) fdp->curp;
766 else fdp->curp = NULL;
767 LeaveCriticalSection(&osi_statFDCS);
774 long osi_StatFDGetInfo(osi_fd_t *ifdp, osi_remGetInfoParms_t *parmsp)
778 osi_rwlockStat_t *rwp;
780 osi_mutex_t *backMutexp;
781 osi_rwlock_t *backRWLockp;
783 /* initialize out structure */
787 fdp = (osi_statFD_t *) ifdp;
790 /* we're done if curp is null */
791 if (qp == NULL) return OSI_DBRPC_EOF;
793 /* copy out statistics */
794 if (fdp->which == 0) {
795 /* this is a mutex */
796 mp = (osi_mutexStat_t *) qp;
798 memset((void *) parmsp, 0, sizeof(*parmsp));
799 backMutexp = mp->qi.backp;
800 parmsp->idata[0] = (long) backMutexp;
801 parmsp->idata[1] = (backMutexp->flags & OSI_LOCKFLAG_EXCL)? 1 : 0;
802 /* reader count [2] is 0 */
803 parmsp->idata[3] = (backMutexp->waiters > 0)? 1 : 0;
804 parmsp->idata[4] = mp->lockedTime.LowPart;
805 parmsp->idata[5] = mp->lockedCount;
806 parmsp->idata[6] = mp->blockedTime.LowPart;
807 parmsp->idata[7] = mp->blockedCount;
808 strcpy(parmsp->sdata[0], mp->qi.namep);
812 else if (fdp->which == 1) {
814 rwp = (osi_rwlockStat_t *) qp;
816 memset((void *) parmsp, 0, sizeof(*parmsp));
817 backRWLockp = rwp->qi.backp;
818 parmsp->idata[0] = (long) backRWLockp;
819 parmsp->idata[1] = (backRWLockp->flags & OSI_LOCKFLAG_EXCL)? 1 : 0;
820 parmsp->idata[2] = backRWLockp->readers;
821 parmsp->idata[3] = (backRWLockp->waiters > 0)? 1 : 0;
822 parmsp->idata[4] = rwp->writeLockedTime.LowPart;
823 parmsp->idata[5] = rwp->writeLockedCount;
824 parmsp->idata[6] = rwp->writeBlockedTime.LowPart;
825 parmsp->idata[7] = rwp->writeBlockedCount;
826 parmsp->idata[8] = rwp->readLockedTime.LowPart;
827 parmsp->idata[9] = rwp->readLockedCount;
828 parmsp->idata[10] = rwp->readBlockedTime.LowPart;
829 parmsp->idata[11] = rwp->readBlockedCount;
830 strcpy(parmsp->sdata[0], rwp->qi.namep);
835 /* advance to next position */
836 EnterCriticalSection(&osi_statFDCS);
838 if (fdp->which == 0) {
839 mp = (osi_mutexStat_t *) qp;
840 lock_DecrMutexStat(mp);
842 else if (fdp->which == 1) {
843 rwp = (osi_rwlockStat_t *) qp;
844 lock_DecrRWLockStat(rwp);
848 if (qp == NULL && fdp->which == 0) {
850 if (osi_allRWLocks) qp = osi_allRWLocks;
855 if (fdp->which == 0) {
856 mp = (osi_mutexStat_t *) qp;
859 else if (fdp->which == 1) {
860 rwp = (osi_rwlockStat_t *) qp;
864 LeaveCriticalSection(&osi_statFDCS);
869 long osi_StatFDClose(osi_fd_t *ifdp)
875 osi_fdOps_t osi_statFDOps = {
886 /* initialize the stat package */
887 InitializeCriticalSection(&osi_activeInfoAllocCS);
888 InitializeCriticalSection(&osi_statFDCS);
890 for(i=0; i<OSI_MUTEXHASHSIZE; i++)
891 InitializeCriticalSection(&osi_statAtomicCS[i]);
893 /* add stat ops to dynamic registry */
894 osi_LockTypeAdd(&osi_statOps, "stat", &osi_statType);
896 /* add debugging info and file descriptor support */
897 typep = osi_RegisterFDType("lock", &osi_statFDOps, NULL);
899 /* add formatting info */
900 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 0,
901 "Lock address", OSI_DBRPC_HEX);
902 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 1,
904 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 2,
906 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 3,
908 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 4,
909 "Write-locked time", 0);
910 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 5,
911 "Write-locked count", 0);
912 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 6,
913 "Write-blocked time", 0);
914 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 7,
915 "Write-blocked count", 0);
916 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 8,
917 "Read-locked time", 0);
918 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 9,
919 "Read-locked count", 0);
920 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 10,
921 "Read-blocked time", 0);
922 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 11,
923 "Read-blocked count", 0);
926 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONSTRING, 0,
931 /* set lock watching stuff */
932 void osi_SetWatchProc(long ms, osi_watchProc_t *procp, void *rockp)
934 osi_statWatchProcp = procp;
935 osi_statWatchRockp = rockp;
936 osi_statWatchMS = ms;