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/. */
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.
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.
50 #define COUNT_LIMIT (10 * ( 1024))
52 #define SMALL_TRACE_BUFSIZE ( 60 * 1024 )
62 PRLogModuleLevel msgLevel
= PR_LOG_ALWAYS
;
64 PRBool help
= PR_FALSE
;
65 PRBool failed
= PR_FALSE
;
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
;
87 PR_INIT_COUNTER_HANDLE( qh
, NULL
);
88 PR_FIND_NEXT_COUNTER_QNAME(qh
, qh
);
91 PR_INIT_COUNTER_HANDLE( rh
, NULL
);
92 PR_FIND_NEXT_COUNTER_RNAME(rh
, rh
, qh
);
95 PR_GET_COUNTER_NAME_FROM_HANDLE( rh
, qname
, rname
, desc
);
96 tCtr
= PR_GET_COUNTER(tCtr
, rh
);
98 ( "QName: %s RName: %s Desc: %s Value: %ld\n",
100 PR_FIND_NEXT_COUNTER_RNAME(rh
, rh
, qh
);
102 PR_FIND_NEXT_COUNTER_QNAME(qh
, qh
);
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
);
118 PR_INIT_TRACE_HANDLE( rh
, NULL
);
119 PR_FIND_NEXT_TRACE_RNAME(rh
, rh
, qh
);
122 PR_GET_TRACE_NAME_FROM_HANDLE( rh
, qname
, rname
, desc
);
123 PR_LOG( lm
, msgLevel
,
124 ( "QName: %s RName: %s Desc: %s",
126 PR_FIND_NEXT_TRACE_RNAME(rh
, rh
, qh
);
128 PR_FIND_NEXT_TRACE_QNAME(qh
, qh
);
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
);
147 PR_LOG( lm
, msgLevel
,
148 ("CountSomething: begin thread %ld", switchVar
));
150 for ( i
= 0; i
< COUNT_LIMIT
; i
++)
155 PR_INCREMENT_COUNTER( hCounter
);
158 PR_DECREMENT_COUNTER( hCounter
);
161 PR_ADD_TO_COUNTER( hCounter
, 1 );
164 PR_SUBTRACT_FROM_COUNTER( hCounter
, 1 );
170 PR_TRACE( hTrace
, CountLoop
, switchVar
, i
, 0, 0, 0, 0, 0 );
173 PR_LOG( lm
, msgLevel
,
174 ("CounterSomething: end thread %ld", switchVar
));
176 PR_EnterMonitor(mon
);
182 } /* end CountSomething() */
185 ** Create the counter threads.
187 static void CounterTest( void )
189 PRThread
*t1
, *t2
, *t3
, *t4
;
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
);
207 PR_LOG( lm
, msgLevel
,
208 ("Counter set/get failed"));
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
,
221 PR_UNJOINABLE_THREAD
,
225 t2
= PR_CreateThread(PR_USER_THREAD
,
226 CountSomething
, &two
,
229 PR_UNJOINABLE_THREAD
,
233 t3
= PR_CreateThread(PR_USER_THREAD
,
234 CountSomething
, &three
,
237 PR_UNJOINABLE_THREAD
,
241 t4
= PR_CreateThread(PR_USER_THREAD
,
242 CountSomething
, &four
,
245 PR_UNJOINABLE_THREAD
,
249 PR_LOG( lm
, msgLevel
,
250 ("Counter Threads started"));
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
);
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)
281 PRTraceEntry
*foundEntries
;
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
));
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
);
317 PR_LOG( lm
, msgLevel
,
318 ("SampleTrace(): exiting"));
322 } /* end RecordTrace() */
327 static void TraceTest( void )
331 PR_DEFINE_TRACE( th
);
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" );
364 t1
= PR_CreateThread(PR_USER_THREAD
,
368 PR_UNJOINABLE_THREAD
,
372 t2
= PR_CreateThread(PR_USER_THREAD
,
376 PR_UNJOINABLE_THREAD
,
382 PR_GET_TRACE_HANDLE_FROM_NAME( th
, "TraceTest","tt1" );
383 PR_ASSERT( th
== hTrace
);
385 PR_LOG( lm
, msgLevel
,
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)
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;
416 case 'v': /* verbose mode */
417 msgLevel
= (PRLogModuleLevel
)atol( opt
->value
);
419 case 'h': /* help message */
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
);
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
);
449 PR_GET_COUNTER( counter
, hCounter
);
453 PR_LOG( lm
, msgLevel
,
454 ("Expected counter == 0, found: %ld", counter
));
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
);
470 printf("Test not defined\n");