instrumt.c 13 KB

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