security/nss/lib/util/nssilock.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /*
     6  * nssilock.c - NSS lock instrumentation wrapper functions
     7  *
     8  * NOTE - These are not public interfaces
     9  *
    10  * Implementation Notes:
    11  * I've tried to make the instrumentation relatively non-intrusive.
    12  * To do this, I have used a single PR_LOG() call in each
    13  * instrumented function. There's room for improvement.
    14  *
    15  *
    16  */
    18 #include "prinit.h"
    19 #include "prerror.h"
    20 #include "prlock.h"
    21 #include "prmem.h"
    22 #include "prenv.h"
    23 #include "prcvar.h"
    24 #include "prio.h"
    26 #if defined(NEED_NSS_ILOCK)
    27 #include "prlog.h"
    28 #include "nssilock.h"
    30 /*
    31 ** Declare the instrumented PZLock 
    32 */
    33 struct pzlock_s {
    34     PRLock *lock;  /* the PZLock to be instrumented */
    35     PRIntervalTime time; /* timestamp when the lock was aquired */
    36     nssILockType ltype;
    37 };
    39 /*
    40 ** Declare the instrumented PZMonitor 
    41 */
    42 struct pzmonitor_s {
    43     PRMonitor *mon;   /* the PZMonitor to be instrumented */
    44     PRIntervalTime time; /* timestamp when the monitor was aquired */
    45     nssILockType ltype;
    46 };
    48 /*
    49 ** Declare the instrumented PZCondVar
    50 */
    51 struct pzcondvar_s  {
    52     PRCondVar   *cvar;  /* the PZCondVar to be instrumented */
    53     nssILockType ltype;
    54 };
    57 /*
    58 ** Define a CallOnce type to ensure serialized self-initialization
    59 */
    60 static PRCallOnceType coNssILock;     /* CallOnce type */
    61 static PRIntn  nssILockInitialized;   /* initialization done when 1 */
    62 static PRLogModuleInfo *nssILog;      /* Log instrumentation to this handle */
    65 #define NUM_TT_ENTRIES 6000000
    66 static PRInt32  traceIndex = -1;      /* index into trace table */
    67 static struct pzTrace_s *tt;          /* pointer to trace table */
    68 static PRInt32  ttBufSize = (NUM_TT_ENTRIES * sizeof(struct pzTrace_s ));
    69 static PRCondVar *ttCVar;
    70 static PRLock    *ttLock;
    71 static PRFileDesc *ttfd;              /* trace table file */
    73 /*
    74 ** Vtrace() -- Trace events, write events to external media
    75 **
    76 ** Vtrace() records traced events in an in-memory trace table
    77 ** when the trace table fills, Vtrace writes the entire table
    78 ** to a file.
    79 **
    80 ** data can be lost!
    81 **
    82 */
    83 static void Vtrace(
    84     nssILockOp      op,
    85     nssILockType    ltype,
    86     PRIntervalTime  callTime,
    87     PRIntervalTime  heldTime,
    88     void            *lock,
    89     PRIntn          line,
    90     char            *file
    91 )  {
    92     PRInt32 idx;
    93     struct pzTrace_s *tp;
    95 RetryTrace:
    96     idx = PR_ATOMIC_INCREMENT( &traceIndex );
    97     while( NUM_TT_ENTRIES <= idx || op == FlushTT ) {
    98         if( NUM_TT_ENTRIES == idx  || op == FlushTT )  {
    99             int writeSize = idx * sizeof(struct pzTrace_s);
   100             PR_Lock(ttLock);
   101             PR_Write( ttfd, tt, writeSize );
   102             traceIndex = -1;
   103             PR_NotifyAllCondVar( ttCVar );
   104             PR_Unlock(ttLock);
   105             goto RetryTrace;
   106         } else {
   107             PR_Lock(ttLock);
   108             while( NUM_TT_ENTRIES < idx )
   109                 PR_WaitCondVar(ttCVar, PR_INTERVAL_NO_WAIT);
   110             PR_Unlock(ttLock);
   111             goto RetryTrace;
   112         }
   113     } /* end while() */
   115     /* create the trace entry */
   116     tp = tt + idx;
   117     tp->threadID = PR_GetThreadID(PR_GetCurrentThread());
   118     tp->op = op;
   119     tp->ltype = ltype;
   120     tp->callTime = callTime;
   121     tp->heldTime = heldTime;
   122     tp->lock = lock;
   123     tp ->line = line;
   124     strcpy(tp->file, file );
   125     return;
   126 } /* --- end Vtrace() --- */
   128 /*
   129 ** pz_TraceFlush() -- Force trace table write to file
   130 **
   131 */
   132 extern void pz_TraceFlush( void )
   133 {
   134     Vtrace( FlushTT, nssILockSelfServ, 0, 0, NULL, 0, "" );
   135     return;
   136 } /* --- end pz_TraceFlush() --- */
   138 /*
   139 ** nssILockInit() -- Initialization for nssilock
   140 **
   141 ** This function is called from the CallOnce mechanism.
   142 */
   143 static PRStatus
   144     nssILockInit( void ) 
   145 {   
   146     int i;
   147     nssILockInitialized = 1;
   149     /* new log module */
   150     nssILog = PR_NewLogModule("nssilock");
   151     if ( NULL == nssILog )  {
   152         return(PR_FAILURE);
   153     }
   155     tt = PR_Calloc( NUM_TT_ENTRIES, sizeof(struct pzTrace_s));
   156     if (NULL == tt ) {
   157         fprintf(stderr, "nssilock: can't allocate trace table\n");
   158         exit(1);
   159     }
   161     ttfd = PR_Open( "xxxTTLog", PR_CREATE_FILE | PR_WRONLY, 0666 );
   162     if ( NULL == ttfd )  {
   163         fprintf( stderr, "Oh Drat! Can't open 'xxxTTLog'\n");
   164         exit(1);
   165     }
   167     ttLock = PR_NewLock();
   168     ttCVar = PR_NewCondVar(ttLock);
   170     return(PR_SUCCESS);
   171 } /* --- end nssILockInit() --- */
   173 extern PZLock * pz_NewLock( 
   174     nssILockType ltype,
   175     char *file,  
   176     PRIntn line )
   177 {
   178     PRStatus rc;
   179     PZLock  *lock;
   181     /* Self Initialize the nssILock feature */
   182     if (!nssILockInitialized)  {
   183         rc = PR_CallOnce( &coNssILock, nssILockInit );
   184         if ( PR_FAILURE == rc ) {
   185             PR_SetError( PR_UNKNOWN_ERROR, 0 );
   186             return( NULL );
   187         }
   188     }
   190     lock = PR_NEWZAP( PZLock );
   191     if ( NULL != lock )  {
   192         lock->ltype = ltype;
   193         lock->lock = PR_NewLock();
   194         if ( NULL == lock->lock )  {
   195             PR_DELETE( lock );
   196             PORT_SetError(SEC_ERROR_NO_MEMORY);
   197         }
   198     } else {
   199             PORT_SetError(SEC_ERROR_NO_MEMORY);
   200     }
   202     Vtrace( NewLock, ltype, 0, 0, lock, line, file );
   203     return(lock);
   204 } /* --- end pz_NewLock() --- */
   206 extern void
   207     pz_Lock(
   208         PZLock *lock,
   209         char *file,
   210         PRIntn line
   211     )
   212 {            
   213     PRIntervalTime callTime;
   215     callTime = PR_IntervalNow();
   216     PR_Lock( lock->lock );
   217     lock->time = PR_IntervalNow();
   218     callTime = lock->time - callTime;
   220     Vtrace( Lock, lock->ltype, callTime, 0, lock, line, file );
   221     return;
   222 } /* --- end  pz_Lock() --- */
   224 extern PRStatus
   225     pz_Unlock(
   226         PZLock *lock,
   227         char *file,
   228         PRIntn line
   229     ) 
   230 {
   231     PRStatus rc;
   232     PRIntervalTime callTime, now, heldTime;
   234     callTime = PR_IntervalNow();
   235     rc = PR_Unlock( lock->lock );
   236     now = PR_IntervalNow(); 
   237     callTime = now - callTime;
   238     heldTime = now - lock->time;
   239     Vtrace( Unlock, lock->ltype, callTime, heldTime, lock, line, file );
   240     return( rc );
   241 } /* --- end  pz_Unlock() --- */
   243 extern void
   244     pz_DestroyLock(
   245         PZLock *lock,
   246         char *file,
   247         PRIntn line
   248     )
   249 {
   250     Vtrace( DestroyLock, lock->ltype, 0, 0, lock, line, file );
   251     PR_DestroyLock( lock->lock );
   252     PR_DELETE( lock );
   253     return;
   254 } /* --- end  pz_DestroyLock() --- */
   258 extern PZCondVar *
   259     pz_NewCondVar(
   260         PZLock *lock,
   261         char *file,
   262         PRIntn line
   263     )
   264 {
   265     PZCondVar *cvar;
   267     cvar = PR_NEWZAP( PZCondVar );
   268     if ( NULL == cvar ) {
   269         PORT_SetError(SEC_ERROR_NO_MEMORY);
   270     } else {
   271         cvar->ltype = lock->ltype; 
   272         cvar->cvar = PR_NewCondVar( lock->lock );
   273         if ( NULL == cvar->cvar )  {
   274             PR_DELETE( cvar );
   275             PORT_SetError(SEC_ERROR_NO_MEMORY);
   276         }
   278     }
   279     Vtrace( NewCondVar, lock->ltype, 0, 0, cvar, line, file );
   280     return( cvar );
   281 } /* --- end  pz_NewCondVar() --- */
   283 extern void
   284     pz_DestroyCondVar(
   285         PZCondVar *cvar,
   286         char *file,
   287         PRIntn line
   288     )
   289 {
   290     Vtrace( DestroyCondVar, cvar->ltype, 0, 0, cvar, line, file );
   291     PR_DestroyCondVar( cvar->cvar );
   292     PR_DELETE( cvar );
   293 } /* --- end  pz_DestroyCondVar() --- */
   295 extern PRStatus
   296     pz_WaitCondVar(
   297         PZCondVar *cvar,
   298         PRIntervalTime timeout,
   299         char *file,
   300         PRIntn line
   301     )
   302 {
   303     PRStatus    rc;
   304     PRIntervalTime callTime;
   306     callTime = PR_IntervalNow();
   307     rc = PR_WaitCondVar( cvar->cvar, timeout );
   308     callTime = PR_IntervalNow() - callTime;
   310     Vtrace( WaitCondVar, cvar->ltype, callTime, 0, cvar, line, file );
   311     return(rc);
   312 } /* --- end  pz_WaitCondVar() --- */
   314 extern PRStatus
   315     pz_NotifyCondVar(
   316         PZCondVar *cvar,
   317         char *file,
   318         PRIntn line
   319     )
   320 {
   321     PRStatus    rc;
   323     rc = PR_NotifyCondVar( cvar->cvar );
   325     Vtrace( NotifyCondVar, cvar->ltype, 0, 0, cvar, line, file );
   326     return(rc);
   327 } /* --- end  pz_NotifyCondVar() --- */
   329 extern PRStatus
   330     pz_NotifyAllCondVar(
   331         PZCondVar *cvar,
   332         char *file,
   333         PRIntn line
   334     )
   335 {
   336     PRStatus    rc;
   338     rc = PR_NotifyAllCondVar( cvar->cvar );
   340     Vtrace( NotifyAllCondVar, cvar->ltype, 0, 0, cvar, line, file );
   341     return(rc);
   342 } /* --- end  pz_NotifyAllCondVar() --- */
   344 extern PZMonitor *
   345     pz_NewMonitor( 
   346         nssILockType ltype,
   347         char *file,
   348         PRIntn line
   349     )
   350 {
   351     PRStatus rc;
   352     PZMonitor   *mon;
   354     /* Self Initialize the nssILock feature */
   355     if (!nssILockInitialized)  {
   356         rc = PR_CallOnce( &coNssILock, nssILockInit );
   357         if ( PR_FAILURE == rc ) {
   358             PR_SetError( PR_UNKNOWN_ERROR, 0 );
   359             return( NULL );
   360         }
   361     }
   363     mon = PR_NEWZAP( PZMonitor );
   364     if ( NULL != mon )  {
   365         mon->ltype = ltype;
   366         mon->mon = PR_NewMonitor();
   367         if ( NULL == mon->mon )  {
   368             PR_DELETE( mon );
   369             PORT_SetError(SEC_ERROR_NO_MEMORY);
   370         }
   371     } else {
   372         PORT_SetError(SEC_ERROR_NO_MEMORY);
   373     }
   375     Vtrace( NewMonitor, ltype, 0, 0, mon, line, file );
   376     return(mon);
   377 } /* --- end  pz_NewMonitor() --- */
   379 extern void
   380     pz_DestroyMonitor(
   381         PZMonitor *mon,
   382         char *file,
   383         PRIntn line
   384     )
   385 {
   386     Vtrace( DestroyMonitor, mon->ltype, 0, 0, mon, line, file );
   387     PR_DestroyMonitor( mon->mon );
   388     PR_DELETE( mon );
   389     return;                
   390 } /* --- end  pz_DestroyMonitor() --- */
   392 extern void
   393     pz_EnterMonitor(
   394         PZMonitor *mon,
   395         char *file,
   396         PRIntn line
   397     )
   398 {
   399     PRIntervalTime callTime, now;
   401     callTime = PR_IntervalNow();
   402     PR_EnterMonitor( mon->mon );
   403     now = PR_IntervalNow();
   404     callTime = now - callTime;
   405     if ( PR_GetMonitorEntryCount(mon->mon) == 1 )  {
   406         mon->time = now;
   407     }
   408     Vtrace( EnterMonitor, mon->ltype, callTime, 0, mon, line, file );
   409     return;
   410 } /* --- end  pz_EnterMonitor() --- */
   412 extern PRStatus
   413     pz_ExitMonitor(
   414         PZMonitor *mon,
   415         char *file,
   416         PRIntn line
   417     )
   418 {
   419     PRStatus rc;
   420     PRIntervalTime callTime, now, heldTime;
   421     PRIntn  mec = PR_GetMonitorEntryCount( mon->mon );
   423     heldTime = (PRIntervalTime)-1; 
   424     callTime = PR_IntervalNow();
   425     rc = PR_ExitMonitor( mon->mon );
   426     now = PR_IntervalNow();
   427     callTime = now - callTime;
   428     if ( mec == 1 )
   429         heldTime = now - mon->time;
   430     Vtrace( ExitMonitor, mon->ltype, callTime, heldTime, mon, line, file );
   431     return( rc );
   432 } /* --- end  pz_ExitMonitor() --- */
   434 extern PRIntn
   435     pz_GetMonitorEntryCount(
   436         PZMonitor *mon,
   437         char *file,
   438         PRIntn line
   439     )
   440 {
   441     return( PR_GetMonitorEntryCount(mon->mon));
   442 } /* --- end pz_GetMonitorEntryCount() --- */
   445 extern PRStatus
   446     pz_Wait(
   447         PZMonitor *mon,
   448         PRIntervalTime ticks,
   449         char *file,
   450         PRIntn line
   451     )
   452 {
   453     PRStatus rc;
   454     PRIntervalTime callTime;
   456     callTime = PR_IntervalNow();
   457     rc = PR_Wait( mon->mon, ticks );
   458     callTime = PR_IntervalNow() - callTime;
   459     Vtrace( Wait, mon->ltype, callTime, 0, mon, line, file );
   460     return( rc );
   461 } /* --- end  pz_Wait() --- */
   463 extern PRStatus
   464     pz_Notify(
   465         PZMonitor *mon,
   466         char *file,
   467         PRIntn line
   468     )
   469 {
   470     PRStatus rc;
   471     PRIntervalTime callTime;
   473     callTime = PR_IntervalNow();
   474     rc = PR_Notify( mon->mon );
   475     callTime = PR_IntervalNow() - callTime;
   476     Vtrace( Notify, mon->ltype, callTime, 0, mon, line, file );
   477     return( rc );
   478 } /* --- end  pz_Notify() --- */
   480 extern PRStatus
   481     pz_NotifyAll(
   482         PZMonitor *mon,
   483         char *file,
   484         PRIntn line
   485     )
   486 {
   487     PRStatus rc;
   488     PRIntervalTime callTime;
   490     callTime = PR_IntervalNow();
   491     rc = PR_NotifyAll( mon->mon );
   492     callTime = PR_IntervalNow() - callTime;
   493     Vtrace( NotifyAll, mon->ltype, callTime, 0, mon, line, file );
   494     return( rc );
   495 } /* --- end  pz_NotifyAll() --- */
   497 #endif /* NEED_NSS_ILOCK */
   498 /* --- end nssilock.c --------------------------------- */

mercurial