123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /*
- * nssilock.c - NSS lock instrumentation wrapper functions
- *
- * NOTE - These are not public interfaces
- *
- * Implementation Notes:
- * I've tried to make the instrumentation relatively non-intrusive.
- * To do this, I have used a single PR_LOG() call in each
- * instrumented function. There's room for improvement.
- *
- *
- */
- #include "prinit.h"
- #include "prerror.h"
- #include "prlock.h"
- #include "prmem.h"
- #include "prenv.h"
- #include "prcvar.h"
- #include "prio.h"
- #if defined(NEED_NSS_ILOCK)
- #include "prlog.h"
- #include "nssilock.h"
- /*
- ** Declare the instrumented PZLock
- */
- struct pzlock_s {
- PRLock *lock; /* the PZLock to be instrumented */
- PRIntervalTime time; /* timestamp when the lock was aquired */
- nssILockType ltype;
- };
- /*
- ** Declare the instrumented PZMonitor
- */
- struct pzmonitor_s {
- PRMonitor *mon; /* the PZMonitor to be instrumented */
- PRIntervalTime time; /* timestamp when the monitor was aquired */
- nssILockType ltype;
- };
- /*
- ** Declare the instrumented PZCondVar
- */
- struct pzcondvar_s {
- PRCondVar *cvar; /* the PZCondVar to be instrumented */
- nssILockType ltype;
- };
- /*
- ** Define a CallOnce type to ensure serialized self-initialization
- */
- static PRCallOnceType coNssILock; /* CallOnce type */
- static PRIntn nssILockInitialized; /* initialization done when 1 */
- static PRLogModuleInfo *nssILog; /* Log instrumentation to this handle */
- #define NUM_TT_ENTRIES 6000000
- static PRInt32 traceIndex = -1; /* index into trace table */
- static struct pzTrace_s *tt; /* pointer to trace table */
- static PRInt32 ttBufSize = (NUM_TT_ENTRIES * sizeof(struct pzTrace_s));
- static PRCondVar *ttCVar;
- static PRLock *ttLock;
- static PRFileDesc *ttfd; /* trace table file */
- /*
- ** Vtrace() -- Trace events, write events to external media
- **
- ** Vtrace() records traced events in an in-memory trace table
- ** when the trace table fills, Vtrace writes the entire table
- ** to a file.
- **
- ** data can be lost!
- **
- */
- static void
- Vtrace(
- nssILockOp op,
- nssILockType ltype,
- PRIntervalTime callTime,
- PRIntervalTime heldTime,
- void *lock,
- PRIntn line,
- char *file)
- {
- PRInt32 idx;
- struct pzTrace_s *tp;
- RetryTrace:
- idx = PR_ATOMIC_INCREMENT(&traceIndex);
- while (NUM_TT_ENTRIES <= idx || op == FlushTT) {
- if (NUM_TT_ENTRIES == idx || op == FlushTT) {
- int writeSize = idx * sizeof(struct pzTrace_s);
- PR_Lock(ttLock);
- PR_Write(ttfd, tt, writeSize);
- traceIndex = -1;
- PR_NotifyAllCondVar(ttCVar);
- PR_Unlock(ttLock);
- goto RetryTrace;
- } else {
- PR_Lock(ttLock);
- while (NUM_TT_ENTRIES < idx)
- PR_WaitCondVar(ttCVar, PR_INTERVAL_NO_WAIT);
- PR_Unlock(ttLock);
- goto RetryTrace;
- }
- } /* end while() */
- /* create the trace entry */
- tp = tt + idx;
- tp->threadID = PR_GetThreadID(PR_GetCurrentThread());
- tp->op = op;
- tp->ltype = ltype;
- tp->callTime = callTime;
- tp->heldTime = heldTime;
- tp->lock = lock;
- tp->line = line;
- strcpy(tp->file, file);
- return;
- } /* --- end Vtrace() --- */
- /*
- ** pz_TraceFlush() -- Force trace table write to file
- **
- */
- extern void
- pz_TraceFlush(void)
- {
- Vtrace(FlushTT, nssILockSelfServ, 0, 0, NULL, 0, "");
- return;
- } /* --- end pz_TraceFlush() --- */
- /*
- ** nssILockInit() -- Initialization for nssilock
- **
- ** This function is called from the CallOnce mechanism.
- */
- static PRStatus
- nssILockInit(void)
- {
- int i;
- nssILockInitialized = 1;
- /* new log module */
- nssILog = PR_NewLogModule("nssilock");
- if (NULL == nssILog) {
- return (PR_FAILURE);
- }
- tt = PR_Calloc(NUM_TT_ENTRIES, sizeof(struct pzTrace_s));
- if (NULL == tt) {
- fprintf(stderr, "nssilock: can't allocate trace table\n");
- exit(1);
- }
- ttfd = PR_Open("xxxTTLog", PR_CREATE_FILE | PR_WRONLY, 0666);
- if (NULL == ttfd) {
- fprintf(stderr, "Oh Drat! Can't open 'xxxTTLog'\n");
- exit(1);
- }
- ttLock = PR_NewLock();
- ttCVar = PR_NewCondVar(ttLock);
- return (PR_SUCCESS);
- } /* --- end nssILockInit() --- */
- extern PZLock *
- pz_NewLock(
- nssILockType ltype,
- char *file,
- PRIntn line)
- {
- PRStatus rc;
- PZLock *lock;
- /* Self Initialize the nssILock feature */
- if (!nssILockInitialized) {
- rc = PR_CallOnce(&coNssILock, nssILockInit);
- if (PR_FAILURE == rc) {
- PR_SetError(PR_UNKNOWN_ERROR, 0);
- return (NULL);
- }
- }
- lock = PR_NEWZAP(PZLock);
- if (NULL != lock) {
- lock->ltype = ltype;
- lock->lock = PR_NewLock();
- if (NULL == lock->lock) {
- PR_DELETE(lock);
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- }
- } else {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- }
- Vtrace(NewLock, ltype, 0, 0, lock, line, file);
- return (lock);
- } /* --- end pz_NewLock() --- */
- extern void
- pz_Lock(
- PZLock *lock,
- char *file,
- PRIntn line)
- {
- PRIntervalTime callTime;
- callTime = PR_IntervalNow();
- PR_Lock(lock->lock);
- lock->time = PR_IntervalNow();
- callTime = lock->time - callTime;
- Vtrace(Lock, lock->ltype, callTime, 0, lock, line, file);
- return;
- } /* --- end pz_Lock() --- */
- extern PRStatus
- pz_Unlock(
- PZLock *lock,
- char *file,
- PRIntn line)
- {
- PRStatus rc;
- PRIntervalTime callTime, now, heldTime;
- callTime = PR_IntervalNow();
- rc = PR_Unlock(lock->lock);
- now = PR_IntervalNow();
- callTime = now - callTime;
- heldTime = now - lock->time;
- Vtrace(Unlock, lock->ltype, callTime, heldTime, lock, line, file);
- return (rc);
- } /* --- end pz_Unlock() --- */
- extern void
- pz_DestroyLock(
- PZLock *lock,
- char *file,
- PRIntn line)
- {
- Vtrace(DestroyLock, lock->ltype, 0, 0, lock, line, file);
- PR_DestroyLock(lock->lock);
- PR_DELETE(lock);
- return;
- } /* --- end pz_DestroyLock() --- */
- extern PZCondVar *
- pz_NewCondVar(
- PZLock *lock,
- char *file,
- PRIntn line)
- {
- PZCondVar *cvar;
- cvar = PR_NEWZAP(PZCondVar);
- if (NULL == cvar) {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- } else {
- cvar->ltype = lock->ltype;
- cvar->cvar = PR_NewCondVar(lock->lock);
- if (NULL == cvar->cvar) {
- PR_DELETE(cvar);
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- }
- }
- Vtrace(NewCondVar, lock->ltype, 0, 0, cvar, line, file);
- return (cvar);
- } /* --- end pz_NewCondVar() --- */
- extern void
- pz_DestroyCondVar(
- PZCondVar *cvar,
- char *file,
- PRIntn line)
- {
- Vtrace(DestroyCondVar, cvar->ltype, 0, 0, cvar, line, file);
- PR_DestroyCondVar(cvar->cvar);
- PR_DELETE(cvar);
- } /* --- end pz_DestroyCondVar() --- */
- extern PRStatus
- pz_WaitCondVar(
- PZCondVar *cvar,
- PRIntervalTime timeout,
- char *file,
- PRIntn line)
- {
- PRStatus rc;
- PRIntervalTime callTime;
- callTime = PR_IntervalNow();
- rc = PR_WaitCondVar(cvar->cvar, timeout);
- callTime = PR_IntervalNow() - callTime;
- Vtrace(WaitCondVar, cvar->ltype, callTime, 0, cvar, line, file);
- return (rc);
- } /* --- end pz_WaitCondVar() --- */
- extern PRStatus
- pz_NotifyCondVar(
- PZCondVar *cvar,
- char *file,
- PRIntn line)
- {
- PRStatus rc;
- rc = PR_NotifyCondVar(cvar->cvar);
- Vtrace(NotifyCondVar, cvar->ltype, 0, 0, cvar, line, file);
- return (rc);
- } /* --- end pz_NotifyCondVar() --- */
- extern PRStatus
- pz_NotifyAllCondVar(
- PZCondVar *cvar,
- char *file,
- PRIntn line)
- {
- PRStatus rc;
- rc = PR_NotifyAllCondVar(cvar->cvar);
- Vtrace(NotifyAllCondVar, cvar->ltype, 0, 0, cvar, line, file);
- return (rc);
- } /* --- end pz_NotifyAllCondVar() --- */
- extern PZMonitor *
- pz_NewMonitor(
- nssILockType ltype,
- char *file,
- PRIntn line)
- {
- PRStatus rc;
- PZMonitor *mon;
- /* Self Initialize the nssILock feature */
- if (!nssILockInitialized) {
- rc = PR_CallOnce(&coNssILock, nssILockInit);
- if (PR_FAILURE == rc) {
- PR_SetError(PR_UNKNOWN_ERROR, 0);
- return (NULL);
- }
- }
- mon = PR_NEWZAP(PZMonitor);
- if (NULL != mon) {
- mon->ltype = ltype;
- mon->mon = PR_NewMonitor();
- if (NULL == mon->mon) {
- PR_DELETE(mon);
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- }
- } else {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- }
- Vtrace(NewMonitor, ltype, 0, 0, mon, line, file);
- return (mon);
- } /* --- end pz_NewMonitor() --- */
- extern void
- pz_DestroyMonitor(
- PZMonitor *mon,
- char *file,
- PRIntn line)
- {
- Vtrace(DestroyMonitor, mon->ltype, 0, 0, mon, line, file);
- PR_DestroyMonitor(mon->mon);
- PR_DELETE(mon);
- return;
- } /* --- end pz_DestroyMonitor() --- */
- extern void
- pz_EnterMonitor(
- PZMonitor *mon,
- char *file,
- PRIntn line)
- {
- PRIntervalTime callTime, now;
- callTime = PR_IntervalNow();
- PR_EnterMonitor(mon->mon);
- now = PR_IntervalNow();
- callTime = now - callTime;
- if (PR_GetMonitorEntryCount(mon->mon) == 1) {
- mon->time = now;
- }
- Vtrace(EnterMonitor, mon->ltype, callTime, 0, mon, line, file);
- return;
- } /* --- end pz_EnterMonitor() --- */
- extern PRStatus
- pz_ExitMonitor(
- PZMonitor *mon,
- char *file,
- PRIntn line)
- {
- PRStatus rc;
- PRIntervalTime callTime, now, heldTime;
- PRIntn mec = PR_GetMonitorEntryCount(mon->mon);
- heldTime = (PRIntervalTime)-1;
- callTime = PR_IntervalNow();
- rc = PR_ExitMonitor(mon->mon);
- now = PR_IntervalNow();
- callTime = now - callTime;
- if (mec == 1)
- heldTime = now - mon->time;
- Vtrace(ExitMonitor, mon->ltype, callTime, heldTime, mon, line, file);
- return (rc);
- } /* --- end pz_ExitMonitor() --- */
- extern PRIntn
- pz_GetMonitorEntryCount(
- PZMonitor *mon,
- char *file,
- PRIntn line)
- {
- return (PR_GetMonitorEntryCount(mon->mon));
- } /* --- end pz_GetMonitorEntryCount() --- */
- extern PRStatus
- pz_Wait(
- PZMonitor *mon,
- PRIntervalTime ticks,
- char *file,
- PRIntn line)
- {
- PRStatus rc;
- PRIntervalTime callTime;
- callTime = PR_IntervalNow();
- rc = PR_Wait(mon->mon, ticks);
- callTime = PR_IntervalNow() - callTime;
- Vtrace(Wait, mon->ltype, callTime, 0, mon, line, file);
- return (rc);
- } /* --- end pz_Wait() --- */
- extern PRStatus
- pz_Notify(
- PZMonitor *mon,
- char *file,
- PRIntn line)
- {
- PRStatus rc;
- PRIntervalTime callTime;
- callTime = PR_IntervalNow();
- rc = PR_Notify(mon->mon);
- callTime = PR_IntervalNow() - callTime;
- Vtrace(Notify, mon->ltype, callTime, 0, mon, line, file);
- return (rc);
- } /* --- end pz_Notify() --- */
- extern PRStatus
- pz_NotifyAll(
- PZMonitor *mon,
- char *file,
- PRIntn line)
- {
- PRStatus rc;
- PRIntervalTime callTime;
- callTime = PR_IntervalNow();
- rc = PR_NotifyAll(mon->mon);
- callTime = PR_IntervalNow() - callTime;
- Vtrace(NotifyAll, mon->ltype, callTime, 0, mon, line, file);
- return (rc);
- } /* --- end pz_NotifyAll() --- */
- #endif /* NEED_NSS_ILOCK */
- /* --- end nssilock.c --------------------------------- */
|