Back to index

lightning-sunbird  0.9+nobinonly
arena.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039 ** File:        arena.c
00040 ** Description: Testing arenas
00041 **
00042 */
00043 
00044 #include <string.h>
00045 #include <time.h>
00046 #include <stdlib.h>
00047 #include "nspr.h"
00048 #include "plarena.h"
00049 #include "plgetopt.h"
00050 
00051 PRLogModuleInfo *tLM;
00052 PRIntn  threadCount = 0;
00053 PRMonitor   *tMon;
00054 PRBool failed_already = PR_FALSE;
00055 
00056 /* Arguments from the command line with default values */
00057 PRIntn debug_mode = 0;
00058 PRIntn  poolMin = 4096;
00059 PRIntn  poolMax = (100 * 4096);
00060 PRIntn  arenaMin = 40;
00061 PRIntn  arenaMax = (100 * 40);
00062 PRIntn  stressIterations = 15;
00063 PRIntn  maxAlloc = (1024 * 1024);
00064 PRIntn  stressThreads = 4;
00065 
00066 void DumpAll( void )
00067 {
00068        return;
00069 }
00070 
00071 /*
00072 ** Test Arena allocation.
00073 */
00074 static void ArenaAllocate( void )
00075 {
00076     PLArenaPool ap;
00077     void    *ptr;
00078        PRInt32       i;
00079 
00080     PL_InitArenaPool( &ap, "AllocArena", 2048, sizeof(double));
00081     PR_LOG( tLM, PR_LOG_DEBUG, ("AA, InitPool -- Pool: %p. first: %p, current: %p, size: %d", 
00082         &ap, ap.first, ap.current, ap.arenasize  ));
00083 
00084        for( i = 0; i < 150; i++ )
00085        {
00086               PL_ARENA_ALLOCATE( ptr, &ap, 512 );
00087         PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d", 
00088                &ap, ap.first, ap.current, ap.arenasize  ));
00089               PR_LOG( tLM, PR_LOG_DEBUG,(
00090                   "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
00091        }
00092 
00093     PL_FreeArenaPool( &ap );
00094 
00095        for( i = 0; i < 221; i++ )
00096        {
00097               PL_ARENA_ALLOCATE( ptr, &ap, 512 );
00098         PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d", 
00099                &ap, ap.first, ap.current, ap.arenasize  ));
00100               PR_LOG( tLM, PR_LOG_DEBUG,(
00101                   "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
00102        }
00103 
00104     PL_FreeArenaPool( &ap );
00105     
00106     return;
00107 } /* end ArenaGrow() */
00108 /*
00109 ** Test Arena grow.
00110 */
00111 static void ArenaGrow( void )
00112 {
00113     PLArenaPool ap;
00114     void    *ptr;
00115        PRInt32       i;
00116 
00117     PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
00118     PL_ARENA_ALLOCATE( ptr, &ap, 512 );
00119 
00120        PR_LOG( tLM, PR_LOG_DEBUG, ("Before growth -- Pool: %p. alloc: %p ", &ap, ptr ));
00121 
00122        for( i = 0; i < 10; i++ )
00123        {
00124               PL_ARENA_GROW( ptr, &ap, 512, 7000 );
00125               PR_LOG( tLM, PR_LOG_DEBUG, ("After growth -- Pool: %p. alloc: %p ", &ap, ptr ));
00126        }
00127 
00128 
00129     return;
00130 } /* end ArenaGrow() */
00131 
00132 
00133 /*
00134 ** Test arena Mark and Release.
00135 */
00136 static void MarkAndRelease( void )
00137 {
00138     PLArenaPool ap;
00139     void    *ptr = NULL;
00140     void    *mark0, *mark1;
00141     PRIntn  i;
00142 
00143     PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
00144     mark0 = PL_ARENA_MARK( &ap );
00145     PR_LOG( tLM, PR_LOG_DEBUG,
00146         ("mark0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m0: %p", 
00147             &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark0 ));
00148 
00149        for( i = 0; i < 201; i++ )
00150        {
00151               PL_ARENA_ALLOCATE( ptr, &ap, 512 );
00152         PR_LOG( tLM, PR_LOG_DEBUG,
00153             ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 
00154                 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
00155        }
00156 
00157     mark1 = PL_ARENA_MARK( &ap );
00158     PR_LOG( tLM, PR_LOG_DEBUG,
00159         ("mark1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m1: %p", 
00160             &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark1 ));
00161 
00162 
00163        for( i = 0; i < 225; i++ )
00164        {
00165               PL_ARENA_ALLOCATE( ptr, &ap, 512 );
00166         PR_LOG( tLM, PR_LOG_DEBUG,
00167             ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 
00168                 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
00169        }
00170 
00171     PL_ARENA_RELEASE( &ap, mark1 );
00172     PR_LOG( tLM, PR_LOG_DEBUG,
00173         ("Release-1: %p -- Pool: %p. first: %p, current: %p, size: %d", 
00174                mark1, &ap, ap.first, ap.current, ap.arenasize  ));
00175 
00176        for( i = 0; i < 20; i++ )
00177        {
00178               PL_ARENA_ALLOCATE( ptr, &ap, 512 );
00179         PR_LOG( tLM, PR_LOG_DEBUG,
00180             ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 
00181                 &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
00182        }
00183 
00184     PL_ARENA_RELEASE( &ap, mark1 );
00185     PR_LOG( tLM, PR_LOG_DEBUG,
00186         ("Release-1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 
00187             &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
00188 
00189     PL_ARENA_RELEASE( &ap, mark0 );
00190     PR_LOG( tLM, PR_LOG_DEBUG,
00191         ("Release-0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 
00192             &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
00193 
00194     PL_FreeArenaPool( &ap );
00195     PR_LOG( tLM, PR_LOG_DEBUG,
00196         ("Free. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 
00197             &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
00198     
00199     PL_FinishArenaPool( &ap );
00200     PR_LOG( tLM, PR_LOG_DEBUG,
00201         ("Finish. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", 
00202             &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
00203 
00204     return;
00205 } /* end MarkAndRelease() */
00206 
00207 /*
00208 ** RandSize() returns a random number in the range 
00209 ** min..max, rounded to the next doubleword
00210 **
00211 */
00212 static PRIntn RandSize( PRIntn min, PRIntn max )
00213 {
00214     PRIntn  sz = (rand() % (max -min)) + min + sizeof(double);
00215 
00216     sz &= ~sizeof(double)-1;
00217 
00218     return(sz);
00219 }
00220 
00221 
00222 /*
00223 ** StressThread()
00224 ** A bunch of these beat on individual arenas
00225 ** This tests the free_list protection.
00226 **
00227 */
00228 static void PR_CALLBACK StressThread( void *arg )
00229 {
00230     PLArenaPool ap;
00231     PRIntn i;
00232     PRIntn sz;
00233     void *ptr;
00234     PRThread *tp = PR_GetCurrentThread();
00235 
00236     PR_LOG( tLM, PR_LOG_DEBUG, ("Stress Thread %p started\n", PR_GetCurrentThread()));
00237     PL_InitArenaPool( &ap, "TheArena", RandSize( poolMin, poolMax), sizeof(double));
00238 
00239     for ( i = 0; i < stressIterations; i++ )
00240     {
00241         PRIntn allocated = 0;
00242 
00243         while ( allocated < maxAlloc )
00244         {
00245             sz = RandSize( arenaMin, arenaMax );
00246             PL_ARENA_ALLOCATE( ptr, &ap, sz );
00247             if ( ptr == NULL )
00248             {
00249                 PR_LOG( tLM, PR_LOG_ERROR, ("ARENA_ALLOCATE() returned NULL\n\tAllocated: %d\n", allocated));
00250                 break;
00251             }
00252             allocated += sz;
00253         }
00254         PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished one iteration\n", tp));
00255         PL_FreeArenaPool( &ap );
00256     }
00257     PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished all iteration\n", tp));
00258     PL_FinishArenaPool( &ap );
00259     PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p after FinishArenaPool()\n", tp));
00260 
00261     /* That's all folks! let's quit */
00262     PR_EnterMonitor(tMon);
00263     threadCount--;
00264     PR_Notify(tMon);
00265     PR_ExitMonitor(tMon);    
00266     return;
00267 }    
00268 
00269 /*
00270 ** Stress()
00271 ** Flog the hell out of arenas multi-threaded.
00272 ** Do NOT pass an individual arena to another thread.
00273 ** 
00274 */
00275 static void Stress( void )
00276 {
00277     PRThread    *tt;
00278     PRIntn      i;
00279 
00280     tMon = PR_NewMonitor();
00281 
00282     for ( i = 0 ; i < stressThreads ; i++ )
00283     {
00284         PR_EnterMonitor(tMon);
00285         tt = PR_CreateThread(PR_USER_THREAD,
00286                StressThread,
00287                NULL,
00288                PR_PRIORITY_NORMAL,
00289                PR_GLOBAL_THREAD,
00290                PR_UNJOINABLE_THREAD,
00291                0);
00292         threadCount++;
00293         PR_ExitMonitor(tMon);
00294     }
00295 
00296     /* Wait for all threads to exit */
00297     PR_EnterMonitor(tMon);
00298     while ( threadCount != 0 ) 
00299     {
00300         PR_Wait(tMon, PR_INTERVAL_NO_TIMEOUT);
00301     }
00302     PR_ExitMonitor(tMon);
00303        PR_DestroyMonitor(tMon);
00304 
00305     return;
00306 } /* end Stress() */
00307 
00308 /*
00309 ** EvaluateResults()
00310 ** uses failed_already to display results and set program
00311 ** exit code.
00312 */
00313 static PRIntn  EvaluateResults(void)
00314 {
00315     PRIntn rc = 0;
00316 
00317     if ( failed_already == PR_TRUE )
00318     {
00319         PR_LOG( tLM, PR_LOG_DEBUG, ("FAIL\n"));
00320         rc =1;
00321     } 
00322     else
00323     {
00324         PR_LOG( tLM, PR_LOG_DEBUG, ("PASS\n"));
00325     }
00326     return(rc);
00327 } /* EvaluateResults() */
00328 
00329 void Help( void )
00330 {
00331     printf("arena [options]\n");
00332     printf("where options are:\n");
00333     printf("-p <n>   minimum size of an arena pool. Default(%d)\n", poolMin);
00334     printf("-P <n>   maximum size of an arena pool. Default(%d)\n", poolMax);
00335     printf("-a <n>   minimum size of an arena allocation. Default(%d)\n", arenaMin);
00336     printf("-A <n>   maximum size of an arena allocation. Default(%d)\n", arenaMax);
00337     printf("-i <n>   number of iterations in a stress thread. Default(%d)\n", stressIterations);
00338     printf("-s <n>   maximum allocation for a single stress thread. Default(%d)\n", maxAlloc);
00339     printf("-t <n>   number of stress threads. Default(%d)\n", stressThreads );
00340     printf("-d       enable debug mode\n");
00341     printf("\n");
00342     exit(1);
00343 }    
00344 
00345 PRIntn main(PRIntn argc, char *argv[])
00346 {
00347     PLOptStatus os;
00348        PLOptState *opt = PL_CreateOptState(argc, argv, "dhp:P:a:A:i:s:t:");
00349        while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
00350     {
00351               if (PL_OPT_BAD == os) continue;
00352         switch (opt->option)
00353         {
00354         case 'a':  /* arena Min size */
00355             arenaMin = atol( opt->value );
00356             break;
00357         case 'A':  /* arena Max size  */
00358             arenaMax = atol( opt->value );
00359             break;
00360         case 'p':  /* pool Min size */
00361             poolMin = atol( opt->value );
00362             break;
00363         case 'P':  /* pool Max size */
00364             poolMax = atol( opt->value );
00365             break;
00366         case 'i':  /* Iterations in stress tests */
00367             stressIterations = atol( opt->value );
00368             break;
00369         case 's':  /* storage to get per iteration */
00370             maxAlloc = atol( opt->value );
00371             break;
00372         case 't':  /* Number of stress threads to create */
00373             stressThreads = atol( opt->value );
00374             break;
00375         case 'd':  /* debug mode */
00376                      debug_mode = 1;
00377             break;
00378         case 'h':  /* help */
00379         default:
00380             Help();
00381         } /* end switch() */
00382     } /* end while() */
00383        PL_DestroyOptState(opt);
00384 
00385     srand( (unsigned)time( NULL ) ); /* seed random number generator */
00386     tLM = PR_NewLogModule("testcase");
00387 
00388 
00389 #if 0
00390        ArenaAllocate();
00391        ArenaGrow();
00392 #endif
00393 
00394     MarkAndRelease();
00395 
00396     Stress();
00397 
00398     return(EvaluateResults());
00399 } /* end main() */
00400 
00401 /* arena.c */