1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/lib/tests/arena.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,369 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 +** File: arena.c 1.11 +** Description: Testing arenas 1.12 +** 1.13 +*/ 1.14 + 1.15 +#include <string.h> 1.16 +#include <time.h> 1.17 +#include <stdlib.h> 1.18 +#include "nspr.h" 1.19 +#include "plarena.h" 1.20 +#include "plgetopt.h" 1.21 + 1.22 +PRLogModuleInfo *tLM; 1.23 +PRIntn threadCount = 0; 1.24 +PRMonitor *tMon; 1.25 +PRBool failed_already = PR_FALSE; 1.26 + 1.27 +/* Arguments from the command line with default values */ 1.28 +PRIntn debug_mode = 0; 1.29 +PRIntn poolMin = 4096; 1.30 +PRIntn poolMax = (100 * 4096); 1.31 +PRIntn arenaMin = 40; 1.32 +PRIntn arenaMax = (100 * 40); 1.33 +PRIntn stressIterations = 15; 1.34 +PRIntn maxAlloc = (1024 * 1024); 1.35 +PRIntn stressThreads = 4; 1.36 + 1.37 +void DumpAll( void ) 1.38 +{ 1.39 + return; 1.40 +} 1.41 + 1.42 +/* 1.43 +** Test Arena allocation. 1.44 +*/ 1.45 +static void ArenaAllocate( void ) 1.46 +{ 1.47 + PLArenaPool ap; 1.48 + void *ptr; 1.49 + PRInt32 i; 1.50 + 1.51 + PL_InitArenaPool( &ap, "AllocArena", 2048, sizeof(double)); 1.52 + PR_LOG( tLM, PR_LOG_DEBUG, ("AA, InitPool -- Pool: %p. first: %p, current: %p, size: %d", 1.53 + &ap, ap.first, ap.current, ap.arenasize )); 1.54 + 1.55 + for( i = 0; i < 150; i++ ) 1.56 + { 1.57 + PL_ARENA_ALLOCATE( ptr, &ap, 512 ); 1.58 + PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d", 1.59 + &ap, ap.first, ap.current, ap.arenasize )); 1.60 + PR_LOG( tLM, PR_LOG_DEBUG,( 1.61 + "AA -- Pool: %p. alloc: %p ", &ap, ptr )); 1.62 + } 1.63 + 1.64 + PL_FreeArenaPool( &ap ); 1.65 + 1.66 + for( i = 0; i < 221; i++ ) 1.67 + { 1.68 + PL_ARENA_ALLOCATE( ptr, &ap, 512 ); 1.69 + PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d", 1.70 + &ap, ap.first, ap.current, ap.arenasize )); 1.71 + PR_LOG( tLM, PR_LOG_DEBUG,( 1.72 + "AA -- Pool: %p. alloc: %p ", &ap, ptr )); 1.73 + } 1.74 + 1.75 + PL_FreeArenaPool( &ap ); 1.76 + 1.77 + return; 1.78 +} /* end ArenaGrow() */ 1.79 +/* 1.80 +** Test Arena grow. 1.81 +*/ 1.82 +static void ArenaGrow( void ) 1.83 +{ 1.84 + PLArenaPool ap; 1.85 + void *ptr; 1.86 + PRInt32 i; 1.87 + 1.88 + PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double)); 1.89 + PL_ARENA_ALLOCATE( ptr, &ap, 512 ); 1.90 + 1.91 + PR_LOG( tLM, PR_LOG_DEBUG, ("Before growth -- Pool: %p. alloc: %p ", &ap, ptr )); 1.92 + 1.93 + for( i = 0; i < 10; i++ ) 1.94 + { 1.95 + PL_ARENA_GROW( ptr, &ap, 512, 7000 ); 1.96 + PR_LOG( tLM, PR_LOG_DEBUG, ("After growth -- Pool: %p. alloc: %p ", &ap, ptr )); 1.97 + } 1.98 + 1.99 + 1.100 + return; 1.101 +} /* end ArenaGrow() */ 1.102 + 1.103 + 1.104 +/* 1.105 +** Test arena Mark and Release. 1.106 +*/ 1.107 +static void MarkAndRelease( void ) 1.108 +{ 1.109 + PLArenaPool ap; 1.110 + void *ptr = NULL; 1.111 + void *mark0, *mark1; 1.112 + PRIntn i; 1.113 + 1.114 + PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double)); 1.115 + mark0 = PL_ARENA_MARK( &ap ); 1.116 + PR_LOG( tLM, PR_LOG_DEBUG, 1.117 + ("mark0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m0: %p", 1.118 + &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark0 )); 1.119 + 1.120 + for( i = 0; i < 201; i++ ) 1.121 + { 1.122 + PL_ARENA_ALLOCATE( ptr, &ap, 512 ); 1.123 + PR_LOG( tLM, PR_LOG_DEBUG, 1.124 + ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 1.125 + &ap, ap.first.next, ap.current, ap.arenasize, ptr )); 1.126 + } 1.127 + 1.128 + mark1 = PL_ARENA_MARK( &ap ); 1.129 + PR_LOG( tLM, PR_LOG_DEBUG, 1.130 + ("mark1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m1: %p", 1.131 + &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark1 )); 1.132 + 1.133 + 1.134 + for( i = 0; i < 225; i++ ) 1.135 + { 1.136 + PL_ARENA_ALLOCATE( ptr, &ap, 512 ); 1.137 + PR_LOG( tLM, PR_LOG_DEBUG, 1.138 + ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 1.139 + &ap, ap.first.next, ap.current, ap.arenasize, ptr )); 1.140 + } 1.141 + 1.142 + PL_ARENA_RELEASE( &ap, mark1 ); 1.143 + PR_LOG( tLM, PR_LOG_DEBUG, 1.144 + ("Release-1: %p -- Pool: %p. first: %p, current: %p, size: %d", 1.145 + mark1, &ap, ap.first, ap.current, ap.arenasize )); 1.146 + 1.147 + for( i = 0; i < 20; i++ ) 1.148 + { 1.149 + PL_ARENA_ALLOCATE( ptr, &ap, 512 ); 1.150 + PR_LOG( tLM, PR_LOG_DEBUG, 1.151 + ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 1.152 + &ap, ap.first.next, ap.current, ap.arenasize, ptr )); 1.153 + } 1.154 + 1.155 + PL_ARENA_RELEASE( &ap, mark1 ); 1.156 + PR_LOG( tLM, PR_LOG_DEBUG, 1.157 + ("Release-1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 1.158 + &ap, ap.first.next, ap.current, ap.arenasize, ptr )); 1.159 + 1.160 + PL_ARENA_RELEASE( &ap, mark0 ); 1.161 + PR_LOG( tLM, PR_LOG_DEBUG, 1.162 + ("Release-0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 1.163 + &ap, ap.first.next, ap.current, ap.arenasize, ptr )); 1.164 + 1.165 + PL_FreeArenaPool( &ap ); 1.166 + PR_LOG( tLM, PR_LOG_DEBUG, 1.167 + ("Free. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 1.168 + &ap, ap.first.next, ap.current, ap.arenasize, ptr )); 1.169 + 1.170 + PL_FinishArenaPool( &ap ); 1.171 + PR_LOG( tLM, PR_LOG_DEBUG, 1.172 + ("Finish. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 1.173 + &ap, ap.first.next, ap.current, ap.arenasize, ptr )); 1.174 + 1.175 + return; 1.176 +} /* end MarkAndRelease() */ 1.177 + 1.178 +/* 1.179 +** RandSize() returns a random number in the range 1.180 +** min..max, rounded to the next doubleword 1.181 +** 1.182 +*/ 1.183 +static PRIntn RandSize( PRIntn min, PRIntn max ) 1.184 +{ 1.185 + PRIntn sz = (rand() % (max -min)) + min + sizeof(double); 1.186 + 1.187 + sz &= ~sizeof(double)-1; 1.188 + 1.189 + return(sz); 1.190 +} 1.191 + 1.192 + 1.193 +/* 1.194 +** StressThread() 1.195 +** A bunch of these beat on individual arenas 1.196 +** This tests the free_list protection. 1.197 +** 1.198 +*/ 1.199 +static void PR_CALLBACK StressThread( void *arg ) 1.200 +{ 1.201 + PLArenaPool ap; 1.202 + PRIntn i; 1.203 + PRIntn sz; 1.204 + void *ptr; 1.205 + PRThread *tp = PR_GetCurrentThread(); 1.206 + 1.207 + PR_LOG( tLM, PR_LOG_DEBUG, ("Stress Thread %p started\n", PR_GetCurrentThread())); 1.208 + PL_InitArenaPool( &ap, "TheArena", RandSize( poolMin, poolMax), sizeof(double)); 1.209 + 1.210 + for ( i = 0; i < stressIterations; i++ ) 1.211 + { 1.212 + PRIntn allocated = 0; 1.213 + 1.214 + while ( allocated < maxAlloc ) 1.215 + { 1.216 + sz = RandSize( arenaMin, arenaMax ); 1.217 + PL_ARENA_ALLOCATE( ptr, &ap, sz ); 1.218 + if ( ptr == NULL ) 1.219 + { 1.220 + PR_LOG( tLM, PR_LOG_ERROR, ("ARENA_ALLOCATE() returned NULL\n\tAllocated: %d\n", allocated)); 1.221 + break; 1.222 + } 1.223 + allocated += sz; 1.224 + } 1.225 + PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished one iteration\n", tp)); 1.226 + PL_FreeArenaPool( &ap ); 1.227 + } 1.228 + PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished all iteration\n", tp)); 1.229 + PL_FinishArenaPool( &ap ); 1.230 + PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p after FinishArenaPool()\n", tp)); 1.231 + 1.232 + /* That's all folks! let's quit */ 1.233 + PR_EnterMonitor(tMon); 1.234 + threadCount--; 1.235 + PR_Notify(tMon); 1.236 + PR_ExitMonitor(tMon); 1.237 + return; 1.238 +} 1.239 + 1.240 +/* 1.241 +** Stress() 1.242 +** Flog the hell out of arenas multi-threaded. 1.243 +** Do NOT pass an individual arena to another thread. 1.244 +** 1.245 +*/ 1.246 +static void Stress( void ) 1.247 +{ 1.248 + PRThread *tt; 1.249 + PRIntn i; 1.250 + 1.251 + tMon = PR_NewMonitor(); 1.252 + 1.253 + for ( i = 0 ; i < stressThreads ; i++ ) 1.254 + { 1.255 + PR_EnterMonitor(tMon); 1.256 + tt = PR_CreateThread(PR_USER_THREAD, 1.257 + StressThread, 1.258 + NULL, 1.259 + PR_PRIORITY_NORMAL, 1.260 + PR_GLOBAL_THREAD, 1.261 + PR_UNJOINABLE_THREAD, 1.262 + 0); 1.263 + threadCount++; 1.264 + PR_ExitMonitor(tMon); 1.265 + } 1.266 + 1.267 + /* Wait for all threads to exit */ 1.268 + PR_EnterMonitor(tMon); 1.269 + while ( threadCount != 0 ) 1.270 + { 1.271 + PR_Wait(tMon, PR_INTERVAL_NO_TIMEOUT); 1.272 + } 1.273 + PR_ExitMonitor(tMon); 1.274 + PR_DestroyMonitor(tMon); 1.275 + 1.276 + return; 1.277 +} /* end Stress() */ 1.278 + 1.279 +/* 1.280 +** EvaluateResults() 1.281 +** uses failed_already to display results and set program 1.282 +** exit code. 1.283 +*/ 1.284 +static PRIntn EvaluateResults(void) 1.285 +{ 1.286 + PRIntn rc = 0; 1.287 + 1.288 + if ( failed_already == PR_TRUE ) 1.289 + { 1.290 + PR_LOG( tLM, PR_LOG_DEBUG, ("FAIL\n")); 1.291 + rc =1; 1.292 + } 1.293 + else 1.294 + { 1.295 + PR_LOG( tLM, PR_LOG_DEBUG, ("PASS\n")); 1.296 + } 1.297 + return(rc); 1.298 +} /* EvaluateResults() */ 1.299 + 1.300 +void Help( void ) 1.301 +{ 1.302 + printf("arena [options]\n"); 1.303 + printf("where options are:\n"); 1.304 + printf("-p <n> minimum size of an arena pool. Default(%d)\n", poolMin); 1.305 + printf("-P <n> maximum size of an arena pool. Default(%d)\n", poolMax); 1.306 + printf("-a <n> minimum size of an arena allocation. Default(%d)\n", arenaMin); 1.307 + printf("-A <n> maximum size of an arena allocation. Default(%d)\n", arenaMax); 1.308 + printf("-i <n> number of iterations in a stress thread. Default(%d)\n", stressIterations); 1.309 + printf("-s <n> maximum allocation for a single stress thread. Default(%d)\n", maxAlloc); 1.310 + printf("-t <n> number of stress threads. Default(%d)\n", stressThreads ); 1.311 + printf("-d enable debug mode\n"); 1.312 + printf("\n"); 1.313 + exit(1); 1.314 +} 1.315 + 1.316 +PRIntn main(PRIntn argc, char *argv[]) 1.317 +{ 1.318 + PLOptStatus os; 1.319 + PLOptState *opt = PL_CreateOptState(argc, argv, "dhp:P:a:A:i:s:t:"); 1.320 + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) 1.321 + { 1.322 + if (PL_OPT_BAD == os) continue; 1.323 + switch (opt->option) 1.324 + { 1.325 + case 'a': /* arena Min size */ 1.326 + arenaMin = atol( opt->value ); 1.327 + break; 1.328 + case 'A': /* arena Max size */ 1.329 + arenaMax = atol( opt->value ); 1.330 + break; 1.331 + case 'p': /* pool Min size */ 1.332 + poolMin = atol( opt->value ); 1.333 + break; 1.334 + case 'P': /* pool Max size */ 1.335 + poolMax = atol( opt->value ); 1.336 + break; 1.337 + case 'i': /* Iterations in stress tests */ 1.338 + stressIterations = atol( opt->value ); 1.339 + break; 1.340 + case 's': /* storage to get per iteration */ 1.341 + maxAlloc = atol( opt->value ); 1.342 + break; 1.343 + case 't': /* Number of stress threads to create */ 1.344 + stressThreads = atol( opt->value ); 1.345 + break; 1.346 + case 'd': /* debug mode */ 1.347 + debug_mode = 1; 1.348 + break; 1.349 + case 'h': /* help */ 1.350 + default: 1.351 + Help(); 1.352 + } /* end switch() */ 1.353 + } /* end while() */ 1.354 + PL_DestroyOptState(opt); 1.355 + 1.356 + srand( (unsigned)time( NULL ) ); /* seed random number generator */ 1.357 + tLM = PR_NewLogModule("testcase"); 1.358 + 1.359 + 1.360 +#if 0 1.361 + ArenaAllocate(); 1.362 + ArenaGrow(); 1.363 +#endif 1.364 + 1.365 + MarkAndRelease(); 1.366 + 1.367 + Stress(); 1.368 + 1.369 + return(EvaluateResults()); 1.370 +} /* end main() */ 1.371 + 1.372 +/* arena.c */