nsprpub/pr/tests/instrumt.c

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rw-r--r--

Correct small whitespace inconsistency, lost while renaming variables.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 ** File: instrumt.c
michael@0 8 ** Description: This test is for the NSPR debug aids defined in
michael@0 9 ** prcountr.h, prtrace.h, prolock.h
michael@0 10 **
michael@0 11 ** The test case tests the three debug aids in NSPR:
michael@0 12 **
michael@0 13 ** Diagnostic messages can be enabled using "instrumt -v 6"
michael@0 14 ** This sets the msgLevel to something that PR_LOG() likes.
michael@0 15 ** Also define in the environment "NSPR_LOG_MODULES=Test:6"
michael@0 16 **
michael@0 17 ** CounterTest() tests the counter facility. This test
michael@0 18 ** creates 4 threads. Each thread either increments, decrements,
michael@0 19 ** adds to or subtracts from a counter, depending on an argument
michael@0 20 ** passed to the thread at thread-create time. Each of these threads
michael@0 21 ** does COUNT_LIMIT iterations doing its thing. When all 4 threads
michael@0 22 ** are done, the result of the counter is evaluated. If all was atomic,
michael@0 23 ** the the value of the counter should be zero.
michael@0 24 **
michael@0 25 ** TraceTest():
michael@0 26 ** This test mingles with the counter test. Counters trace.
michael@0 27 ** A thread to extract trace entries on the fly is started.
michael@0 28 ** A thread to dump trace entries to a file is started.
michael@0 29 **
michael@0 30 ** OrderedLockTest():
michael@0 31 **
michael@0 32 **
michael@0 33 **
michael@0 34 **
michael@0 35 **
michael@0 36 */
michael@0 37
michael@0 38 #include <stdio.h>
michael@0 39 #include <plstr.h>
michael@0 40 #include <prclist.h>
michael@0 41 #include <prmem.h>
michael@0 42 #include <plgetopt.h>
michael@0 43 #include <prlog.h>
michael@0 44 #include <prmon.h>
michael@0 45 #include <pratom.h>
michael@0 46 #include <prtrace.h>
michael@0 47 #include <prcountr.h>
michael@0 48 #include <prolock.h>
michael@0 49
michael@0 50 #define COUNT_LIMIT (10 * ( 1024))
michael@0 51
michael@0 52 #define SMALL_TRACE_BUFSIZE ( 60 * 1024 )
michael@0 53
michael@0 54 typedef enum
michael@0 55 {
michael@0 56 CountLoop = 1,
michael@0 57 TraceLoop = 2,
michael@0 58 TraceFlow = 3
michael@0 59 } TraceTypes;
michael@0 60
michael@0 61
michael@0 62 PRLogModuleLevel msgLevel = PR_LOG_ALWAYS;
michael@0 63
michael@0 64 PRBool help = PR_FALSE;
michael@0 65 PRBool failed = PR_FALSE;
michael@0 66
michael@0 67
michael@0 68 PRLogModuleInfo *lm;
michael@0 69 PRMonitor *mon;
michael@0 70 PRInt32 activeThreads = 0;
michael@0 71 PR_DEFINE_COUNTER( hCounter );
michael@0 72 PR_DEFINE_TRACE( hTrace );
michael@0 73
michael@0 74 static void Help(void)
michael@0 75 {
michael@0 76 printf("Help? ... Ha!\n");
michael@0 77 }
michael@0 78
michael@0 79 static void ListCounters(void)
michael@0 80 {
michael@0 81 PR_DEFINE_COUNTER( qh );
michael@0 82 PR_DEFINE_COUNTER( rh );
michael@0 83 const char *qn, *rn, *dn;
michael@0 84 const char **qname = &qn, **rname = &rn, **desc = &dn;
michael@0 85 PRUint32 tCtr;
michael@0 86
michael@0 87 PR_INIT_COUNTER_HANDLE( qh, NULL );
michael@0 88 PR_FIND_NEXT_COUNTER_QNAME(qh, qh );
michael@0 89 while ( qh != NULL )
michael@0 90 {
michael@0 91 PR_INIT_COUNTER_HANDLE( rh, NULL );
michael@0 92 PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh );
michael@0 93 while ( rh != NULL )
michael@0 94 {
michael@0 95 PR_GET_COUNTER_NAME_FROM_HANDLE( rh, qname, rname, desc );
michael@0 96 PR_GET_COUNTER(tCtr, rh);
michael@0 97 PR_LOG( lm, msgLevel,
michael@0 98 ( "QName: %s RName: %s Desc: %s Value: %ld\n",
michael@0 99 qn, rn, dn, tCtr ));
michael@0 100 PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh );
michael@0 101 }
michael@0 102 PR_FIND_NEXT_COUNTER_QNAME(qh, qh);
michael@0 103 }
michael@0 104 return;
michael@0 105 } /* end ListCounters() */
michael@0 106
michael@0 107 static void ListTraces(void)
michael@0 108 {
michael@0 109 PR_DEFINE_TRACE( qh );
michael@0 110 PR_DEFINE_TRACE( rh );
michael@0 111 const char *qn, *rn, *dn;
michael@0 112 const char **qname = &qn, **rname = &rn, **desc = &dn;
michael@0 113
michael@0 114 PR_INIT_TRACE_HANDLE( qh, NULL );
michael@0 115 PR_FIND_NEXT_TRACE_QNAME(qh, qh );
michael@0 116 while ( qh != NULL )
michael@0 117 {
michael@0 118 PR_INIT_TRACE_HANDLE( rh, NULL );
michael@0 119 PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh );
michael@0 120 while ( rh != NULL )
michael@0 121 {
michael@0 122 PR_GET_TRACE_NAME_FROM_HANDLE( rh, qname, rname, desc );
michael@0 123 PR_LOG( lm, msgLevel,
michael@0 124 ( "QName: %s RName: %s Desc: %s",
michael@0 125 qn, rn, dn ));
michael@0 126 PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh );
michael@0 127 }
michael@0 128 PR_FIND_NEXT_TRACE_QNAME(qh, qh);
michael@0 129 }
michael@0 130 return;
michael@0 131 } /* end ListCounters() */
michael@0 132
michael@0 133
michael@0 134 static PRInt32 one = 1;
michael@0 135 static PRInt32 two = 2;
michael@0 136 static PRInt32 three = 3;
michael@0 137 static PRInt32 four = 4;
michael@0 138
michael@0 139 /*
michael@0 140 ** Thread to iteratively count something.
michael@0 141 */
michael@0 142 static void PR_CALLBACK CountSomething( void *arg )
michael@0 143 {
michael@0 144 PRInt32 switchVar = *((PRInt32 *)arg);
michael@0 145 PRInt32 i;
michael@0 146
michael@0 147 PR_LOG( lm, msgLevel,
michael@0 148 ("CountSomething: begin thread %ld", switchVar ));
michael@0 149
michael@0 150 for ( i = 0; i < COUNT_LIMIT ; i++)
michael@0 151 {
michael@0 152 switch ( switchVar )
michael@0 153 {
michael@0 154 case 1 :
michael@0 155 PR_INCREMENT_COUNTER( hCounter );
michael@0 156 break;
michael@0 157 case 2 :
michael@0 158 PR_DECREMENT_COUNTER( hCounter );
michael@0 159 break;
michael@0 160 case 3 :
michael@0 161 PR_ADD_TO_COUNTER( hCounter, 1 );
michael@0 162 break;
michael@0 163 case 4 :
michael@0 164 PR_SUBTRACT_FROM_COUNTER( hCounter, 1 );
michael@0 165 break;
michael@0 166 default :
michael@0 167 PR_ASSERT( 0 );
michael@0 168 break;
michael@0 169 }
michael@0 170 PR_TRACE( hTrace, CountLoop, switchVar, i, 0, 0, 0, 0, 0 );
michael@0 171 } /* end for() */
michael@0 172
michael@0 173 PR_LOG( lm, msgLevel,
michael@0 174 ("CounterSomething: end thread %ld", switchVar ));
michael@0 175
michael@0 176 PR_EnterMonitor(mon);
michael@0 177 --activeThreads;
michael@0 178 PR_Notify( mon );
michael@0 179 PR_ExitMonitor(mon);
michael@0 180
michael@0 181 return;
michael@0 182 } /* end CountSomething() */
michael@0 183
michael@0 184 /*
michael@0 185 ** Create the counter threads.
michael@0 186 */
michael@0 187 static void CounterTest( void )
michael@0 188 {
michael@0 189 PRThread *t1, *t2, *t3, *t4;
michael@0 190 PRIntn i = 0;
michael@0 191 PR_DEFINE_COUNTER( tc );
michael@0 192 PR_DEFINE_COUNTER( zCounter );
michael@0 193
michael@0 194 PR_LOG( lm, msgLevel,
michael@0 195 ("Begin CounterTest"));
michael@0 196
michael@0 197 /*
michael@0 198 ** Test Get and Set of a counter.
michael@0 199 **
michael@0 200 */
michael@0 201 PR_CREATE_COUNTER( zCounter, "Atomic", "get/set test", "test get and set of counter" );
michael@0 202 PR_SET_COUNTER( zCounter, 9 );
michael@0 203 PR_GET_COUNTER( i, zCounter );
michael@0 204 if ( i != 9 )
michael@0 205 {
michael@0 206 failed = PR_TRUE;
michael@0 207 PR_LOG( lm, msgLevel,
michael@0 208 ("Counter set/get failed"));
michael@0 209 }
michael@0 210
michael@0 211 activeThreads += 4;
michael@0 212 PR_CREATE_COUNTER( hCounter, "Atomic", "SMP Tests", "test atomic nature of counter" );
michael@0 213
michael@0 214 PR_GET_COUNTER_HANDLE_FROM_NAME( tc, "Atomic", "SMP Tests" );
michael@0 215 PR_ASSERT( tc == hCounter );
michael@0 216
michael@0 217 t1 = PR_CreateThread(PR_USER_THREAD,
michael@0 218 CountSomething, &one,
michael@0 219 PR_PRIORITY_NORMAL,
michael@0 220 PR_GLOBAL_THREAD,
michael@0 221 PR_UNJOINABLE_THREAD,
michael@0 222 0);
michael@0 223 PR_ASSERT(t1);
michael@0 224
michael@0 225 t2 = PR_CreateThread(PR_USER_THREAD,
michael@0 226 CountSomething, &two,
michael@0 227 PR_PRIORITY_NORMAL,
michael@0 228 PR_GLOBAL_THREAD,
michael@0 229 PR_UNJOINABLE_THREAD,
michael@0 230 0);
michael@0 231 PR_ASSERT(t2);
michael@0 232
michael@0 233 t3 = PR_CreateThread(PR_USER_THREAD,
michael@0 234 CountSomething, &three,
michael@0 235 PR_PRIORITY_NORMAL,
michael@0 236 PR_GLOBAL_THREAD,
michael@0 237 PR_UNJOINABLE_THREAD,
michael@0 238 0);
michael@0 239 PR_ASSERT(t3);
michael@0 240
michael@0 241 t4 = PR_CreateThread(PR_USER_THREAD,
michael@0 242 CountSomething, &four,
michael@0 243 PR_PRIORITY_NORMAL,
michael@0 244 PR_GLOBAL_THREAD,
michael@0 245 PR_UNJOINABLE_THREAD,
michael@0 246 0);
michael@0 247 PR_ASSERT(t4);
michael@0 248
michael@0 249 PR_LOG( lm, msgLevel,
michael@0 250 ("Counter Threads started"));
michael@0 251
michael@0 252 ListCounters();
michael@0 253 return;
michael@0 254 } /* end CounterTest() */
michael@0 255
michael@0 256 /*
michael@0 257 ** Thread to dump trace buffer to a file.
michael@0 258 */
michael@0 259 static void PR_CALLBACK RecordTrace(void *arg )
michael@0 260 {
michael@0 261 PR_RECORD_TRACE_ENTRIES();
michael@0 262
michael@0 263 PR_EnterMonitor(mon);
michael@0 264 --activeThreads;
michael@0 265 PR_Notify( mon );
michael@0 266 PR_ExitMonitor(mon);
michael@0 267
michael@0 268 return;
michael@0 269 } /* end RecordTrace() */
michael@0 270
michael@0 271
michael@0 272
michael@0 273 #define NUM_TRACE_RECORDS ( 10000 )
michael@0 274 /*
michael@0 275 ** Thread to extract and print trace entries from the buffer.
michael@0 276 */
michael@0 277 static void PR_CALLBACK SampleTrace( void *arg )
michael@0 278 {
michael@0 279 #if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
michael@0 280 PRInt32 found, rc;
michael@0 281 PRTraceEntry *foundEntries;
michael@0 282 PRInt32 i;
michael@0 283
michael@0 284 foundEntries = (PRTraceEntry *)PR_Malloc( NUM_TRACE_RECORDS * sizeof(PRTraceEntry));
michael@0 285 PR_ASSERT(foundEntries != NULL );
michael@0 286
michael@0 287 do
michael@0 288 {
michael@0 289 rc = PR_GetTraceEntries( foundEntries, NUM_TRACE_RECORDS, &found);
michael@0 290 PR_LOG( lm, msgLevel,
michael@0 291 ("SampleTrace: Lost Data: %ld found: %ld", rc, found ));
michael@0 292
michael@0 293 if ( found != 0)
michael@0 294 {
michael@0 295 for ( i = 0 ; i < found; i++ )
michael@0 296 {
michael@0 297 PR_LOG( lm, msgLevel,
michael@0 298 ("SampleTrace, detail: Thread: %p, Time: %llX, UD0: %ld, UD1: %ld, UD2: %8.8ld",
michael@0 299 (foundEntries +i)->thread,
michael@0 300 (foundEntries +i)->time,
michael@0 301 (foundEntries +i)->userData[0],
michael@0 302 (foundEntries +i)->userData[1],
michael@0 303 (foundEntries +i)->userData[2] ));
michael@0 304 }
michael@0 305 }
michael@0 306 PR_Sleep(PR_MillisecondsToInterval(50));
michael@0 307 }
michael@0 308 while( found != 0 && activeThreads >= 1 );
michael@0 309
michael@0 310 PR_Free( foundEntries );
michael@0 311
michael@0 312 PR_EnterMonitor(mon);
michael@0 313 --activeThreads;
michael@0 314 PR_Notify( mon );
michael@0 315 PR_ExitMonitor(mon);
michael@0 316
michael@0 317 PR_LOG( lm, msgLevel,
michael@0 318 ("SampleTrace(): exiting"));
michael@0 319
michael@0 320 #endif
michael@0 321 return;
michael@0 322 } /* end RecordTrace() */
michael@0 323
michael@0 324 /*
michael@0 325 ** Basic trace test.
michael@0 326 */
michael@0 327 static void TraceTest( void )
michael@0 328 {
michael@0 329 PRInt32 i;
michael@0 330 PRInt32 size;
michael@0 331 PR_DEFINE_TRACE( th );
michael@0 332 PRThread *t1, *t2;
michael@0 333
michael@0 334 PR_LOG( lm, msgLevel,
michael@0 335 ("Begin TraceTest"));
michael@0 336
michael@0 337 size = SMALL_TRACE_BUFSIZE;
michael@0 338 PR_SET_TRACE_OPTION( PRTraceBufSize, &size );
michael@0 339 PR_GET_TRACE_OPTION( PRTraceBufSize, &i );
michael@0 340
michael@0 341 PR_CREATE_TRACE( th, "TraceTest", "tt2", "A description for the trace test" );
michael@0 342 PR_CREATE_TRACE( th, "TraceTest", "tt3", "A description for the trace test" );
michael@0 343 PR_CREATE_TRACE( th, "TraceTest", "tt4", "A description for the trace test" );
michael@0 344 PR_CREATE_TRACE( th, "TraceTest", "tt5", "A description for the trace test" );
michael@0 345 PR_CREATE_TRACE( th, "TraceTest", "tt6", "A description for the trace test" );
michael@0 346 PR_CREATE_TRACE( th, "TraceTest", "tt7", "A description for the trace test" );
michael@0 347 PR_CREATE_TRACE( th, "TraceTest", "tt8", "A description for the trace test" );
michael@0 348
michael@0 349 PR_CREATE_TRACE( th, "Trace Test", "tt0", "QName is Trace Test, not TraceTest" );
michael@0 350 PR_CREATE_TRACE( th, "Trace Test", "tt1", "QName is Trace Test, not TraceTest" );
michael@0 351 PR_CREATE_TRACE( th, "Trace Test", "tt2", "QName is Trace Test, not TraceTest" );
michael@0 352 PR_CREATE_TRACE( th, "Trace Test", "tt3", "QName is Trace Test, not TraceTest" );
michael@0 353 PR_CREATE_TRACE( th, "Trace Test", "tt4", "QName is Trace Test, not TraceTest" );
michael@0 354 PR_CREATE_TRACE( th, "Trace Test", "tt5", "QName is Trace Test, not TraceTest" );
michael@0 355 PR_CREATE_TRACE( th, "Trace Test", "tt6", "QName is Trace Test, not TraceTest" );
michael@0 356 PR_CREATE_TRACE( th, "Trace Test", "tt7", "QName is Trace Test, not TraceTest" );
michael@0 357 PR_CREATE_TRACE( th, "Trace Test", "tt8", "QName is Trace Test, not TraceTest" );
michael@0 358 PR_CREATE_TRACE( th, "Trace Test", "tt9", "QName is Trace Test, not TraceTest" );
michael@0 359 PR_CREATE_TRACE( th, "Trace Test", "tt10", "QName is Trace Test, not TraceTest" );
michael@0 360
michael@0 361
michael@0 362
michael@0 363 activeThreads += 2;
michael@0 364 t1 = PR_CreateThread(PR_USER_THREAD,
michael@0 365 RecordTrace, NULL,
michael@0 366 PR_PRIORITY_NORMAL,
michael@0 367 PR_GLOBAL_THREAD,
michael@0 368 PR_UNJOINABLE_THREAD,
michael@0 369 0);
michael@0 370 PR_ASSERT(t1);
michael@0 371
michael@0 372 t2 = PR_CreateThread(PR_USER_THREAD,
michael@0 373 SampleTrace, 0,
michael@0 374 PR_PRIORITY_NORMAL,
michael@0 375 PR_GLOBAL_THREAD,
michael@0 376 PR_UNJOINABLE_THREAD,
michael@0 377 0);
michael@0 378 PR_ASSERT(t2);
michael@0 379
michael@0 380 ListTraces();
michael@0 381
michael@0 382 PR_GET_TRACE_HANDLE_FROM_NAME( th, "TraceTest","tt1" );
michael@0 383 PR_ASSERT( th == hTrace );
michael@0 384
michael@0 385 PR_LOG( lm, msgLevel,
michael@0 386 ("End TraceTest"));
michael@0 387 return;
michael@0 388 } /* end TraceTest() */
michael@0 389
michael@0 390
michael@0 391 /*
michael@0 392 ** Ordered lock test.
michael@0 393 */
michael@0 394 static void OrderedLockTest( void )
michael@0 395 {
michael@0 396 PR_LOG( lm, msgLevel,
michael@0 397 ("Begin OrderedLockTest"));
michael@0 398
michael@0 399
michael@0 400 } /* end OrderedLockTest() */
michael@0 401
michael@0 402
michael@0 403 int main(int argc, char **argv)
michael@0 404 {
michael@0 405 #if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
michael@0 406 PRUint32 counter;
michael@0 407 PLOptStatus os;
michael@0 408 PLOptState *opt = PL_CreateOptState(argc, argv, "hdv:");
michael@0 409 lm = PR_NewLogModule("Test");
michael@0 410
michael@0 411 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
michael@0 412 {
michael@0 413 if (PL_OPT_BAD == os) continue;
michael@0 414 switch (opt->option)
michael@0 415 {
michael@0 416 case 'v': /* verbose mode */
michael@0 417 msgLevel = (PRLogModuleLevel)atol( opt->value);
michael@0 418 break;
michael@0 419 case 'h': /* help message */
michael@0 420 Help();
michael@0 421 help = PR_TRUE;
michael@0 422 break;
michael@0 423 default:
michael@0 424 break;
michael@0 425 }
michael@0 426 }
michael@0 427 PL_DestroyOptState(opt);
michael@0 428
michael@0 429 PR_CREATE_TRACE( hTrace, "TraceTest", "tt1", "A description for the trace test" );
michael@0 430 mon = PR_NewMonitor();
michael@0 431 PR_EnterMonitor( mon );
michael@0 432
michael@0 433 TraceTest();
michael@0 434 CounterTest();
michael@0 435 OrderedLockTest();
michael@0 436
michael@0 437 /* Wait for all threads to exit */
michael@0 438 while ( activeThreads > 0 ) {
michael@0 439 if ( activeThreads == 1 )
michael@0 440 PR_SET_TRACE_OPTION( PRTraceStopRecording, NULL );
michael@0 441 PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
michael@0 442 PR_GET_COUNTER( counter, hCounter );
michael@0 443 }
michael@0 444 PR_ExitMonitor( mon );
michael@0 445
michael@0 446 /*
michael@0 447 ** Evaluate results
michael@0 448 */
michael@0 449 PR_GET_COUNTER( counter, hCounter );
michael@0 450 if ( counter != 0 )
michael@0 451 {
michael@0 452 failed = PR_TRUE;
michael@0 453 PR_LOG( lm, msgLevel,
michael@0 454 ("Expected counter == 0, found: %ld", counter));
michael@0 455 printf("FAIL\n");
michael@0 456 }
michael@0 457 else
michael@0 458 {
michael@0 459 printf("PASS\n");
michael@0 460 }
michael@0 461
michael@0 462
michael@0 463 PR_DESTROY_COUNTER( hCounter );
michael@0 464
michael@0 465 PR_DestroyMonitor( mon );
michael@0 466
michael@0 467 PR_TRACE( hTrace, TraceFlow, 0xfff,0,0,0,0,0,0);
michael@0 468 PR_DESTROY_TRACE( hTrace );
michael@0 469 #else
michael@0 470 printf("Test not defined\n");
michael@0 471 #endif
michael@0 472 return 0;
michael@0 473 } /* main() */
michael@0 474 /* end instrumt.c */
michael@0 475

mercurial