backout 29799f914cab, Bug 917642 - [Helix] Please update the helix blobs
[gecko.git] / nsprpub / pr / tests / instrumt.c
blob21fb84941fc26c965450fb9bb67c57da79dec1fd
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 ** File: instrumt.c
8 ** Description: This test is for the NSPR debug aids defined in
9 ** prcountr.h, prtrace.h, prolock.h
11 ** The test case tests the three debug aids in NSPR:
13 ** Diagnostic messages can be enabled using "instrumt -v 6"
14 ** This sets the msgLevel to something that PR_LOG() likes.
15 ** Also define in the environment "NSPR_LOG_MODULES=Test:6"
17 ** CounterTest() tests the counter facility. This test
18 ** creates 4 threads. Each thread either increments, decrements,
19 ** adds to or subtracts from a counter, depending on an argument
20 ** passed to the thread at thread-create time. Each of these threads
21 ** does COUNT_LIMIT iterations doing its thing. When all 4 threads
22 ** are done, the result of the counter is evaluated. If all was atomic,
23 ** the the value of the counter should be zero.
25 ** TraceTest():
26 ** This test mingles with the counter test. Counters trace.
27 ** A thread to extract trace entries on the fly is started.
28 ** A thread to dump trace entries to a file is started.
30 ** OrderedLockTest():
38 #include <stdio.h>
39 #include <plstr.h>
40 #include <prclist.h>
41 #include <prmem.h>
42 #include <plgetopt.h>
43 #include <prlog.h>
44 #include <prmon.h>
45 #include <pratom.h>
46 #include <prtrace.h>
47 #include <prcountr.h>
48 #include <prolock.h>
50 #define COUNT_LIMIT (10 * ( 1024))
52 #define SMALL_TRACE_BUFSIZE ( 60 * 1024 )
54 typedef enum
56 CountLoop = 1,
57 TraceLoop = 2,
58 TraceFlow = 3
59 } TraceTypes;
62 PRLogModuleLevel msgLevel = PR_LOG_ALWAYS;
64 PRBool help = PR_FALSE;
65 PRBool failed = PR_FALSE;
68 PRLogModuleInfo *lm;
69 PRMonitor *mon;
70 PRInt32 activeThreads = 0;
71 PR_DEFINE_COUNTER( hCounter );
72 PR_DEFINE_TRACE( hTrace );
74 static void Help(void)
76 printf("Help? ... Ha!\n");
79 static void ListCounters(void)
81 PR_DEFINE_COUNTER( qh );
82 PR_DEFINE_COUNTER( rh );
83 const char *qn, *rn, *dn;
84 const char **qname = &qn, **rname = &rn, **desc = &dn;
85 PRUint32 tCtr;
87 PR_INIT_COUNTER_HANDLE( qh, NULL );
88 PR_FIND_NEXT_COUNTER_QNAME(qh, qh );
89 while ( qh != NULL )
91 PR_INIT_COUNTER_HANDLE( rh, NULL );
92 PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh );
93 while ( rh != NULL )
95 PR_GET_COUNTER_NAME_FROM_HANDLE( rh, qname, rname, desc );
96 tCtr = PR_GET_COUNTER(tCtr, rh);
97 PR_LOG( lm, msgLevel,
98 ( "QName: %s RName: %s Desc: %s Value: %ld\n",
99 qn, rn, dn, tCtr ));
100 PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh );
102 PR_FIND_NEXT_COUNTER_QNAME(qh, qh);
104 return;
105 } /* end ListCounters() */
107 static void ListTraces(void)
109 PR_DEFINE_TRACE( qh );
110 PR_DEFINE_TRACE( rh );
111 const char *qn, *rn, *dn;
112 const char **qname = &qn, **rname = &rn, **desc = &dn;
114 PR_INIT_TRACE_HANDLE( qh, NULL );
115 PR_FIND_NEXT_TRACE_QNAME(qh, qh );
116 while ( qh != NULL )
118 PR_INIT_TRACE_HANDLE( rh, NULL );
119 PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh );
120 while ( rh != NULL )
122 PR_GET_TRACE_NAME_FROM_HANDLE( rh, qname, rname, desc );
123 PR_LOG( lm, msgLevel,
124 ( "QName: %s RName: %s Desc: %s",
125 qn, rn, dn ));
126 PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh );
128 PR_FIND_NEXT_TRACE_QNAME(qh, qh);
130 return;
131 } /* end ListCounters() */
134 static PRInt32 one = 1;
135 static PRInt32 two = 2;
136 static PRInt32 three = 3;
137 static PRInt32 four = 4;
140 ** Thread to iteratively count something.
142 static void PR_CALLBACK CountSomething( void *arg )
144 PRInt32 switchVar = *((PRInt32 *)arg);
145 PRInt32 i;
147 PR_LOG( lm, msgLevel,
148 ("CountSomething: begin thread %ld", switchVar ));
150 for ( i = 0; i < COUNT_LIMIT ; i++)
152 switch ( switchVar )
154 case 1 :
155 PR_INCREMENT_COUNTER( hCounter );
156 break;
157 case 2 :
158 PR_DECREMENT_COUNTER( hCounter );
159 break;
160 case 3 :
161 PR_ADD_TO_COUNTER( hCounter, 1 );
162 break;
163 case 4 :
164 PR_SUBTRACT_FROM_COUNTER( hCounter, 1 );
165 break;
166 default :
167 PR_ASSERT( 0 );
168 break;
170 PR_TRACE( hTrace, CountLoop, switchVar, i, 0, 0, 0, 0, 0 );
171 } /* end for() */
173 PR_LOG( lm, msgLevel,
174 ("CounterSomething: end thread %ld", switchVar ));
176 PR_EnterMonitor(mon);
177 --activeThreads;
178 PR_Notify( mon );
179 PR_ExitMonitor(mon);
181 return;
182 } /* end CountSomething() */
185 ** Create the counter threads.
187 static void CounterTest( void )
189 PRThread *t1, *t2, *t3, *t4;
190 PRIntn i = 0;
191 PR_DEFINE_COUNTER( tc );
192 PR_DEFINE_COUNTER( zCounter );
194 PR_LOG( lm, msgLevel,
195 ("Begin CounterTest"));
198 ** Test Get and Set of a counter.
201 PR_CREATE_COUNTER( zCounter, "Atomic", "get/set test", "test get and set of counter" );
202 PR_SET_COUNTER( zCounter, 9 );
203 PR_GET_COUNTER( i, zCounter );
204 if ( i != 9 )
206 failed = PR_TRUE;
207 PR_LOG( lm, msgLevel,
208 ("Counter set/get failed"));
211 activeThreads += 4;
212 PR_CREATE_COUNTER( hCounter, "Atomic", "SMP Tests", "test atomic nature of counter" );
214 PR_GET_COUNTER_HANDLE_FROM_NAME( tc, "Atomic", "SMP Tests" );
215 PR_ASSERT( tc == hCounter );
217 t1 = PR_CreateThread(PR_USER_THREAD,
218 CountSomething, &one,
219 PR_PRIORITY_NORMAL,
220 PR_GLOBAL_THREAD,
221 PR_UNJOINABLE_THREAD,
223 PR_ASSERT(t1);
225 t2 = PR_CreateThread(PR_USER_THREAD,
226 CountSomething, &two,
227 PR_PRIORITY_NORMAL,
228 PR_GLOBAL_THREAD,
229 PR_UNJOINABLE_THREAD,
231 PR_ASSERT(t2);
233 t3 = PR_CreateThread(PR_USER_THREAD,
234 CountSomething, &three,
235 PR_PRIORITY_NORMAL,
236 PR_GLOBAL_THREAD,
237 PR_UNJOINABLE_THREAD,
239 PR_ASSERT(t3);
241 t4 = PR_CreateThread(PR_USER_THREAD,
242 CountSomething, &four,
243 PR_PRIORITY_NORMAL,
244 PR_GLOBAL_THREAD,
245 PR_UNJOINABLE_THREAD,
247 PR_ASSERT(t4);
249 PR_LOG( lm, msgLevel,
250 ("Counter Threads started"));
252 ListCounters();
253 return;
254 } /* end CounterTest() */
257 ** Thread to dump trace buffer to a file.
259 static void PR_CALLBACK RecordTrace(void *arg )
261 PR_RECORD_TRACE_ENTRIES();
263 PR_EnterMonitor(mon);
264 --activeThreads;
265 PR_Notify( mon );
266 PR_ExitMonitor(mon);
268 return;
269 } /* end RecordTrace() */
273 #define NUM_TRACE_RECORDS ( 10000 )
275 ** Thread to extract and print trace entries from the buffer.
277 static void PR_CALLBACK SampleTrace( void *arg )
279 #if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
280 PRInt32 found, rc;
281 PRTraceEntry *foundEntries;
282 PRInt32 i;
284 foundEntries = (PRTraceEntry *)PR_Malloc( NUM_TRACE_RECORDS * sizeof(PRTraceEntry));
285 PR_ASSERT(foundEntries != NULL );
289 rc = PR_GetTraceEntries( foundEntries, NUM_TRACE_RECORDS, &found);
290 PR_LOG( lm, msgLevel,
291 ("SampleTrace: Lost Data: %ld found: %ld", rc, found ));
293 if ( found != 0)
295 for ( i = 0 ; i < found; i++ )
297 PR_LOG( lm, msgLevel,
298 ("SampleTrace, detail: Thread: %p, Time: %llX, UD0: %ld, UD1: %ld, UD2: %8.8ld",
299 (foundEntries +i)->thread,
300 (foundEntries +i)->time,
301 (foundEntries +i)->userData[0],
302 (foundEntries +i)->userData[1],
303 (foundEntries +i)->userData[2] ));
306 PR_Sleep(PR_MillisecondsToInterval(50));
308 while( found != 0 && activeThreads >= 1 );
310 PR_Free( foundEntries );
312 PR_EnterMonitor(mon);
313 --activeThreads;
314 PR_Notify( mon );
315 PR_ExitMonitor(mon);
317 PR_LOG( lm, msgLevel,
318 ("SampleTrace(): exiting"));
320 #endif
321 return;
322 } /* end RecordTrace() */
325 ** Basic trace test.
327 static void TraceTest( void )
329 PRInt32 i;
330 PRInt32 size;
331 PR_DEFINE_TRACE( th );
332 PRThread *t1, *t2;
334 PR_LOG( lm, msgLevel,
335 ("Begin TraceTest"));
337 size = SMALL_TRACE_BUFSIZE;
338 PR_SET_TRACE_OPTION( PRTraceBufSize, &size );
339 PR_GET_TRACE_OPTION( PRTraceBufSize, &i );
341 PR_CREATE_TRACE( th, "TraceTest", "tt2", "A description for the trace test" );
342 PR_CREATE_TRACE( th, "TraceTest", "tt3", "A description for the trace test" );
343 PR_CREATE_TRACE( th, "TraceTest", "tt4", "A description for the trace test" );
344 PR_CREATE_TRACE( th, "TraceTest", "tt5", "A description for the trace test" );
345 PR_CREATE_TRACE( th, "TraceTest", "tt6", "A description for the trace test" );
346 PR_CREATE_TRACE( th, "TraceTest", "tt7", "A description for the trace test" );
347 PR_CREATE_TRACE( th, "TraceTest", "tt8", "A description for the trace test" );
349 PR_CREATE_TRACE( th, "Trace Test", "tt0", "QName is Trace Test, not TraceTest" );
350 PR_CREATE_TRACE( th, "Trace Test", "tt1", "QName is Trace Test, not TraceTest" );
351 PR_CREATE_TRACE( th, "Trace Test", "tt2", "QName is Trace Test, not TraceTest" );
352 PR_CREATE_TRACE( th, "Trace Test", "tt3", "QName is Trace Test, not TraceTest" );
353 PR_CREATE_TRACE( th, "Trace Test", "tt4", "QName is Trace Test, not TraceTest" );
354 PR_CREATE_TRACE( th, "Trace Test", "tt5", "QName is Trace Test, not TraceTest" );
355 PR_CREATE_TRACE( th, "Trace Test", "tt6", "QName is Trace Test, not TraceTest" );
356 PR_CREATE_TRACE( th, "Trace Test", "tt7", "QName is Trace Test, not TraceTest" );
357 PR_CREATE_TRACE( th, "Trace Test", "tt8", "QName is Trace Test, not TraceTest" );
358 PR_CREATE_TRACE( th, "Trace Test", "tt9", "QName is Trace Test, not TraceTest" );
359 PR_CREATE_TRACE( th, "Trace Test", "tt10", "QName is Trace Test, not TraceTest" );
363 activeThreads += 2;
364 t1 = PR_CreateThread(PR_USER_THREAD,
365 RecordTrace, NULL,
366 PR_PRIORITY_NORMAL,
367 PR_GLOBAL_THREAD,
368 PR_UNJOINABLE_THREAD,
370 PR_ASSERT(t1);
372 t2 = PR_CreateThread(PR_USER_THREAD,
373 SampleTrace, 0,
374 PR_PRIORITY_NORMAL,
375 PR_GLOBAL_THREAD,
376 PR_UNJOINABLE_THREAD,
378 PR_ASSERT(t2);
380 ListTraces();
382 PR_GET_TRACE_HANDLE_FROM_NAME( th, "TraceTest","tt1" );
383 PR_ASSERT( th == hTrace );
385 PR_LOG( lm, msgLevel,
386 ("End TraceTest"));
387 return;
388 } /* end TraceTest() */
392 ** Ordered lock test.
394 static void OrderedLockTest( void )
396 PR_LOG( lm, msgLevel,
397 ("Begin OrderedLockTest"));
400 } /* end OrderedLockTest() */
403 int main(int argc, char **argv)
405 #if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
406 PRUint32 counter;
407 PLOptStatus os;
408 PLOptState *opt = PL_CreateOptState(argc, argv, "hdv:");
409 lm = PR_NewLogModule("Test");
411 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
413 if (PL_OPT_BAD == os) continue;
414 switch (opt->option)
416 case 'v': /* verbose mode */
417 msgLevel = (PRLogModuleLevel)atol( opt->value);
418 break;
419 case 'h': /* help message */
420 Help();
421 help = PR_TRUE;
422 break;
423 default:
424 break;
427 PL_DestroyOptState(opt);
429 PR_CREATE_TRACE( hTrace, "TraceTest", "tt1", "A description for the trace test" );
430 mon = PR_NewMonitor();
431 PR_EnterMonitor( mon );
433 TraceTest();
434 CounterTest();
435 OrderedLockTest();
437 /* Wait for all threads to exit */
438 while ( activeThreads > 0 ) {
439 if ( activeThreads == 1 )
440 PR_SET_TRACE_OPTION( PRTraceStopRecording, NULL );
441 PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
442 PR_GET_COUNTER( counter, hCounter );
444 PR_ExitMonitor( mon );
447 ** Evaluate results
449 PR_GET_COUNTER( counter, hCounter );
450 if ( counter != 0 )
452 failed = PR_TRUE;
453 PR_LOG( lm, msgLevel,
454 ("Expected counter == 0, found: %ld", counter));
455 printf("FAIL\n");
457 else
459 printf("PASS\n");
463 PR_DESTROY_COUNTER( hCounter );
465 PR_DestroyMonitor( mon );
467 PR_TRACE( hTrace, TraceFlow, 0xfff,0,0,0,0,0,0);
468 PR_DESTROY_TRACE( hTrace );
469 #else
470 printf("Test not defined\n");
471 #endif
472 return 0;
473 } /* main() */
474 /* end instrumt.c */