| Index: third_party/nspr/mozilla/nsprpub/lib/tests/arena.c
|
| diff --git a/third_party/nspr/mozilla/nsprpub/lib/tests/arena.c b/third_party/nspr/mozilla/nsprpub/lib/tests/arena.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9c74479cbd7e98d3ea2f336c122c578b347347b2
|
| --- /dev/null
|
| +++ b/third_party/nspr/mozilla/nsprpub/lib/tests/arena.c
|
| @@ -0,0 +1,401 @@
|
| +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
| +/* ***** BEGIN LICENSE BLOCK *****
|
| + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
| + *
|
| + * The contents of this file are subject to the Mozilla Public License Version
|
| + * 1.1 (the "License"); you may not use this file except in compliance with
|
| + * the License. You may obtain a copy of the License at
|
| + * http://www.mozilla.org/MPL/
|
| + *
|
| + * Software distributed under the License is distributed on an "AS IS" basis,
|
| + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
| + * for the specific language governing rights and limitations under the
|
| + * License.
|
| + *
|
| + * The Original Code is the Netscape Portable Runtime (NSPR).
|
| + *
|
| + * The Initial Developer of the Original Code is
|
| + * Netscape Communications Corporation.
|
| + * Portions created by the Initial Developer are Copyright (C) 1998-2000
|
| + * the Initial Developer. All Rights Reserved.
|
| + *
|
| + * Contributor(s):
|
| + *
|
| + * Alternatively, the contents of this file may be used under the terms of
|
| + * either the GNU General Public License Version 2 or later (the "GPL"), or
|
| + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
| + * in which case the provisions of the GPL or the LGPL are applicable instead
|
| + * of those above. If you wish to allow use of your version of this file only
|
| + * under the terms of either the GPL or the LGPL, and not to allow others to
|
| + * use your version of this file under the terms of the MPL, indicate your
|
| + * decision by deleting the provisions above and replace them with the notice
|
| + * and other provisions required by the GPL or the LGPL. If you do not delete
|
| + * the provisions above, a recipient may use your version of this file under
|
| + * the terms of any one of the MPL, the GPL or the LGPL.
|
| + *
|
| + * ***** END LICENSE BLOCK ***** */
|
| +
|
| +/*
|
| +** File: arena.c
|
| +** Description: Testing arenas
|
| +**
|
| +*/
|
| +
|
| +#include <string.h>
|
| +#include <time.h>
|
| +#include <stdlib.h>
|
| +#include "nspr.h"
|
| +#include "plarena.h"
|
| +#include "plgetopt.h"
|
| +
|
| +PRLogModuleInfo *tLM;
|
| +PRIntn threadCount = 0;
|
| +PRMonitor *tMon;
|
| +PRBool failed_already = PR_FALSE;
|
| +
|
| +/* Arguments from the command line with default values */
|
| +PRIntn debug_mode = 0;
|
| +PRIntn poolMin = 4096;
|
| +PRIntn poolMax = (100 * 4096);
|
| +PRIntn arenaMin = 40;
|
| +PRIntn arenaMax = (100 * 40);
|
| +PRIntn stressIterations = 15;
|
| +PRIntn maxAlloc = (1024 * 1024);
|
| +PRIntn stressThreads = 4;
|
| +
|
| +void DumpAll( void )
|
| +{
|
| + return;
|
| +}
|
| +
|
| +/*
|
| +** Test Arena allocation.
|
| +*/
|
| +static void ArenaAllocate( void )
|
| +{
|
| + PLArenaPool ap;
|
| + void *ptr;
|
| + PRInt32 i;
|
| +
|
| + PL_InitArenaPool( &ap, "AllocArena", 2048, sizeof(double));
|
| + PR_LOG( tLM, PR_LOG_DEBUG, ("AA, InitPool -- Pool: %p. first: %p, current: %p, size: %d",
|
| + &ap, ap.first, ap.current, ap.arenasize ));
|
| +
|
| + for( i = 0; i < 150; i++ )
|
| + {
|
| + PL_ARENA_ALLOCATE( ptr, &ap, 512 );
|
| + PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
|
| + &ap, ap.first, ap.current, ap.arenasize ));
|
| + PR_LOG( tLM, PR_LOG_DEBUG,(
|
| + "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
|
| + }
|
| +
|
| + PL_FreeArenaPool( &ap );
|
| +
|
| + for( i = 0; i < 221; i++ )
|
| + {
|
| + PL_ARENA_ALLOCATE( ptr, &ap, 512 );
|
| + PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
|
| + &ap, ap.first, ap.current, ap.arenasize ));
|
| + PR_LOG( tLM, PR_LOG_DEBUG,(
|
| + "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
|
| + }
|
| +
|
| + PL_FreeArenaPool( &ap );
|
| +
|
| + return;
|
| +} /* end ArenaGrow() */
|
| +/*
|
| +** Test Arena grow.
|
| +*/
|
| +static void ArenaGrow( void )
|
| +{
|
| + PLArenaPool ap;
|
| + void *ptr;
|
| + PRInt32 i;
|
| +
|
| + PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
|
| + PL_ARENA_ALLOCATE( ptr, &ap, 512 );
|
| +
|
| + PR_LOG( tLM, PR_LOG_DEBUG, ("Before growth -- Pool: %p. alloc: %p ", &ap, ptr ));
|
| +
|
| + for( i = 0; i < 10; i++ )
|
| + {
|
| + PL_ARENA_GROW( ptr, &ap, 512, 7000 );
|
| + PR_LOG( tLM, PR_LOG_DEBUG, ("After growth -- Pool: %p. alloc: %p ", &ap, ptr ));
|
| + }
|
| +
|
| +
|
| + return;
|
| +} /* end ArenaGrow() */
|
| +
|
| +
|
| +/*
|
| +** Test arena Mark and Release.
|
| +*/
|
| +static void MarkAndRelease( void )
|
| +{
|
| + PLArenaPool ap;
|
| + void *ptr = NULL;
|
| + void *mark0, *mark1;
|
| + PRIntn i;
|
| +
|
| + PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
|
| + mark0 = PL_ARENA_MARK( &ap );
|
| + PR_LOG( tLM, PR_LOG_DEBUG,
|
| + ("mark0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m0: %p",
|
| + &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark0 ));
|
| +
|
| + for( i = 0; i < 201; i++ )
|
| + {
|
| + PL_ARENA_ALLOCATE( ptr, &ap, 512 );
|
| + PR_LOG( tLM, PR_LOG_DEBUG,
|
| + ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
|
| + &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
|
| + }
|
| +
|
| + mark1 = PL_ARENA_MARK( &ap );
|
| + PR_LOG( tLM, PR_LOG_DEBUG,
|
| + ("mark1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m1: %p",
|
| + &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark1 ));
|
| +
|
| +
|
| + for( i = 0; i < 225; i++ )
|
| + {
|
| + PL_ARENA_ALLOCATE( ptr, &ap, 512 );
|
| + PR_LOG( tLM, PR_LOG_DEBUG,
|
| + ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
|
| + &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
|
| + }
|
| +
|
| + PL_ARENA_RELEASE( &ap, mark1 );
|
| + PR_LOG( tLM, PR_LOG_DEBUG,
|
| + ("Release-1: %p -- Pool: %p. first: %p, current: %p, size: %d",
|
| + mark1, &ap, ap.first, ap.current, ap.arenasize ));
|
| +
|
| + for( i = 0; i < 20; i++ )
|
| + {
|
| + PL_ARENA_ALLOCATE( ptr, &ap, 512 );
|
| + PR_LOG( tLM, PR_LOG_DEBUG,
|
| + ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
|
| + &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
|
| + }
|
| +
|
| + PL_ARENA_RELEASE( &ap, mark1 );
|
| + PR_LOG( tLM, PR_LOG_DEBUG,
|
| + ("Release-1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
|
| + &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
|
| +
|
| + PL_ARENA_RELEASE( &ap, mark0 );
|
| + PR_LOG( tLM, PR_LOG_DEBUG,
|
| + ("Release-0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
|
| + &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
|
| +
|
| + PL_FreeArenaPool( &ap );
|
| + PR_LOG( tLM, PR_LOG_DEBUG,
|
| + ("Free. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
|
| + &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
|
| +
|
| + PL_FinishArenaPool( &ap );
|
| + PR_LOG( tLM, PR_LOG_DEBUG,
|
| + ("Finish. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
|
| + &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
|
| +
|
| + return;
|
| +} /* end MarkAndRelease() */
|
| +
|
| +/*
|
| +** RandSize() returns a random number in the range
|
| +** min..max, rounded to the next doubleword
|
| +**
|
| +*/
|
| +static PRIntn RandSize( PRIntn min, PRIntn max )
|
| +{
|
| + PRIntn sz = (rand() % (max -min)) + min + sizeof(double);
|
| +
|
| + sz &= ~sizeof(double)-1;
|
| +
|
| + return(sz);
|
| +}
|
| +
|
| +
|
| +/*
|
| +** StressThread()
|
| +** A bunch of these beat on individual arenas
|
| +** This tests the free_list protection.
|
| +**
|
| +*/
|
| +static void PR_CALLBACK StressThread( void *arg )
|
| +{
|
| + PLArenaPool ap;
|
| + PRIntn i;
|
| + PRIntn sz;
|
| + void *ptr;
|
| + PRThread *tp = PR_GetCurrentThread();
|
| +
|
| + PR_LOG( tLM, PR_LOG_DEBUG, ("Stress Thread %p started\n", PR_GetCurrentThread()));
|
| + PL_InitArenaPool( &ap, "TheArena", RandSize( poolMin, poolMax), sizeof(double));
|
| +
|
| + for ( i = 0; i < stressIterations; i++ )
|
| + {
|
| + PRIntn allocated = 0;
|
| +
|
| + while ( allocated < maxAlloc )
|
| + {
|
| + sz = RandSize( arenaMin, arenaMax );
|
| + PL_ARENA_ALLOCATE( ptr, &ap, sz );
|
| + if ( ptr == NULL )
|
| + {
|
| + PR_LOG( tLM, PR_LOG_ERROR, ("ARENA_ALLOCATE() returned NULL\n\tAllocated: %d\n", allocated));
|
| + break;
|
| + }
|
| + allocated += sz;
|
| + }
|
| + PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished one iteration\n", tp));
|
| + PL_FreeArenaPool( &ap );
|
| + }
|
| + PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished all iteration\n", tp));
|
| + PL_FinishArenaPool( &ap );
|
| + PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p after FinishArenaPool()\n", tp));
|
| +
|
| + /* That's all folks! let's quit */
|
| + PR_EnterMonitor(tMon);
|
| + threadCount--;
|
| + PR_Notify(tMon);
|
| + PR_ExitMonitor(tMon);
|
| + return;
|
| +}
|
| +
|
| +/*
|
| +** Stress()
|
| +** Flog the hell out of arenas multi-threaded.
|
| +** Do NOT pass an individual arena to another thread.
|
| +**
|
| +*/
|
| +static void Stress( void )
|
| +{
|
| + PRThread *tt;
|
| + PRIntn i;
|
| +
|
| + tMon = PR_NewMonitor();
|
| +
|
| + for ( i = 0 ; i < stressThreads ; i++ )
|
| + {
|
| + PR_EnterMonitor(tMon);
|
| + tt = PR_CreateThread(PR_USER_THREAD,
|
| + StressThread,
|
| + NULL,
|
| + PR_PRIORITY_NORMAL,
|
| + PR_GLOBAL_THREAD,
|
| + PR_UNJOINABLE_THREAD,
|
| + 0);
|
| + threadCount++;
|
| + PR_ExitMonitor(tMon);
|
| + }
|
| +
|
| + /* Wait for all threads to exit */
|
| + PR_EnterMonitor(tMon);
|
| + while ( threadCount != 0 )
|
| + {
|
| + PR_Wait(tMon, PR_INTERVAL_NO_TIMEOUT);
|
| + }
|
| + PR_ExitMonitor(tMon);
|
| + PR_DestroyMonitor(tMon);
|
| +
|
| + return;
|
| +} /* end Stress() */
|
| +
|
| +/*
|
| +** EvaluateResults()
|
| +** uses failed_already to display results and set program
|
| +** exit code.
|
| +*/
|
| +static PRIntn EvaluateResults(void)
|
| +{
|
| + PRIntn rc = 0;
|
| +
|
| + if ( failed_already == PR_TRUE )
|
| + {
|
| + PR_LOG( tLM, PR_LOG_DEBUG, ("FAIL\n"));
|
| + rc =1;
|
| + }
|
| + else
|
| + {
|
| + PR_LOG( tLM, PR_LOG_DEBUG, ("PASS\n"));
|
| + }
|
| + return(rc);
|
| +} /* EvaluateResults() */
|
| +
|
| +void Help( void )
|
| +{
|
| + printf("arena [options]\n");
|
| + printf("where options are:\n");
|
| + printf("-p <n> minimum size of an arena pool. Default(%d)\n", poolMin);
|
| + printf("-P <n> maximum size of an arena pool. Default(%d)\n", poolMax);
|
| + printf("-a <n> minimum size of an arena allocation. Default(%d)\n", arenaMin);
|
| + printf("-A <n> maximum size of an arena allocation. Default(%d)\n", arenaMax);
|
| + printf("-i <n> number of iterations in a stress thread. Default(%d)\n", stressIterations);
|
| + printf("-s <n> maximum allocation for a single stress thread. Default(%d)\n", maxAlloc);
|
| + printf("-t <n> number of stress threads. Default(%d)\n", stressThreads );
|
| + printf("-d enable debug mode\n");
|
| + printf("\n");
|
| + exit(1);
|
| +}
|
| +
|
| +PRIntn main(PRIntn argc, char *argv[])
|
| +{
|
| + PLOptStatus os;
|
| + PLOptState *opt = PL_CreateOptState(argc, argv, "dhp:P:a:A:i:s:t:");
|
| + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
|
| + {
|
| + if (PL_OPT_BAD == os) continue;
|
| + switch (opt->option)
|
| + {
|
| + case 'a': /* arena Min size */
|
| + arenaMin = atol( opt->value );
|
| + break;
|
| + case 'A': /* arena Max size */
|
| + arenaMax = atol( opt->value );
|
| + break;
|
| + case 'p': /* pool Min size */
|
| + poolMin = atol( opt->value );
|
| + break;
|
| + case 'P': /* pool Max size */
|
| + poolMax = atol( opt->value );
|
| + break;
|
| + case 'i': /* Iterations in stress tests */
|
| + stressIterations = atol( opt->value );
|
| + break;
|
| + case 's': /* storage to get per iteration */
|
| + maxAlloc = atol( opt->value );
|
| + break;
|
| + case 't': /* Number of stress threads to create */
|
| + stressThreads = atol( opt->value );
|
| + break;
|
| + case 'd': /* debug mode */
|
| + debug_mode = 1;
|
| + break;
|
| + case 'h': /* help */
|
| + default:
|
| + Help();
|
| + } /* end switch() */
|
| + } /* end while() */
|
| + PL_DestroyOptState(opt);
|
| +
|
| + srand( (unsigned)time( NULL ) ); /* seed random number generator */
|
| + tLM = PR_NewLogModule("testcase");
|
| +
|
| +
|
| +#if 0
|
| + ArenaAllocate();
|
| + ArenaGrow();
|
| +#endif
|
| +
|
| + MarkAndRelease();
|
| +
|
| + Stress();
|
| +
|
| + return(EvaluateResults());
|
| +} /* end main() */
|
| +
|
| +/* arena.c */
|
|
|