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
) {
225 lock
->lock
= PR_NewLock();
226 if ( NULL
== lock
->lock
) {
228 PORT_SetError(SEC_ERROR_NO_MEMORY
);
231 PORT_SetError(SEC_ERROR_NO_MEMORY
);
234 Vtrace( NewLock
, ltype
, 0, 0, lock
, line
, file
);
236 } /* --- end pz_NewLock() --- */
245 PRIntervalTime callTime
;
247 callTime
= PR_IntervalNow();
248 PR_Lock( lock
->lock
);
249 lock
->time
= PR_IntervalNow();
250 callTime
= lock
->time
- callTime
;
252 Vtrace( Lock
, lock
->ltype
, callTime
, 0, lock
, line
, file
);
254 } /* --- end pz_Lock() --- */
264 PRIntervalTime callTime
, now
, heldTime
;
266 callTime
= PR_IntervalNow();
267 rc
= PR_Unlock( lock
->lock
);
268 now
= PR_IntervalNow();
269 callTime
= now
- callTime
;
270 heldTime
= now
- lock
->time
;
271 Vtrace( Unlock
, lock
->ltype
, callTime
, heldTime
, lock
, line
, file
);
273 } /* --- end pz_Unlock() --- */
282 Vtrace( DestroyLock
, lock
->ltype
, 0, 0, lock
, line
, file
);
283 PR_DestroyLock( lock
->lock
);
286 } /* --- end pz_DestroyLock() --- */
299 cvar
= PR_NEWZAP( PZCondVar
);
300 if ( NULL
== cvar
) {
301 PORT_SetError(SEC_ERROR_NO_MEMORY
);
303 cvar
->ltype
= lock
->ltype
;
304 cvar
->cvar
= PR_NewCondVar( lock
->lock
);
305 if ( NULL
== cvar
->cvar
) {
307 PORT_SetError(SEC_ERROR_NO_MEMORY
);
311 Vtrace( NewCondVar
, lock
->ltype
, 0, 0, cvar
, line
, file
);
313 } /* --- end pz_NewCondVar() --- */
322 Vtrace( DestroyCondVar
, cvar
->ltype
, 0, 0, cvar
, line
, file
);
323 PR_DestroyCondVar( cvar
->cvar
);
325 } /* --- end pz_DestroyCondVar() --- */
330 PRIntervalTime timeout
,
336 PRIntervalTime callTime
;
338 callTime
= PR_IntervalNow();
339 rc
= PR_WaitCondVar( cvar
->cvar
, timeout
);
340 callTime
= PR_IntervalNow() - callTime
;
342 Vtrace( WaitCondVar
, cvar
->ltype
, callTime
, 0, cvar
, line
, file
);
344 } /* --- end pz_WaitCondVar() --- */
355 rc
= PR_NotifyCondVar( cvar
->cvar
);
357 Vtrace( NotifyCondVar
, cvar
->ltype
, 0, 0, cvar
, line
, file
);
359 } /* --- end pz_NotifyCondVar() --- */
370 rc
= PR_NotifyAllCondVar( cvar
->cvar
);
372 Vtrace( NotifyAllCondVar
, cvar
->ltype
, 0, 0, cvar
, line
, file
);
374 } /* --- end pz_NotifyAllCondVar() --- */
386 /* Self Initialize the nssILock feature */
387 if (!nssILockInitialized
) {
388 rc
= PR_CallOnce( &coNssILock
, nssILockInit
);
389 if ( PR_FAILURE
== rc
) {
390 PR_SetError( PR_UNKNOWN_ERROR
, 0 );
395 mon
= PR_NEWZAP( PZMonitor
);
398 mon
->mon
= PR_NewMonitor();
399 if ( NULL
== mon
->mon
) {
401 PORT_SetError(SEC_ERROR_NO_MEMORY
);
404 PORT_SetError(SEC_ERROR_NO_MEMORY
);
407 Vtrace( NewMonitor
, ltype
, 0, 0, mon
, line
, file
);
409 } /* --- end pz_NewMonitor() --- */
418 Vtrace( DestroyMonitor
, mon
->ltype
, 0, 0, mon
, line
, file
);
419 PR_DestroyMonitor( mon
->mon
);
422 } /* --- end pz_DestroyMonitor() --- */
431 PRIntervalTime callTime
, now
;
433 callTime
= PR_IntervalNow();
434 PR_EnterMonitor( mon
->mon
);
435 now
= PR_IntervalNow();
436 callTime
= now
- callTime
;
437 if ( PR_GetMonitorEntryCount(mon
->mon
) == 1 ) {
440 Vtrace( EnterMonitor
, mon
->ltype
, callTime
, 0, mon
, line
, file
);
442 } /* --- end pz_EnterMonitor() --- */
452 PRIntervalTime callTime
, now
, heldTime
;
453 PRIntn mec
= PR_GetMonitorEntryCount( mon
->mon
);
455 heldTime
= (PRIntervalTime
)-1;
456 callTime
= PR_IntervalNow();
457 rc
= PR_ExitMonitor( mon
->mon
);
458 now
= PR_IntervalNow();
459 callTime
= now
- callTime
;
461 heldTime
= now
- mon
->time
;
462 Vtrace( ExitMonitor
, mon
->ltype
, callTime
, heldTime
, mon
, line
, file
);
464 } /* --- end pz_ExitMonitor() --- */
467 pz_GetMonitorEntryCount(
473 return( PR_GetMonitorEntryCount(mon
->mon
));
474 } /* --- end pz_GetMonitorEntryCount() --- */
480 PRIntervalTime ticks
,
486 PRIntervalTime callTime
;
488 callTime
= PR_IntervalNow();
489 rc
= PR_Wait( mon
->mon
, ticks
);
490 callTime
= PR_IntervalNow() - callTime
;
491 Vtrace( Wait
, mon
->ltype
, callTime
, 0, mon
, line
, file
);
493 } /* --- end pz_Wait() --- */
503 PRIntervalTime callTime
;
505 callTime
= PR_IntervalNow();
506 rc
= PR_Notify( mon
->mon
);
507 callTime
= PR_IntervalNow() - callTime
;
508 Vtrace( Notify
, mon
->ltype
, callTime
, 0, mon
, line
, file
);
510 } /* --- end pz_Notify() --- */
520 PRIntervalTime callTime
;
522 callTime
= PR_IntervalNow();
523 rc
= PR_NotifyAll( mon
->mon
);
524 callTime
= PR_IntervalNow() - callTime
;
525 Vtrace( NotifyAll
, mon
->ltype
, callTime
, 0, mon
, line
, file
);
527 } /* --- end pz_NotifyAll() --- */
529 #endif /* NEED_NSS_ILOCK */
530 /* --- end nssilock.c --------------------------------- */