arena.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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: arena.c
  7. ** Description: Testing arenas
  8. **
  9. */
  10. #include <string.h>
  11. #include <time.h>
  12. #include <stdlib.h>
  13. #include "nspr.h"
  14. #include "plarena.h"
  15. #include "plgetopt.h"
  16. PRLogModuleInfo *tLM;
  17. PRIntn threadCount = 0;
  18. PRMonitor *tMon;
  19. PRBool failed_already = PR_FALSE;
  20. /* Arguments from the command line with default values */
  21. PRIntn debug_mode = 0;
  22. PRIntn poolMin = 4096;
  23. PRIntn poolMax = (100 * 4096);
  24. PRIntn arenaMin = 40;
  25. PRIntn arenaMax = (100 * 40);
  26. PRIntn stressIterations = 15;
  27. PRIntn maxAlloc = (1024 * 1024);
  28. PRIntn stressThreads = 4;
  29. void DumpAll( void )
  30. {
  31. return;
  32. }
  33. /*
  34. ** Test Arena allocation.
  35. */
  36. static void ArenaAllocate( void )
  37. {
  38. PLArenaPool ap;
  39. void *ptr;
  40. PRInt32 i;
  41. PL_InitArenaPool( &ap, "AllocArena", 2048, sizeof(double));
  42. PR_LOG( tLM, PR_LOG_DEBUG, ("AA, InitPool -- Pool: %p. first: %p, current: %p, size: %d",
  43. &ap, ap.first, ap.current, ap.arenasize ));
  44. for( i = 0; i < 150; i++ )
  45. {
  46. PL_ARENA_ALLOCATE( ptr, &ap, 512 );
  47. PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
  48. &ap, ap.first, ap.current, ap.arenasize ));
  49. PR_LOG( tLM, PR_LOG_DEBUG,(
  50. "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
  51. }
  52. PL_FreeArenaPool( &ap );
  53. for( i = 0; i < 221; i++ )
  54. {
  55. PL_ARENA_ALLOCATE( ptr, &ap, 512 );
  56. PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
  57. &ap, ap.first, ap.current, ap.arenasize ));
  58. PR_LOG( tLM, PR_LOG_DEBUG,(
  59. "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
  60. }
  61. PL_FreeArenaPool( &ap );
  62. return;
  63. } /* end ArenaGrow() */
  64. /*
  65. ** Test Arena grow.
  66. */
  67. static void ArenaGrow( void )
  68. {
  69. PLArenaPool ap;
  70. void *ptr;
  71. PRInt32 i;
  72. PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
  73. PL_ARENA_ALLOCATE( ptr, &ap, 512 );
  74. PR_LOG( tLM, PR_LOG_DEBUG, ("Before growth -- Pool: %p. alloc: %p ", &ap, ptr ));
  75. for( i = 0; i < 10; i++ )
  76. {
  77. PL_ARENA_GROW( ptr, &ap, 512, 7000 );
  78. PR_LOG( tLM, PR_LOG_DEBUG, ("After growth -- Pool: %p. alloc: %p ", &ap, ptr ));
  79. }
  80. return;
  81. } /* end ArenaGrow() */
  82. /*
  83. ** Test arena Mark and Release.
  84. */
  85. static void MarkAndRelease( void )
  86. {
  87. PLArenaPool ap;
  88. void *ptr = NULL;
  89. void *mark0, *mark1;
  90. PRIntn i;
  91. PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
  92. mark0 = PL_ARENA_MARK( &ap );
  93. PR_LOG( tLM, PR_LOG_DEBUG,
  94. ("mark0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m0: %p",
  95. &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark0 ));
  96. for( i = 0; i < 201; i++ )
  97. {
  98. PL_ARENA_ALLOCATE( ptr, &ap, 512 );
  99. PR_LOG( tLM, PR_LOG_DEBUG,
  100. ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
  101. &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
  102. }
  103. mark1 = PL_ARENA_MARK( &ap );
  104. PR_LOG( tLM, PR_LOG_DEBUG,
  105. ("mark1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m1: %p",
  106. &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark1 ));
  107. for( i = 0; i < 225; i++ )
  108. {
  109. PL_ARENA_ALLOCATE( ptr, &ap, 512 );
  110. PR_LOG( tLM, PR_LOG_DEBUG,
  111. ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
  112. &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
  113. }
  114. PL_ARENA_RELEASE( &ap, mark1 );
  115. PR_LOG( tLM, PR_LOG_DEBUG,
  116. ("Release-1: %p -- Pool: %p. first: %p, current: %p, size: %d",
  117. mark1, &ap, ap.first, ap.current, ap.arenasize ));
  118. for( i = 0; i < 20; i++ )
  119. {
  120. PL_ARENA_ALLOCATE( ptr, &ap, 512 );
  121. PR_LOG( tLM, PR_LOG_DEBUG,
  122. ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
  123. &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
  124. }
  125. PL_ARENA_RELEASE( &ap, mark1 );
  126. PR_LOG( tLM, PR_LOG_DEBUG,
  127. ("Release-1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
  128. &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
  129. PL_ARENA_RELEASE( &ap, mark0 );
  130. PR_LOG( tLM, PR_LOG_DEBUG,
  131. ("Release-0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
  132. &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
  133. PL_FreeArenaPool( &ap );
  134. PR_LOG( tLM, PR_LOG_DEBUG,
  135. ("Free. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
  136. &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
  137. PL_FinishArenaPool( &ap );
  138. PR_LOG( tLM, PR_LOG_DEBUG,
  139. ("Finish. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
  140. &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
  141. return;
  142. } /* end MarkAndRelease() */
  143. /*
  144. ** RandSize() returns a random number in the range
  145. ** min..max, rounded to the next doubleword
  146. **
  147. */
  148. static PRIntn RandSize( PRIntn min, PRIntn max )
  149. {
  150. PRIntn sz = (rand() % (max -min)) + min + sizeof(double);
  151. sz &= ~sizeof(double)-1;
  152. return(sz);
  153. }
  154. /*
  155. ** StressThread()
  156. ** A bunch of these beat on individual arenas
  157. ** This tests the free_list protection.
  158. **
  159. */
  160. static void PR_CALLBACK StressThread( void *arg )
  161. {
  162. PLArenaPool ap;
  163. PRIntn i;
  164. PRIntn sz;
  165. void *ptr;
  166. PRThread *tp = PR_GetCurrentThread();
  167. PR_LOG( tLM, PR_LOG_DEBUG, ("Stress Thread %p started\n", PR_GetCurrentThread()));
  168. PL_InitArenaPool( &ap, "TheArena", RandSize( poolMin, poolMax), sizeof(double));
  169. for ( i = 0; i < stressIterations; i++ )
  170. {
  171. PRIntn allocated = 0;
  172. while ( allocated < maxAlloc )
  173. {
  174. sz = RandSize( arenaMin, arenaMax );
  175. PL_ARENA_ALLOCATE( ptr, &ap, sz );
  176. if ( ptr == NULL )
  177. {
  178. PR_LOG( tLM, PR_LOG_ERROR, ("ARENA_ALLOCATE() returned NULL\n\tAllocated: %d\n", allocated));
  179. break;
  180. }
  181. allocated += sz;
  182. }
  183. PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished one iteration\n", tp));
  184. PL_FreeArenaPool( &ap );
  185. }
  186. PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished all iteration\n", tp));
  187. PL_FinishArenaPool( &ap );
  188. PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p after FinishArenaPool()\n", tp));
  189. /* That's all folks! let's quit */
  190. PR_EnterMonitor(tMon);
  191. threadCount--;
  192. PR_Notify(tMon);
  193. PR_ExitMonitor(tMon);
  194. return;
  195. }
  196. /*
  197. ** Stress()
  198. ** Flog the hell out of arenas multi-threaded.
  199. ** Do NOT pass an individual arena to another thread.
  200. **
  201. */
  202. static void Stress( void )
  203. {
  204. PRThread *tt;
  205. PRIntn i;
  206. tMon = PR_NewMonitor();
  207. for ( i = 0 ; i < stressThreads ; i++ )
  208. {
  209. PR_EnterMonitor(tMon);
  210. tt = PR_CreateThread(PR_USER_THREAD,
  211. StressThread,
  212. NULL,
  213. PR_PRIORITY_NORMAL,
  214. PR_GLOBAL_THREAD,
  215. PR_UNJOINABLE_THREAD,
  216. 0);
  217. threadCount++;
  218. PR_ExitMonitor(tMon);
  219. }
  220. /* Wait for all threads to exit */
  221. PR_EnterMonitor(tMon);
  222. while ( threadCount != 0 )
  223. {
  224. PR_Wait(tMon, PR_INTERVAL_NO_TIMEOUT);
  225. }
  226. PR_ExitMonitor(tMon);
  227. PR_DestroyMonitor(tMon);
  228. return;
  229. } /* end Stress() */
  230. /*
  231. ** EvaluateResults()
  232. ** uses failed_already to display results and set program
  233. ** exit code.
  234. */
  235. static PRIntn EvaluateResults(void)
  236. {
  237. PRIntn rc = 0;
  238. if ( failed_already == PR_TRUE )
  239. {
  240. PR_LOG( tLM, PR_LOG_DEBUG, ("FAIL\n"));
  241. rc =1;
  242. }
  243. else
  244. {
  245. PR_LOG( tLM, PR_LOG_DEBUG, ("PASS\n"));
  246. }
  247. return(rc);
  248. } /* EvaluateResults() */
  249. void Help( void )
  250. {
  251. printf("arena [options]\n");
  252. printf("where options are:\n");
  253. printf("-p <n> minimum size of an arena pool. Default(%d)\n", poolMin);
  254. printf("-P <n> maximum size of an arena pool. Default(%d)\n", poolMax);
  255. printf("-a <n> minimum size of an arena allocation. Default(%d)\n", arenaMin);
  256. printf("-A <n> maximum size of an arena allocation. Default(%d)\n", arenaMax);
  257. printf("-i <n> number of iterations in a stress thread. Default(%d)\n", stressIterations);
  258. printf("-s <n> maximum allocation for a single stress thread. Default(%d)\n", maxAlloc);
  259. printf("-t <n> number of stress threads. Default(%d)\n", stressThreads );
  260. printf("-d enable debug mode\n");
  261. printf("\n");
  262. exit(1);
  263. }
  264. PRIntn main(PRIntn argc, char *argv[])
  265. {
  266. PLOptStatus os;
  267. PLOptState *opt = PL_CreateOptState(argc, argv, "dhp:P:a:A:i:s:t:");
  268. while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
  269. {
  270. if (PL_OPT_BAD == os) {
  271. continue;
  272. }
  273. switch (opt->option)
  274. {
  275. case 'a': /* arena Min size */
  276. arenaMin = atol( opt->value );
  277. break;
  278. case 'A': /* arena Max size */
  279. arenaMax = atol( opt->value );
  280. break;
  281. case 'p': /* pool Min size */
  282. poolMin = atol( opt->value );
  283. break;
  284. case 'P': /* pool Max size */
  285. poolMax = atol( opt->value );
  286. break;
  287. case 'i': /* Iterations in stress tests */
  288. stressIterations = atol( opt->value );
  289. break;
  290. case 's': /* storage to get per iteration */
  291. maxAlloc = atol( opt->value );
  292. break;
  293. case 't': /* Number of stress threads to create */
  294. stressThreads = atol( opt->value );
  295. break;
  296. case 'd': /* debug mode */
  297. debug_mode = 1;
  298. break;
  299. case 'h': /* help */
  300. default:
  301. Help();
  302. } /* end switch() */
  303. } /* end while() */
  304. PL_DestroyOptState(opt);
  305. srand( (unsigned)time( NULL ) ); /* seed random number generator */
  306. tLM = PR_NewLogModule("testcase");
  307. #if 0
  308. ArenaAllocate();
  309. ArenaGrow();
  310. #endif
  311. MarkAndRelease();
  312. Stress();
  313. return(EvaluateResults());
  314. } /* end main() */
  315. /* arena.c */