1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/tests/instrumt.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,475 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 +** File: instrumt.c 1.11 +** Description: This test is for the NSPR debug aids defined in 1.12 +** prcountr.h, prtrace.h, prolock.h 1.13 +** 1.14 +** The test case tests the three debug aids in NSPR: 1.15 +** 1.16 +** Diagnostic messages can be enabled using "instrumt -v 6" 1.17 +** This sets the msgLevel to something that PR_LOG() likes. 1.18 +** Also define in the environment "NSPR_LOG_MODULES=Test:6" 1.19 +** 1.20 +** CounterTest() tests the counter facility. This test 1.21 +** creates 4 threads. Each thread either increments, decrements, 1.22 +** adds to or subtracts from a counter, depending on an argument 1.23 +** passed to the thread at thread-create time. Each of these threads 1.24 +** does COUNT_LIMIT iterations doing its thing. When all 4 threads 1.25 +** are done, the result of the counter is evaluated. If all was atomic, 1.26 +** the the value of the counter should be zero. 1.27 +** 1.28 +** TraceTest(): 1.29 +** This test mingles with the counter test. Counters trace. 1.30 +** A thread to extract trace entries on the fly is started. 1.31 +** A thread to dump trace entries to a file is started. 1.32 +** 1.33 +** OrderedLockTest(): 1.34 +** 1.35 +** 1.36 +** 1.37 +** 1.38 +** 1.39 +*/ 1.40 + 1.41 +#include <stdio.h> 1.42 +#include <plstr.h> 1.43 +#include <prclist.h> 1.44 +#include <prmem.h> 1.45 +#include <plgetopt.h> 1.46 +#include <prlog.h> 1.47 +#include <prmon.h> 1.48 +#include <pratom.h> 1.49 +#include <prtrace.h> 1.50 +#include <prcountr.h> 1.51 +#include <prolock.h> 1.52 + 1.53 +#define COUNT_LIMIT (10 * ( 1024)) 1.54 + 1.55 +#define SMALL_TRACE_BUFSIZE ( 60 * 1024 ) 1.56 + 1.57 +typedef enum 1.58 +{ 1.59 + CountLoop = 1, 1.60 + TraceLoop = 2, 1.61 + TraceFlow = 3 1.62 +} TraceTypes; 1.63 + 1.64 + 1.65 +PRLogModuleLevel msgLevel = PR_LOG_ALWAYS; 1.66 + 1.67 +PRBool help = PR_FALSE; 1.68 +PRBool failed = PR_FALSE; 1.69 + 1.70 + 1.71 +PRLogModuleInfo *lm; 1.72 +PRMonitor *mon; 1.73 +PRInt32 activeThreads = 0; 1.74 +PR_DEFINE_COUNTER( hCounter ); 1.75 +PR_DEFINE_TRACE( hTrace ); 1.76 + 1.77 +static void Help(void) 1.78 +{ 1.79 + printf("Help? ... Ha!\n"); 1.80 +} 1.81 + 1.82 +static void ListCounters(void) 1.83 +{ 1.84 + PR_DEFINE_COUNTER( qh ); 1.85 + PR_DEFINE_COUNTER( rh ); 1.86 + const char *qn, *rn, *dn; 1.87 + const char **qname = &qn, **rname = &rn, **desc = &dn; 1.88 + PRUint32 tCtr; 1.89 + 1.90 + PR_INIT_COUNTER_HANDLE( qh, NULL ); 1.91 + PR_FIND_NEXT_COUNTER_QNAME(qh, qh ); 1.92 + while ( qh != NULL ) 1.93 + { 1.94 + PR_INIT_COUNTER_HANDLE( rh, NULL ); 1.95 + PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh ); 1.96 + while ( rh != NULL ) 1.97 + { 1.98 + PR_GET_COUNTER_NAME_FROM_HANDLE( rh, qname, rname, desc ); 1.99 + PR_GET_COUNTER(tCtr, rh); 1.100 + PR_LOG( lm, msgLevel, 1.101 + ( "QName: %s RName: %s Desc: %s Value: %ld\n", 1.102 + qn, rn, dn, tCtr )); 1.103 + PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh ); 1.104 + } 1.105 + PR_FIND_NEXT_COUNTER_QNAME(qh, qh); 1.106 + } 1.107 + return; 1.108 +} /* end ListCounters() */ 1.109 + 1.110 +static void ListTraces(void) 1.111 +{ 1.112 + PR_DEFINE_TRACE( qh ); 1.113 + PR_DEFINE_TRACE( rh ); 1.114 + const char *qn, *rn, *dn; 1.115 + const char **qname = &qn, **rname = &rn, **desc = &dn; 1.116 + 1.117 + PR_INIT_TRACE_HANDLE( qh, NULL ); 1.118 + PR_FIND_NEXT_TRACE_QNAME(qh, qh ); 1.119 + while ( qh != NULL ) 1.120 + { 1.121 + PR_INIT_TRACE_HANDLE( rh, NULL ); 1.122 + PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh ); 1.123 + while ( rh != NULL ) 1.124 + { 1.125 + PR_GET_TRACE_NAME_FROM_HANDLE( rh, qname, rname, desc ); 1.126 + PR_LOG( lm, msgLevel, 1.127 + ( "QName: %s RName: %s Desc: %s", 1.128 + qn, rn, dn )); 1.129 + PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh ); 1.130 + } 1.131 + PR_FIND_NEXT_TRACE_QNAME(qh, qh); 1.132 + } 1.133 + return; 1.134 +} /* end ListCounters() */ 1.135 + 1.136 + 1.137 +static PRInt32 one = 1; 1.138 +static PRInt32 two = 2; 1.139 +static PRInt32 three = 3; 1.140 +static PRInt32 four = 4; 1.141 + 1.142 +/* 1.143 +** Thread to iteratively count something. 1.144 +*/ 1.145 +static void PR_CALLBACK CountSomething( void *arg ) 1.146 +{ 1.147 + PRInt32 switchVar = *((PRInt32 *)arg); 1.148 + PRInt32 i; 1.149 + 1.150 + PR_LOG( lm, msgLevel, 1.151 + ("CountSomething: begin thread %ld", switchVar )); 1.152 + 1.153 + for ( i = 0; i < COUNT_LIMIT ; i++) 1.154 + { 1.155 + switch ( switchVar ) 1.156 + { 1.157 + case 1 : 1.158 + PR_INCREMENT_COUNTER( hCounter ); 1.159 + break; 1.160 + case 2 : 1.161 + PR_DECREMENT_COUNTER( hCounter ); 1.162 + break; 1.163 + case 3 : 1.164 + PR_ADD_TO_COUNTER( hCounter, 1 ); 1.165 + break; 1.166 + case 4 : 1.167 + PR_SUBTRACT_FROM_COUNTER( hCounter, 1 ); 1.168 + break; 1.169 + default : 1.170 + PR_ASSERT( 0 ); 1.171 + break; 1.172 + } 1.173 + PR_TRACE( hTrace, CountLoop, switchVar, i, 0, 0, 0, 0, 0 ); 1.174 + } /* end for() */ 1.175 + 1.176 + PR_LOG( lm, msgLevel, 1.177 + ("CounterSomething: end thread %ld", switchVar )); 1.178 + 1.179 + PR_EnterMonitor(mon); 1.180 + --activeThreads; 1.181 + PR_Notify( mon ); 1.182 + PR_ExitMonitor(mon); 1.183 + 1.184 + return; 1.185 +} /* end CountSomething() */ 1.186 + 1.187 +/* 1.188 +** Create the counter threads. 1.189 +*/ 1.190 +static void CounterTest( void ) 1.191 +{ 1.192 + PRThread *t1, *t2, *t3, *t4; 1.193 + PRIntn i = 0; 1.194 + PR_DEFINE_COUNTER( tc ); 1.195 + PR_DEFINE_COUNTER( zCounter ); 1.196 + 1.197 + PR_LOG( lm, msgLevel, 1.198 + ("Begin CounterTest")); 1.199 + 1.200 + /* 1.201 + ** Test Get and Set of a counter. 1.202 + ** 1.203 + */ 1.204 + PR_CREATE_COUNTER( zCounter, "Atomic", "get/set test", "test get and set of counter" ); 1.205 + PR_SET_COUNTER( zCounter, 9 ); 1.206 + PR_GET_COUNTER( i, zCounter ); 1.207 + if ( i != 9 ) 1.208 + { 1.209 + failed = PR_TRUE; 1.210 + PR_LOG( lm, msgLevel, 1.211 + ("Counter set/get failed")); 1.212 + } 1.213 + 1.214 + activeThreads += 4; 1.215 + PR_CREATE_COUNTER( hCounter, "Atomic", "SMP Tests", "test atomic nature of counter" ); 1.216 + 1.217 + PR_GET_COUNTER_HANDLE_FROM_NAME( tc, "Atomic", "SMP Tests" ); 1.218 + PR_ASSERT( tc == hCounter ); 1.219 + 1.220 + t1 = PR_CreateThread(PR_USER_THREAD, 1.221 + CountSomething, &one, 1.222 + PR_PRIORITY_NORMAL, 1.223 + PR_GLOBAL_THREAD, 1.224 + PR_UNJOINABLE_THREAD, 1.225 + 0); 1.226 + PR_ASSERT(t1); 1.227 + 1.228 + t2 = PR_CreateThread(PR_USER_THREAD, 1.229 + CountSomething, &two, 1.230 + PR_PRIORITY_NORMAL, 1.231 + PR_GLOBAL_THREAD, 1.232 + PR_UNJOINABLE_THREAD, 1.233 + 0); 1.234 + PR_ASSERT(t2); 1.235 + 1.236 + t3 = PR_CreateThread(PR_USER_THREAD, 1.237 + CountSomething, &three, 1.238 + PR_PRIORITY_NORMAL, 1.239 + PR_GLOBAL_THREAD, 1.240 + PR_UNJOINABLE_THREAD, 1.241 + 0); 1.242 + PR_ASSERT(t3); 1.243 + 1.244 + t4 = PR_CreateThread(PR_USER_THREAD, 1.245 + CountSomething, &four, 1.246 + PR_PRIORITY_NORMAL, 1.247 + PR_GLOBAL_THREAD, 1.248 + PR_UNJOINABLE_THREAD, 1.249 + 0); 1.250 + PR_ASSERT(t4); 1.251 + 1.252 + PR_LOG( lm, msgLevel, 1.253 + ("Counter Threads started")); 1.254 + 1.255 + ListCounters(); 1.256 + return; 1.257 +} /* end CounterTest() */ 1.258 + 1.259 +/* 1.260 +** Thread to dump trace buffer to a file. 1.261 +*/ 1.262 +static void PR_CALLBACK RecordTrace(void *arg ) 1.263 +{ 1.264 + PR_RECORD_TRACE_ENTRIES(); 1.265 + 1.266 + PR_EnterMonitor(mon); 1.267 + --activeThreads; 1.268 + PR_Notify( mon ); 1.269 + PR_ExitMonitor(mon); 1.270 + 1.271 + return; 1.272 +} /* end RecordTrace() */ 1.273 + 1.274 + 1.275 + 1.276 +#define NUM_TRACE_RECORDS ( 10000 ) 1.277 +/* 1.278 +** Thread to extract and print trace entries from the buffer. 1.279 +*/ 1.280 +static void PR_CALLBACK SampleTrace( void *arg ) 1.281 +{ 1.282 +#if defined(DEBUG) || defined(FORCE_NSPR_TRACE) 1.283 + PRInt32 found, rc; 1.284 + PRTraceEntry *foundEntries; 1.285 + PRInt32 i; 1.286 + 1.287 + foundEntries = (PRTraceEntry *)PR_Malloc( NUM_TRACE_RECORDS * sizeof(PRTraceEntry)); 1.288 + PR_ASSERT(foundEntries != NULL ); 1.289 + 1.290 + do 1.291 + { 1.292 + rc = PR_GetTraceEntries( foundEntries, NUM_TRACE_RECORDS, &found); 1.293 + PR_LOG( lm, msgLevel, 1.294 + ("SampleTrace: Lost Data: %ld found: %ld", rc, found )); 1.295 + 1.296 + if ( found != 0) 1.297 + { 1.298 + for ( i = 0 ; i < found; i++ ) 1.299 + { 1.300 + PR_LOG( lm, msgLevel, 1.301 + ("SampleTrace, detail: Thread: %p, Time: %llX, UD0: %ld, UD1: %ld, UD2: %8.8ld", 1.302 + (foundEntries +i)->thread, 1.303 + (foundEntries +i)->time, 1.304 + (foundEntries +i)->userData[0], 1.305 + (foundEntries +i)->userData[1], 1.306 + (foundEntries +i)->userData[2] )); 1.307 + } 1.308 + } 1.309 + PR_Sleep(PR_MillisecondsToInterval(50)); 1.310 + } 1.311 + while( found != 0 && activeThreads >= 1 ); 1.312 + 1.313 + PR_Free( foundEntries ); 1.314 + 1.315 + PR_EnterMonitor(mon); 1.316 + --activeThreads; 1.317 + PR_Notify( mon ); 1.318 + PR_ExitMonitor(mon); 1.319 + 1.320 + PR_LOG( lm, msgLevel, 1.321 + ("SampleTrace(): exiting")); 1.322 + 1.323 +#endif 1.324 + return; 1.325 +} /* end RecordTrace() */ 1.326 + 1.327 +/* 1.328 +** Basic trace test. 1.329 +*/ 1.330 +static void TraceTest( void ) 1.331 +{ 1.332 + PRInt32 i; 1.333 + PRInt32 size; 1.334 + PR_DEFINE_TRACE( th ); 1.335 + PRThread *t1, *t2; 1.336 + 1.337 + PR_LOG( lm, msgLevel, 1.338 + ("Begin TraceTest")); 1.339 + 1.340 + size = SMALL_TRACE_BUFSIZE; 1.341 + PR_SET_TRACE_OPTION( PRTraceBufSize, &size ); 1.342 + PR_GET_TRACE_OPTION( PRTraceBufSize, &i ); 1.343 + 1.344 + PR_CREATE_TRACE( th, "TraceTest", "tt2", "A description for the trace test" ); 1.345 + PR_CREATE_TRACE( th, "TraceTest", "tt3", "A description for the trace test" ); 1.346 + PR_CREATE_TRACE( th, "TraceTest", "tt4", "A description for the trace test" ); 1.347 + PR_CREATE_TRACE( th, "TraceTest", "tt5", "A description for the trace test" ); 1.348 + PR_CREATE_TRACE( th, "TraceTest", "tt6", "A description for the trace test" ); 1.349 + PR_CREATE_TRACE( th, "TraceTest", "tt7", "A description for the trace test" ); 1.350 + PR_CREATE_TRACE( th, "TraceTest", "tt8", "A description for the trace test" ); 1.351 + 1.352 + PR_CREATE_TRACE( th, "Trace Test", "tt0", "QName is Trace Test, not TraceTest" ); 1.353 + PR_CREATE_TRACE( th, "Trace Test", "tt1", "QName is Trace Test, not TraceTest" ); 1.354 + PR_CREATE_TRACE( th, "Trace Test", "tt2", "QName is Trace Test, not TraceTest" ); 1.355 + PR_CREATE_TRACE( th, "Trace Test", "tt3", "QName is Trace Test, not TraceTest" ); 1.356 + PR_CREATE_TRACE( th, "Trace Test", "tt4", "QName is Trace Test, not TraceTest" ); 1.357 + PR_CREATE_TRACE( th, "Trace Test", "tt5", "QName is Trace Test, not TraceTest" ); 1.358 + PR_CREATE_TRACE( th, "Trace Test", "tt6", "QName is Trace Test, not TraceTest" ); 1.359 + PR_CREATE_TRACE( th, "Trace Test", "tt7", "QName is Trace Test, not TraceTest" ); 1.360 + PR_CREATE_TRACE( th, "Trace Test", "tt8", "QName is Trace Test, not TraceTest" ); 1.361 + PR_CREATE_TRACE( th, "Trace Test", "tt9", "QName is Trace Test, not TraceTest" ); 1.362 + PR_CREATE_TRACE( th, "Trace Test", "tt10", "QName is Trace Test, not TraceTest" ); 1.363 + 1.364 + 1.365 + 1.366 + activeThreads += 2; 1.367 + t1 = PR_CreateThread(PR_USER_THREAD, 1.368 + RecordTrace, NULL, 1.369 + PR_PRIORITY_NORMAL, 1.370 + PR_GLOBAL_THREAD, 1.371 + PR_UNJOINABLE_THREAD, 1.372 + 0); 1.373 + PR_ASSERT(t1); 1.374 + 1.375 + t2 = PR_CreateThread(PR_USER_THREAD, 1.376 + SampleTrace, 0, 1.377 + PR_PRIORITY_NORMAL, 1.378 + PR_GLOBAL_THREAD, 1.379 + PR_UNJOINABLE_THREAD, 1.380 + 0); 1.381 + PR_ASSERT(t2); 1.382 + 1.383 + ListTraces(); 1.384 + 1.385 + PR_GET_TRACE_HANDLE_FROM_NAME( th, "TraceTest","tt1" ); 1.386 + PR_ASSERT( th == hTrace ); 1.387 + 1.388 + PR_LOG( lm, msgLevel, 1.389 + ("End TraceTest")); 1.390 + return; 1.391 +} /* end TraceTest() */ 1.392 + 1.393 + 1.394 +/* 1.395 +** Ordered lock test. 1.396 +*/ 1.397 +static void OrderedLockTest( void ) 1.398 +{ 1.399 + PR_LOG( lm, msgLevel, 1.400 + ("Begin OrderedLockTest")); 1.401 + 1.402 + 1.403 +} /* end OrderedLockTest() */ 1.404 + 1.405 + 1.406 +int main(int argc, char **argv) 1.407 +{ 1.408 +#if defined(DEBUG) || defined(FORCE_NSPR_TRACE) 1.409 + PRUint32 counter; 1.410 + PLOptStatus os; 1.411 + PLOptState *opt = PL_CreateOptState(argc, argv, "hdv:"); 1.412 + lm = PR_NewLogModule("Test"); 1.413 + 1.414 + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) 1.415 + { 1.416 + if (PL_OPT_BAD == os) continue; 1.417 + switch (opt->option) 1.418 + { 1.419 + case 'v': /* verbose mode */ 1.420 + msgLevel = (PRLogModuleLevel)atol( opt->value); 1.421 + break; 1.422 + case 'h': /* help message */ 1.423 + Help(); 1.424 + help = PR_TRUE; 1.425 + break; 1.426 + default: 1.427 + break; 1.428 + } 1.429 + } 1.430 + PL_DestroyOptState(opt); 1.431 + 1.432 + PR_CREATE_TRACE( hTrace, "TraceTest", "tt1", "A description for the trace test" ); 1.433 + mon = PR_NewMonitor(); 1.434 + PR_EnterMonitor( mon ); 1.435 + 1.436 + TraceTest(); 1.437 + CounterTest(); 1.438 + OrderedLockTest(); 1.439 + 1.440 + /* Wait for all threads to exit */ 1.441 + while ( activeThreads > 0 ) { 1.442 + if ( activeThreads == 1 ) 1.443 + PR_SET_TRACE_OPTION( PRTraceStopRecording, NULL ); 1.444 + PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); 1.445 + PR_GET_COUNTER( counter, hCounter ); 1.446 + } 1.447 + PR_ExitMonitor( mon ); 1.448 + 1.449 + /* 1.450 + ** Evaluate results 1.451 + */ 1.452 + PR_GET_COUNTER( counter, hCounter ); 1.453 + if ( counter != 0 ) 1.454 + { 1.455 + failed = PR_TRUE; 1.456 + PR_LOG( lm, msgLevel, 1.457 + ("Expected counter == 0, found: %ld", counter)); 1.458 + printf("FAIL\n"); 1.459 + } 1.460 + else 1.461 + { 1.462 + printf("PASS\n"); 1.463 + } 1.464 + 1.465 + 1.466 + PR_DESTROY_COUNTER( hCounter ); 1.467 + 1.468 + PR_DestroyMonitor( mon ); 1.469 + 1.470 + PR_TRACE( hTrace, TraceFlow, 0xfff,0,0,0,0,0,0); 1.471 + PR_DESTROY_TRACE( hTrace ); 1.472 +#else 1.473 + printf("Test not defined\n"); 1.474 +#endif 1.475 + return 0; 1.476 +} /* main() */ 1.477 +/* end instrumt.c */ 1.478 +