📄 prcountr.c
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape Portable Runtime (NSPR). * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//*** prcountr.c -- NSPR Instrumentation Counters**** Implement the interface defined in prcountr.h**** Design Notes:**** The Counter Facility (CF) has a single anchor: qNameList. ** The anchor is a PRCList. qNameList is a list of links in QName** structures. From qNameList any QName structure and its** associated RName structure can be located. ** ** For each QName, a list of RName structures is anchored at** rnLink in the QName structure.** ** The counter itself is embedded in the RName structure.** ** For manipulating the counter database, single lock is used to** protect the entire list: counterLock.**** A PRCounterHandle, defined in prcountr.h, is really a pointer** to a RName structure. References by PRCounterHandle are** dead-reconed to the RName structure. The PRCounterHandle is** "overloaded" for traversing the QName structures; only the** function PR_FindNextQnameHandle() uses this overloading.**** ** ToDo (lth): decide on how to lock or atomically update** individual counters. Candidates are: the global lock; a lock** per RName structure; Atomic operations (Note that there are** not adaquate atomic operations (yet) to achieve this goal). At** this writing (6/19/98) , the update of the counter variable in** a QName structure is unprotected.***/#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)#include "prcountr.h"#include "prclist.h"#include "prlock.h"#include "prlog.h"#include "prmem.h"#include <string.h>/****/typedef struct QName{ PRCList link; PRCList rNameList; char name[PRCOUNTER_NAME_MAX+1];} QName;/****/typedef struct RName{ PRCList link; QName *qName; PRLock *lock; volatile PRUint32 counter; char name[PRCOUNTER_NAME_MAX+1]; char desc[PRCOUNTER_DESC_MAX+1]; } RName;/*** Define the Counter Facility database*/static PRLock *counterLock;static PRCList qNameList;static PRLogModuleInfo *lm;/*** _PR_CounterInitialize() -- Initialize the Counter Facility***/static void _PR_CounterInitialize( void ){ /* ** This function should be called only once */ PR_ASSERT( counterLock == NULL ); counterLock = PR_NewLock(); PR_INIT_CLIST( &qNameList ); lm = PR_NewLogModule("counters"); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Initialization complete")); return;} /* end _PR_CounterInitialize() *//*** PR_CreateCounter() -- Create a counter**** ValidateArguments** Lock** if (qName not already in database)** NewQname** if (rName already in database )** Assert** else NewRname** NewCounter** link 'em up** Unlock***/PR_IMPLEMENT(PRCounterHandle) PR_CreateCounter( const char *qName, const char *rName, const char *description ) { QName *qnp; RName *rnp; PRBool matchQname = PR_FALSE; /* Self initialize, if necessary */ if ( counterLock == NULL ) _PR_CounterInitialize(); /* Validate input arguments */ PR_ASSERT( strlen(qName) <= PRCOUNTER_NAME_MAX ); PR_ASSERT( strlen(rName) <= PRCOUNTER_NAME_MAX ); PR_ASSERT( strlen(description) <= PRCOUNTER_DESC_MAX ); /* Lock the Facility */ PR_Lock( counterLock ); /* Do we already have a matching QName? */ if (!PR_CLIST_IS_EMPTY( &qNameList )) { qnp = (QName *) PR_LIST_HEAD( &qNameList ); do { if ( strcmp(qnp->name, qName) == 0) { matchQname = PR_TRUE; break; } qnp = (QName *)PR_NEXT_LINK( &qnp->link ); } while( qnp != (QName *)PR_LIST_HEAD( &qNameList )); } /* ** If we did not find a matching QName, ** allocate one and initialize it. ** link it onto the qNameList. ** */ if ( matchQname != PR_TRUE ) { qnp = PR_NEWZAP( QName ); PR_ASSERT( qnp != NULL ); PR_INIT_CLIST( &qnp->link ); PR_INIT_CLIST( &qnp->rNameList ); strcpy( qnp->name, qName ); PR_APPEND_LINK( &qnp->link, &qNameList ); } /* Do we already have a matching RName? */ if (!PR_CLIST_IS_EMPTY( &qnp->rNameList )) { rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList ); do { /* ** No duplicate RNames are allowed within a QName ** */ PR_ASSERT( strcmp(rnp->name, rName)); rnp = (RName *)PR_NEXT_LINK( &rnp->link ); } while( rnp != (RName *)PR_LIST_HEAD( &qnp->rNameList )); } /* Get a new RName structure; initialize its members */ rnp = PR_NEWZAP( RName ); PR_ASSERT( rnp != NULL ); PR_INIT_CLIST( &rnp->link ); strcpy( rnp->name, rName ); strcpy( rnp->desc, description ); rnp->lock = PR_NewLock(); if ( rnp->lock == NULL ) { PR_ASSERT(0); } PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */ rnp->qName = qnp; /* point the RName to the QName */ /* Unlock the Facility */ PR_Unlock( counterLock ); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Create: QName: %s %p, RName: %s %p\n\t", qName, qnp, rName, rnp )); return((PRCounterHandle)rnp);} /* end PR_CreateCounter() */ /****/PR_IMPLEMENT(void) PR_DestroyCounter( PRCounterHandle handle ){ RName *rnp = (RName *)handle; QName *qnp = rnp->qName; PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting: QName: %s, RName: %s", qnp->name, rnp->name)); /* Lock the Facility */ PR_Lock( counterLock ); /* ** Remove RName from the list of RNames in QName ** and free RName */ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting RName: %s, %p", rnp->name, rnp)); PR_REMOVE_LINK( &rnp->link ); PR_Free( rnp->lock ); PR_DELETE( rnp ); /* ** If this is the last RName within QName ** remove QName from the qNameList and free it */ if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) ) { PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting unused QName: %s, %p", qnp->name, qnp)); PR_REMOVE_LINK( &qnp->link ); PR_DELETE( qnp ); } /* Unlock the Facility */ PR_Unlock( counterLock ); return;} /* end PR_DestroyCounter() *//****/PR_IMPLEMENT(PRCounterHandle) PR_GetCounterHandleFromName( const char *qName, const char *rName ){ const char *qn, *rn, *desc; PRCounterHandle qh, rh; RName *rnp = NULL; PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounterHandleFromName:\n\t" "QName: %s, RName: %s", qName, rName )); qh = PR_FindNextCounterQname( NULL ); while (qh != NULL) { rh = PR_FindNextCounterRname( NULL, qh ); while ( rh != NULL ) { PR_GetCounterNameFromHandle( rh, &qn, &rn, &desc ); if ( (strcmp( qName, qn ) == 0) && (strcmp( rName, rn ) == 0 )) { rnp = (RName *)rh; goto foundIt; } rh = PR_FindNextCounterRname( rh, qh ); } qh = PR_FindNextCounterQname( NULL ); }foundIt: PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp )); return(rh);} /* end PR_GetCounterHandleFromName() *//****/PR_IMPLEMENT(void) PR_GetCounterNameFromHandle( PRCounterHandle handle, const char **qName, const char **rName, const char **description ){ RName *rnp = (RName *)handle; QName *qnp = rnp->qName; *qName = qnp->name; *rName = rnp->name; *description = rnp->desc; PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterNameFromHandle: " "QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s", qnp, rnp, qnp->name, rnp->name, rnp->desc )); return;} /* end PR_GetCounterNameFromHandle() *//****/PR_IMPLEMENT(void) PR_IncrementCounter( PRCounterHandle handle){ PR_Lock(((RName *)handle)->lock); ((RName *)handle)->counter++; PR_Unlock(((RName *)handle)->lock); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Increment: %p, %ld", handle, ((RName *)handle)->counter )); return;} /* end PR_IncrementCounter() *//****/PR_IMPLEMENT(void) PR_DecrementCounter( PRCounterHandle handle){ PR_Lock(((RName *)handle)->lock); ((RName *)handle)->counter--; PR_Unlock(((RName *)handle)->lock); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Decrement: %p, %ld", handle, ((RName *)handle)->counter )); return;} /* end PR_DecrementCounter() *//****/PR_IMPLEMENT(void) PR_AddToCounter( PRCounterHandle handle, PRUint32 value ){ PR_Lock(((RName *)handle)->lock); ((RName *)handle)->counter += value; PR_Unlock(((RName *)handle)->lock); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: AddToCounter: %p, %ld", handle, ((RName *)handle)->counter )); return;} /* end PR_AddToCounter() *//****/PR_IMPLEMENT(void) PR_SubtractFromCounter( PRCounterHandle handle, PRUint32 value ){ PR_Lock(((RName *)handle)->lock); ((RName *)handle)->counter -= value; PR_Unlock(((RName *)handle)->lock); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SubtractFromCounter: %p, %ld", handle, ((RName *)handle)->counter )); return;} /* end PR_SubtractFromCounter() *//****/PR_IMPLEMENT(PRUint32) PR_GetCounter( PRCounterHandle handle ){ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounter: %p, %ld", handle, ((RName *)handle)->counter )); return(((RName *)handle)->counter);} /* end PR_GetCounter() *//****/PR_IMPLEMENT(void) PR_SetCounter( PRCounterHandle handle, PRUint32 value ){ ((RName *)handle)->counter = value; PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SetCounter: %p, %ld", handle, ((RName *)handle)->counter )); return;} /* end PR_SetCounter() *//****/PR_IMPLEMENT(PRCounterHandle) PR_FindNextCounterQname( PRCounterHandle handle){ QName *qnp = (QName *)handle; if ( PR_CLIST_IS_EMPTY( &qNameList )) qnp = NULL; else if ( qnp == NULL ) qnp = (QName *)PR_LIST_HEAD( &qNameList ); else if ( PR_NEXT_LINK( &qnp->link ) == &qNameList ) qnp = NULL; else qnp = (QName *)PR_NEXT_LINK( &qnp->link ); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextQname: Handle: %p, Returns: %p", handle, qnp )); return((PRCounterHandle)qnp);} /* end PR_FindNextCounterQname() *//****/PR_IMPLEMENT(PRCounterHandle) PR_FindNextCounterRname( PRCounterHandle rhandle, PRCounterHandle qhandle ){ RName *rnp = (RName *)rhandle; QName *qnp = (QName *)qhandle; if ( PR_CLIST_IS_EMPTY( &qnp->rNameList )) rnp = NULL; else if ( rnp == NULL ) rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList ); else if ( PR_NEXT_LINK( &rnp->link ) == &qnp->rNameList ) rnp = NULL; else rnp = (RName *)PR_NEXT_LINK( &rnp->link ); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p", rhandle, qhandle, rnp )); return((PRCounterHandle)rnp);} /* end PR_FindNextCounterRname() */#else /* !(defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)) *//*** NSPR Counters are not defined in this case*****//* Some compilers don't like an empty compilation unit. */static int dummy = 0;#endif /* defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -