Back to index

lightning-sunbird  0.9+nobinonly
gc1.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 ** Includes
00040 ***********************************************************************/
00041 /* Used to get the command line option */
00042 #include "plgetopt.h"
00043 
00044 #include "prgc.h"
00045 #include "prinit.h"
00046 #include "prmon.h"
00047 #include "prinrval.h"
00048 #ifndef XP_MAC
00049 #include "private/pprthred.h"
00050 #else
00051 #include "pprthred.h"
00052 #endif
00053 
00054 #include <stdio.h>
00055 #include <stdlib.h>
00056 
00057 #ifdef XP_MAC
00058 #include "prlog.h"
00059 #define printf PR_LogPrint
00060 extern void SetupMacPrintfLog(char *logFile);
00061 #endif
00062 
00063 static PRMonitor *mon;
00064 static PRInt32 threads, waiting, iterations;
00065 static PRInt32 scanCount, finalizeCount, freeCount;
00066 
00067 PRIntn failed_already=0;
00068 PRIntn debug_mode;
00069 
00070 
00071 typedef struct Array {
00072     PRUintn size;
00073     void *body[1];
00074 } Array;
00075 
00076 int arrayTypeIndex;
00077 
00078 static void PR_CALLBACK ScanArray(void *a)
00079 {
00080 /*     printf ("In ScanArray a = %X size = %d \n", a, a->size); */
00081        scanCount++;
00082 }
00083 
00084 static void PR_CALLBACK FinalizeArray(void *a)
00085 {
00086 /*     printf ("In FinalizeArray a = %X size = %d \n", a, a->size); */       
00087        finalizeCount++;
00088 }
00089 
00090 static void PR_CALLBACK FreeArray(void *a)
00091 {
00092 /*     printf ("In FreeArray\n");  */
00093        freeCount++;
00094 }
00095 
00096 static Array *NewArray(PRUintn size)
00097 {
00098     Array *a;
00099 
00100     a = (Array *)PR_AllocMemory(sizeof(Array) + size*sizeof(void*) - 1*sizeof(void*),
00101                        arrayTypeIndex, PR_ALLOC_CLEAN);
00102 
00103 /*     printf ("In NewArray a = %X \n", a); */   
00104 
00105     if (a)
00106         a->size = size;
00107     return a;
00108 }
00109 
00110 GCType arrayType = {
00111     ScanArray,
00112     FinalizeArray,
00113     0,
00114     0,
00115     FreeArray,
00116     0
00117 };
00118 
00119 static void Initialize(void)
00120 {
00121     PR_InitGC(0, 0, 0, PR_GLOBAL_THREAD);
00122     arrayTypeIndex = PR_RegisterType(&arrayType);
00123 }
00124 
00125 static void PR_CALLBACK AllocateLikeMad(void *arg)
00126 {
00127     Array *prev;
00128     PRInt32 i;
00129        PRInt32 count;
00130 
00131        count = (PRInt32)arg;
00132     prev = 0;
00133     for (i = 0; i < count; i++) {
00134         Array *leak = NewArray(i & 511);
00135         if ((i & 1023) == 0) {
00136             prev = 0;                   /* forget */
00137         } else {
00138             if (i & 1) {
00139                 prev = leak;            /* remember */
00140             }
00141         }
00142     }
00143     PR_EnterMonitor(mon);
00144     waiting++;
00145     PR_Notify(mon);
00146     PR_ExitMonitor(mon);
00147 }
00148 
00149 int main(int argc, char **argv)
00150 {
00151     PRIntervalTime start, stop, usec;
00152     double d;
00153     PRIntn i, totalIterations;
00154        /* The command line argument: -d is used to determine if the test is being run
00155        in debug mode. The regress tool requires only one line output:PASS or FAIL.
00156        All of the printfs associated with this test has been handled with a if (debug_mode)
00157        test.
00158        Usage: test_name -d
00159        */
00160        PLOptStatus os;
00161        PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:");
00162 
00163        threads = 10;
00164        iterations = 100;
00165 
00166        while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
00167     {
00168         if (PL_OPT_BAD == os) {
00169             fprintf(stderr, "Invalid command-line option\n");
00170             exit(1);
00171         }
00172         switch (opt->option)
00173         {
00174         case 'd':  /* debug mode */
00175                      debug_mode = 1;
00176             break;
00177         case 't':  /* number of threads */
00178             threads = atoi(opt->value);
00179             break;
00180         case 'c':  /* iteration count */
00181             iterations = atoi(opt->value);
00182             break;
00183         default:
00184             break;
00185         }
00186     }
00187        PL_DestroyOptState(opt);
00188 
00189     fprintf(stderr, "t is %ld, i is %ld\n", (long) threads, (long) iterations);
00190        /* main test */
00191 
00192     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 5);
00193     PR_STDIO_INIT();
00194     Initialize();
00195 
00196 #ifdef XP_MAC
00197        SetupMacPrintfLog("gc1.log");
00198        debug_mode = 1;
00199 #endif
00200 
00201     /* Spin all of the allocator threads and then wait for them to exit */
00202     start = PR_IntervalNow();
00203     mon = PR_NewMonitor();
00204     PR_EnterMonitor(mon);
00205     waiting = 0;
00206     for (i = 0; i < threads; i++) {
00207         (void) PR_CreateThreadGCAble(PR_USER_THREAD,
00208                                AllocateLikeMad, (void*)iterations,
00209                                                 PR_PRIORITY_NORMAL,
00210                                                 PR_LOCAL_THREAD,
00211                                             PR_UNJOINABLE_THREAD,
00212                                                 0);
00213     }
00214     while (waiting != threads) {
00215         PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
00216     }
00217     PR_ExitMonitor(mon);
00218 
00219        PR_GC();
00220        PR_ForceFinalize();  
00221 
00222        totalIterations = iterations * threads;
00223 /*
00224        if (scanCount != totalIterations)
00225               printf ("scanCount discrepancy scanCount = %d totalIterations = %d \n", 
00226                      scanCount, totalIterations);
00227        if (freeCount != totalIterations)
00228               printf ("freeCount discrepancy freeCount = %d totalIterations = %d \n", 
00229                      freeCount, totalIterations);
00230        if ((finalizeCount != totalIterations) && (finalizeCount != (totalIterations-1)))
00231               printf ("finalizeCount discrepancy finalizeCount = %d totalIterations = %d \n", 
00232                      finalizeCount,totalIterations);
00233 */
00234 
00235     stop = PR_IntervalNow();
00236     
00237     usec = stop = stop - start;
00238     d = (double)usec;
00239 
00240     if (debug_mode) printf("%40s: %6.2f usec\n", "GC allocation", d / (iterations * threads));
00241        else {
00242               if (d == 0.0) failed_already = PR_TRUE;
00243 
00244        }
00245 
00246     PR_Cleanup();
00247        if(failed_already)   
00248        {
00249            printf("FAIL\n");
00250               return 1;
00251        }
00252        else
00253        {
00254            printf("PASS\n");
00255               return 0;
00256        }
00257 }