andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: andre@0: /* andre@0: ** nssilock.h - Instrumented locking functions for NSS andre@0: ** andre@0: ** Description: andre@0: ** nssilock provides instrumentation for locks and monitors in andre@0: ** the NSS libraries. The instrumentation, when enabled, causes andre@0: ** each call to the instrumented function to record data about andre@0: ** the call to an external file. The external file andre@0: ** subsequently used to extract performance data and other andre@0: ** statistical information about the operation of locks used in andre@0: ** the nss library. andre@0: ** andre@0: ** To enable compilation with instrumentation, build NSS with andre@0: ** the compile time switch NEED_NSS_ILOCK defined. andre@0: ** andre@0: ** say: "gmake OS_CFLAGS+=-DNEED_NSS_ILOCK" at make time. andre@0: ** andre@0: ** At runtime, to enable recording from nssilock, one or more andre@0: ** environment variables must be set. For each nssILockType to andre@0: ** be recorded, an environment variable of the form NSS_ILOCK_x andre@0: ** must be set to 1. For example: andre@0: ** andre@0: ** set NSS_ILOCK_Cert=1 andre@0: ** andre@0: ** nssilock uses PRLOG is used to record to trace data. The andre@0: ** PRLogModule name associated with nssilock data is: "nssilock". andre@0: ** To enable recording of nssilock data you will need to set the andre@0: ** environment variable NSPR_LOG_MODULES to enable andre@0: ** recording for the nssilock log module. Similarly, you will andre@0: ** need to set the environment variable NSPR_LOG_FILE to specify andre@0: ** the filename to receive the recorded data. See prlog.h for usage. andre@0: ** Example: andre@0: ** andre@0: ** export NSPR_LOG_MODULES=nssilock:6 andre@0: ** export NSPR_LOG_FILE=xxxLogfile andre@0: ** andre@0: ** Operation: andre@0: ** nssilock wraps calls to NSPR's PZLock and PZMonitor functions andre@0: ** with similarly named functions: PZ_NewLock(), etc. When NSS is andre@0: ** built with lock instrumentation enabled, the PZ* functions are andre@0: ** compiled into NSS; when lock instrumentation is disabled, andre@0: ** calls to PZ* functions are directly mapped to PR* functions andre@0: ** and the instrumentation arguments to the PZ* functions are andre@0: ** compiled away. andre@0: ** andre@0: ** andre@0: ** File Format: andre@0: ** The format of the external file is implementation andre@0: ** dependent. Where NSPR's PR_LOG() function is used, the file andre@0: ** contains data defined for PR_LOG() plus the data written by andre@0: ** the wrapped function. On some platforms and under some andre@0: ** circumstances, platform dependent logging or andre@0: ** instrumentation probes may be used. In any case, the andre@0: ** relevant data provided by the lock instrumentation is: andre@0: ** andre@0: ** lockType, func, address, duration, line, file [heldTime] andre@0: ** andre@0: ** where: andre@0: ** andre@0: ** lockType: a character representation of nssILockType for the andre@0: ** call. e.g. ... "cert" andre@0: ** andre@0: ** func: the function doing the tracing. e.g. "NewLock" andre@0: ** andre@0: ** address: address of the instrumented lock or monitor andre@0: ** andre@0: ** duration: is how long was spent in the instrumented function, andre@0: ** in PRIntervalTime "ticks". andre@0: ** andre@0: ** line: the line number within the calling function andre@0: ** andre@0: ** file: the file from which the call was made andre@0: ** andre@0: ** heldTime: how long the lock/monitor was held. field andre@0: ** present only for PZ_Unlock() and PZ_ExitMonitor(). andre@0: ** andre@0: ** Design Notes: andre@0: ** The design for lock instrumentation was influenced by the andre@0: ** need to gather performance data on NSS 3.x. It is intended andre@0: ** that the effort to modify NSS to use lock instrumentation andre@0: ** be minimized. Existing calls to locking functions need only andre@0: ** have their names changed to the instrumentation function andre@0: ** names. andre@0: ** andre@0: ** Private NSS Interface: andre@0: ** nssilock.h defines a private interface for use by NSS. andre@0: ** nssilock.h is experimental in nature and is subject to andre@0: ** change or revocation without notice. ... Don't mess with andre@0: ** it. andre@0: ** andre@0: */ andre@0: andre@0: /* andre@0: * $Id: andre@0: */ andre@0: andre@0: #ifndef _NSSILOCK_H_ andre@0: #define _NSSILOCK_H_ andre@0: andre@0: #include "utilrename.h" andre@0: #include "prtypes.h" andre@0: #include "prmon.h" andre@0: #include "prlock.h" andre@0: #include "prcvar.h" andre@0: andre@0: #include "nssilckt.h" andre@0: andre@0: PR_BEGIN_EXTERN_C andre@0: andre@0: #if defined(NEED_NSS_ILOCK) andre@0: andre@0: #define PZ_NewLock(t) pz_NewLock((t),__FILE__,__LINE__) andre@0: extern PZLock * andre@0: pz_NewLock( andre@0: nssILockType ltype, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_Lock(k) pz_Lock((k),__FILE__,__LINE__) andre@0: extern void andre@0: pz_Lock( andre@0: PZLock *lock, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_Unlock(k) pz_Unlock((k),__FILE__,__LINE__) andre@0: extern PRStatus andre@0: pz_Unlock( andre@0: PZLock *lock, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_DestroyLock(k) pz_DestroyLock((k),__FILE__,__LINE__) andre@0: extern void andre@0: pz_DestroyLock( andre@0: PZLock *lock, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: andre@0: #define PZ_NewCondVar(l) pz_NewCondVar((l),__FILE__,__LINE__) andre@0: extern PZCondVar * andre@0: pz_NewCondVar( andre@0: PZLock *lock, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_DestroyCondVar(v) pz_DestroyCondVar((v),__FILE__,__LINE__) andre@0: extern void andre@0: pz_DestroyCondVar( andre@0: PZCondVar *cvar, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_WaitCondVar(v,t) pz_WaitCondVar((v),(t),__FILE__,__LINE__) andre@0: extern PRStatus andre@0: pz_WaitCondVar( andre@0: PZCondVar *cvar, andre@0: PRIntervalTime timeout, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_NotifyCondVar(v) pz_NotifyCondVar((v),__FILE__,__LINE__) andre@0: extern PRStatus andre@0: pz_NotifyCondVar( andre@0: PZCondVar *cvar, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_NotifyAllCondVar(v) pz_NotifyAllCondVar((v),__FILE__,__LINE__) andre@0: extern PRStatus andre@0: pz_NotifyAllCondVar( andre@0: PZCondVar *cvar, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: andre@0: #define PZ_NewMonitor(t) pz_NewMonitor((t),__FILE__,__LINE__) andre@0: extern PZMonitor * andre@0: pz_NewMonitor( andre@0: nssILockType ltype, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_DestroyMonitor(m) pz_DestroyMonitor((m),__FILE__,__LINE__) andre@0: extern void andre@0: pz_DestroyMonitor( andre@0: PZMonitor *mon, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_EnterMonitor(m) pz_EnterMonitor((m),__FILE__,__LINE__) andre@0: extern void andre@0: pz_EnterMonitor( andre@0: PZMonitor *mon, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: andre@0: #define PZ_ExitMonitor(m) pz_ExitMonitor((m),__FILE__,__LINE__) andre@0: extern PRStatus andre@0: pz_ExitMonitor( andre@0: PZMonitor *mon, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_InMonitor(m) (PZ_GetMonitorEntryCount(m) > 0 ) andre@0: #define PZ_GetMonitorEntryCount(m) pz_GetMonitorEntryCount((m),__FILE__,__LINE__) andre@0: extern PRIntn andre@0: pz_GetMonitorEntryCount( andre@0: PZMonitor *mon, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_Wait(m,i) pz_Wait((m),((i)),__FILE__,__LINE__) andre@0: extern PRStatus andre@0: pz_Wait( andre@0: PZMonitor *mon, andre@0: PRIntervalTime ticks, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_Notify(m) pz_Notify((m),__FILE__,__LINE__) andre@0: extern PRStatus andre@0: pz_Notify( andre@0: PZMonitor *mon, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_NotifyAll(m) pz_NotifyAll((m),__FILE__,__LINE__) andre@0: extern PRStatus andre@0: pz_NotifyAll( andre@0: PZMonitor *mon, andre@0: char *file, andre@0: PRIntn line andre@0: ); andre@0: andre@0: #define PZ_TraceFlush() pz_TraceFlush() andre@0: extern void pz_TraceFlush( void ); andre@0: andre@0: #else /* NEED_NSS_ILOCK */ andre@0: andre@0: #define PZ_NewLock(t) PR_NewLock() andre@0: #define PZ_DestroyLock(k) PR_DestroyLock((k)) andre@0: #define PZ_Lock(k) PR_Lock((k)) andre@0: #define PZ_Unlock(k) PR_Unlock((k)) andre@0: andre@0: #define PZ_NewCondVar(l) PR_NewCondVar((l)) andre@0: #define PZ_DestroyCondVar(v) PR_DestroyCondVar((v)) andre@0: #define PZ_WaitCondVar(v,t) PR_WaitCondVar((v),(t)) andre@0: #define PZ_NotifyCondVar(v) PR_NotifyCondVar((v)) andre@0: #define PZ_NotifyAllCondVar(v) PR_NotifyAllCondVar((v)) andre@0: andre@0: #define PZ_NewMonitor(t) PR_NewMonitor() andre@0: #define PZ_DestroyMonitor(m) PR_DestroyMonitor((m)) andre@0: #define PZ_EnterMonitor(m) PR_EnterMonitor((m)) andre@0: #define PZ_ExitMonitor(m) PR_ExitMonitor((m)) andre@0: #define PZ_InMonitor(m) PR_InMonitor((m)) andre@0: #define PZ_Wait(m,t) PR_Wait(((m)),((t))) andre@0: #define PZ_Notify(m) PR_Notify((m)) andre@0: #define PZ_NotifyAll(m) PR_Notify((m)) andre@0: #define PZ_TraceFlush() /* nothing */ andre@0: andre@0: andre@0: #endif /* NEED_NSS_ILOCK */ andre@0: andre@0: PR_END_EXTERN_C andre@0: #endif /* _NSSILOCK_H_ */