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
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.
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 ***** */
40 ** Description: Testing arenas
52 PRIntn threadCount
= 0;
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);
61 PRIntn arenaMax
= (100 * 40);
62 PRIntn stressIterations
= 15;
63 PRIntn maxAlloc
= (1024 * 1024);
64 PRIntn stressThreads
= 4;
72 ** Test Arena allocation.
74 static void ArenaAllocate( void )
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
);
107 } /* end ArenaGrow() */
111 static void ArenaGrow( void )
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
));
130 } /* end ArenaGrow() */
134 ** Test arena Mark and Release.
136 static void MarkAndRelease( void )
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
));
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;
224 ** A bunch of these beat on individual arenas
225 ** This tests the free_list protection.
228 static void PR_CALLBACK
StressThread( void *arg
)
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
);
249 PR_LOG( tLM
, PR_LOG_ERROR
, ("ARENA_ALLOCATE() returned NULL\n\tAllocated: %d\n", allocated
));
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
);
265 PR_ExitMonitor(tMon
);
271 ** Flog the hell out of arenas multi-threaded.
272 ** Do NOT pass an individual arena to another thread.
275 static void Stress( void )
280 tMon
= PR_NewMonitor();
282 for ( i
= 0 ; i
< stressThreads
; i
++ )
284 PR_EnterMonitor(tMon
);
285 tt
= PR_CreateThread(PR_USER_THREAD
,
290 PR_UNJOINABLE_THREAD
,
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
);
310 ** uses failed_already to display results and set program
313 static PRIntn
EvaluateResults(void)
317 if ( failed_already
== PR_TRUE
)
319 PR_LOG( tLM
, PR_LOG_DEBUG
, ("FAIL\n"));
324 PR_LOG( tLM
, PR_LOG_DEBUG
, ("PASS\n"));
327 } /* EvaluateResults() */
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");
345 PRIntn
main(PRIntn argc
, char *argv
[])
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;
354 case 'a': /* arena Min size */
355 arenaMin
= atol( opt
->value
);
357 case 'A': /* arena Max size */
358 arenaMax
= atol( opt
->value
);
360 case 'p': /* pool Min size */
361 poolMin
= atol( opt
->value
);
363 case 'P': /* pool Max size */
364 poolMax
= atol( opt
->value
);
366 case 'i': /* Iterations in stress tests */
367 stressIterations
= atol( opt
->value
);
369 case 's': /* storage to get per iteration */
370 maxAlloc
= atol( opt
->value
);
372 case 't': /* Number of stress threads to create */
373 stressThreads
= atol( opt
->value
);
375 case 'd': /* debug mode */
383 PL_DestroyOptState(opt
);
385 srand( (unsigned)time( NULL
) ); /* seed random number generator */
386 tLM
= PR_NewLogModule("testcase");
398 return(EvaluateResults());