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
) {
324 case 'a': /* arena Min size */
325 arenaMin
= atol( opt
->value
);
327 case 'A': /* arena Max size */
328 arenaMax
= atol( opt
->value
);
330 case 'p': /* pool Min size */
331 poolMin
= atol( opt
->value
);
333 case 'P': /* pool Max size */
334 poolMax
= atol( opt
->value
);
336 case 'i': /* Iterations in stress tests */
337 stressIterations
= atol( opt
->value
);
339 case 's': /* storage to get per iteration */
340 maxAlloc
= atol( opt
->value
);
342 case 't': /* Number of stress threads to create */
343 stressThreads
= atol( opt
->value
);
345 case 'd': /* debug mode */
353 PL_DestroyOptState(opt
);
355 srand( (unsigned)time( NULL
) ); /* seed random number generator */
356 tLM
= PR_NewLogModule("testcase");
368 return(EvaluateResults());