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.

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

mercurial