123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /*
- ** 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 */
|