1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is the Netscape Portable Runtime (NSPR).
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
40 ** Description: This test is for the NSPR debug aids defined in
41 ** prcountr.h, prtrace.h, prolock.h
43 ** The test case tests the three debug aids in NSPR:
45 ** Diagnostic messages can be enabled using "instrumt -v 6"
46 ** This sets the msgLevel to something that PR_LOG() likes.
47 ** Also define in the environment "NSPR_LOG_MODULES=Test:6"
49 ** CounterTest() tests the counter facility. This test
50 ** creates 4 threads. Each thread either increments, decrements,
51 ** adds to or subtracts from a counter, depending on an argument
52 ** passed to the thread at thread-create time. Each of these threads
53 ** does COUNT_LIMIT iterations doing its thing. When all 4 threads
54 ** are done, the result of the counter is evaluated. If all was atomic,
55 ** the the value of the counter should be zero.
58 ** This test mingles with the counter test. Counters trace.
59 ** A thread to extract trace entries on the fly is started.
60 ** A thread to dump trace entries to a file is started.
82 #define COUNT_LIMIT (10 * ( 1024))
84 #define SMALL_TRACE_BUFSIZE ( 60 * 1024 )
94 PRLogModuleLevel msgLevel
= PR_LOG_ALWAYS
;
96 PRBool help
= PR_FALSE
;
97 PRBool failed
= PR_FALSE
;
102 PRInt32 activeThreads
= 0;
103 PR_DEFINE_COUNTER( hCounter
);
104 PR_DEFINE_TRACE( hTrace
);
106 static void Help(void)
108 printf("Help? ... Ha!\n");
111 static void ListCounters(void)
113 PR_DEFINE_COUNTER( qh
);
114 PR_DEFINE_COUNTER( rh
);
115 const char *qn
, *rn
, *dn
;
116 const char **qname
= &qn
, **rname
= &rn
, **desc
= &dn
;
119 PR_INIT_COUNTER_HANDLE( qh
, NULL
);
120 PR_FIND_NEXT_COUNTER_QNAME(qh
, qh
);
123 PR_INIT_COUNTER_HANDLE( rh
, NULL
);
124 PR_FIND_NEXT_COUNTER_RNAME(rh
, rh
, qh
);
127 PR_GET_COUNTER_NAME_FROM_HANDLE( rh
, qname
, rname
, desc
);
128 tCtr
= PR_GET_COUNTER(tCtr
, rh
);
129 PR_LOG( lm
, msgLevel
,
130 ( "QName: %s RName: %s Desc: %s Value: %ld\n",
132 PR_FIND_NEXT_COUNTER_RNAME(rh
, rh
, qh
);
134 PR_FIND_NEXT_COUNTER_QNAME(qh
, qh
);
137 } /* end ListCounters() */
139 static void ListTraces(void)
141 PR_DEFINE_TRACE( qh
);
142 PR_DEFINE_TRACE( rh
);
143 const char *qn
, *rn
, *dn
;
144 const char **qname
= &qn
, **rname
= &rn
, **desc
= &dn
;
146 PR_INIT_TRACE_HANDLE( qh
, NULL
);
147 PR_FIND_NEXT_TRACE_QNAME(qh
, qh
);
150 PR_INIT_TRACE_HANDLE( rh
, NULL
);
151 PR_FIND_NEXT_TRACE_RNAME(rh
, rh
, qh
);
154 PR_GET_TRACE_NAME_FROM_HANDLE( rh
, qname
, rname
, desc
);
155 PR_LOG( lm
, msgLevel
,
156 ( "QName: %s RName: %s Desc: %s",
158 PR_FIND_NEXT_TRACE_RNAME(rh
, rh
, qh
);
160 PR_FIND_NEXT_TRACE_QNAME(qh
, qh
);
163 } /* end ListCounters() */
166 static PRInt32 one
= 1;
167 static PRInt32 two
= 2;
168 static PRInt32 three
= 3;
169 static PRInt32 four
= 4;
172 ** Thread to iteratively count something.
174 static void PR_CALLBACK
CountSomething( void *arg
)
176 PRInt32 switchVar
= *((PRInt32
*)arg
);
179 PR_LOG( lm
, msgLevel
,
180 ("CountSomething: begin thread %ld", switchVar
));
182 for ( i
= 0; i
< COUNT_LIMIT
; i
++)
187 PR_INCREMENT_COUNTER( hCounter
);
190 PR_DECREMENT_COUNTER( hCounter
);
193 PR_ADD_TO_COUNTER( hCounter
, 1 );
196 PR_SUBTRACT_FROM_COUNTER( hCounter
, 1 );
202 PR_TRACE( hTrace
, CountLoop
, switchVar
, i
, 0, 0, 0, 0, 0 );
205 PR_LOG( lm
, msgLevel
,
206 ("CounterSomething: end thread %ld", switchVar
));
208 PR_EnterMonitor(mon
);
214 } /* end CountSomething() */
217 ** Create the counter threads.
219 static void CounterTest( void )
221 PRThread
*t1
, *t2
, *t3
, *t4
;
223 PR_DEFINE_COUNTER( tc
);
224 PR_DEFINE_COUNTER( zCounter
);
226 PR_LOG( lm
, msgLevel
,
227 ("Begin CounterTest"));
230 ** Test Get and Set of a counter.
233 PR_CREATE_COUNTER( zCounter
, "Atomic", "get/set test", "test get and set of counter" );
234 PR_SET_COUNTER( zCounter
, 9 );
235 PR_GET_COUNTER( i
, zCounter
);
239 PR_LOG( lm
, msgLevel
,
240 ("Counter set/get failed"));
244 PR_CREATE_COUNTER( hCounter
, "Atomic", "SMP Tests", "test atomic nature of counter" );
246 PR_GET_COUNTER_HANDLE_FROM_NAME( tc
, "Atomic", "SMP Tests" );
247 PR_ASSERT( tc
== hCounter
);
249 t1
= PR_CreateThread(PR_USER_THREAD
,
250 CountSomething
, &one
,
253 PR_UNJOINABLE_THREAD
,
257 t2
= PR_CreateThread(PR_USER_THREAD
,
258 CountSomething
, &two
,
261 PR_UNJOINABLE_THREAD
,
265 t3
= PR_CreateThread(PR_USER_THREAD
,
266 CountSomething
, &three
,
269 PR_UNJOINABLE_THREAD
,
273 t4
= PR_CreateThread(PR_USER_THREAD
,
274 CountSomething
, &four
,
277 PR_UNJOINABLE_THREAD
,
281 PR_LOG( lm
, msgLevel
,
282 ("Counter Threads started"));
286 } /* end CounterTest() */
289 ** Thread to dump trace buffer to a file.
291 static void PR_CALLBACK
RecordTrace(void *arg
)
293 PR_RECORD_TRACE_ENTRIES();
295 PR_EnterMonitor(mon
);
301 } /* end RecordTrace() */
305 #define NUM_TRACE_RECORDS ( 10000 )
307 ** Thread to extract and print trace entries from the buffer.
309 static void PR_CALLBACK
SampleTrace( void *arg
)
311 #if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
313 PRTraceEntry
*foundEntries
;
316 foundEntries
= (PRTraceEntry
*)PR_Malloc( NUM_TRACE_RECORDS
* sizeof(PRTraceEntry
));
317 PR_ASSERT(foundEntries
!= NULL
);
321 rc
= PR_GetTraceEntries( foundEntries
, NUM_TRACE_RECORDS
, &found
);
322 PR_LOG( lm
, msgLevel
,
323 ("SampleTrace: Lost Data: %ld found: %ld", rc
, found
));
327 for ( i
= 0 ; i
< found
; i
++ )
329 PR_LOG( lm
, msgLevel
,
330 ("SampleTrace, detail: Thread: %p, Time: %llX, UD0: %ld, UD1: %ld, UD2: %8.8ld",
331 (foundEntries
+i
)->thread
,
332 (foundEntries
+i
)->time
,
333 (foundEntries
+i
)->userData
[0],
334 (foundEntries
+i
)->userData
[1],
335 (foundEntries
+i
)->userData
[2] ));
338 PR_Sleep(PR_MillisecondsToInterval(50));
340 while( found
!= 0 && activeThreads
>= 1 );
342 PR_Free( foundEntries
);
344 PR_EnterMonitor(mon
);
349 PR_LOG( lm
, msgLevel
,
350 ("SampleTrace(): exiting"));
354 } /* end RecordTrace() */
359 static void TraceTest( void )
363 PR_DEFINE_TRACE( th
);
366 PR_LOG( lm
, msgLevel
,
367 ("Begin TraceTest"));
369 size
= SMALL_TRACE_BUFSIZE
;
370 PR_SET_TRACE_OPTION( PRTraceBufSize
, &size
);
371 PR_GET_TRACE_OPTION( PRTraceBufSize
, &i
);
373 PR_CREATE_TRACE( th
, "TraceTest", "tt2", "A description for the trace test" );
374 PR_CREATE_TRACE( th
, "TraceTest", "tt3", "A description for the trace test" );
375 PR_CREATE_TRACE( th
, "TraceTest", "tt4", "A description for the trace test" );
376 PR_CREATE_TRACE( th
, "TraceTest", "tt5", "A description for the trace test" );
377 PR_CREATE_TRACE( th
, "TraceTest", "tt6", "A description for the trace test" );
378 PR_CREATE_TRACE( th
, "TraceTest", "tt7", "A description for the trace test" );
379 PR_CREATE_TRACE( th
, "TraceTest", "tt8", "A description for the trace test" );
381 PR_CREATE_TRACE( th
, "Trace Test", "tt0", "QName is Trace Test, not TraceTest" );
382 PR_CREATE_TRACE( th
, "Trace Test", "tt1", "QName is Trace Test, not TraceTest" );
383 PR_CREATE_TRACE( th
, "Trace Test", "tt2", "QName is Trace Test, not TraceTest" );
384 PR_CREATE_TRACE( th
, "Trace Test", "tt3", "QName is Trace Test, not TraceTest" );
385 PR_CREATE_TRACE( th
, "Trace Test", "tt4", "QName is Trace Test, not TraceTest" );
386 PR_CREATE_TRACE( th
, "Trace Test", "tt5", "QName is Trace Test, not TraceTest" );
387 PR_CREATE_TRACE( th
, "Trace Test", "tt6", "QName is Trace Test, not TraceTest" );
388 PR_CREATE_TRACE( th
, "Trace Test", "tt7", "QName is Trace Test, not TraceTest" );
389 PR_CREATE_TRACE( th
, "Trace Test", "tt8", "QName is Trace Test, not TraceTest" );
390 PR_CREATE_TRACE( th
, "Trace Test", "tt9", "QName is Trace Test, not TraceTest" );
391 PR_CREATE_TRACE( th
, "Trace Test", "tt10", "QName is Trace Test, not TraceTest" );
396 t1
= PR_CreateThread(PR_USER_THREAD
,
400 PR_UNJOINABLE_THREAD
,
404 t2
= PR_CreateThread(PR_USER_THREAD
,
408 PR_UNJOINABLE_THREAD
,
414 PR_GET_TRACE_HANDLE_FROM_NAME( th
, "TraceTest","tt1" );
415 PR_ASSERT( th
== hTrace
);
417 PR_LOG( lm
, msgLevel
,
420 } /* end TraceTest() */
424 ** Ordered lock test.
426 static void OrderedLockTest( void )
428 PR_LOG( lm
, msgLevel
,
429 ("Begin OrderedLockTest"));
432 } /* end OrderedLockTest() */
435 PRIntn
main(PRIntn argc
, char *argv
[])
437 #if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
440 PLOptState
*opt
= PL_CreateOptState(argc
, argv
, "hdv:");
441 lm
= PR_NewLogModule("Test");
443 while (PL_OPT_EOL
!= (os
= PL_GetNextOpt(opt
)))
445 if (PL_OPT_BAD
== os
) continue;
448 case 'v': /* verbose mode */
449 msgLevel
= (PRLogModuleLevel
)atol( opt
->value
);
451 case 'h': /* help message */
459 PL_DestroyOptState(opt
);
461 PR_CREATE_TRACE( hTrace
, "TraceTest", "tt1", "A description for the trace test" );
462 mon
= PR_NewMonitor();
463 PR_EnterMonitor( mon
);
469 /* Wait for all threads to exit */
470 while ( activeThreads
> 0 ) {
471 if ( activeThreads
== 1 )
472 PR_SET_TRACE_OPTION( PRTraceStopRecording
, NULL
);
473 PR_Wait(mon
, PR_INTERVAL_NO_TIMEOUT
);
474 PR_GET_COUNTER( counter
, hCounter
);
476 PR_ExitMonitor( mon
);
481 PR_GET_COUNTER( counter
, hCounter
);
485 PR_LOG( lm
, msgLevel
,
486 ("Expected counter == 0, found: %ld", counter
));
495 PR_DESTROY_COUNTER( hCounter
);
497 PR_DestroyMonitor( mon
);
499 PR_TRACE( hTrace
, TraceFlow
, 0xfff,0,0,0,0,0,0);
500 PR_DESTROY_TRACE( hTrace
);
502 printf("Test not defined\n");