Backed out 2 changesets (bug 1943998) for causing wd failures @ phases.py CLOSED...
[gecko.git] / nsprpub / pr / src / misc / prcountr.c
blobe16f6d85cabf3089d456471df33875de4d8ddb2c
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
11 ** Design Notes:
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.
18 ** For each QName, a list of RName structures is anchored at
19 ** rnLink in the QName structure.
21 ** The counter itself is embedded in the RName structure.
23 ** For manipulating the counter database, single lock is used to
24 ** protect the entire list: counterLock.
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.
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.
42 #include "prcountr.h"
43 #include "prclist.h"
44 #include "prlock.h"
45 #include "prlog.h"
46 #include "prmem.h"
47 #include <string.h>
52 typedef struct QName {
53 PRCList link;
54 PRCList rNameList;
55 char name[PRCOUNTER_NAME_MAX + 1];
56 } QName;
61 typedef struct RName {
62 PRCList link;
63 QName* qName;
64 PRLock* lock;
65 volatile PRUint32 counter;
66 char name[PRCOUNTER_NAME_MAX + 1];
67 char desc[PRCOUNTER_DESC_MAX + 1];
68 } RName;
71 ** Define the Counter Facility database
73 static PRLock* counterLock;
74 static PRCList qNameList;
75 static PRLogModuleInfo* lm;
78 ** _PR_CounterInitialize() -- Initialize the Counter Facility
81 static void _PR_CounterInitialize(void) {
83 ** This function should be called only once
85 PR_ASSERT(counterLock == NULL);
87 counterLock = PR_NewLock();
88 PR_INIT_CLIST(&qNameList);
89 lm = PR_NewLogModule("counters");
90 PR_LOG(lm, PR_LOG_DEBUG, ("PR_Counter: Initialization complete"));
92 return;
93 } /* end _PR_CounterInitialize() */
96 ** PR_CreateCounter() -- Create a counter
98 ** ValidateArguments
99 ** Lock
100 ** if (qName not already in database)
101 ** NewQname
102 ** if (rName already in database )
103 ** Assert
104 ** else NewRname
105 ** NewCounter
106 ** link 'em up
107 ** Unlock
110 PR_IMPLEMENT(PRCounterHandle)
111 PR_CreateCounter(const char* qName, const char* rName,
112 const char* description) {
113 QName* qnp;
114 RName* rnp;
115 PRBool matchQname = PR_FALSE;
117 /* Self initialize, if necessary */
118 if (counterLock == NULL) {
119 _PR_CounterInitialize();
122 /* Validate input arguments */
123 PR_ASSERT(strlen(qName) <= PRCOUNTER_NAME_MAX);
124 PR_ASSERT(strlen(rName) <= PRCOUNTER_NAME_MAX);
125 PR_ASSERT(strlen(description) <= PRCOUNTER_DESC_MAX);
127 /* Lock the Facility */
128 PR_Lock(counterLock);
130 /* Do we already have a matching QName? */
131 if (!PR_CLIST_IS_EMPTY(&qNameList)) {
132 qnp = (QName*)PR_LIST_HEAD(&qNameList);
133 do {
134 if (strcmp(qnp->name, qName) == 0) {
135 matchQname = PR_TRUE;
136 break;
138 qnp = (QName*)PR_NEXT_LINK(&qnp->link);
139 } while (qnp != (QName*)&qNameList);
142 ** If we did not find a matching QName,
143 ** allocate one and initialize it.
144 ** link it onto the qNameList.
147 if (matchQname != PR_TRUE) {
148 qnp = PR_NEWZAP(QName);
149 PR_ASSERT(qnp != NULL);
150 PR_INIT_CLIST(&qnp->link);
151 PR_INIT_CLIST(&qnp->rNameList);
152 strcpy(qnp->name, qName);
153 PR_APPEND_LINK(&qnp->link, &qNameList);
156 /* Do we already have a matching RName? */
157 if (!PR_CLIST_IS_EMPTY(&qnp->rNameList)) {
158 rnp = (RName*)PR_LIST_HEAD(&qnp->rNameList);
159 do {
161 ** No duplicate RNames are allowed within a QName
164 PR_ASSERT(strcmp(rnp->name, rName));
165 rnp = (RName*)PR_NEXT_LINK(&rnp->link);
166 } while (rnp != (RName*)&qnp->rNameList);
169 /* Get a new RName structure; initialize its members */
170 rnp = PR_NEWZAP(RName);
171 PR_ASSERT(rnp != NULL);
172 PR_INIT_CLIST(&rnp->link);
173 strcpy(rnp->name, rName);
174 strcpy(rnp->desc, description);
175 rnp->lock = PR_NewLock();
176 if (rnp->lock == NULL) {
177 PR_ASSERT(0);
180 PR_APPEND_LINK(&rnp->link, &qnp->rNameList); /* add RName to QName's rnList */
181 rnp->qName = qnp; /* point the RName to the QName */
183 /* Unlock the Facility */
184 PR_Unlock(counterLock);
185 PR_LOG(lm, PR_LOG_DEBUG,
186 ("PR_Counter: Create: QName: %s %p, RName: %s %p\n\t", qName, qnp,
187 rName, rnp));
189 return ((PRCounterHandle)rnp);
190 } /* end PR_CreateCounter() */
195 PR_IMPLEMENT(void)
196 PR_DestroyCounter(PRCounterHandle handle) {
197 RName* rnp = (RName*)handle;
198 QName* qnp = rnp->qName;
200 PR_LOG(lm, PR_LOG_DEBUG,
201 ("PR_Counter: Deleting: QName: %s, RName: %s", qnp->name, rnp->name));
203 /* Lock the Facility */
204 PR_Lock(counterLock);
207 ** Remove RName from the list of RNames in QName
208 ** and free RName
210 PR_LOG(lm, PR_LOG_DEBUG,
211 ("PR_Counter: Deleting RName: %s, %p", rnp->name, rnp));
212 PR_REMOVE_LINK(&rnp->link);
213 PR_Free(rnp->lock);
214 PR_DELETE(rnp);
217 ** If this is the last RName within QName
218 ** remove QName from the qNameList and free it
220 if (PR_CLIST_IS_EMPTY(&qnp->rNameList)) {
221 PR_LOG(lm, PR_LOG_DEBUG,
222 ("PR_Counter: Deleting unused QName: %s, %p", qnp->name, qnp));
223 PR_REMOVE_LINK(&qnp->link);
224 PR_DELETE(qnp);
227 /* Unlock the Facility */
228 PR_Unlock(counterLock);
229 return;
230 } /* end PR_DestroyCounter() */
235 PR_IMPLEMENT(PRCounterHandle)
236 PR_GetCounterHandleFromName(const char* qName, const char* rName) {
237 const char *qn, *rn, *desc;
238 PRCounterHandle qh, rh = NULL;
239 RName* rnp = NULL;
241 PR_LOG(lm, PR_LOG_DEBUG,
242 ("PR_Counter: GetCounterHandleFromName:\n\t"
243 "QName: %s, RName: %s",
244 qName, rName));
246 qh = PR_FindNextCounterQname(NULL);
247 while (qh != NULL) {
248 rh = PR_FindNextCounterRname(NULL, qh);
249 while (rh != NULL) {
250 PR_GetCounterNameFromHandle(rh, &qn, &rn, &desc);
251 if ((strcmp(qName, qn) == 0) && (strcmp(rName, rn) == 0)) {
252 rnp = (RName*)rh;
253 goto foundIt;
255 rh = PR_FindNextCounterRname(rh, qh);
257 qh = PR_FindNextCounterQname(NULL);
260 foundIt:
261 PR_LOG(lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp));
262 return (rh);
263 } /* end PR_GetCounterHandleFromName() */
268 PR_IMPLEMENT(void)
269 PR_GetCounterNameFromHandle(PRCounterHandle handle, const char** qName,
270 const char** rName, const char** description) {
271 RName* rnp = (RName*)handle;
272 QName* qnp = rnp->qName;
274 *qName = qnp->name;
275 *rName = rnp->name;
276 *description = rnp->desc;
278 PR_LOG(lm, PR_LOG_DEBUG,
279 ("PR_Counter: GetConterNameFromHandle: "
280 "QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s",
281 qnp, rnp, qnp->name, rnp->name, rnp->desc));
283 return;
284 } /* end PR_GetCounterNameFromHandle() */
289 PR_IMPLEMENT(void)
290 PR_IncrementCounter(PRCounterHandle handle) {
291 PR_Lock(((RName*)handle)->lock);
292 ((RName*)handle)->counter++;
293 PR_Unlock(((RName*)handle)->lock);
295 PR_LOG(lm, PR_LOG_DEBUG,
296 ("PR_Counter: Increment: %p, %ld", handle, ((RName*)handle)->counter));
298 return;
299 } /* end PR_IncrementCounter() */
304 PR_IMPLEMENT(void)
305 PR_DecrementCounter(PRCounterHandle handle) {
306 PR_Lock(((RName*)handle)->lock);
307 ((RName*)handle)->counter--;
308 PR_Unlock(((RName*)handle)->lock);
310 PR_LOG(lm, PR_LOG_DEBUG,
311 ("PR_Counter: Decrement: %p, %ld", handle, ((RName*)handle)->counter));
313 return;
314 } /* end PR_DecrementCounter() */
319 PR_IMPLEMENT(void)
320 PR_AddToCounter(PRCounterHandle handle, PRUint32 value) {
321 PR_Lock(((RName*)handle)->lock);
322 ((RName*)handle)->counter += value;
323 PR_Unlock(((RName*)handle)->lock);
325 PR_LOG(
326 lm, PR_LOG_DEBUG,
327 ("PR_Counter: AddToCounter: %p, %ld", handle, ((RName*)handle)->counter));
329 return;
330 } /* end PR_AddToCounter() */
335 PR_IMPLEMENT(void)
336 PR_SubtractFromCounter(PRCounterHandle handle, PRUint32 value) {
337 PR_Lock(((RName*)handle)->lock);
338 ((RName*)handle)->counter -= value;
339 PR_Unlock(((RName*)handle)->lock);
341 PR_LOG(lm, PR_LOG_DEBUG,
342 ("PR_Counter: SubtractFromCounter: %p, %ld", handle,
343 ((RName*)handle)->counter));
345 return;
346 } /* end PR_SubtractFromCounter() */
351 PR_IMPLEMENT(PRUint32)
352 PR_GetCounter(PRCounterHandle handle) {
353 PR_LOG(
354 lm, PR_LOG_DEBUG,
355 ("PR_Counter: GetCounter: %p, %ld", handle, ((RName*)handle)->counter));
357 return (((RName*)handle)->counter);
358 } /* end PR_GetCounter() */
363 PR_IMPLEMENT(void)
364 PR_SetCounter(PRCounterHandle handle, PRUint32 value) {
365 ((RName*)handle)->counter = value;
367 PR_LOG(
368 lm, PR_LOG_DEBUG,
369 ("PR_Counter: SetCounter: %p, %ld", handle, ((RName*)handle)->counter));
371 return;
372 } /* end PR_SetCounter() */
377 PR_IMPLEMENT(PRCounterHandle)
378 PR_FindNextCounterQname(PRCounterHandle handle) {
379 QName* qnp = (QName*)handle;
381 if (PR_CLIST_IS_EMPTY(&qNameList)) {
382 qnp = NULL;
383 } else if (qnp == NULL) {
384 qnp = (QName*)PR_LIST_HEAD(&qNameList);
385 } else if (PR_NEXT_LINK(&qnp->link) == &qNameList) {
386 qnp = NULL;
387 } else {
388 qnp = (QName*)PR_NEXT_LINK(&qnp->link);
391 PR_LOG(lm, PR_LOG_DEBUG,
392 ("PR_Counter: FindNextQname: Handle: %p, Returns: %p", handle, qnp));
394 return ((PRCounterHandle)qnp);
395 } /* end PR_FindNextCounterQname() */
400 PR_IMPLEMENT(PRCounterHandle)
401 PR_FindNextCounterRname(PRCounterHandle rhandle, PRCounterHandle qhandle) {
402 RName* rnp = (RName*)rhandle;
403 QName* qnp = (QName*)qhandle;
405 if (PR_CLIST_IS_EMPTY(&qnp->rNameList)) {
406 rnp = NULL;
407 } else if (rnp == NULL) {
408 rnp = (RName*)PR_LIST_HEAD(&qnp->rNameList);
409 } else if (PR_NEXT_LINK(&rnp->link) == &qnp->rNameList) {
410 rnp = NULL;
411 } else {
412 rnp = (RName*)PR_NEXT_LINK(&rnp->link);
415 PR_LOG(lm, PR_LOG_DEBUG,
416 ("PR_Counter: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p",
417 rhandle, qhandle, rnp));
419 return ((PRCounterHandle)rnp);
420 } /* end PR_FindNextCounterRname() */