CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / nsprpub / lib / tests / arena.c
blob9c74479cbd7e98d3ea2f336c122c578b347347b2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is the Netscape Portable Runtime (NSPR).
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
39 ** File: arena.c
40 ** Description: Testing arenas
44 #include <string.h>
45 #include <time.h>
46 #include <stdlib.h>
47 #include "nspr.h"
48 #include "plarena.h"
49 #include "plgetopt.h"
51 PRLogModuleInfo *tLM;
52 PRIntn threadCount = 0;
53 PRMonitor *tMon;
54 PRBool failed_already = PR_FALSE;
56 /* Arguments from the command line with default values */
57 PRIntn debug_mode = 0;
58 PRIntn poolMin = 4096;
59 PRIntn poolMax = (100 * 4096);
60 PRIntn arenaMin = 40;
61 PRIntn arenaMax = (100 * 40);
62 PRIntn stressIterations = 15;
63 PRIntn maxAlloc = (1024 * 1024);
64 PRIntn stressThreads = 4;
66 void DumpAll( void )
68 return;
72 ** Test Arena allocation.
74 static void ArenaAllocate( void )
76 PLArenaPool ap;
77 void *ptr;
78 PRInt32 i;
80 PL_InitArenaPool( &ap, "AllocArena", 2048, sizeof(double));
81 PR_LOG( tLM, PR_LOG_DEBUG, ("AA, InitPool -- Pool: %p. first: %p, current: %p, size: %d",
82 &ap, ap.first, ap.current, ap.arenasize ));
84 for( i = 0; i < 150; i++ )
86 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
87 PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
88 &ap, ap.first, ap.current, ap.arenasize ));
89 PR_LOG( tLM, PR_LOG_DEBUG,(
90 "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
93 PL_FreeArenaPool( &ap );
95 for( i = 0; i < 221; i++ )
97 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
98 PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
99 &ap, ap.first, ap.current, ap.arenasize ));
100 PR_LOG( tLM, PR_LOG_DEBUG,(
101 "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
104 PL_FreeArenaPool( &ap );
106 return;
107 } /* end ArenaGrow() */
109 ** Test Arena grow.
111 static void ArenaGrow( void )
113 PLArenaPool ap;
114 void *ptr;
115 PRInt32 i;
117 PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
118 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
120 PR_LOG( tLM, PR_LOG_DEBUG, ("Before growth -- Pool: %p. alloc: %p ", &ap, ptr ));
122 for( i = 0; i < 10; i++ )
124 PL_ARENA_GROW( ptr, &ap, 512, 7000 );
125 PR_LOG( tLM, PR_LOG_DEBUG, ("After growth -- Pool: %p. alloc: %p ", &ap, ptr ));
129 return;
130 } /* end ArenaGrow() */
134 ** Test arena Mark and Release.
136 static void MarkAndRelease( void )
138 PLArenaPool ap;
139 void *ptr = NULL;
140 void *mark0, *mark1;
141 PRIntn i;
143 PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
144 mark0 = PL_ARENA_MARK( &ap );
145 PR_LOG( tLM, PR_LOG_DEBUG,
146 ("mark0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m0: %p",
147 &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark0 ));
149 for( i = 0; i < 201; i++ )
151 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
152 PR_LOG( tLM, PR_LOG_DEBUG,
153 ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
154 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
157 mark1 = PL_ARENA_MARK( &ap );
158 PR_LOG( tLM, PR_LOG_DEBUG,
159 ("mark1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m1: %p",
160 &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark1 ));
163 for( i = 0; i < 225; i++ )
165 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
166 PR_LOG( tLM, PR_LOG_DEBUG,
167 ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
168 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
171 PL_ARENA_RELEASE( &ap, mark1 );
172 PR_LOG( tLM, PR_LOG_DEBUG,
173 ("Release-1: %p -- Pool: %p. first: %p, current: %p, size: %d",
174 mark1, &ap, ap.first, ap.current, ap.arenasize ));
176 for( i = 0; i < 20; i++ )
178 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
179 PR_LOG( tLM, PR_LOG_DEBUG,
180 ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
181 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
184 PL_ARENA_RELEASE( &ap, mark1 );
185 PR_LOG( tLM, PR_LOG_DEBUG,
186 ("Release-1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
187 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
189 PL_ARENA_RELEASE( &ap, mark0 );
190 PR_LOG( tLM, PR_LOG_DEBUG,
191 ("Release-0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
192 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
194 PL_FreeArenaPool( &ap );
195 PR_LOG( tLM, PR_LOG_DEBUG,
196 ("Free. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
197 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
199 PL_FinishArenaPool( &ap );
200 PR_LOG( tLM, PR_LOG_DEBUG,
201 ("Finish. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
202 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
204 return;
205 } /* end MarkAndRelease() */
208 ** RandSize() returns a random number in the range
209 ** min..max, rounded to the next doubleword
212 static PRIntn RandSize( PRIntn min, PRIntn max )
214 PRIntn sz = (rand() % (max -min)) + min + sizeof(double);
216 sz &= ~sizeof(double)-1;
218 return(sz);
223 ** StressThread()
224 ** A bunch of these beat on individual arenas
225 ** This tests the free_list protection.
228 static void PR_CALLBACK StressThread( void *arg )
230 PLArenaPool ap;
231 PRIntn i;
232 PRIntn sz;
233 void *ptr;
234 PRThread *tp = PR_GetCurrentThread();
236 PR_LOG( tLM, PR_LOG_DEBUG, ("Stress Thread %p started\n", PR_GetCurrentThread()));
237 PL_InitArenaPool( &ap, "TheArena", RandSize( poolMin, poolMax), sizeof(double));
239 for ( i = 0; i < stressIterations; i++ )
241 PRIntn allocated = 0;
243 while ( allocated < maxAlloc )
245 sz = RandSize( arenaMin, arenaMax );
246 PL_ARENA_ALLOCATE( ptr, &ap, sz );
247 if ( ptr == NULL )
249 PR_LOG( tLM, PR_LOG_ERROR, ("ARENA_ALLOCATE() returned NULL\n\tAllocated: %d\n", allocated));
250 break;
252 allocated += sz;
254 PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished one iteration\n", tp));
255 PL_FreeArenaPool( &ap );
257 PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished all iteration\n", tp));
258 PL_FinishArenaPool( &ap );
259 PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p after FinishArenaPool()\n", tp));
261 /* That's all folks! let's quit */
262 PR_EnterMonitor(tMon);
263 threadCount--;
264 PR_Notify(tMon);
265 PR_ExitMonitor(tMon);
266 return;
270 ** Stress()
271 ** Flog the hell out of arenas multi-threaded.
272 ** Do NOT pass an individual arena to another thread.
275 static void Stress( void )
277 PRThread *tt;
278 PRIntn i;
280 tMon = PR_NewMonitor();
282 for ( i = 0 ; i < stressThreads ; i++ )
284 PR_EnterMonitor(tMon);
285 tt = PR_CreateThread(PR_USER_THREAD,
286 StressThread,
287 NULL,
288 PR_PRIORITY_NORMAL,
289 PR_GLOBAL_THREAD,
290 PR_UNJOINABLE_THREAD,
292 threadCount++;
293 PR_ExitMonitor(tMon);
296 /* Wait for all threads to exit */
297 PR_EnterMonitor(tMon);
298 while ( threadCount != 0 )
300 PR_Wait(tMon, PR_INTERVAL_NO_TIMEOUT);
302 PR_ExitMonitor(tMon);
303 PR_DestroyMonitor(tMon);
305 return;
306 } /* end Stress() */
309 ** EvaluateResults()
310 ** uses failed_already to display results and set program
311 ** exit code.
313 static PRIntn EvaluateResults(void)
315 PRIntn rc = 0;
317 if ( failed_already == PR_TRUE )
319 PR_LOG( tLM, PR_LOG_DEBUG, ("FAIL\n"));
320 rc =1;
322 else
324 PR_LOG( tLM, PR_LOG_DEBUG, ("PASS\n"));
326 return(rc);
327 } /* EvaluateResults() */
329 void Help( void )
331 printf("arena [options]\n");
332 printf("where options are:\n");
333 printf("-p <n> minimum size of an arena pool. Default(%d)\n", poolMin);
334 printf("-P <n> maximum size of an arena pool. Default(%d)\n", poolMax);
335 printf("-a <n> minimum size of an arena allocation. Default(%d)\n", arenaMin);
336 printf("-A <n> maximum size of an arena allocation. Default(%d)\n", arenaMax);
337 printf("-i <n> number of iterations in a stress thread. Default(%d)\n", stressIterations);
338 printf("-s <n> maximum allocation for a single stress thread. Default(%d)\n", maxAlloc);
339 printf("-t <n> number of stress threads. Default(%d)\n", stressThreads );
340 printf("-d enable debug mode\n");
341 printf("\n");
342 exit(1);
345 PRIntn main(PRIntn argc, char *argv[])
347 PLOptStatus os;
348 PLOptState *opt = PL_CreateOptState(argc, argv, "dhp:P:a:A:i:s:t:");
349 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
351 if (PL_OPT_BAD == os) continue;
352 switch (opt->option)
354 case 'a': /* arena Min size */
355 arenaMin = atol( opt->value );
356 break;
357 case 'A': /* arena Max size */
358 arenaMax = atol( opt->value );
359 break;
360 case 'p': /* pool Min size */
361 poolMin = atol( opt->value );
362 break;
363 case 'P': /* pool Max size */
364 poolMax = atol( opt->value );
365 break;
366 case 'i': /* Iterations in stress tests */
367 stressIterations = atol( opt->value );
368 break;
369 case 's': /* storage to get per iteration */
370 maxAlloc = atol( opt->value );
371 break;
372 case 't': /* Number of stress threads to create */
373 stressThreads = atol( opt->value );
374 break;
375 case 'd': /* debug mode */
376 debug_mode = 1;
377 break;
378 case 'h': /* help */
379 default:
380 Help();
381 } /* end switch() */
382 } /* end while() */
383 PL_DestroyOptState(opt);
385 srand( (unsigned)time( NULL ) ); /* seed random number generator */
386 tLM = PR_NewLogModule("testcase");
389 #if 0
390 ArenaAllocate();
391 ArenaGrow();
392 #endif
394 MarkAndRelease();
396 Stress();
398 return(EvaluateResults());
399 } /* end main() */
401 /* arena.c */