📄 instrumt.c
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape Portable Runtime (NSPR). * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//*** 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 ); tCtr = 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() */PRIntn main(PRIntn 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -