nsprpub/pr/src/misc/prcountr.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 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     7 ** prcountr.c -- NSPR Instrumentation Counters
     8 **
     9 ** Implement the interface defined in prcountr.h
    10 **
    11 ** Design Notes:
    12 **
    13 ** The Counter Facility (CF) has a single anchor: qNameList.      
    14 ** The anchor is a PRCList. qNameList is a list of links in QName
    15 ** structures. From qNameList any QName structure and its
    16 ** associated RName structure can be located. 
    17 ** 
    18 ** For each QName, a list of RName structures is anchored at
    19 ** rnLink in the QName structure.
    20 ** 
    21 ** The counter itself is embedded in the RName structure.
    22 ** 
    23 ** For manipulating the counter database, single lock is used to
    24 ** protect the entire list: counterLock.
    25 **
    26 ** A PRCounterHandle, defined in prcountr.h, is really a pointer
    27 ** to a RName structure. References by PRCounterHandle are
    28 ** dead-reconed to the RName structure. The PRCounterHandle is
    29 ** "overloaded" for traversing the QName structures; only the
    30 ** function PR_FindNextQnameHandle() uses this overloading.
    31 **
    32 ** 
    33 ** ToDo (lth): decide on how to lock or atomically update
    34 ** individual counters. Candidates are: the global lock; a lock
    35 ** per RName structure; Atomic operations (Note that there are
    36 ** not adaquate atomic operations (yet) to achieve this goal). At
    37 ** this writing (6/19/98) , the update of the counter variable in
    38 ** a QName structure is unprotected.
    39 **
    40 */
    42 #include "prcountr.h"
    43 #include "prclist.h"
    44 #include "prlock.h"
    45 #include "prlog.h"
    46 #include "prmem.h"
    47 #include <string.h>
    49 /*
    50 **
    51 */
    52 typedef struct QName
    53 {
    54     PRCList link;
    55     PRCList rNameList;
    56     char    name[PRCOUNTER_NAME_MAX+1];
    57 } QName;
    59 /*
    60 **
    61 */
    62 typedef struct RName
    63 {
    64     PRCList link;
    65     QName   *qName;
    66     PRLock  *lock;
    67     volatile PRUint32   counter;    
    68     char    name[PRCOUNTER_NAME_MAX+1]; 
    69     char    desc[PRCOUNTER_DESC_MAX+1]; 
    70 } RName;
    73 /*
    74 ** Define the Counter Facility database
    75 */
    76 static PRLock  *counterLock;
    77 static PRCList qNameList;
    78 static PRLogModuleInfo *lm;
    80 /*
    81 ** _PR_CounterInitialize() -- Initialize the Counter Facility
    82 **
    83 */
    84 static void _PR_CounterInitialize( void )
    85 {
    86     /*
    87     ** This function should be called only once
    88     */
    89     PR_ASSERT( counterLock == NULL );
    91     counterLock = PR_NewLock();
    92     PR_INIT_CLIST( &qNameList );
    93     lm = PR_NewLogModule("counters");
    94     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Initialization complete"));
    96     return;
    97 } /* end _PR_CounterInitialize() */
    99 /*
   100 ** PR_CreateCounter() -- Create a counter
   101 **
   102 **  ValidateArguments
   103 **  Lock
   104 **  if (qName not already in database)
   105 **      NewQname
   106 **  if (rName already in database )
   107 **      Assert
   108 **  else NewRname
   109 **  NewCounter
   110 **  link 'em up
   111 **  Unlock
   112 **
   113 */
   114 PR_IMPLEMENT(PRCounterHandle) 
   115 	PR_CreateCounter( 
   116 		const char *qName, 
   117     	const char *rName, 
   118         const char *description 
   119 ) 
   120 {
   121     QName   *qnp;
   122     RName   *rnp;
   123     PRBool  matchQname = PR_FALSE;
   125     /* Self initialize, if necessary */
   126     if ( counterLock == NULL )
   127         _PR_CounterInitialize();
   129     /* Validate input arguments */
   130     PR_ASSERT( strlen(qName) <= PRCOUNTER_NAME_MAX );
   131     PR_ASSERT( strlen(rName) <= PRCOUNTER_NAME_MAX );
   132     PR_ASSERT( strlen(description) <= PRCOUNTER_DESC_MAX );
   134     /* Lock the Facility */
   135     PR_Lock( counterLock );
   137     /* Do we already have a matching QName? */
   138     if (!PR_CLIST_IS_EMPTY( &qNameList ))
   139     {
   140         qnp = (QName *) PR_LIST_HEAD( &qNameList );
   141         do {
   142             if ( strcmp(qnp->name, qName) == 0)
   143             {
   144                 matchQname = PR_TRUE;
   145                 break;
   146             }
   147             qnp = (QName *)PR_NEXT_LINK( &qnp->link );
   148         } while( qnp != (QName *)&qNameList );
   149     }
   150     /*
   151     ** If we did not find a matching QName,
   152     **    allocate one and initialize it.
   153     **    link it onto the qNameList.
   154     **
   155     */
   156     if ( matchQname != PR_TRUE )
   157     {
   158         qnp = PR_NEWZAP( QName );
   159         PR_ASSERT( qnp != NULL );
   160         PR_INIT_CLIST( &qnp->link ); 
   161         PR_INIT_CLIST( &qnp->rNameList ); 
   162         strcpy( qnp->name, qName );
   163         PR_APPEND_LINK( &qnp->link, &qNameList ); 
   164     }
   166     /* Do we already have a matching RName? */
   167     if (!PR_CLIST_IS_EMPTY( &qnp->rNameList ))
   168     {
   169         rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList );
   170         do {
   171             /*
   172             ** No duplicate RNames are allowed within a QName
   173             **
   174             */
   175             PR_ASSERT( strcmp(rnp->name, rName));
   176             rnp = (RName *)PR_NEXT_LINK( &rnp->link );
   177         } while( rnp != (RName *)&qnp->rNameList );
   178     }
   180     /* Get a new RName structure; initialize its members */
   181     rnp = PR_NEWZAP( RName );
   182     PR_ASSERT( rnp != NULL );
   183     PR_INIT_CLIST( &rnp->link );
   184     strcpy( rnp->name, rName );
   185     strcpy( rnp->desc, description );
   186     rnp->lock = PR_NewLock();
   187     if ( rnp->lock == NULL )
   188     {
   189         PR_ASSERT(0);
   190     }
   192     PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */    
   193     rnp->qName = qnp;                       /* point the RName to the QName */
   195     /* Unlock the Facility */
   196     PR_Unlock( counterLock );
   197     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Create: QName: %s %p, RName: %s %p\n\t",
   198         qName, qnp, rName, rnp ));
   200     return((PRCounterHandle)rnp);
   201 } /*  end PR_CreateCounter() */
   204 /*
   205 **
   206 */
   207 PR_IMPLEMENT(void) 
   208 	PR_DestroyCounter( 
   209 		PRCounterHandle handle 
   210 )
   211 {
   212     RName   *rnp = (RName *)handle;
   213     QName   *qnp = rnp->qName;
   215     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting: QName: %s, RName: %s", 
   216         qnp->name, rnp->name));
   218     /* Lock the Facility */
   219     PR_Lock( counterLock );
   221     /*
   222     ** Remove RName from the list of RNames in QName
   223     ** and free RName
   224     */
   225     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting RName: %s, %p", 
   226         rnp->name, rnp));
   227     PR_REMOVE_LINK( &rnp->link );
   228     PR_Free( rnp->lock );
   229     PR_DELETE( rnp );
   231     /*
   232     ** If this is the last RName within QName
   233     **   remove QName from the qNameList and free it
   234     */
   235     if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) )
   236     {
   237         PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting unused QName: %s, %p", 
   238             qnp->name, qnp));
   239         PR_REMOVE_LINK( &qnp->link );
   240         PR_DELETE( qnp );
   241     } 
   243     /* Unlock the Facility */
   244     PR_Unlock( counterLock );
   245     return;
   246 } /*  end PR_DestroyCounter() */
   248 /*
   249 **
   250 */
   251 PR_IMPLEMENT(PRCounterHandle) 
   252 	PR_GetCounterHandleFromName( 
   253     	const char *qName, 
   254     	const char *rName 
   255 )
   256 {
   257     const char    *qn, *rn, *desc;
   258     PRCounterHandle     qh, rh = NULL;
   259     RName   *rnp = NULL;
   261     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounterHandleFromName:\n\t"
   262         "QName: %s, RName: %s", qName, rName ));
   264     qh = PR_FindNextCounterQname( NULL );
   265     while (qh != NULL)
   266     {
   267         rh = PR_FindNextCounterRname( NULL, qh );
   268         while ( rh != NULL )
   269         {
   270             PR_GetCounterNameFromHandle( rh, &qn, &rn, &desc );
   271             if ( (strcmp( qName, qn ) == 0)
   272                 && (strcmp( rName, rn ) == 0 ))
   273             {
   274                 rnp = (RName *)rh;
   275                 goto foundIt;
   276             }
   277             rh = PR_FindNextCounterRname( rh, qh );
   278         }
   279         qh = PR_FindNextCounterQname( NULL );
   280     }
   282 foundIt:
   283     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp ));
   284     return(rh);
   285 } /*  end PR_GetCounterHandleFromName() */
   287 /*
   288 **
   289 */
   290 PR_IMPLEMENT(void) 
   291 	PR_GetCounterNameFromHandle( 
   292     	PRCounterHandle handle,  
   293 	    const char **qName, 
   294 	    const char **rName, 
   295 		const char **description 
   296 )
   297 {
   298     RName   *rnp = (RName *)handle;
   299     QName   *qnp = rnp->qName;
   301     *qName = qnp->name;
   302     *rName = rnp->name;
   303     *description = rnp->desc;
   305     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterNameFromHandle: "
   306         "QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s", 
   307         qnp, rnp, qnp->name, rnp->name, rnp->desc ));
   309     return;
   310 } /*  end PR_GetCounterNameFromHandle() */
   313 /*
   314 **
   315 */
   316 PR_IMPLEMENT(void) 
   317 	PR_IncrementCounter( 
   318 		PRCounterHandle handle
   319 )
   320 {
   321     PR_Lock(((RName *)handle)->lock);
   322     ((RName *)handle)->counter++;
   323     PR_Unlock(((RName *)handle)->lock);
   325     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Increment: %p, %ld", 
   326         handle, ((RName *)handle)->counter ));
   328     return;
   329 } /*  end PR_IncrementCounter() */
   333 /*
   334 **
   335 */
   336 PR_IMPLEMENT(void) 
   337 	PR_DecrementCounter( 
   338 		PRCounterHandle handle
   339 )
   340 {
   341     PR_Lock(((RName *)handle)->lock);
   342     ((RName *)handle)->counter--;
   343     PR_Unlock(((RName *)handle)->lock);
   345     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Decrement: %p, %ld", 
   346         handle, ((RName *)handle)->counter ));
   348     return;
   349 } /*  end PR_DecrementCounter()  */
   352 /*
   353 **
   354 */
   355 PR_IMPLEMENT(void) 
   356 	PR_AddToCounter( 
   357     	PRCounterHandle handle, 
   358 	    PRUint32 value 
   359 )
   360 {
   361     PR_Lock(((RName *)handle)->lock);
   362     ((RName *)handle)->counter += value;
   363     PR_Unlock(((RName *)handle)->lock);
   365     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: AddToCounter: %p, %ld", 
   366         handle, ((RName *)handle)->counter ));
   368     return;
   369 } /*  end PR_AddToCounter() */
   372 /*
   373 **
   374 */
   375 PR_IMPLEMENT(void) 
   376 	PR_SubtractFromCounter( 
   377     	PRCounterHandle handle, 
   378 	    PRUint32 value 
   379 )
   380 {
   381     PR_Lock(((RName *)handle)->lock);
   382     ((RName *)handle)->counter -= value;
   383     PR_Unlock(((RName *)handle)->lock);
   385     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SubtractFromCounter: %p, %ld", 
   386         handle, ((RName *)handle)->counter ));
   388     return;
   389 } /*  end  PR_SubtractFromCounter() */
   391 /*
   392 **
   393 */
   394 PR_IMPLEMENT(PRUint32) 
   395 	PR_GetCounter( 
   396 		PRCounterHandle handle 
   397 )
   398 {
   399     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounter: %p, %ld", 
   400         handle, ((RName *)handle)->counter ));
   402     return(((RName *)handle)->counter);
   403 } /*  end  PR_GetCounter() */
   405 /*
   406 **
   407 */
   408 PR_IMPLEMENT(void) 
   409 	PR_SetCounter( 
   410 		PRCounterHandle handle, 
   411 		PRUint32 value 
   412 )
   413 {
   414     ((RName *)handle)->counter = value;
   416     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SetCounter: %p, %ld", 
   417         handle, ((RName *)handle)->counter ));
   419     return;
   420 } /*  end  PR_SetCounter() */
   422 /*
   423 **
   424 */
   425 PR_IMPLEMENT(PRCounterHandle) 
   426 	PR_FindNextCounterQname( 
   427         PRCounterHandle handle
   428 )
   429 {
   430     QName *qnp = (QName *)handle;
   432     if ( PR_CLIST_IS_EMPTY( &qNameList ))
   433             qnp = NULL;
   434     else if ( qnp == NULL )
   435         qnp = (QName *)PR_LIST_HEAD( &qNameList );
   436     else if ( PR_NEXT_LINK( &qnp->link ) ==  &qNameList )
   437         qnp = NULL;
   438     else  
   439         qnp = (QName *)PR_NEXT_LINK( &qnp->link );
   441     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextQname: Handle: %p, Returns: %p", 
   442         handle, qnp ));
   444     return((PRCounterHandle)qnp);
   445 } /*  end  PR_FindNextCounterQname() */
   448 /*
   449 **
   450 */
   451 PR_IMPLEMENT(PRCounterHandle) 
   452 	PR_FindNextCounterRname( 
   453         PRCounterHandle rhandle, 
   454         PRCounterHandle qhandle 
   455 )
   456 {
   457     RName *rnp = (RName *)rhandle;
   458     QName *qnp = (QName *)qhandle;
   461     if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ))
   462         rnp = NULL;
   463     else if ( rnp == NULL )
   464         rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList );
   465     else if ( PR_NEXT_LINK( &rnp->link ) ==  &qnp->rNameList )
   466         rnp = NULL;
   467     else
   468         rnp = (RName *)PR_NEXT_LINK( &rnp->link );
   470     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p", 
   471         rhandle, qhandle, rnp ));
   473     return((PRCounterHandle)rnp);
   474 } /*  end PR_FindNextCounterRname() */

mercurial