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());