1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1994-2000
19
* the Initial Developer. All Rights Reserved.
23
* Alternatively, the contents of this file may be used under the terms of
24
* either the GNU General Public License Version 2 or later (the "GPL"), or
25
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26
* in which case the provisions of the GPL or the LGPL are applicable instead
27
* of those above. If you wish to allow use of your version of this file only
28
* under the terms of either the GPL or the LGPL, and not to allow others to
29
* use your version of this file under the terms of the MPL, indicate your
30
* decision by deleting the provisions above and replace them with the notice
31
* and other provisions required by the GPL or the LGPL. If you do not delete
32
* the provisions above, a recipient may use your version of this file under
33
* the terms of any one of the MPL, the GPL or the LGPL.
35
* ***** END LICENSE BLOCK ***** */
38
* nssilock.c - NSS lock instrumentation wrapper functions
40
* NOTE - These are not public interfaces
42
* Implementation Notes:
43
* I've tried to make the instrumentation relatively non-intrusive.
44
* To do this, I have used a single PR_LOG() call in each
45
* instrumented function. There's room for improvement.
58
#if defined(NEED_NSS_ILOCK)
63
** Declare the instrumented PZLock
66
PRLock *lock; /* the PZLock to be instrumented */
67
PRIntervalTime time; /* timestamp when the lock was aquired */
72
** Declare the instrumented PZMonitor
75
PRMonitor *mon; /* the PZMonitor to be instrumented */
76
PRIntervalTime time; /* timestamp when the monitor was aquired */
81
** Declare the instrumented PZCondVar
84
PRCondVar *cvar; /* the PZCondVar to be instrumented */
90
** Define a CallOnce type to ensure serialized self-initialization
92
static PRCallOnceType coNssILock; /* CallOnce type */
93
static PRIntn nssILockInitialized; /* initialization done when 1 */
94
static PRLogModuleInfo *nssILog; /* Log instrumentation to this handle */
97
#define NUM_TT_ENTRIES 6000000
98
static PRInt32 traceIndex = -1; /* index into trace table */
99
static struct pzTrace_s *tt; /* pointer to trace table */
100
static PRInt32 ttBufSize = (NUM_TT_ENTRIES * sizeof(struct pzTrace_s ));
101
static PRCondVar *ttCVar;
102
static PRLock *ttLock;
103
static PRFileDesc *ttfd; /* trace table file */
106
** Vtrace() -- Trace events, write events to external media
108
** Vtrace() records traced events in an in-memory trace table
109
** when the trace table fills, Vtrace writes the entire table
118
PRIntervalTime callTime,
119
PRIntervalTime heldTime,
125
struct pzTrace_s *tp;
128
idx = PR_AtomicIncrement( &traceIndex );
129
while( NUM_TT_ENTRIES <= idx || op == FlushTT ) {
130
if( NUM_TT_ENTRIES == idx || op == FlushTT ) {
131
int writeSize = idx * sizeof(struct pzTrace_s);
133
PR_Write( ttfd, tt, writeSize );
135
PR_NotifyAllCondVar( ttCVar );
140
while( NUM_TT_ENTRIES < idx )
141
PR_WaitCondVar(ttCVar, PR_INTERVAL_NO_WAIT);
147
/* create the trace entry */
149
tp->threadID = PR_GetThreadID(PR_GetCurrentThread());
152
tp->callTime = callTime;
153
tp->heldTime = heldTime;
156
strcpy(tp->file, file );
158
} /* --- end Vtrace() --- */
161
** pz_TraceFlush() -- Force trace table write to file
164
extern void pz_TraceFlush( void )
166
Vtrace( FlushTT, nssILockSelfServ, 0, 0, NULL, 0, "" );
168
} /* --- end pz_TraceFlush() --- */
171
** nssILockInit() -- Initialization for nssilock
173
** This function is called from the CallOnce mechanism.
179
nssILockInitialized = 1;
182
nssILog = PR_NewLogModule("nssilock");
183
if ( NULL == nssILog ) {
187
tt = PR_Calloc( NUM_TT_ENTRIES, sizeof(struct pzTrace_s));
189
fprintf(stderr, "nssilock: can't allocate trace table\n");
193
ttfd = PR_Open( "xxxTTLog", PR_CREATE_FILE | PR_WRONLY, 0666 );
194
if ( NULL == ttfd ) {
195
fprintf( stderr, "Oh Drat! Can't open 'xxxTTLog'\n");
199
ttLock = PR_NewLock();
200
ttCVar = PR_NewCondVar(ttLock);
203
} /* --- end nssILockInit() --- */
205
extern PZLock * pz_NewLock(
213
/* Self Initialize the nssILock feature */
214
if (!nssILockInitialized) {
215
rc = PR_CallOnce( &coNssILock, nssILockInit );
216
if ( PR_FAILURE == rc ) {
217
PR_SetError( PR_UNKNOWN_ERROR, 0 );
222
lock = PR_NEWZAP( PZLock );
223
if ( NULL != lock ) {
224
lock->lock = PR_NewLock();
225
if ( NULL == lock->lock ) {
232
Vtrace( NewLock, ltype, 0, 0, lock, line, file );
234
} /* --- end pz_NewLock() --- */
243
PRIntervalTime callTime;
245
callTime = PR_IntervalNow();
246
PR_Lock( lock->lock );
247
lock->time = PR_IntervalNow();
248
callTime = lock->time - callTime;
250
Vtrace( Lock, lock->ltype, callTime, 0, lock, line, file );
252
} /* --- end pz_Lock() --- */
262
PRIntervalTime callTime, now, heldTime;
264
callTime = PR_IntervalNow();
265
rc = PR_Unlock( lock->lock );
266
now = PR_IntervalNow();
267
callTime = now - callTime;
268
heldTime = now - lock->time;
269
Vtrace( Unlock, lock->ltype, callTime, heldTime, lock, line, file );
271
} /* --- end pz_Unlock() --- */
280
Vtrace( DestroyLock, lock->ltype, 0, 0, lock, line, file );
281
PR_DestroyLock( lock->lock );
284
} /* --- end pz_DestroyLock() --- */
297
cvar = PR_NEWZAP( PZCondVar );
298
if ( NULL == cvar ) return(NULL);
300
cvar->ltype = lock->ltype;
301
cvar->cvar = PR_NewCondVar( lock->lock );
302
if ( NULL == cvar->cvar ) {
305
Vtrace( NewCondVar, cvar->ltype, 0, 0, cvar, line, file );
307
} /* --- end pz_NewCondVar() --- */
316
Vtrace( DestroyCondVar, cvar->ltype, 0, 0, cvar, line, file );
317
PR_DestroyCondVar( cvar->cvar );
319
} /* --- end pz_DestroyCondVar() --- */
324
PRIntervalTime timeout,
330
PRIntervalTime callTime;
332
callTime = PR_IntervalNow();
333
rc = PR_WaitCondVar( cvar->cvar, timeout );
334
callTime = PR_IntervalNow() - callTime;
336
Vtrace( WaitCondVar, cvar->ltype, callTime, 0, cvar, line, file );
338
} /* --- end pz_WaitCondVar() --- */
349
rc = PR_NotifyCondVar( cvar->cvar );
351
Vtrace( NotifyCondVar, cvar->ltype, 0, 0, cvar, line, file );
353
} /* --- end pz_NotifyCondVar() --- */
364
rc = PR_NotifyAllCondVar( cvar->cvar );
366
Vtrace( NotifyAllCondVar, cvar->ltype, 0, 0, cvar, line, file );
368
} /* --- end pz_NotifyAllCondVar() --- */
380
/* Self Initialize the nssILock feature */
381
if (!nssILockInitialized) {
382
rc = PR_CallOnce( &coNssILock, nssILockInit );
383
if ( PR_FAILURE == rc ) {
384
PR_SetError( PR_UNKNOWN_ERROR, 0 );
389
mon = PR_NEWZAP( PZMonitor );
391
mon->mon = PR_NewMonitor();
392
if ( NULL == mon->mon ) {
399
Vtrace( NewMonitor, mon->ltype, 0, 0, mon, line, file );
401
} /* --- end pz_NewMonitor() --- */
410
Vtrace( DestroyMonitor, mon->ltype, 0, 0, mon, line, file );
411
PR_DestroyMonitor( mon->mon );
414
} /* --- end pz_DestroyMonitor() --- */
423
PRIntervalTime callTime, now;
425
callTime = PR_IntervalNow();
426
PR_EnterMonitor( mon->mon );
427
now = PR_IntervalNow();
428
callTime = now - callTime;
429
if ( PR_GetMonitorEntryCount(mon->mon) == 1 ) {
432
Vtrace( EnterMonitor, mon->ltype, callTime, 0, mon, line, file );
434
} /* --- end pz_EnterMonitor() --- */
444
PRIntervalTime callTime, now, heldTime;
445
PRIntn mec = PR_GetMonitorEntryCount( mon->mon );
447
heldTime = (PRIntervalTime)-1;
448
callTime = PR_IntervalNow();
449
rc = PR_ExitMonitor( mon->mon );
450
now = PR_IntervalNow();
451
callTime = now - callTime;
453
heldTime = now - mon->time;
454
Vtrace( ExitMonitor, mon->ltype, callTime, heldTime, mon, line, file );
456
} /* --- end pz_ExitMonitor() --- */
459
pz_GetMonitorEntryCount(
465
return( PR_GetMonitorEntryCount(mon->mon));
466
} /* --- end pz_GetMonitorEntryCount() --- */
472
PRIntervalTime ticks,
478
PRIntervalTime callTime;
480
callTime = PR_IntervalNow();
481
rc = PR_Wait( mon->mon, ticks );
482
callTime = PR_IntervalNow() - callTime;
483
Vtrace( Wait, mon->ltype, callTime, 0, mon, line, file );
485
} /* --- end pz_Wait() --- */
495
PRIntervalTime callTime;
497
callTime = PR_IntervalNow();
498
rc = PR_Notify( mon->mon );
499
callTime = PR_IntervalNow() - callTime;
500
Vtrace( Notify, mon->ltype, callTime, 0, mon, line, file );
502
} /* --- end pz_Notify() --- */
512
PRIntervalTime callTime;
514
callTime = PR_IntervalNow();
515
rc = PR_NotifyAll( mon->mon );
516
callTime = PR_IntervalNow() - callTime;
517
Vtrace( NotifyAll, mon->ltype, callTime, 0, mon, line, file );
519
} /* --- end pz_NotifyAll() --- */
521
#endif /* NEED_NSS_ILOCK */
522
/* --- end nssilock.c --------------------------------- */