threads.c (4446B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "nspr.h" 7 #include "prinrval.h" 8 #include "plgetopt.h" 9 #include "pprthred.h" 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 PRMonitor* mon; 15 PRInt32 count, iterations, alive; 16 17 PRBool debug_mode = PR_FALSE, passed = PR_TRUE; 18 19 void PR_CALLBACK ReallyDumbThread(void* arg) { return; } 20 21 void PR_CALLBACK DumbThread(void* arg) { 22 PRInt32 tmp = (PRInt32)arg; 23 PRThreadScope scope = (PRThreadScope)tmp; 24 PRThread* thr; 25 26 thr = PR_CreateThread(PR_USER_THREAD, ReallyDumbThread, NULL, 27 PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); 28 29 if (!thr) { 30 if (debug_mode) { 31 printf("Could not create really dumb thread (%d, %d)!\n", PR_GetError(), 32 PR_GetOSError()); 33 } 34 passed = PR_FALSE; 35 } else { 36 PR_JoinThread(thr); 37 } 38 PR_EnterMonitor(mon); 39 alive--; 40 PR_Notify(mon); 41 PR_ExitMonitor(mon); 42 } 43 44 static void CreateThreads(PRThreadScope scope1, PRThreadScope scope2) { 45 PRThread* thr; 46 int n; 47 48 alive = 0; 49 mon = PR_NewMonitor(); 50 51 alive = count; 52 for (n = 0; n < count; n++) { 53 thr = PR_CreateThread(PR_USER_THREAD, DumbThread, (void*)scope2, 54 PR_PRIORITY_NORMAL, scope1, PR_UNJOINABLE_THREAD, 0); 55 if (!thr) { 56 if (debug_mode) { 57 printf("Could not create dumb thread (%d, %d)!\n", PR_GetError(), 58 PR_GetOSError()); 59 } 60 passed = PR_FALSE; 61 alive--; 62 } 63 64 PR_Sleep(0); 65 } 66 67 /* Wait for all threads to exit */ 68 PR_EnterMonitor(mon); 69 while (alive) { 70 PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); 71 } 72 73 PR_ExitMonitor(mon); 74 PR_DestroyMonitor(mon); 75 } 76 77 static void CreateThreadsUU(void) { 78 CreateThreads(PR_LOCAL_THREAD, PR_LOCAL_THREAD); 79 } 80 81 static void CreateThreadsUK(void) { 82 CreateThreads(PR_LOCAL_THREAD, PR_GLOBAL_THREAD); 83 } 84 85 static void CreateThreadsKU(void) { 86 CreateThreads(PR_GLOBAL_THREAD, PR_LOCAL_THREAD); 87 } 88 89 static void CreateThreadsKK(void) { 90 CreateThreads(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD); 91 } 92 93 /************************************************************************/ 94 95 static void Measure(void (*func)(void), const char* msg) { 96 PRIntervalTime start, stop; 97 double d; 98 99 start = PR_IntervalNow(); 100 (*func)(); 101 stop = PR_IntervalNow(); 102 103 if (debug_mode) { 104 d = (double)PR_IntervalToMicroseconds(stop - start); 105 printf("%40s: %6.2f usec\n", msg, d / count); 106 } 107 } 108 109 int main(int argc, char** argv) { 110 int index; 111 112 PR_Init(PR_USER_THREAD, PR_PRIORITY_HIGH, 0); 113 114 { 115 PLOptStatus os; 116 PLOptState* opt = PL_CreateOptState(argc, argv, "dc:i:"); 117 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { 118 if (PL_OPT_BAD == os) { 119 continue; 120 } 121 switch (opt->option) { 122 case 'd': /* debug mode */ 123 debug_mode = PR_TRUE; 124 break; 125 case 'c': /* loop counter */ 126 count = atoi(opt->value); 127 break; 128 case 'i': /* loop counter */ 129 iterations = atoi(opt->value); 130 break; 131 default: 132 break; 133 } 134 } 135 PL_DestroyOptState(opt); 136 } 137 138 if (0 == count) { 139 count = 50; 140 } 141 if (0 == iterations) { 142 iterations = 10; 143 } 144 145 if (debug_mode) { 146 printf( 147 "\ 148 ** Tests lots of thread creations. \n\ 149 ** Create %ld native threads %ld times. \n\ 150 ** Create %ld user threads %ld times \n", 151 iterations, count, iterations, count); 152 } 153 154 for (index = 0; index < iterations; index++) { 155 Measure(CreateThreadsUU, "Create user/user threads"); 156 Measure(CreateThreadsUK, "Create user/native threads"); 157 Measure(CreateThreadsKU, "Create native/user threads"); 158 Measure(CreateThreadsKK, "Create native/native threads"); 159 } 160 161 if (debug_mode) { 162 printf("\nNow switch to recycling threads \n\n"); 163 } 164 PR_SetThreadRecycleMode(1); 165 166 for (index = 0; index < iterations; index++) { 167 Measure(CreateThreadsUU, "Create user/user threads"); 168 Measure(CreateThreadsUK, "Create user/native threads"); 169 Measure(CreateThreadsKU, "Create native/user threads"); 170 Measure(CreateThreadsKK, "Create native/native threads"); 171 } 172 173 printf("%s\n", ((passed) ? "PASS" : "FAIL")); 174 175 PR_Cleanup(); 176 177 if (passed) { 178 return 0; 179 } else { 180 return 1; 181 } 182 }