123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /*
- ** File: instrumt.c
- ** Description: This test is for the NSPR debug aids defined in
- ** prcountr.h, prtrace.h, prolock.h
- **
- ** The test case tests the three debug aids in NSPR:
- **
- ** Diagnostic messages can be enabled using "instrumt -v 6"
- ** This sets the msgLevel to something that PR_LOG() likes.
- ** Also define in the environment "NSPR_LOG_MODULES=Test:6"
- **
- ** CounterTest() tests the counter facility. This test
- ** creates 4 threads. Each thread either increments, decrements,
- ** adds to or subtracts from a counter, depending on an argument
- ** passed to the thread at thread-create time. Each of these threads
- ** does COUNT_LIMIT iterations doing its thing. When all 4 threads
- ** are done, the result of the counter is evaluated. If all was atomic,
- ** the the value of the counter should be zero.
- **
- ** TraceTest():
- ** This test mingles with the counter test. Counters trace.
- ** A thread to extract trace entries on the fly is started.
- ** A thread to dump trace entries to a file is started.
- **
- ** OrderedLockTest():
- **
- **
- **
- **
- **
- */
- #include <stdio.h>
- #include <plstr.h>
- #include <prclist.h>
- #include <prmem.h>
- #include <plgetopt.h>
- #include <prlog.h>
- #include <prmon.h>
- #include <pratom.h>
- #include <prtrace.h>
- #include <prcountr.h>
- #include <prolock.h>
- #define COUNT_LIMIT (10 * ( 1024))
- #define SMALL_TRACE_BUFSIZE ( 60 * 1024 )
- typedef enum
- {
- CountLoop = 1,
- TraceLoop = 2,
- TraceFlow = 3
- } TraceTypes;
- PRLogModuleLevel msgLevel = PR_LOG_ALWAYS;
- PRBool help = PR_FALSE;
- PRBool failed = PR_FALSE;
- PRLogModuleInfo *lm;
- PRMonitor *mon;
- PRInt32 activeThreads = 0;
- PR_DEFINE_COUNTER( hCounter );
- PR_DEFINE_TRACE( hTrace );
- static void Help(void)
- {
- printf("Help? ... Ha!\n");
- }
- static void ListCounters(void)
- {
- PR_DEFINE_COUNTER( qh );
- PR_DEFINE_COUNTER( rh );
- const char *qn, *rn, *dn;
- const char **qname = &qn, **rname = &rn, **desc = &dn;
- PRUint32 tCtr;
- PR_INIT_COUNTER_HANDLE( qh, NULL );
- PR_FIND_NEXT_COUNTER_QNAME(qh, qh );
- while ( qh != NULL )
- {
- PR_INIT_COUNTER_HANDLE( rh, NULL );
- PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh );
- while ( rh != NULL )
- {
- PR_GET_COUNTER_NAME_FROM_HANDLE( rh, qname, rname, desc );
- PR_GET_COUNTER(tCtr, rh);
- PR_LOG( lm, msgLevel,
- ( "QName: %s RName: %s Desc: %s Value: %ld\n",
- qn, rn, dn, tCtr ));
- PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh );
- }
- PR_FIND_NEXT_COUNTER_QNAME(qh, qh);
- }
- return;
- } /* end ListCounters() */
- static void ListTraces(void)
- {
- PR_DEFINE_TRACE( qh );
- PR_DEFINE_TRACE( rh );
- const char *qn, *rn, *dn;
- const char **qname = &qn, **rname = &rn, **desc = &dn;
- PR_INIT_TRACE_HANDLE( qh, NULL );
- PR_FIND_NEXT_TRACE_QNAME(qh, qh );
- while ( qh != NULL )
- {
- PR_INIT_TRACE_HANDLE( rh, NULL );
- PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh );
- while ( rh != NULL )
- {
- PR_GET_TRACE_NAME_FROM_HANDLE( rh, qname, rname, desc );
- PR_LOG( lm, msgLevel,
- ( "QName: %s RName: %s Desc: %s",
- qn, rn, dn ));
- PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh );
- }
- PR_FIND_NEXT_TRACE_QNAME(qh, qh);
- }
- return;
- } /* end ListCounters() */
- static PRInt32 one = 1;
- static PRInt32 two = 2;
- static PRInt32 three = 3;
- static PRInt32 four = 4;
- /*
- ** Thread to iteratively count something.
- */
- static void PR_CALLBACK CountSomething( void *arg )
- {
- PRInt32 switchVar = *((PRInt32 *)arg);
- PRInt32 i;
- PR_LOG( lm, msgLevel,
- ("CountSomething: begin thread %ld", switchVar ));
- for ( i = 0; i < COUNT_LIMIT ; i++)
- {
- switch ( switchVar )
- {
- case 1 :
- PR_INCREMENT_COUNTER( hCounter );
- break;
- case 2 :
- PR_DECREMENT_COUNTER( hCounter );
- break;
- case 3 :
- PR_ADD_TO_COUNTER( hCounter, 1 );
- break;
- case 4 :
- PR_SUBTRACT_FROM_COUNTER( hCounter, 1 );
- break;
- default :
- PR_ASSERT( 0 );
- break;
- }
- PR_TRACE( hTrace, CountLoop, switchVar, i, 0, 0, 0, 0, 0 );
- } /* end for() */
- PR_LOG( lm, msgLevel,
- ("CounterSomething: end thread %ld", switchVar ));
- PR_EnterMonitor(mon);
- --activeThreads;
- PR_Notify( mon );
- PR_ExitMonitor(mon);
- return;
- } /* end CountSomething() */
- /*
- ** Create the counter threads.
- */
- static void CounterTest( void )
- {
- PRThread *t1, *t2, *t3, *t4;
- PRIntn i = 0;
- PR_DEFINE_COUNTER( tc );
- PR_DEFINE_COUNTER( zCounter );
- PR_LOG( lm, msgLevel,
- ("Begin CounterTest"));
- /*
- ** Test Get and Set of a counter.
- **
- */
- PR_CREATE_COUNTER( zCounter, "Atomic", "get/set test", "test get and set of counter" );
- PR_SET_COUNTER( zCounter, 9 );
- PR_GET_COUNTER( i, zCounter );
- if ( i != 9 )
- {
- failed = PR_TRUE;
- PR_LOG( lm, msgLevel,
- ("Counter set/get failed"));
- }
- activeThreads += 4;
- PR_CREATE_COUNTER( hCounter, "Atomic", "SMP Tests", "test atomic nature of counter" );
- PR_GET_COUNTER_HANDLE_FROM_NAME( tc, "Atomic", "SMP Tests" );
- PR_ASSERT( tc == hCounter );
- t1 = PR_CreateThread(PR_USER_THREAD,
- CountSomething, &one,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
- PR_ASSERT(t1);
- t2 = PR_CreateThread(PR_USER_THREAD,
- CountSomething, &two,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
- PR_ASSERT(t2);
- t3 = PR_CreateThread(PR_USER_THREAD,
- CountSomething, &three,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
- PR_ASSERT(t3);
- t4 = PR_CreateThread(PR_USER_THREAD,
- CountSomething, &four,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
- PR_ASSERT(t4);
- PR_LOG( lm, msgLevel,
- ("Counter Threads started"));
- ListCounters();
- return;
- } /* end CounterTest() */
- /*
- ** Thread to dump trace buffer to a file.
- */
- static void PR_CALLBACK RecordTrace(void *arg )
- {
- PR_RECORD_TRACE_ENTRIES();
- PR_EnterMonitor(mon);
- --activeThreads;
- PR_Notify( mon );
- PR_ExitMonitor(mon);
- return;
- } /* end RecordTrace() */
- #define NUM_TRACE_RECORDS ( 10000 )
- /*
- ** Thread to extract and print trace entries from the buffer.
- */
- static void PR_CALLBACK SampleTrace( void *arg )
- {
- #if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
- PRInt32 found, rc;
- PRTraceEntry *foundEntries;
- PRInt32 i;
- foundEntries = (PRTraceEntry *)PR_Malloc( NUM_TRACE_RECORDS * sizeof(PRTraceEntry));
- PR_ASSERT(foundEntries != NULL );
- do
- {
- rc = PR_GetTraceEntries( foundEntries, NUM_TRACE_RECORDS, &found);
- PR_LOG( lm, msgLevel,
- ("SampleTrace: Lost Data: %ld found: %ld", rc, found ));
- if ( found != 0)
- {
- for ( i = 0 ; i < found; i++ )
- {
- PR_LOG( lm, msgLevel,
- ("SampleTrace, detail: Thread: %p, Time: %llX, UD0: %ld, UD1: %ld, UD2: %8.8ld",
- (foundEntries +i)->thread,
- (foundEntries +i)->time,
- (foundEntries +i)->userData[0],
- (foundEntries +i)->userData[1],
- (foundEntries +i)->userData[2] ));
- }
- }
- PR_Sleep(PR_MillisecondsToInterval(50));
- }
- while( found != 0 && activeThreads >= 1 );
- PR_Free( foundEntries );
- PR_EnterMonitor(mon);
- --activeThreads;
- PR_Notify( mon );
- PR_ExitMonitor(mon);
- PR_LOG( lm, msgLevel,
- ("SampleTrace(): exiting"));
- #endif
- return;
- } /* end RecordTrace() */
- /*
- ** Basic trace test.
- */
- static void TraceTest( void )
- {
- PRInt32 i;
- PRInt32 size;
- PR_DEFINE_TRACE( th );
- PRThread *t1, *t2;
- PR_LOG( lm, msgLevel,
- ("Begin TraceTest"));
- size = SMALL_TRACE_BUFSIZE;
- PR_SET_TRACE_OPTION( PRTraceBufSize, &size );
- PR_GET_TRACE_OPTION( PRTraceBufSize, &i );
- PR_CREATE_TRACE( th, "TraceTest", "tt2", "A description for the trace test" );
- PR_CREATE_TRACE( th, "TraceTest", "tt3", "A description for the trace test" );
- PR_CREATE_TRACE( th, "TraceTest", "tt4", "A description for the trace test" );
- PR_CREATE_TRACE( th, "TraceTest", "tt5", "A description for the trace test" );
- PR_CREATE_TRACE( th, "TraceTest", "tt6", "A description for the trace test" );
- PR_CREATE_TRACE( th, "TraceTest", "tt7", "A description for the trace test" );
- PR_CREATE_TRACE( th, "TraceTest", "tt8", "A description for the trace test" );
- PR_CREATE_TRACE( th, "Trace Test", "tt0", "QName is Trace Test, not TraceTest" );
- PR_CREATE_TRACE( th, "Trace Test", "tt1", "QName is Trace Test, not TraceTest" );
- PR_CREATE_TRACE( th, "Trace Test", "tt2", "QName is Trace Test, not TraceTest" );
- PR_CREATE_TRACE( th, "Trace Test", "tt3", "QName is Trace Test, not TraceTest" );
- PR_CREATE_TRACE( th, "Trace Test", "tt4", "QName is Trace Test, not TraceTest" );
- PR_CREATE_TRACE( th, "Trace Test", "tt5", "QName is Trace Test, not TraceTest" );
- PR_CREATE_TRACE( th, "Trace Test", "tt6", "QName is Trace Test, not TraceTest" );
- PR_CREATE_TRACE( th, "Trace Test", "tt7", "QName is Trace Test, not TraceTest" );
- PR_CREATE_TRACE( th, "Trace Test", "tt8", "QName is Trace Test, not TraceTest" );
- PR_CREATE_TRACE( th, "Trace Test", "tt9", "QName is Trace Test, not TraceTest" );
- PR_CREATE_TRACE( th, "Trace Test", "tt10", "QName is Trace Test, not TraceTest" );
- activeThreads += 2;
- t1 = PR_CreateThread(PR_USER_THREAD,
- RecordTrace, NULL,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
- PR_ASSERT(t1);
- t2 = PR_CreateThread(PR_USER_THREAD,
- SampleTrace, 0,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
- PR_ASSERT(t2);
- ListTraces();
- PR_GET_TRACE_HANDLE_FROM_NAME( th, "TraceTest","tt1" );
- PR_ASSERT( th == hTrace );
- PR_LOG( lm, msgLevel,
- ("End TraceTest"));
- return;
- } /* end TraceTest() */
- /*
- ** Ordered lock test.
- */
- static void OrderedLockTest( void )
- {
- PR_LOG( lm, msgLevel,
- ("Begin OrderedLockTest"));
- } /* end OrderedLockTest() */
- int main(int argc, char **argv)
- {
- #if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
- PRUint32 counter;
- PLOptStatus os;
- PLOptState *opt = PL_CreateOptState(argc, argv, "hdv:");
- lm = PR_NewLogModule("Test");
- while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
- {
- if (PL_OPT_BAD == os) {
- continue;
- }
- switch (opt->option)
- {
- case 'v': /* verbose mode */
- msgLevel = (PRLogModuleLevel)atol( opt->value);
- break;
- case 'h': /* help message */
- Help();
- help = PR_TRUE;
- break;
- default:
- break;
- }
- }
- PL_DestroyOptState(opt);
- PR_CREATE_TRACE( hTrace, "TraceTest", "tt1", "A description for the trace test" );
- mon = PR_NewMonitor();
- PR_EnterMonitor( mon );
- TraceTest();
- CounterTest();
- OrderedLockTest();
- /* Wait for all threads to exit */
- while ( activeThreads > 0 ) {
- if ( activeThreads == 1 ) {
- PR_SET_TRACE_OPTION( PRTraceStopRecording, NULL );
- }
- PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
- PR_GET_COUNTER( counter, hCounter );
- }
- PR_ExitMonitor( mon );
- /*
- ** Evaluate results
- */
- PR_GET_COUNTER( counter, hCounter );
- if ( counter != 0 )
- {
- failed = PR_TRUE;
- PR_LOG( lm, msgLevel,
- ("Expected counter == 0, found: %ld", counter));
- printf("FAIL\n");
- }
- else
- {
- printf("PASS\n");
- }
- PR_DESTROY_COUNTER( hCounter );
- PR_DestroyMonitor( mon );
- PR_TRACE( hTrace, TraceFlow, 0xfff,0,0,0,0,0,0);
- PR_DESTROY_TRACE( hTrace );
- #else
- printf("Test not defined\n");
- #endif
- return 0;
- } /* main() */
- /* end instrumt.c */
|