Back to index

lightning-sunbird  0.9+nobinonly
threads.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 #include "nspr.h"
00039 #include "prinrval.h"
00040 #include "plgetopt.h"
00041 #include "pprthred.h"
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045 
00046 #ifdef XP_MAC
00047 #include "prlog.h"
00048 #define printf PR_LogPrint
00049 extern void SetupMacPrintfLog(char *logFile);
00050 #endif
00051 
00052 PRMonitor *mon;
00053 PRInt32 count, iterations, alive;
00054 
00055 PRBool debug_mode = PR_FALSE, passed = PR_TRUE;
00056 
00057 void 
00058 PR_CALLBACK
00059 ReallyDumbThread(void *arg)
00060 {
00061     return;
00062 }
00063 
00064 void
00065 PR_CALLBACK
00066 DumbThread(void *arg)
00067 {
00068     PRInt32 tmp = (PRInt32)arg;
00069     PRThreadScope scope = (PRThreadScope)tmp;
00070     PRThread *thr;
00071 
00072     thr = PR_CreateThread(PR_USER_THREAD,
00073                           ReallyDumbThread,
00074                           NULL,
00075                           PR_PRIORITY_NORMAL,
00076                           scope,
00077                           PR_JOINABLE_THREAD,
00078                           0);
00079 
00080     if (!thr) {
00081         if (debug_mode) {
00082             printf("Could not create really dumb thread (%d, %d)!\n",
00083                     PR_GetError(), PR_GetOSError());
00084         }
00085         passed = PR_FALSE;
00086     } else {
00087         PR_JoinThread(thr);
00088     }
00089     PR_EnterMonitor(mon);
00090     alive--;
00091     PR_Notify(mon);
00092     PR_ExitMonitor(mon);
00093 }
00094 
00095 static void CreateThreads(PRThreadScope scope1, PRThreadScope scope2)
00096 {
00097     PRThread *thr;
00098     int n;
00099 
00100     alive = 0;
00101     mon = PR_NewMonitor();
00102 
00103     alive = count;
00104     for (n=0; n<count; n++) {
00105         thr = PR_CreateThread(PR_USER_THREAD,
00106                               DumbThread, 
00107                               (void *)scope2, 
00108                               PR_PRIORITY_NORMAL,
00109                               scope1,
00110                               PR_UNJOINABLE_THREAD,
00111                               0);
00112         if (!thr) {
00113             if (debug_mode) {
00114                 printf("Could not create dumb thread (%d, %d)!\n",
00115                         PR_GetError(), PR_GetOSError());
00116             }
00117             passed = PR_FALSE;
00118             alive--;
00119         }
00120          
00121         PR_Sleep(0);
00122     }
00123 
00124     /* Wait for all threads to exit */
00125     PR_EnterMonitor(mon);
00126     while (alive) {
00127         PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
00128     }
00129 
00130     PR_ExitMonitor(mon);
00131        PR_DestroyMonitor(mon);
00132 }
00133 
00134 static void CreateThreadsUU(void)
00135 {
00136     CreateThreads(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
00137 }
00138 
00139 static void CreateThreadsUK(void)
00140 {
00141     CreateThreads(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
00142 }
00143 
00144 static void CreateThreadsKU(void)
00145 {
00146     CreateThreads(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
00147 }
00148 
00149 static void CreateThreadsKK(void)
00150 {
00151     CreateThreads(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
00152 }
00153 
00154 /************************************************************************/
00155 
00156 static void Measure(void (*func)(void), const char *msg)
00157 {
00158     PRIntervalTime start, stop;
00159     double d;
00160 
00161     start = PR_IntervalNow();
00162     (*func)();
00163     stop = PR_IntervalNow();
00164 
00165     if (debug_mode)
00166     {
00167         d = (double)PR_IntervalToMicroseconds(stop - start);
00168         printf("%40s: %6.2f usec\n", msg, d / count);
00169     }
00170 }
00171 
00172 int main(int argc, char **argv)
00173 {
00174     int index;
00175 
00176     PR_STDIO_INIT();
00177     PR_Init(PR_USER_THREAD, PR_PRIORITY_HIGH, 0);
00178     
00179     {
00180        PLOptStatus os;
00181        PLOptState *opt = PL_CreateOptState(argc, argv, "dc:i:");
00182        while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
00183         {
00184               if (PL_OPT_BAD == os) continue;
00185             switch (opt->option)
00186             {
00187             case 'd':  /* debug mode */
00188                      debug_mode = PR_TRUE;
00189                 break;
00190             case 'c':  /* loop counter */
00191                      count = atoi(opt->value);
00192                 break;
00193             case 'i':  /* loop counter */
00194                      iterations = atoi(opt->value);
00195                 break;
00196              default:
00197                 break;
00198             }
00199         }
00200        PL_DestroyOptState(opt);
00201     }
00202 
00203 #ifdef XP_MAC
00204        SetupMacPrintfLog("threads.log");
00205        count = 10;
00206        iterations = 10;
00207        debug_mode = PR_TRUE;
00208 #else
00209     if (0 == count) count = 50;
00210     if (0 == iterations) iterations = 10;
00211 
00212 #endif
00213 
00214     if (debug_mode)
00215     {
00216     printf("\
00217 ** Tests lots of thread creations.  \n\
00218 ** Create %ld native threads %ld times. \n\
00219 ** Create %ld user threads %ld times \n", iterations,count,iterations,count);
00220     }
00221 
00222     for (index=0; index<iterations; index++) {
00223         Measure(CreateThreadsUU, "Create user/user threads");
00224         Measure(CreateThreadsUK, "Create user/native threads");
00225         Measure(CreateThreadsKU, "Create native/user threads");
00226         Measure(CreateThreadsKK, "Create native/native threads");
00227     }
00228 
00229     if (debug_mode) printf("\nNow switch to recycling threads \n\n");
00230     PR_SetThreadRecycleMode(1);
00231 
00232     for (index=0; index<iterations; index++) {
00233         Measure(CreateThreadsUU, "Create user/user threads");
00234         Measure(CreateThreadsUK, "Create user/native threads");
00235         Measure(CreateThreadsKU, "Create native/user threads");
00236         Measure(CreateThreadsKK, "Create native/native threads");
00237     }
00238 
00239 
00240     printf("%s\n", ((passed) ? "PASS" : "FAIL"));
00241 
00242     PR_Cleanup();
00243 
00244     if (passed) {
00245         return 0;
00246     } else {
00247         return 1;
00248     }
00249 }