nsprpub/lib/tests/arena.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 ** File: arena.c
michael@0 8 ** Description: Testing arenas
michael@0 9 **
michael@0 10 */
michael@0 11
michael@0 12 #include <string.h>
michael@0 13 #include <time.h>
michael@0 14 #include <stdlib.h>
michael@0 15 #include "nspr.h"
michael@0 16 #include "plarena.h"
michael@0 17 #include "plgetopt.h"
michael@0 18
michael@0 19 PRLogModuleInfo *tLM;
michael@0 20 PRIntn threadCount = 0;
michael@0 21 PRMonitor *tMon;
michael@0 22 PRBool failed_already = PR_FALSE;
michael@0 23
michael@0 24 /* Arguments from the command line with default values */
michael@0 25 PRIntn debug_mode = 0;
michael@0 26 PRIntn poolMin = 4096;
michael@0 27 PRIntn poolMax = (100 * 4096);
michael@0 28 PRIntn arenaMin = 40;
michael@0 29 PRIntn arenaMax = (100 * 40);
michael@0 30 PRIntn stressIterations = 15;
michael@0 31 PRIntn maxAlloc = (1024 * 1024);
michael@0 32 PRIntn stressThreads = 4;
michael@0 33
michael@0 34 void DumpAll( void )
michael@0 35 {
michael@0 36 return;
michael@0 37 }
michael@0 38
michael@0 39 /*
michael@0 40 ** Test Arena allocation.
michael@0 41 */
michael@0 42 static void ArenaAllocate( void )
michael@0 43 {
michael@0 44 PLArenaPool ap;
michael@0 45 void *ptr;
michael@0 46 PRInt32 i;
michael@0 47
michael@0 48 PL_InitArenaPool( &ap, "AllocArena", 2048, sizeof(double));
michael@0 49 PR_LOG( tLM, PR_LOG_DEBUG, ("AA, InitPool -- Pool: %p. first: %p, current: %p, size: %d",
michael@0 50 &ap, ap.first, ap.current, ap.arenasize ));
michael@0 51
michael@0 52 for( i = 0; i < 150; i++ )
michael@0 53 {
michael@0 54 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
michael@0 55 PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
michael@0 56 &ap, ap.first, ap.current, ap.arenasize ));
michael@0 57 PR_LOG( tLM, PR_LOG_DEBUG,(
michael@0 58 "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
michael@0 59 }
michael@0 60
michael@0 61 PL_FreeArenaPool( &ap );
michael@0 62
michael@0 63 for( i = 0; i < 221; i++ )
michael@0 64 {
michael@0 65 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
michael@0 66 PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
michael@0 67 &ap, ap.first, ap.current, ap.arenasize ));
michael@0 68 PR_LOG( tLM, PR_LOG_DEBUG,(
michael@0 69 "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
michael@0 70 }
michael@0 71
michael@0 72 PL_FreeArenaPool( &ap );
michael@0 73
michael@0 74 return;
michael@0 75 } /* end ArenaGrow() */
michael@0 76 /*
michael@0 77 ** Test Arena grow.
michael@0 78 */
michael@0 79 static void ArenaGrow( void )
michael@0 80 {
michael@0 81 PLArenaPool ap;
michael@0 82 void *ptr;
michael@0 83 PRInt32 i;
michael@0 84
michael@0 85 PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
michael@0 86 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
michael@0 87
michael@0 88 PR_LOG( tLM, PR_LOG_DEBUG, ("Before growth -- Pool: %p. alloc: %p ", &ap, ptr ));
michael@0 89
michael@0 90 for( i = 0; i < 10; i++ )
michael@0 91 {
michael@0 92 PL_ARENA_GROW( ptr, &ap, 512, 7000 );
michael@0 93 PR_LOG( tLM, PR_LOG_DEBUG, ("After growth -- Pool: %p. alloc: %p ", &ap, ptr ));
michael@0 94 }
michael@0 95
michael@0 96
michael@0 97 return;
michael@0 98 } /* end ArenaGrow() */
michael@0 99
michael@0 100
michael@0 101 /*
michael@0 102 ** Test arena Mark and Release.
michael@0 103 */
michael@0 104 static void MarkAndRelease( void )
michael@0 105 {
michael@0 106 PLArenaPool ap;
michael@0 107 void *ptr = NULL;
michael@0 108 void *mark0, *mark1;
michael@0 109 PRIntn i;
michael@0 110
michael@0 111 PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
michael@0 112 mark0 = PL_ARENA_MARK( &ap );
michael@0 113 PR_LOG( tLM, PR_LOG_DEBUG,
michael@0 114 ("mark0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m0: %p",
michael@0 115 &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark0 ));
michael@0 116
michael@0 117 for( i = 0; i < 201; i++ )
michael@0 118 {
michael@0 119 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
michael@0 120 PR_LOG( tLM, PR_LOG_DEBUG,
michael@0 121 ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
michael@0 122 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
michael@0 123 }
michael@0 124
michael@0 125 mark1 = PL_ARENA_MARK( &ap );
michael@0 126 PR_LOG( tLM, PR_LOG_DEBUG,
michael@0 127 ("mark1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m1: %p",
michael@0 128 &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark1 ));
michael@0 129
michael@0 130
michael@0 131 for( i = 0; i < 225; i++ )
michael@0 132 {
michael@0 133 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
michael@0 134 PR_LOG( tLM, PR_LOG_DEBUG,
michael@0 135 ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
michael@0 136 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
michael@0 137 }
michael@0 138
michael@0 139 PL_ARENA_RELEASE( &ap, mark1 );
michael@0 140 PR_LOG( tLM, PR_LOG_DEBUG,
michael@0 141 ("Release-1: %p -- Pool: %p. first: %p, current: %p, size: %d",
michael@0 142 mark1, &ap, ap.first, ap.current, ap.arenasize ));
michael@0 143
michael@0 144 for( i = 0; i < 20; i++ )
michael@0 145 {
michael@0 146 PL_ARENA_ALLOCATE( ptr, &ap, 512 );
michael@0 147 PR_LOG( tLM, PR_LOG_DEBUG,
michael@0 148 ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
michael@0 149 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
michael@0 150 }
michael@0 151
michael@0 152 PL_ARENA_RELEASE( &ap, mark1 );
michael@0 153 PR_LOG( tLM, PR_LOG_DEBUG,
michael@0 154 ("Release-1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
michael@0 155 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
michael@0 156
michael@0 157 PL_ARENA_RELEASE( &ap, mark0 );
michael@0 158 PR_LOG( tLM, PR_LOG_DEBUG,
michael@0 159 ("Release-0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
michael@0 160 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
michael@0 161
michael@0 162 PL_FreeArenaPool( &ap );
michael@0 163 PR_LOG( tLM, PR_LOG_DEBUG,
michael@0 164 ("Free. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
michael@0 165 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
michael@0 166
michael@0 167 PL_FinishArenaPool( &ap );
michael@0 168 PR_LOG( tLM, PR_LOG_DEBUG,
michael@0 169 ("Finish. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
michael@0 170 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
michael@0 171
michael@0 172 return;
michael@0 173 } /* end MarkAndRelease() */
michael@0 174
michael@0 175 /*
michael@0 176 ** RandSize() returns a random number in the range
michael@0 177 ** min..max, rounded to the next doubleword
michael@0 178 **
michael@0 179 */
michael@0 180 static PRIntn RandSize( PRIntn min, PRIntn max )
michael@0 181 {
michael@0 182 PRIntn sz = (rand() % (max -min)) + min + sizeof(double);
michael@0 183
michael@0 184 sz &= ~sizeof(double)-1;
michael@0 185
michael@0 186 return(sz);
michael@0 187 }
michael@0 188
michael@0 189
michael@0 190 /*
michael@0 191 ** StressThread()
michael@0 192 ** A bunch of these beat on individual arenas
michael@0 193 ** This tests the free_list protection.
michael@0 194 **
michael@0 195 */
michael@0 196 static void PR_CALLBACK StressThread( void *arg )
michael@0 197 {
michael@0 198 PLArenaPool ap;
michael@0 199 PRIntn i;
michael@0 200 PRIntn sz;
michael@0 201 void *ptr;
michael@0 202 PRThread *tp = PR_GetCurrentThread();
michael@0 203
michael@0 204 PR_LOG( tLM, PR_LOG_DEBUG, ("Stress Thread %p started\n", PR_GetCurrentThread()));
michael@0 205 PL_InitArenaPool( &ap, "TheArena", RandSize( poolMin, poolMax), sizeof(double));
michael@0 206
michael@0 207 for ( i = 0; i < stressIterations; i++ )
michael@0 208 {
michael@0 209 PRIntn allocated = 0;
michael@0 210
michael@0 211 while ( allocated < maxAlloc )
michael@0 212 {
michael@0 213 sz = RandSize( arenaMin, arenaMax );
michael@0 214 PL_ARENA_ALLOCATE( ptr, &ap, sz );
michael@0 215 if ( ptr == NULL )
michael@0 216 {
michael@0 217 PR_LOG( tLM, PR_LOG_ERROR, ("ARENA_ALLOCATE() returned NULL\n\tAllocated: %d\n", allocated));
michael@0 218 break;
michael@0 219 }
michael@0 220 allocated += sz;
michael@0 221 }
michael@0 222 PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished one iteration\n", tp));
michael@0 223 PL_FreeArenaPool( &ap );
michael@0 224 }
michael@0 225 PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished all iteration\n", tp));
michael@0 226 PL_FinishArenaPool( &ap );
michael@0 227 PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p after FinishArenaPool()\n", tp));
michael@0 228
michael@0 229 /* That's all folks! let's quit */
michael@0 230 PR_EnterMonitor(tMon);
michael@0 231 threadCount--;
michael@0 232 PR_Notify(tMon);
michael@0 233 PR_ExitMonitor(tMon);
michael@0 234 return;
michael@0 235 }
michael@0 236
michael@0 237 /*
michael@0 238 ** Stress()
michael@0 239 ** Flog the hell out of arenas multi-threaded.
michael@0 240 ** Do NOT pass an individual arena to another thread.
michael@0 241 **
michael@0 242 */
michael@0 243 static void Stress( void )
michael@0 244 {
michael@0 245 PRThread *tt;
michael@0 246 PRIntn i;
michael@0 247
michael@0 248 tMon = PR_NewMonitor();
michael@0 249
michael@0 250 for ( i = 0 ; i < stressThreads ; i++ )
michael@0 251 {
michael@0 252 PR_EnterMonitor(tMon);
michael@0 253 tt = PR_CreateThread(PR_USER_THREAD,
michael@0 254 StressThread,
michael@0 255 NULL,
michael@0 256 PR_PRIORITY_NORMAL,
michael@0 257 PR_GLOBAL_THREAD,
michael@0 258 PR_UNJOINABLE_THREAD,
michael@0 259 0);
michael@0 260 threadCount++;
michael@0 261 PR_ExitMonitor(tMon);
michael@0 262 }
michael@0 263
michael@0 264 /* Wait for all threads to exit */
michael@0 265 PR_EnterMonitor(tMon);
michael@0 266 while ( threadCount != 0 )
michael@0 267 {
michael@0 268 PR_Wait(tMon, PR_INTERVAL_NO_TIMEOUT);
michael@0 269 }
michael@0 270 PR_ExitMonitor(tMon);
michael@0 271 PR_DestroyMonitor(tMon);
michael@0 272
michael@0 273 return;
michael@0 274 } /* end Stress() */
michael@0 275
michael@0 276 /*
michael@0 277 ** EvaluateResults()
michael@0 278 ** uses failed_already to display results and set program
michael@0 279 ** exit code.
michael@0 280 */
michael@0 281 static PRIntn EvaluateResults(void)
michael@0 282 {
michael@0 283 PRIntn rc = 0;
michael@0 284
michael@0 285 if ( failed_already == PR_TRUE )
michael@0 286 {
michael@0 287 PR_LOG( tLM, PR_LOG_DEBUG, ("FAIL\n"));
michael@0 288 rc =1;
michael@0 289 }
michael@0 290 else
michael@0 291 {
michael@0 292 PR_LOG( tLM, PR_LOG_DEBUG, ("PASS\n"));
michael@0 293 }
michael@0 294 return(rc);
michael@0 295 } /* EvaluateResults() */
michael@0 296
michael@0 297 void Help( void )
michael@0 298 {
michael@0 299 printf("arena [options]\n");
michael@0 300 printf("where options are:\n");
michael@0 301 printf("-p <n> minimum size of an arena pool. Default(%d)\n", poolMin);
michael@0 302 printf("-P <n> maximum size of an arena pool. Default(%d)\n", poolMax);
michael@0 303 printf("-a <n> minimum size of an arena allocation. Default(%d)\n", arenaMin);
michael@0 304 printf("-A <n> maximum size of an arena allocation. Default(%d)\n", arenaMax);
michael@0 305 printf("-i <n> number of iterations in a stress thread. Default(%d)\n", stressIterations);
michael@0 306 printf("-s <n> maximum allocation for a single stress thread. Default(%d)\n", maxAlloc);
michael@0 307 printf("-t <n> number of stress threads. Default(%d)\n", stressThreads );
michael@0 308 printf("-d enable debug mode\n");
michael@0 309 printf("\n");
michael@0 310 exit(1);
michael@0 311 }
michael@0 312
michael@0 313 PRIntn main(PRIntn argc, char *argv[])
michael@0 314 {
michael@0 315 PLOptStatus os;
michael@0 316 PLOptState *opt = PL_CreateOptState(argc, argv, "dhp:P:a:A:i:s:t:");
michael@0 317 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
michael@0 318 {
michael@0 319 if (PL_OPT_BAD == os) continue;
michael@0 320 switch (opt->option)
michael@0 321 {
michael@0 322 case 'a': /* arena Min size */
michael@0 323 arenaMin = atol( opt->value );
michael@0 324 break;
michael@0 325 case 'A': /* arena Max size */
michael@0 326 arenaMax = atol( opt->value );
michael@0 327 break;
michael@0 328 case 'p': /* pool Min size */
michael@0 329 poolMin = atol( opt->value );
michael@0 330 break;
michael@0 331 case 'P': /* pool Max size */
michael@0 332 poolMax = atol( opt->value );
michael@0 333 break;
michael@0 334 case 'i': /* Iterations in stress tests */
michael@0 335 stressIterations = atol( opt->value );
michael@0 336 break;
michael@0 337 case 's': /* storage to get per iteration */
michael@0 338 maxAlloc = atol( opt->value );
michael@0 339 break;
michael@0 340 case 't': /* Number of stress threads to create */
michael@0 341 stressThreads = atol( opt->value );
michael@0 342 break;
michael@0 343 case 'd': /* debug mode */
michael@0 344 debug_mode = 1;
michael@0 345 break;
michael@0 346 case 'h': /* help */
michael@0 347 default:
michael@0 348 Help();
michael@0 349 } /* end switch() */
michael@0 350 } /* end while() */
michael@0 351 PL_DestroyOptState(opt);
michael@0 352
michael@0 353 srand( (unsigned)time( NULL ) ); /* seed random number generator */
michael@0 354 tLM = PR_NewLogModule("testcase");
michael@0 355
michael@0 356
michael@0 357 #if 0
michael@0 358 ArenaAllocate();
michael@0 359 ArenaGrow();
michael@0 360 #endif
michael@0 361
michael@0 362 MarkAndRelease();
michael@0 363
michael@0 364 Stress();
michael@0 365
michael@0 366 return(EvaluateResults());
michael@0 367 } /* end main() */
michael@0 368
michael@0 369 /* arena.c */

mercurial