2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 /* Copyright (C) 1994 Cazamar Systems, Inc. */
12 #include <afs/param.h>
22 * 2. osi_activeInfoAllocCS.
23 * 3. individual log critical sections (since we call log pkg).
25 * There are no cases today where both 1 and 2 are locked simultaneously.
28 /* el cheapo watch system */
29 osi_watchProc_t *osi_statWatchProcp; /* proc to call on too-long held locks */
30 void *osi_statWatchRockp; /* with this rock */
31 unsigned long osi_statWatchMS; /* after a lock is held this many MS */
33 /* type index of the statistics gathering lock package */
36 /* log to which to log lock events */
37 osi_log_t *osi_statLogp;
39 /* queue of all rwlock auxiliary structures */
40 osi_queue_t *osi_allRWLocks;
42 /* queue of all mutex auxiliary structures */
43 osi_queue_t *osi_allMutexes;
45 /* free list and mutex for active info structures */
46 osi_activeInfo_t *osi_activeInfoFreeListp;
47 CRITICAL_SECTION osi_activeInfoAllocCS;
49 /* atomicity-providing critical sections */
50 CRITICAL_SECTION osi_statAtomicCS[OSI_MUTEXHASHSIZE];
52 /* lock protecting ref count on locks, osi_allMutexes and osi_RWLocks, and
53 * file descriptor contents
55 CRITICAL_SECTION osi_statFDCS;
57 void osi_SetStatLog(osi_log_t *logp)
59 /* nicer if ref counted */
63 static void lock_ObtainWriteStat(osi_rwlock_t *lockp)
65 osi_rwlockStat_t *realp;
67 CRITICAL_SECTION *csp;
69 realp = (osi_rwlockStat_t *)lockp->d.privateDatap;
72 csp = &osi_statAtomicCS[lockp->atomicIndex];
73 EnterCriticalSection(csp);
75 /* here we have the fast lock, so see if we can obtain the real lock */
76 if ((lockp->waiters > 0) || (lockp->flags & OSI_LOCKFLAG_EXCL)
77 || (lockp->readers > 0)) {
79 if (!ap) ap = osi_QueueActiveInfo(&realp->qi,
80 OSI_ACTIVEFLAGS_WRITER | OSI_ACTIVEFLAGS_WAITER);
81 osi_TWait(&realp->turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
83 osi_assert((lockp->flags & OSI_LOCKFLAG_EXCL) && lockp->readers == 0);
86 /* if we're here, all clear to set the lock */
87 lockp->flags |= OSI_LOCKFLAG_EXCL;
90 /* if we have ap set, we have some timer info about the last sleep operation
91 * that we should merge in under the spin lock.
94 /* remove from queue and turn time to incremental time */
95 osi_RemoveActiveInfo(&realp->qi, ap);
97 /* add in increment to statistics */
98 realp->writeBlockedCount++;
99 realp->writeBlockedTime = LargeIntegerAdd(realp->writeBlockedTime,
101 osi_FreeActiveInfo(ap);
104 osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_WRITER);
105 LeaveCriticalSection(csp);
108 static void lock_ObtainReadStat(osi_rwlock_t *lockp)
110 osi_activeInfo_t *ap;
111 osi_rwlockStat_t *realp;
112 CRITICAL_SECTION *csp;
115 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
117 /* otherwise we're the fast base type */
118 csp = &osi_statAtomicCS[lockp->atomicIndex];
119 EnterCriticalSection(csp);
121 /* here we have the fast lock, so see if we can obtain the real lock */
122 if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
124 if (!ap) ap = osi_QueueActiveInfo(&realp->qi,
125 OSI_ACTIVEFLAGS_WAITER | OSI_ACTIVEFLAGS_READER);
126 osi_TWait(&realp->turn, OSI_SLEEPINFO_W4READ, &lockp->readers, csp);
128 osi_assert(!(lockp->flags & OSI_LOCKFLAG_EXCL) && lockp->readers > 0);
131 /* if we're here, all clear to set the lock */
136 /* have statistics to merge in */
137 osi_RemoveActiveInfo(&realp->qi, ap);
138 realp->readBlockedCount++;
139 realp->readBlockedTime = LargeIntegerAdd(realp->readBlockedTime, ap->startTime);
140 osi_FreeActiveInfo(ap);
143 osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_READER);
144 LeaveCriticalSection(csp);
147 static void lock_ReleaseReadStat(osi_rwlock_t *lockp)
149 osi_activeInfo_t *ap;
150 osi_rwlockStat_t *realp;
151 CRITICAL_SECTION *csp;
153 realp = (osi_rwlockStat_t *)lockp->d.privateDatap;
155 csp = &osi_statAtomicCS[lockp->atomicIndex];
156 EnterCriticalSection(csp);
158 osi_assert(lockp->readers > 0);
159 ap = osi_FindActiveInfo(&realp->qi);
160 osi_assert(ap != NULL);
161 osi_RemoveActiveInfo(&realp->qi, ap);
162 realp->readLockedCount++;
163 realp->readLockedTime = LargeIntegerAdd(realp->readLockedTime, ap->startTime);
164 osi_FreeActiveInfo(ap);
166 if (--lockp->readers == 0 && !osi_TEmpty(&realp->turn)) {
167 osi_TSignalForMLs(&realp->turn, 0, csp);
170 /* and finally release the big lock */
171 LeaveCriticalSection(csp);
175 static void lock_ConvertWToRStat(osi_rwlock_t *lockp)
177 osi_activeInfo_t *ap;
178 osi_rwlockStat_t *realp;
179 CRITICAL_SECTION *csp;
181 realp = (osi_rwlockStat_t *)lockp->d.privateDatap;
183 /* otherwise we're the fast base type */
184 csp = &osi_statAtomicCS[lockp->atomicIndex];
185 EnterCriticalSection(csp);
187 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
188 ap = osi_FindActiveInfo(&realp->qi);
189 osi_assert(ap !=NULL);
190 osi_RemoveActiveInfo(&realp->qi, ap);
191 realp->writeLockedCount++;
192 realp->writeLockedTime = LargeIntegerAdd(realp->writeLockedTime, ap->startTime);
193 osi_FreeActiveInfo(ap);
195 /* and obtain the read lock */
197 osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_READER);
199 lockp->flags &= ~OSI_LOCKFLAG_EXCL;
200 if (!osi_TEmpty(&realp->turn)) {
201 osi_TSignalForMLs(&realp->turn, 1, csp);
204 /* and finally release the big lock */
205 LeaveCriticalSection(csp);
209 static void lock_ReleaseWriteStat(osi_rwlock_t *lockp)
211 osi_activeInfo_t *ap;
212 osi_rwlockStat_t *realp;
213 CRITICAL_SECTION *csp;
215 realp = (osi_rwlockStat_t *)lockp->d.privateDatap;
217 /* otherwise we're the fast base type */
218 csp = &osi_statAtomicCS[lockp->atomicIndex];
219 EnterCriticalSection(csp);
221 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
222 ap = osi_FindActiveInfo(&realp->qi);
223 osi_assert(ap !=NULL);
224 osi_RemoveActiveInfo(&realp->qi, ap);
225 realp->writeLockedCount++;
226 realp->writeLockedTime = LargeIntegerAdd(realp->writeLockedTime, ap->startTime);
227 osi_FreeActiveInfo(ap);
229 lockp->flags &= ~OSI_LOCKFLAG_EXCL;
230 if (!osi_TEmpty(&realp->turn)) {
231 osi_TSignalForMLs(&realp->turn, 0, csp);
234 /* and finally release the big lock */
235 LeaveCriticalSection(csp);
239 static void lock_ObtainMutexStat(struct osi_mutex *lockp)
241 osi_activeInfo_t *ap;
242 osi_mutexStat_t *realp;
243 CRITICAL_SECTION *csp;
246 realp = (osi_mutexStat_t *) lockp->d.privateDatap;
248 csp = &osi_statAtomicCS[lockp->atomicIndex];
249 EnterCriticalSection(csp);
251 /* here we have the fast lock, so see if we can obtain the real lock */
252 if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
254 ap = osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_WAITER);
255 osi_TWait(&realp->turn, OSI_SLEEPINFO_W4WRITE, &lockp->flags, csp);
257 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
260 /* if we're here, all clear to set the lock */
261 lockp->flags |= OSI_LOCKFLAG_EXCL;
264 /* release the blocking ap */
266 osi_RemoveActiveInfo(&realp->qi, ap);
267 realp->blockedCount++;
268 realp->blockedTime = LargeIntegerAdd(realp->blockedTime, ap->startTime);
269 osi_FreeActiveInfo(ap);
272 /* start tracking this call */
273 osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_WRITER);
275 LeaveCriticalSection(csp);
278 static void lock_ReleaseMutexStat(struct osi_mutex *lockp)
280 osi_activeInfo_t *ap;
281 osi_mutexStat_t *realp;
282 CRITICAL_SECTION *csp;
284 realp = (osi_mutexStat_t *)lockp->d.privateDatap;
286 csp = &osi_statAtomicCS[lockp->atomicIndex];
287 EnterCriticalSection(csp);
289 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
291 ap = osi_FindActiveInfo(&realp->qi);
292 osi_assert(ap != NULL);
293 osi_RemoveActiveInfo(&realp->qi, ap);
294 realp->lockedCount++;
295 realp->lockedTime = LargeIntegerAdd(realp->lockedTime, ap->startTime);
296 osi_FreeActiveInfo(ap);
298 lockp->flags &= ~OSI_LOCKFLAG_EXCL;
299 if (!osi_TEmpty(&realp->turn)) {
300 osi_TSignalForMLs(&realp->turn, 0, csp);
303 /* and finally release the big lock */
304 LeaveCriticalSection(csp);
308 static int lock_TryReadStat(struct osi_rwlock *lockp)
311 osi_rwlockStat_t *realp;
312 CRITICAL_SECTION *csp;
314 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
316 /* otherwise we're the fast base type */
317 csp = &osi_statAtomicCS[lockp->atomicIndex];
318 EnterCriticalSection(csp);
320 /* here we have the fast lock, so see if we can obtain the real lock */
321 if (lockp->waiters > 0 || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
325 /* if we're here, all clear to set the lock */
330 /* start tracking lock holding stats */
331 if (i) osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_READER);
333 LeaveCriticalSection(csp);
339 static int lock_TryWriteStat(struct osi_rwlock *lockp)
342 osi_rwlockStat_t *realp;
343 CRITICAL_SECTION *csp;
345 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
347 /* otherwise we're the fast base type */
348 csp = &osi_statAtomicCS[lockp->atomicIndex];
349 EnterCriticalSection(csp);
351 /* here we have the fast lock, so see if we can obtain the real lock */
352 if ((lockp->waiters > 0) || (lockp->flags & OSI_LOCKFLAG_EXCL)
353 || (lockp->readers > 0)) {
357 /* if we're here, all clear to set the lock */
358 lockp->flags |= OSI_LOCKFLAG_EXCL;
362 /* start tracking lock holding stats */
363 if (i) osi_QueueActiveInfo(&realp->qi, OSI_ACTIVEFLAGS_WRITER);
365 LeaveCriticalSection(csp);
371 static int lock_GetRWLockStateStat(struct osi_rwlock *lockp)
374 osi_rwlockStat_t *realp;
375 CRITICAL_SECTION *csp;
377 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
379 /* otherwise we're the fast base type */
380 csp = &osi_statAtomicCS[lockp->atomicIndex];
381 EnterCriticalSection(csp);
384 if (lockp->flags & OSI_LOCKFLAG_EXCL) {
385 i |= OSI_RWLOCK_WRITEHELD;
387 if (lockp->readers) {
388 i |= OSI_RWLOCK_READHELD;
391 LeaveCriticalSection(csp);
397 static int lock_GetMutexStateStat(struct osi_mutex *lockp) {
399 osi_mutexStat_t *realp;
400 CRITICAL_SECTION *csp;
402 realp = (osi_mutexStat_t *) lockp->d.privateDatap;
404 /* otherwise we're the fast base type */
405 csp = &osi_statAtomicCS[lockp->atomicIndex];
406 EnterCriticalSection(csp);
408 /* here we have the fast lock, so see if we can obtain the real lock */
410 if (lockp->flags & OSI_LOCKFLAG_EXCL) {
414 LeaveCriticalSection(csp);
419 static int lock_TryMutexStat(struct osi_mutex *lockp) {
421 osi_mutexStat_t *realp;
422 CRITICAL_SECTION *csp;
424 realp = (osi_mutexStat_t *) lockp->d.privateDatap;
426 /* otherwise we're the fast base type */
427 csp = &osi_statAtomicCS[lockp->atomicIndex];
428 EnterCriticalSection(csp);
430 /* here we have the fast lock, so see if we can obtain the real lock */
431 if ((lockp->waiters > 0) || (lockp->flags & OSI_LOCKFLAG_EXCL)) {
435 /* if we're here, all clear to set the lock */
436 lockp->flags |= OSI_LOCKFLAG_EXCL;
440 if (i) osi_QueueActiveInfo(&realp->qi, 0);
442 LeaveCriticalSection(csp);
447 static void osi_SleepRStat(long sleepVal, struct osi_rwlock *lockp)
449 osi_rwlockStat_t *realp;
450 osi_activeInfo_t *ap;
451 CRITICAL_SECTION *csp;
453 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
455 /* otherwise we're the fast base type */
456 csp = &osi_statAtomicCS[lockp->atomicIndex];
457 EnterCriticalSection(csp);
459 osi_assert(lockp->readers > 0);
461 if (--lockp->readers == 0 && !osi_TEmpty(&realp->turn)) {
462 osi_TSignalForMLs(&realp->turn, 0, NULL);
465 /* now merge in lock hold stats */
466 ap = osi_FindActiveInfo(&realp->qi);
467 osi_assert(ap != NULL);
468 osi_RemoveActiveInfo(&realp->qi, ap);
469 realp->writeLockedCount++;
470 realp->writeLockedTime = LargeIntegerAdd(realp->writeLockedTime, ap->startTime);
471 osi_FreeActiveInfo(ap);
473 /* now call into scheduler to sleep atomically with releasing spin lock */
474 osi_SleepSpin(sleepVal, csp);
477 static void osi_SleepWStat(long sleepVal, struct osi_rwlock *lockp)
479 osi_activeInfo_t *ap;
480 osi_rwlockStat_t *realp;
481 CRITICAL_SECTION *csp;
483 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
485 /* otherwise we're the fast base type */
486 csp = &osi_statAtomicCS[lockp->atomicIndex];
487 EnterCriticalSection(csp);
489 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
491 lockp->flags &= ~OSI_LOCKFLAG_EXCL;
492 if (!osi_TEmpty(&realp->turn)) {
493 osi_TSignalForMLs(&realp->turn, 0, NULL);
496 /* now merge in lock hold stats */
497 ap = osi_FindActiveInfo(&realp->qi);
498 osi_assert(ap != NULL);
499 osi_RemoveActiveInfo(&realp->qi, ap);
500 realp->readLockedCount++;
501 realp->readLockedTime = LargeIntegerAdd(realp->readLockedTime, ap->startTime);
502 osi_FreeActiveInfo(ap);
504 /* and finally release the big lock */
505 osi_SleepSpin(sleepVal, csp);
508 static void osi_SleepMStat(long sleepVal, struct osi_mutex *lockp)
510 osi_mutexStat_t *realp;
511 osi_activeInfo_t *ap;
512 CRITICAL_SECTION *csp;
514 realp = (osi_mutexStat_t *) lockp->d.privateDatap;
516 /* otherwise we're the fast base type */
517 csp = &osi_statAtomicCS[lockp->atomicIndex];
518 EnterCriticalSection(csp);
520 osi_assert(lockp->flags & OSI_LOCKFLAG_EXCL);
522 lockp->flags &= ~OSI_LOCKFLAG_EXCL;
523 if (!osi_TEmpty(&realp->turn)) {
524 osi_TSignalForMLs(&realp->turn, 0, NULL);
527 /* now merge in lock hold stats */
528 ap = osi_FindActiveInfo(&realp->qi);
529 osi_assert(ap != NULL);
530 osi_RemoveActiveInfo(&realp->qi, ap);
531 realp->lockedCount++;
532 realp->lockedTime = LargeIntegerAdd(realp->lockedTime, ap->startTime);
533 osi_FreeActiveInfo(ap);
535 /* and finally release the big lock */
536 osi_SleepSpin(sleepVal, csp);
539 /* this is a function that release a ref count, but we give it a different
540 * name than release to avoid confusion with all of the releases here.
541 * Must be called holding the osi_statFDCS lock.
543 static void lock_DecrMutexStat(osi_mutexStat_t *mp)
545 if (--mp->refCount <= 0 && (mp->states & OSI_STATL_DELETED)) {
546 osi_QRemove(&osi_allMutexes, &mp->q);
551 /* Must be called holding the osi_statFDCS lock. */
552 static void lock_DecrRWLockStat(osi_rwlockStat_t *rwp)
554 if (--rwp->refCount <= 0 && (rwp->states & OSI_STATL_DELETED)) {
555 osi_QRemove(&osi_allRWLocks, &rwp->q);
560 static void lock_FinalizeMutexStat(osi_mutex_t *lockp)
562 osi_mutexStat_t *realp;
564 /* pull out the real pointer */
565 realp = (osi_mutexStat_t *) lockp->d.privateDatap;
567 /* remove from the queues, and free */
568 EnterCriticalSection(&osi_statFDCS);
569 if (realp->refCount <= 0) {
570 osi_QRemove(&osi_allMutexes, &realp->q);
571 free((void *) realp);
573 else realp->states |= OSI_STATL_DELETED;
574 LeaveCriticalSection(&osi_statFDCS);
577 static void lock_FinalizeRWLockStat(osi_rwlock_t *lockp)
579 osi_rwlockStat_t *realp;
581 /* pull out the real pointer */
582 realp = (osi_rwlockStat_t *) lockp->d.privateDatap;
584 /* remove from the queues, and free */
585 EnterCriticalSection(&osi_statFDCS);
586 if (realp->refCount <= 0) {
587 osi_QRemove(&osi_allRWLocks, &realp->q);
588 free((void *) realp);
590 else realp->states |= OSI_STATL_DELETED;
591 LeaveCriticalSection(&osi_statFDCS);
594 void lock_InitializeRWLockStat(osi_rwlock_t *lockp, char *namep)
596 osi_rwlockStat_t *realp;
598 realp = (osi_rwlockStat_t *) malloc(sizeof(*realp));
599 lockp->d.privateDatap = (void *) realp;
600 lockp->type = osi_statType;
603 lockp->atomicIndex = osi_MUTEXHASH(lockp);
604 memset(realp, 0, sizeof(*realp));
605 osi_TInit(&realp->turn);
606 realp->qi.namep = namep;
607 realp->qi.backp = lockp;
608 EnterCriticalSection(&osi_statFDCS);
609 osi_QAdd(&osi_allRWLocks, &realp->q);
610 LeaveCriticalSection(&osi_statFDCS);
613 void lock_InitializeMutexStat(osi_mutex_t *lockp, char *namep)
615 osi_mutexStat_t *realp;
617 realp = (osi_mutexStat_t *) malloc(sizeof(*realp));
618 lockp->d.privateDatap = (void *) realp;
619 lockp->type = osi_statType;
621 lockp->atomicIndex = osi_MUTEXHASH(lockp);
622 memset(realp, 0, sizeof(*realp));
623 osi_TInit(&realp->turn);
624 realp->qi.namep = namep;
625 realp->qi.backp = lockp;
626 EnterCriticalSection(&osi_statFDCS);
627 osi_QAdd(&osi_allMutexes, &realp->q);
628 LeaveCriticalSection(&osi_statFDCS);
631 static void osi_FreeActiveInfo(osi_activeInfo_t *ap)
633 EnterCriticalSection(&osi_activeInfoAllocCS);
634 ap->q.nextp = (osi_queue_t *) osi_activeInfoFreeListp;
635 osi_activeInfoFreeListp = ap;
636 LeaveCriticalSection(&osi_activeInfoAllocCS);
639 static osi_activeInfo_t *osi_AllocActiveInfo()
641 osi_activeInfo_t *ap;
643 EnterCriticalSection(&osi_activeInfoAllocCS);
644 if (!(ap = osi_activeInfoFreeListp)) {
645 ap = (osi_activeInfo_t *) malloc(sizeof(osi_activeInfo_t));
648 osi_activeInfoFreeListp = (osi_activeInfo_t *) ap->q.nextp;
650 LeaveCriticalSection(&osi_activeInfoAllocCS);
655 static osi_activeInfo_t *osi_QueueActiveInfo(osi_qiStat_t *qp, int flags)
657 osi_activeInfo_t *ap;
658 osi_queue_t **qpp = (osi_queue_t **) &qp->activeListp;
661 ap = osi_AllocActiveInfo();
663 ap->startTime.LowPart = GetCurrentTime();
664 ap->startTime.HighPart = 0;
665 ap->tid = GetCurrentThreadId();
666 osi_QAdd(qpp, &ap->q);
667 if (osi_statLogp && (flags & OSI_ACTIVEFLAGS_WAITER)) {
668 if (flags & OSI_ACTIVEFLAGS_READER)
670 else if (flags & OSI_ACTIVEFLAGS_WRITER)
671 whatp = "write lock";
672 else whatp = "mutex";
673 osi_Log2(osi_statLogp, "Blocking on %s on %s", whatp, qp->namep);
678 static void osi_RemoveActiveInfo(osi_qiStat_t *qp, osi_activeInfo_t *ap)
681 osi_queue_t **qpp = (osi_queue_t **) &qp->activeListp;
685 now = GetCurrentTime();
686 osi_QRemove(qpp, &ap->q);
688 ap->startTime.LowPart = now - ap->startTime.LowPart;
690 if (osi_statLogp && (flags & OSI_ACTIVEFLAGS_WAITER)) {
691 if (flags & OSI_ACTIVEFLAGS_READER)
693 else if (flags & OSI_ACTIVEFLAGS_WRITER)
694 whatp = "write lock";
695 else whatp = "mutex";
696 osi_Log2(osi_statLogp, "Finally obtained %s on %s", whatp, qp->namep);
699 /* releasing a lock or mutex */
700 if (osi_statWatchProcp && ap->startTime.LowPart > osi_statWatchMS) {
701 (*osi_statWatchProcp)(osi_statWatchRockp, ap->startTime.LowPart,
707 static osi_activeInfo_t *osi_FindActiveInfo(osi_qiStat_t *qp)
710 osi_activeInfo_t *ap;
712 osi_queue_t **qpp = (osi_queue_t **) &qp->activeListp;
715 tid = GetCurrentThreadId();
717 for(tqp = *qpp; tqp; tqp = tqp->nextp) {
718 ap = (osi_activeInfo_t *) tqp;
719 if (ap->tid == tid) break;
725 static osi_lockOps_t osi_statOps = {
727 lock_ObtainWriteStat,
728 lock_ReleaseReadStat,
729 lock_ReleaseWriteStat,
730 lock_ObtainMutexStat,
731 lock_ReleaseMutexStat,
738 lock_InitializeMutexStat,
739 lock_InitializeRWLockStat,
740 lock_FinalizeMutexStat,
741 lock_FinalizeRWLockStat,
742 lock_ConvertWToRStat,
743 lock_GetRWLockStateStat,
744 lock_GetMutexStateStat
747 long osi_StatFDCreate(osi_fdType_t *typep, osi_fd_t **fdpp)
751 osi_rwlockStat_t *rwp;
753 fdp = (osi_statFD_t *) malloc(sizeof(*fdp));
754 EnterCriticalSection(&osi_statFDCS);
755 if (osi_allMutexes) {
756 fdp->curp = osi_allMutexes;
757 mp = (osi_mutexStat_t *) fdp->curp;
761 else if (osi_allRWLocks) {
762 fdp->curp = osi_allRWLocks;
763 rwp = (osi_rwlockStat_t *) fdp->curp;
767 else fdp->curp = NULL;
768 LeaveCriticalSection(&osi_statFDCS);
775 long osi_StatFDGetInfo(osi_fd_t *ifdp, osi_remGetInfoParms_t *parmsp)
779 osi_rwlockStat_t *rwp;
781 osi_mutex_t *backMutexp;
782 osi_rwlock_t *backRWLockp;
784 /* initialize out structure */
788 fdp = (osi_statFD_t *) ifdp;
791 /* we're done if curp is null */
792 if (qp == NULL) return OSI_DBRPC_EOF;
794 /* copy out statistics */
795 if (fdp->which == 0) {
796 /* this is a mutex */
797 mp = (osi_mutexStat_t *) qp;
799 memset((void *) parmsp, 0, sizeof(*parmsp));
800 backMutexp = mp->qi.backp;
801 parmsp->idata[0] = (long) backMutexp;
802 parmsp->idata[1] = (backMutexp->flags & OSI_LOCKFLAG_EXCL)? 1 : 0;
803 /* reader count [2] is 0 */
804 parmsp->idata[3] = (backMutexp->waiters > 0)? 1 : 0;
805 parmsp->idata[4] = mp->lockedTime.LowPart;
806 parmsp->idata[5] = mp->lockedCount;
807 parmsp->idata[6] = mp->blockedTime.LowPart;
808 parmsp->idata[7] = mp->blockedCount;
809 strcpy(parmsp->sdata[0], mp->qi.namep);
813 else if (fdp->which == 1) {
815 rwp = (osi_rwlockStat_t *) qp;
817 memset((void *) parmsp, 0, sizeof(*parmsp));
818 backRWLockp = rwp->qi.backp;
819 parmsp->idata[0] = (long) backRWLockp;
820 parmsp->idata[1] = (backRWLockp->flags & OSI_LOCKFLAG_EXCL)? 1 : 0;
821 parmsp->idata[2] = backRWLockp->readers;
822 parmsp->idata[3] = (backRWLockp->waiters > 0)? 1 : 0;
823 parmsp->idata[4] = rwp->writeLockedTime.LowPart;
824 parmsp->idata[5] = rwp->writeLockedCount;
825 parmsp->idata[6] = rwp->writeBlockedTime.LowPart;
826 parmsp->idata[7] = rwp->writeBlockedCount;
827 parmsp->idata[8] = rwp->readLockedTime.LowPart;
828 parmsp->idata[9] = rwp->readLockedCount;
829 parmsp->idata[10] = rwp->readBlockedTime.LowPart;
830 parmsp->idata[11] = rwp->readBlockedCount;
831 strcpy(parmsp->sdata[0], rwp->qi.namep);
836 /* advance to next position */
837 EnterCriticalSection(&osi_statFDCS);
839 if (fdp->which == 0) {
840 mp = (osi_mutexStat_t *) qp;
841 lock_DecrMutexStat(mp);
843 else if (fdp->which == 1) {
844 rwp = (osi_rwlockStat_t *) qp;
845 lock_DecrRWLockStat(rwp);
849 if (qp == NULL && fdp->which == 0) {
851 if (osi_allRWLocks) qp = osi_allRWLocks;
856 if (fdp->which == 0) {
857 mp = (osi_mutexStat_t *) qp;
860 else if (fdp->which == 1) {
861 rwp = (osi_rwlockStat_t *) qp;
865 LeaveCriticalSection(&osi_statFDCS);
870 long osi_StatFDClose(osi_fd_t *ifdp)
876 osi_fdOps_t osi_statFDOps = {
887 /* initialize the stat package */
888 InitializeCriticalSection(&osi_activeInfoAllocCS);
889 InitializeCriticalSection(&osi_statFDCS);
891 for(i=0; i<OSI_MUTEXHASHSIZE; i++)
892 InitializeCriticalSection(&osi_statAtomicCS[i]);
894 /* add stat ops to dynamic registry */
895 osi_LockTypeAdd(&osi_statOps, "stat", &osi_statType);
897 /* add debugging info and file descriptor support */
898 typep = osi_RegisterFDType("lock", &osi_statFDOps, NULL);
900 /* add formatting info */
901 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 0,
902 "Lock address", OSI_DBRPC_HEX);
903 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 1,
905 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 2,
907 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 3,
909 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 4,
910 "Write-locked time", 0);
911 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 5,
912 "Write-locked count", 0);
913 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 6,
914 "Write-blocked time", 0);
915 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 7,
916 "Write-blocked count", 0);
917 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 8,
918 "Read-locked time", 0);
919 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 9,
920 "Read-locked count", 0);
921 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 10,
922 "Read-blocked time", 0);
923 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 11,
924 "Read-blocked count", 0);
927 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONSTRING, 0,
932 /* set lock watching stuff */
933 void osi_SetWatchProc(long ms, osi_watchProc_t *procp, void *rockp)
935 osi_statWatchProcp = procp;
936 osi_statWatchRockp = rockp;
937 osi_statWatchMS = ms;