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