| OLD | NEW |
| (Empty) |
| 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/. */ | |
| 5 | |
| 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 */ | |
| 41 | |
| 42 #include "prcountr.h" | |
| 43 #include "prclist.h" | |
| 44 #include "prlock.h" | |
| 45 #include "prlog.h" | |
| 46 #include "prmem.h" | |
| 47 #include <string.h> | |
| 48 | |
| 49 /* | |
| 50 ** | |
| 51 */ | |
| 52 typedef struct QName | |
| 53 { | |
| 54 PRCList link; | |
| 55 PRCList rNameList; | |
| 56 char name[PRCOUNTER_NAME_MAX+1]; | |
| 57 } QName; | |
| 58 | |
| 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; | |
| 71 | |
| 72 | |
| 73 /* | |
| 74 ** Define the Counter Facility database | |
| 75 */ | |
| 76 static PRLock *counterLock; | |
| 77 static PRCList qNameList; | |
| 78 static PRLogModuleInfo *lm; | |
| 79 | |
| 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 ); | |
| 90 | |
| 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")); | |
| 95 | |
| 96 return; | |
| 97 } /* end _PR_CounterInitialize() */ | |
| 98 | |
| 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; | |
| 124 | |
| 125 /* Self initialize, if necessary */ | |
| 126 if ( counterLock == NULL ) | |
| 127 _PR_CounterInitialize(); | |
| 128 | |
| 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 ); | |
| 133 | |
| 134 /* Lock the Facility */ | |
| 135 PR_Lock( counterLock ); | |
| 136 | |
| 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 } | |
| 165 | |
| 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 } | |
| 179 | |
| 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 } | |
| 191 | |
| 192 PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnLis
t */ | |
| 193 rnp->qName = qnp; /* point the RName to the QName */ | |
| 194 | |
| 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 )); | |
| 199 | |
| 200 return((PRCounterHandle)rnp); | |
| 201 } /* end PR_CreateCounter() */ | |
| 202 | |
| 203 | |
| 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; | |
| 214 | |
| 215 PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting: QName: %s, RName: %s", | |
| 216 qnp->name, rnp->name)); | |
| 217 | |
| 218 /* Lock the Facility */ | |
| 219 PR_Lock( counterLock ); | |
| 220 | |
| 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 ); | |
| 230 | |
| 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 } | |
| 242 | |
| 243 /* Unlock the Facility */ | |
| 244 PR_Unlock( counterLock ); | |
| 245 return; | |
| 246 } /* end PR_DestroyCounter() */ | |
| 247 | |
| 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; | |
| 260 | |
| 261 PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounterHandleFromName:\n\t" | |
| 262 "QName: %s, RName: %s", qName, rName )); | |
| 263 | |
| 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 } | |
| 281 | |
| 282 foundIt: | |
| 283 PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp ))
; | |
| 284 return(rh); | |
| 285 } /* end PR_GetCounterHandleFromName() */ | |
| 286 | |
| 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; | |
| 300 | |
| 301 *qName = qnp->name; | |
| 302 *rName = rnp->name; | |
| 303 *description = rnp->desc; | |
| 304 | |
| 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 )); | |
| 308 | |
| 309 return; | |
| 310 } /* end PR_GetCounterNameFromHandle() */ | |
| 311 | |
| 312 | |
| 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); | |
| 324 | |
| 325 PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Increment: %p, %ld", | |
| 326 handle, ((RName *)handle)->counter )); | |
| 327 | |
| 328 return; | |
| 329 } /* end PR_IncrementCounter() */ | |
| 330 | |
| 331 | |
| 332 | |
| 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); | |
| 344 | |
| 345 PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Decrement: %p, %ld", | |
| 346 handle, ((RName *)handle)->counter )); | |
| 347 | |
| 348 return; | |
| 349 } /* end PR_DecrementCounter() */ | |
| 350 | |
| 351 | |
| 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); | |
| 364 | |
| 365 PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: AddToCounter: %p, %ld", | |
| 366 handle, ((RName *)handle)->counter )); | |
| 367 | |
| 368 return; | |
| 369 } /* end PR_AddToCounter() */ | |
| 370 | |
| 371 | |
| 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); | |
| 384 | |
| 385 PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SubtractFromCounter: %p, %ld", | |
| 386 handle, ((RName *)handle)->counter )); | |
| 387 | |
| 388 return; | |
| 389 } /* end PR_SubtractFromCounter() */ | |
| 390 | |
| 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 )); | |
| 401 | |
| 402 return(((RName *)handle)->counter); | |
| 403 } /* end PR_GetCounter() */ | |
| 404 | |
| 405 /* | |
| 406 ** | |
| 407 */ | |
| 408 PR_IMPLEMENT(void) | |
| 409 PR_SetCounter( | |
| 410 PRCounterHandle handle, | |
| 411 PRUint32 value | |
| 412 ) | |
| 413 { | |
| 414 ((RName *)handle)->counter = value; | |
| 415 | |
| 416 PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SetCounter: %p, %ld", | |
| 417 handle, ((RName *)handle)->counter )); | |
| 418 | |
| 419 return; | |
| 420 } /* end PR_SetCounter() */ | |
| 421 | |
| 422 /* | |
| 423 ** | |
| 424 */ | |
| 425 PR_IMPLEMENT(PRCounterHandle) | |
| 426 PR_FindNextCounterQname( | |
| 427 PRCounterHandle handle | |
| 428 ) | |
| 429 { | |
| 430 QName *qnp = (QName *)handle; | |
| 431 | |
| 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 ); | |
| 440 | |
| 441 PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextQname: Handle: %p, Returns:
%p", | |
| 442 handle, qnp )); | |
| 443 | |
| 444 return((PRCounterHandle)qnp); | |
| 445 } /* end PR_FindNextCounterQname() */ | |
| 446 | |
| 447 | |
| 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; | |
| 459 | |
| 460 | |
| 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 ); | |
| 469 | |
| 470 PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextRname: Rhandle: %p, QHandle:
%p, Returns: %p", | |
| 471 rhandle, qhandle, rnp )); | |
| 472 | |
| 473 return((PRCounterHandle)rnp); | |
| 474 } /* end PR_FindNextCounterRname() */ | |
| OLD | NEW |