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/. */
8 ** Description: Testing arenas
20 PRIntn threadCount = 0;
22 PRBool failed_already = PR_FALSE;
24 /* Arguments from the command line with default values */
25 PRIntn debug_mode = 0;
26 PRIntn poolMin = 4096;
27 PRIntn poolMax = (100 * 4096);
29 PRIntn arenaMax = (100 * 40);
30 PRIntn stressIterations = 15;
31 PRIntn maxAlloc = (1024 * 1024);
32 PRIntn stressThreads = 4;
40 ** Test Arena allocation.
42 static void ArenaAllocate( void )
48 PL_InitArenaPool( &ap, "AllocArena", 2048, sizeof(double));
49 PR_LOG( tLM, PR_LOG_DEBUG, ("AA, InitPool -- Pool: %p. first: %p, current: %p, size: %d",
50 &ap, ap.first, ap.current, ap.arenasize ));
52 for( i = 0; i < 150; i++ )
54 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
55 PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
56 &ap, ap.first, ap.current, ap.arenasize ));
57 PR_LOG( tLM, PR_LOG_DEBUG,(
58 "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
61 PL_FreeArenaPool( &ap );
63 for( i = 0; i < 221; i++ )
65 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
66 PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
67 &ap, ap.first, ap.current, ap.arenasize ));
68 PR_LOG( tLM, PR_LOG_DEBUG,(
69 "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
72 PL_FreeArenaPool( &ap );
75 } /* end ArenaGrow() */
79 static void ArenaGrow( void )
85 PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
86 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
88 PR_LOG( tLM, PR_LOG_DEBUG, ("Before growth -- Pool: %p. alloc: %p ", &ap, ptr ));
90 for( i = 0; i < 10; i++ )
92 PL_ARENA_GROW( ptr, &ap, 512, 7000 );
93 PR_LOG( tLM, PR_LOG_DEBUG, ("After growth -- Pool: %p. alloc: %p ", &ap, ptr ));
98 } /* end ArenaGrow() */
102 ** Test arena Mark and Release.
104 static void MarkAndRelease( void )
111 PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
112 mark0 = PL_ARENA_MARK( &ap );
113 PR_LOG( tLM, PR_LOG_DEBUG,
114 ("mark0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m0: %p",
115 &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark0 ));
117 for( i = 0; i < 201; i++ )
119 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
120 PR_LOG( tLM, PR_LOG_DEBUG,
121 ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
122 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
125 mark1 = PL_ARENA_MARK( &ap );
126 PR_LOG( tLM, PR_LOG_DEBUG,
127 ("mark1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m1: %p",
128 &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark1 ));
131 for( i = 0; i < 225; i++ )
133 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
134 PR_LOG( tLM, PR_LOG_DEBUG,
135 ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
136 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
139 PL_ARENA_RELEASE( &ap, mark1 );
140 PR_LOG( tLM, PR_LOG_DEBUG,
141 ("Release-1: %p -- Pool: %p. first: %p, current: %p, size: %d",
142 mark1, &ap, ap.first, ap.current, ap.arenasize ));
144 for( i = 0; i < 20; i++ )
146 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
147 PR_LOG( tLM, PR_LOG_DEBUG,
148 ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
149 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
152 PL_ARENA_RELEASE( &ap, mark1 );
153 PR_LOG( tLM, PR_LOG_DEBUG,
154 ("Release-1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
155 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
157 PL_ARENA_RELEASE( &ap, mark0 );
158 PR_LOG( tLM, PR_LOG_DEBUG,
159 ("Release-0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
160 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
162 PL_FreeArenaPool( &ap );
163 PR_LOG( tLM, PR_LOG_DEBUG,
164 ("Free. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
165 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
167 PL_FinishArenaPool( &ap );
168 PR_LOG( tLM, PR_LOG_DEBUG,
169 ("Finish. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
170 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
173 } /* end MarkAndRelease() */
176 ** RandSize() returns a random number in the range
177 ** min..max, rounded to the next doubleword
180 static PRIntn RandSize( PRIntn min, PRIntn max )
182 PRIntn sz = (rand() % (max -min)) + min + sizeof(double);
184 sz &= ~sizeof(double)-1;
192 ** A bunch of these beat on individual arenas
193 ** This tests the free_list protection.
196 static void PR_CALLBACK StressThread( void *arg )
202 PRThread *tp = PR_GetCurrentThread();
204 PR_LOG( tLM, PR_LOG_DEBUG, ("Stress Thread %p started\n", PR_GetCurrentThread()));
205 PL_InitArenaPool( &ap, "TheArena", RandSize( poolMin, poolMax), sizeof(double));
207 for ( i = 0; i < stressIterations; i++ )
209 PRIntn allocated = 0;
211 while ( allocated < maxAlloc )
213 sz = RandSize( arenaMin, arenaMax );
214 PL_ARENA_ALLOCATE( ptr, &ap, sz );
217 PR_LOG( tLM, PR_LOG_ERROR, ("ARENA_ALLOCATE() returned NULL\n\tAllocated: %d\n", allocated));
222 PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished one iteration\n", tp));
223 PL_FreeArenaPool( &ap );
225 PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished all iteration\n", tp));
226 PL_FinishArenaPool( &ap );
227 PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p after FinishArenaPool()\n", tp));
229 /* That's all folks! let's quit */
230 PR_EnterMonitor(tMon);
233 PR_ExitMonitor(tMon);
239 ** Flog the hell out of arenas multi-threaded.
240 ** Do NOT pass an individual arena to another thread.
243 static void Stress( void )
248 tMon = PR_NewMonitor();
250 for ( i = 0 ; i < stressThreads ; i++ )
252 PR_EnterMonitor(tMon);
253 tt = PR_CreateThread(PR_USER_THREAD,
258 PR_UNJOINABLE_THREAD,
261 PR_ExitMonitor(tMon);
264 /* Wait for all threads to exit */
265 PR_EnterMonitor(tMon);
266 while ( threadCount != 0 )
268 PR_Wait(tMon, PR_INTERVAL_NO_TIMEOUT);
270 PR_ExitMonitor(tMon);
271 PR_DestroyMonitor(tMon);
278 ** uses failed_already to display results and set program
281 static PRIntn EvaluateResults(void)
285 if ( failed_already == PR_TRUE )
287 PR_LOG( tLM, PR_LOG_DEBUG, ("FAIL\n"));
292 PR_LOG( tLM, PR_LOG_DEBUG, ("PASS\n"));
295 } /* EvaluateResults() */
299 printf("arena [options]\n");
300 printf("where options are:\n");
301 printf("-p <n> minimum size of an arena pool. Default(%d)\n", poolMin);
302 printf("-P <n> maximum size of an arena pool. Default(%d)\n", poolMax);
303 printf("-a <n> minimum size of an arena allocation. Default(%d)\n", arenaMin);
304 printf("-A <n> maximum size of an arena allocation. Default(%d)\n", arenaMax);
305 printf("-i <n> number of iterations in a stress thread. Default(%d)\n", stressIterations);
306 printf("-s <n> maximum allocation for a single stress thread. Default(%d)\n", maxAlloc);
307 printf("-t <n> number of stress threads. Default(%d)\n", stressThreads );
308 printf("-d enable debug mode\n");
313 PRIntn main(PRIntn argc, char *argv[])
316 PLOptState *opt = PL_CreateOptState(argc, argv, "dhp:P:a:A:i:s:t:");
317 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
319 if (PL_OPT_BAD == os) continue;
322 case 'a': /* arena Min size */
323 arenaMin = atol( opt->value );
325 case 'A': /* arena Max size */
326 arenaMax = atol( opt->value );
328 case 'p': /* pool Min size */
329 poolMin = atol( opt->value );
331 case 'P': /* pool Max size */
332 poolMax = atol( opt->value );
334 case 'i': /* Iterations in stress tests */
335 stressIterations = atol( opt->value );
337 case 's': /* storage to get per iteration */
338 maxAlloc = atol( opt->value );
340 case 't': /* Number of stress threads to create */
341 stressThreads = atol( opt->value );
343 case 'd': /* debug mode */
351 PL_DestroyOptState(opt);
353 srand( (unsigned)time( NULL ) ); /* seed random number generator */
354 tLM = PR_NewLogModule("testcase");
366 return(EvaluateResults());